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()->SignalConnectionState.connect( |
| 501 this, &WebRtcSession::OnTransportControllerConnectionState); |
| 502 transport_controller()->SignalReceiving.connect( |
| 503 this, &WebRtcSession::OnTransportControllerReceiving); |
| 504 transport_controller()->SignalGatheringState.connect( |
| 505 this, &WebRtcSession::OnTransportControllerGatheringState); |
| 506 transport_controller()->SignalCandidatesGathered.connect( |
| 507 this, &WebRtcSession::OnTransportControllerCandidatesGathered); |
499 } | 508 } |
500 | 509 |
501 WebRtcSession::~WebRtcSession() { | 510 WebRtcSession::~WebRtcSession() { |
502 ASSERT(signaling_thread()->IsCurrent()); | 511 ASSERT(signaling_thread()->IsCurrent()); |
503 // Destroy video_channel_ first since it may have a pointer to the | 512 // Destroy video_channel_ first since it may have a pointer to the |
504 // voice_channel_. | 513 // voice_channel_. |
505 if (video_channel_) { | 514 if (video_channel_) { |
506 SignalVideoChannelDestroyed(); | 515 SignalVideoChannelDestroyed(); |
507 channel_manager_->DestroyVideoChannel(video_channel_.release()); | 516 channel_manager_->DestroyVideoChannel(video_channel_.release()); |
508 } | 517 } |
509 if (voice_channel_) { | 518 if (voice_channel_) { |
510 SignalVoiceChannelDestroyed(); | 519 SignalVoiceChannelDestroyed(); |
511 channel_manager_->DestroyVoiceChannel(voice_channel_.release(), nullptr); | 520 channel_manager_->DestroyVoiceChannel(voice_channel_.release(), nullptr); |
512 } | 521 } |
513 if (data_channel_) { | 522 if (data_channel_) { |
514 SignalDataChannelDestroyed(); | 523 SignalDataChannelDestroyed(); |
515 channel_manager_->DestroyDataChannel(data_channel_.release()); | 524 channel_manager_->DestroyDataChannel(data_channel_.release()); |
516 } | 525 } |
517 for (size_t i = 0; i < saved_candidates_.size(); ++i) { | 526 for (size_t i = 0; i < saved_candidates_.size(); ++i) { |
518 delete saved_candidates_[i]; | 527 delete saved_candidates_[i]; |
519 } | 528 } |
520 delete identity(); | |
521 } | 529 } |
522 | 530 |
523 bool WebRtcSession::Initialize( | 531 bool WebRtcSession::Initialize( |
524 const PeerConnectionFactoryInterface::Options& options, | 532 const PeerConnectionFactoryInterface::Options& options, |
525 const MediaConstraintsInterface* constraints, | 533 const MediaConstraintsInterface* constraints, |
526 DTLSIdentityServiceInterface* dtls_identity_service, | 534 DTLSIdentityServiceInterface* dtls_identity_service, |
527 const PeerConnectionInterface::RTCConfiguration& rtc_configuration) { | 535 const PeerConnectionInterface::RTCConfiguration& rtc_configuration) { |
528 bundle_policy_ = rtc_configuration.bundle_policy; | 536 bundle_policy_ = rtc_configuration.bundle_policy; |
529 rtcp_mux_policy_ = rtc_configuration.rtcp_mux_policy; | 537 rtcp_mux_policy_ = rtc_configuration.rtcp_mux_policy; |
530 SetSslMaxProtocolVersion(options.ssl_max_version); | 538 transport_controller()->SetSslMaxProtocolVersion(options.ssl_max_version); |
531 | 539 |
532 // TODO(perkj): Take |constraints| into consideration. Return false if not all | 540 // TODO(perkj): Take |constraints| into consideration. Return false if not all |
533 // mandatory constraints can be fulfilled. Note that |constraints| | 541 // mandatory constraints can be fulfilled. Note that |constraints| |
534 // can be null. | 542 // can be null. |
535 bool value; | 543 bool value; |
536 | 544 |
537 if (options.disable_encryption) { | 545 if (options.disable_encryption) { |
538 dtls_enabled_ = false; | 546 dtls_enabled_ = false; |
539 } else { | 547 } else { |
540 // Enable DTLS by default if |dtls_identity_service| is valid. | 548 // 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) { | 684 if (options.disable_encryption) { |
677 webrtc_session_desc_factory_->SetSdesPolicy(cricket::SEC_DISABLED); | 685 webrtc_session_desc_factory_->SetSdesPolicy(cricket::SEC_DISABLED); |
678 } | 686 } |
679 port_allocator()->set_candidate_filter( | 687 port_allocator()->set_candidate_filter( |
680 ConvertIceTransportTypeToCandidateFilter(rtc_configuration.type)); | 688 ConvertIceTransportTypeToCandidateFilter(rtc_configuration.type)); |
681 return true; | 689 return true; |
682 } | 690 } |
683 | 691 |
684 void WebRtcSession::Terminate() { | 692 void WebRtcSession::Terminate() { |
685 SetState(STATE_RECEIVEDTERMINATE); | 693 SetState(STATE_RECEIVEDTERMINATE); |
686 RemoveUnusedChannelsAndTransports(NULL); | 694 RemoveUnusedChannels(NULL); |
687 ASSERT(!voice_channel_); | 695 ASSERT(!voice_channel_); |
688 ASSERT(!video_channel_); | 696 ASSERT(!video_channel_); |
689 ASSERT(!data_channel_); | 697 ASSERT(!data_channel_); |
690 } | 698 } |
691 | 699 |
692 bool WebRtcSession::StartCandidatesAllocation() { | |
693 // SpeculativelyConnectTransportChannels, will call ConnectChannels method | |
694 // from TransportProxy to start gathering ice candidates. | |
695 SpeculativelyConnectAllTransportChannels(); | |
696 if (!saved_candidates_.empty()) { | |
697 // If there are saved candidates which arrived before local description is | |
698 // set, copy those to remote description. | |
699 CopySavedCandidates(remote_desc_.get()); | |
700 } | |
701 // Push remote candidates present in remote description to transport channels. | |
702 UseCandidatesInSessionDescription(remote_desc_.get()); | |
703 return true; | |
704 } | |
705 | |
706 void WebRtcSession::SetSdesPolicy(cricket::SecurePolicy secure_policy) { | 700 void WebRtcSession::SetSdesPolicy(cricket::SecurePolicy secure_policy) { |
707 webrtc_session_desc_factory_->SetSdesPolicy(secure_policy); | 701 webrtc_session_desc_factory_->SetSdesPolicy(secure_policy); |
708 } | 702 } |
709 | 703 |
710 cricket::SecurePolicy WebRtcSession::SdesPolicy() const { | 704 cricket::SecurePolicy WebRtcSession::SdesPolicy() const { |
711 return webrtc_session_desc_factory_->SdesPolicy(); | 705 return webrtc_session_desc_factory_->SdesPolicy(); |
712 } | 706 } |
713 | 707 |
714 bool WebRtcSession::GetSslRole(rtc::SSLRole* role) { | 708 bool WebRtcSession::GetSslRole(rtc::SSLRole* role) { |
715 if (local_description() == NULL || remote_description() == NULL) { | 709 if (local_description() == NULL || remote_description() == NULL) { |
716 LOG(LS_INFO) << "Local and Remote descriptions must be applied to get " | 710 LOG(LS_INFO) << "Local and Remote descriptions must be applied to get " |
717 << "SSL Role of the session."; | 711 << "SSL Role of the session."; |
718 return false; | 712 return false; |
719 } | 713 } |
720 | 714 |
721 // TODO(mallinath) - Return role of each transport, as role may differ from | 715 return transport_controller()->GetSslRole(role); |
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 } | 716 } |
733 | 717 |
734 void WebRtcSession::CreateOffer( | 718 void WebRtcSession::CreateOffer( |
735 CreateSessionDescriptionObserver* observer, | 719 CreateSessionDescriptionObserver* observer, |
736 const PeerConnectionInterface::RTCOfferAnswerOptions& options) { | 720 const PeerConnectionInterface::RTCOfferAnswerOptions& options) { |
737 webrtc_session_desc_factory_->CreateOffer(observer, options); | 721 webrtc_session_desc_factory_->CreateOffer(observer, options); |
738 } | 722 } |
739 | 723 |
740 void WebRtcSession::CreateAnswer(CreateSessionDescriptionObserver* observer, | 724 void WebRtcSession::CreateAnswer(CreateSessionDescriptionObserver* observer, |
741 const MediaConstraintsInterface* constraints) { | 725 const MediaConstraintsInterface* constraints) { |
742 webrtc_session_desc_factory_->CreateAnswer(observer, constraints); | 726 webrtc_session_desc_factory_->CreateAnswer(observer, constraints); |
743 } | 727 } |
744 | 728 |
745 bool WebRtcSession::SetLocalDescription(SessionDescriptionInterface* desc, | 729 bool WebRtcSession::SetLocalDescription(SessionDescriptionInterface* desc, |
746 std::string* err_desc) { | 730 std::string* err_desc) { |
| 731 ASSERT(signaling_thread()->IsCurrent()); |
| 732 |
747 // Takes the ownership of |desc| regardless of the result. | 733 // Takes the ownership of |desc| regardless of the result. |
748 rtc::scoped_ptr<SessionDescriptionInterface> desc_temp(desc); | 734 rtc::scoped_ptr<SessionDescriptionInterface> desc_temp(desc); |
749 | 735 |
750 // Validate SDP. | 736 // Validate SDP. |
751 if (!ValidateSessionDescription(desc, cricket::CS_LOCAL, err_desc)) { | 737 if (!ValidateSessionDescription(desc, cricket::CS_LOCAL, err_desc)) { |
752 return false; | 738 return false; |
753 } | 739 } |
754 | 740 |
755 // Update the initiator flag if this session is the initiator. | 741 // Update the initiator flag if this session is the initiator. |
756 Action action = GetAction(desc->type()); | 742 Action action = GetAction(desc->type()); |
(...skipping 12 matching lines...) Expand all Loading... |
769 set_local_description(desc->description()->Copy()); | 755 set_local_description(desc->description()->Copy()); |
770 local_desc_.reset(desc_temp.release()); | 756 local_desc_.reset(desc_temp.release()); |
771 | 757 |
772 // Transport and Media channels will be created only when offer is set. | 758 // Transport and Media channels will be created only when offer is set. |
773 if (action == kOffer && !CreateChannels(local_desc_->description())) { | 759 if (action == kOffer && !CreateChannels(local_desc_->description())) { |
774 // TODO(mallinath) - Handle CreateChannel failure, as new local description | 760 // TODO(mallinath) - Handle CreateChannel failure, as new local description |
775 // is applied. Restore back to old description. | 761 // is applied. Restore back to old description. |
776 return BadLocalSdp(desc->type(), kCreateChannelFailed, err_desc); | 762 return BadLocalSdp(desc->type(), kCreateChannelFailed, err_desc); |
777 } | 763 } |
778 | 764 |
779 // Remove channel and transport proxies, if MediaContentDescription is | 765 // Enable BUNDLE before when kMaxBundle policy is in effect |
780 // rejected. | 766 if (bundle_policy_ == PeerConnectionInterface::kBundlePolicyMaxBundle) { |
781 RemoveUnusedChannelsAndTransports(local_desc_->description()); | 767 const cricket::ContentGroup* local_bundle = |
| 768 BaseSession::local_description()->GetGroupByName( |
| 769 cricket::GROUP_TYPE_BUNDLE); |
| 770 if (!local_bundle) { |
| 771 LOG(LS_WARNING) << "max-bundle specified without BUNDLE specified"; |
| 772 return false; |
| 773 } |
| 774 if (!EnableBundle(*local_bundle)) { |
| 775 LOG(LS_WARNING) << "max-bundle failed to enable bundling."; |
| 776 return false; |
| 777 } |
| 778 } |
| 779 |
| 780 // Remove unused channels if MediaContentDescription is rejected. |
| 781 RemoveUnusedChannels(local_desc_->description()); |
782 | 782 |
783 if (!UpdateSessionState(action, cricket::CS_LOCAL, err_desc)) { | 783 if (!UpdateSessionState(action, cricket::CS_LOCAL, err_desc)) { |
784 return false; | 784 return false; |
785 } | 785 } |
786 | 786 |
787 // Kick starting the ice candidates allocation. | 787 if (remote_description()) { |
788 StartCandidatesAllocation(); | 788 // Now that we have a local description, we can push down remote candidates |
| 789 // that we stored, and those from the remote description. |
| 790 if (!saved_candidates_.empty()) { |
| 791 // If there are saved candidates which arrived before local description is |
| 792 // set, copy those to remote description. |
| 793 CopySavedCandidates(remote_desc_.get()); |
| 794 } |
| 795 // Push remote candidates in remote description to transport channels. |
| 796 UseCandidatesInSessionDescription(remote_desc_.get()); |
| 797 } |
789 | 798 |
790 // Update state and SSRC of local MediaStreams and DataChannels based on the | 799 // Update state and SSRC of local MediaStreams and DataChannels based on the |
791 // local session description. | 800 // local session description. |
792 mediastream_signaling_->OnLocalDescriptionChanged(local_desc_.get()); | 801 mediastream_signaling_->OnLocalDescriptionChanged(local_desc_.get()); |
793 | 802 |
794 rtc::SSLRole role; | 803 rtc::SSLRole role; |
795 if (data_channel_type_ == cricket::DCT_SCTP && GetSslRole(&role)) { | 804 if (data_channel_type_ == cricket::DCT_SCTP && GetSslRole(&role)) { |
796 mediastream_signaling_->OnDtlsRoleReadyForSctp(role); | 805 mediastream_signaling_->OnDtlsRoleReadyForSctp(role); |
797 } | 806 } |
798 if (error() != cricket::BaseSession::ERROR_NONE) { | 807 if (error() != cricket::BaseSession::ERROR_NONE) { |
799 return BadLocalSdp(desc->type(), GetSessionErrorMsg(), err_desc); | 808 return BadLocalSdp(desc->type(), GetSessionErrorMsg(), err_desc); |
800 } | 809 } |
801 return true; | 810 return true; |
802 } | 811 } |
803 | 812 |
804 bool WebRtcSession::SetRemoteDescription(SessionDescriptionInterface* desc, | 813 bool WebRtcSession::SetRemoteDescription(SessionDescriptionInterface* desc, |
805 std::string* err_desc) { | 814 std::string* err_desc) { |
| 815 ASSERT(signaling_thread()->IsCurrent()); |
| 816 |
806 // Takes the ownership of |desc| regardless of the result. | 817 // Takes the ownership of |desc| regardless of the result. |
807 rtc::scoped_ptr<SessionDescriptionInterface> desc_temp(desc); | 818 rtc::scoped_ptr<SessionDescriptionInterface> desc_temp(desc); |
808 | 819 |
809 // Validate SDP. | 820 // Validate SDP. |
810 if (!ValidateSessionDescription(desc, cricket::CS_REMOTE, err_desc)) { | 821 if (!ValidateSessionDescription(desc, cricket::CS_REMOTE, err_desc)) { |
811 return false; | 822 return false; |
812 } | 823 } |
813 | 824 |
814 // Transport and Media channels will be created only when offer is set. | 825 // Transport and Media channels will be created only when offer is set. |
815 Action action = GetAction(desc->type()); | 826 Action action = GetAction(desc->type()); |
816 if (action == kOffer && !CreateChannels(desc->description())) { | 827 if (action == kOffer && !CreateChannels(desc->description())) { |
817 // TODO(mallinath) - Handle CreateChannel failure, as new local description | 828 // TODO(mallinath) - Handle CreateChannel failure, as new local description |
818 // is applied. Restore back to old description. | 829 // is applied. Restore back to old description. |
819 return BadRemoteSdp(desc->type(), kCreateChannelFailed, err_desc); | 830 return BadRemoteSdp(desc->type(), kCreateChannelFailed, err_desc); |
820 } | 831 } |
821 | 832 |
822 // Remove channel and transport proxies, if MediaContentDescription is | 833 // Remove unused channels if MediaContentDescription is rejected. |
823 // rejected. | 834 RemoveUnusedChannels(desc->description()); |
824 RemoveUnusedChannelsAndTransports(desc->description()); | |
825 | 835 |
826 // NOTE: Candidates allocation will be initiated only when SetLocalDescription | 836 // NOTE: Candidates allocation will be initiated only when SetLocalDescription |
827 // is called. | 837 // is called. |
828 set_remote_description(desc->description()->Copy()); | 838 set_remote_description(desc->description()->Copy()); |
829 if (!UpdateSessionState(action, cricket::CS_REMOTE, err_desc)) { | 839 if (!UpdateSessionState(action, cricket::CS_REMOTE, err_desc)) { |
830 return false; | 840 return false; |
831 } | 841 } |
832 | 842 |
833 // Update remote MediaStreams. | 843 // Update remote MediaStreams. |
834 mediastream_signaling_->OnRemoteDescriptionChanged(desc); | 844 mediastream_signaling_->OnRemoteDescriptionChanged(desc); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
873 if (desc->type() != SessionDescriptionInterface::kOffer && | 883 if (desc->type() != SessionDescriptionInterface::kOffer && |
874 ice_connection_state_ == PeerConnectionInterface::kIceConnectionNew) { | 884 ice_connection_state_ == PeerConnectionInterface::kIceConnectionNew) { |
875 SetIceConnectionState(PeerConnectionInterface::kIceConnectionChecking); | 885 SetIceConnectionState(PeerConnectionInterface::kIceConnectionChecking); |
876 } | 886 } |
877 return true; | 887 return true; |
878 } | 888 } |
879 | 889 |
880 bool WebRtcSession::UpdateSessionState( | 890 bool WebRtcSession::UpdateSessionState( |
881 Action action, cricket::ContentSource source, | 891 Action action, cricket::ContentSource source, |
882 std::string* err_desc) { | 892 std::string* err_desc) { |
| 893 ASSERT(signaling_thread()->IsCurrent()); |
| 894 |
883 // If there's already a pending error then no state transition should happen. | 895 // 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! | 896 // But all call-sites should be verifying this before calling us! |
885 ASSERT(error() == cricket::BaseSession::ERROR_NONE); | 897 ASSERT(error() == cricket::BaseSession::ERROR_NONE); |
886 std::string td_err; | 898 std::string td_err; |
887 if (action == kOffer) { | 899 if (action == kOffer) { |
888 if (!PushdownTransportDescription(source, cricket::CA_OFFER, &td_err)) { | 900 if (!PushdownTransportDescription(source, cricket::CA_OFFER, &td_err)) { |
889 return BadOfferSdp(source, MakeTdErrorString(td_err), err_desc); | 901 return BadOfferSdp(source, MakeTdErrorString(td_err), err_desc); |
890 } | 902 } |
891 SetState(source == cricket::CS_LOCAL ? | 903 SetState(source == cricket::CS_LOCAL ? |
892 STATE_SENTINITIATE : STATE_RECEIVEDINITIATE); | 904 STATE_SENTINITIATE : STATE_RECEIVEDINITIATE); |
(...skipping 13 matching lines...) Expand all Loading... |
906 if (!PushdownMediaDescription(cricket::CA_PRANSWER, source, err_desc)) { | 918 if (!PushdownMediaDescription(cricket::CA_PRANSWER, source, err_desc)) { |
907 SetError(BaseSession::ERROR_CONTENT, *err_desc); | 919 SetError(BaseSession::ERROR_CONTENT, *err_desc); |
908 } | 920 } |
909 if (error() != cricket::BaseSession::ERROR_NONE) { | 921 if (error() != cricket::BaseSession::ERROR_NONE) { |
910 return BadPranswerSdp(source, GetSessionErrorMsg(), err_desc); | 922 return BadPranswerSdp(source, GetSessionErrorMsg(), err_desc); |
911 } | 923 } |
912 } else if (action == kAnswer) { | 924 } else if (action == kAnswer) { |
913 if (!PushdownTransportDescription(source, cricket::CA_ANSWER, &td_err)) { | 925 if (!PushdownTransportDescription(source, cricket::CA_ANSWER, &td_err)) { |
914 return BadAnswerSdp(source, MakeTdErrorString(td_err), err_desc); | 926 return BadAnswerSdp(source, MakeTdErrorString(td_err), err_desc); |
915 } | 927 } |
916 MaybeEnableMuxingSupport(); | 928 const cricket::ContentGroup* local_bundle = |
| 929 BaseSession::local_description()->GetGroupByName( |
| 930 cricket::GROUP_TYPE_BUNDLE); |
| 931 const cricket::ContentGroup* remote_bundle = |
| 932 BaseSession::remote_description()->GetGroupByName( |
| 933 cricket::GROUP_TYPE_BUNDLE); |
| 934 if (local_bundle && remote_bundle) { |
| 935 // The answerer decides the transport to bundle on |
| 936 const cricket::ContentGroup* answer_bundle = |
| 937 (source == cricket::CS_LOCAL ? local_bundle : remote_bundle); |
| 938 if (!EnableBundle(*answer_bundle)) { |
| 939 LOG(LS_WARNING) << "Failed to enable BUNDLE."; |
| 940 return BadAnswerSdp(source, kEnableBundleFailed, err_desc); |
| 941 } |
| 942 } |
917 EnableChannels(); | 943 EnableChannels(); |
918 SetState(source == cricket::CS_LOCAL ? | 944 SetState(source == cricket::CS_LOCAL ? |
919 STATE_SENTACCEPT : STATE_RECEIVEDACCEPT); | 945 STATE_SENTACCEPT : STATE_RECEIVEDACCEPT); |
920 if (!PushdownMediaDescription(cricket::CA_ANSWER, source, err_desc)) { | 946 if (!PushdownMediaDescription(cricket::CA_ANSWER, source, err_desc)) { |
921 SetError(BaseSession::ERROR_CONTENT, *err_desc); | 947 SetError(BaseSession::ERROR_CONTENT, *err_desc); |
922 } | 948 } |
923 if (error() != cricket::BaseSession::ERROR_NONE) { | 949 if (error() != cricket::BaseSession::ERROR_NONE) { |
924 return BadAnswerSdp(source, GetSessionErrorMsg(), err_desc); | 950 return BadAnswerSdp(source, GetSessionErrorMsg(), err_desc); |
925 } | 951 } |
926 } | 952 } |
(...skipping 28 matching lines...) Expand all Loading... |
955 return WebRtcSession::kPrAnswer; | 981 return WebRtcSession::kPrAnswer; |
956 } else if (type == SessionDescriptionInterface::kAnswer) { | 982 } else if (type == SessionDescriptionInterface::kAnswer) { |
957 return WebRtcSession::kAnswer; | 983 return WebRtcSession::kAnswer; |
958 } | 984 } |
959 ASSERT(false && "unknown action type"); | 985 ASSERT(false && "unknown action type"); |
960 return WebRtcSession::kOffer; | 986 return WebRtcSession::kOffer; |
961 } | 987 } |
962 | 988 |
963 bool WebRtcSession::GetTransportStats(cricket::SessionStats* stats) { | 989 bool WebRtcSession::GetTransportStats(cricket::SessionStats* stats) { |
964 ASSERT(signaling_thread()->IsCurrent()); | 990 ASSERT(signaling_thread()->IsCurrent()); |
| 991 return (GetChannelTransportStats(voice_channel(), stats) && |
| 992 GetChannelTransportStats(video_channel(), stats) && |
| 993 GetChannelTransportStats(data_channel(), stats)); |
| 994 } |
965 | 995 |
966 const auto get_transport_stats = [stats](const std::string& content_name, | 996 bool WebRtcSession::GetChannelTransportStats(cricket::BaseChannel* ch, |
967 cricket::Transport* transport) { | 997 cricket::SessionStats* stats) { |
968 const std::string& transport_id = transport->content_name(); | 998 ASSERT(signaling_thread()->IsCurrent()); |
969 stats->proxy_to_transport[content_name] = transport_id; | 999 if (!ch) { |
970 if (stats->transport_stats.find(transport_id) | 1000 // Not using this channel. |
971 != stats->transport_stats.end()) { | 1001 return true; |
972 // Transport stats already done for this transport. | 1002 } |
973 return true; | |
974 } | |
975 | 1003 |
976 cricket::TransportStats tstats; | 1004 const std::string& content_name = ch->content_name(); |
977 if (!transport->GetStats(&tstats)) { | 1005 const std::string& transport_name = ch->transport_name(); |
978 return false; | 1006 stats->proxy_to_transport[content_name] = transport_name; |
979 } | 1007 if (stats->transport_stats.find(transport_name) != |
| 1008 stats->transport_stats.end()) { |
| 1009 // Transport stats already done for this transport. |
| 1010 return true; |
| 1011 } |
980 | 1012 |
981 stats->transport_stats[transport_id] = tstats; | 1013 cricket::TransportStats tstats; |
982 return true; | 1014 if (!transport_controller()->GetStats(transport_name, &tstats)) { |
983 }; | 1015 return false; |
| 1016 } |
984 | 1017 |
985 for (const auto& kv : transport_proxies()) { | 1018 stats->transport_stats[transport_name] = tstats; |
986 cricket::Transport* transport = kv.second->impl(); | |
987 if (transport && !get_transport_stats(kv.first, transport)) { | |
988 return false; | |
989 } | |
990 } | |
991 return true; | 1019 return true; |
992 } | 1020 } |
993 | 1021 |
| 1022 bool WebRtcSession::GetIdentity(const std::string& content_name, |
| 1023 rtc::SSLIdentity** identity) { |
| 1024 ASSERT(signaling_thread()->IsCurrent()); |
| 1025 |
| 1026 cricket::BaseChannel* ch = GetChannel(content_name); |
| 1027 if (!ch) { |
| 1028 return false; |
| 1029 } |
| 1030 |
| 1031 return transport_controller()->GetIdentity(ch->transport_name(), identity); |
| 1032 } |
| 1033 |
| 1034 bool WebRtcSession::GetRemoteCertificate(const std::string& content_name, |
| 1035 rtc::SSLCertificate** cert) { |
| 1036 ASSERT(signaling_thread()->IsCurrent()); |
| 1037 |
| 1038 cricket::BaseChannel* ch = GetChannel(content_name); |
| 1039 if (!ch) { |
| 1040 return false; |
| 1041 } |
| 1042 |
| 1043 return transport_controller()->GetRemoteCertificate(ch->transport_name(), |
| 1044 cert); |
| 1045 } |
| 1046 |
| 1047 cricket::BaseChannel* WebRtcSession::GetChannel( |
| 1048 const std::string& content_name) { |
| 1049 if (voice_channel() && voice_channel()->content_name() == content_name) { |
| 1050 return voice_channel(); |
| 1051 } |
| 1052 if (video_channel() && video_channel()->content_name() == content_name) { |
| 1053 return video_channel(); |
| 1054 } |
| 1055 if (data_channel() && data_channel()->content_name() == content_name) { |
| 1056 return data_channel(); |
| 1057 } |
| 1058 return nullptr; |
| 1059 } |
| 1060 |
| 1061 bool WebRtcSession::EnableBundle(const cricket::ContentGroup& bundle) { |
| 1062 const std::string* first_content_name = bundle.FirstContentName(); |
| 1063 if (!first_content_name) { |
| 1064 LOG(LS_WARNING) << "Tried to BUNDLE with no contents."; |
| 1065 return false; |
| 1066 } |
| 1067 const std::string& transport_name = *first_content_name; |
| 1068 cricket::BaseChannel* first_channel = GetChannel(transport_name); |
| 1069 |
| 1070 auto maybe_set_transport = |
| 1071 [this, bundle, transport_name, first_channel](cricket::BaseChannel* ch) { |
| 1072 if (!ch || !bundle.HasContentName(ch->content_name())) { |
| 1073 return true; |
| 1074 } |
| 1075 |
| 1076 if (ch->transport_name() == transport_name) { |
| 1077 LOG(LS_INFO) << "BUNDLE already enabled for " << ch->content_name() |
| 1078 << " on " << transport_name << "."; |
| 1079 return true; |
| 1080 } |
| 1081 |
| 1082 if (!ch->SetTransport(transport_name)) { |
| 1083 LOG(LS_WARNING) << "Failed to enable BUNDLE for " |
| 1084 << ch->content_name(); |
| 1085 return false; |
| 1086 } |
| 1087 LOG(LS_INFO) << "Enabled BUNDLE for " << ch->content_name() << " on " |
| 1088 << transport_name << "."; |
| 1089 return true; |
| 1090 }; |
| 1091 |
| 1092 if (!maybe_set_transport(voice_channel()) || |
| 1093 !maybe_set_transport(video_channel()) || |
| 1094 !maybe_set_transport(data_channel())) { |
| 1095 return false; |
| 1096 } |
| 1097 |
| 1098 return true; |
| 1099 } |
| 1100 |
994 bool WebRtcSession::ProcessIceMessage(const IceCandidateInterface* candidate) { | 1101 bool WebRtcSession::ProcessIceMessage(const IceCandidateInterface* candidate) { |
995 if (state() == STATE_INIT) { | 1102 if (state() == STATE_INIT) { |
996 LOG(LS_ERROR) << "ProcessIceMessage: ICE candidates can't be added " | 1103 LOG(LS_ERROR) << "ProcessIceMessage: ICE candidates can't be added " |
997 << "without any offer (local or remote) " | 1104 << "without any offer (local or remote) " |
998 << "session description."; | 1105 << "session description."; |
999 return false; | 1106 return false; |
1000 } | 1107 } |
1001 | 1108 |
1002 if (!candidate) { | 1109 if (!candidate) { |
1003 LOG(LS_ERROR) << "ProcessIceMessage: Candidate is NULL"; | 1110 LOG(LS_ERROR) << "ProcessIceMessage: Candidate is NULL"; |
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1298 | 1405 |
1299 bool WebRtcSession::IceRestartPending() const { | 1406 bool WebRtcSession::IceRestartPending() const { |
1300 return ice_restart_latch_->Get(); | 1407 return ice_restart_latch_->Get(); |
1301 } | 1408 } |
1302 | 1409 |
1303 void WebRtcSession::ResetIceRestartLatch() { | 1410 void WebRtcSession::ResetIceRestartLatch() { |
1304 ice_restart_latch_->Reset(); | 1411 ice_restart_latch_->Reset(); |
1305 } | 1412 } |
1306 | 1413 |
1307 void WebRtcSession::OnIdentityReady(rtc::SSLIdentity* identity) { | 1414 void WebRtcSession::OnIdentityReady(rtc::SSLIdentity* identity) { |
1308 SetIdentity(identity); | 1415 transport_controller()->SetIdentity(identity); |
1309 } | 1416 } |
1310 | 1417 |
1311 bool WebRtcSession::waiting_for_identity() const { | 1418 bool WebRtcSession::waiting_for_identity() const { |
1312 return webrtc_session_desc_factory_->waiting_for_identity(); | 1419 return webrtc_session_desc_factory_->waiting_for_identity(); |
1313 } | 1420 } |
1314 | 1421 |
1315 void WebRtcSession::SetIceConnectionState( | 1422 void WebRtcSession::SetIceConnectionState( |
1316 PeerConnectionInterface::IceConnectionState state) { | 1423 PeerConnectionInterface::IceConnectionState state) { |
1317 if (ice_connection_state_ == state) { | 1424 if (ice_connection_state_ == state) { |
1318 return; | 1425 return; |
1319 } | 1426 } |
1320 | 1427 |
1321 // ASSERT that the requested transition is allowed. Note that | 1428 // ASSERT that the requested transition is allowed. Note that |
1322 // WebRtcSession does not implement "kIceConnectionClosed" (that is handled | 1429 // WebRtcSession does not implement "kIceConnectionClosed" (that is handled |
1323 // within PeerConnection). This switch statement should compile away when | 1430 // within PeerConnection). This switch statement should compile away when |
1324 // ASSERTs are disabled. | 1431 // ASSERTs are disabled. |
| 1432 LOG(LS_INFO) << "Changing IceConnectionState " << ice_connection_state_ |
| 1433 << " => " << state; |
1325 switch (ice_connection_state_) { | 1434 switch (ice_connection_state_) { |
1326 case PeerConnectionInterface::kIceConnectionNew: | 1435 case PeerConnectionInterface::kIceConnectionNew: |
1327 ASSERT(state == PeerConnectionInterface::kIceConnectionChecking); | 1436 ASSERT(state == PeerConnectionInterface::kIceConnectionChecking); |
1328 break; | 1437 break; |
1329 case PeerConnectionInterface::kIceConnectionChecking: | 1438 case PeerConnectionInterface::kIceConnectionChecking: |
1330 ASSERT(state == PeerConnectionInterface::kIceConnectionFailed || | 1439 ASSERT(state == PeerConnectionInterface::kIceConnectionFailed || |
1331 state == PeerConnectionInterface::kIceConnectionConnected); | 1440 state == PeerConnectionInterface::kIceConnectionConnected); |
1332 break; | 1441 break; |
1333 case PeerConnectionInterface::kIceConnectionConnected: | 1442 case PeerConnectionInterface::kIceConnectionConnected: |
1334 ASSERT(state == PeerConnectionInterface::kIceConnectionDisconnected || | 1443 ASSERT(state == PeerConnectionInterface::kIceConnectionDisconnected || |
(...skipping 20 matching lines...) Expand all Loading... |
1355 ASSERT(false); | 1464 ASSERT(false); |
1356 break; | 1465 break; |
1357 } | 1466 } |
1358 | 1467 |
1359 ice_connection_state_ = state; | 1468 ice_connection_state_ = state; |
1360 if (ice_observer_) { | 1469 if (ice_observer_) { |
1361 ice_observer_->OnIceConnectionChange(ice_connection_state_); | 1470 ice_observer_->OnIceConnectionChange(ice_connection_state_); |
1362 } | 1471 } |
1363 } | 1472 } |
1364 | 1473 |
1365 void WebRtcSession::OnTransportRequestSignaling( | 1474 void WebRtcSession::OnTransportControllerConnectionState( |
1366 cricket::Transport* transport) { | 1475 cricket::IceConnectionState state) { |
1367 ASSERT(signaling_thread()->IsCurrent()); | 1476 switch (state) { |
1368 transport->OnSignalingReady(); | 1477 case cricket::kIceConnectionConnecting: |
1369 if (ice_observer_) { | 1478 // If the current state is Connected or Completed, then there were |
1370 ice_observer_->OnIceGatheringChange( | 1479 // writable channels but now there are not, so the next state must |
1371 PeerConnectionInterface::kIceGatheringGathering); | 1480 // be Disconnected. |
| 1481 if (ice_connection_state_ == |
| 1482 PeerConnectionInterface::kIceConnectionConnected || |
| 1483 ice_connection_state_ == |
| 1484 PeerConnectionInterface::kIceConnectionCompleted) { |
| 1485 SetIceConnectionState( |
| 1486 PeerConnectionInterface::kIceConnectionDisconnected); |
| 1487 } |
| 1488 break; |
| 1489 case cricket::kIceConnectionFailed: |
| 1490 SetIceConnectionState(PeerConnectionInterface::kIceConnectionFailed); |
| 1491 break; |
| 1492 case cricket::kIceConnectionConnected: |
| 1493 LOG(LS_INFO) << "Changing to ICE connected state because " |
| 1494 << "all transports are writable."; |
| 1495 SetIceConnectionState(PeerConnectionInterface::kIceConnectionConnected); |
| 1496 break; |
| 1497 case cricket::kIceConnectionCompleted: |
| 1498 LOG(LS_INFO) << "Changing to ICE completed state because " |
| 1499 << "all transports are complete."; |
| 1500 if (ice_connection_state_ != |
| 1501 PeerConnectionInterface::kIceConnectionConnected) { |
| 1502 // If jumping directly from "checking" to "connected", |
| 1503 // signal "connected" first. |
| 1504 SetIceConnectionState(PeerConnectionInterface::kIceConnectionConnected); |
| 1505 } |
| 1506 SetIceConnectionState(PeerConnectionInterface::kIceConnectionCompleted); |
| 1507 if (metrics_observer_) { |
| 1508 // Once ICE connection is completed, report stats for all transports |
| 1509 // in use. |
| 1510 std::set<std::string> transport_names; |
| 1511 if (voice_channel()) { |
| 1512 transport_names.insert(voice_channel()->transport_name()); |
| 1513 } |
| 1514 if (video_channel()) { |
| 1515 transport_names.insert(video_channel()->transport_name()); |
| 1516 } |
| 1517 if (data_channel()) { |
| 1518 transport_names.insert(data_channel()->transport_name()); |
| 1519 } |
| 1520 for (auto name : transport_names) { |
| 1521 cricket::TransportStats stats; |
| 1522 if (transport_controller()->GetStats(name, &stats)) { |
| 1523 ReportBestConnectionState(stats); |
| 1524 ReportNegotiatedCiphers(stats); |
| 1525 } |
| 1526 } |
| 1527 } |
| 1528 break; |
| 1529 default: |
| 1530 ASSERT(false); |
1372 } | 1531 } |
1373 } | 1532 } |
1374 | 1533 |
1375 void WebRtcSession::OnTransportConnecting(cricket::Transport* transport) { | 1534 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); | 1535 SetIceConnectionReceiving(receiving); |
1430 } | 1536 } |
1431 | 1537 |
1432 void WebRtcSession::SetIceConnectionReceiving(bool receiving) { | 1538 void WebRtcSession::SetIceConnectionReceiving(bool receiving) { |
1433 if (ice_connection_receiving_ == receiving) { | 1539 if (ice_connection_receiving_ == receiving) { |
1434 return; | 1540 return; |
1435 } | 1541 } |
1436 ice_connection_receiving_ = receiving; | 1542 ice_connection_receiving_ = receiving; |
1437 if (ice_observer_) { | 1543 if (ice_observer_) { |
1438 ice_observer_->OnIceConnectionReceivingChange(receiving); | 1544 ice_observer_->OnIceConnectionReceivingChange(receiving); |
1439 } | 1545 } |
1440 } | 1546 } |
1441 | 1547 |
1442 void WebRtcSession::OnTransportProxyCandidatesReady( | 1548 void WebRtcSession::OnTransportControllerCandidatesGathered( |
1443 cricket::TransportProxy* proxy, const cricket::Candidates& candidates) { | 1549 const std::string& transport_name, |
| 1550 const cricket::Candidates& candidates) { |
1444 ASSERT(signaling_thread()->IsCurrent()); | 1551 ASSERT(signaling_thread()->IsCurrent()); |
1445 ProcessNewLocalCandidate(proxy->content_name(), candidates); | 1552 int sdp_mline_index; |
1446 } | 1553 if (!GetLocalCandidateMediaIndex(transport_name, &sdp_mline_index)) { |
| 1554 LOG(LS_ERROR) << "OnTransportControllerCandidatesGathered: content name " |
| 1555 << transport_name << " not found"; |
| 1556 return; |
| 1557 } |
1447 | 1558 |
1448 void WebRtcSession::OnCandidatesAllocationDone() { | 1559 for (cricket::Candidates::const_iterator citer = candidates.begin(); |
1449 ASSERT(signaling_thread()->IsCurrent()); | 1560 citer != candidates.end(); ++citer) { |
1450 if (ice_observer_) { | 1561 // Use transport_name as the candidate media id. |
1451 ice_observer_->OnIceGatheringChange( | 1562 JsepIceCandidate candidate(transport_name, sdp_mline_index, *citer); |
1452 PeerConnectionInterface::kIceGatheringComplete); | 1563 if (ice_observer_) { |
1453 ice_observer_->OnIceComplete(); | 1564 ice_observer_->OnIceCandidate(&candidate); |
| 1565 } |
| 1566 if (local_desc_) { |
| 1567 local_desc_->AddCandidate(&candidate); |
| 1568 } |
1454 } | 1569 } |
1455 } | 1570 } |
1456 | 1571 |
1457 // Enabling voice and video channel. | 1572 // Enabling voice and video channel. |
1458 void WebRtcSession::EnableChannels() { | 1573 void WebRtcSession::EnableChannels() { |
1459 if (voice_channel_ && !voice_channel_->enabled()) | 1574 if (voice_channel_ && !voice_channel_->enabled()) |
1460 voice_channel_->Enable(true); | 1575 voice_channel_->Enable(true); |
1461 | 1576 |
1462 if (video_channel_ && !video_channel_->enabled()) | 1577 if (video_channel_ && !video_channel_->enabled()) |
1463 video_channel_->Enable(true); | 1578 video_channel_->Enable(true); |
1464 | 1579 |
1465 if (data_channel_ && !data_channel_->enabled()) | 1580 if (data_channel_ && !data_channel_->enabled()) |
1466 data_channel_->Enable(true); | 1581 data_channel_->Enable(true); |
1467 } | 1582 } |
1468 | 1583 |
1469 void WebRtcSession::ProcessNewLocalCandidate( | |
1470 const std::string& content_name, | |
1471 const cricket::Candidates& candidates) { | |
1472 int sdp_mline_index; | |
1473 if (!GetLocalCandidateMediaIndex(content_name, &sdp_mline_index)) { | |
1474 LOG(LS_ERROR) << "ProcessNewLocalCandidate: content name " | |
1475 << content_name << " not found"; | |
1476 return; | |
1477 } | |
1478 | |
1479 for (cricket::Candidates::const_iterator citer = candidates.begin(); | |
1480 citer != candidates.end(); ++citer) { | |
1481 // Use content_name as the candidate media id. | |
1482 JsepIceCandidate candidate(content_name, sdp_mline_index, *citer); | |
1483 if (ice_observer_) { | |
1484 ice_observer_->OnIceCandidate(&candidate); | |
1485 } | |
1486 if (local_desc_) { | |
1487 local_desc_->AddCandidate(&candidate); | |
1488 } | |
1489 } | |
1490 } | |
1491 | |
1492 // Returns the media index for a local ice candidate given the content name. | 1584 // Returns the media index for a local ice candidate given the content name. |
1493 bool WebRtcSession::GetLocalCandidateMediaIndex(const std::string& content_name, | 1585 bool WebRtcSession::GetLocalCandidateMediaIndex(const std::string& content_name, |
1494 int* sdp_mline_index) { | 1586 int* sdp_mline_index) { |
1495 if (!base_local_description() || !sdp_mline_index) | 1587 if (!base_local_description() || !sdp_mline_index) |
1496 return false; | 1588 return false; |
1497 | 1589 |
1498 bool content_found = false; | 1590 bool content_found = false; |
1499 const ContentInfos& contents = base_local_description()->contents(); | 1591 const ContentInfos& contents = base_local_description()->contents(); |
1500 for (size_t index = 0; index < contents.size(); ++index) { | 1592 for (size_t index = 0; index < contents.size(); ++index) { |
1501 if (contents[index].name == content_name) { | 1593 if (contents[index].name == content_name) { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1542 size_t mediacontent_index = static_cast<size_t>(candidate->sdp_mline_index()); | 1634 size_t mediacontent_index = static_cast<size_t>(candidate->sdp_mline_index()); |
1543 size_t remote_content_size = base_remote_description()->contents().size(); | 1635 size_t remote_content_size = base_remote_description()->contents().size(); |
1544 if (mediacontent_index >= remote_content_size) { | 1636 if (mediacontent_index >= remote_content_size) { |
1545 LOG(LS_ERROR) | 1637 LOG(LS_ERROR) |
1546 << "UseRemoteCandidateInSession: Invalid candidate media index."; | 1638 << "UseRemoteCandidateInSession: Invalid candidate media index."; |
1547 return false; | 1639 return false; |
1548 } | 1640 } |
1549 | 1641 |
1550 cricket::ContentInfo content = | 1642 cricket::ContentInfo content = |
1551 base_remote_description()->contents()[mediacontent_index]; | 1643 base_remote_description()->contents()[mediacontent_index]; |
| 1644 |
1552 std::vector<cricket::Candidate> candidates; | 1645 std::vector<cricket::Candidate> candidates; |
1553 candidates.push_back(candidate->candidate()); | 1646 candidates.push_back(candidate->candidate()); |
1554 // Invoking BaseSession method to handle remote candidates. | 1647 // Invoking BaseSession method to handle remote candidates. |
1555 std::string error; | 1648 std::string error; |
1556 if (OnRemoteCandidates(content.name, candidates, &error)) { | 1649 if (transport_controller()->AddRemoteCandidates(content.name, candidates, |
| 1650 &error)) { |
1557 // Candidates successfully submitted for checking. | 1651 // Candidates successfully submitted for checking. |
1558 if (ice_connection_state_ == PeerConnectionInterface::kIceConnectionNew || | 1652 if (ice_connection_state_ == PeerConnectionInterface::kIceConnectionNew || |
1559 ice_connection_state_ == | 1653 ice_connection_state_ == |
1560 PeerConnectionInterface::kIceConnectionDisconnected) { | 1654 PeerConnectionInterface::kIceConnectionDisconnected) { |
1561 // If state is New, then the session has just gotten its first remote ICE | 1655 // If state is New, then the session has just gotten its first remote ICE |
1562 // candidates, so go to Checking. | 1656 // candidates, so go to Checking. |
1563 // If state is Disconnected, the session is re-using old candidates or | 1657 // If state is Disconnected, the session is re-using old candidates or |
1564 // receiving additional ones, so go to Checking. | 1658 // receiving additional ones, so go to Checking. |
1565 // If state is Connected, stay Connected. | 1659 // If state is Connected, stay Connected. |
1566 // TODO(bemasc): If state is Connected, and the new candidates are for a | 1660 // TODO(bemasc): If state is Connected, and the new candidates are for a |
1567 // newly added transport, then the state actually _should_ move to | 1661 // newly added transport, then the state actually _should_ move to |
1568 // checking. Add a way to distinguish that case. | 1662 // checking. Add a way to distinguish that case. |
1569 SetIceConnectionState(PeerConnectionInterface::kIceConnectionChecking); | 1663 SetIceConnectionState(PeerConnectionInterface::kIceConnectionChecking); |
1570 } | 1664 } |
1571 // TODO(bemasc): If state is Completed, go back to Connected. | 1665 // TODO(bemasc): If state is Completed, go back to Connected. |
1572 } else { | 1666 } else { |
1573 if (!error.empty()) { | 1667 if (!error.empty()) { |
1574 LOG(LS_WARNING) << error; | 1668 LOG(LS_WARNING) << error; |
1575 } | 1669 } |
1576 } | 1670 } |
1577 return true; | 1671 return true; |
1578 } | 1672 } |
1579 | 1673 |
1580 void WebRtcSession::RemoveUnusedChannelsAndTransports( | 1674 void WebRtcSession::RemoveUnusedChannels(const SessionDescription* desc) { |
1581 const SessionDescription* desc) { | |
1582 // Destroy video_channel_ first since it may have a pointer to the | 1675 // Destroy video_channel_ first since it may have a pointer to the |
1583 // voice_channel_. | 1676 // voice_channel_. |
1584 const cricket::ContentInfo* video_info = | 1677 const cricket::ContentInfo* video_info = |
1585 cricket::GetFirstVideoContent(desc); | 1678 cricket::GetFirstVideoContent(desc); |
1586 if ((!video_info || video_info->rejected) && video_channel_) { | 1679 if ((!video_info || video_info->rejected) && video_channel_) { |
1587 mediastream_signaling_->OnVideoChannelClose(); | 1680 mediastream_signaling_->OnVideoChannelClose(); |
1588 SignalVideoChannelDestroyed(); | 1681 SignalVideoChannelDestroyed(); |
1589 const std::string content_name = video_channel_->content_name(); | 1682 const std::string content_name = video_channel_->content_name(); |
1590 channel_manager_->DestroyVideoChannel(video_channel_.release()); | 1683 channel_manager_->DestroyVideoChannel(video_channel_.release()); |
1591 DestroyTransportProxy(content_name); | |
1592 } | 1684 } |
1593 | 1685 |
1594 const cricket::ContentInfo* voice_info = | 1686 const cricket::ContentInfo* voice_info = |
1595 cricket::GetFirstAudioContent(desc); | 1687 cricket::GetFirstAudioContent(desc); |
1596 if ((!voice_info || voice_info->rejected) && voice_channel_) { | 1688 if ((!voice_info || voice_info->rejected) && voice_channel_) { |
1597 mediastream_signaling_->OnAudioChannelClose(); | 1689 mediastream_signaling_->OnAudioChannelClose(); |
1598 SignalVoiceChannelDestroyed(); | 1690 SignalVoiceChannelDestroyed(); |
1599 const std::string content_name = voice_channel_->content_name(); | 1691 const std::string content_name = voice_channel_->content_name(); |
1600 channel_manager_->DestroyVoiceChannel(voice_channel_.release(), | 1692 channel_manager_->DestroyVoiceChannel(voice_channel_.release(), |
1601 video_channel_.get()); | 1693 video_channel_.get()); |
1602 DestroyTransportProxy(content_name); | |
1603 } | 1694 } |
1604 | 1695 |
1605 const cricket::ContentInfo* data_info = | 1696 const cricket::ContentInfo* data_info = |
1606 cricket::GetFirstDataContent(desc); | 1697 cricket::GetFirstDataContent(desc); |
1607 if ((!data_info || data_info->rejected) && data_channel_) { | 1698 if ((!data_info || data_info->rejected) && data_channel_) { |
1608 mediastream_signaling_->OnDataChannelClose(); | 1699 mediastream_signaling_->OnDataChannelClose(); |
1609 SignalDataChannelDestroyed(); | 1700 SignalDataChannelDestroyed(); |
1610 const std::string content_name = data_channel_->content_name(); | 1701 const std::string content_name = data_channel_->content_name(); |
1611 channel_manager_->DestroyDataChannel(data_channel_.release()); | 1702 channel_manager_->DestroyDataChannel(data_channel_.release()); |
1612 DestroyTransportProxy(content_name); | |
1613 } | 1703 } |
1614 } | 1704 } |
1615 | 1705 |
1616 // TODO(mallinath) - Add a correct error code if the channels are not creatued | 1706 // TODO(mallinath) - Add a correct error code if the channels are not creatued |
1617 // due to BUNDLE is enabled but rtcp-mux is disabled. | 1707 // due to BUNDLE is enabled but rtcp-mux is disabled. |
1618 bool WebRtcSession::CreateChannels(const SessionDescription* desc) { | 1708 bool WebRtcSession::CreateChannels(const SessionDescription* desc) { |
1619 // Creating the media channels and transport proxies. | 1709 // Creating the media channels and transport proxies. |
1620 const cricket::ContentInfo* voice = cricket::GetFirstAudioContent(desc); | 1710 const cricket::ContentInfo* voice = cricket::GetFirstAudioContent(desc); |
1621 if (voice && !voice->rejected && !voice_channel_) { | 1711 if (voice && !voice->rejected && !voice_channel_) { |
1622 if (!CreateVoiceChannel(voice)) { | 1712 if (!CreateVoiceChannel(voice)) { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1655 } | 1745 } |
1656 | 1746 |
1657 // Enable bundle before when kMaxBundle policy is in effect. | 1747 // Enable bundle before when kMaxBundle policy is in effect. |
1658 if (bundle_policy_ == PeerConnectionInterface::kBundlePolicyMaxBundle) { | 1748 if (bundle_policy_ == PeerConnectionInterface::kBundlePolicyMaxBundle) { |
1659 const cricket::ContentGroup* bundle_group = desc->GetGroupByName( | 1749 const cricket::ContentGroup* bundle_group = desc->GetGroupByName( |
1660 cricket::GROUP_TYPE_BUNDLE); | 1750 cricket::GROUP_TYPE_BUNDLE); |
1661 if (!bundle_group) { | 1751 if (!bundle_group) { |
1662 LOG(LS_WARNING) << "max-bundle specified without BUNDLE specified"; | 1752 LOG(LS_WARNING) << "max-bundle specified without BUNDLE specified"; |
1663 return false; | 1753 return false; |
1664 } | 1754 } |
1665 if (!BaseSession::BundleContentGroup(bundle_group)) { | 1755 if (!EnableBundle(*bundle_group)) { |
1666 LOG(LS_WARNING) << "max-bundle failed to enable bundling."; | 1756 LOG(LS_WARNING) << "max-bundle failed to enable bundling."; |
1667 return false; | 1757 return false; |
1668 } | 1758 } |
1669 } | 1759 } |
1670 | 1760 |
1671 return true; | 1761 return true; |
1672 } | 1762 } |
1673 | 1763 |
1674 bool WebRtcSession::CreateVoiceChannel(const cricket::ContentInfo* content) { | 1764 bool WebRtcSession::CreateVoiceChannel(const cricket::ContentInfo* content) { |
1675 voice_channel_.reset(channel_manager_->CreateVoiceChannel( | 1765 voice_channel_.reset(channel_manager_->CreateVoiceChannel( |
1676 this, content->name, true, audio_options_)); | 1766 transport_controller(), content->name, true, audio_options_)); |
1677 if (!voice_channel_) { | 1767 if (!voice_channel_) { |
1678 return false; | 1768 return false; |
1679 } | 1769 } |
1680 | 1770 |
1681 voice_channel_->SignalDtlsSetupFailure.connect( | 1771 voice_channel_->SignalDtlsSetupFailure.connect( |
1682 this, &WebRtcSession::OnDtlsSetupFailure); | 1772 this, &WebRtcSession::OnDtlsSetupFailure); |
1683 return true; | 1773 return true; |
1684 } | 1774 } |
1685 | 1775 |
1686 bool WebRtcSession::CreateVideoChannel(const cricket::ContentInfo* content) { | 1776 bool WebRtcSession::CreateVideoChannel(const cricket::ContentInfo* content) { |
1687 video_channel_.reset(channel_manager_->CreateVideoChannel( | 1777 video_channel_.reset(channel_manager_->CreateVideoChannel( |
1688 this, content->name, true, video_options_, voice_channel_.get())); | 1778 transport_controller(), content->name, true, video_options_, |
| 1779 voice_channel_.get())); |
1689 if (!video_channel_) { | 1780 if (!video_channel_) { |
1690 return false; | 1781 return false; |
1691 } | 1782 } |
1692 | 1783 |
1693 video_channel_->SignalDtlsSetupFailure.connect( | 1784 video_channel_->SignalDtlsSetupFailure.connect( |
1694 this, &WebRtcSession::OnDtlsSetupFailure); | 1785 this, &WebRtcSession::OnDtlsSetupFailure); |
1695 return true; | 1786 return true; |
1696 } | 1787 } |
1697 | 1788 |
1698 bool WebRtcSession::CreateDataChannel(const cricket::ContentInfo* content) { | 1789 bool WebRtcSession::CreateDataChannel(const cricket::ContentInfo* content) { |
1699 bool sctp = (data_channel_type_ == cricket::DCT_SCTP); | 1790 bool sctp = (data_channel_type_ == cricket::DCT_SCTP); |
1700 data_channel_.reset(channel_manager_->CreateDataChannel( | 1791 data_channel_.reset(channel_manager_->CreateDataChannel( |
1701 this, content->name, !sctp, data_channel_type_)); | 1792 transport_controller(), content->name, !sctp, data_channel_type_)); |
1702 if (!data_channel_) { | 1793 if (!data_channel_) { |
1703 return false; | 1794 return false; |
1704 } | 1795 } |
1705 | 1796 |
1706 if (sctp) { | 1797 if (sctp) { |
1707 mediastream_signaling_->OnDataTransportCreatedForSctp(); | 1798 mediastream_signaling_->OnDataTransportCreatedForSctp(); |
1708 data_channel_->SignalDataReceived.connect( | 1799 data_channel_->SignalDataReceived.connect( |
1709 this, &WebRtcSession::OnDataChannelMessageReceived); | 1800 this, &WebRtcSession::OnDataChannelMessageReceived); |
1710 data_channel_->SignalStreamClosedRemotely.connect( | 1801 data_channel_->SignalStreamClosedRemotely.connect( |
1711 mediastream_signaling_, | 1802 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 | 1963 // 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 | 1964 // the session, because a new Transport added during renegotiation may have |
1874 // them unset while the session has them set from the previous negotiation. | 1965 // 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 | 1966 // Not doing so may trigger the auto generation of transport description and |
1876 // mess up DTLS identity information, ICE credential, etc. | 1967 // mess up DTLS identity information, ICE credential, etc. |
1877 bool WebRtcSession::ReadyToUseRemoteCandidate( | 1968 bool WebRtcSession::ReadyToUseRemoteCandidate( |
1878 const IceCandidateInterface* candidate, | 1969 const IceCandidateInterface* candidate, |
1879 const SessionDescriptionInterface* remote_desc, | 1970 const SessionDescriptionInterface* remote_desc, |
1880 bool* valid) { | 1971 bool* valid) { |
1881 *valid = true;; | 1972 *valid = true;; |
1882 cricket::TransportProxy* transport_proxy = NULL; | |
1883 | 1973 |
1884 const SessionDescriptionInterface* current_remote_desc = | 1974 const SessionDescriptionInterface* current_remote_desc = |
1885 remote_desc ? remote_desc : remote_description(); | 1975 remote_desc ? remote_desc : remote_description(); |
1886 | 1976 |
1887 if (!current_remote_desc) | 1977 if (!current_remote_desc) |
1888 return false; | 1978 return false; |
1889 | 1979 |
1890 size_t mediacontent_index = | 1980 size_t mediacontent_index = |
1891 static_cast<size_t>(candidate->sdp_mline_index()); | 1981 static_cast<size_t>(candidate->sdp_mline_index()); |
1892 size_t remote_content_size = | 1982 size_t remote_content_size = |
1893 current_remote_desc->description()->contents().size(); | 1983 current_remote_desc->description()->contents().size(); |
1894 if (mediacontent_index >= remote_content_size) { | 1984 if (mediacontent_index >= remote_content_size) { |
1895 LOG(LS_ERROR) | 1985 LOG(LS_ERROR) |
1896 << "ReadyToUseRemoteCandidate: Invalid candidate media index."; | 1986 << "ReadyToUseRemoteCandidate: Invalid candidate media index."; |
1897 | 1987 |
1898 *valid = false; | 1988 *valid = false; |
1899 return false; | 1989 return false; |
1900 } | 1990 } |
1901 | 1991 |
1902 cricket::ContentInfo content = | 1992 cricket::ContentInfo content = |
1903 current_remote_desc->description()->contents()[mediacontent_index]; | 1993 current_remote_desc->description()->contents()[mediacontent_index]; |
1904 transport_proxy = GetTransportProxy(content.name); | 1994 cricket::BaseChannel* channel = GetChannel(content.name); |
| 1995 if (!channel) { |
| 1996 return false; |
| 1997 } |
1905 | 1998 |
1906 return transport_proxy && transport_proxy->local_description_set() && | 1999 return transport_controller()->ReadyForRemoteCandidates( |
1907 transport_proxy->remote_description_set(); | 2000 channel->transport_name()); |
| 2001 } |
| 2002 |
| 2003 void WebRtcSession::OnTransportControllerGatheringState( |
| 2004 cricket::IceGatheringState state) { |
| 2005 ASSERT(signaling_thread()->IsCurrent()); |
| 2006 if (state == cricket::kIceGatheringGathering) { |
| 2007 if (ice_observer_) { |
| 2008 ice_observer_->OnIceGatheringChange( |
| 2009 PeerConnectionInterface::kIceGatheringGathering); |
| 2010 } |
| 2011 } else if (state == cricket::kIceGatheringComplete) { |
| 2012 if (ice_observer_) { |
| 2013 ice_observer_->OnIceGatheringChange( |
| 2014 PeerConnectionInterface::kIceGatheringComplete); |
| 2015 ice_observer_->OnIceComplete(); |
| 2016 } |
| 2017 } |
1908 } | 2018 } |
1909 | 2019 |
1910 // Walk through the ConnectionInfos to gather best connection usage | 2020 // Walk through the ConnectionInfos to gather best connection usage |
1911 // for IPv4 and IPv6. | 2021 // for IPv4 and IPv6. |
1912 void WebRtcSession::ReportBestConnectionState( | 2022 void WebRtcSession::ReportBestConnectionState( |
1913 const cricket::TransportStats& stats) { | 2023 const cricket::TransportStats& stats) { |
1914 DCHECK(metrics_observer_ != NULL); | 2024 DCHECK(metrics_observer_ != NULL); |
1915 for (cricket::TransportChannelStatsList::const_iterator it = | 2025 for (cricket::TransportChannelStatsList::const_iterator it = |
1916 stats.channel_stats.begin(); | 2026 stats.channel_stats.begin(); |
1917 it != stats.channel_stats.end(); ++it) { | 2027 it != stats.channel_stats.end(); ++it) { |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1965 | 2075 |
1966 if (!srtp_cipher.empty()) { | 2076 if (!srtp_cipher.empty()) { |
1967 metrics_observer_->AddHistogramSample(srtp_name, srtp_cipher); | 2077 metrics_observer_->AddHistogramSample(srtp_name, srtp_cipher); |
1968 } | 2078 } |
1969 if (!ssl_cipher.empty()) { | 2079 if (!ssl_cipher.empty()) { |
1970 metrics_observer_->AddHistogramSample(ssl_name, ssl_cipher); | 2080 metrics_observer_->AddHistogramSample(ssl_name, ssl_cipher); |
1971 } | 2081 } |
1972 } | 2082 } |
1973 | 2083 |
1974 } // namespace webrtc | 2084 } // namespace webrtc |
OLD | NEW |