Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * libjingle | 2 * libjingle |
| 3 * Copyright 2012 Google Inc. | 3 * Copyright 2012 Google Inc. |
| 4 * | 4 * |
| 5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions are met: | 6 * modification, are permitted provided that the following conditions are met: |
| 7 * | 7 * |
| 8 * 1. Redistributions of source code must retain the above copyright notice, | 8 * 1. Redistributions of source code must retain the above copyright notice, |
| 9 * this list of conditions and the following disclaimer. | 9 * this list of conditions and the following disclaimer. |
| 10 * 2. Redistributions in binary form must reproduce the above copyright notice, | 10 * 2. Redistributions in binary form must reproduce the above copyright notice, |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
| 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 26 */ | 26 */ |
| 27 | 27 |
| 28 #include "talk/app/webrtc/webrtcsession.h" | 28 #include "talk/app/webrtc/webrtcsession.h" |
| 29 | 29 |
| 30 #include <limits.h> | 30 #include <limits.h> |
| 31 | 31 |
| 32 #include <algorithm> | 32 #include <algorithm> |
| 33 #include <vector> | 33 #include <vector> |
| 34 #include <set> | |
| 34 | 35 |
| 35 #include "talk/app/webrtc/jsepicecandidate.h" | 36 #include "talk/app/webrtc/jsepicecandidate.h" |
| 36 #include "talk/app/webrtc/jsepsessiondescription.h" | 37 #include "talk/app/webrtc/jsepsessiondescription.h" |
| 37 #include "talk/app/webrtc/mediaconstraintsinterface.h" | 38 #include "talk/app/webrtc/mediaconstraintsinterface.h" |
| 38 #include "talk/app/webrtc/mediastreamsignaling.h" | 39 #include "talk/app/webrtc/mediastreamsignaling.h" |
| 39 #include "talk/app/webrtc/peerconnectioninterface.h" | 40 #include "talk/app/webrtc/peerconnectioninterface.h" |
| 40 #include "talk/app/webrtc/webrtcsessiondescriptionfactory.h" | 41 #include "talk/app/webrtc/webrtcsessiondescriptionfactory.h" |
| 41 #include "talk/media/base/constants.h" | 42 #include "talk/media/base/constants.h" |
| 42 #include "talk/media/base/videocapturer.h" | 43 #include "talk/media/base/videocapturer.h" |
| 43 #include "talk/session/media/channel.h" | 44 #include "talk/session/media/channel.h" |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 74 const char kSdpWithoutSdesCrypto[] = | 75 const char kSdpWithoutSdesCrypto[] = |
| 75 "Called with SDP without SDES crypto."; | 76 "Called with SDP without SDES crypto."; |
| 76 const char kSdpWithoutIceUfragPwd[] = | 77 const char kSdpWithoutIceUfragPwd[] = |
| 77 "Called with SDP without ice-ufrag and ice-pwd."; | 78 "Called with SDP without ice-ufrag and ice-pwd."; |
| 78 const char kSessionError[] = "Session error code: "; | 79 const char kSessionError[] = "Session error code: "; |
| 79 const char kSessionErrorDesc[] = "Session error description: "; | 80 const char kSessionErrorDesc[] = "Session error description: "; |
| 80 const char kDtlsSetupFailureRtp[] = | 81 const char kDtlsSetupFailureRtp[] = |
| 81 "Couldn't set up DTLS-SRTP on RTP channel."; | 82 "Couldn't set up DTLS-SRTP on RTP channel."; |
| 82 const char kDtlsSetupFailureRtcp[] = | 83 const char kDtlsSetupFailureRtcp[] = |
| 83 "Couldn't set up DTLS-SRTP on RTCP channel."; | 84 "Couldn't set up DTLS-SRTP on RTCP channel."; |
| 85 const char kEnableBundleFailed[] = "Failed to enable BUNDLE."; | |
| 84 const int kMaxUnsignalledRecvStreams = 20; | 86 const int kMaxUnsignalledRecvStreams = 20; |
| 85 | 87 |
| 86 // Compares |answer| against |offer|. Comparision is done | 88 // Compares |answer| against |offer|. Comparision is done |
| 87 // for number of m-lines in answer against offer. If matches true will be | 89 // for number of m-lines in answer against offer. If matches true will be |
| 88 // returned otherwise false. | 90 // returned otherwise false. |
| 89 static bool VerifyMediaDescriptions( | 91 static bool VerifyMediaDescriptions( |
| 90 const SessionDescription* answer, const SessionDescription* offer) { | 92 const SessionDescription* answer, const SessionDescription* offer) { |
| 91 if (offer->contents().size() != answer->contents().size()) | 93 if (offer->contents().size() != answer->contents().size()) |
| 92 return false; | 94 return false; |
| 93 | 95 |
| (...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 474 WebRtcSession::WebRtcSession( | 476 WebRtcSession::WebRtcSession( |
| 475 cricket::ChannelManager* channel_manager, | 477 cricket::ChannelManager* channel_manager, |
| 476 rtc::Thread* signaling_thread, | 478 rtc::Thread* signaling_thread, |
| 477 rtc::Thread* worker_thread, | 479 rtc::Thread* worker_thread, |
| 478 cricket::PortAllocator* port_allocator, | 480 cricket::PortAllocator* port_allocator, |
| 479 MediaStreamSignaling* mediastream_signaling) | 481 MediaStreamSignaling* mediastream_signaling) |
| 480 : cricket::BaseSession(signaling_thread, | 482 : cricket::BaseSession(signaling_thread, |
| 481 worker_thread, | 483 worker_thread, |
| 482 port_allocator, | 484 port_allocator, |
| 483 rtc::ToString(rtc::CreateRandomId64() & LLONG_MAX), | 485 rtc::ToString(rtc::CreateRandomId64() & LLONG_MAX), |
| 484 cricket::NS_JINGLE_RTP, | |
| 485 false), | 486 false), |
| 486 // RFC 3264: The numeric value of the session id and version in the | 487 // RFC 3264: The numeric value of the session id and version in the |
| 487 // o line MUST be representable with a "64 bit signed integer". | 488 // o line MUST be representable with a "64 bit signed integer". |
| 488 // Due to this constraint session id |sid_| is max limited to LLONG_MAX. | 489 // Due to this constraint session id |sid_| is max limited to LLONG_MAX. |
| 489 channel_manager_(channel_manager), | 490 channel_manager_(channel_manager), |
| 490 mediastream_signaling_(mediastream_signaling), | 491 mediastream_signaling_(mediastream_signaling), |
| 491 ice_observer_(NULL), | 492 ice_observer_(NULL), |
| 492 ice_connection_state_(PeerConnectionInterface::kIceConnectionNew), | 493 ice_connection_state_(PeerConnectionInterface::kIceConnectionNew), |
| 493 ice_connection_receiving_(true), | 494 ice_connection_receiving_(true), |
| 494 older_version_remote_peer_(false), | 495 older_version_remote_peer_(false), |
| 495 dtls_enabled_(false), | 496 dtls_enabled_(false), |
| 496 data_channel_type_(cricket::DCT_NONE), | 497 data_channel_type_(cricket::DCT_NONE), |
| 497 ice_restart_latch_(new IceRestartAnswerLatch), | 498 ice_restart_latch_(new IceRestartAnswerLatch), |
| 498 metrics_observer_(NULL) { | 499 metrics_observer_(NULL) { |
| 500 transport_controller()->SignalConnectionStateChanged.connect( | |
| 501 this, &WebRtcSession::OnTransportControllerConnectionStateChanged); | |
| 502 transport_controller()->SignalReceiving.connect( | |
| 503 this, &WebRtcSession::OnTransportControllerReceiving); | |
| 504 transport_controller()->SignalCandidatesAllocationStarted.connect( | |
| 505 this, &WebRtcSession::OnTransportControllerCandidatesAllocationStarted); | |
| 506 transport_controller()->SignalCandidatesAllocationDone.connect( | |
| 507 this, &WebRtcSession::OnTransportControllerCandidatesAllocationDone); | |
| 508 transport_controller()->SignalCandidatesReady.connect( | |
| 509 this, &WebRtcSession::OnTransportControllerCandidatesReady); | |
| 499 } | 510 } |
| 500 | 511 |
| 501 WebRtcSession::~WebRtcSession() { | 512 WebRtcSession::~WebRtcSession() { |
| 502 ASSERT(signaling_thread()->IsCurrent()); | 513 ASSERT(signaling_thread()->IsCurrent()); |
| 503 // Destroy video_channel_ first since it may have a pointer to the | 514 // Destroy video_channel_ first since it may have a pointer to the |
| 504 // voice_channel_. | 515 // voice_channel_. |
| 505 if (video_channel_) { | 516 if (video_channel_) { |
| 506 SignalVideoChannelDestroyed(); | 517 SignalVideoChannelDestroyed(); |
| 507 channel_manager_->DestroyVideoChannel(video_channel_.release()); | 518 channel_manager_->DestroyVideoChannel(video_channel_.release()); |
| 508 } | 519 } |
| 509 if (voice_channel_) { | 520 if (voice_channel_) { |
| 510 SignalVoiceChannelDestroyed(); | 521 SignalVoiceChannelDestroyed(); |
| 511 channel_manager_->DestroyVoiceChannel(voice_channel_.release(), nullptr); | 522 channel_manager_->DestroyVoiceChannel(voice_channel_.release(), nullptr); |
| 512 } | 523 } |
| 513 if (data_channel_) { | 524 if (data_channel_) { |
| 514 SignalDataChannelDestroyed(); | 525 SignalDataChannelDestroyed(); |
| 515 channel_manager_->DestroyDataChannel(data_channel_.release()); | 526 channel_manager_->DestroyDataChannel(data_channel_.release()); |
| 516 } | 527 } |
| 517 for (size_t i = 0; i < saved_candidates_.size(); ++i) { | 528 for (size_t i = 0; i < saved_candidates_.size(); ++i) { |
| 518 delete saved_candidates_[i]; | 529 delete saved_candidates_[i]; |
| 519 } | 530 } |
| 520 delete identity(); | |
| 521 } | 531 } |
| 522 | 532 |
| 523 bool WebRtcSession::Initialize( | 533 bool WebRtcSession::Initialize( |
| 524 const PeerConnectionFactoryInterface::Options& options, | 534 const PeerConnectionFactoryInterface::Options& options, |
| 525 const MediaConstraintsInterface* constraints, | 535 const MediaConstraintsInterface* constraints, |
| 526 DTLSIdentityServiceInterface* dtls_identity_service, | 536 DTLSIdentityServiceInterface* dtls_identity_service, |
| 527 const PeerConnectionInterface::RTCConfiguration& rtc_configuration) { | 537 const PeerConnectionInterface::RTCConfiguration& rtc_configuration) { |
| 528 bundle_policy_ = rtc_configuration.bundle_policy; | 538 bundle_policy_ = rtc_configuration.bundle_policy; |
| 529 rtcp_mux_policy_ = rtc_configuration.rtcp_mux_policy; | 539 rtcp_mux_policy_ = rtc_configuration.rtcp_mux_policy; |
| 530 SetSslMaxProtocolVersion(options.ssl_max_version); | 540 transport_controller()->SetSslMaxProtocolVersion(options.ssl_max_version); |
| 531 | 541 |
| 532 // TODO(perkj): Take |constraints| into consideration. Return false if not all | 542 // TODO(perkj): Take |constraints| into consideration. Return false if not all |
| 533 // mandatory constraints can be fulfilled. Note that |constraints| | 543 // mandatory constraints can be fulfilled. Note that |constraints| |
| 534 // can be null. | 544 // can be null. |
| 535 bool value; | 545 bool value; |
| 536 | 546 |
| 537 if (options.disable_encryption) { | 547 if (options.disable_encryption) { |
| 538 dtls_enabled_ = false; | 548 dtls_enabled_ = false; |
| 539 } else { | 549 } else { |
| 540 // Enable DTLS by default if |dtls_identity_service| is valid. | 550 // Enable DTLS by default if |dtls_identity_service| is valid. |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 676 if (options.disable_encryption) { | 686 if (options.disable_encryption) { |
| 677 webrtc_session_desc_factory_->SetSdesPolicy(cricket::SEC_DISABLED); | 687 webrtc_session_desc_factory_->SetSdesPolicy(cricket::SEC_DISABLED); |
| 678 } | 688 } |
| 679 port_allocator()->set_candidate_filter( | 689 port_allocator()->set_candidate_filter( |
| 680 ConvertIceTransportTypeToCandidateFilter(rtc_configuration.type)); | 690 ConvertIceTransportTypeToCandidateFilter(rtc_configuration.type)); |
| 681 return true; | 691 return true; |
| 682 } | 692 } |
| 683 | 693 |
| 684 void WebRtcSession::Terminate() { | 694 void WebRtcSession::Terminate() { |
| 685 SetState(STATE_RECEIVEDTERMINATE); | 695 SetState(STATE_RECEIVEDTERMINATE); |
| 686 RemoveUnusedChannelsAndTransports(NULL); | 696 RemoveUnusedChannels(NULL); |
| 687 ASSERT(!voice_channel_); | 697 ASSERT(!voice_channel_); |
| 688 ASSERT(!video_channel_); | 698 ASSERT(!video_channel_); |
| 689 ASSERT(!data_channel_); | 699 ASSERT(!data_channel_); |
| 690 } | 700 } |
| 691 | 701 |
| 692 bool WebRtcSession::StartCandidatesAllocation() { | 702 bool WebRtcSession::StartCandidatesAllocation() { |
|
pthatcher1
2015/08/10 20:40:16
And while we're in here, we might as well call thi
Taylor Brandstetter
2015/08/11 01:20:07
Done.
| |
| 693 // SpeculativelyConnectTransportChannels, will call ConnectChannels method | |
| 694 // from TransportProxy to start gathering ice candidates. | |
| 695 SpeculativelyConnectAllTransportChannels(); | |
| 696 if (!saved_candidates_.empty()) { | 703 if (!saved_candidates_.empty()) { |
| 697 // If there are saved candidates which arrived before local description is | 704 // If there are saved candidates which arrived before local description is |
| 698 // set, copy those to remote description. | 705 // set, copy those to remote description. |
| 699 CopySavedCandidates(remote_desc_.get()); | 706 CopySavedCandidates(remote_desc_.get()); |
| 700 } | 707 } |
| 701 // Push remote candidates present in remote description to transport channels. | 708 // Push remote candidates present in remote description to transport channels. |
| 702 UseCandidatesInSessionDescription(remote_desc_.get()); | 709 UseCandidatesInSessionDescription(remote_desc_.get()); |
| 703 return true; | 710 return true; |
| 704 } | 711 } |
| 705 | 712 |
| 706 void WebRtcSession::SetSdesPolicy(cricket::SecurePolicy secure_policy) { | 713 void WebRtcSession::SetSdesPolicy(cricket::SecurePolicy secure_policy) { |
| 707 webrtc_session_desc_factory_->SetSdesPolicy(secure_policy); | 714 webrtc_session_desc_factory_->SetSdesPolicy(secure_policy); |
| 708 } | 715 } |
| 709 | 716 |
| 710 cricket::SecurePolicy WebRtcSession::SdesPolicy() const { | 717 cricket::SecurePolicy WebRtcSession::SdesPolicy() const { |
| 711 return webrtc_session_desc_factory_->SdesPolicy(); | 718 return webrtc_session_desc_factory_->SdesPolicy(); |
| 712 } | 719 } |
| 713 | 720 |
| 714 bool WebRtcSession::GetSslRole(rtc::SSLRole* role) { | 721 bool WebRtcSession::GetSslRole(rtc::SSLRole* role) { |
| 715 if (local_description() == NULL || remote_description() == NULL) { | 722 if (local_description() == NULL || remote_description() == NULL) { |
| 716 LOG(LS_INFO) << "Local and Remote descriptions must be applied to get " | 723 LOG(LS_INFO) << "Local and Remote descriptions must be applied to get " |
| 717 << "SSL Role of the session."; | 724 << "SSL Role of the session."; |
| 718 return false; | 725 return false; |
| 719 } | 726 } |
| 720 | 727 |
| 721 // TODO(mallinath) - Return role of each transport, as role may differ from | 728 return transport_controller()->GetSslRole(role); |
|
pthatcher1
2015/08/10 20:40:16
We should probably still leave the TODO about the
Taylor Brandstetter
2015/08/11 01:20:07
I left it, it just moved to transportcontroller.cc
| |
| 722 // one another. | |
| 723 // In current implementaion we just return the role of first transport in the | |
| 724 // transport map. | |
| 725 for (cricket::TransportMap::const_iterator iter = transport_proxies().begin(); | |
| 726 iter != transport_proxies().end(); ++iter) { | |
| 727 if (iter->second->impl()) { | |
| 728 return iter->second->impl()->GetSslRole(role); | |
| 729 } | |
| 730 } | |
| 731 return false; | |
| 732 } | 729 } |
| 733 | 730 |
| 734 void WebRtcSession::CreateOffer( | 731 void WebRtcSession::CreateOffer( |
| 735 CreateSessionDescriptionObserver* observer, | 732 CreateSessionDescriptionObserver* observer, |
| 736 const PeerConnectionInterface::RTCOfferAnswerOptions& options) { | 733 const PeerConnectionInterface::RTCOfferAnswerOptions& options) { |
| 737 webrtc_session_desc_factory_->CreateOffer(observer, options); | 734 webrtc_session_desc_factory_->CreateOffer(observer, options); |
| 738 } | 735 } |
| 739 | 736 |
| 740 void WebRtcSession::CreateAnswer(CreateSessionDescriptionObserver* observer, | 737 void WebRtcSession::CreateAnswer(CreateSessionDescriptionObserver* observer, |
| 741 const MediaConstraintsInterface* constraints) { | 738 const MediaConstraintsInterface* constraints) { |
| 742 webrtc_session_desc_factory_->CreateAnswer(observer, constraints); | 739 webrtc_session_desc_factory_->CreateAnswer(observer, constraints); |
| 743 } | 740 } |
| 744 | 741 |
| 745 bool WebRtcSession::SetLocalDescription(SessionDescriptionInterface* desc, | 742 bool WebRtcSession::SetLocalDescription(SessionDescriptionInterface* desc, |
| 746 std::string* err_desc) { | 743 std::string* err_desc) { |
| 744 ASSERT(signaling_thread()->IsCurrent()); | |
| 745 | |
| 747 // Takes the ownership of |desc| regardless of the result. | 746 // Takes the ownership of |desc| regardless of the result. |
| 748 rtc::scoped_ptr<SessionDescriptionInterface> desc_temp(desc); | 747 rtc::scoped_ptr<SessionDescriptionInterface> desc_temp(desc); |
| 749 | 748 |
| 750 // Validate SDP. | 749 // Validate SDP. |
| 751 if (!ValidateSessionDescription(desc, cricket::CS_LOCAL, err_desc)) { | 750 if (!ValidateSessionDescription(desc, cricket::CS_LOCAL, err_desc)) { |
| 752 return false; | 751 return false; |
| 753 } | 752 } |
| 754 | 753 |
| 755 // Update the initiator flag if this session is the initiator. | 754 // Update the initiator flag if this session is the initiator. |
| 756 Action action = GetAction(desc->type()); | 755 Action action = GetAction(desc->type()); |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 769 set_local_description(desc->description()->Copy()); | 768 set_local_description(desc->description()->Copy()); |
| 770 local_desc_.reset(desc_temp.release()); | 769 local_desc_.reset(desc_temp.release()); |
| 771 | 770 |
| 772 // Transport and Media channels will be created only when offer is set. | 771 // Transport and Media channels will be created only when offer is set. |
| 773 if (action == kOffer && !CreateChannels(local_desc_->description())) { | 772 if (action == kOffer && !CreateChannels(local_desc_->description())) { |
| 774 // TODO(mallinath) - Handle CreateChannel failure, as new local description | 773 // TODO(mallinath) - Handle CreateChannel failure, as new local description |
| 775 // is applied. Restore back to old description. | 774 // is applied. Restore back to old description. |
| 776 return BadLocalSdp(desc->type(), kCreateChannelFailed, err_desc); | 775 return BadLocalSdp(desc->type(), kCreateChannelFailed, err_desc); |
| 777 } | 776 } |
| 778 | 777 |
| 779 // Remove channel and transport proxies, if MediaContentDescription is | 778 // Enable BUNDLE before when kMaxBundle policy is in effect |
| 780 // rejected. | 779 if (bundle_policy_ == PeerConnectionInterface::kBundlePolicyMaxBundle) { |
| 781 RemoveUnusedChannelsAndTransports(local_desc_->description()); | 780 const cricket::ContentGroup* local_bundle = |
| 781 BaseSession::local_description()->GetGroupByName( | |
| 782 cricket::GROUP_TYPE_BUNDLE); | |
| 783 if (!local_bundle) { | |
| 784 LOG(LS_WARNING) << "max-bundle specified without BUNDLE specified"; | |
| 785 return false; | |
| 786 } | |
| 787 if (!EnableBundle(*local_bundle)) { | |
| 788 LOG(LS_WARNING) << "max-bundle failed to enable bundling."; | |
| 789 return false; | |
| 790 } | |
| 791 } | |
| 792 | |
| 793 // Remove transport channels if MediaContentDescription is rejected. | |
| 794 RemoveUnusedChannels(local_desc_->description()); | |
| 782 | 795 |
| 783 if (!UpdateSessionState(action, cricket::CS_LOCAL, err_desc)) { | 796 if (!UpdateSessionState(action, cricket::CS_LOCAL, err_desc)) { |
| 784 return false; | 797 return false; |
| 785 } | 798 } |
| 786 | 799 |
| 787 // Kick starting the ice candidates allocation. | 800 // Kick starting the ice candidates allocation. |
| 788 StartCandidatesAllocation(); | 801 StartCandidatesAllocation(); |
| 789 | 802 |
| 790 // Update state and SSRC of local MediaStreams and DataChannels based on the | 803 // Update state and SSRC of local MediaStreams and DataChannels based on the |
| 791 // local session description. | 804 // local session description. |
| 792 mediastream_signaling_->OnLocalDescriptionChanged(local_desc_.get()); | 805 mediastream_signaling_->OnLocalDescriptionChanged(local_desc_.get()); |
| 793 | 806 |
| 794 rtc::SSLRole role; | 807 rtc::SSLRole role; |
| 795 if (data_channel_type_ == cricket::DCT_SCTP && GetSslRole(&role)) { | 808 if (data_channel_type_ == cricket::DCT_SCTP && GetSslRole(&role)) { |
| 796 mediastream_signaling_->OnDtlsRoleReadyForSctp(role); | 809 mediastream_signaling_->OnDtlsRoleReadyForSctp(role); |
| 797 } | 810 } |
| 798 if (error() != cricket::BaseSession::ERROR_NONE) { | 811 if (error() != cricket::BaseSession::ERROR_NONE) { |
| 799 return BadLocalSdp(desc->type(), GetSessionErrorMsg(), err_desc); | 812 return BadLocalSdp(desc->type(), GetSessionErrorMsg(), err_desc); |
| 800 } | 813 } |
| 801 return true; | 814 return true; |
| 802 } | 815 } |
| 803 | 816 |
| 804 bool WebRtcSession::SetRemoteDescription(SessionDescriptionInterface* desc, | 817 bool WebRtcSession::SetRemoteDescription(SessionDescriptionInterface* desc, |
| 805 std::string* err_desc) { | 818 std::string* err_desc) { |
| 819 ASSERT(signaling_thread()->IsCurrent()); | |
| 820 | |
| 806 // Takes the ownership of |desc| regardless of the result. | 821 // Takes the ownership of |desc| regardless of the result. |
| 807 rtc::scoped_ptr<SessionDescriptionInterface> desc_temp(desc); | 822 rtc::scoped_ptr<SessionDescriptionInterface> desc_temp(desc); |
| 808 | 823 |
| 809 // Validate SDP. | 824 // Validate SDP. |
| 810 if (!ValidateSessionDescription(desc, cricket::CS_REMOTE, err_desc)) { | 825 if (!ValidateSessionDescription(desc, cricket::CS_REMOTE, err_desc)) { |
| 811 return false; | 826 return false; |
| 812 } | 827 } |
| 813 | 828 |
| 814 // Transport and Media channels will be created only when offer is set. | 829 // Transport and Media channels will be created only when offer is set. |
| 815 Action action = GetAction(desc->type()); | 830 Action action = GetAction(desc->type()); |
| 816 if (action == kOffer && !CreateChannels(desc->description())) { | 831 if (action == kOffer && !CreateChannels(desc->description())) { |
| 817 // TODO(mallinath) - Handle CreateChannel failure, as new local description | 832 // TODO(mallinath) - Handle CreateChannel failure, as new local description |
| 818 // is applied. Restore back to old description. | 833 // is applied. Restore back to old description. |
| 819 return BadRemoteSdp(desc->type(), kCreateChannelFailed, err_desc); | 834 return BadRemoteSdp(desc->type(), kCreateChannelFailed, err_desc); |
| 820 } | 835 } |
| 821 | 836 |
| 822 // Remove channel and transport proxies, if MediaContentDescription is | 837 // Remove transport channels if MediaContentDescription is rejected. |
|
pthatcher1
2015/08/10 20:40:16
I think you mean Remove channels, not transport ch
Taylor Brandstetter
2015/08/11 01:20:07
Done.
| |
| 823 // rejected. | 838 RemoveUnusedChannels(desc->description()); |
| 824 RemoveUnusedChannelsAndTransports(desc->description()); | |
| 825 | 839 |
| 826 // NOTE: Candidates allocation will be initiated only when SetLocalDescription | 840 // NOTE: Candidates allocation will be initiated only when SetLocalDescription |
| 827 // is called. | 841 // is called. |
| 828 set_remote_description(desc->description()->Copy()); | 842 set_remote_description(desc->description()->Copy()); |
| 829 if (!UpdateSessionState(action, cricket::CS_REMOTE, err_desc)) { | 843 if (!UpdateSessionState(action, cricket::CS_REMOTE, err_desc)) { |
| 830 return false; | 844 return false; |
| 831 } | 845 } |
| 832 | 846 |
| 833 // Update remote MediaStreams. | 847 // Update remote MediaStreams. |
| 834 mediastream_signaling_->OnRemoteDescriptionChanged(desc); | 848 mediastream_signaling_->OnRemoteDescriptionChanged(desc); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 873 if (desc->type() != SessionDescriptionInterface::kOffer && | 887 if (desc->type() != SessionDescriptionInterface::kOffer && |
| 874 ice_connection_state_ == PeerConnectionInterface::kIceConnectionNew) { | 888 ice_connection_state_ == PeerConnectionInterface::kIceConnectionNew) { |
| 875 SetIceConnectionState(PeerConnectionInterface::kIceConnectionChecking); | 889 SetIceConnectionState(PeerConnectionInterface::kIceConnectionChecking); |
| 876 } | 890 } |
| 877 return true; | 891 return true; |
| 878 } | 892 } |
| 879 | 893 |
| 880 bool WebRtcSession::UpdateSessionState( | 894 bool WebRtcSession::UpdateSessionState( |
| 881 Action action, cricket::ContentSource source, | 895 Action action, cricket::ContentSource source, |
| 882 std::string* err_desc) { | 896 std::string* err_desc) { |
| 897 ASSERT(signaling_thread()->IsCurrent()); | |
| 898 | |
| 883 // If there's already a pending error then no state transition should happen. | 899 // If there's already a pending error then no state transition should happen. |
| 884 // But all call-sites should be verifying this before calling us! | 900 // But all call-sites should be verifying this before calling us! |
| 885 ASSERT(error() == cricket::BaseSession::ERROR_NONE); | 901 ASSERT(error() == cricket::BaseSession::ERROR_NONE); |
| 886 std::string td_err; | 902 std::string td_err; |
| 887 if (action == kOffer) { | 903 if (action == kOffer) { |
| 888 if (!PushdownTransportDescription(source, cricket::CA_OFFER, &td_err)) { | 904 if (!PushdownTransportDescription(source, cricket::CA_OFFER, &td_err)) { |
| 889 return BadOfferSdp(source, MakeTdErrorString(td_err), err_desc); | 905 return BadOfferSdp(source, MakeTdErrorString(td_err), err_desc); |
| 890 } | 906 } |
| 891 SetState(source == cricket::CS_LOCAL ? | 907 SetState(source == cricket::CS_LOCAL ? |
| 892 STATE_SENTINITIATE : STATE_RECEIVEDINITIATE); | 908 STATE_SENTINITIATE : STATE_RECEIVEDINITIATE); |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 906 if (!PushdownMediaDescription(cricket::CA_PRANSWER, source, err_desc)) { | 922 if (!PushdownMediaDescription(cricket::CA_PRANSWER, source, err_desc)) { |
| 907 SetError(BaseSession::ERROR_CONTENT, *err_desc); | 923 SetError(BaseSession::ERROR_CONTENT, *err_desc); |
| 908 } | 924 } |
| 909 if (error() != cricket::BaseSession::ERROR_NONE) { | 925 if (error() != cricket::BaseSession::ERROR_NONE) { |
| 910 return BadPranswerSdp(source, GetSessionErrorMsg(), err_desc); | 926 return BadPranswerSdp(source, GetSessionErrorMsg(), err_desc); |
| 911 } | 927 } |
| 912 } else if (action == kAnswer) { | 928 } else if (action == kAnswer) { |
| 913 if (!PushdownTransportDescription(source, cricket::CA_ANSWER, &td_err)) { | 929 if (!PushdownTransportDescription(source, cricket::CA_ANSWER, &td_err)) { |
| 914 return BadAnswerSdp(source, MakeTdErrorString(td_err), err_desc); | 930 return BadAnswerSdp(source, MakeTdErrorString(td_err), err_desc); |
| 915 } | 931 } |
| 916 MaybeEnableMuxingSupport(); | 932 const cricket::ContentGroup* local_bundle = |
| 933 BaseSession::local_description()->GetGroupByName( | |
| 934 cricket::GROUP_TYPE_BUNDLE); | |
| 935 const cricket::ContentGroup* remote_bundle = | |
| 936 BaseSession::remote_description()->GetGroupByName( | |
| 937 cricket::GROUP_TYPE_BUNDLE); | |
| 938 if (local_bundle && remote_bundle) { | |
| 939 // The answerer decides the transport to bundle on | |
| 940 const cricket::ContentGroup* answer_bundle = ( | |
| 941 source == cricket::CS_LOCAL ? local_bundle : remote_bundle); | |
| 942 if (!EnableBundle(*answer_bundle)) { | |
| 943 LOG(LS_WARNING) << "Failed to enable BUNDLE."; | |
| 944 return BadAnswerSdp(source, kEnableBundleFailed, err_desc); | |
| 945 } | |
| 946 } | |
| 917 EnableChannels(); | 947 EnableChannels(); |
| 918 SetState(source == cricket::CS_LOCAL ? | 948 SetState(source == cricket::CS_LOCAL ? |
| 919 STATE_SENTACCEPT : STATE_RECEIVEDACCEPT); | 949 STATE_SENTACCEPT : STATE_RECEIVEDACCEPT); |
| 920 if (!PushdownMediaDescription(cricket::CA_ANSWER, source, err_desc)) { | 950 if (!PushdownMediaDescription(cricket::CA_ANSWER, source, err_desc)) { |
| 921 SetError(BaseSession::ERROR_CONTENT, *err_desc); | 951 SetError(BaseSession::ERROR_CONTENT, *err_desc); |
| 922 } | 952 } |
| 923 if (error() != cricket::BaseSession::ERROR_NONE) { | 953 if (error() != cricket::BaseSession::ERROR_NONE) { |
| 924 return BadAnswerSdp(source, GetSessionErrorMsg(), err_desc); | 954 return BadAnswerSdp(source, GetSessionErrorMsg(), err_desc); |
| 925 } | 955 } |
| 926 } | 956 } |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 955 return WebRtcSession::kPrAnswer; | 985 return WebRtcSession::kPrAnswer; |
| 956 } else if (type == SessionDescriptionInterface::kAnswer) { | 986 } else if (type == SessionDescriptionInterface::kAnswer) { |
| 957 return WebRtcSession::kAnswer; | 987 return WebRtcSession::kAnswer; |
| 958 } | 988 } |
| 959 ASSERT(false && "unknown action type"); | 989 ASSERT(false && "unknown action type"); |
| 960 return WebRtcSession::kOffer; | 990 return WebRtcSession::kOffer; |
| 961 } | 991 } |
| 962 | 992 |
| 963 bool WebRtcSession::GetTransportStats(cricket::SessionStats* stats) { | 993 bool WebRtcSession::GetTransportStats(cricket::SessionStats* stats) { |
| 964 ASSERT(signaling_thread()->IsCurrent()); | 994 ASSERT(signaling_thread()->IsCurrent()); |
| 995 return (GetChannelTransportStats(voice_channel(), stats) && | |
| 996 GetChannelTransportStats(video_channel(), stats) && | |
| 997 GetChannelTransportStats(data_channel(), stats)); | |
| 998 } | |
| 965 | 999 |
| 966 const auto get_transport_stats = [stats](const std::string& content_name, | 1000 bool WebRtcSession::GetChannelTransportStats(cricket::BaseChannel* ch, |
| 967 cricket::Transport* transport) { | 1001 cricket::SessionStats* stats) { |
| 968 const std::string& transport_id = transport->content_name(); | 1002 ASSERT(signaling_thread()->IsCurrent()); |
| 969 stats->proxy_to_transport[content_name] = transport_id; | 1003 if (!ch) { |
| 970 if (stats->transport_stats.find(transport_id) | 1004 // Not using this channel. |
| 971 != stats->transport_stats.end()) { | 1005 return true; |
| 972 // Transport stats already done for this transport. | 1006 } |
| 1007 | |
| 1008 const std::string& content_name = ch->content_name(); | |
| 1009 const std::string& transport_name = ch->transport_name(); | |
| 1010 stats->proxy_to_transport[content_name] = transport_name; | |
| 1011 if (stats->transport_stats.find(transport_name) | |
| 1012 != stats->transport_stats.end()) { | |
| 1013 // Transport stats already done for this transport. | |
| 1014 return true; | |
| 1015 } | |
| 1016 | |
| 1017 cricket::TransportStats tstats; | |
| 1018 if (!transport_controller()->GetStats(transport_name, &tstats)) { | |
| 1019 return false; | |
| 1020 } | |
| 1021 | |
| 1022 stats->transport_stats[transport_name] = tstats; | |
| 1023 return true; | |
| 1024 } | |
| 1025 | |
| 1026 bool WebRtcSession::GetIdentity(const std::string& content_name, | |
| 1027 rtc::SSLIdentity** identity) { | |
| 1028 ASSERT(signaling_thread()->IsCurrent()); | |
| 1029 | |
| 1030 cricket::BaseChannel* ch = GetChannel(content_name); | |
| 1031 if (!ch) { | |
| 1032 return false; | |
| 1033 } | |
| 1034 | |
| 1035 return transport_controller()->GetIdentity(ch->transport_name(), identity); | |
| 1036 } | |
| 1037 | |
| 1038 bool WebRtcSession::GetRemoteCertificate(const std::string& content_name, | |
| 1039 rtc::SSLCertificate** cert) { | |
| 1040 ASSERT(signaling_thread()->IsCurrent()); | |
| 1041 | |
| 1042 cricket::BaseChannel* ch = GetChannel(content_name); | |
| 1043 if (!ch) { | |
| 1044 return false; | |
| 1045 } | |
| 1046 | |
| 1047 return transport_controller()->GetRemoteCertificate(ch->transport_name(), | |
| 1048 cert); | |
| 1049 } | |
| 1050 | |
| 1051 cricket::BaseChannel* WebRtcSession::GetChannel( | |
| 1052 const std::string& content_name) { | |
| 1053 if (voice_channel() && voice_channel()->content_name() == content_name) { | |
| 1054 return voice_channel(); | |
| 1055 } | |
| 1056 if (video_channel() && video_channel()->content_name() == content_name) { | |
| 1057 return video_channel(); | |
| 1058 } | |
| 1059 if (data_channel() && data_channel()->content_name() == content_name) { | |
| 1060 return data_channel(); | |
| 1061 } | |
| 1062 return nullptr; | |
| 1063 } | |
| 1064 | |
| 1065 bool WebRtcSession::EnableBundle(const cricket::ContentGroup& bundle) { | |
| 1066 const std::string* first_content_name = bundle.FirstContentName(); | |
| 1067 if (!first_content_name) { | |
| 1068 LOG(LS_WARNING) << "Tried to BUNDLE with no contents."; | |
| 1069 return false; | |
| 1070 } | |
| 1071 const std::string& transport_name = *first_content_name; | |
| 1072 cricket::BaseChannel* first_channel = GetChannel(transport_name); | |
| 1073 | |
| 1074 auto maybe_set_transport = [this, bundle, transport_name, first_channel]( | |
| 1075 cricket::BaseChannel* ch) { | |
| 1076 if (!ch || !bundle.HasContentName(ch->content_name())) { | |
| 973 return true; | 1077 return true; |
| 974 } | 1078 } |
| 975 | 1079 |
| 976 cricket::TransportStats tstats; | 1080 if (ch->transport_name() == transport_name) { |
| 977 if (!transport->GetStats(&tstats)) { | 1081 LOG(LS_INFO) << "BUNDLE already enabled for " << ch->content_name() |
| 1082 << " on " << transport_name << "."; | |
| 1083 return true; | |
| 1084 } | |
| 1085 | |
| 1086 if (!ch->SetTransport(transport_name)) { | |
| 1087 LOG(LS_WARNING) << "Failed to enable BUNDLE for " << ch->content_name(); | |
| 978 return false; | 1088 return false; |
| 979 } | 1089 } |
| 980 | 1090 LOG(LS_INFO) << "Enabled BUNDLE for " << ch->content_name() |
| 981 stats->transport_stats[transport_id] = tstats; | 1091 << " on " << transport_name << "."; |
| 982 return true; | 1092 return true; |
| 983 }; | 1093 }; |
| 984 | 1094 |
| 985 for (const auto& kv : transport_proxies()) { | 1095 if (!maybe_set_transport(voice_channel()) || |
| 986 cricket::Transport* transport = kv.second->impl(); | 1096 !maybe_set_transport(video_channel()) || |
| 987 if (transport && !get_transport_stats(kv.first, transport)) { | 1097 !maybe_set_transport(data_channel())) { |
| 988 return false; | 1098 return false; |
| 989 } | |
| 990 } | 1099 } |
| 1100 | |
| 991 return true; | 1101 return true; |
| 992 } | 1102 } |
| 993 | 1103 |
| 994 bool WebRtcSession::ProcessIceMessage(const IceCandidateInterface* candidate) { | 1104 bool WebRtcSession::ProcessIceMessage(const IceCandidateInterface* candidate) { |
| 995 if (state() == STATE_INIT) { | 1105 if (state() == STATE_INIT) { |
| 996 LOG(LS_ERROR) << "ProcessIceMessage: ICE candidates can't be added " | 1106 LOG(LS_ERROR) << "ProcessIceMessage: ICE candidates can't be added " |
| 997 << "without any offer (local or remote) " | 1107 << "without any offer (local or remote) " |
| 998 << "session description."; | 1108 << "session description."; |
| 999 return false; | 1109 return false; |
| 1000 } | 1110 } |
| (...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1298 | 1408 |
| 1299 bool WebRtcSession::IceRestartPending() const { | 1409 bool WebRtcSession::IceRestartPending() const { |
| 1300 return ice_restart_latch_->Get(); | 1410 return ice_restart_latch_->Get(); |
| 1301 } | 1411 } |
| 1302 | 1412 |
| 1303 void WebRtcSession::ResetIceRestartLatch() { | 1413 void WebRtcSession::ResetIceRestartLatch() { |
| 1304 ice_restart_latch_->Reset(); | 1414 ice_restart_latch_->Reset(); |
| 1305 } | 1415 } |
| 1306 | 1416 |
| 1307 void WebRtcSession::OnIdentityReady(rtc::SSLIdentity* identity) { | 1417 void WebRtcSession::OnIdentityReady(rtc::SSLIdentity* identity) { |
| 1308 SetIdentity(identity); | 1418 transport_controller()->SetIdentity(identity); |
| 1309 } | 1419 } |
| 1310 | 1420 |
| 1311 bool WebRtcSession::waiting_for_identity() const { | 1421 bool WebRtcSession::waiting_for_identity() const { |
| 1312 return webrtc_session_desc_factory_->waiting_for_identity(); | 1422 return webrtc_session_desc_factory_->waiting_for_identity(); |
| 1313 } | 1423 } |
| 1314 | 1424 |
| 1315 void WebRtcSession::SetIceConnectionState( | 1425 void WebRtcSession::SetIceConnectionState( |
| 1316 PeerConnectionInterface::IceConnectionState state) { | 1426 PeerConnectionInterface::IceConnectionState state) { |
| 1317 if (ice_connection_state_ == state) { | 1427 if (ice_connection_state_ == state) { |
| 1318 return; | 1428 return; |
| 1319 } | 1429 } |
| 1320 | 1430 |
| 1321 // ASSERT that the requested transition is allowed. Note that | 1431 // ASSERT that the requested transition is allowed. Note that |
| 1322 // WebRtcSession does not implement "kIceConnectionClosed" (that is handled | 1432 // WebRtcSession does not implement "kIceConnectionClosed" (that is handled |
| 1323 // within PeerConnection). This switch statement should compile away when | 1433 // within PeerConnection). This switch statement should compile away when |
| 1324 // ASSERTs are disabled. | 1434 // ASSERTs are disabled. |
| 1435 LOG(LS_INFO) << "Changing IceConnectionState " << ice_connection_state_ | |
| 1436 << " => " << state; | |
| 1325 switch (ice_connection_state_) { | 1437 switch (ice_connection_state_) { |
| 1326 case PeerConnectionInterface::kIceConnectionNew: | 1438 case PeerConnectionInterface::kIceConnectionNew: |
| 1327 ASSERT(state == PeerConnectionInterface::kIceConnectionChecking); | 1439 ASSERT(state == PeerConnectionInterface::kIceConnectionChecking); |
| 1328 break; | 1440 break; |
| 1329 case PeerConnectionInterface::kIceConnectionChecking: | 1441 case PeerConnectionInterface::kIceConnectionChecking: |
| 1330 ASSERT(state == PeerConnectionInterface::kIceConnectionFailed || | 1442 ASSERT(state == PeerConnectionInterface::kIceConnectionFailed || |
| 1331 state == PeerConnectionInterface::kIceConnectionConnected); | 1443 state == PeerConnectionInterface::kIceConnectionConnected); |
| 1332 break; | 1444 break; |
| 1333 case PeerConnectionInterface::kIceConnectionConnected: | 1445 case PeerConnectionInterface::kIceConnectionConnected: |
| 1334 ASSERT(state == PeerConnectionInterface::kIceConnectionDisconnected || | 1446 ASSERT(state == PeerConnectionInterface::kIceConnectionDisconnected || |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 1355 ASSERT(false); | 1467 ASSERT(false); |
| 1356 break; | 1468 break; |
| 1357 } | 1469 } |
| 1358 | 1470 |
| 1359 ice_connection_state_ = state; | 1471 ice_connection_state_ = state; |
| 1360 if (ice_observer_) { | 1472 if (ice_observer_) { |
| 1361 ice_observer_->OnIceConnectionChange(ice_connection_state_); | 1473 ice_observer_->OnIceConnectionChange(ice_connection_state_); |
| 1362 } | 1474 } |
| 1363 } | 1475 } |
| 1364 | 1476 |
| 1365 void WebRtcSession::OnTransportRequestSignaling( | 1477 void WebRtcSession::OnTransportControllerConnectionStateChanged( |
| 1366 cricket::Transport* transport) { | 1478 cricket::TransportController::ConnectionState state) { |
|
pthatcher1
2015/08/10 20:40:16
It seems like this enum type should still be a Tra
Taylor Brandstetter
2015/08/11 01:20:07
Because it has a slightly different meaning than t
| |
| 1367 ASSERT(signaling_thread()->IsCurrent()); | 1479 switch (state) { |
| 1368 transport->OnSignalingReady(); | 1480 case cricket::TransportController::kConnecting: |
| 1369 if (ice_observer_) { | 1481 // If the current state is Connected or Completed, then there were |
| 1370 ice_observer_->OnIceGatheringChange( | 1482 // writable channels but now there are not, so the next state must |
| 1371 PeerConnectionInterface::kIceGatheringGathering); | 1483 // be Disconnected. |
| 1484 if (ice_connection_state_ == | |
| 1485 PeerConnectionInterface::kIceConnectionConnected || | |
| 1486 ice_connection_state_ == | |
| 1487 PeerConnectionInterface::kIceConnectionCompleted) { | |
| 1488 SetIceConnectionState( | |
| 1489 PeerConnectionInterface::kIceConnectionDisconnected); | |
|
pthatcher1
2015/08/10 20:40:16
Should it not go to checking, or maybe disconnecte
Taylor Brandstetter
2015/08/11 01:20:07
This is the behavior we had before so I kept it. A
| |
| 1490 } | |
| 1491 break; | |
| 1492 case cricket::TransportController::kFailed: | |
| 1493 SetIceConnectionState(PeerConnectionInterface::kIceConnectionFailed); | |
| 1494 break; | |
| 1495 case cricket::TransportController::kConnected: | |
| 1496 LOG(LS_INFO) << "Changing to ICE connected state because " | |
| 1497 << "all transports are writable."; | |
| 1498 SetIceConnectionState(PeerConnectionInterface::kIceConnectionConnected); | |
| 1499 break; | |
| 1500 case cricket::TransportController::kCompleted: | |
| 1501 LOG(LS_INFO) << "Changing to ICE completed state because " | |
| 1502 << "all transports are complete."; | |
| 1503 if (ice_connection_state_ != | |
| 1504 PeerConnectionInterface::kIceConnectionConnected) { | |
| 1505 // If jumping directly from "checking" to "connected", | |
| 1506 // signal "connected" first. | |
| 1507 SetIceConnectionState(PeerConnectionInterface::kIceConnectionConnected); | |
| 1508 } | |
| 1509 SetIceConnectionState(PeerConnectionInterface::kIceConnectionCompleted); | |
| 1510 if (metrics_observer_) { | |
| 1511 // Once ICE connection is completed, report stats for all transports | |
| 1512 // in use. | |
| 1513 std::set<std::string> transport_names; | |
|
pthatcher1
2015/08/10 20:40:16
Could just be a vector instead of a set.
Actually
Taylor Brandstetter
2015/08/11 01:20:07
If BUNDLE is enabled, I assumed we wouldn't want t
| |
| 1514 if (voice_channel()) { | |
| 1515 transport_names.insert(voice_channel()->transport_name()); | |
| 1516 } | |
| 1517 if (video_channel()) { | |
| 1518 transport_names.insert(video_channel()->transport_name()); | |
| 1519 } | |
| 1520 if (data_channel()) { | |
| 1521 transport_names.insert(data_channel()->transport_name()); | |
| 1522 } | |
| 1523 for (auto name : transport_names) { | |
| 1524 cricket::TransportStats stats; | |
| 1525 if (transport_controller()->GetStats(name, &stats)) { | |
| 1526 ReportBestConnectionState(stats); | |
| 1527 ReportNegotiatedCiphers(stats); | |
| 1528 } | |
| 1529 } | |
| 1530 } | |
| 1531 break; | |
| 1532 default: | |
| 1533 ASSERT(false); | |
| 1372 } | 1534 } |
| 1373 } | 1535 } |
| 1374 | 1536 |
| 1375 void WebRtcSession::OnTransportConnecting(cricket::Transport* transport) { | 1537 void WebRtcSession::OnTransportControllerReceiving(bool receiving) { |
| 1376 ASSERT(signaling_thread()->IsCurrent()); | |
| 1377 // start monitoring for the write state of the transport. | |
| 1378 OnTransportWritable(transport); | |
| 1379 } | |
| 1380 | |
| 1381 void WebRtcSession::OnTransportWritable(cricket::Transport* transport) { | |
| 1382 ASSERT(signaling_thread()->IsCurrent()); | |
| 1383 if (transport->all_channels_writable()) { | |
| 1384 SetIceConnectionState(PeerConnectionInterface::kIceConnectionConnected); | |
| 1385 } else if (transport->HasChannels()) { | |
| 1386 // If the current state is Connected or Completed, then there were writable | |
| 1387 // channels but now there are not, so the next state must be Disconnected. | |
| 1388 if (ice_connection_state_ == | |
| 1389 PeerConnectionInterface::kIceConnectionConnected || | |
| 1390 ice_connection_state_ == | |
| 1391 PeerConnectionInterface::kIceConnectionCompleted) { | |
| 1392 SetIceConnectionState( | |
| 1393 PeerConnectionInterface::kIceConnectionDisconnected); | |
| 1394 } | |
| 1395 } | |
| 1396 } | |
| 1397 | |
| 1398 void WebRtcSession::OnTransportCompleted(cricket::Transport* transport) { | |
| 1399 ASSERT(signaling_thread()->IsCurrent()); | |
| 1400 PeerConnectionInterface::IceConnectionState old_state = ice_connection_state_; | |
| 1401 SetIceConnectionState(PeerConnectionInterface::kIceConnectionCompleted); | |
| 1402 // Only report once when Ice connection is completed. | |
| 1403 if (old_state != PeerConnectionInterface::kIceConnectionCompleted) { | |
| 1404 cricket::TransportStats stats; | |
| 1405 if (metrics_observer_ && transport->GetStats(&stats)) { | |
| 1406 ReportBestConnectionState(stats); | |
| 1407 ReportNegotiatedCiphers(stats); | |
| 1408 } | |
| 1409 } | |
| 1410 } | |
| 1411 | |
| 1412 void WebRtcSession::OnTransportFailed(cricket::Transport* transport) { | |
| 1413 ASSERT(signaling_thread()->IsCurrent()); | |
| 1414 SetIceConnectionState(PeerConnectionInterface::kIceConnectionFailed); | |
| 1415 } | |
| 1416 | |
| 1417 void WebRtcSession::OnTransportReceiving(cricket::Transport* transport) { | |
| 1418 ASSERT(signaling_thread()->IsCurrent()); | |
| 1419 // The ice connection is considered receiving if at least one transport is | |
| 1420 // receiving on any channels. | |
| 1421 bool receiving = false; | |
| 1422 for (const auto& kv : transport_proxies()) { | |
| 1423 cricket::Transport* transport = kv.second->impl(); | |
| 1424 if (transport && transport->any_channel_receiving()) { | |
| 1425 receiving = true; | |
| 1426 break; | |
| 1427 } | |
| 1428 } | |
| 1429 SetIceConnectionReceiving(receiving); | 1538 SetIceConnectionReceiving(receiving); |
| 1430 } | 1539 } |
| 1431 | 1540 |
| 1432 void WebRtcSession::SetIceConnectionReceiving(bool receiving) { | 1541 void WebRtcSession::SetIceConnectionReceiving(bool receiving) { |
| 1433 if (ice_connection_receiving_ == receiving) { | 1542 if (ice_connection_receiving_ == receiving) { |
| 1434 return; | 1543 return; |
| 1435 } | 1544 } |
| 1436 ice_connection_receiving_ = receiving; | 1545 ice_connection_receiving_ = receiving; |
| 1437 if (ice_observer_) { | 1546 if (ice_observer_) { |
| 1438 ice_observer_->OnIceConnectionReceivingChange(receiving); | 1547 ice_observer_->OnIceConnectionReceivingChange(receiving); |
| 1439 } | 1548 } |
| 1440 } | 1549 } |
| 1441 | 1550 |
| 1442 void WebRtcSession::OnTransportProxyCandidatesReady( | 1551 void WebRtcSession::OnTransportControllerCandidatesReady( |
| 1443 cricket::TransportProxy* proxy, const cricket::Candidates& candidates) { | 1552 const std::string& transport_name, const cricket::Candidates& candidates) { |
| 1444 ASSERT(signaling_thread()->IsCurrent()); | 1553 ASSERT(signaling_thread()->IsCurrent()); |
| 1445 ProcessNewLocalCandidate(proxy->content_name(), candidates); | 1554 ProcessNewLocalCandidate(transport_name, candidates); |
|
pthatcher1
2015/08/10 20:40:16
Could we just put the ProcessNewLocalCandidate cod
Taylor Brandstetter
2015/08/11 01:20:07
Done.
| |
| 1446 } | |
| 1447 | |
| 1448 void WebRtcSession::OnCandidatesAllocationDone() { | |
| 1449 ASSERT(signaling_thread()->IsCurrent()); | |
| 1450 if (ice_observer_) { | |
| 1451 ice_observer_->OnIceGatheringChange( | |
| 1452 PeerConnectionInterface::kIceGatheringComplete); | |
| 1453 ice_observer_->OnIceComplete(); | |
| 1454 } | |
| 1455 } | 1555 } |
| 1456 | 1556 |
| 1457 // Enabling voice and video channel. | 1557 // Enabling voice and video channel. |
| 1458 void WebRtcSession::EnableChannels() { | 1558 void WebRtcSession::EnableChannels() { |
| 1459 if (voice_channel_ && !voice_channel_->enabled()) | 1559 if (voice_channel_ && !voice_channel_->enabled()) |
| 1460 voice_channel_->Enable(true); | 1560 voice_channel_->Enable(true); |
| 1461 | 1561 |
| 1462 if (video_channel_ && !video_channel_->enabled()) | 1562 if (video_channel_ && !video_channel_->enabled()) |
| 1463 video_channel_->Enable(true); | 1563 video_channel_->Enable(true); |
| 1464 | 1564 |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1542 size_t mediacontent_index = static_cast<size_t>(candidate->sdp_mline_index()); | 1642 size_t mediacontent_index = static_cast<size_t>(candidate->sdp_mline_index()); |
| 1543 size_t remote_content_size = base_remote_description()->contents().size(); | 1643 size_t remote_content_size = base_remote_description()->contents().size(); |
| 1544 if (mediacontent_index >= remote_content_size) { | 1644 if (mediacontent_index >= remote_content_size) { |
| 1545 LOG(LS_ERROR) | 1645 LOG(LS_ERROR) |
| 1546 << "UseRemoteCandidateInSession: Invalid candidate media index."; | 1646 << "UseRemoteCandidateInSession: Invalid candidate media index."; |
| 1547 return false; | 1647 return false; |
| 1548 } | 1648 } |
| 1549 | 1649 |
| 1550 cricket::ContentInfo content = | 1650 cricket::ContentInfo content = |
| 1551 base_remote_description()->contents()[mediacontent_index]; | 1651 base_remote_description()->contents()[mediacontent_index]; |
| 1652 | |
| 1552 std::vector<cricket::Candidate> candidates; | 1653 std::vector<cricket::Candidate> candidates; |
| 1553 candidates.push_back(candidate->candidate()); | 1654 candidates.push_back(candidate->candidate()); |
| 1554 // Invoking BaseSession method to handle remote candidates. | 1655 // Invoking BaseSession method to handle remote candidates. |
| 1555 std::string error; | 1656 std::string error; |
| 1556 if (OnRemoteCandidates(content.name, candidates, &error)) { | 1657 if (transport_controller()->AddRemoteCandidates( |
| 1658 content.name, candidates, &error)) { | |
| 1557 // Candidates successfully submitted for checking. | 1659 // Candidates successfully submitted for checking. |
| 1558 if (ice_connection_state_ == PeerConnectionInterface::kIceConnectionNew || | 1660 if (ice_connection_state_ == PeerConnectionInterface::kIceConnectionNew || |
| 1559 ice_connection_state_ == | 1661 ice_connection_state_ == |
| 1560 PeerConnectionInterface::kIceConnectionDisconnected) { | 1662 PeerConnectionInterface::kIceConnectionDisconnected) { |
| 1561 // If state is New, then the session has just gotten its first remote ICE | 1663 // If state is New, then the session has just gotten its first remote ICE |
| 1562 // candidates, so go to Checking. | 1664 // candidates, so go to Checking. |
| 1563 // If state is Disconnected, the session is re-using old candidates or | 1665 // If state is Disconnected, the session is re-using old candidates or |
| 1564 // receiving additional ones, so go to Checking. | 1666 // receiving additional ones, so go to Checking. |
| 1565 // If state is Connected, stay Connected. | 1667 // If state is Connected, stay Connected. |
| 1566 // TODO(bemasc): If state is Connected, and the new candidates are for a | 1668 // TODO(bemasc): If state is Connected, and the new candidates are for a |
| 1567 // newly added transport, then the state actually _should_ move to | 1669 // newly added transport, then the state actually _should_ move to |
| 1568 // checking. Add a way to distinguish that case. | 1670 // checking. Add a way to distinguish that case. |
| 1569 SetIceConnectionState(PeerConnectionInterface::kIceConnectionChecking); | 1671 SetIceConnectionState(PeerConnectionInterface::kIceConnectionChecking); |
| 1570 } | 1672 } |
| 1571 // TODO(bemasc): If state is Completed, go back to Connected. | 1673 // TODO(bemasc): If state is Completed, go back to Connected. |
| 1572 } else { | 1674 } else { |
| 1573 if (!error.empty()) { | 1675 if (!error.empty()) { |
| 1574 LOG(LS_WARNING) << error; | 1676 LOG(LS_WARNING) << error; |
| 1575 } | 1677 } |
| 1576 } | 1678 } |
| 1577 return true; | 1679 return true; |
| 1578 } | 1680 } |
| 1579 | 1681 |
| 1580 void WebRtcSession::RemoveUnusedChannelsAndTransports( | 1682 void WebRtcSession::RemoveUnusedChannels( |
| 1581 const SessionDescription* desc) { | 1683 const SessionDescription* desc) { |
| 1582 // Destroy video_channel_ first since it may have a pointer to the | 1684 // Destroy video_channel_ first since it may have a pointer to the |
| 1583 // voice_channel_. | 1685 // voice_channel_. |
| 1584 const cricket::ContentInfo* video_info = | 1686 const cricket::ContentInfo* video_info = |
| 1585 cricket::GetFirstVideoContent(desc); | 1687 cricket::GetFirstVideoContent(desc); |
| 1586 if ((!video_info || video_info->rejected) && video_channel_) { | 1688 if ((!video_info || video_info->rejected) && video_channel_) { |
| 1587 mediastream_signaling_->OnVideoChannelClose(); | 1689 mediastream_signaling_->OnVideoChannelClose(); |
| 1588 SignalVideoChannelDestroyed(); | 1690 SignalVideoChannelDestroyed(); |
| 1589 const std::string content_name = video_channel_->content_name(); | 1691 const std::string content_name = video_channel_->content_name(); |
| 1590 channel_manager_->DestroyVideoChannel(video_channel_.release()); | 1692 channel_manager_->DestroyVideoChannel(video_channel_.release()); |
| 1591 DestroyTransportProxy(content_name); | |
| 1592 } | 1693 } |
| 1593 | 1694 |
| 1594 const cricket::ContentInfo* voice_info = | 1695 const cricket::ContentInfo* voice_info = |
| 1595 cricket::GetFirstAudioContent(desc); | 1696 cricket::GetFirstAudioContent(desc); |
| 1596 if ((!voice_info || voice_info->rejected) && voice_channel_) { | 1697 if ((!voice_info || voice_info->rejected) && voice_channel_) { |
| 1597 mediastream_signaling_->OnAudioChannelClose(); | 1698 mediastream_signaling_->OnAudioChannelClose(); |
| 1598 SignalVoiceChannelDestroyed(); | 1699 SignalVoiceChannelDestroyed(); |
| 1599 const std::string content_name = voice_channel_->content_name(); | 1700 const std::string content_name = voice_channel_->content_name(); |
| 1600 channel_manager_->DestroyVoiceChannel(voice_channel_.release(), | 1701 channel_manager_->DestroyVoiceChannel(voice_channel_.release(), |
| 1601 video_channel_.get()); | 1702 video_channel_.get()); |
| 1602 DestroyTransportProxy(content_name); | |
| 1603 } | 1703 } |
| 1604 | 1704 |
| 1605 const cricket::ContentInfo* data_info = | 1705 const cricket::ContentInfo* data_info = |
| 1606 cricket::GetFirstDataContent(desc); | 1706 cricket::GetFirstDataContent(desc); |
| 1607 if ((!data_info || data_info->rejected) && data_channel_) { | 1707 if ((!data_info || data_info->rejected) && data_channel_) { |
| 1608 mediastream_signaling_->OnDataChannelClose(); | 1708 mediastream_signaling_->OnDataChannelClose(); |
| 1609 SignalDataChannelDestroyed(); | 1709 SignalDataChannelDestroyed(); |
| 1610 const std::string content_name = data_channel_->content_name(); | 1710 const std::string content_name = data_channel_->content_name(); |
| 1611 channel_manager_->DestroyDataChannel(data_channel_.release()); | 1711 channel_manager_->DestroyDataChannel(data_channel_.release()); |
| 1612 DestroyTransportProxy(content_name); | |
| 1613 } | 1712 } |
| 1614 } | 1713 } |
| 1615 | 1714 |
| 1616 // TODO(mallinath) - Add a correct error code if the channels are not creatued | 1715 // TODO(mallinath) - Add a correct error code if the channels are not creatued |
| 1617 // due to BUNDLE is enabled but rtcp-mux is disabled. | 1716 // due to BUNDLE is enabled but rtcp-mux is disabled. |
| 1618 bool WebRtcSession::CreateChannels(const SessionDescription* desc) { | 1717 bool WebRtcSession::CreateChannels(const SessionDescription* desc) { |
| 1619 // Creating the media channels and transport proxies. | 1718 // Creating the media channels and transport proxies. |
| 1620 const cricket::ContentInfo* voice = cricket::GetFirstAudioContent(desc); | 1719 const cricket::ContentInfo* voice = cricket::GetFirstAudioContent(desc); |
| 1621 if (voice && !voice->rejected && !voice_channel_) { | 1720 if (voice && !voice->rejected && !voice_channel_) { |
| 1622 if (!CreateVoiceChannel(voice)) { | 1721 if (!CreateVoiceChannel(voice)) { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1655 } | 1754 } |
| 1656 | 1755 |
| 1657 // Enable bundle before when kMaxBundle policy is in effect. | 1756 // Enable bundle before when kMaxBundle policy is in effect. |
| 1658 if (bundle_policy_ == PeerConnectionInterface::kBundlePolicyMaxBundle) { | 1757 if (bundle_policy_ == PeerConnectionInterface::kBundlePolicyMaxBundle) { |
| 1659 const cricket::ContentGroup* bundle_group = desc->GetGroupByName( | 1758 const cricket::ContentGroup* bundle_group = desc->GetGroupByName( |
| 1660 cricket::GROUP_TYPE_BUNDLE); | 1759 cricket::GROUP_TYPE_BUNDLE); |
| 1661 if (!bundle_group) { | 1760 if (!bundle_group) { |
| 1662 LOG(LS_WARNING) << "max-bundle specified without BUNDLE specified"; | 1761 LOG(LS_WARNING) << "max-bundle specified without BUNDLE specified"; |
| 1663 return false; | 1762 return false; |
| 1664 } | 1763 } |
| 1665 if (!BaseSession::BundleContentGroup(bundle_group)) { | 1764 if (!EnableBundle(*bundle_group)) { |
| 1666 LOG(LS_WARNING) << "max-bundle failed to enable bundling."; | 1765 LOG(LS_WARNING) << "max-bundle failed to enable bundling."; |
| 1667 return false; | 1766 return false; |
| 1668 } | 1767 } |
| 1669 } | 1768 } |
| 1670 | 1769 |
| 1671 return true; | 1770 return true; |
| 1672 } | 1771 } |
| 1673 | 1772 |
| 1674 bool WebRtcSession::CreateVoiceChannel(const cricket::ContentInfo* content) { | 1773 bool WebRtcSession::CreateVoiceChannel(const cricket::ContentInfo* content) { |
| 1675 voice_channel_.reset(channel_manager_->CreateVoiceChannel( | 1774 voice_channel_.reset(channel_manager_->CreateVoiceChannel( |
| 1676 this, content->name, true, audio_options_)); | 1775 transport_controller(), content->name, true, audio_options_)); |
| 1677 if (!voice_channel_) { | 1776 if (!voice_channel_) { |
| 1678 return false; | 1777 return false; |
| 1679 } | 1778 } |
| 1680 | 1779 |
| 1681 voice_channel_->SignalDtlsSetupFailure.connect( | 1780 voice_channel_->SignalDtlsSetupFailure.connect( |
| 1682 this, &WebRtcSession::OnDtlsSetupFailure); | 1781 this, &WebRtcSession::OnDtlsSetupFailure); |
| 1683 return true; | 1782 return true; |
| 1684 } | 1783 } |
| 1685 | 1784 |
| 1686 bool WebRtcSession::CreateVideoChannel(const cricket::ContentInfo* content) { | 1785 bool WebRtcSession::CreateVideoChannel(const cricket::ContentInfo* content) { |
| 1687 video_channel_.reset(channel_manager_->CreateVideoChannel( | 1786 video_channel_.reset(channel_manager_->CreateVideoChannel( |
| 1688 this, content->name, true, video_options_, voice_channel_.get())); | 1787 transport_controller(), content->name, true, |
| 1788 video_options_, voice_channel_.get())); | |
| 1689 if (!video_channel_) { | 1789 if (!video_channel_) { |
| 1690 return false; | 1790 return false; |
| 1691 } | 1791 } |
| 1692 | 1792 |
| 1693 video_channel_->SignalDtlsSetupFailure.connect( | 1793 video_channel_->SignalDtlsSetupFailure.connect( |
| 1694 this, &WebRtcSession::OnDtlsSetupFailure); | 1794 this, &WebRtcSession::OnDtlsSetupFailure); |
| 1695 return true; | 1795 return true; |
| 1696 } | 1796 } |
| 1697 | 1797 |
| 1698 bool WebRtcSession::CreateDataChannel(const cricket::ContentInfo* content) { | 1798 bool WebRtcSession::CreateDataChannel(const cricket::ContentInfo* content) { |
| 1699 bool sctp = (data_channel_type_ == cricket::DCT_SCTP); | 1799 bool sctp = (data_channel_type_ == cricket::DCT_SCTP); |
| 1700 data_channel_.reset(channel_manager_->CreateDataChannel( | 1800 data_channel_.reset(channel_manager_->CreateDataChannel( |
| 1701 this, content->name, !sctp, data_channel_type_)); | 1801 transport_controller(), content->name, !sctp, data_channel_type_)); |
| 1702 if (!data_channel_) { | 1802 if (!data_channel_) { |
| 1703 return false; | 1803 return false; |
| 1704 } | 1804 } |
| 1705 | 1805 |
| 1706 if (sctp) { | 1806 if (sctp) { |
| 1707 mediastream_signaling_->OnDataTransportCreatedForSctp(); | 1807 mediastream_signaling_->OnDataTransportCreatedForSctp(); |
| 1708 data_channel_->SignalDataReceived.connect( | 1808 data_channel_->SignalDataReceived.connect( |
| 1709 this, &WebRtcSession::OnDataChannelMessageReceived); | 1809 this, &WebRtcSession::OnDataChannelMessageReceived); |
| 1710 data_channel_->SignalStreamClosedRemotely.connect( | 1810 data_channel_->SignalStreamClosedRemotely.connect( |
| 1711 mediastream_signaling_, | 1811 mediastream_signaling_, |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1872 // We need to check the local/remote description for the Transport instead of | 1972 // We need to check the local/remote description for the Transport instead of |
| 1873 // the session, because a new Transport added during renegotiation may have | 1973 // the session, because a new Transport added during renegotiation may have |
| 1874 // them unset while the session has them set from the previous negotiation. | 1974 // them unset while the session has them set from the previous negotiation. |
| 1875 // Not doing so may trigger the auto generation of transport description and | 1975 // Not doing so may trigger the auto generation of transport description and |
| 1876 // mess up DTLS identity information, ICE credential, etc. | 1976 // mess up DTLS identity information, ICE credential, etc. |
| 1877 bool WebRtcSession::ReadyToUseRemoteCandidate( | 1977 bool WebRtcSession::ReadyToUseRemoteCandidate( |
| 1878 const IceCandidateInterface* candidate, | 1978 const IceCandidateInterface* candidate, |
| 1879 const SessionDescriptionInterface* remote_desc, | 1979 const SessionDescriptionInterface* remote_desc, |
| 1880 bool* valid) { | 1980 bool* valid) { |
| 1881 *valid = true;; | 1981 *valid = true;; |
| 1882 cricket::TransportProxy* transport_proxy = NULL; | |
| 1883 | 1982 |
| 1884 const SessionDescriptionInterface* current_remote_desc = | 1983 const SessionDescriptionInterface* current_remote_desc = |
| 1885 remote_desc ? remote_desc : remote_description(); | 1984 remote_desc ? remote_desc : remote_description(); |
| 1886 | 1985 |
| 1887 if (!current_remote_desc) | 1986 if (!current_remote_desc) |
| 1888 return false; | 1987 return false; |
| 1889 | 1988 |
| 1890 size_t mediacontent_index = | 1989 size_t mediacontent_index = |
| 1891 static_cast<size_t>(candidate->sdp_mline_index()); | 1990 static_cast<size_t>(candidate->sdp_mline_index()); |
| 1892 size_t remote_content_size = | 1991 size_t remote_content_size = |
| 1893 current_remote_desc->description()->contents().size(); | 1992 current_remote_desc->description()->contents().size(); |
| 1894 if (mediacontent_index >= remote_content_size) { | 1993 if (mediacontent_index >= remote_content_size) { |
| 1895 LOG(LS_ERROR) | 1994 LOG(LS_ERROR) |
| 1896 << "ReadyToUseRemoteCandidate: Invalid candidate media index."; | 1995 << "ReadyToUseRemoteCandidate: Invalid candidate media index."; |
| 1897 | 1996 |
| 1898 *valid = false; | 1997 *valid = false; |
| 1899 return false; | 1998 return false; |
| 1900 } | 1999 } |
| 1901 | 2000 |
| 1902 cricket::ContentInfo content = | 2001 cricket::ContentInfo content = |
| 1903 current_remote_desc->description()->contents()[mediacontent_index]; | 2002 current_remote_desc->description()->contents()[mediacontent_index]; |
| 1904 transport_proxy = GetTransportProxy(content.name); | 2003 cricket::BaseChannel* channel = GetChannel(content.name); |
| 2004 if (!channel) { | |
| 2005 return false; | |
| 2006 } | |
| 1905 | 2007 |
| 1906 return transport_proxy && transport_proxy->local_description_set() && | 2008 return transport_controller()->ReadyForRemoteCandidates( |
| 1907 transport_proxy->remote_description_set(); | 2009 channel->transport_name()); |
| 2010 } | |
| 2011 | |
| 2012 void WebRtcSession::OnTransportControllerCandidatesAllocationStarted() { | |
| 2013 ASSERT(signaling_thread()->IsCurrent()); | |
| 2014 if (ice_observer_) { | |
| 2015 ice_observer_->OnIceGatheringChange( | |
| 2016 PeerConnectionInterface::kIceGatheringGathering); | |
| 2017 } | |
| 2018 } | |
| 2019 | |
| 2020 void WebRtcSession::OnTransportControllerCandidatesAllocationDone() { | |
| 2021 ASSERT(signaling_thread()->IsCurrent()); | |
| 2022 if (ice_observer_) { | |
| 2023 ice_observer_->OnIceGatheringChange( | |
| 2024 PeerConnectionInterface::kIceGatheringComplete); | |
| 2025 ice_observer_->OnIceComplete(); | |
| 2026 } | |
| 1908 } | 2027 } |
| 1909 | 2028 |
| 1910 // Walk through the ConnectionInfos to gather best connection usage | 2029 // Walk through the ConnectionInfos to gather best connection usage |
| 1911 // for IPv4 and IPv6. | 2030 // for IPv4 and IPv6. |
| 1912 void WebRtcSession::ReportBestConnectionState( | 2031 void WebRtcSession::ReportBestConnectionState( |
| 1913 const cricket::TransportStats& stats) { | 2032 const cricket::TransportStats& stats) { |
| 1914 DCHECK(metrics_observer_ != NULL); | 2033 DCHECK(metrics_observer_ != NULL); |
| 1915 for (cricket::TransportChannelStatsList::const_iterator it = | 2034 for (cricket::TransportChannelStatsList::const_iterator it = |
| 1916 stats.channel_stats.begin(); | 2035 stats.channel_stats.begin(); |
| 1917 it != stats.channel_stats.end(); ++it) { | 2036 it != stats.channel_stats.end(); ++it) { |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1965 | 2084 |
| 1966 if (!srtp_cipher.empty()) { | 2085 if (!srtp_cipher.empty()) { |
| 1967 metrics_observer_->AddHistogramSample(srtp_name, srtp_cipher); | 2086 metrics_observer_->AddHistogramSample(srtp_name, srtp_cipher); |
| 1968 } | 2087 } |
| 1969 if (!ssl_cipher.empty()) { | 2088 if (!ssl_cipher.empty()) { |
| 1970 metrics_observer_->AddHistogramSample(ssl_name, ssl_cipher); | 2089 metrics_observer_->AddHistogramSample(ssl_name, ssl_cipher); |
| 1971 } | 2090 } |
| 1972 } | 2091 } |
| 1973 | 2092 |
| 1974 } // namespace webrtc | 2093 } // namespace webrtc |
| OLD | NEW |