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 <utility> 29 #include <vector> 30 31 #include "talk/app/webrtc/audiotrack.h" 32 #include "talk/app/webrtc/fakemediacontroller.h" 33 #include "talk/app/webrtc/fakemetricsobserver.h" 34 #include "talk/app/webrtc/jsepicecandidate.h" 35 #include "talk/app/webrtc/jsepsessiondescription.h" 36 #include "talk/app/webrtc/peerconnection.h" 37 #include "talk/app/webrtc/sctputils.h" 38 #include "talk/app/webrtc/streamcollection.h" 39 #include "talk/app/webrtc/streamcollection.h" 40 #include "talk/app/webrtc/test/fakeconstraints.h" 41 #include "talk/app/webrtc/test/fakedtlsidentitystore.h" 42 #include "talk/app/webrtc/videotrack.h" 43 #include "talk/app/webrtc/webrtcsession.h" 44 #include "talk/app/webrtc/webrtcsessiondescriptionfactory.h" 45 #include "talk/media/base/fakemediaengine.h" 46 #include "talk/media/base/fakevideorenderer.h" 47 #include "talk/media/base/mediachannel.h" 48 #include "talk/media/webrtc/fakewebrtccall.h" 49 #include "webrtc/p2p/base/stunserver.h" 50 #include "webrtc/p2p/base/teststunserver.h" 51 #include "webrtc/p2p/base/testturnserver.h" 52 #include "webrtc/p2p/base/transportchannel.h" 53 #include "webrtc/p2p/client/basicportallocator.h" 54 #include "talk/session/media/channelmanager.h" 55 #include "talk/session/media/mediasession.h" 56 #include "webrtc/base/fakenetwork.h" 57 #include "webrtc/base/firewallsocketserver.h" 58 #include "webrtc/base/gunit.h" 59 #include "webrtc/base/logging.h" 60 #include "webrtc/base/network.h" 61 #include "webrtc/base/physicalsocketserver.h" 62 #include "webrtc/base/ssladapter.h" 63 #include "webrtc/base/sslidentity.h" 64 #include "webrtc/base/sslstreamadapter.h" 65 #include "webrtc/base/stringutils.h" 66 #include "webrtc/base/thread.h" 67 #include "webrtc/base/virtualsocketserver.h" 68 69 #define MAYBE_SKIP_TEST(feature) \ 70 if (!(feature())) { \ 71 LOG(LS_INFO) << "Feature disabled... skipping"; \ 72 return; \ 73 } 74 75 using cricket::FakeVoiceMediaChannel; 76 using cricket::TransportInfo; 77 using rtc::SocketAddress; 78 using rtc::scoped_ptr; 79 using rtc::Thread; 80 using webrtc::CreateSessionDescription; 81 using webrtc::CreateSessionDescriptionObserver; 82 using webrtc::CreateSessionDescriptionRequest; 83 using webrtc::DataChannel; 84 using webrtc::DtlsIdentityStoreInterface; 85 using webrtc::FakeConstraints; 86 using webrtc::FakeMetricsObserver; 87 using webrtc::IceCandidateCollection; 88 using webrtc::InternalDataChannelInit; 89 using webrtc::JsepIceCandidate; 90 using webrtc::JsepSessionDescription; 91 using webrtc::PeerConnectionFactoryInterface; 92 using webrtc::PeerConnectionInterface; 93 using webrtc::SessionDescriptionInterface; 94 using webrtc::SessionStats; 95 using webrtc::StreamCollection; 96 using webrtc::WebRtcSession; 97 using webrtc::kBundleWithoutRtcpMux; 98 using webrtc::kCreateChannelFailed; 99 using webrtc::kInvalidSdp; 100 using webrtc::kMlineMismatch; 101 using webrtc::kPushDownTDFailed; 102 using webrtc::kSdpWithoutIceUfragPwd; 103 using webrtc::kSdpWithoutDtlsFingerprint; 104 using webrtc::kSdpWithoutSdesCrypto; 105 using webrtc::kSessionError; 106 using webrtc::kSessionErrorDesc; 107 using webrtc::kMaxUnsignalledRecvStreams; 108 109 typedef PeerConnectionInterface::RTCOfferAnswerOptions RTCOfferAnswerOptions; 110 111 static const int kClientAddrPort = 0; 112 static const char kClientAddrHost1[] = "11.11.11.11"; 113 static const char kClientIPv6AddrHost1[] = 114 "2620:0:aaaa:bbbb:cccc:dddd:eeee:ffff"; 115 static const char kClientAddrHost2[] = "22.22.22.22"; 116 static const char kStunAddrHost[] = "99.99.99.1"; 117 static const SocketAddress kTurnUdpIntAddr("99.99.99.4", 3478); 118 static const SocketAddress kTurnUdpExtAddr("99.99.99.6", 0); 119 static const char kTurnUsername[] = "test"; 120 static const char kTurnPassword[] = "test"; 121 122 static const char kSessionVersion[] = "1"; 123 124 // Media index of candidates belonging to the first media content. 125 static const int kMediaContentIndex0 = 0; 126 static const char kMediaContentName0[] = "audio"; 127 128 // Media index of candidates belonging to the second media content. 129 static const int kMediaContentIndex1 = 1; 130 static const char kMediaContentName1[] = "video"; 131 132 static const int kIceCandidatesTimeout = 10000; 133 134 static const char kFakeDtlsFingerprint[] = 135 "BB:CD:72:F7:2F:D0:BA:43:F3:68:B1:0C:23:72:B6:4A:" 136 "0F:DE:34:06:BC:E0:FE:01:BC:73:C8:6D:F4:65:D5:24"; 137 138 static const char kTooLongIceUfragPwd[] = 139 "IceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfrag" 140 "IceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfrag" 141 "IceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfrag" 142 "IceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfragIceUfrag"; 143 144 static const char kSdpWithRtx[] = 145 "v=0\r\n" 146 "o=- 4104004319237231850 2 IN IP4 127.0.0.1\r\n" 147 "s=-\r\n" 148 "t=0 0\r\n" 149 "a=msid-semantic: WMS stream1\r\n" 150 "m=video 9 RTP/SAVPF 0 96\r\n" 151 "c=IN IP4 0.0.0.0\r\n" 152 "a=rtcp:9 IN IP4 0.0.0.0\r\n" 153 "a=ice-ufrag:CerjGp19G7wpXwl7\r\n" 154 "a=ice-pwd:cMvOlFvQ6ochez1ZOoC2uBEC\r\n" 155 "a=mid:video\r\n" 156 "a=sendrecv\r\n" 157 "a=rtcp-mux\r\n" 158 "a=crypto:1 AES_CM_128_HMAC_SHA1_80 " 159 "inline:5/4N5CDvMiyDArHtBByUM71VIkguH17ZNoX60GrA\r\n" 160 "a=rtpmap:0 fake_video_codec/90000\r\n" 161 "a=rtpmap:96 rtx/90000\r\n" 162 "a=fmtp:96 apt=0\r\n"; 163 164 static const char kStream1[] = "stream1"; 165 static const char kVideoTrack1[] = "video1"; 166 static const char kAudioTrack1[] = "audio1"; 167 168 static const char kStream2[] = "stream2"; 169 static const char kVideoTrack2[] = "video2"; 170 static const char kAudioTrack2[] = "audio2"; 171 172 enum RTCCertificateGenerationMethod { ALREADY_GENERATED, DTLS_IDENTITY_STORE }; 173 174 class MockIceObserver : public webrtc::IceObserver { 175 public: 176 MockIceObserver() 177 : oncandidatesready_(false), 178 ice_connection_state_(PeerConnectionInterface::kIceConnectionNew), 179 ice_gathering_state_(PeerConnectionInterface::kIceGatheringNew) { 180 } 181 182 virtual void OnIceConnectionChange( 183 PeerConnectionInterface::IceConnectionState new_state) { 184 ice_connection_state_ = new_state; 185 } 186 virtual void OnIceGatheringChange( 187 PeerConnectionInterface::IceGatheringState new_state) { 188 // We can never transition back to "new". 189 EXPECT_NE(PeerConnectionInterface::kIceGatheringNew, new_state); 190 ice_gathering_state_ = new_state; 191 192 // oncandidatesready_ really means "ICE gathering is complete". 193 // This if statement ensures that this value remains correct when we 194 // transition from kIceGatheringComplete to kIceGatheringGathering. 195 if (new_state == PeerConnectionInterface::kIceGatheringGathering) { 196 oncandidatesready_ = false; 197 } 198 } 199 200 // Found a new candidate. 201 virtual void OnIceCandidate(const webrtc::IceCandidateInterface* candidate) { 202 switch (candidate->sdp_mline_index()) { 203 case kMediaContentIndex0: 204 mline_0_candidates_.push_back(candidate->candidate()); 205 break; 206 case kMediaContentIndex1: 207 mline_1_candidates_.push_back(candidate->candidate()); 208 break; 209 default: 210 ASSERT(false); 211 } 212 213 // The ICE gathering state should always be Gathering when a candidate is 214 // received (or possibly Completed in the case of the final candidate). 215 EXPECT_NE(PeerConnectionInterface::kIceGatheringNew, ice_gathering_state_); 216 } 217 218 // TODO(bemasc): Remove this once callers transition to OnIceGatheringChange. 219 virtual void OnIceComplete() { 220 EXPECT_FALSE(oncandidatesready_); 221 oncandidatesready_ = true; 222 223 // OnIceGatheringChange(IceGatheringCompleted) and OnIceComplete() should 224 // be called approximately simultaneously. For ease of testing, this 225 // check additionally requires that they be called in the above order. 226 EXPECT_EQ(PeerConnectionInterface::kIceGatheringComplete, 227 ice_gathering_state_); 228 } 229 230 bool oncandidatesready_; 231 std::vector<cricket::Candidate> mline_0_candidates_; 232 std::vector<cricket::Candidate> mline_1_candidates_; 233 PeerConnectionInterface::IceConnectionState ice_connection_state_; 234 PeerConnectionInterface::IceGatheringState ice_gathering_state_; 235 }; 236 237 class WebRtcSessionForTest : public webrtc::WebRtcSession { 238 public: 239 WebRtcSessionForTest(webrtc::MediaControllerInterface* media_controller, 240 rtc::Thread* signaling_thread, 241 rtc::Thread* worker_thread, 242 cricket::PortAllocator* port_allocator, 243 webrtc::IceObserver* ice_observer) 244 : WebRtcSession(media_controller, 245 signaling_thread, 246 worker_thread, 247 port_allocator) { 248 RegisterIceObserver(ice_observer); 249 } 250 virtual ~WebRtcSessionForTest() {} 251 252 // Note that these methods are only safe to use if the signaling thread 253 // is the same as the worker thread 254 cricket::TransportChannel* voice_rtp_transport_channel() { 255 return rtp_transport_channel(voice_channel()); 256 } 257 258 cricket::TransportChannel* voice_rtcp_transport_channel() { 259 return rtcp_transport_channel(voice_channel()); 260 } 261 262 cricket::TransportChannel* video_rtp_transport_channel() { 263 return rtp_transport_channel(video_channel()); 264 } 265 266 cricket::TransportChannel* video_rtcp_transport_channel() { 267 return rtcp_transport_channel(video_channel()); 268 } 269 270 cricket::TransportChannel* data_rtp_transport_channel() { 271 return rtp_transport_channel(data_channel()); 272 } 273 274 cricket::TransportChannel* data_rtcp_transport_channel() { 275 return rtcp_transport_channel(data_channel()); 276 } 277 278 using webrtc::WebRtcSession::SetAudioPlayout; 279 using webrtc::WebRtcSession::SetAudioSend; 280 using webrtc::WebRtcSession::SetCaptureDevice; 281 using webrtc::WebRtcSession::SetVideoPlayout; 282 using webrtc::WebRtcSession::SetVideoSend; 283 284 private: 285 cricket::TransportChannel* rtp_transport_channel(cricket::BaseChannel* ch) { 286 if (!ch) { 287 return nullptr; 288 } 289 return ch->transport_channel(); 290 } 291 292 cricket::TransportChannel* rtcp_transport_channel(cricket::BaseChannel* ch) { 293 if (!ch) { 294 return nullptr; 295 } 296 return ch->rtcp_transport_channel(); 297 } 298 }; 299 300 class WebRtcSessionCreateSDPObserverForTest 301 : public rtc::RefCountedObject<CreateSessionDescriptionObserver> { 302 public: 303 enum State { 304 kInit, 305 kFailed, 306 kSucceeded, 307 }; 308 WebRtcSessionCreateSDPObserverForTest() : state_(kInit) {} 309 310 // CreateSessionDescriptionObserver implementation. 311 virtual void OnSuccess(SessionDescriptionInterface* desc) { 312 description_.reset(desc); 313 state_ = kSucceeded; 314 } 315 virtual void OnFailure(const std::string& error) { 316 state_ = kFailed; 317 } 318 319 SessionDescriptionInterface* description() { return description_.get(); } 320 321 SessionDescriptionInterface* ReleaseDescription() { 322 return description_.release(); 323 } 324 325 State state() const { return state_; } 326 327 protected: 328 ~WebRtcSessionCreateSDPObserverForTest() {} 329 330 private: 331 rtc::scoped_ptr<SessionDescriptionInterface> description_; 332 State state_; 333 }; 334 335 class FakeAudioRenderer : public cricket::AudioRenderer { 336 public: 337 FakeAudioRenderer() : sink_(NULL) {} 338 virtual ~FakeAudioRenderer() { 339 if (sink_) 340 sink_->OnClose(); 341 } 342 343 void SetSink(Sink* sink) override { sink_ = sink; } 344 345 cricket::AudioRenderer::Sink* sink() const { return sink_; } 346 private: 347 cricket::AudioRenderer::Sink* sink_; 348 }; 349 350 class WebRtcSessionTest 351 : public testing::TestWithParam<RTCCertificateGenerationMethod>, 352 public sigslot::has_slots<> { 353 protected: 354 // TODO Investigate why ChannelManager crashes, if it's created 355 // after stun_server. 356 WebRtcSessionTest() 357 : media_engine_(new cricket::FakeMediaEngine()), 358 data_engine_(new cricket::FakeDataEngine()), 359 channel_manager_( 360 new cricket::ChannelManager(media_engine_, 361 data_engine_, 362 new cricket::CaptureManager(), 363 rtc::Thread::Current())), 364 fake_call_(webrtc::Call::Config()), 365 media_controller_( 366 webrtc::MediaControllerInterface::Create(rtc::Thread::Current(), 367 channel_manager_.get())), 368 tdesc_factory_(new cricket::TransportDescriptionFactory()), 369 desc_factory_( 370 new cricket::MediaSessionDescriptionFactory(channel_manager_.get(), 371 tdesc_factory_.get())), 372 pss_(new rtc::PhysicalSocketServer), 373 vss_(new rtc::VirtualSocketServer(pss_.get())), 374 fss_(new rtc::FirewallSocketServer(vss_.get())), 375 ss_scope_(fss_.get()), 376 stun_socket_addr_( 377 rtc::SocketAddress(kStunAddrHost, cricket::STUN_SERVER_PORT)), 378 stun_server_(cricket::TestStunServer::Create(Thread::Current(), 379 stun_socket_addr_)), 380 turn_server_(Thread::Current(), kTurnUdpIntAddr, kTurnUdpExtAddr), 381 metrics_observer_(new rtc::RefCountedObject<FakeMetricsObserver>()) { 382 cricket::ServerAddresses stun_servers; 383 stun_servers.insert(stun_socket_addr_); 384 allocator_.reset(new cricket::BasicPortAllocator( 385 &network_manager_, 386 stun_servers, 387 SocketAddress(), SocketAddress(), SocketAddress())); 388 allocator_->set_flags(cricket::PORTALLOCATOR_DISABLE_TCP | 389 cricket::PORTALLOCATOR_DISABLE_RELAY); 390 EXPECT_TRUE(channel_manager_->Init()); 391 desc_factory_->set_add_legacy_streams(false); 392 allocator_->set_step_delay(cricket::kMinimumStepDelay); 393 } 394 395 void AddInterface(const SocketAddress& addr) { 396 network_manager_.AddInterface(addr); 397 } 398 399 // If |dtls_identity_store| != null or |rtc_configuration| contains 400 // |certificates| then DTLS will be enabled unless explicitly disabled by 401 // |rtc_configuration| options. When DTLS is enabled a certificate will be 402 // used if provided, otherwise one will be generated using the 403 // |dtls_identity_store|. 404 void Init( 405 rtc::scoped_ptr<webrtc::DtlsIdentityStoreInterface> dtls_identity_store, 406 const PeerConnectionInterface::RTCConfiguration& rtc_configuration) { 407 ASSERT_TRUE(session_.get() == NULL); 408 session_.reset(new WebRtcSessionForTest( 409 media_controller_.get(), rtc::Thread::Current(), rtc::Thread::Current(), 410 allocator_.get(), &observer_)); 411 session_->SignalDataChannelOpenMessage.connect( 412 this, &WebRtcSessionTest::OnDataChannelOpenMessage); 413 414 EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew, 415 observer_.ice_connection_state_); 416 EXPECT_EQ(PeerConnectionInterface::kIceGatheringNew, 417 observer_.ice_gathering_state_); 418 419 EXPECT_TRUE(session_->Initialize(options_, constraints_.get(), 420 std::move(dtls_identity_store), 421 rtc_configuration)); 422 session_->set_metrics_observer(metrics_observer_); 423 } 424 425 void OnDataChannelOpenMessage(const std::string& label, 426 const InternalDataChannelInit& config) { 427 last_data_channel_label_ = label; 428 last_data_channel_config_ = config; 429 } 430 431 void Init() { 432 PeerConnectionInterface::RTCConfiguration configuration; 433 Init(nullptr, configuration); 434 } 435 436 void InitWithIceTransport( 437 PeerConnectionInterface::IceTransportsType ice_transport_type) { 438 PeerConnectionInterface::RTCConfiguration configuration; 439 configuration.type = ice_transport_type; 440 Init(nullptr, configuration); 441 } 442 443 void InitWithBundlePolicy( 444 PeerConnectionInterface::BundlePolicy bundle_policy) { 445 PeerConnectionInterface::RTCConfiguration configuration; 446 configuration.bundle_policy = bundle_policy; 447 Init(nullptr, configuration); 448 } 449 450 void InitWithRtcpMuxPolicy( 451 PeerConnectionInterface::RtcpMuxPolicy rtcp_mux_policy) { 452 PeerConnectionInterface::RTCConfiguration configuration; 453 configuration.rtcp_mux_policy = rtcp_mux_policy; 454 Init(nullptr, configuration); 455 } 456 457 // Successfully init with DTLS; with a certificate generated and supplied or 458 // with a store that generates it for us. 459 void InitWithDtls(RTCCertificateGenerationMethod cert_gen_method) { 460 rtc::scoped_ptr<FakeDtlsIdentityStore> dtls_identity_store; 461 PeerConnectionInterface::RTCConfiguration configuration; 462 if (cert_gen_method == ALREADY_GENERATED) { 463 configuration.certificates.push_back( 464 FakeDtlsIdentityStore::GenerateCertificate()); 465 } else if (cert_gen_method == DTLS_IDENTITY_STORE) { 466 dtls_identity_store.reset(new FakeDtlsIdentityStore()); 467 dtls_identity_store->set_should_fail(false); 468 } else { 469 RTC_CHECK(false); 470 } 471 Init(std::move(dtls_identity_store), configuration); 472 } 473 474 // Init with DTLS with a store that will fail to generate a certificate. 475 void InitWithDtlsIdentityGenFail() { 476 rtc::scoped_ptr<FakeDtlsIdentityStore> dtls_identity_store( 477 new FakeDtlsIdentityStore()); 478 dtls_identity_store->set_should_fail(true); 479 PeerConnectionInterface::RTCConfiguration configuration; 480 Init(std::move(dtls_identity_store), configuration); 481 } 482 483 void InitWithDtmfCodec() { 484 // Add kTelephoneEventCodec for dtmf test. 485 const cricket::AudioCodec kTelephoneEventCodec( 486 106, "telephone-event", 8000, 0, 1, 0); 487 std::vector<cricket::AudioCodec> codecs; 488 codecs.push_back(kTelephoneEventCodec); 489 media_engine_->SetAudioCodecs(codecs); 490 desc_factory_->set_audio_codecs(codecs); 491 Init(); 492 } 493 494 void SendAudioVideoStream1() { 495 send_stream_1_ = true; 496 send_stream_2_ = false; 497 send_audio_ = true; 498 send_video_ = true; 499 } 500 501 void SendAudioVideoStream2() { 502 send_stream_1_ = false; 503 send_stream_2_ = true; 504 send_audio_ = true; 505 send_video_ = true; 506 } 507 508 void SendAudioVideoStream1And2() { 509 send_stream_1_ = true; 510 send_stream_2_ = true; 511 send_audio_ = true; 512 send_video_ = true; 513 } 514 515 void SendNothing() { 516 send_stream_1_ = false; 517 send_stream_2_ = false; 518 send_audio_ = false; 519 send_video_ = false; 520 } 521 522 void SendAudioOnlyStream2() { 523 send_stream_1_ = false; 524 send_stream_2_ = true; 525 send_audio_ = true; 526 send_video_ = false; 527 } 528 529 void SendVideoOnlyStream2() { 530 send_stream_1_ = false; 531 send_stream_2_ = true; 532 send_audio_ = false; 533 send_video_ = true; 534 } 535 536 void AddStreamsToOptions(cricket::MediaSessionOptions* session_options) { 537 if (send_stream_1_ && send_audio_) { 538 session_options->AddSendStream(cricket::MEDIA_TYPE_AUDIO, kAudioTrack1, 539 kStream1); 540 } 541 if (send_stream_1_ && send_video_) { 542 session_options->AddSendStream(cricket::MEDIA_TYPE_VIDEO, kVideoTrack1, 543 kStream1); 544 } 545 if (send_stream_2_ && send_audio_) { 546 session_options->AddSendStream(cricket::MEDIA_TYPE_AUDIO, kAudioTrack2, 547 kStream2); 548 } 549 if (send_stream_2_ && send_video_) { 550 session_options->AddSendStream(cricket::MEDIA_TYPE_VIDEO, kVideoTrack2, 551 kStream2); 552 } 553 if (data_channel_ && session_->data_channel_type() == cricket::DCT_RTP) { 554 session_options->AddSendStream(cricket::MEDIA_TYPE_DATA, 555 data_channel_->label(), 556 data_channel_->label()); 557 } 558 } 559 560 void GetOptionsForOffer( 561 const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options, 562 cricket::MediaSessionOptions* session_options) { 563 ASSERT_TRUE(ConvertRtcOptionsForOffer(rtc_options, session_options)); 564 565 AddStreamsToOptions(session_options); 566 if (rtc_options.offer_to_receive_audio == 567 RTCOfferAnswerOptions::kUndefined) { 568 session_options->recv_audio = 569 session_options->HasSendMediaStream(cricket::MEDIA_TYPE_AUDIO); 570 } 571 if (rtc_options.offer_to_receive_video == 572 RTCOfferAnswerOptions::kUndefined) { 573 session_options->recv_video = 574 session_options->HasSendMediaStream(cricket::MEDIA_TYPE_VIDEO); 575 } 576 session_options->bundle_enabled = 577 session_options->bundle_enabled && 578 (session_options->has_audio() || session_options->has_video() || 579 session_options->has_data()); 580 581 if (session_->data_channel_type() == cricket::DCT_SCTP && data_channel_) { 582 session_options->data_channel_type = cricket::DCT_SCTP; 583 } 584 } 585 586 void GetOptionsForAnswer(const webrtc::MediaConstraintsInterface* constraints, 587 cricket::MediaSessionOptions* session_options) { 588 session_options->recv_audio = false; 589 session_options->recv_video = false; 590 ASSERT_TRUE(ParseConstraintsForAnswer(constraints, session_options)); 591 592 AddStreamsToOptions(session_options); 593 session_options->bundle_enabled = 594 session_options->bundle_enabled && 595 (session_options->has_audio() || session_options->has_video() || 596 session_options->has_data()); 597 598 if (session_->data_channel_type() == cricket::DCT_SCTP) { 599 session_options->data_channel_type = cricket::DCT_SCTP; 600 } 601 } 602 603 // Creates a local offer and applies it. Starts ICE. 604 // Call SendAudioVideoStreamX() before this function 605 // to decide which streams to create. 606 void InitiateCall() { 607 SessionDescriptionInterface* offer = CreateOffer(); 608 SetLocalDescriptionWithoutError(offer); 609 EXPECT_TRUE_WAIT(PeerConnectionInterface::kIceGatheringNew != 610 observer_.ice_gathering_state_, 611 kIceCandidatesTimeout); 612 } 613 614 SessionDescriptionInterface* CreateOffer() { 615 PeerConnectionInterface::RTCOfferAnswerOptions options; 616 options.offer_to_receive_audio = 617 RTCOfferAnswerOptions::kOfferToReceiveMediaTrue; 618 619 return CreateOffer(options); 620 } 621 622 SessionDescriptionInterface* CreateOffer( 623 const PeerConnectionInterface::RTCOfferAnswerOptions& options) { 624 rtc::scoped_refptr<WebRtcSessionCreateSDPObserverForTest> 625 observer = new WebRtcSessionCreateSDPObserverForTest(); 626 cricket::MediaSessionOptions session_options; 627 GetOptionsForOffer(options, &session_options); 628 session_->CreateOffer(observer, options, session_options); 629 EXPECT_TRUE_WAIT( 630 observer->state() != WebRtcSessionCreateSDPObserverForTest::kInit, 631 2000); 632 return observer->ReleaseDescription(); 633 } 634 635 SessionDescriptionInterface* CreateAnswer( 636 const webrtc::MediaConstraintsInterface* constraints) { 637 rtc::scoped_refptr<WebRtcSessionCreateSDPObserverForTest> observer 638 = new WebRtcSessionCreateSDPObserverForTest(); 639 cricket::MediaSessionOptions session_options; 640 GetOptionsForAnswer(constraints, &session_options); 641 session_->CreateAnswer(observer, constraints, session_options); 642 EXPECT_TRUE_WAIT( 643 observer->state() != WebRtcSessionCreateSDPObserverForTest::kInit, 644 2000); 645 return observer->ReleaseDescription(); 646 } 647 648 bool ChannelsExist() const { 649 return (session_->voice_channel() != NULL && 650 session_->video_channel() != NULL); 651 } 652 653 void VerifyCryptoParams(const cricket::SessionDescription* sdp) { 654 ASSERT_TRUE(session_.get() != NULL); 655 const cricket::ContentInfo* content = cricket::GetFirstAudioContent(sdp); 656 ASSERT_TRUE(content != NULL); 657 const cricket::AudioContentDescription* audio_content = 658 static_cast<const cricket::AudioContentDescription*>( 659 content->description); 660 ASSERT_TRUE(audio_content != NULL); 661 ASSERT_EQ(1U, audio_content->cryptos().size()); 662 ASSERT_EQ(47U, audio_content->cryptos()[0].key_params.size()); 663 ASSERT_EQ("AES_CM_128_HMAC_SHA1_80", 664 audio_content->cryptos()[0].cipher_suite); 665 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), 666 audio_content->protocol()); 667 668 content = cricket::GetFirstVideoContent(sdp); 669 ASSERT_TRUE(content != NULL); 670 const cricket::VideoContentDescription* video_content = 671 static_cast<const cricket::VideoContentDescription*>( 672 content->description); 673 ASSERT_TRUE(video_content != NULL); 674 ASSERT_EQ(1U, video_content->cryptos().size()); 675 ASSERT_EQ("AES_CM_128_HMAC_SHA1_80", 676 video_content->cryptos()[0].cipher_suite); 677 ASSERT_EQ(47U, video_content->cryptos()[0].key_params.size()); 678 EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), 679 video_content->protocol()); 680 } 681 682 void VerifyNoCryptoParams(const cricket::SessionDescription* sdp, bool dtls) { 683 const cricket::ContentInfo* content = cricket::GetFirstAudioContent(sdp); 684 ASSERT_TRUE(content != NULL); 685 const cricket::AudioContentDescription* audio_content = 686 static_cast<const cricket::AudioContentDescription*>( 687 content->description); 688 ASSERT_TRUE(audio_content != NULL); 689 ASSERT_EQ(0U, audio_content->cryptos().size()); 690 691 content = cricket::GetFirstVideoContent(sdp); 692 ASSERT_TRUE(content != NULL); 693 const cricket::VideoContentDescription* video_content = 694 static_cast<const cricket::VideoContentDescription*>( 695 content->description); 696 ASSERT_TRUE(video_content != NULL); 697 ASSERT_EQ(0U, video_content->cryptos().size()); 698 699 if (dtls) { 700 EXPECT_EQ(std::string(cricket::kMediaProtocolDtlsSavpf), 701 audio_content->protocol()); 702 EXPECT_EQ(std::string(cricket::kMediaProtocolDtlsSavpf), 703 video_content->protocol()); 704 } else { 705 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf), 706 audio_content->protocol()); 707 EXPECT_EQ(std::string(cricket::kMediaProtocolAvpf), 708 video_content->protocol()); 709 } 710 } 711 712 // Set the internal fake description factories to do DTLS-SRTP. 713 void SetFactoryDtlsSrtp() { 714 desc_factory_->set_secure(cricket::SEC_DISABLED); 715 std::string identity_name = "WebRTC" + 716 rtc::ToString(rtc::CreateRandomId()); 717 // Confirmed to work with KT_RSA and KT_ECDSA. 718 tdesc_factory_->set_certificate( 719 rtc::RTCCertificate::Create(rtc::scoped_ptr<rtc::SSLIdentity>( 720 rtc::SSLIdentity::Generate(identity_name, rtc::KT_DEFAULT)))); 721 tdesc_factory_->set_secure(cricket::SEC_REQUIRED); 722 } 723 724 void VerifyFingerprintStatus(const cricket::SessionDescription* sdp, 725 bool expected) { 726 const TransportInfo* audio = sdp->GetTransportInfoByName("audio"); 727 ASSERT_TRUE(audio != NULL); 728 ASSERT_EQ(expected, audio->description.identity_fingerprint.get() != NULL); 729 const TransportInfo* video = sdp->GetTransportInfoByName("video"); 730 ASSERT_TRUE(video != NULL); 731 ASSERT_EQ(expected, video->description.identity_fingerprint.get() != NULL); 732 } 733 734 void VerifyAnswerFromNonCryptoOffer() { 735 // Create an SDP without Crypto. 736 cricket::MediaSessionOptions options; 737 options.recv_video = true; 738 JsepSessionDescription* offer( 739 CreateRemoteOffer(options, cricket::SEC_DISABLED)); 740 ASSERT_TRUE(offer != NULL); 741 VerifyNoCryptoParams(offer->description(), false); 742 SetRemoteDescriptionOfferExpectError(kSdpWithoutSdesCrypto, 743 offer); 744 const webrtc::SessionDescriptionInterface* answer = CreateAnswer(NULL); 745 // Answer should be NULL as no crypto params in offer. 746 ASSERT_TRUE(answer == NULL); 747 } 748 749 void VerifyAnswerFromCryptoOffer() { 750 cricket::MediaSessionOptions options; 751 options.recv_video = true; 752 options.bundle_enabled = true; 753 scoped_ptr<JsepSessionDescription> offer( 754 CreateRemoteOffer(options, cricket::SEC_REQUIRED)); 755 ASSERT_TRUE(offer.get() != NULL); 756 VerifyCryptoParams(offer->description()); 757 SetRemoteDescriptionWithoutError(offer.release()); 758 scoped_ptr<SessionDescriptionInterface> answer(CreateAnswer(NULL)); 759 ASSERT_TRUE(answer.get() != NULL); 760 VerifyCryptoParams(answer->description()); 761 } 762 763 void SetAndVerifyNumUnsignalledRecvStreams( 764 int value_set, int value_expected) { 765 constraints_.reset(new FakeConstraints()); 766 constraints_->AddOptional( 767 webrtc::MediaConstraintsInterface::kNumUnsignalledRecvStreams, 768 value_set); 769 session_.reset(); 770 Init(); 771 SendAudioVideoStream1(); 772 SessionDescriptionInterface* offer = CreateOffer(); 773 774 SetLocalDescriptionWithoutError(offer); 775 776 video_channel_ = media_engine_->GetVideoChannel(0); 777 778 ASSERT_TRUE(video_channel_ != NULL); 779 const cricket::VideoOptions& video_options = video_channel_->options(); 780 EXPECT_EQ(value_expected, 781 video_options.unsignalled_recv_stream_limit.value_or(-1)); 782 } 783 784 void CompareIceUfragAndPassword(const cricket::SessionDescription* desc1, 785 const cricket::SessionDescription* desc2, 786 bool expect_equal) { 787 if (desc1->contents().size() != desc2->contents().size()) { 788 EXPECT_FALSE(expect_equal); 789 return; 790 } 791 792 const cricket::ContentInfos& contents = desc1->contents(); 793 cricket::ContentInfos::const_iterator it = contents.begin(); 794 795 for (; it != contents.end(); ++it) { 796 const cricket::TransportDescription* transport_desc1 = 797 desc1->GetTransportDescriptionByName(it->name); 798 const cricket::TransportDescription* transport_desc2 = 799 desc2->GetTransportDescriptionByName(it->name); 800 if (!transport_desc1 || !transport_desc2) { 801 EXPECT_FALSE(expect_equal); 802 return; 803 } 804 if (transport_desc1->ice_pwd != transport_desc2->ice_pwd || 805 transport_desc1->ice_ufrag != transport_desc2->ice_ufrag) { 806 EXPECT_FALSE(expect_equal); 807 return; 808 } 809 } 810 EXPECT_TRUE(expect_equal); 811 } 812 813 void RemoveIceUfragPwdLines(const SessionDescriptionInterface* current_desc, 814 std::string *sdp) { 815 const cricket::SessionDescription* desc = current_desc->description(); 816 EXPECT_TRUE(current_desc->ToString(sdp)); 817 818 const cricket::ContentInfos& contents = desc->contents(); 819 cricket::ContentInfos::const_iterator it = contents.begin(); 820 // Replace ufrag and pwd lines with empty strings. 821 for (; it != contents.end(); ++it) { 822 const cricket::TransportDescription* transport_desc = 823 desc->GetTransportDescriptionByName(it->name); 824 std::string ufrag_line = "a=ice-ufrag:" + transport_desc->ice_ufrag 825 + "\r\n"; 826 std::string pwd_line = "a=ice-pwd:" + transport_desc->ice_pwd 827 + "\r\n"; 828 rtc::replace_substrs(ufrag_line.c_str(), ufrag_line.length(), 829 "", 0, 830 sdp); 831 rtc::replace_substrs(pwd_line.c_str(), pwd_line.length(), 832 "", 0, 833 sdp); 834 } 835 } 836 837 void ModifyIceUfragPwdLines(const SessionDescriptionInterface* current_desc, 838 const std::string& modified_ice_ufrag, 839 const std::string& modified_ice_pwd, 840 std::string* sdp) { 841 const cricket::SessionDescription* desc = current_desc->description(); 842 EXPECT_TRUE(current_desc->ToString(sdp)); 843 844 const cricket::ContentInfos& contents = desc->contents(); 845 cricket::ContentInfos::const_iterator it = contents.begin(); 846 // Replace ufrag and pwd lines with |modified_ice_ufrag| and 847 // |modified_ice_pwd| strings. 848 for (; it != contents.end(); ++it) { 849 const cricket::TransportDescription* transport_desc = 850 desc->GetTransportDescriptionByName(it->name); 851 std::string ufrag_line = "a=ice-ufrag:" + transport_desc->ice_ufrag 852 + "\r\n"; 853 std::string pwd_line = "a=ice-pwd:" + transport_desc->ice_pwd 854 + "\r\n"; 855 std::string mod_ufrag = "a=ice-ufrag:" + modified_ice_ufrag + "\r\n"; 856 std::string mod_pwd = "a=ice-pwd:" + modified_ice_pwd + "\r\n"; 857 rtc::replace_substrs(ufrag_line.c_str(), ufrag_line.length(), 858 mod_ufrag.c_str(), mod_ufrag.length(), 859 sdp); 860 rtc::replace_substrs(pwd_line.c_str(), pwd_line.length(), 861 mod_pwd.c_str(), mod_pwd.length(), 862 sdp); 863 } 864 } 865 866 // Creates a remote offer and and applies it as a remote description, 867 // creates a local answer and applies is as a local description. 868 // Call SendAudioVideoStreamX() before this function 869 // to decide which local and remote streams to create. 870 void CreateAndSetRemoteOfferAndLocalAnswer() { 871 SessionDescriptionInterface* offer = CreateRemoteOffer(); 872 SetRemoteDescriptionWithoutError(offer); 873 SessionDescriptionInterface* answer = CreateAnswer(NULL); 874 SetLocalDescriptionWithoutError(answer); 875 } 876 void SetLocalDescriptionWithoutError(SessionDescriptionInterface* desc) { 877 EXPECT_TRUE(session_->SetLocalDescription(desc, NULL)); 878 session_->MaybeStartGathering(); 879 } 880 void SetLocalDescriptionExpectState(SessionDescriptionInterface* desc, 881 WebRtcSession::State expected_state) { 882 SetLocalDescriptionWithoutError(desc); 883 EXPECT_EQ(expected_state, session_->state()); 884 } 885 void SetLocalDescriptionExpectError(const std::string& action, 886 const std::string& expected_error, 887 SessionDescriptionInterface* desc) { 888 std::string error; 889 EXPECT_FALSE(session_->SetLocalDescription(desc, &error)); 890 std::string sdp_type = "local "; 891 sdp_type.append(action); 892 EXPECT_NE(std::string::npos, error.find(sdp_type)); 893 EXPECT_NE(std::string::npos, error.find(expected_error)); 894 } 895 void SetLocalDescriptionOfferExpectError(const std::string& expected_error, 896 SessionDescriptionInterface* desc) { 897 SetLocalDescriptionExpectError(SessionDescriptionInterface::kOffer, 898 expected_error, desc); 899 } 900 void SetLocalDescriptionAnswerExpectError(const std::string& expected_error, 901 SessionDescriptionInterface* desc) { 902 SetLocalDescriptionExpectError(SessionDescriptionInterface::kAnswer, 903 expected_error, desc); 904 } 905 void SetRemoteDescriptionWithoutError(SessionDescriptionInterface* desc) { 906 EXPECT_TRUE(session_->SetRemoteDescription(desc, NULL)); 907 } 908 void SetRemoteDescriptionExpectState(SessionDescriptionInterface* desc, 909 WebRtcSession::State expected_state) { 910 SetRemoteDescriptionWithoutError(desc); 911 EXPECT_EQ(expected_state, session_->state()); 912 } 913 void SetRemoteDescriptionExpectError(const std::string& action, 914 const std::string& expected_error, 915 SessionDescriptionInterface* desc) { 916 std::string error; 917 EXPECT_FALSE(session_->SetRemoteDescription(desc, &error)); 918 std::string sdp_type = "remote "; 919 sdp_type.append(action); 920 EXPECT_NE(std::string::npos, error.find(sdp_type)); 921 EXPECT_NE(std::string::npos, error.find(expected_error)); 922 } 923 void SetRemoteDescriptionOfferExpectError( 924 const std::string& expected_error, SessionDescriptionInterface* desc) { 925 SetRemoteDescriptionExpectError(SessionDescriptionInterface::kOffer, 926 expected_error, desc); 927 } 928 void SetRemoteDescriptionPranswerExpectError( 929 const std::string& expected_error, SessionDescriptionInterface* desc) { 930 SetRemoteDescriptionExpectError(SessionDescriptionInterface::kPrAnswer, 931 expected_error, desc); 932 } 933 void SetRemoteDescriptionAnswerExpectError( 934 const std::string& expected_error, SessionDescriptionInterface* desc) { 935 SetRemoteDescriptionExpectError(SessionDescriptionInterface::kAnswer, 936 expected_error, desc); 937 } 938 939 void CreateCryptoOfferAndNonCryptoAnswer(SessionDescriptionInterface** offer, 940 SessionDescriptionInterface** nocrypto_answer) { 941 // Create a SDP without Crypto. 942 cricket::MediaSessionOptions options; 943 options.recv_video = true; 944 options.bundle_enabled = true; 945 *offer = CreateRemoteOffer(options, cricket::SEC_ENABLED); 946 ASSERT_TRUE(*offer != NULL); 947 VerifyCryptoParams((*offer)->description()); 948 949 *nocrypto_answer = CreateRemoteAnswer(*offer, options, 950 cricket::SEC_DISABLED); 951 EXPECT_TRUE(*nocrypto_answer != NULL); 952 } 953 954 void CreateDtlsOfferAndNonDtlsAnswer(SessionDescriptionInterface** offer, 955 SessionDescriptionInterface** nodtls_answer) { 956 cricket::MediaSessionOptions options; 957 options.recv_video = true; 958 options.bundle_enabled = true; 959 960 rtc::scoped_ptr<SessionDescriptionInterface> temp_offer( 961 CreateRemoteOffer(options, cricket::SEC_ENABLED)); 962 963 *nodtls_answer = 964 CreateRemoteAnswer(temp_offer.get(), options, cricket::SEC_ENABLED); 965 EXPECT_TRUE(*nodtls_answer != NULL); 966 VerifyFingerprintStatus((*nodtls_answer)->description(), false); 967 VerifyCryptoParams((*nodtls_answer)->description()); 968 969 SetFactoryDtlsSrtp(); 970 *offer = CreateRemoteOffer(options, cricket::SEC_ENABLED); 971 ASSERT_TRUE(*offer != NULL); 972 VerifyFingerprintStatus((*offer)->description(), true); 973 VerifyCryptoParams((*offer)->description()); 974 } 975 976 JsepSessionDescription* CreateRemoteOfferWithVersion( 977 cricket::MediaSessionOptions options, 978 cricket::SecurePolicy secure_policy, 979 const std::string& session_version, 980 const SessionDescriptionInterface* current_desc) { 981 std::string session_id = rtc::ToString(rtc::CreateRandomId64()); 982 const cricket::SessionDescription* cricket_desc = NULL; 983 if (current_desc) { 984 cricket_desc = current_desc->description(); 985 session_id = current_desc->session_id(); 986 } 987 988 desc_factory_->set_secure(secure_policy); 989 JsepSessionDescription* offer( 990 new JsepSessionDescription(JsepSessionDescription::kOffer)); 991 if (!offer->Initialize(desc_factory_->CreateOffer(options, cricket_desc), 992 session_id, session_version)) { 993 delete offer; 994 offer = NULL; 995 } 996 return offer; 997 } 998 JsepSessionDescription* CreateRemoteOffer( 999 cricket::MediaSessionOptions options) { 1000 return CreateRemoteOfferWithVersion(options, cricket::SEC_ENABLED, 1001 kSessionVersion, NULL); 1002 } 1003 JsepSessionDescription* CreateRemoteOffer( 1004 cricket::MediaSessionOptions options, cricket::SecurePolicy sdes_policy) { 1005 return CreateRemoteOfferWithVersion( 1006 options, sdes_policy, kSessionVersion, NULL); 1007 } 1008 JsepSessionDescription* CreateRemoteOffer( 1009 cricket::MediaSessionOptions options, 1010 const SessionDescriptionInterface* current_desc) { 1011 return CreateRemoteOfferWithVersion(options, cricket::SEC_ENABLED, 1012 kSessionVersion, current_desc); 1013 } 1014 1015 JsepSessionDescription* CreateRemoteOfferWithSctpPort( 1016 const char* sctp_stream_name, int new_port, 1017 cricket::MediaSessionOptions options) { 1018 options.data_channel_type = cricket::DCT_SCTP; 1019 options.AddSendStream(cricket::MEDIA_TYPE_DATA, "datachannel", 1020 sctp_stream_name); 1021 return ChangeSDPSctpPort(new_port, CreateRemoteOffer(options)); 1022 } 1023 1024 // Takes ownership of offer_basis (and deletes it). 1025 JsepSessionDescription* ChangeSDPSctpPort( 1026 int new_port, webrtc::SessionDescriptionInterface *offer_basis) { 1027 // Stringify the input SDP, swap the 5000 for 'new_port' and create a new 1028 // SessionDescription from the mutated string. 1029 const char* default_port_str = "5000"; 1030 char new_port_str[16]; 1031 rtc::sprintfn(new_port_str, sizeof(new_port_str), "%d", new_port); 1032 std::string offer_str; 1033 offer_basis->ToString(&offer_str); 1034 rtc::replace_substrs(default_port_str, strlen(default_port_str), 1035 new_port_str, strlen(new_port_str), 1036 &offer_str); 1037 JsepSessionDescription* offer = new JsepSessionDescription( 1038 offer_basis->type()); 1039 delete offer_basis; 1040 offer->Initialize(offer_str, NULL); 1041 return offer; 1042 } 1043 1044 // Create a remote offer. Call SendAudioVideoStreamX() 1045 // before this function to decide which streams to create. 1046 JsepSessionDescription* CreateRemoteOffer() { 1047 cricket::MediaSessionOptions options; 1048 GetOptionsForAnswer(NULL, &options); 1049 return CreateRemoteOffer(options, session_->remote_description()); 1050 } 1051 1052 JsepSessionDescription* CreateRemoteAnswer( 1053 const SessionDescriptionInterface* offer, 1054 cricket::MediaSessionOptions options, 1055 cricket::SecurePolicy policy) { 1056 desc_factory_->set_secure(policy); 1057 const std::string session_id = 1058 rtc::ToString(rtc::CreateRandomId64()); 1059 JsepSessionDescription* answer( 1060 new JsepSessionDescription(JsepSessionDescription::kAnswer)); 1061 if (!answer->Initialize(desc_factory_->CreateAnswer(offer->description(), 1062 options, NULL), 1063 session_id, kSessionVersion)) { 1064 delete answer; 1065 answer = NULL; 1066 } 1067 return answer; 1068 } 1069 1070 JsepSessionDescription* CreateRemoteAnswer( 1071 const SessionDescriptionInterface* offer, 1072 cricket::MediaSessionOptions options) { 1073 return CreateRemoteAnswer(offer, options, cricket::SEC_REQUIRED); 1074 } 1075 1076 // Creates an answer session description. 1077 // Call SendAudioVideoStreamX() before this function 1078 // to decide which streams to create. 1079 JsepSessionDescription* CreateRemoteAnswer( 1080 const SessionDescriptionInterface* offer) { 1081 cricket::MediaSessionOptions options; 1082 GetOptionsForAnswer(NULL, &options); 1083 return CreateRemoteAnswer(offer, options, cricket::SEC_REQUIRED); 1084 } 1085 1086 void TestSessionCandidatesWithBundleRtcpMux(bool bundle, bool rtcp_mux) { 1087 AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort)); 1088 Init(); 1089 SendAudioVideoStream1(); 1090 1091 PeerConnectionInterface::RTCOfferAnswerOptions options; 1092 options.use_rtp_mux = bundle; 1093 1094 SessionDescriptionInterface* offer = CreateOffer(options); 1095 // SetLocalDescription and SetRemoteDescriptions takes ownership of offer 1096 // and answer. 1097 SetLocalDescriptionWithoutError(offer); 1098 1099 rtc::scoped_ptr<SessionDescriptionInterface> answer( 1100 CreateRemoteAnswer(session_->local_description())); 1101 std::string sdp; 1102 EXPECT_TRUE(answer->ToString(&sdp)); 1103 1104 size_t expected_candidate_num = 2; 1105 if (!rtcp_mux) { 1106 // If rtcp_mux is enabled we should expect 4 candidates - host and srflex 1107 // for rtp and rtcp. 1108 expected_candidate_num = 4; 1109 // Disable rtcp-mux from the answer 1110 const std::string kRtcpMux = "a=rtcp-mux"; 1111 const std::string kXRtcpMux = "a=xrtcp-mux"; 1112 rtc::replace_substrs(kRtcpMux.c_str(), kRtcpMux.length(), 1113 kXRtcpMux.c_str(), kXRtcpMux.length(), 1114 &sdp); 1115 } 1116 1117 SessionDescriptionInterface* new_answer = CreateSessionDescription( 1118 JsepSessionDescription::kAnswer, sdp, NULL); 1119 1120 // SetRemoteDescription to enable rtcp mux. 1121 SetRemoteDescriptionWithoutError(new_answer); 1122 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout); 1123 EXPECT_EQ(expected_candidate_num, observer_.mline_0_candidates_.size()); 1124 if (bundle) { 1125 EXPECT_EQ(0, observer_.mline_1_candidates_.size()); 1126 } else { 1127 EXPECT_EQ(expected_candidate_num, observer_.mline_1_candidates_.size()); 1128 } 1129 } 1130 // Tests that we can only send DTMF when the dtmf codec is supported. 1131 void TestCanInsertDtmf(bool can) { 1132 if (can) { 1133 InitWithDtmfCodec(); 1134 } else { 1135 Init(); 1136 } 1137 SendAudioVideoStream1(); 1138 CreateAndSetRemoteOfferAndLocalAnswer(); 1139 EXPECT_FALSE(session_->CanInsertDtmf("")); 1140 EXPECT_EQ(can, session_->CanInsertDtmf(kAudioTrack1)); 1141 } 1142 1143 // Helper class to configure loopback network and verify Best 1144 // Connection using right IP protocol for TestLoopbackCall 1145 // method. LoopbackNetworkManager applies firewall rules to block 1146 // all ping traffic once ICE completed, and remove them to observe 1147 // ICE reconnected again. This LoopbackNetworkConfiguration struct 1148 // verifies the best connection is using the right IP protocol after 1149 // initial ICE convergences. 1150 1151 class LoopbackNetworkConfiguration { 1152 public: 1153 LoopbackNetworkConfiguration() 1154 : test_ipv6_network_(false), 1155 test_extra_ipv4_network_(false), 1156 best_connection_after_initial_ice_converged_(1, 0) {} 1157 1158 // Used to track the expected best connection count in each IP protocol. 1159 struct ExpectedBestConnection { 1160 ExpectedBestConnection(int ipv4_count, int ipv6_count) 1161 : ipv4_count_(ipv4_count), 1162 ipv6_count_(ipv6_count) {} 1163 1164 int ipv4_count_; 1165 int ipv6_count_; 1166 }; 1167 1168 bool test_ipv6_network_; 1169 bool test_extra_ipv4_network_; 1170 ExpectedBestConnection best_connection_after_initial_ice_converged_; 1171 1172 void VerifyBestConnectionAfterIceConverge( 1173 const rtc::scoped_refptr<FakeMetricsObserver> metrics_observer) const { 1174 Verify(metrics_observer, best_connection_after_initial_ice_converged_); 1175 } 1176 1177 private: 1178 void Verify(const rtc::scoped_refptr<FakeMetricsObserver> metrics_observer, 1179 const ExpectedBestConnection& expected) const { 1180 EXPECT_EQ( 1181 metrics_observer->GetEnumCounter(webrtc::kEnumCounterAddressFamily, 1182 webrtc::kBestConnections_IPv4), 1183 expected.ipv4_count_); 1184 EXPECT_EQ( 1185 metrics_observer->GetEnumCounter(webrtc::kEnumCounterAddressFamily, 1186 webrtc::kBestConnections_IPv6), 1187 expected.ipv6_count_); 1188 // This is used in the loopback call so there is only single host to host 1189 // candidate pair. 1190 EXPECT_EQ(metrics_observer->GetEnumCounter( 1191 webrtc::kEnumCounterIceCandidatePairTypeUdp, 1192 webrtc::kIceCandidatePairHostHost), 1193 0); 1194 EXPECT_EQ(metrics_observer->GetEnumCounter( 1195 webrtc::kEnumCounterIceCandidatePairTypeUdp, 1196 webrtc::kIceCandidatePairHostPublicHostPublic), 1197 1); 1198 } 1199 }; 1200 1201 class LoopbackNetworkManager { 1202 public: 1203 LoopbackNetworkManager(WebRtcSessionTest* session, 1204 const LoopbackNetworkConfiguration& config) 1205 : config_(config) { 1206 session->AddInterface( 1207 rtc::SocketAddress(kClientAddrHost1, kClientAddrPort)); 1208 if (config_.test_extra_ipv4_network_) { 1209 session->AddInterface( 1210 rtc::SocketAddress(kClientAddrHost2, kClientAddrPort)); 1211 } 1212 if (config_.test_ipv6_network_) { 1213 session->AddInterface( 1214 rtc::SocketAddress(kClientIPv6AddrHost1, kClientAddrPort)); 1215 } 1216 } 1217 1218 void ApplyFirewallRules(rtc::FirewallSocketServer* fss) { 1219 fss->AddRule(false, rtc::FP_ANY, rtc::FD_ANY, 1220 rtc::SocketAddress(kClientAddrHost1, kClientAddrPort)); 1221 if (config_.test_extra_ipv4_network_) { 1222 fss->AddRule(false, rtc::FP_ANY, rtc::FD_ANY, 1223 rtc::SocketAddress(kClientAddrHost2, kClientAddrPort)); 1224 } 1225 if (config_.test_ipv6_network_) { 1226 fss->AddRule(false, rtc::FP_ANY, rtc::FD_ANY, 1227 rtc::SocketAddress(kClientIPv6AddrHost1, kClientAddrPort)); 1228 } 1229 } 1230 1231 void ClearRules(rtc::FirewallSocketServer* fss) { fss->ClearRules(); } 1232 1233 private: 1234 LoopbackNetworkConfiguration config_; 1235 }; 1236 1237 // The method sets up a call from the session to itself, in a loopback 1238 // arrangement. It also uses a firewall rule to create a temporary 1239 // disconnection, and then a permanent disconnection. 1240 // This code is placed in a method so that it can be invoked 1241 // by multiple tests with different allocators (e.g. with and without BUNDLE). 1242 // While running the call, this method also checks if the session goes through 1243 // the correct sequence of ICE states when a connection is established, 1244 // broken, and re-established. 1245 // The Connection state should go: 1246 // New -> Checking -> (Connected) -> Completed -> Disconnected -> Completed 1247 // -> Failed. 1248 // The Gathering state should go: New -> Gathering -> Completed. 1249 1250 void SetupLoopbackCall() { 1251 Init(); 1252 SendAudioVideoStream1(); 1253 SessionDescriptionInterface* offer = CreateOffer(); 1254 1255 EXPECT_EQ(PeerConnectionInterface::kIceGatheringNew, 1256 observer_.ice_gathering_state_); 1257 SetLocalDescriptionWithoutError(offer); 1258 EXPECT_EQ(PeerConnectionInterface::kIceConnectionNew, 1259 observer_.ice_connection_state_); 1260 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceGatheringGathering, 1261 observer_.ice_gathering_state_, kIceCandidatesTimeout); 1262 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout); 1263 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceGatheringComplete, 1264 observer_.ice_gathering_state_, kIceCandidatesTimeout); 1265 1266 std::string sdp; 1267 offer->ToString(&sdp); 1268 SessionDescriptionInterface* desc = webrtc::CreateSessionDescription( 1269 JsepSessionDescription::kAnswer, sdp, nullptr); 1270 ASSERT_TRUE(desc != NULL); 1271 SetRemoteDescriptionWithoutError(desc); 1272 1273 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionChecking, 1274 observer_.ice_connection_state_, kIceCandidatesTimeout); 1275 1276 // The ice connection state is "Connected" too briefly to catch in a test. 1277 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionCompleted, 1278 observer_.ice_connection_state_, kIceCandidatesTimeout); 1279 } 1280 1281 void TestLoopbackCall(const LoopbackNetworkConfiguration& config) { 1282 LoopbackNetworkManager loopback_network_manager(this, config); 1283 SetupLoopbackCall(); 1284 config.VerifyBestConnectionAfterIceConverge(metrics_observer_); 1285 // Adding firewall rule to block ping requests, which should cause 1286 // transport channel failure. 1287 1288 loopback_network_manager.ApplyFirewallRules(fss_.get()); 1289 1290 LOG(LS_INFO) << "Firewall Rules applied"; 1291 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionDisconnected, 1292 observer_.ice_connection_state_, 1293 kIceCandidatesTimeout); 1294 1295 metrics_observer_->Reset(); 1296 1297 // Clearing the rules, session should move back to completed state. 1298 loopback_network_manager.ClearRules(fss_.get()); 1299 1300 LOG(LS_INFO) << "Firewall Rules cleared"; 1301 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionCompleted, 1302 observer_.ice_connection_state_, 1303 kIceCandidatesTimeout); 1304 1305 // Now we block ping requests and wait until the ICE connection transitions 1306 // to the Failed state. This will take at least 30 seconds because it must 1307 // wait for the Port to timeout. 1308 int port_timeout = 30000; 1309 1310 loopback_network_manager.ApplyFirewallRules(fss_.get()); 1311 LOG(LS_INFO) << "Firewall Rules applied again"; 1312 EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionDisconnected, 1313 observer_.ice_connection_state_, 1314 kIceCandidatesTimeout + port_timeout); 1315 } 1316 1317 void TestLoopbackCall() { 1318 LoopbackNetworkConfiguration config; 1319 TestLoopbackCall(config); 1320 } 1321 1322 void TestPacketOptions() { 1323 media_controller_.reset( 1324 new cricket::FakeMediaController(channel_manager_.get(), &fake_call_)); 1325 LoopbackNetworkConfiguration config; 1326 LoopbackNetworkManager loopback_network_manager(this, config); 1327 1328 SetupLoopbackCall(); 1329 1330 uint8_t test_packet[15] = {0}; 1331 rtc::PacketOptions options; 1332 options.packet_id = 10; 1333 media_engine_->GetVideoChannel(0) 1334 ->SendRtp(test_packet, sizeof(test_packet), options); 1335 1336 const int kPacketTimeout = 2000; 1337 EXPECT_EQ_WAIT(fake_call_.last_sent_packet().packet_id, 10, kPacketTimeout); 1338 EXPECT_GT(fake_call_.last_sent_packet().send_time_ms, -1); 1339 } 1340 1341 // Adds CN codecs to FakeMediaEngine and MediaDescriptionFactory. 1342 void AddCNCodecs() { 1343 const cricket::AudioCodec kCNCodec1(102, "CN", 8000, 0, 1, 0); 1344 const cricket::AudioCodec kCNCodec2(103, "CN", 16000, 0, 1, 0); 1345 1346 // Add kCNCodec for dtmf test. 1347 std::vector<cricket::AudioCodec> codecs = media_engine_->audio_codecs();; 1348 codecs.push_back(kCNCodec1); 1349 codecs.push_back(kCNCodec2); 1350 media_engine_->SetAudioCodecs(codecs); 1351 desc_factory_->set_audio_codecs(codecs); 1352 } 1353 1354 bool VerifyNoCNCodecs(const cricket::ContentInfo* content) { 1355 const cricket::ContentDescription* description = content->description; 1356 ASSERT(description != NULL); 1357 const cricket::AudioContentDescription* audio_content_desc = 1358 static_cast<const cricket::AudioContentDescription*>(description); 1359 ASSERT(audio_content_desc != NULL); 1360 for (size_t i = 0; i < audio_content_desc->codecs().size(); ++i) { 1361 if (audio_content_desc->codecs()[i].name == "CN") 1362 return false; 1363 } 1364 return true; 1365 } 1366 1367 void CreateDataChannel() { 1368 webrtc::InternalDataChannelInit dci; 1369 dci.reliable = session_->data_channel_type() == cricket::DCT_SCTP; 1370 data_channel_ = DataChannel::Create( 1371 session_.get(), session_->data_channel_type(), "datachannel", dci); 1372 } 1373 1374 void SetLocalDescriptionWithDataChannel() { 1375 CreateDataChannel(); 1376 SessionDescriptionInterface* offer = CreateOffer(); 1377 SetLocalDescriptionWithoutError(offer); 1378 } 1379 1380 void VerifyMultipleAsyncCreateDescription( 1381 RTCCertificateGenerationMethod cert_gen_method, 1382 CreateSessionDescriptionRequest::Type type) { 1383 InitWithDtls(cert_gen_method); 1384 VerifyMultipleAsyncCreateDescriptionAfterInit(true, type); 1385 } 1386 1387 void VerifyMultipleAsyncCreateDescriptionIdentityGenFailure( 1388 CreateSessionDescriptionRequest::Type type) { 1389 InitWithDtlsIdentityGenFail(); 1390 VerifyMultipleAsyncCreateDescriptionAfterInit(false, type); 1391 } 1392 1393 void VerifyMultipleAsyncCreateDescriptionAfterInit( 1394 bool success, CreateSessionDescriptionRequest::Type type) { 1395 RTC_CHECK(session_); 1396 SetFactoryDtlsSrtp(); 1397 if (type == CreateSessionDescriptionRequest::kAnswer) { 1398 cricket::MediaSessionOptions options; 1399 scoped_ptr<JsepSessionDescription> offer( 1400 CreateRemoteOffer(options, cricket::SEC_DISABLED)); 1401 ASSERT_TRUE(offer.get() != NULL); 1402 SetRemoteDescriptionWithoutError(offer.release()); 1403 } 1404 1405 PeerConnectionInterface::RTCOfferAnswerOptions options; 1406 cricket::MediaSessionOptions session_options; 1407 const int kNumber = 3; 1408 rtc::scoped_refptr<WebRtcSessionCreateSDPObserverForTest> 1409 observers[kNumber]; 1410 for (int i = 0; i < kNumber; ++i) { 1411 observers[i] = new WebRtcSessionCreateSDPObserverForTest(); 1412 if (type == CreateSessionDescriptionRequest::kOffer) { 1413 session_->CreateOffer(observers[i], options, session_options); 1414 } else { 1415 session_->CreateAnswer(observers[i], nullptr, session_options); 1416 } 1417 } 1418 1419 WebRtcSessionCreateSDPObserverForTest::State expected_state = 1420 success ? WebRtcSessionCreateSDPObserverForTest::kSucceeded : 1421 WebRtcSessionCreateSDPObserverForTest::kFailed; 1422 1423 for (int i = 0; i < kNumber; ++i) { 1424 EXPECT_EQ_WAIT(expected_state, observers[i]->state(), 1000); 1425 if (success) { 1426 EXPECT_TRUE(observers[i]->description() != NULL); 1427 } else { 1428 EXPECT_TRUE(observers[i]->description() == NULL); 1429 } 1430 } 1431 } 1432 1433 void ConfigureAllocatorWithTurn() { 1434 cricket::RelayServerConfig turn_server(cricket::RELAY_TURN); 1435 cricket::RelayCredentials credentials(kTurnUsername, kTurnPassword); 1436 turn_server.credentials = credentials; 1437 turn_server.ports.push_back( 1438 cricket::ProtocolAddress(kTurnUdpIntAddr, cricket::PROTO_UDP, false)); 1439 allocator_->AddTurnServer(turn_server); 1440 allocator_->set_step_delay(cricket::kMinimumStepDelay); 1441 allocator_->set_flags(cricket::PORTALLOCATOR_DISABLE_TCP); 1442 } 1443 1444 cricket::FakeMediaEngine* media_engine_; 1445 cricket::FakeDataEngine* data_engine_; 1446 rtc::scoped_ptr<cricket::ChannelManager> channel_manager_; 1447 cricket::FakeCall fake_call_; 1448 rtc::scoped_ptr<webrtc::MediaControllerInterface> media_controller_; 1449 rtc::scoped_ptr<cricket::TransportDescriptionFactory> tdesc_factory_; 1450 rtc::scoped_ptr<cricket::MediaSessionDescriptionFactory> desc_factory_; 1451 rtc::scoped_ptr<rtc::PhysicalSocketServer> pss_; 1452 rtc::scoped_ptr<rtc::VirtualSocketServer> vss_; 1453 rtc::scoped_ptr<rtc::FirewallSocketServer> fss_; 1454 rtc::SocketServerScope ss_scope_; 1455 rtc::SocketAddress stun_socket_addr_; 1456 rtc::scoped_ptr<cricket::TestStunServer> stun_server_; 1457 cricket::TestTurnServer turn_server_; 1458 rtc::FakeNetworkManager network_manager_; 1459 rtc::scoped_ptr<cricket::BasicPortAllocator> allocator_; 1460 PeerConnectionFactoryInterface::Options options_; 1461 rtc::scoped_ptr<FakeConstraints> constraints_; 1462 rtc::scoped_ptr<WebRtcSessionForTest> session_; 1463 MockIceObserver observer_; 1464 cricket::FakeVideoMediaChannel* video_channel_; 1465 cricket::FakeVoiceMediaChannel* voice_channel_; 1466 rtc::scoped_refptr<FakeMetricsObserver> metrics_observer_; 1467 // The following flags affect options created for CreateOffer/CreateAnswer. 1468 bool send_stream_1_ = false; 1469 bool send_stream_2_ = false; 1470 bool send_audio_ = false; 1471 bool send_video_ = false; 1472 rtc::scoped_refptr<DataChannel> data_channel_; 1473 // Last values received from data channel creation signal. 1474 std::string last_data_channel_label_; 1475 InternalDataChannelInit last_data_channel_config_; 1476 }; 1477 1478 TEST_P(WebRtcSessionTest, TestInitializeWithDtls) { 1479 InitWithDtls(GetParam()); 1480 // SDES is disabled when DTLS is on. 1481 EXPECT_EQ(cricket::SEC_DISABLED, session_->SdesPolicy()); 1482 } 1483 1484 TEST_F(WebRtcSessionTest, TestInitializeWithoutDtls) { 1485 Init(); 1486 // SDES is required if DTLS is off. 1487 EXPECT_EQ(cricket::SEC_REQUIRED, session_->SdesPolicy()); 1488 } 1489 1490 TEST_F(WebRtcSessionTest, TestSessionCandidates) { 1491 TestSessionCandidatesWithBundleRtcpMux(false, false); 1492 } 1493 1494 // Below test cases (TestSessionCandidatesWith*) verify the candidates gathered 1495 // with rtcp-mux and/or bundle. 1496 TEST_F(WebRtcSessionTest, TestSessionCandidatesWithRtcpMux) { 1497 TestSessionCandidatesWithBundleRtcpMux(false, true); 1498 } 1499 1500 TEST_F(WebRtcSessionTest, TestSessionCandidatesWithBundleRtcpMux) { 1501 TestSessionCandidatesWithBundleRtcpMux(true, true); 1502 } 1503 1504 TEST_F(WebRtcSessionTest, TestMultihomeCandidates) { 1505 AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort)); 1506 AddInterface(rtc::SocketAddress(kClientAddrHost2, kClientAddrPort)); 1507 Init(); 1508 SendAudioVideoStream1(); 1509 InitiateCall(); 1510 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout); 1511 EXPECT_EQ(8u, observer_.mline_0_candidates_.size()); 1512 EXPECT_EQ(8u, observer_.mline_1_candidates_.size()); 1513 } 1514 1515 TEST_F(WebRtcSessionTest, TestStunError) { 1516 AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort)); 1517 AddInterface(rtc::SocketAddress(kClientAddrHost2, kClientAddrPort)); 1518 fss_->AddRule(false, 1519 rtc::FP_UDP, 1520 rtc::FD_ANY, 1521 rtc::SocketAddress(kClientAddrHost1, kClientAddrPort)); 1522 Init(); 1523 SendAudioVideoStream1(); 1524 InitiateCall(); 1525 // Since kClientAddrHost1 is blocked, not expecting stun candidates for it. 1526 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout); 1527 EXPECT_EQ(6u, observer_.mline_0_candidates_.size()); 1528 EXPECT_EQ(6u, observer_.mline_1_candidates_.size()); 1529 } 1530 1531 // Test session delivers no candidates gathered when constraint set to "none". 1532 TEST_F(WebRtcSessionTest, TestIceTransportsNone) { 1533 AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort)); 1534 InitWithIceTransport(PeerConnectionInterface::kNone); 1535 SendAudioVideoStream1(); 1536 InitiateCall(); 1537 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout); 1538 EXPECT_EQ(0u, observer_.mline_0_candidates_.size()); 1539 EXPECT_EQ(0u, observer_.mline_1_candidates_.size()); 1540 } 1541 1542 // Test session delivers only relay candidates gathered when constaint set to 1543 // "relay". 1544 TEST_F(WebRtcSessionTest, TestIceTransportsRelay) { 1545 AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort)); 1546 ConfigureAllocatorWithTurn(); 1547 InitWithIceTransport(PeerConnectionInterface::kRelay); 1548 SendAudioVideoStream1(); 1549 InitiateCall(); 1550 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout); 1551 EXPECT_EQ(2u, observer_.mline_0_candidates_.size()); 1552 EXPECT_EQ(2u, observer_.mline_1_candidates_.size()); 1553 for (size_t i = 0; i < observer_.mline_0_candidates_.size(); ++i) { 1554 EXPECT_EQ(cricket::RELAY_PORT_TYPE, 1555 observer_.mline_0_candidates_[i].type()); 1556 } 1557 for (size_t i = 0; i < observer_.mline_1_candidates_.size(); ++i) { 1558 EXPECT_EQ(cricket::RELAY_PORT_TYPE, 1559 observer_.mline_1_candidates_[i].type()); 1560 } 1561 } 1562 1563 // Test session delivers all candidates gathered when constaint set to "all". 1564 TEST_F(WebRtcSessionTest, TestIceTransportsAll) { 1565 AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort)); 1566 InitWithIceTransport(PeerConnectionInterface::kAll); 1567 SendAudioVideoStream1(); 1568 InitiateCall(); 1569 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout); 1570 // Host + STUN. By default allocator is disabled to gather relay candidates. 1571 EXPECT_EQ(4u, observer_.mline_0_candidates_.size()); 1572 EXPECT_EQ(4u, observer_.mline_1_candidates_.size()); 1573 } 1574 1575 TEST_F(WebRtcSessionTest, SetSdpFailedOnInvalidSdp) { 1576 Init(); 1577 SessionDescriptionInterface* offer = NULL; 1578 // Since |offer| is NULL, there's no way to tell if it's an offer or answer. 1579 std::string unknown_action; 1580 SetLocalDescriptionExpectError(unknown_action, kInvalidSdp, offer); 1581 SetRemoteDescriptionExpectError(unknown_action, kInvalidSdp, offer); 1582 } 1583 1584 // Test creating offers and receive answers and make sure the 1585 // media engine creates the expected send and receive streams. 1586 TEST_F(WebRtcSessionTest, TestCreateSdesOfferReceiveSdesAnswer) { 1587 Init(); 1588 SendAudioVideoStream1(); 1589 SessionDescriptionInterface* offer = CreateOffer(); 1590 const std::string session_id_orig = offer->session_id(); 1591 const std::string session_version_orig = offer->session_version(); 1592 SetLocalDescriptionWithoutError(offer); 1593 1594 SendAudioVideoStream2(); 1595 SessionDescriptionInterface* answer = 1596 CreateRemoteAnswer(session_->local_description()); 1597 SetRemoteDescriptionWithoutError(answer); 1598 1599 video_channel_ = media_engine_->GetVideoChannel(0); 1600 voice_channel_ = media_engine_->GetVoiceChannel(0); 1601 1602 ASSERT_EQ(1u, video_channel_->recv_streams().size()); 1603 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id); 1604 1605 ASSERT_EQ(1u, voice_channel_->recv_streams().size()); 1606 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id); 1607 1608 ASSERT_EQ(1u, video_channel_->send_streams().size()); 1609 EXPECT_TRUE(kVideoTrack1 == video_channel_->send_streams()[0].id); 1610 ASSERT_EQ(1u, voice_channel_->send_streams().size()); 1611 EXPECT_TRUE(kAudioTrack1 == voice_channel_->send_streams()[0].id); 1612 1613 // Create new offer without send streams. 1614 SendNothing(); 1615 offer = CreateOffer(); 1616 1617 // Verify the session id is the same and the session version is 1618 // increased. 1619 EXPECT_EQ(session_id_orig, offer->session_id()); 1620 EXPECT_LT(rtc::FromString<uint64_t>(session_version_orig), 1621 rtc::FromString<uint64_t>(offer->session_version())); 1622 1623 SetLocalDescriptionWithoutError(offer); 1624 EXPECT_EQ(0u, video_channel_->send_streams().size()); 1625 EXPECT_EQ(0u, voice_channel_->send_streams().size()); 1626 1627 SendAudioVideoStream2(); 1628 answer = CreateRemoteAnswer(session_->local_description()); 1629 SetRemoteDescriptionWithoutError(answer); 1630 1631 // Make sure the receive streams have not changed. 1632 ASSERT_EQ(1u, video_channel_->recv_streams().size()); 1633 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id); 1634 ASSERT_EQ(1u, voice_channel_->recv_streams().size()); 1635 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id); 1636 } 1637 1638 // Test receiving offers and creating answers and make sure the 1639 // media engine creates the expected send and receive streams. 1640 TEST_F(WebRtcSessionTest, TestReceiveSdesOfferCreateSdesAnswer) { 1641 Init(); 1642 SendAudioVideoStream2(); 1643 SessionDescriptionInterface* offer = CreateOffer(); 1644 VerifyCryptoParams(offer->description()); 1645 SetRemoteDescriptionWithoutError(offer); 1646 1647 SendAudioVideoStream1(); 1648 SessionDescriptionInterface* answer = CreateAnswer(NULL); 1649 VerifyCryptoParams(answer->description()); 1650 SetLocalDescriptionWithoutError(answer); 1651 1652 const std::string session_id_orig = answer->session_id(); 1653 const std::string session_version_orig = answer->session_version(); 1654 1655 video_channel_ = media_engine_->GetVideoChannel(0); 1656 voice_channel_ = media_engine_->GetVoiceChannel(0); 1657 1658 ASSERT_EQ(1u, video_channel_->recv_streams().size()); 1659 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[0].id); 1660 1661 ASSERT_EQ(1u, voice_channel_->recv_streams().size()); 1662 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[0].id); 1663 1664 ASSERT_EQ(1u, video_channel_->send_streams().size()); 1665 EXPECT_TRUE(kVideoTrack1 == video_channel_->send_streams()[0].id); 1666 ASSERT_EQ(1u, voice_channel_->send_streams().size()); 1667 EXPECT_TRUE(kAudioTrack1 == voice_channel_->send_streams()[0].id); 1668 1669 SendAudioVideoStream1And2(); 1670 offer = CreateOffer(); 1671 SetRemoteDescriptionWithoutError(offer); 1672 1673 // Answer by turning off all send streams. 1674 SendNothing(); 1675 answer = CreateAnswer(NULL); 1676 1677 // Verify the session id is the same and the session version is 1678 // increased. 1679 EXPECT_EQ(session_id_orig, answer->session_id()); 1680 EXPECT_LT(rtc::FromString<uint64_t>(session_version_orig), 1681 rtc::FromString<uint64_t>(answer->session_version())); 1682 SetLocalDescriptionWithoutError(answer); 1683 1684 ASSERT_EQ(2u, video_channel_->recv_streams().size()); 1685 EXPECT_TRUE(kVideoTrack1 == video_channel_->recv_streams()[0].id); 1686 EXPECT_TRUE(kVideoTrack2 == video_channel_->recv_streams()[1].id); 1687 ASSERT_EQ(2u, voice_channel_->recv_streams().size()); 1688 EXPECT_TRUE(kAudioTrack1 == voice_channel_->recv_streams()[0].id); 1689 EXPECT_TRUE(kAudioTrack2 == voice_channel_->recv_streams()[1].id); 1690 1691 // Make sure we have no send streams. 1692 EXPECT_EQ(0u, video_channel_->send_streams().size()); 1693 EXPECT_EQ(0u, voice_channel_->send_streams().size()); 1694 } 1695 1696 TEST_F(WebRtcSessionTest, SetLocalSdpFailedOnCreateChannel) { 1697 Init(); 1698 media_engine_->set_fail_create_channel(true); 1699 1700 SessionDescriptionInterface* offer = CreateOffer(); 1701 ASSERT_TRUE(offer != NULL); 1702 // SetRemoteDescription and SetLocalDescription will take the ownership of 1703 // the offer. 1704 SetRemoteDescriptionOfferExpectError(kCreateChannelFailed, offer); 1705 offer = CreateOffer(); 1706 ASSERT_TRUE(offer != NULL); 1707 SetLocalDescriptionOfferExpectError(kCreateChannelFailed, offer); 1708 } 1709 1710 // 1711 // Tests for creating/setting SDP under different SDES/DTLS polices: 1712 // 1713 // --DTLS off and SDES on 1714 // TestCreateSdesOfferReceiveSdesAnswer/TestReceiveSdesOfferCreateSdesAnswer: 1715 // set local/remote offer/answer with crypto --> success 1716 // TestSetNonSdesOfferWhenSdesOn: set local/remote offer without crypto ---> 1717 // failure 1718 // TestSetLocalNonSdesAnswerWhenSdesOn: set local answer without crypto --> 1719 // failure 1720 // TestSetRemoteNonSdesAnswerWhenSdesOn: set remote answer without crypto --> 1721 // failure 1722 // 1723 // --DTLS on and SDES off 1724 // TestCreateDtlsOfferReceiveDtlsAnswer/TestReceiveDtlsOfferCreateDtlsAnswer: 1725 // set local/remote offer/answer with DTLS fingerprint --> success 1726 // TestReceiveNonDtlsOfferWhenDtlsOn: set local/remote offer without DTLS 1727 // fingerprint --> failure 1728 // TestSetLocalNonDtlsAnswerWhenDtlsOn: set local answer without fingerprint 1729 // --> failure 1730 // TestSetRemoteNonDtlsAnswerWhenDtlsOn: set remote answer without fingerprint 1731 // --> failure 1732 // 1733 // --Encryption disabled: DTLS off and SDES off 1734 // TestCreateOfferReceiveAnswerWithoutEncryption: set local offer and remote 1735 // answer without SDES or DTLS --> success 1736 // TestCreateAnswerReceiveOfferWithoutEncryption: set remote offer and local 1737 // answer without SDES or DTLS --> success 1738 // 1739 1740 // Test that we return a failure when applying a remote/local offer that doesn't 1741 // have cryptos enabled when DTLS is off. 1742 TEST_F(WebRtcSessionTest, TestSetNonSdesOfferWhenSdesOn) { 1743 Init(); 1744 cricket::MediaSessionOptions options; 1745 options.recv_video = true; 1746 JsepSessionDescription* offer = CreateRemoteOffer( 1747 options, cricket::SEC_DISABLED); 1748 ASSERT_TRUE(offer != NULL); 1749 VerifyNoCryptoParams(offer->description(), false); 1750 // SetRemoteDescription and SetLocalDescription will take the ownership of 1751 // the offer. 1752 SetRemoteDescriptionOfferExpectError(kSdpWithoutSdesCrypto, offer); 1753 offer = CreateRemoteOffer(options, cricket::SEC_DISABLED); 1754 ASSERT_TRUE(offer != NULL); 1755 SetLocalDescriptionOfferExpectError(kSdpWithoutSdesCrypto, offer); 1756 } 1757 1758 // Test that we return a failure when applying a local answer that doesn't have 1759 // cryptos enabled when DTLS is off. 1760 TEST_F(WebRtcSessionTest, TestSetLocalNonSdesAnswerWhenSdesOn) { 1761 Init(); 1762 SessionDescriptionInterface* offer = NULL; 1763 SessionDescriptionInterface* answer = NULL; 1764 CreateCryptoOfferAndNonCryptoAnswer(&offer, &answer); 1765 // SetRemoteDescription and SetLocalDescription will take the ownership of 1766 // the offer. 1767 SetRemoteDescriptionWithoutError(offer); 1768 SetLocalDescriptionAnswerExpectError(kSdpWithoutSdesCrypto, answer); 1769 } 1770 1771 // Test we will return fail when apply an remote answer that doesn't have 1772 // crypto enabled when DTLS is off. 1773 TEST_F(WebRtcSessionTest, TestSetRemoteNonSdesAnswerWhenSdesOn) { 1774 Init(); 1775 SessionDescriptionInterface* offer = NULL; 1776 SessionDescriptionInterface* answer = NULL; 1777 CreateCryptoOfferAndNonCryptoAnswer(&offer, &answer); 1778 // SetRemoteDescription and SetLocalDescription will take the ownership of 1779 // the offer. 1780 SetLocalDescriptionWithoutError(offer); 1781 SetRemoteDescriptionAnswerExpectError(kSdpWithoutSdesCrypto, answer); 1782 } 1783 1784 // Test that we accept an offer with a DTLS fingerprint when DTLS is on 1785 // and that we return an answer with a DTLS fingerprint. 1786 TEST_P(WebRtcSessionTest, TestReceiveDtlsOfferCreateDtlsAnswer) { 1787 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); 1788 SendAudioVideoStream1(); 1789 InitWithDtls(GetParam()); 1790 SetFactoryDtlsSrtp(); 1791 cricket::MediaSessionOptions options; 1792 options.recv_video = true; 1793 JsepSessionDescription* offer = 1794 CreateRemoteOffer(options, cricket::SEC_DISABLED); 1795 ASSERT_TRUE(offer != NULL); 1796 VerifyFingerprintStatus(offer->description(), true); 1797 VerifyNoCryptoParams(offer->description(), true); 1798 1799 // SetRemoteDescription will take the ownership of the offer. 1800 SetRemoteDescriptionWithoutError(offer); 1801 1802 // Verify that we get a crypto fingerprint in the answer. 1803 SessionDescriptionInterface* answer = CreateAnswer(NULL); 1804 ASSERT_TRUE(answer != NULL); 1805 VerifyFingerprintStatus(answer->description(), true); 1806 // Check that we don't have an a=crypto line in the answer. 1807 VerifyNoCryptoParams(answer->description(), true); 1808 1809 // Now set the local description, which should work, even without a=crypto. 1810 SetLocalDescriptionWithoutError(answer); 1811 } 1812 1813 // Test that we set a local offer with a DTLS fingerprint when DTLS is on 1814 // and then we accept a remote answer with a DTLS fingerprint successfully. 1815 TEST_P(WebRtcSessionTest, TestCreateDtlsOfferReceiveDtlsAnswer) { 1816 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); 1817 SendAudioVideoStream1(); 1818 InitWithDtls(GetParam()); 1819 SetFactoryDtlsSrtp(); 1820 1821 // Verify that we get a crypto fingerprint in the answer. 1822 SessionDescriptionInterface* offer = CreateOffer(); 1823 ASSERT_TRUE(offer != NULL); 1824 VerifyFingerprintStatus(offer->description(), true); 1825 // Check that we don't have an a=crypto line in the offer. 1826 VerifyNoCryptoParams(offer->description(), true); 1827 1828 // Now set the local description, which should work, even without a=crypto. 1829 SetLocalDescriptionWithoutError(offer); 1830 1831 cricket::MediaSessionOptions options; 1832 options.recv_video = true; 1833 JsepSessionDescription* answer = 1834 CreateRemoteAnswer(offer, options, cricket::SEC_DISABLED); 1835 ASSERT_TRUE(answer != NULL); 1836 VerifyFingerprintStatus(answer->description(), true); 1837 VerifyNoCryptoParams(answer->description(), true); 1838 1839 // SetRemoteDescription will take the ownership of the answer. 1840 SetRemoteDescriptionWithoutError(answer); 1841 } 1842 1843 // Test that if we support DTLS and the other side didn't offer a fingerprint, 1844 // we will fail to set the remote description. 1845 TEST_P(WebRtcSessionTest, TestReceiveNonDtlsOfferWhenDtlsOn) { 1846 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); 1847 InitWithDtls(GetParam()); 1848 cricket::MediaSessionOptions options; 1849 options.recv_video = true; 1850 options.bundle_enabled = true; 1851 JsepSessionDescription* offer = CreateRemoteOffer( 1852 options, cricket::SEC_REQUIRED); 1853 ASSERT_TRUE(offer != NULL); 1854 VerifyFingerprintStatus(offer->description(), false); 1855 VerifyCryptoParams(offer->description()); 1856 1857 // SetRemoteDescription will take the ownership of the offer. 1858 SetRemoteDescriptionOfferExpectError( 1859 kSdpWithoutDtlsFingerprint, offer); 1860 1861 offer = CreateRemoteOffer(options, cricket::SEC_REQUIRED); 1862 // SetLocalDescription will take the ownership of the offer. 1863 SetLocalDescriptionOfferExpectError( 1864 kSdpWithoutDtlsFingerprint, offer); 1865 } 1866 1867 // Test that we return a failure when applying a local answer that doesn't have 1868 // a DTLS fingerprint when DTLS is required. 1869 TEST_P(WebRtcSessionTest, TestSetLocalNonDtlsAnswerWhenDtlsOn) { 1870 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); 1871 InitWithDtls(GetParam()); 1872 SessionDescriptionInterface* offer = NULL; 1873 SessionDescriptionInterface* answer = NULL; 1874 CreateDtlsOfferAndNonDtlsAnswer(&offer, &answer); 1875 1876 // SetRemoteDescription and SetLocalDescription will take the ownership of 1877 // the offer and answer. 1878 SetRemoteDescriptionWithoutError(offer); 1879 SetLocalDescriptionAnswerExpectError( 1880 kSdpWithoutDtlsFingerprint, answer); 1881 } 1882 1883 // Test that we return a failure when applying a remote answer that doesn't have 1884 // a DTLS fingerprint when DTLS is required. 1885 TEST_P(WebRtcSessionTest, TestSetRemoteNonDtlsAnswerWhenDtlsOn) { 1886 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); 1887 InitWithDtls(GetParam()); 1888 SessionDescriptionInterface* offer = CreateOffer(); 1889 cricket::MediaSessionOptions options; 1890 options.recv_video = true; 1891 rtc::scoped_ptr<SessionDescriptionInterface> temp_offer( 1892 CreateRemoteOffer(options, cricket::SEC_ENABLED)); 1893 JsepSessionDescription* answer = 1894 CreateRemoteAnswer(temp_offer.get(), options, cricket::SEC_ENABLED); 1895 1896 // SetRemoteDescription and SetLocalDescription will take the ownership of 1897 // the offer and answer. 1898 SetLocalDescriptionWithoutError(offer); 1899 SetRemoteDescriptionAnswerExpectError( 1900 kSdpWithoutDtlsFingerprint, answer); 1901 } 1902 1903 // Test that we create a local offer without SDES or DTLS and accept a remote 1904 // answer without SDES or DTLS when encryption is disabled. 1905 TEST_P(WebRtcSessionTest, TestCreateOfferReceiveAnswerWithoutEncryption) { 1906 SendAudioVideoStream1(); 1907 options_.disable_encryption = true; 1908 InitWithDtls(GetParam()); 1909 1910 // Verify that we get a crypto fingerprint in the answer. 1911 SessionDescriptionInterface* offer = CreateOffer(); 1912 ASSERT_TRUE(offer != NULL); 1913 VerifyFingerprintStatus(offer->description(), false); 1914 // Check that we don't have an a=crypto line in the offer. 1915 VerifyNoCryptoParams(offer->description(), false); 1916 1917 // Now set the local description, which should work, even without a=crypto. 1918 SetLocalDescriptionWithoutError(offer); 1919 1920 cricket::MediaSessionOptions options; 1921 options.recv_video = true; 1922 JsepSessionDescription* answer = 1923 CreateRemoteAnswer(offer, options, cricket::SEC_DISABLED); 1924 ASSERT_TRUE(answer != NULL); 1925 VerifyFingerprintStatus(answer->description(), false); 1926 VerifyNoCryptoParams(answer->description(), false); 1927 1928 // SetRemoteDescription will take the ownership of the answer. 1929 SetRemoteDescriptionWithoutError(answer); 1930 } 1931 1932 // Test that we create a local answer without SDES or DTLS and accept a remote 1933 // offer without SDES or DTLS when encryption is disabled. 1934 TEST_P(WebRtcSessionTest, TestCreateAnswerReceiveOfferWithoutEncryption) { 1935 options_.disable_encryption = true; 1936 InitWithDtls(GetParam()); 1937 1938 cricket::MediaSessionOptions options; 1939 options.recv_video = true; 1940 JsepSessionDescription* offer = 1941 CreateRemoteOffer(options, cricket::SEC_DISABLED); 1942 ASSERT_TRUE(offer != NULL); 1943 VerifyFingerprintStatus(offer->description(), false); 1944 VerifyNoCryptoParams(offer->description(), false); 1945 1946 // SetRemoteDescription will take the ownership of the offer. 1947 SetRemoteDescriptionWithoutError(offer); 1948 1949 // Verify that we get a crypto fingerprint in the answer. 1950 SessionDescriptionInterface* answer = CreateAnswer(NULL); 1951 ASSERT_TRUE(answer != NULL); 1952 VerifyFingerprintStatus(answer->description(), false); 1953 // Check that we don't have an a=crypto line in the answer. 1954 VerifyNoCryptoParams(answer->description(), false); 1955 1956 // Now set the local description, which should work, even without a=crypto. 1957 SetLocalDescriptionWithoutError(answer); 1958 } 1959 1960 // Test that we can create and set an answer correctly when different 1961 // SSL roles have been negotiated for different transports. 1962 // See: https://bugs.chromium.org/p/webrtc/issues/detail?id=4525 1963 TEST_P(WebRtcSessionTest, TestCreateAnswerWithDifferentSslRoles) { 1964 SendAudioVideoStream1(); 1965 InitWithDtls(GetParam()); 1966 SetFactoryDtlsSrtp(); 1967 1968 SessionDescriptionInterface* offer = CreateOffer(); 1969 SetLocalDescriptionWithoutError(offer); 1970 1971 cricket::MediaSessionOptions options; 1972 options.recv_video = true; 1973 1974 // First, negotiate different SSL roles. 1975 SessionDescriptionInterface* answer = 1976 CreateRemoteAnswer(offer, options, cricket::SEC_DISABLED); 1977 TransportInfo* audio_transport_info = 1978 answer->description()->GetTransportInfoByName("audio"); 1979 audio_transport_info->description.connection_role = 1980 cricket::CONNECTIONROLE_ACTIVE; 1981 TransportInfo* video_transport_info = 1982 answer->description()->GetTransportInfoByName("video"); 1983 video_transport_info->description.connection_role = 1984 cricket::CONNECTIONROLE_PASSIVE; 1985 SetRemoteDescriptionWithoutError(answer); 1986 1987 // Now create an offer in the reverse direction, and ensure the initial 1988 // offerer responds with an answer with correct SSL roles. 1989 offer = CreateRemoteOfferWithVersion(options, cricket::SEC_DISABLED, 1990 kSessionVersion, 1991 session_->remote_description()); 1992 SetRemoteDescriptionWithoutError(offer); 1993 1994 answer = CreateAnswer(nullptr); 1995 audio_transport_info = answer->description()->GetTransportInfoByName("audio"); 1996 EXPECT_EQ(cricket::CONNECTIONROLE_PASSIVE, 1997 audio_transport_info->description.connection_role); 1998 video_transport_info = answer->description()->GetTransportInfoByName("video"); 1999 EXPECT_EQ(cricket::CONNECTIONROLE_ACTIVE, 2000 video_transport_info->description.connection_role); 2001 SetLocalDescriptionWithoutError(answer); 2002 2003 // Lastly, start BUNDLE-ing on "audio", expecting that the "passive" role of 2004 // audio is transferred over to video in the answer that completes the BUNDLE 2005 // negotiation. 2006 options.bundle_enabled = true; 2007 offer = CreateRemoteOfferWithVersion(options, cricket::SEC_DISABLED, 2008 kSessionVersion, 2009 session_->remote_description()); 2010 SetRemoteDescriptionWithoutError(offer); 2011 answer = CreateAnswer(nullptr); 2012 audio_transport_info = answer->description()->GetTransportInfoByName("audio"); 2013 EXPECT_EQ(cricket::CONNECTIONROLE_PASSIVE, 2014 audio_transport_info->description.connection_role); 2015 video_transport_info = answer->description()->GetTransportInfoByName("video"); 2016 EXPECT_EQ(cricket::CONNECTIONROLE_PASSIVE, 2017 video_transport_info->description.connection_role); 2018 SetLocalDescriptionWithoutError(answer); 2019 } 2020 2021 TEST_F(WebRtcSessionTest, TestSetLocalOfferTwice) { 2022 Init(); 2023 SendNothing(); 2024 // SetLocalDescription take ownership of offer. 2025 SessionDescriptionInterface* offer = CreateOffer(); 2026 SetLocalDescriptionWithoutError(offer); 2027 2028 // SetLocalDescription take ownership of offer. 2029 SessionDescriptionInterface* offer2 = CreateOffer(); 2030 SetLocalDescriptionWithoutError(offer2); 2031 } 2032 2033 TEST_F(WebRtcSessionTest, TestSetRemoteOfferTwice) { 2034 Init(); 2035 SendNothing(); 2036 // SetLocalDescription take ownership of offer. 2037 SessionDescriptionInterface* offer = CreateOffer(); 2038 SetRemoteDescriptionWithoutError(offer); 2039 2040 SessionDescriptionInterface* offer2 = CreateOffer(); 2041 SetRemoteDescriptionWithoutError(offer2); 2042 } 2043 2044 TEST_F(WebRtcSessionTest, TestSetLocalAndRemoteOffer) { 2045 Init(); 2046 SendNothing(); 2047 SessionDescriptionInterface* offer = CreateOffer(); 2048 SetLocalDescriptionWithoutError(offer); 2049 offer = CreateOffer(); 2050 SetRemoteDescriptionOfferExpectError("Called in wrong state: STATE_SENTOFFER", 2051 offer); 2052 } 2053 2054 TEST_F(WebRtcSessionTest, TestSetRemoteAndLocalOffer) { 2055 Init(); 2056 SendNothing(); 2057 SessionDescriptionInterface* offer = CreateOffer(); 2058 SetRemoteDescriptionWithoutError(offer); 2059 offer = CreateOffer(); 2060 SetLocalDescriptionOfferExpectError( 2061 "Called in wrong state: STATE_RECEIVEDOFFER", offer); 2062 } 2063 2064 TEST_F(WebRtcSessionTest, TestSetLocalPrAnswer) { 2065 Init(); 2066 SendNothing(); 2067 SessionDescriptionInterface* offer = CreateRemoteOffer(); 2068 SetRemoteDescriptionExpectState(offer, WebRtcSession::STATE_RECEIVEDOFFER); 2069 2070 JsepSessionDescription* pranswer = static_cast<JsepSessionDescription*>( 2071 CreateAnswer(NULL)); 2072 pranswer->set_type(SessionDescriptionInterface::kPrAnswer); 2073 SetLocalDescriptionExpectState(pranswer, WebRtcSession::STATE_SENTPRANSWER); 2074 2075 SendAudioVideoStream1(); 2076 JsepSessionDescription* pranswer2 = static_cast<JsepSessionDescription*>( 2077 CreateAnswer(NULL)); 2078 pranswer2->set_type(SessionDescriptionInterface::kPrAnswer); 2079 2080 SetLocalDescriptionExpectState(pranswer2, WebRtcSession::STATE_SENTPRANSWER); 2081 2082 SendAudioVideoStream2(); 2083 SessionDescriptionInterface* answer = CreateAnswer(NULL); 2084 SetLocalDescriptionExpectState(answer, WebRtcSession::STATE_INPROGRESS); 2085 } 2086 2087 TEST_F(WebRtcSessionTest, TestSetRemotePrAnswer) { 2088 Init(); 2089 SendNothing(); 2090 SessionDescriptionInterface* offer = CreateOffer(); 2091 SetLocalDescriptionExpectState(offer, WebRtcSession::STATE_SENTOFFER); 2092 2093 JsepSessionDescription* pranswer = 2094 CreateRemoteAnswer(session_->local_description()); 2095 pranswer->set_type(SessionDescriptionInterface::kPrAnswer); 2096 2097 SetRemoteDescriptionExpectState(pranswer, 2098 WebRtcSession::STATE_RECEIVEDPRANSWER); 2099 2100 SendAudioVideoStream1(); 2101 JsepSessionDescription* pranswer2 = 2102 CreateRemoteAnswer(session_->local_description()); 2103 pranswer2->set_type(SessionDescriptionInterface::kPrAnswer); 2104 2105 SetRemoteDescriptionExpectState(pranswer2, 2106 WebRtcSession::STATE_RECEIVEDPRANSWER); 2107 2108 SendAudioVideoStream2(); 2109 SessionDescriptionInterface* answer = 2110 CreateRemoteAnswer(session_->local_description()); 2111 SetRemoteDescriptionExpectState(answer, WebRtcSession::STATE_INPROGRESS); 2112 } 2113 2114 TEST_F(WebRtcSessionTest, TestSetLocalAnswerWithoutOffer) { 2115 Init(); 2116 SendNothing(); 2117 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer()); 2118 2119 SessionDescriptionInterface* answer = 2120 CreateRemoteAnswer(offer.get()); 2121 SetLocalDescriptionAnswerExpectError("Called in wrong state: STATE_INIT", 2122 answer); 2123 } 2124 2125 TEST_F(WebRtcSessionTest, TestSetRemoteAnswerWithoutOffer) { 2126 Init(); 2127 SendNothing(); 2128 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer()); 2129 2130 SessionDescriptionInterface* answer = 2131 CreateRemoteAnswer(offer.get()); 2132 SetRemoteDescriptionAnswerExpectError( 2133 "Called in wrong state: STATE_INIT", answer); 2134 } 2135 2136 TEST_F(WebRtcSessionTest, TestAddRemoteCandidate) { 2137 Init(); 2138 SendAudioVideoStream1(); 2139 2140 cricket::Candidate candidate; 2141 candidate.set_component(1); 2142 JsepIceCandidate ice_candidate1(kMediaContentName0, 0, candidate); 2143 2144 // Fail since we have not set a remote description. 2145 EXPECT_FALSE(session_->ProcessIceMessage(&ice_candidate1)); 2146 2147 SessionDescriptionInterface* offer = CreateOffer(); 2148 SetLocalDescriptionWithoutError(offer); 2149 2150 // Fail since we have not set a remote description. 2151 EXPECT_FALSE(session_->ProcessIceMessage(&ice_candidate1)); 2152 2153 SessionDescriptionInterface* answer = CreateRemoteAnswer( 2154 session_->local_description()); 2155 SetRemoteDescriptionWithoutError(answer); 2156 2157 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate1)); 2158 candidate.set_component(2); 2159 JsepIceCandidate ice_candidate2(kMediaContentName0, 0, candidate); 2160 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate2)); 2161 2162 // Verifying the candidates are copied properly from internal vector. 2163 const SessionDescriptionInterface* remote_desc = 2164 session_->remote_description(); 2165 ASSERT_TRUE(remote_desc != NULL); 2166 ASSERT_EQ(2u, remote_desc->number_of_mediasections()); 2167 const IceCandidateCollection* candidates = 2168 remote_desc->candidates(kMediaContentIndex0); 2169 ASSERT_EQ(2u, candidates->count()); 2170 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index()); 2171 EXPECT_EQ(kMediaContentName0, candidates->at(0)->sdp_mid()); 2172 EXPECT_EQ(1, candidates->at(0)->candidate().component()); 2173 EXPECT_EQ(2, candidates->at(1)->candidate().component()); 2174 2175 // |ice_candidate3| is identical to |ice_candidate2|. It can be added 2176 // successfully, but the total count of candidates will not increase. 2177 candidate.set_component(2); 2178 JsepIceCandidate ice_candidate3(kMediaContentName0, 0, candidate); 2179 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate3)); 2180 ASSERT_EQ(2u, candidates->count()); 2181 2182 JsepIceCandidate bad_ice_candidate("bad content name", 99, candidate); 2183 EXPECT_FALSE(session_->ProcessIceMessage(&bad_ice_candidate)); 2184 } 2185 2186 // Test that a remote candidate is added to the remote session description and 2187 // that it is retained if the remote session description is changed. 2188 TEST_F(WebRtcSessionTest, TestRemoteCandidatesAddedToSessionDescription) { 2189 Init(); 2190 cricket::Candidate candidate1; 2191 candidate1.set_component(1); 2192 JsepIceCandidate ice_candidate1(kMediaContentName0, kMediaContentIndex0, 2193 candidate1); 2194 SendAudioVideoStream1(); 2195 CreateAndSetRemoteOfferAndLocalAnswer(); 2196 2197 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate1)); 2198 const SessionDescriptionInterface* remote_desc = 2199 session_->remote_description(); 2200 ASSERT_TRUE(remote_desc != NULL); 2201 ASSERT_EQ(2u, remote_desc->number_of_mediasections()); 2202 const IceCandidateCollection* candidates = 2203 remote_desc->candidates(kMediaContentIndex0); 2204 ASSERT_EQ(1u, candidates->count()); 2205 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index()); 2206 2207 // Update the RemoteSessionDescription with a new session description and 2208 // a candidate and check that the new remote session description contains both 2209 // candidates. 2210 SessionDescriptionInterface* offer = CreateRemoteOffer(); 2211 cricket::Candidate candidate2; 2212 JsepIceCandidate ice_candidate2(kMediaContentName0, kMediaContentIndex0, 2213 candidate2); 2214 EXPECT_TRUE(offer->AddCandidate(&ice_candidate2)); 2215 SetRemoteDescriptionWithoutError(offer); 2216 2217 remote_desc = session_->remote_description(); 2218 ASSERT_TRUE(remote_desc != NULL); 2219 ASSERT_EQ(2u, remote_desc->number_of_mediasections()); 2220 candidates = remote_desc->candidates(kMediaContentIndex0); 2221 ASSERT_EQ(2u, candidates->count()); 2222 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index()); 2223 // Username and password have be updated with the TransportInfo of the 2224 // SessionDescription, won't be equal to the original one. 2225 candidate2.set_username(candidates->at(0)->candidate().username()); 2226 candidate2.set_password(candidates->at(0)->candidate().password()); 2227 EXPECT_TRUE(candidate2.IsEquivalent(candidates->at(0)->candidate())); 2228 EXPECT_EQ(kMediaContentIndex0, candidates->at(1)->sdp_mline_index()); 2229 // No need to verify the username and password. 2230 candidate1.set_username(candidates->at(1)->candidate().username()); 2231 candidate1.set_password(candidates->at(1)->candidate().password()); 2232 EXPECT_TRUE(candidate1.IsEquivalent(candidates->at(1)->candidate())); 2233 2234 // Test that the candidate is ignored if we can add the same candidate again. 2235 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate2)); 2236 } 2237 2238 // Test that local candidates are added to the local session description and 2239 // that they are retained if the local session description is changed. 2240 TEST_F(WebRtcSessionTest, TestLocalCandidatesAddedToSessionDescription) { 2241 AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort)); 2242 Init(); 2243 SendAudioVideoStream1(); 2244 CreateAndSetRemoteOfferAndLocalAnswer(); 2245 2246 const SessionDescriptionInterface* local_desc = session_->local_description(); 2247 const IceCandidateCollection* candidates = 2248 local_desc->candidates(kMediaContentIndex0); 2249 ASSERT_TRUE(candidates != NULL); 2250 EXPECT_EQ(0u, candidates->count()); 2251 2252 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout); 2253 2254 local_desc = session_->local_description(); 2255 candidates = local_desc->candidates(kMediaContentIndex0); 2256 ASSERT_TRUE(candidates != NULL); 2257 EXPECT_LT(0u, candidates->count()); 2258 candidates = local_desc->candidates(1); 2259 ASSERT_TRUE(candidates != NULL); 2260 EXPECT_EQ(0u, candidates->count()); 2261 2262 // Update the session descriptions. 2263 SendAudioVideoStream1(); 2264 CreateAndSetRemoteOfferAndLocalAnswer(); 2265 2266 local_desc = session_->local_description(); 2267 candidates = local_desc->candidates(kMediaContentIndex0); 2268 ASSERT_TRUE(candidates != NULL); 2269 EXPECT_LT(0u, candidates->count()); 2270 candidates = local_desc->candidates(1); 2271 ASSERT_TRUE(candidates != NULL); 2272 EXPECT_EQ(0u, candidates->count()); 2273 } 2274 2275 // Test that we can set a remote session description with remote candidates. 2276 TEST_F(WebRtcSessionTest, TestSetRemoteSessionDescriptionWithCandidates) { 2277 Init(); 2278 2279 cricket::Candidate candidate1; 2280 candidate1.set_component(1); 2281 JsepIceCandidate ice_candidate(kMediaContentName0, kMediaContentIndex0, 2282 candidate1); 2283 SendAudioVideoStream1(); 2284 SessionDescriptionInterface* offer = CreateOffer(); 2285 2286 EXPECT_TRUE(offer->AddCandidate(&ice_candidate)); 2287 SetRemoteDescriptionWithoutError(offer); 2288 2289 const SessionDescriptionInterface* remote_desc = 2290 session_->remote_description(); 2291 ASSERT_TRUE(remote_desc != NULL); 2292 ASSERT_EQ(2u, remote_desc->number_of_mediasections()); 2293 const IceCandidateCollection* candidates = 2294 remote_desc->candidates(kMediaContentIndex0); 2295 ASSERT_EQ(1u, candidates->count()); 2296 EXPECT_EQ(kMediaContentIndex0, candidates->at(0)->sdp_mline_index()); 2297 2298 SessionDescriptionInterface* answer = CreateAnswer(NULL); 2299 SetLocalDescriptionWithoutError(answer); 2300 } 2301 2302 // Test that offers and answers contains ice candidates when Ice candidates have 2303 // been gathered. 2304 TEST_F(WebRtcSessionTest, TestSetLocalAndRemoteDescriptionWithCandidates) { 2305 AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort)); 2306 Init(); 2307 SendAudioVideoStream1(); 2308 // Ice is started but candidates are not provided until SetLocalDescription 2309 // is called. 2310 EXPECT_EQ(0u, observer_.mline_0_candidates_.size()); 2311 EXPECT_EQ(0u, observer_.mline_1_candidates_.size()); 2312 CreateAndSetRemoteOfferAndLocalAnswer(); 2313 // Wait until at least one local candidate has been collected. 2314 EXPECT_TRUE_WAIT(0u < observer_.mline_0_candidates_.size(), 2315 kIceCandidatesTimeout); 2316 2317 rtc::scoped_ptr<SessionDescriptionInterface> local_offer(CreateOffer()); 2318 2319 ASSERT_TRUE(local_offer->candidates(kMediaContentIndex0) != NULL); 2320 EXPECT_LT(0u, local_offer->candidates(kMediaContentIndex0)->count()); 2321 2322 SessionDescriptionInterface* remote_offer(CreateRemoteOffer()); 2323 SetRemoteDescriptionWithoutError(remote_offer); 2324 SessionDescriptionInterface* answer = CreateAnswer(NULL); 2325 ASSERT_TRUE(answer->candidates(kMediaContentIndex0) != NULL); 2326 EXPECT_LT(0u, answer->candidates(kMediaContentIndex0)->count()); 2327 SetLocalDescriptionWithoutError(answer); 2328 } 2329 2330 // Verifies TransportProxy and media channels are created with content names 2331 // present in the SessionDescription. 2332 TEST_F(WebRtcSessionTest, TestChannelCreationsWithContentNames) { 2333 Init(); 2334 SendAudioVideoStream1(); 2335 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer()); 2336 2337 // CreateOffer creates session description with the content names "audio" and 2338 // "video". Goal is to modify these content names and verify transport 2339 // channels 2340 // in the WebRtcSession, as channels are created with the content names 2341 // present in SDP. 2342 std::string sdp; 2343 EXPECT_TRUE(offer->ToString(&sdp)); 2344 const std::string kAudioMid = "a=mid:audio"; 2345 const std::string kAudioMidReplaceStr = "a=mid:audio_content_name"; 2346 const std::string kVideoMid = "a=mid:video"; 2347 const std::string kVideoMidReplaceStr = "a=mid:video_content_name"; 2348 2349 // Replacing |audio| with |audio_content_name|. 2350 rtc::replace_substrs(kAudioMid.c_str(), kAudioMid.length(), 2351 kAudioMidReplaceStr.c_str(), 2352 kAudioMidReplaceStr.length(), 2353 &sdp); 2354 // Replacing |video| with |video_content_name|. 2355 rtc::replace_substrs(kVideoMid.c_str(), kVideoMid.length(), 2356 kVideoMidReplaceStr.c_str(), 2357 kVideoMidReplaceStr.length(), 2358 &sdp); 2359 2360 SessionDescriptionInterface* modified_offer = 2361 CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL); 2362 2363 SetRemoteDescriptionWithoutError(modified_offer); 2364 2365 SessionDescriptionInterface* answer = 2366 CreateAnswer(NULL); 2367 SetLocalDescriptionWithoutError(answer); 2368 2369 cricket::TransportChannel* voice_transport_channel = 2370 session_->voice_rtp_transport_channel(); 2371 EXPECT_TRUE(voice_transport_channel != NULL); 2372 EXPECT_EQ(voice_transport_channel->transport_name(), "audio_content_name"); 2373 cricket::TransportChannel* video_transport_channel = 2374 session_->video_rtp_transport_channel(); 2375 EXPECT_TRUE(video_transport_channel != NULL); 2376 EXPECT_EQ(video_transport_channel->transport_name(), "video_content_name"); 2377 EXPECT_TRUE((video_channel_ = media_engine_->GetVideoChannel(0)) != NULL); 2378 EXPECT_TRUE((voice_channel_ = media_engine_->GetVoiceChannel(0)) != NULL); 2379 } 2380 2381 // Test that an offer contains the correct media content descriptions based on 2382 // the send streams when no constraints have been set. 2383 TEST_F(WebRtcSessionTest, CreateOfferWithoutConstraintsOrStreams) { 2384 Init(); 2385 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer()); 2386 2387 ASSERT_TRUE(offer != NULL); 2388 const cricket::ContentInfo* content = 2389 cricket::GetFirstAudioContent(offer->description()); 2390 EXPECT_TRUE(content != NULL); 2391 content = cricket::GetFirstVideoContent(offer->description()); 2392 EXPECT_TRUE(content == NULL); 2393 } 2394 2395 // Test that an offer contains the correct media content descriptions based on 2396 // the send streams when no constraints have been set. 2397 TEST_F(WebRtcSessionTest, CreateOfferWithoutConstraints) { 2398 Init(); 2399 // Test Audio only offer. 2400 SendAudioOnlyStream2(); 2401 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer()); 2402 2403 const cricket::ContentInfo* content = 2404 cricket::GetFirstAudioContent(offer->description()); 2405 EXPECT_TRUE(content != NULL); 2406 content = cricket::GetFirstVideoContent(offer->description()); 2407 EXPECT_TRUE(content == NULL); 2408 2409 // Test Audio / Video offer. 2410 SendAudioVideoStream1(); 2411 offer.reset(CreateOffer()); 2412 content = cricket::GetFirstAudioContent(offer->description()); 2413 EXPECT_TRUE(content != NULL); 2414 content = cricket::GetFirstVideoContent(offer->description()); 2415 EXPECT_TRUE(content != NULL); 2416 } 2417 2418 // Test that an offer contains no media content descriptions if 2419 // kOfferToReceiveVideo and kOfferToReceiveAudio constraints are set to false. 2420 TEST_F(WebRtcSessionTest, CreateOfferWithConstraintsWithoutStreams) { 2421 Init(); 2422 PeerConnectionInterface::RTCOfferAnswerOptions options; 2423 options.offer_to_receive_audio = 0; 2424 options.offer_to_receive_video = 0; 2425 2426 rtc::scoped_ptr<SessionDescriptionInterface> offer( 2427 CreateOffer(options)); 2428 2429 ASSERT_TRUE(offer != NULL); 2430 const cricket::ContentInfo* content = 2431 cricket::GetFirstAudioContent(offer->description()); 2432 EXPECT_TRUE(content == NULL); 2433 content = cricket::GetFirstVideoContent(offer->description()); 2434 EXPECT_TRUE(content == NULL); 2435 } 2436 2437 // Test that an offer contains only audio media content descriptions if 2438 // kOfferToReceiveAudio constraints are set to true. 2439 TEST_F(WebRtcSessionTest, CreateAudioOnlyOfferWithConstraints) { 2440 Init(); 2441 PeerConnectionInterface::RTCOfferAnswerOptions options; 2442 options.offer_to_receive_audio = 2443 RTCOfferAnswerOptions::kOfferToReceiveMediaTrue; 2444 2445 rtc::scoped_ptr<SessionDescriptionInterface> offer( 2446 CreateOffer(options)); 2447 2448 const cricket::ContentInfo* content = 2449 cricket::GetFirstAudioContent(offer->description()); 2450 EXPECT_TRUE(content != NULL); 2451 content = cricket::GetFirstVideoContent(offer->description()); 2452 EXPECT_TRUE(content == NULL); 2453 } 2454 2455 // Test that an offer contains audio and video media content descriptions if 2456 // kOfferToReceiveAudio and kOfferToReceiveVideo constraints are set to true. 2457 TEST_F(WebRtcSessionTest, CreateOfferWithConstraints) { 2458 Init(); 2459 // Test Audio / Video offer. 2460 PeerConnectionInterface::RTCOfferAnswerOptions options; 2461 options.offer_to_receive_audio = 2462 RTCOfferAnswerOptions::kOfferToReceiveMediaTrue; 2463 options.offer_to_receive_video = 2464 RTCOfferAnswerOptions::kOfferToReceiveMediaTrue; 2465 2466 rtc::scoped_ptr<SessionDescriptionInterface> offer( 2467 CreateOffer(options)); 2468 2469 const cricket::ContentInfo* content = 2470 cricket::GetFirstAudioContent(offer->description()); 2471 EXPECT_TRUE(content != NULL); 2472 2473 content = cricket::GetFirstVideoContent(offer->description()); 2474 EXPECT_TRUE(content != NULL); 2475 2476 // Sets constraints to false and verifies that audio/video contents are 2477 // removed. 2478 options.offer_to_receive_audio = 0; 2479 options.offer_to_receive_video = 0; 2480 offer.reset(CreateOffer(options)); 2481 2482 content = cricket::GetFirstAudioContent(offer->description()); 2483 EXPECT_TRUE(content == NULL); 2484 content = cricket::GetFirstVideoContent(offer->description()); 2485 EXPECT_TRUE(content == NULL); 2486 } 2487 2488 // Test that an answer can not be created if the last remote description is not 2489 // an offer. 2490 TEST_F(WebRtcSessionTest, CreateAnswerWithoutAnOffer) { 2491 Init(); 2492 SessionDescriptionInterface* offer = CreateOffer(); 2493 SetLocalDescriptionWithoutError(offer); 2494 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer); 2495 SetRemoteDescriptionWithoutError(answer); 2496 EXPECT_TRUE(CreateAnswer(NULL) == NULL); 2497 } 2498 2499 // Test that an answer contains the correct media content descriptions when no 2500 // constraints have been set. 2501 TEST_F(WebRtcSessionTest, CreateAnswerWithoutConstraintsOrStreams) { 2502 Init(); 2503 // Create a remote offer with audio and video content. 2504 rtc::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer()); 2505 SetRemoteDescriptionWithoutError(offer.release()); 2506 rtc::scoped_ptr<SessionDescriptionInterface> answer( 2507 CreateAnswer(NULL)); 2508 const cricket::ContentInfo* content = 2509 cricket::GetFirstAudioContent(answer->description()); 2510 ASSERT_TRUE(content != NULL); 2511 EXPECT_FALSE(content->rejected); 2512 2513 content = cricket::GetFirstVideoContent(answer->description()); 2514 ASSERT_TRUE(content != NULL); 2515 EXPECT_FALSE(content->rejected); 2516 } 2517 2518 // Test that an answer contains the correct media content descriptions when no 2519 // constraints have been set and the offer only contain audio. 2520 TEST_F(WebRtcSessionTest, CreateAudioAnswerWithoutConstraintsOrStreams) { 2521 Init(); 2522 // Create a remote offer with audio only. 2523 cricket::MediaSessionOptions options; 2524 2525 rtc::scoped_ptr<JsepSessionDescription> offer( 2526 CreateRemoteOffer(options)); 2527 ASSERT_TRUE(cricket::GetFirstVideoContent(offer->description()) == NULL); 2528 ASSERT_TRUE(cricket::GetFirstAudioContent(offer->description()) != NULL); 2529 2530 SetRemoteDescriptionWithoutError(offer.release()); 2531 rtc::scoped_ptr<SessionDescriptionInterface> answer( 2532 CreateAnswer(NULL)); 2533 const cricket::ContentInfo* content = 2534 cricket::GetFirstAudioContent(answer->description()); 2535 ASSERT_TRUE(content != NULL); 2536 EXPECT_FALSE(content->rejected); 2537 2538 EXPECT_TRUE(cricket::GetFirstVideoContent(answer->description()) == NULL); 2539 } 2540 2541 // Test that an answer contains the correct media content descriptions when no 2542 // constraints have been set. 2543 TEST_F(WebRtcSessionTest, CreateAnswerWithoutConstraints) { 2544 Init(); 2545 // Create a remote offer with audio and video content. 2546 rtc::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer()); 2547 SetRemoteDescriptionWithoutError(offer.release()); 2548 // Test with a stream with tracks. 2549 SendAudioVideoStream1(); 2550 rtc::scoped_ptr<SessionDescriptionInterface> answer( 2551 CreateAnswer(NULL)); 2552 const cricket::ContentInfo* content = 2553 cricket::GetFirstAudioContent(answer->description()); 2554 ASSERT_TRUE(content != NULL); 2555 EXPECT_FALSE(content->rejected); 2556 2557 content = cricket::GetFirstVideoContent(answer->description()); 2558 ASSERT_TRUE(content != NULL); 2559 EXPECT_FALSE(content->rejected); 2560 } 2561 2562 // Test that an answer contains the correct media content descriptions when 2563 // constraints have been set but no stream is sent. 2564 TEST_F(WebRtcSessionTest, CreateAnswerWithConstraintsWithoutStreams) { 2565 Init(); 2566 // Create a remote offer with audio and video content. 2567 rtc::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer()); 2568 SetRemoteDescriptionWithoutError(offer.release()); 2569 2570 webrtc::FakeConstraints constraints_no_receive; 2571 constraints_no_receive.SetMandatoryReceiveAudio(false); 2572 constraints_no_receive.SetMandatoryReceiveVideo(false); 2573 2574 rtc::scoped_ptr<SessionDescriptionInterface> answer( 2575 CreateAnswer(&constraints_no_receive)); 2576 const cricket::ContentInfo* content = 2577 cricket::GetFirstAudioContent(answer->description()); 2578 ASSERT_TRUE(content != NULL); 2579 EXPECT_TRUE(content->rejected); 2580 2581 content = cricket::GetFirstVideoContent(answer->description()); 2582 ASSERT_TRUE(content != NULL); 2583 EXPECT_TRUE(content->rejected); 2584 } 2585 2586 // Test that an answer contains the correct media content descriptions when 2587 // constraints have been set and streams are sent. 2588 TEST_F(WebRtcSessionTest, CreateAnswerWithConstraints) { 2589 Init(); 2590 // Create a remote offer with audio and video content. 2591 rtc::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer()); 2592 SetRemoteDescriptionWithoutError(offer.release()); 2593 2594 webrtc::FakeConstraints constraints_no_receive; 2595 constraints_no_receive.SetMandatoryReceiveAudio(false); 2596 constraints_no_receive.SetMandatoryReceiveVideo(false); 2597 2598 // Test with a stream with tracks. 2599 SendAudioVideoStream1(); 2600 rtc::scoped_ptr<SessionDescriptionInterface> answer( 2601 CreateAnswer(&constraints_no_receive)); 2602 2603 // TODO(perkj): Should the direction be set to SEND_ONLY? 2604 const cricket::ContentInfo* content = 2605 cricket::GetFirstAudioContent(answer->description()); 2606 ASSERT_TRUE(content != NULL); 2607 EXPECT_FALSE(content->rejected); 2608 2609 // TODO(perkj): Should the direction be set to SEND_ONLY? 2610 content = cricket::GetFirstVideoContent(answer->description()); 2611 ASSERT_TRUE(content != NULL); 2612 EXPECT_FALSE(content->rejected); 2613 } 2614 2615 TEST_F(WebRtcSessionTest, CreateOfferWithoutCNCodecs) { 2616 AddCNCodecs(); 2617 Init(); 2618 PeerConnectionInterface::RTCOfferAnswerOptions options; 2619 options.offer_to_receive_audio = 2620 RTCOfferAnswerOptions::kOfferToReceiveMediaTrue; 2621 options.voice_activity_detection = false; 2622 2623 rtc::scoped_ptr<SessionDescriptionInterface> offer( 2624 CreateOffer(options)); 2625 2626 const cricket::ContentInfo* content = 2627 cricket::GetFirstAudioContent(offer->description()); 2628 EXPECT_TRUE(content != NULL); 2629 EXPECT_TRUE(VerifyNoCNCodecs(content)); 2630 } 2631 2632 TEST_F(WebRtcSessionTest, CreateAnswerWithoutCNCodecs) { 2633 AddCNCodecs(); 2634 Init(); 2635 // Create a remote offer with audio and video content. 2636 rtc::scoped_ptr<JsepSessionDescription> offer(CreateRemoteOffer()); 2637 SetRemoteDescriptionWithoutError(offer.release()); 2638 2639 webrtc::FakeConstraints constraints; 2640 constraints.SetOptionalVAD(false); 2641 rtc::scoped_ptr<SessionDescriptionInterface> answer( 2642 CreateAnswer(&constraints)); 2643 const cricket::ContentInfo* content = 2644 cricket::GetFirstAudioContent(answer->description()); 2645 ASSERT_TRUE(content != NULL); 2646 EXPECT_TRUE(VerifyNoCNCodecs(content)); 2647 } 2648 2649 // This test verifies the call setup when remote answer with audio only and 2650 // later updates with video. 2651 TEST_F(WebRtcSessionTest, TestAVOfferWithAudioOnlyAnswer) { 2652 Init(); 2653 EXPECT_TRUE(media_engine_->GetVideoChannel(0) == NULL); 2654 EXPECT_TRUE(media_engine_->GetVoiceChannel(0) == NULL); 2655 2656 SendAudioVideoStream1(); 2657 SessionDescriptionInterface* offer = CreateOffer(); 2658 2659 cricket::MediaSessionOptions options; 2660 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer, options); 2661 2662 // SetLocalDescription and SetRemoteDescriptions takes ownership of offer 2663 // and answer; 2664 SetLocalDescriptionWithoutError(offer); 2665 SetRemoteDescriptionWithoutError(answer); 2666 2667 video_channel_ = media_engine_->GetVideoChannel(0); 2668 voice_channel_ = media_engine_->GetVoiceChannel(0); 2669 2670 ASSERT_TRUE(video_channel_ == NULL); 2671 2672 ASSERT_EQ(0u, voice_channel_->recv_streams().size()); 2673 ASSERT_EQ(1u, voice_channel_->send_streams().size()); 2674 EXPECT_EQ(kAudioTrack1, voice_channel_->send_streams()[0].id); 2675 2676 // Let the remote end update the session descriptions, with Audio and Video. 2677 SendAudioVideoStream2(); 2678 CreateAndSetRemoteOfferAndLocalAnswer(); 2679 2680 video_channel_ = media_engine_->GetVideoChannel(0); 2681 voice_channel_ = media_engine_->GetVoiceChannel(0); 2682 2683 ASSERT_TRUE(video_channel_ != NULL); 2684 ASSERT_TRUE(voice_channel_ != NULL); 2685 2686 ASSERT_EQ(1u, video_channel_->recv_streams().size()); 2687 ASSERT_EQ(1u, video_channel_->send_streams().size()); 2688 EXPECT_EQ(kVideoTrack2, video_channel_->recv_streams()[0].id); 2689 EXPECT_EQ(kVideoTrack2, video_channel_->send_streams()[0].id); 2690 ASSERT_EQ(1u, voice_channel_->recv_streams().size()); 2691 ASSERT_EQ(1u, voice_channel_->send_streams().size()); 2692 EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id); 2693 EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id); 2694 2695 // Change session back to audio only. 2696 SendAudioOnlyStream2(); 2697 CreateAndSetRemoteOfferAndLocalAnswer(); 2698 2699 EXPECT_EQ(0u, video_channel_->recv_streams().size()); 2700 ASSERT_EQ(1u, voice_channel_->recv_streams().size()); 2701 EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id); 2702 ASSERT_EQ(1u, voice_channel_->send_streams().size()); 2703 EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id); 2704 } 2705 2706 // This test verifies the call setup when remote answer with video only and 2707 // later updates with audio. 2708 TEST_F(WebRtcSessionTest, TestAVOfferWithVideoOnlyAnswer) { 2709 Init(); 2710 EXPECT_TRUE(media_engine_->GetVideoChannel(0) == NULL); 2711 EXPECT_TRUE(media_engine_->GetVoiceChannel(0) == NULL); 2712 SendAudioVideoStream1(); 2713 SessionDescriptionInterface* offer = CreateOffer(); 2714 2715 cricket::MediaSessionOptions options; 2716 options.recv_audio = false; 2717 options.recv_video = true; 2718 SessionDescriptionInterface* answer = CreateRemoteAnswer( 2719 offer, options, cricket::SEC_ENABLED); 2720 2721 // SetLocalDescription and SetRemoteDescriptions takes ownership of offer 2722 // and answer. 2723 SetLocalDescriptionWithoutError(offer); 2724 SetRemoteDescriptionWithoutError(answer); 2725 2726 video_channel_ = media_engine_->GetVideoChannel(0); 2727 voice_channel_ = media_engine_->GetVoiceChannel(0); 2728 2729 ASSERT_TRUE(voice_channel_ == NULL); 2730 ASSERT_TRUE(video_channel_ != NULL); 2731 2732 EXPECT_EQ(0u, video_channel_->recv_streams().size()); 2733 ASSERT_EQ(1u, video_channel_->send_streams().size()); 2734 EXPECT_EQ(kVideoTrack1, video_channel_->send_streams()[0].id); 2735 2736 // Update the session descriptions, with Audio and Video. 2737 SendAudioVideoStream2(); 2738 CreateAndSetRemoteOfferAndLocalAnswer(); 2739 2740 voice_channel_ = media_engine_->GetVoiceChannel(0); 2741 ASSERT_TRUE(voice_channel_ != NULL); 2742 2743 ASSERT_EQ(1u, voice_channel_->recv_streams().size()); 2744 ASSERT_EQ(1u, voice_channel_->send_streams().size()); 2745 EXPECT_EQ(kAudioTrack2, voice_channel_->recv_streams()[0].id); 2746 EXPECT_EQ(kAudioTrack2, voice_channel_->send_streams()[0].id); 2747 2748 // Change session back to video only. 2749 SendVideoOnlyStream2(); 2750 CreateAndSetRemoteOfferAndLocalAnswer(); 2751 2752 video_channel_ = media_engine_->GetVideoChannel(0); 2753 voice_channel_ = media_engine_->GetVoiceChannel(0); 2754 2755 ASSERT_EQ(1u, video_channel_->recv_streams().size()); 2756 EXPECT_EQ(kVideoTrack2, video_channel_->recv_streams()[0].id); 2757 ASSERT_EQ(1u, video_channel_->send_streams().size()); 2758 EXPECT_EQ(kVideoTrack2, video_channel_->send_streams()[0].id); 2759 } 2760 2761 TEST_F(WebRtcSessionTest, VerifyCryptoParamsInSDP) { 2762 Init(); 2763 SendAudioVideoStream1(); 2764 scoped_ptr<SessionDescriptionInterface> offer(CreateOffer()); 2765 VerifyCryptoParams(offer->description()); 2766 SetRemoteDescriptionWithoutError(offer.release()); 2767 scoped_ptr<SessionDescriptionInterface> answer(CreateAnswer(NULL)); 2768 VerifyCryptoParams(answer->description()); 2769 } 2770 2771 TEST_F(WebRtcSessionTest, VerifyNoCryptoParamsInSDP) { 2772 options_.disable_encryption = true; 2773 Init(); 2774 SendAudioVideoStream1(); 2775 scoped_ptr<SessionDescriptionInterface> offer(CreateOffer()); 2776 VerifyNoCryptoParams(offer->description(), false); 2777 } 2778 2779 TEST_F(WebRtcSessionTest, VerifyAnswerFromNonCryptoOffer) { 2780 Init(); 2781 VerifyAnswerFromNonCryptoOffer(); 2782 } 2783 2784 TEST_F(WebRtcSessionTest, VerifyAnswerFromCryptoOffer) { 2785 Init(); 2786 VerifyAnswerFromCryptoOffer(); 2787 } 2788 2789 // This test verifies that setLocalDescription fails if 2790 // no a=ice-ufrag and a=ice-pwd lines are present in the SDP. 2791 TEST_F(WebRtcSessionTest, TestSetLocalDescriptionWithoutIce) { 2792 Init(); 2793 SendAudioVideoStream1(); 2794 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer()); 2795 2796 std::string sdp; 2797 RemoveIceUfragPwdLines(offer.get(), &sdp); 2798 SessionDescriptionInterface* modified_offer = 2799 CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL); 2800 SetLocalDescriptionOfferExpectError(kSdpWithoutIceUfragPwd, modified_offer); 2801 } 2802 2803 // This test verifies that setRemoteDescription fails if 2804 // no a=ice-ufrag and a=ice-pwd lines are present in the SDP. 2805 TEST_F(WebRtcSessionTest, TestSetRemoteDescriptionWithoutIce) { 2806 Init(); 2807 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateRemoteOffer()); 2808 std::string sdp; 2809 RemoveIceUfragPwdLines(offer.get(), &sdp); 2810 SessionDescriptionInterface* modified_offer = 2811 CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL); 2812 SetRemoteDescriptionOfferExpectError(kSdpWithoutIceUfragPwd, modified_offer); 2813 } 2814 2815 // This test verifies that setLocalDescription fails if local offer has 2816 // too short ice ufrag and pwd strings. 2817 TEST_F(WebRtcSessionTest, TestSetLocalDescriptionInvalidIceCredentials) { 2818 Init(); 2819 SendAudioVideoStream1(); 2820 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer()); 2821 2822 std::string sdp; 2823 // Modifying ice ufrag and pwd in local offer with strings smaller than the 2824 // recommended values of 4 and 22 bytes respectively. 2825 ModifyIceUfragPwdLines(offer.get(), "ice", "icepwd", &sdp); 2826 SessionDescriptionInterface* modified_offer = 2827 CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL); 2828 std::string error; 2829 EXPECT_FALSE(session_->SetLocalDescription(modified_offer, &error)); 2830 2831 // Test with string greater than 256. 2832 sdp.clear(); 2833 ModifyIceUfragPwdLines(offer.get(), kTooLongIceUfragPwd, kTooLongIceUfragPwd, 2834 &sdp); 2835 modified_offer = CreateSessionDescription(JsepSessionDescription::kOffer, sdp, 2836 NULL); 2837 EXPECT_FALSE(session_->SetLocalDescription(modified_offer, &error)); 2838 } 2839 2840 // This test verifies that setRemoteDescription fails if remote offer has 2841 // too short ice ufrag and pwd strings. 2842 TEST_F(WebRtcSessionTest, TestSetRemoteDescriptionInvalidIceCredentials) { 2843 Init(); 2844 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateRemoteOffer()); 2845 std::string sdp; 2846 // Modifying ice ufrag and pwd in remote offer with strings smaller than the 2847 // recommended values of 4 and 22 bytes respectively. 2848 ModifyIceUfragPwdLines(offer.get(), "ice", "icepwd", &sdp); 2849 SessionDescriptionInterface* modified_offer = 2850 CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL); 2851 std::string error; 2852 EXPECT_FALSE(session_->SetRemoteDescription(modified_offer, &error)); 2853 2854 sdp.clear(); 2855 ModifyIceUfragPwdLines(offer.get(), kTooLongIceUfragPwd, kTooLongIceUfragPwd, 2856 &sdp); 2857 modified_offer = CreateSessionDescription(JsepSessionDescription::kOffer, sdp, 2858 NULL); 2859 EXPECT_FALSE(session_->SetRemoteDescription(modified_offer, &error)); 2860 } 2861 2862 // Test that if the remote offer indicates the peer requested ICE restart (via 2863 // a new ufrag or pwd), the old ICE candidates are not copied, and vice versa. 2864 TEST_F(WebRtcSessionTest, TestSetRemoteOfferWithIceRestart) { 2865 Init(); 2866 scoped_ptr<SessionDescriptionInterface> offer(CreateRemoteOffer()); 2867 2868 // Create the first offer. 2869 std::string sdp; 2870 ModifyIceUfragPwdLines(offer.get(), "0123456789012345", 2871 "abcdefghijklmnopqrstuvwx", &sdp); 2872 SessionDescriptionInterface* offer1 = 2873 CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL); 2874 cricket::Candidate candidate1(1, "udp", rtc::SocketAddress("1.1.1.1", 5000), 2875 0, "", "", "relay", 0, ""); 2876 JsepIceCandidate ice_candidate1(kMediaContentName0, kMediaContentIndex0, 2877 candidate1); 2878 EXPECT_TRUE(offer1->AddCandidate(&ice_candidate1)); 2879 SetRemoteDescriptionWithoutError(offer1); 2880 EXPECT_EQ(1, session_->remote_description()->candidates(0)->count()); 2881 2882 // The second offer has the same ufrag and pwd but different address. 2883 sdp.clear(); 2884 ModifyIceUfragPwdLines(offer.get(), "0123456789012345", 2885 "abcdefghijklmnopqrstuvwx", &sdp); 2886 SessionDescriptionInterface* offer2 = 2887 CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL); 2888 candidate1.set_address(rtc::SocketAddress("1.1.1.1", 6000)); 2889 JsepIceCandidate ice_candidate2(kMediaContentName0, kMediaContentIndex0, 2890 candidate1); 2891 EXPECT_TRUE(offer2->AddCandidate(&ice_candidate2)); 2892 SetRemoteDescriptionWithoutError(offer2); 2893 EXPECT_EQ(2, session_->remote_description()->candidates(0)->count()); 2894 2895 // The third offer has a different ufrag and different address. 2896 sdp.clear(); 2897 ModifyIceUfragPwdLines(offer.get(), "0123456789012333", 2898 "abcdefghijklmnopqrstuvwx", &sdp); 2899 SessionDescriptionInterface* offer3 = 2900 CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL); 2901 candidate1.set_address(rtc::SocketAddress("1.1.1.1", 7000)); 2902 JsepIceCandidate ice_candidate3(kMediaContentName0, kMediaContentIndex0, 2903 candidate1); 2904 EXPECT_TRUE(offer3->AddCandidate(&ice_candidate3)); 2905 SetRemoteDescriptionWithoutError(offer3); 2906 EXPECT_EQ(1, session_->remote_description()->candidates(0)->count()); 2907 2908 // The fourth offer has no candidate but a different ufrag/pwd. 2909 sdp.clear(); 2910 ModifyIceUfragPwdLines(offer.get(), "0123456789012444", 2911 "abcdefghijklmnopqrstuvyz", &sdp); 2912 SessionDescriptionInterface* offer4 = 2913 CreateSessionDescription(JsepSessionDescription::kOffer, sdp, NULL); 2914 SetRemoteDescriptionWithoutError(offer4); 2915 EXPECT_EQ(0, session_->remote_description()->candidates(0)->count()); 2916 } 2917 2918 // Test that if the remote answer indicates the peer requested ICE restart (via 2919 // a new ufrag or pwd), the old ICE candidates are not copied, and vice versa. 2920 TEST_F(WebRtcSessionTest, TestSetRemoteAnswerWithIceRestart) { 2921 Init(); 2922 SessionDescriptionInterface* offer = CreateOffer(); 2923 SetLocalDescriptionWithoutError(offer); 2924 scoped_ptr<SessionDescriptionInterface> answer(CreateRemoteAnswer(offer)); 2925 2926 // Create the first answer. 2927 std::string sdp; 2928 ModifyIceUfragPwdLines(answer.get(), "0123456789012345", 2929 "abcdefghijklmnopqrstuvwx", &sdp); 2930 SessionDescriptionInterface* answer1 = 2931 CreateSessionDescription(JsepSessionDescription::kPrAnswer, sdp, NULL); 2932 cricket::Candidate candidate1(1, "udp", rtc::SocketAddress("1.1.1.1", 5000), 2933 0, "", "", "relay", 0, ""); 2934 JsepIceCandidate ice_candidate1(kMediaContentName0, kMediaContentIndex0, 2935 candidate1); 2936 EXPECT_TRUE(answer1->AddCandidate(&ice_candidate1)); 2937 SetRemoteDescriptionWithoutError(answer1); 2938 EXPECT_EQ(1, session_->remote_description()->candidates(0)->count()); 2939 2940 // The second answer has the same ufrag and pwd but different address. 2941 sdp.clear(); 2942 ModifyIceUfragPwdLines(answer.get(), "0123456789012345", 2943 "abcdefghijklmnopqrstuvwx", &sdp); 2944 SessionDescriptionInterface* answer2 = 2945 CreateSessionDescription(JsepSessionDescription::kPrAnswer, sdp, NULL); 2946 candidate1.set_address(rtc::SocketAddress("1.1.1.1", 6000)); 2947 JsepIceCandidate ice_candidate2(kMediaContentName0, kMediaContentIndex0, 2948 candidate1); 2949 EXPECT_TRUE(answer2->AddCandidate(&ice_candidate2)); 2950 SetRemoteDescriptionWithoutError(answer2); 2951 EXPECT_EQ(2, session_->remote_description()->candidates(0)->count()); 2952 2953 // The third answer has a different ufrag and different address. 2954 sdp.clear(); 2955 ModifyIceUfragPwdLines(answer.get(), "0123456789012333", 2956 "abcdefghijklmnopqrstuvwx", &sdp); 2957 SessionDescriptionInterface* answer3 = 2958 CreateSessionDescription(JsepSessionDescription::kPrAnswer, sdp, NULL); 2959 candidate1.set_address(rtc::SocketAddress("1.1.1.1", 7000)); 2960 JsepIceCandidate ice_candidate3(kMediaContentName0, kMediaContentIndex0, 2961 candidate1); 2962 EXPECT_TRUE(answer3->AddCandidate(&ice_candidate3)); 2963 SetRemoteDescriptionWithoutError(answer3); 2964 EXPECT_EQ(1, session_->remote_description()->candidates(0)->count()); 2965 2966 // The fourth answer has no candidate but a different ufrag/pwd. 2967 sdp.clear(); 2968 ModifyIceUfragPwdLines(answer.get(), "0123456789012444", 2969 "abcdefghijklmnopqrstuvyz", &sdp); 2970 SessionDescriptionInterface* offer4 = 2971 CreateSessionDescription(JsepSessionDescription::kPrAnswer, sdp, NULL); 2972 SetRemoteDescriptionWithoutError(offer4); 2973 EXPECT_EQ(0, session_->remote_description()->candidates(0)->count()); 2974 } 2975 2976 // Test that candidates sent to the "video" transport do not get pushed down to 2977 // the "audio" transport channel when bundling. 2978 TEST_F(WebRtcSessionTest, TestIgnoreCandidatesForUnusedTransportWhenBundling) { 2979 AddInterface(rtc::SocketAddress(kClientAddrHost1, kClientAddrPort)); 2980 2981 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyBalanced); 2982 SendAudioVideoStream1(); 2983 2984 PeerConnectionInterface::RTCOfferAnswerOptions options; 2985 options.use_rtp_mux = true; 2986 2987 SessionDescriptionInterface* offer = CreateRemoteOffer(); 2988 SetRemoteDescriptionWithoutError(offer); 2989 2990 SessionDescriptionInterface* answer = CreateAnswer(NULL); 2991 SetLocalDescriptionWithoutError(answer); 2992 2993 EXPECT_EQ(session_->voice_rtp_transport_channel(), 2994 session_->video_rtp_transport_channel()); 2995 2996 cricket::BaseChannel* voice_channel = session_->voice_channel(); 2997 ASSERT(voice_channel != NULL); 2998 2999 // Checks if one of the transport channels contains a connection using a given 3000 // port. 3001 auto connection_with_remote_port = [this, voice_channel](int port) { 3002 SessionStats stats; 3003 session_->GetChannelTransportStats(voice_channel, &stats); 3004 for (auto& kv : stats.transport_stats) { 3005 for (auto& chan_stat : kv.second.channel_stats) { 3006 for (auto& conn_info : chan_stat.connection_infos) { 3007 if (conn_info.remote_candidate.address().port() == port) { 3008 return true; 3009 } 3010 } 3011 } 3012 } 3013 return false; 3014 }; 3015 3016 EXPECT_FALSE(connection_with_remote_port(5000)); 3017 EXPECT_FALSE(connection_with_remote_port(5001)); 3018 EXPECT_FALSE(connection_with_remote_port(6000)); 3019 3020 // The way the *_WAIT checks work is they only wait if the condition fails, 3021 // which does not help in the case where state is not changing. This is 3022 // problematic in this test since we want to verify that adding a video 3023 // candidate does _not_ change state. So we interleave candidates and assume 3024 // that messages are executed in the order they were posted. 3025 3026 // First audio candidate. 3027 cricket::Candidate candidate0; 3028 candidate0.set_address(rtc::SocketAddress("1.1.1.1", 5000)); 3029 candidate0.set_component(1); 3030 candidate0.set_protocol("udp"); 3031 JsepIceCandidate ice_candidate0(kMediaContentName0, kMediaContentIndex0, 3032 candidate0); 3033 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate0)); 3034 3035 // Video candidate. 3036 cricket::Candidate candidate1; 3037 candidate1.set_address(rtc::SocketAddress("1.1.1.1", 6000)); 3038 candidate1.set_component(1); 3039 candidate1.set_protocol("udp"); 3040 JsepIceCandidate ice_candidate1(kMediaContentName1, kMediaContentIndex1, 3041 candidate1); 3042 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate1)); 3043 3044 // Second audio candidate. 3045 cricket::Candidate candidate2; 3046 candidate2.set_address(rtc::SocketAddress("1.1.1.1", 5001)); 3047 candidate2.set_component(1); 3048 candidate2.set_protocol("udp"); 3049 JsepIceCandidate ice_candidate2(kMediaContentName0, kMediaContentIndex0, 3050 candidate2); 3051 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate2)); 3052 3053 EXPECT_TRUE_WAIT(connection_with_remote_port(5000), 1000); 3054 EXPECT_TRUE_WAIT(connection_with_remote_port(5001), 1000); 3055 3056 // No need here for a _WAIT check since we are checking that state hasn't 3057 // changed: if this is false we would be doing waits for nothing and if this 3058 // is true then there will be no messages processed anyways. 3059 EXPECT_FALSE(connection_with_remote_port(6000)); 3060 } 3061 3062 // kBundlePolicyBalanced BUNDLE policy and answer contains BUNDLE. 3063 TEST_F(WebRtcSessionTest, TestBalancedBundleInAnswer) { 3064 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyBalanced); 3065 SendAudioVideoStream1(); 3066 3067 PeerConnectionInterface::RTCOfferAnswerOptions options; 3068 options.use_rtp_mux = true; 3069 3070 SessionDescriptionInterface* offer = CreateOffer(options); 3071 SetLocalDescriptionWithoutError(offer); 3072 3073 EXPECT_NE(session_->voice_rtp_transport_channel(), 3074 session_->video_rtp_transport_channel()); 3075 3076 SendAudioVideoStream2(); 3077 SessionDescriptionInterface* answer = 3078 CreateRemoteAnswer(session_->local_description()); 3079 SetRemoteDescriptionWithoutError(answer); 3080 3081 EXPECT_EQ(session_->voice_rtp_transport_channel(), 3082 session_->video_rtp_transport_channel()); 3083 } 3084 3085 // kBundlePolicyBalanced BUNDLE policy but no BUNDLE in the answer. 3086 TEST_F(WebRtcSessionTest, TestBalancedNoBundleInAnswer) { 3087 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyBalanced); 3088 SendAudioVideoStream1(); 3089 3090 PeerConnectionInterface::RTCOfferAnswerOptions options; 3091 options.use_rtp_mux = true; 3092 3093 SessionDescriptionInterface* offer = CreateOffer(options); 3094 SetLocalDescriptionWithoutError(offer); 3095 3096 EXPECT_NE(session_->voice_rtp_transport_channel(), 3097 session_->video_rtp_transport_channel()); 3098 3099 SendAudioVideoStream2(); 3100 3101 // Remove BUNDLE from the answer. 3102 rtc::scoped_ptr<SessionDescriptionInterface> answer( 3103 CreateRemoteAnswer(session_->local_description())); 3104 cricket::SessionDescription* answer_copy = answer->description()->Copy(); 3105 answer_copy->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE); 3106 JsepSessionDescription* modified_answer = 3107 new JsepSessionDescription(JsepSessionDescription::kAnswer); 3108 modified_answer->Initialize(answer_copy, "1", "1"); 3109 SetRemoteDescriptionWithoutError(modified_answer); // 3110 3111 EXPECT_NE(session_->voice_rtp_transport_channel(), 3112 session_->video_rtp_transport_channel()); 3113 } 3114 3115 // kBundlePolicyMaxBundle policy with BUNDLE in the answer. 3116 TEST_F(WebRtcSessionTest, TestMaxBundleBundleInAnswer) { 3117 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyMaxBundle); 3118 SendAudioVideoStream1(); 3119 3120 PeerConnectionInterface::RTCOfferAnswerOptions options; 3121 options.use_rtp_mux = true; 3122 3123 SessionDescriptionInterface* offer = CreateOffer(options); 3124 SetLocalDescriptionWithoutError(offer); 3125 3126 EXPECT_EQ(session_->voice_rtp_transport_channel(), 3127 session_->video_rtp_transport_channel()); 3128 3129 SendAudioVideoStream2(); 3130 SessionDescriptionInterface* answer = 3131 CreateRemoteAnswer(session_->local_description()); 3132 SetRemoteDescriptionWithoutError(answer); 3133 3134 EXPECT_EQ(session_->voice_rtp_transport_channel(), 3135 session_->video_rtp_transport_channel()); 3136 } 3137 3138 // kBundlePolicyMaxBundle policy with BUNDLE in the answer, but no 3139 // audio content in the answer. 3140 TEST_F(WebRtcSessionTest, TestMaxBundleRejectAudio) { 3141 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyMaxBundle); 3142 SendAudioVideoStream1(); 3143 3144 PeerConnectionInterface::RTCOfferAnswerOptions options; 3145 options.use_rtp_mux = true; 3146 3147 SessionDescriptionInterface* offer = CreateOffer(options); 3148 SetLocalDescriptionWithoutError(offer); 3149 3150 EXPECT_EQ(session_->voice_rtp_transport_channel(), 3151 session_->video_rtp_transport_channel()); 3152 3153 SendAudioVideoStream2(); 3154 cricket::MediaSessionOptions recv_options; 3155 recv_options.recv_audio = false; 3156 recv_options.recv_video = true; 3157 SessionDescriptionInterface* answer = 3158 CreateRemoteAnswer(session_->local_description(), recv_options); 3159 SetRemoteDescriptionWithoutError(answer); 3160 3161 EXPECT_TRUE(nullptr == session_->voice_channel()); 3162 EXPECT_TRUE(nullptr != session_->video_rtp_transport_channel()); 3163 3164 session_->Close(); 3165 EXPECT_TRUE(nullptr == session_->voice_rtp_transport_channel()); 3166 EXPECT_TRUE(nullptr == session_->voice_rtcp_transport_channel()); 3167 EXPECT_TRUE(nullptr == session_->video_rtp_transport_channel()); 3168 EXPECT_TRUE(nullptr == session_->video_rtcp_transport_channel()); 3169 } 3170 3171 // kBundlePolicyMaxBundle policy but no BUNDLE in the answer. 3172 TEST_F(WebRtcSessionTest, TestMaxBundleNoBundleInAnswer) { 3173 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyMaxBundle); 3174 SendAudioVideoStream1(); 3175 3176 PeerConnectionInterface::RTCOfferAnswerOptions options; 3177 options.use_rtp_mux = true; 3178 3179 SessionDescriptionInterface* offer = CreateOffer(options); 3180 SetLocalDescriptionWithoutError(offer); 3181 3182 EXPECT_EQ(session_->voice_rtp_transport_channel(), 3183 session_->video_rtp_transport_channel()); 3184 3185 SendAudioVideoStream2(); 3186 3187 // Remove BUNDLE from the answer. 3188 rtc::scoped_ptr<SessionDescriptionInterface> answer( 3189 CreateRemoteAnswer(session_->local_description())); 3190 cricket::SessionDescription* answer_copy = answer->description()->Copy(); 3191 answer_copy->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE); 3192 JsepSessionDescription* modified_answer = 3193 new JsepSessionDescription(JsepSessionDescription::kAnswer); 3194 modified_answer->Initialize(answer_copy, "1", "1"); 3195 SetRemoteDescriptionWithoutError(modified_answer); 3196 3197 EXPECT_EQ(session_->voice_rtp_transport_channel(), 3198 session_->video_rtp_transport_channel()); 3199 } 3200 3201 // kBundlePolicyMaxBundle policy with BUNDLE in the remote offer. 3202 TEST_F(WebRtcSessionTest, TestMaxBundleBundleInRemoteOffer) { 3203 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyMaxBundle); 3204 SendAudioVideoStream1(); 3205 3206 SessionDescriptionInterface* offer = CreateRemoteOffer(); 3207 SetRemoteDescriptionWithoutError(offer); 3208 3209 EXPECT_EQ(session_->voice_rtp_transport_channel(), 3210 session_->video_rtp_transport_channel()); 3211 3212 SendAudioVideoStream2(); 3213 SessionDescriptionInterface* answer = CreateAnswer(nullptr); 3214 SetLocalDescriptionWithoutError(answer); 3215 3216 EXPECT_EQ(session_->voice_rtp_transport_channel(), 3217 session_->video_rtp_transport_channel()); 3218 } 3219 3220 // kBundlePolicyMaxBundle policy but no BUNDLE in the remote offer. 3221 TEST_F(WebRtcSessionTest, TestMaxBundleNoBundleInRemoteOffer) { 3222 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyMaxBundle); 3223 SendAudioVideoStream1(); 3224 3225 // Remove BUNDLE from the offer. 3226 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateRemoteOffer()); 3227 cricket::SessionDescription* offer_copy = offer->description()->Copy(); 3228 offer_copy->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE); 3229 JsepSessionDescription* modified_offer = 3230 new JsepSessionDescription(JsepSessionDescription::kOffer); 3231 modified_offer->Initialize(offer_copy, "1", "1"); 3232 3233 // Expect an error when applying the remote description 3234 SetRemoteDescriptionExpectError(JsepSessionDescription::kOffer, 3235 kCreateChannelFailed, modified_offer); 3236 } 3237 3238 // kBundlePolicyMaxCompat bundle policy and answer contains BUNDLE. 3239 TEST_F(WebRtcSessionTest, TestMaxCompatBundleInAnswer) { 3240 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyMaxCompat); 3241 SendAudioVideoStream1(); 3242 3243 PeerConnectionInterface::RTCOfferAnswerOptions options; 3244 options.use_rtp_mux = true; 3245 3246 SessionDescriptionInterface* offer = CreateOffer(options); 3247 SetLocalDescriptionWithoutError(offer); 3248 3249 EXPECT_NE(session_->voice_rtp_transport_channel(), 3250 session_->video_rtp_transport_channel()); 3251 3252 SendAudioVideoStream2(); 3253 SessionDescriptionInterface* answer = 3254 CreateRemoteAnswer(session_->local_description()); 3255 SetRemoteDescriptionWithoutError(answer); 3256 3257 // This should lead to an audio-only call but isn't implemented 3258 // correctly yet. 3259 EXPECT_EQ(session_->voice_rtp_transport_channel(), 3260 session_->video_rtp_transport_channel()); 3261 } 3262 3263 // kBundlePolicyMaxCompat BUNDLE policy but no BUNDLE in the answer. 3264 TEST_F(WebRtcSessionTest, TestMaxCompatNoBundleInAnswer) { 3265 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyMaxCompat); 3266 SendAudioVideoStream1(); 3267 PeerConnectionInterface::RTCOfferAnswerOptions options; 3268 options.use_rtp_mux = true; 3269 3270 SessionDescriptionInterface* offer = CreateOffer(options); 3271 SetLocalDescriptionWithoutError(offer); 3272 3273 EXPECT_NE(session_->voice_rtp_transport_channel(), 3274 session_->video_rtp_transport_channel()); 3275 3276 SendAudioVideoStream2(); 3277 3278 // Remove BUNDLE from the answer. 3279 rtc::scoped_ptr<SessionDescriptionInterface> answer( 3280 CreateRemoteAnswer(session_->local_description())); 3281 cricket::SessionDescription* answer_copy = answer->description()->Copy(); 3282 answer_copy->RemoveGroupByName(cricket::GROUP_TYPE_BUNDLE); 3283 JsepSessionDescription* modified_answer = 3284 new JsepSessionDescription(JsepSessionDescription::kAnswer); 3285 modified_answer->Initialize(answer_copy, "1", "1"); 3286 SetRemoteDescriptionWithoutError(modified_answer); // 3287 3288 EXPECT_NE(session_->voice_rtp_transport_channel(), 3289 session_->video_rtp_transport_channel()); 3290 } 3291 3292 // kBundlePolicyMaxbundle and then we call SetRemoteDescription first. 3293 TEST_F(WebRtcSessionTest, TestMaxBundleWithSetRemoteDescriptionFirst) { 3294 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyMaxBundle); 3295 SendAudioVideoStream1(); 3296 3297 PeerConnectionInterface::RTCOfferAnswerOptions options; 3298 options.use_rtp_mux = true; 3299 3300 SessionDescriptionInterface* offer = CreateOffer(options); 3301 SetRemoteDescriptionWithoutError(offer); 3302 3303 EXPECT_EQ(session_->voice_rtp_transport_channel(), 3304 session_->video_rtp_transport_channel()); 3305 } 3306 3307 TEST_F(WebRtcSessionTest, TestRequireRtcpMux) { 3308 InitWithRtcpMuxPolicy(PeerConnectionInterface::kRtcpMuxPolicyRequire); 3309 SendAudioVideoStream1(); 3310 3311 PeerConnectionInterface::RTCOfferAnswerOptions options; 3312 SessionDescriptionInterface* offer = CreateOffer(options); 3313 SetLocalDescriptionWithoutError(offer); 3314 3315 EXPECT_TRUE(session_->voice_rtcp_transport_channel() == NULL); 3316 EXPECT_TRUE(session_->video_rtcp_transport_channel() == NULL); 3317 3318 SendAudioVideoStream2(); 3319 SessionDescriptionInterface* answer = 3320 CreateRemoteAnswer(session_->local_description()); 3321 SetRemoteDescriptionWithoutError(answer); 3322 3323 EXPECT_TRUE(session_->voice_rtcp_transport_channel() == NULL); 3324 EXPECT_TRUE(session_->video_rtcp_transport_channel() == NULL); 3325 } 3326 3327 TEST_F(WebRtcSessionTest, TestNegotiateRtcpMux) { 3328 InitWithRtcpMuxPolicy(PeerConnectionInterface::kRtcpMuxPolicyNegotiate); 3329 SendAudioVideoStream1(); 3330 3331 PeerConnectionInterface::RTCOfferAnswerOptions options; 3332 SessionDescriptionInterface* offer = CreateOffer(options); 3333 SetLocalDescriptionWithoutError(offer); 3334 3335 EXPECT_TRUE(session_->voice_rtcp_transport_channel() != NULL); 3336 EXPECT_TRUE(session_->video_rtcp_transport_channel() != NULL); 3337 3338 SendAudioVideoStream2(); 3339 SessionDescriptionInterface* answer = 3340 CreateRemoteAnswer(session_->local_description()); 3341 SetRemoteDescriptionWithoutError(answer); 3342 3343 EXPECT_TRUE(session_->voice_rtcp_transport_channel() == NULL); 3344 EXPECT_TRUE(session_->video_rtcp_transport_channel() == NULL); 3345 } 3346 3347 // This test verifies that SetLocalDescription and SetRemoteDescription fails 3348 // if BUNDLE is enabled but rtcp-mux is disabled in m-lines. 3349 TEST_F(WebRtcSessionTest, TestDisabledRtcpMuxWithBundleEnabled) { 3350 Init(); 3351 SendAudioVideoStream1(); 3352 3353 PeerConnectionInterface::RTCOfferAnswerOptions options; 3354 options.use_rtp_mux = true; 3355 3356 SessionDescriptionInterface* offer = CreateOffer(options); 3357 std::string offer_str; 3358 offer->ToString(&offer_str); 3359 // Disable rtcp-mux 3360 const std::string rtcp_mux = "rtcp-mux"; 3361 const std::string xrtcp_mux = "xrtcp-mux"; 3362 rtc::replace_substrs(rtcp_mux.c_str(), rtcp_mux.length(), 3363 xrtcp_mux.c_str(), xrtcp_mux.length(), 3364 &offer_str); 3365 JsepSessionDescription* local_offer = 3366 new JsepSessionDescription(JsepSessionDescription::kOffer); 3367 EXPECT_TRUE((local_offer)->Initialize(offer_str, NULL)); 3368 SetLocalDescriptionOfferExpectError(kBundleWithoutRtcpMux, local_offer); 3369 JsepSessionDescription* remote_offer = 3370 new JsepSessionDescription(JsepSessionDescription::kOffer); 3371 EXPECT_TRUE((remote_offer)->Initialize(offer_str, NULL)); 3372 SetRemoteDescriptionOfferExpectError(kBundleWithoutRtcpMux, remote_offer); 3373 // Trying unmodified SDP. 3374 SetLocalDescriptionWithoutError(offer); 3375 } 3376 3377 TEST_F(WebRtcSessionTest, SetAudioPlayout) { 3378 Init(); 3379 SendAudioVideoStream1(); 3380 CreateAndSetRemoteOfferAndLocalAnswer(); 3381 cricket::FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0); 3382 ASSERT_TRUE(channel != NULL); 3383 ASSERT_EQ(1u, channel->recv_streams().size()); 3384 uint32_t receive_ssrc = channel->recv_streams()[0].first_ssrc(); 3385 double volume; 3386 EXPECT_TRUE(channel->GetOutputVolume(receive_ssrc, &volume)); 3387 EXPECT_EQ(1, volume); 3388 session_->SetAudioPlayout(receive_ssrc, false); 3389 EXPECT_TRUE(channel->GetOutputVolume(receive_ssrc, &volume)); 3390 EXPECT_EQ(0, volume); 3391 session_->SetAudioPlayout(receive_ssrc, true); 3392 EXPECT_TRUE(channel->GetOutputVolume(receive_ssrc, &volume)); 3393 EXPECT_EQ(1, volume); 3394 } 3395 3396 TEST_F(WebRtcSessionTest, SetAudioSend) { 3397 Init(); 3398 SendAudioVideoStream1(); 3399 CreateAndSetRemoteOfferAndLocalAnswer(); 3400 cricket::FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0); 3401 ASSERT_TRUE(channel != NULL); 3402 ASSERT_EQ(1u, channel->send_streams().size()); 3403 uint32_t send_ssrc = channel->send_streams()[0].first_ssrc(); 3404 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc)); 3405 3406 cricket::AudioOptions options; 3407 options.echo_cancellation = rtc::Optional<bool>(true); 3408 3409 rtc::scoped_ptr<FakeAudioRenderer> renderer(new FakeAudioRenderer()); 3410 session_->SetAudioSend(send_ssrc, false, options, renderer.get()); 3411 EXPECT_TRUE(channel->IsStreamMuted(send_ssrc)); 3412 EXPECT_EQ(rtc::Optional<bool>(), channel->options().echo_cancellation); 3413 EXPECT_TRUE(renderer->sink() != NULL); 3414 3415 // This will trigger SetSink(NULL) to the |renderer|. 3416 session_->SetAudioSend(send_ssrc, true, options, NULL); 3417 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc)); 3418 EXPECT_EQ(rtc::Optional<bool>(true), channel->options().echo_cancellation); 3419 EXPECT_TRUE(renderer->sink() == NULL); 3420 } 3421 3422 TEST_F(WebRtcSessionTest, AudioRendererForLocalStream) { 3423 Init(); 3424 SendAudioVideoStream1(); 3425 CreateAndSetRemoteOfferAndLocalAnswer(); 3426 cricket::FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0); 3427 ASSERT_TRUE(channel != NULL); 3428 ASSERT_EQ(1u, channel->send_streams().size()); 3429 uint32_t send_ssrc = channel->send_streams()[0].first_ssrc(); 3430 3431 rtc::scoped_ptr<FakeAudioRenderer> renderer(new FakeAudioRenderer()); 3432 cricket::AudioOptions options; 3433 session_->SetAudioSend(send_ssrc, true, options, renderer.get()); 3434 EXPECT_TRUE(renderer->sink() != NULL); 3435 3436 // Delete the |renderer| and it will trigger OnClose() to the sink, and this 3437 // will invalidate the |renderer_| pointer in the sink and prevent getting a 3438 // SetSink(NULL) callback afterwards. 3439 renderer.reset(); 3440 3441 // This will trigger SetSink(NULL) if no OnClose() callback. 3442 session_->SetAudioSend(send_ssrc, true, options, NULL); 3443 } 3444 3445 TEST_F(WebRtcSessionTest, SetVideoPlayout) { 3446 Init(); 3447 SendAudioVideoStream1(); 3448 CreateAndSetRemoteOfferAndLocalAnswer(); 3449 cricket::FakeVideoMediaChannel* channel = media_engine_->GetVideoChannel(0); 3450 ASSERT_TRUE(channel != NULL); 3451 ASSERT_LT(0u, channel->renderers().size()); 3452 EXPECT_TRUE(channel->renderers().begin()->second == NULL); 3453 ASSERT_EQ(1u, channel->recv_streams().size()); 3454 uint32_t receive_ssrc = channel->recv_streams()[0].first_ssrc(); 3455 cricket::FakeVideoRenderer renderer; 3456 session_->SetVideoPlayout(receive_ssrc, true, &renderer); 3457 EXPECT_TRUE(channel->renderers().begin()->second == &renderer); 3458 session_->SetVideoPlayout(receive_ssrc, false, &renderer); 3459 EXPECT_TRUE(channel->renderers().begin()->second == NULL); 3460 } 3461 3462 TEST_F(WebRtcSessionTest, SetVideoSend) { 3463 Init(); 3464 SendAudioVideoStream1(); 3465 CreateAndSetRemoteOfferAndLocalAnswer(); 3466 cricket::FakeVideoMediaChannel* channel = media_engine_->GetVideoChannel(0); 3467 ASSERT_TRUE(channel != NULL); 3468 ASSERT_EQ(1u, channel->send_streams().size()); 3469 uint32_t send_ssrc = channel->send_streams()[0].first_ssrc(); 3470 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc)); 3471 cricket::VideoOptions* options = NULL; 3472 session_->SetVideoSend(send_ssrc, false, options); 3473 EXPECT_TRUE(channel->IsStreamMuted(send_ssrc)); 3474 session_->SetVideoSend(send_ssrc, true, options); 3475 EXPECT_FALSE(channel->IsStreamMuted(send_ssrc)); 3476 } 3477 3478 TEST_F(WebRtcSessionTest, CanNotInsertDtmf) { 3479 TestCanInsertDtmf(false); 3480 } 3481 3482 TEST_F(WebRtcSessionTest, CanInsertDtmf) { 3483 TestCanInsertDtmf(true); 3484 } 3485 3486 TEST_F(WebRtcSessionTest, InsertDtmf) { 3487 // Setup 3488 Init(); 3489 SendAudioVideoStream1(); 3490 CreateAndSetRemoteOfferAndLocalAnswer(); 3491 FakeVoiceMediaChannel* channel = media_engine_->GetVoiceChannel(0); 3492 EXPECT_EQ(0U, channel->dtmf_info_queue().size()); 3493 3494 // Insert DTMF 3495 const int expected_duration = 90; 3496 session_->InsertDtmf(kAudioTrack1, 0, expected_duration); 3497 session_->InsertDtmf(kAudioTrack1, 1, expected_duration); 3498 session_->InsertDtmf(kAudioTrack1, 2, expected_duration); 3499 3500 // Verify 3501 ASSERT_EQ(3U, channel->dtmf_info_queue().size()); 3502 const uint32_t send_ssrc = channel->send_streams()[0].first_ssrc(); 3503 EXPECT_TRUE(CompareDtmfInfo(channel->dtmf_info_queue()[0], send_ssrc, 0, 3504 expected_duration)); 3505 EXPECT_TRUE(CompareDtmfInfo(channel->dtmf_info_queue()[1], send_ssrc, 1, 3506 expected_duration)); 3507 EXPECT_TRUE(CompareDtmfInfo(channel->dtmf_info_queue()[2], send_ssrc, 2, 3508 expected_duration)); 3509 } 3510 3511 // This test verifies the |initial_offerer| flag when session initiates the 3512 // call. 3513 TEST_F(WebRtcSessionTest, TestInitiatorFlagAsOriginator) { 3514 Init(); 3515 EXPECT_FALSE(session_->initial_offerer()); 3516 SessionDescriptionInterface* offer = CreateOffer(); 3517 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer); 3518 SetLocalDescriptionWithoutError(offer); 3519 EXPECT_TRUE(session_->initial_offerer()); 3520 SetRemoteDescriptionWithoutError(answer); 3521 EXPECT_TRUE(session_->initial_offerer()); 3522 } 3523 3524 // This test verifies the |initial_offerer| flag when session receives the call. 3525 TEST_F(WebRtcSessionTest, TestInitiatorFlagAsReceiver) { 3526 Init(); 3527 EXPECT_FALSE(session_->initial_offerer()); 3528 SessionDescriptionInterface* offer = CreateRemoteOffer(); 3529 SetRemoteDescriptionWithoutError(offer); 3530 SessionDescriptionInterface* answer = CreateAnswer(NULL); 3531 3532 EXPECT_FALSE(session_->initial_offerer()); 3533 SetLocalDescriptionWithoutError(answer); 3534 EXPECT_FALSE(session_->initial_offerer()); 3535 } 3536 3537 // Verifing local offer and remote answer have matching m-lines as per RFC 3264. 3538 TEST_F(WebRtcSessionTest, TestIncorrectMLinesInRemoteAnswer) { 3539 Init(); 3540 SendAudioVideoStream1(); 3541 SessionDescriptionInterface* offer = CreateOffer(); 3542 SetLocalDescriptionWithoutError(offer); 3543 rtc::scoped_ptr<SessionDescriptionInterface> answer( 3544 CreateRemoteAnswer(session_->local_description())); 3545 3546 cricket::SessionDescription* answer_copy = answer->description()->Copy(); 3547 answer_copy->RemoveContentByName("video"); 3548 JsepSessionDescription* modified_answer = 3549 new JsepSessionDescription(JsepSessionDescription::kAnswer); 3550 3551 EXPECT_TRUE(modified_answer->Initialize(answer_copy, 3552 answer->session_id(), 3553 answer->session_version())); 3554 SetRemoteDescriptionAnswerExpectError(kMlineMismatch, modified_answer); 3555 3556 // Different content names. 3557 std::string sdp; 3558 EXPECT_TRUE(answer->ToString(&sdp)); 3559 const std::string kAudioMid = "a=mid:audio"; 3560 const std::string kAudioMidReplaceStr = "a=mid:audio_content_name"; 3561 rtc::replace_substrs(kAudioMid.c_str(), kAudioMid.length(), 3562 kAudioMidReplaceStr.c_str(), 3563 kAudioMidReplaceStr.length(), 3564 &sdp); 3565 SessionDescriptionInterface* modified_answer1 = 3566 CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL); 3567 SetRemoteDescriptionAnswerExpectError(kMlineMismatch, modified_answer1); 3568 3569 // Different media types. 3570 EXPECT_TRUE(answer->ToString(&sdp)); 3571 const std::string kAudioMline = "m=audio"; 3572 const std::string kAudioMlineReplaceStr = "m=video"; 3573 rtc::replace_substrs(kAudioMline.c_str(), kAudioMline.length(), 3574 kAudioMlineReplaceStr.c_str(), 3575 kAudioMlineReplaceStr.length(), 3576 &sdp); 3577 SessionDescriptionInterface* modified_answer2 = 3578 CreateSessionDescription(JsepSessionDescription::kAnswer, sdp, NULL); 3579 SetRemoteDescriptionAnswerExpectError(kMlineMismatch, modified_answer2); 3580 3581 SetRemoteDescriptionWithoutError(answer.release()); 3582 } 3583 3584 // Verifying remote offer and local answer have matching m-lines as per 3585 // RFC 3264. 3586 TEST_F(WebRtcSessionTest, TestIncorrectMLinesInLocalAnswer) { 3587 Init(); 3588 SendAudioVideoStream1(); 3589 SessionDescriptionInterface* offer = CreateRemoteOffer(); 3590 SetRemoteDescriptionWithoutError(offer); 3591 SessionDescriptionInterface* answer = CreateAnswer(NULL); 3592 3593 cricket::SessionDescription* answer_copy = answer->description()->Copy(); 3594 answer_copy->RemoveContentByName("video"); 3595 JsepSessionDescription* modified_answer = 3596 new JsepSessionDescription(JsepSessionDescription::kAnswer); 3597 3598 EXPECT_TRUE(modified_answer->Initialize(answer_copy, 3599 answer->session_id(), 3600 answer->session_version())); 3601 SetLocalDescriptionAnswerExpectError(kMlineMismatch, modified_answer); 3602 SetLocalDescriptionWithoutError(answer); 3603 } 3604 3605 // This test verifies that WebRtcSession does not start candidate allocation 3606 // before SetLocalDescription is called. 3607 TEST_F(WebRtcSessionTest, TestIceStartAfterSetLocalDescriptionOnly) { 3608 Init(); 3609 SendAudioVideoStream1(); 3610 SessionDescriptionInterface* offer = CreateRemoteOffer(); 3611 cricket::Candidate candidate; 3612 candidate.set_component(1); 3613 JsepIceCandidate ice_candidate(kMediaContentName0, kMediaContentIndex0, 3614 candidate); 3615 EXPECT_TRUE(offer->AddCandidate(&ice_candidate)); 3616 cricket::Candidate candidate1; 3617 candidate1.set_component(1); 3618 JsepIceCandidate ice_candidate1(kMediaContentName1, kMediaContentIndex1, 3619 candidate1); 3620 EXPECT_TRUE(offer->AddCandidate(&ice_candidate1)); 3621 SetRemoteDescriptionWithoutError(offer); 3622 ASSERT_TRUE(session_->voice_rtp_transport_channel() != NULL); 3623 ASSERT_TRUE(session_->video_rtp_transport_channel() != NULL); 3624 3625 // Pump for 1 second and verify that no candidates are generated. 3626 rtc::Thread::Current()->ProcessMessages(1000); 3627 EXPECT_TRUE(observer_.mline_0_candidates_.empty()); 3628 EXPECT_TRUE(observer_.mline_1_candidates_.empty()); 3629 3630 SessionDescriptionInterface* answer = CreateAnswer(NULL); 3631 SetLocalDescriptionWithoutError(answer); 3632 EXPECT_TRUE_WAIT(observer_.oncandidatesready_, kIceCandidatesTimeout); 3633 } 3634 3635 // This test verifies that crypto parameter is updated in local session 3636 // description as per security policy set in MediaSessionDescriptionFactory. 3637 TEST_F(WebRtcSessionTest, TestCryptoAfterSetLocalDescription) { 3638 Init(); 3639 SendAudioVideoStream1(); 3640 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer()); 3641 3642 // Making sure SetLocalDescription correctly sets crypto value in 3643 // SessionDescription object after de-serialization of sdp string. The value 3644 // will be set as per MediaSessionDescriptionFactory. 3645 std::string offer_str; 3646 offer->ToString(&offer_str); 3647 SessionDescriptionInterface* jsep_offer_str = 3648 CreateSessionDescription(JsepSessionDescription::kOffer, offer_str, NULL); 3649 SetLocalDescriptionWithoutError(jsep_offer_str); 3650 EXPECT_TRUE(session_->voice_channel()->secure_required()); 3651 EXPECT_TRUE(session_->video_channel()->secure_required()); 3652 } 3653 3654 // This test verifies the crypto parameter when security is disabled. 3655 TEST_F(WebRtcSessionTest, TestCryptoAfterSetLocalDescriptionWithDisabled) { 3656 options_.disable_encryption = true; 3657 Init(); 3658 SendAudioVideoStream1(); 3659 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer()); 3660 3661 // Making sure SetLocalDescription correctly sets crypto value in 3662 // SessionDescription object after de-serialization of sdp string. The value 3663 // will be set as per MediaSessionDescriptionFactory. 3664 std::string offer_str; 3665 offer->ToString(&offer_str); 3666 SessionDescriptionInterface* jsep_offer_str = 3667 CreateSessionDescription(JsepSessionDescription::kOffer, offer_str, NULL); 3668 SetLocalDescriptionWithoutError(jsep_offer_str); 3669 EXPECT_FALSE(session_->voice_channel()->secure_required()); 3670 EXPECT_FALSE(session_->video_channel()->secure_required()); 3671 } 3672 3673 // This test verifies that an answer contains new ufrag and password if an offer 3674 // with new ufrag and password is received. 3675 TEST_F(WebRtcSessionTest, TestCreateAnswerWithNewUfragAndPassword) { 3676 Init(); 3677 cricket::MediaSessionOptions options; 3678 options.recv_video = true; 3679 rtc::scoped_ptr<JsepSessionDescription> offer( 3680 CreateRemoteOffer(options)); 3681 SetRemoteDescriptionWithoutError(offer.release()); 3682 3683 SendAudioVideoStream1(); 3684 rtc::scoped_ptr<SessionDescriptionInterface> answer( 3685 CreateAnswer(NULL)); 3686 SetLocalDescriptionWithoutError(answer.release()); 3687 3688 // Receive an offer with new ufrag and password. 3689 options.audio_transport_options.ice_restart = true; 3690 options.video_transport_options.ice_restart = true; 3691 options.data_transport_options.ice_restart = true; 3692 rtc::scoped_ptr<JsepSessionDescription> updated_offer1( 3693 CreateRemoteOffer(options, session_->remote_description())); 3694 SetRemoteDescriptionWithoutError(updated_offer1.release()); 3695 3696 rtc::scoped_ptr<SessionDescriptionInterface> updated_answer1( 3697 CreateAnswer(NULL)); 3698 3699 CompareIceUfragAndPassword(updated_answer1->description(), 3700 session_->local_description()->description(), 3701 false); 3702 3703 SetLocalDescriptionWithoutError(updated_answer1.release()); 3704 } 3705 3706 // This test verifies that an answer contains old ufrag and password if an offer 3707 // with old ufrag and password is received. 3708 TEST_F(WebRtcSessionTest, TestCreateAnswerWithOldUfragAndPassword) { 3709 Init(); 3710 cricket::MediaSessionOptions options; 3711 options.recv_video = true; 3712 rtc::scoped_ptr<JsepSessionDescription> offer( 3713 CreateRemoteOffer(options)); 3714 SetRemoteDescriptionWithoutError(offer.release()); 3715 3716 SendAudioVideoStream1(); 3717 rtc::scoped_ptr<SessionDescriptionInterface> answer( 3718 CreateAnswer(NULL)); 3719 SetLocalDescriptionWithoutError(answer.release()); 3720 3721 // Receive an offer without changed ufrag or password. 3722 options.audio_transport_options.ice_restart = false; 3723 options.video_transport_options.ice_restart = false; 3724 options.data_transport_options.ice_restart = false; 3725 rtc::scoped_ptr<JsepSessionDescription> updated_offer2( 3726 CreateRemoteOffer(options, session_->remote_description())); 3727 SetRemoteDescriptionWithoutError(updated_offer2.release()); 3728 3729 rtc::scoped_ptr<SessionDescriptionInterface> updated_answer2( 3730 CreateAnswer(NULL)); 3731 3732 CompareIceUfragAndPassword(updated_answer2->description(), 3733 session_->local_description()->description(), 3734 true); 3735 3736 SetLocalDescriptionWithoutError(updated_answer2.release()); 3737 } 3738 3739 TEST_F(WebRtcSessionTest, TestSessionContentError) { 3740 Init(); 3741 SendAudioVideoStream1(); 3742 SessionDescriptionInterface* offer = CreateOffer(); 3743 const std::string session_id_orig = offer->session_id(); 3744 const std::string session_version_orig = offer->session_version(); 3745 SetLocalDescriptionWithoutError(offer); 3746 3747 video_channel_ = media_engine_->GetVideoChannel(0); 3748 video_channel_->set_fail_set_send_codecs(true); 3749 3750 SessionDescriptionInterface* answer = 3751 CreateRemoteAnswer(session_->local_description()); 3752 SetRemoteDescriptionAnswerExpectError("ERROR_CONTENT", answer); 3753 3754 // Test that after a content error, setting any description will 3755 // result in an error. 3756 video_channel_->set_fail_set_send_codecs(false); 3757 answer = CreateRemoteAnswer(session_->local_description()); 3758 SetRemoteDescriptionExpectError("", "ERROR_CONTENT", answer); 3759 offer = CreateRemoteOffer(); 3760 SetLocalDescriptionExpectError("", "ERROR_CONTENT", offer); 3761 } 3762 3763 // Runs the loopback call test with BUNDLE and STUN disabled. 3764 TEST_F(WebRtcSessionTest, TestIceStatesBasic) { 3765 // Lets try with only UDP ports. 3766 allocator_->set_flags(cricket::PORTALLOCATOR_DISABLE_TCP | 3767 cricket::PORTALLOCATOR_DISABLE_STUN | 3768 cricket::PORTALLOCATOR_DISABLE_RELAY); 3769 TestLoopbackCall(); 3770 } 3771 3772 TEST_F(WebRtcSessionTest, TestIceStatesBasicIPv6) { 3773 allocator_->set_flags(cricket::PORTALLOCATOR_DISABLE_TCP | 3774 cricket::PORTALLOCATOR_DISABLE_STUN | 3775 cricket::PORTALLOCATOR_ENABLE_IPV6 | 3776 cricket::PORTALLOCATOR_DISABLE_RELAY); 3777 3778 // best connection is IPv6 since it has higher network preference. 3779 LoopbackNetworkConfiguration config; 3780 config.test_ipv6_network_ = true; 3781 config.best_connection_after_initial_ice_converged_ = 3782 LoopbackNetworkConfiguration::ExpectedBestConnection(0, 1); 3783 3784 TestLoopbackCall(config); 3785 } 3786 3787 // Runs the loopback call test with BUNDLE and STUN enabled. 3788 TEST_F(WebRtcSessionTest, TestIceStatesBundle) { 3789 allocator_->set_flags(cricket::PORTALLOCATOR_DISABLE_TCP | 3790 cricket::PORTALLOCATOR_DISABLE_RELAY); 3791 TestLoopbackCall(); 3792 } 3793 3794 TEST_F(WebRtcSessionTest, TestRtpDataChannel) { 3795 constraints_.reset(new FakeConstraints()); 3796 constraints_->AddOptional( 3797 webrtc::MediaConstraintsInterface::kEnableRtpDataChannels, true); 3798 Init(); 3799 3800 SetLocalDescriptionWithDataChannel(); 3801 EXPECT_EQ(cricket::DCT_RTP, data_engine_->last_channel_type()); 3802 } 3803 3804 TEST_P(WebRtcSessionTest, TestRtpDataChannelConstraintTakesPrecedence) { 3805 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); 3806 3807 constraints_.reset(new FakeConstraints()); 3808 constraints_->AddOptional( 3809 webrtc::MediaConstraintsInterface::kEnableRtpDataChannels, true); 3810 options_.disable_sctp_data_channels = false; 3811 3812 InitWithDtls(GetParam()); 3813 3814 SetLocalDescriptionWithDataChannel(); 3815 EXPECT_EQ(cricket::DCT_RTP, data_engine_->last_channel_type()); 3816 } 3817 3818 TEST_P(WebRtcSessionTest, TestCreateOfferWithSctpEnabledWithoutStreams) { 3819 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); 3820 3821 InitWithDtls(GetParam()); 3822 3823 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer()); 3824 EXPECT_TRUE(offer->description()->GetContentByName("data") == NULL); 3825 EXPECT_TRUE(offer->description()->GetTransportInfoByName("data") == NULL); 3826 } 3827 3828 TEST_P(WebRtcSessionTest, TestCreateAnswerWithSctpInOfferAndNoStreams) { 3829 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); 3830 SetFactoryDtlsSrtp(); 3831 InitWithDtls(GetParam()); 3832 3833 // Create remote offer with SCTP. 3834 cricket::MediaSessionOptions options; 3835 options.data_channel_type = cricket::DCT_SCTP; 3836 JsepSessionDescription* offer = 3837 CreateRemoteOffer(options, cricket::SEC_DISABLED); 3838 SetRemoteDescriptionWithoutError(offer); 3839 3840 // Verifies the answer contains SCTP. 3841 rtc::scoped_ptr<SessionDescriptionInterface> answer(CreateAnswer(NULL)); 3842 EXPECT_TRUE(answer != NULL); 3843 EXPECT_TRUE(answer->description()->GetContentByName("data") != NULL); 3844 EXPECT_TRUE(answer->description()->GetTransportInfoByName("data") != NULL); 3845 } 3846 3847 TEST_P(WebRtcSessionTest, TestSctpDataChannelWithoutDtls) { 3848 constraints_.reset(new FakeConstraints()); 3849 constraints_->AddOptional( 3850 webrtc::MediaConstraintsInterface::kEnableDtlsSrtp, false); 3851 InitWithDtls(GetParam()); 3852 3853 SetLocalDescriptionWithDataChannel(); 3854 EXPECT_EQ(cricket::DCT_NONE, data_engine_->last_channel_type()); 3855 } 3856 3857 TEST_P(WebRtcSessionTest, TestSctpDataChannelWithDtls) { 3858 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); 3859 3860 InitWithDtls(GetParam()); 3861 3862 SetLocalDescriptionWithDataChannel(); 3863 EXPECT_EQ(cricket::DCT_SCTP, data_engine_->last_channel_type()); 3864 } 3865 3866 TEST_P(WebRtcSessionTest, TestDisableSctpDataChannels) { 3867 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); 3868 options_.disable_sctp_data_channels = true; 3869 InitWithDtls(GetParam()); 3870 3871 SetLocalDescriptionWithDataChannel(); 3872 EXPECT_EQ(cricket::DCT_NONE, data_engine_->last_channel_type()); 3873 } 3874 3875 TEST_P(WebRtcSessionTest, TestSctpDataChannelSendPortParsing) { 3876 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); 3877 const int new_send_port = 9998; 3878 const int new_recv_port = 7775; 3879 3880 InitWithDtls(GetParam()); 3881 SetFactoryDtlsSrtp(); 3882 3883 // By default, don't actually add the codecs to desc_factory_; they don't 3884 // actually get serialized for SCTP in BuildMediaDescription(). Instead, 3885 // let the session description get parsed. That'll get the proper codecs 3886 // into the stream. 3887 cricket::MediaSessionOptions options; 3888 JsepSessionDescription* offer = CreateRemoteOfferWithSctpPort( 3889 "stream1", new_send_port, options); 3890 3891 // SetRemoteDescription will take the ownership of the offer. 3892 SetRemoteDescriptionWithoutError(offer); 3893 3894 SessionDescriptionInterface* answer = ChangeSDPSctpPort( 3895 new_recv_port, CreateAnswer(NULL)); 3896 ASSERT_TRUE(answer != NULL); 3897 3898 // Now set the local description, which'll take ownership of the answer. 3899 SetLocalDescriptionWithoutError(answer); 3900 3901 // TEST PLAN: Set the port number to something new, set it in the SDP, 3902 // and pass it all the way down. 3903 EXPECT_EQ(cricket::DCT_SCTP, data_engine_->last_channel_type()); 3904 CreateDataChannel(); 3905 3906 cricket::FakeDataMediaChannel* ch = data_engine_->GetChannel(0); 3907 int portnum = -1; 3908 ASSERT_TRUE(ch != NULL); 3909 ASSERT_EQ(1UL, ch->send_codecs().size()); 3910 EXPECT_EQ(cricket::kGoogleSctpDataCodecId, ch->send_codecs()[0].id); 3911 EXPECT_EQ(0, strcmp(cricket::kGoogleSctpDataCodecName, 3912 ch->send_codecs()[0].name.c_str())); 3913 EXPECT_TRUE(ch->send_codecs()[0].GetParam(cricket::kCodecParamPort, 3914 &portnum)); 3915 EXPECT_EQ(new_send_port, portnum); 3916 3917 ASSERT_EQ(1UL, ch->recv_codecs().size()); 3918 EXPECT_EQ(cricket::kGoogleSctpDataCodecId, ch->recv_codecs()[0].id); 3919 EXPECT_EQ(0, strcmp(cricket::kGoogleSctpDataCodecName, 3920 ch->recv_codecs()[0].name.c_str())); 3921 EXPECT_TRUE(ch->recv_codecs()[0].GetParam(cricket::kCodecParamPort, 3922 &portnum)); 3923 EXPECT_EQ(new_recv_port, portnum); 3924 } 3925 3926 // Verifies that when a session's DataChannel receives an OPEN message, 3927 // WebRtcSession signals the DataChannel creation request with the expected 3928 // config. 3929 TEST_P(WebRtcSessionTest, TestSctpDataChannelOpenMessage) { 3930 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); 3931 3932 InitWithDtls(GetParam()); 3933 3934 SetLocalDescriptionWithDataChannel(); 3935 EXPECT_EQ(cricket::DCT_SCTP, data_engine_->last_channel_type()); 3936 3937 webrtc::DataChannelInit config; 3938 config.id = 1; 3939 rtc::Buffer payload; 3940 webrtc::WriteDataChannelOpenMessage("a", config, &payload); 3941 cricket::ReceiveDataParams params; 3942 params.ssrc = config.id; 3943 params.type = cricket::DMT_CONTROL; 3944 3945 cricket::DataChannel* data_channel = session_->data_channel(); 3946 data_channel->SignalDataReceived(data_channel, params, payload); 3947 3948 EXPECT_EQ("a", last_data_channel_label_); 3949 EXPECT_EQ(config.id, last_data_channel_config_.id); 3950 EXPECT_FALSE(last_data_channel_config_.negotiated); 3951 EXPECT_EQ(webrtc::InternalDataChannelInit::kAcker, 3952 last_data_channel_config_.open_handshake_role); 3953 } 3954 3955 TEST_P(WebRtcSessionTest, TestUsesProvidedCertificate) { 3956 rtc::scoped_refptr<rtc::RTCCertificate> certificate = 3957 FakeDtlsIdentityStore::GenerateCertificate(); 3958 3959 PeerConnectionInterface::RTCConfiguration configuration; 3960 configuration.certificates.push_back(certificate); 3961 Init(nullptr, configuration); 3962 EXPECT_TRUE_WAIT(!session_->waiting_for_certificate_for_testing(), 1000); 3963 3964 EXPECT_EQ(session_->certificate_for_testing(), certificate); 3965 } 3966 3967 // Verifies that CreateOffer succeeds when CreateOffer is called before async 3968 // identity generation is finished (even if a certificate is provided this is 3969 // an async op). 3970 TEST_P(WebRtcSessionTest, TestCreateOfferBeforeIdentityRequestReturnSuccess) { 3971 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); 3972 InitWithDtls(GetParam()); 3973 3974 EXPECT_TRUE(session_->waiting_for_certificate_for_testing()); 3975 SendAudioVideoStream1(); 3976 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer()); 3977 3978 EXPECT_TRUE(offer != NULL); 3979 VerifyNoCryptoParams(offer->description(), true); 3980 VerifyFingerprintStatus(offer->description(), true); 3981 } 3982 3983 // Verifies that CreateAnswer succeeds when CreateOffer is called before async 3984 // identity generation is finished (even if a certificate is provided this is 3985 // an async op). 3986 TEST_P(WebRtcSessionTest, TestCreateAnswerBeforeIdentityRequestReturnSuccess) { 3987 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); 3988 InitWithDtls(GetParam()); 3989 SetFactoryDtlsSrtp(); 3990 3991 cricket::MediaSessionOptions options; 3992 options.recv_video = true; 3993 scoped_ptr<JsepSessionDescription> offer( 3994 CreateRemoteOffer(options, cricket::SEC_DISABLED)); 3995 ASSERT_TRUE(offer.get() != NULL); 3996 SetRemoteDescriptionWithoutError(offer.release()); 3997 3998 rtc::scoped_ptr<SessionDescriptionInterface> answer(CreateAnswer(NULL)); 3999 EXPECT_TRUE(answer != NULL); 4000 VerifyNoCryptoParams(answer->description(), true); 4001 VerifyFingerprintStatus(answer->description(), true); 4002 } 4003 4004 // Verifies that CreateOffer succeeds when CreateOffer is called after async 4005 // identity generation is finished (even if a certificate is provided this is 4006 // an async op). 4007 TEST_P(WebRtcSessionTest, TestCreateOfferAfterIdentityRequestReturnSuccess) { 4008 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); 4009 InitWithDtls(GetParam()); 4010 4011 EXPECT_TRUE_WAIT(!session_->waiting_for_certificate_for_testing(), 1000); 4012 4013 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer()); 4014 EXPECT_TRUE(offer != NULL); 4015 } 4016 4017 // Verifies that CreateOffer fails when CreateOffer is called after async 4018 // identity generation fails. 4019 TEST_F(WebRtcSessionTest, TestCreateOfferAfterIdentityRequestReturnFailure) { 4020 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); 4021 InitWithDtlsIdentityGenFail(); 4022 4023 EXPECT_TRUE_WAIT(!session_->waiting_for_certificate_for_testing(), 1000); 4024 4025 rtc::scoped_ptr<SessionDescriptionInterface> offer(CreateOffer()); 4026 EXPECT_TRUE(offer == NULL); 4027 } 4028 4029 // Verifies that CreateOffer succeeds when Multiple CreateOffer calls are made 4030 // before async identity generation is finished. 4031 TEST_P(WebRtcSessionTest, 4032 TestMultipleCreateOfferBeforeIdentityRequestReturnSuccess) { 4033 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); 4034 VerifyMultipleAsyncCreateDescription(GetParam(), 4035 CreateSessionDescriptionRequest::kOffer); 4036 } 4037 4038 // Verifies that CreateOffer fails when Multiple CreateOffer calls are made 4039 // before async identity generation fails. 4040 TEST_F(WebRtcSessionTest, 4041 TestMultipleCreateOfferBeforeIdentityRequestReturnFailure) { 4042 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); 4043 VerifyMultipleAsyncCreateDescriptionIdentityGenFailure( 4044 CreateSessionDescriptionRequest::kOffer); 4045 } 4046 4047 // Verifies that CreateAnswer succeeds when Multiple CreateAnswer calls are made 4048 // before async identity generation is finished. 4049 TEST_P(WebRtcSessionTest, 4050 TestMultipleCreateAnswerBeforeIdentityRequestReturnSuccess) { 4051 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); 4052 VerifyMultipleAsyncCreateDescription( 4053 GetParam(), CreateSessionDescriptionRequest::kAnswer); 4054 } 4055 4056 // Verifies that CreateAnswer fails when Multiple CreateAnswer calls are made 4057 // before async identity generation fails. 4058 TEST_F(WebRtcSessionTest, 4059 TestMultipleCreateAnswerBeforeIdentityRequestReturnFailure) { 4060 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); 4061 VerifyMultipleAsyncCreateDescriptionIdentityGenFailure( 4062 CreateSessionDescriptionRequest::kAnswer); 4063 } 4064 4065 // Verifies that setRemoteDescription fails when DTLS is disabled and the remote 4066 // offer has no SDES crypto but only DTLS fingerprint. 4067 TEST_F(WebRtcSessionTest, TestSetRemoteOfferFailIfDtlsDisabledAndNoCrypto) { 4068 // Init without DTLS. 4069 Init(); 4070 // Create a remote offer with secured transport disabled. 4071 cricket::MediaSessionOptions options; 4072 JsepSessionDescription* offer(CreateRemoteOffer( 4073 options, cricket::SEC_DISABLED)); 4074 // Adds a DTLS fingerprint to the remote offer. 4075 cricket::SessionDescription* sdp = offer->description(); 4076 TransportInfo* audio = sdp->GetTransportInfoByName("audio"); 4077 ASSERT_TRUE(audio != NULL); 4078 ASSERT_TRUE(audio->description.identity_fingerprint.get() == NULL); 4079 audio->description.identity_fingerprint.reset( 4080 rtc::SSLFingerprint::CreateFromRfc4572( 4081 rtc::DIGEST_SHA_256, kFakeDtlsFingerprint)); 4082 SetRemoteDescriptionOfferExpectError(kSdpWithoutSdesCrypto, 4083 offer); 4084 } 4085 4086 // This test verifies DSCP is properly applied on the media channels. 4087 TEST_F(WebRtcSessionTest, TestDscpConstraint) { 4088 constraints_.reset(new FakeConstraints()); 4089 constraints_->AddOptional( 4090 webrtc::MediaConstraintsInterface::kEnableDscp, true); 4091 Init(); 4092 SendAudioVideoStream1(); 4093 SessionDescriptionInterface* offer = CreateOffer(); 4094 4095 SetLocalDescriptionWithoutError(offer); 4096 4097 video_channel_ = media_engine_->GetVideoChannel(0); 4098 voice_channel_ = media_engine_->GetVoiceChannel(0); 4099 4100 ASSERT_TRUE(video_channel_ != NULL); 4101 ASSERT_TRUE(voice_channel_ != NULL); 4102 const cricket::AudioOptions& audio_options = voice_channel_->options(); 4103 const cricket::VideoOptions& video_options = video_channel_->options(); 4104 EXPECT_EQ(rtc::Optional<bool>(true), audio_options.dscp); 4105 EXPECT_EQ(rtc::Optional<bool>(true), video_options.dscp); 4106 } 4107 4108 TEST_F(WebRtcSessionTest, TestSuspendBelowMinBitrateConstraint) { 4109 constraints_.reset(new FakeConstraints()); 4110 constraints_->AddOptional( 4111 webrtc::MediaConstraintsInterface::kEnableVideoSuspendBelowMinBitrate, 4112 true); 4113 Init(); 4114 SendAudioVideoStream1(); 4115 SessionDescriptionInterface* offer = CreateOffer(); 4116 4117 SetLocalDescriptionWithoutError(offer); 4118 4119 video_channel_ = media_engine_->GetVideoChannel(0); 4120 4121 ASSERT_TRUE(video_channel_ != NULL); 4122 const cricket::VideoOptions& video_options = video_channel_->options(); 4123 EXPECT_EQ(rtc::Optional<bool>(true), video_options.suspend_below_min_bitrate); 4124 } 4125 4126 TEST_F(WebRtcSessionTest, TestNumUnsignalledRecvStreamsConstraint) { 4127 // Number of unsignalled receiving streams should be between 0 and 4128 // kMaxUnsignalledRecvStreams. 4129 SetAndVerifyNumUnsignalledRecvStreams(10, 10); 4130 SetAndVerifyNumUnsignalledRecvStreams(kMaxUnsignalledRecvStreams + 1, 4131 kMaxUnsignalledRecvStreams); 4132 SetAndVerifyNumUnsignalledRecvStreams(-1, 0); 4133 } 4134 4135 TEST_F(WebRtcSessionTest, TestCombinedAudioVideoBweConstraint) { 4136 constraints_.reset(new FakeConstraints()); 4137 constraints_->AddOptional( 4138 webrtc::MediaConstraintsInterface::kCombinedAudioVideoBwe, 4139 true); 4140 Init(); 4141 SendAudioVideoStream1(); 4142 SessionDescriptionInterface* offer = CreateOffer(); 4143 4144 SetLocalDescriptionWithoutError(offer); 4145 4146 voice_channel_ = media_engine_->GetVoiceChannel(0); 4147 4148 ASSERT_TRUE(voice_channel_ != NULL); 4149 const cricket::AudioOptions& audio_options = voice_channel_->options(); 4150 EXPECT_EQ(rtc::Optional<bool>(true), audio_options.combined_audio_video_bwe); 4151 } 4152 4153 // Tests that we can renegotiate new media content with ICE candidates in the 4154 // new remote SDP. 4155 TEST_P(WebRtcSessionTest, TestRenegotiateNewMediaWithCandidatesInSdp) { 4156 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); 4157 InitWithDtls(GetParam()); 4158 SetFactoryDtlsSrtp(); 4159 4160 SendAudioOnlyStream2(); 4161 SessionDescriptionInterface* offer = CreateOffer(); 4162 SetLocalDescriptionWithoutError(offer); 4163 4164 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer); 4165 SetRemoteDescriptionWithoutError(answer); 4166 4167 cricket::MediaSessionOptions options; 4168 options.recv_video = true; 4169 offer = CreateRemoteOffer(options, cricket::SEC_DISABLED); 4170 4171 cricket::Candidate candidate1; 4172 candidate1.set_address(rtc::SocketAddress("1.1.1.1", 5000)); 4173 candidate1.set_component(1); 4174 JsepIceCandidate ice_candidate(kMediaContentName1, kMediaContentIndex1, 4175 candidate1); 4176 EXPECT_TRUE(offer->AddCandidate(&ice_candidate)); 4177 SetRemoteDescriptionWithoutError(offer); 4178 4179 answer = CreateAnswer(NULL); 4180 SetLocalDescriptionWithoutError(answer); 4181 } 4182 4183 // Tests that we can renegotiate new media content with ICE candidates separated 4184 // from the remote SDP. 4185 TEST_P(WebRtcSessionTest, TestRenegotiateNewMediaWithCandidatesSeparated) { 4186 MAYBE_SKIP_TEST(rtc::SSLStreamAdapter::HaveDtlsSrtp); 4187 InitWithDtls(GetParam()); 4188 SetFactoryDtlsSrtp(); 4189 4190 SendAudioOnlyStream2(); 4191 SessionDescriptionInterface* offer = CreateOffer(); 4192 SetLocalDescriptionWithoutError(offer); 4193 4194 SessionDescriptionInterface* answer = CreateRemoteAnswer(offer); 4195 SetRemoteDescriptionWithoutError(answer); 4196 4197 cricket::MediaSessionOptions options; 4198 options.recv_video = true; 4199 offer = CreateRemoteOffer(options, cricket::SEC_DISABLED); 4200 SetRemoteDescriptionWithoutError(offer); 4201 4202 cricket::Candidate candidate1; 4203 candidate1.set_address(rtc::SocketAddress("1.1.1.1", 5000)); 4204 candidate1.set_component(1); 4205 JsepIceCandidate ice_candidate(kMediaContentName1, kMediaContentIndex1, 4206 candidate1); 4207 EXPECT_TRUE(session_->ProcessIceMessage(&ice_candidate)); 4208 4209 answer = CreateAnswer(NULL); 4210 SetLocalDescriptionWithoutError(answer); 4211 } 4212 // Tests that RTX codec is removed from the answer when it isn't supported 4213 // by local side. 4214 TEST_F(WebRtcSessionTest, TestRtxRemovedByCreateAnswer) { 4215 Init(); 4216 SendAudioVideoStream1(); 4217 std::string offer_sdp(kSdpWithRtx); 4218 4219 SessionDescriptionInterface* offer = 4220 CreateSessionDescription(JsepSessionDescription::kOffer, offer_sdp, NULL); 4221 EXPECT_TRUE(offer->ToString(&offer_sdp)); 4222 4223 // Offer SDP contains the RTX codec. 4224 EXPECT_TRUE(offer_sdp.find("rtx") != std::string::npos); 4225 SetRemoteDescriptionWithoutError(offer); 4226 4227 SessionDescriptionInterface* answer = CreateAnswer(NULL); 4228 std::string answer_sdp; 4229 answer->ToString(&answer_sdp); 4230 // Answer SDP removes the unsupported RTX codec. 4231 EXPECT_TRUE(answer_sdp.find("rtx") == std::string::npos); 4232 SetLocalDescriptionWithoutError(answer); 4233 } 4234 4235 // This verifies that the voice channel after bundle has both options from video 4236 // and voice channels. 4237 TEST_F(WebRtcSessionTest, TestSetSocketOptionBeforeBundle) { 4238 InitWithBundlePolicy(PeerConnectionInterface::kBundlePolicyBalanced); 4239 SendAudioVideoStream1(); 4240 4241 PeerConnectionInterface::RTCOfferAnswerOptions options; 4242 options.use_rtp_mux = true; 4243 4244 SessionDescriptionInterface* offer = CreateOffer(options); 4245 SetLocalDescriptionWithoutError(offer); 4246 4247 session_->video_channel()->SetOption(cricket::BaseChannel::ST_RTP, 4248 rtc::Socket::Option::OPT_SNDBUF, 4000); 4249 4250 session_->voice_channel()->SetOption(cricket::BaseChannel::ST_RTP, 4251 rtc::Socket::Option::OPT_RCVBUF, 8000); 4252 4253 int option_val; 4254 EXPECT_TRUE(session_->video_rtp_transport_channel()->GetOption( 4255 rtc::Socket::Option::OPT_SNDBUF, &option_val)); 4256 EXPECT_EQ(4000, option_val); 4257 EXPECT_FALSE(session_->voice_rtp_transport_channel()->GetOption( 4258 rtc::Socket::Option::OPT_SNDBUF, &option_val)); 4259 4260 EXPECT_TRUE(session_->voice_rtp_transport_channel()->GetOption( 4261 rtc::Socket::Option::OPT_RCVBUF, &option_val)); 4262 EXPECT_EQ(8000, option_val); 4263 EXPECT_FALSE(session_->video_rtp_transport_channel()->GetOption( 4264 rtc::Socket::Option::OPT_RCVBUF, &option_val)); 4265 4266 EXPECT_NE(session_->voice_rtp_transport_channel(), 4267 session_->video_rtp_transport_channel()); 4268 4269 SendAudioVideoStream2(); 4270 SessionDescriptionInterface* answer = 4271 CreateRemoteAnswer(session_->local_description()); 4272 SetRemoteDescriptionWithoutError(answer); 4273 4274 EXPECT_TRUE(session_->voice_rtp_transport_channel()->GetOption( 4275 rtc::Socket::Option::OPT_SNDBUF, &option_val)); 4276 EXPECT_EQ(4000, option_val); 4277 4278 EXPECT_TRUE(session_->voice_rtp_transport_channel()->GetOption( 4279 rtc::Socket::Option::OPT_RCVBUF, &option_val)); 4280 EXPECT_EQ(8000, option_val); 4281 } 4282 4283 // Test creating a session, request multiple offers, destroy the session 4284 // and make sure we got success/failure callbacks for all of the requests. 4285 // Background: crbug.com/507307 4286 TEST_F(WebRtcSessionTest, CreateOffersAndShutdown) { 4287 Init(); 4288 4289 rtc::scoped_refptr<WebRtcSessionCreateSDPObserverForTest> observers[100]; 4290 PeerConnectionInterface::RTCOfferAnswerOptions options; 4291 options.offer_to_receive_audio = 4292 RTCOfferAnswerOptions::kOfferToReceiveMediaTrue; 4293 cricket::MediaSessionOptions session_options; 4294 session_options.recv_audio = true; 4295 4296 for (auto& o : observers) { 4297 o = new WebRtcSessionCreateSDPObserverForTest(); 4298 session_->CreateOffer(o, options, session_options); 4299 } 4300 4301 session_.reset(); 4302 4303 for (auto& o : observers) { 4304 // We expect to have received a notification now even if the session was 4305 // terminated. The offer creation may or may not have succeeded, but we 4306 // must have received a notification which, so the only invalid state 4307 // is kInit. 4308 EXPECT_NE(WebRtcSessionCreateSDPObserverForTest::kInit, o->state()); 4309 } 4310 } 4311 4312 TEST_F(WebRtcSessionTest, TestPacketOptionsAndOnPacketSent) { 4313 TestPacketOptions(); 4314 } 4315 4316 // TODO(bemasc): Add a TestIceStatesBundle with BUNDLE enabled. That test 4317 // currently fails because upon disconnection and reconnection OnIceComplete is 4318 // called more than once without returning to IceGatheringGathering. 4319 4320 INSTANTIATE_TEST_CASE_P(WebRtcSessionTests, 4321 WebRtcSessionTest, 4322 testing::Values(ALREADY_GENERATED, 4323 DTLS_IDENTITY_STORE)); 4324