Chromium Code Reviews| Index: webrtc/api/webrtcsession.cc | 
| diff --git a/webrtc/api/webrtcsession.cc b/webrtc/api/webrtcsession.cc | 
| index 92a5f0aec45979b80cea44b430cbaa9af80a726f..69d123a6634f32d8d542de63cf563e040793899c 100644 | 
| --- a/webrtc/api/webrtcsession.cc | 
| +++ b/webrtc/api/webrtcsession.cc | 
| @@ -457,69 +457,37 @@ uint32_t ConvertIceTransportTypeToCandidateFilter( | 
| return cricket::CF_NONE; | 
| } | 
| -// Help class used to remember if a a remote peer has requested ice restart by | 
| -// by sending a description with new ice ufrag and password. | 
| -class IceRestartAnswerLatch { | 
| - public: | 
| - IceRestartAnswerLatch() : ice_restart_(false) { } | 
| - | 
| - // Returns true if CheckForRemoteIceRestart has been called with a new session | 
| - // description where ice password and ufrag has changed since last time | 
| - // Reset() was called. | 
| - bool Get() const { | 
| - return ice_restart_; | 
| - } | 
| - | 
| - void Reset() { | 
| - if (ice_restart_) { | 
| - ice_restart_ = false; | 
| - } | 
| +// Returns true if |new_desc| requests an ICE restart (i.e., new ufrag/pwd). | 
| +bool CheckForRemoteIceRestart(const SessionDescriptionInterface* old_desc, | 
| + const SessionDescriptionInterface* new_desc, | 
| + const std::string& content_name) { | 
| + if (!old_desc) { | 
| + return false; | 
| } | 
| - | 
| - // This method has two purposes: 1. Return whether |new_desc| requests | 
| - // an ICE restart (i.e., new ufrag/pwd). 2. If it requests an ICE restart | 
| - // and it is an OFFER, remember this in |ice_restart_| so that the next | 
| - // Local Answer will be created with new ufrag and pwd. | 
| - bool CheckForRemoteIceRestart(const SessionDescriptionInterface* old_desc, | 
| - const SessionDescriptionInterface* new_desc) { | 
| - if (!old_desc) { | 
| - return false; | 
| - } | 
| - const SessionDescription* new_sd = new_desc->description(); | 
| - const SessionDescription* old_sd = old_desc->description(); | 
| - const ContentInfos& contents = new_sd->contents(); | 
| - for (size_t index = 0; index < contents.size(); ++index) { | 
| - const ContentInfo* cinfo = &contents[index]; | 
| - if (cinfo->rejected) { | 
| - continue; | 
| - } | 
| - // If the content isn't rejected, check if ufrag and password has | 
| - // changed. | 
| - const cricket::TransportDescription* new_transport_desc = | 
| - new_sd->GetTransportDescriptionByName(cinfo->name); | 
| - const cricket::TransportDescription* old_transport_desc = | 
| - old_sd->GetTransportDescriptionByName(cinfo->name); | 
| - if (!new_transport_desc || !old_transport_desc) { | 
| - // No transport description exist. This is not an ice restart. | 
| - continue; | 
| - } | 
| - if (cricket::IceCredentialsChanged(old_transport_desc->ice_ufrag, | 
| - old_transport_desc->ice_pwd, | 
| - new_transport_desc->ice_ufrag, | 
| - new_transport_desc->ice_pwd)) { | 
| - LOG(LS_INFO) << "Remote peer request ice restart."; | 
| - if (new_desc->type() == SessionDescriptionInterface::kOffer) { | 
| - ice_restart_ = true; | 
| - } | 
| - return true; | 
| - } | 
| - } | 
| + const SessionDescription* new_sd = new_desc->description(); | 
| 
 
pthatcher1
2016/02/17 06:46:58
Using existing style, this would be "new_desc" and
 
Taylor Brandstetter
2016/02/17 21:43:50
But one is a SessionDescription and one is a Sessi
 
 | 
| + const SessionDescription* old_sd = old_desc->description(); | 
| + const ContentInfo* cinfo = new_sd->GetContentByName(content_name); | 
| + if (!cinfo || cinfo->rejected) { | 
| return false; | 
| } | 
| - | 
| - private: | 
| - bool ice_restart_; | 
| -}; | 
| + // If the content isn't rejected, check if ufrag and password has changed. | 
| + const cricket::TransportDescription* new_transport_desc = | 
| + new_sd->GetTransportDescriptionByName(content_name); | 
| + const cricket::TransportDescription* old_transport_desc = | 
| + old_sd->GetTransportDescriptionByName(content_name); | 
| + if (!new_transport_desc || !old_transport_desc) { | 
| + // No transport description exists. This is not an ICE restart. | 
| + return false; | 
| + } | 
| + if (cricket::IceCredentialsChanged( | 
| + old_transport_desc->ice_ufrag, old_transport_desc->ice_pwd, | 
| + new_transport_desc->ice_ufrag, new_transport_desc->ice_pwd)) { | 
| + LOG(LS_INFO) << "Remote peer requests ICE restart for " << content_name | 
| + << "."; | 
| + return true; | 
| + } | 
| + return false; | 
| +} | 
| WebRtcSession::WebRtcSession(webrtc::MediaControllerInterface* media_controller, | 
| rtc::Thread* signaling_thread, | 
| @@ -543,7 +511,6 @@ WebRtcSession::WebRtcSession(webrtc::MediaControllerInterface* media_controller, | 
| older_version_remote_peer_(false), | 
| dtls_enabled_(false), | 
| data_channel_type_(cricket::DCT_NONE), | 
| - ice_restart_latch_(new IceRestartAnswerLatch), | 
| metrics_observer_(NULL) { | 
| transport_controller_->SetIceRole(cricket::ICEROLE_CONTROLLED); | 
| transport_controller_->SignalConnectionState.connect( | 
| @@ -708,6 +675,20 @@ void WebRtcSession::Close() { | 
| ASSERT(!data_channel_); | 
| } | 
| +cricket::BaseChannel* WebRtcSession::GetChannel( | 
| + const std::string& content_name) { | 
| + if (voice_channel() && voice_channel()->content_name() == content_name) { | 
| + return voice_channel(); | 
| + } | 
| + if (video_channel() && video_channel()->content_name() == content_name) { | 
| + return video_channel(); | 
| + } | 
| + if (data_channel() && data_channel()->content_name() == content_name) { | 
| + return data_channel(); | 
| + } | 
| + return nullptr; | 
| +} | 
| 
 
honghaiz3
2016/02/12 18:21:04
Did you change this part?
Either way, it would be
 
Taylor Brandstetter
2016/02/12 20:43:02
No, I didn't change it. But I moved it in the head
 
 | 
| + | 
| void WebRtcSession::SetSdesPolicy(cricket::SecurePolicy secure_policy) { | 
| webrtc_session_desc_factory_->SetSdesPolicy(secure_policy); | 
| } | 
| @@ -795,6 +776,8 @@ bool WebRtcSession::SetLocalDescription(SessionDescriptionInterface* desc, | 
| UseCandidatesInSessionDescription(remote_desc_.get()); | 
| } | 
| + pending_ice_restarts_.clear(); | 
| 
 
pthatcher1
2016/02/17 06:46:58
What if the call to SetLocalDescription didn't act
 
Taylor Brandstetter
2016/02/17 21:43:50
Well, for one, the issue you describe occurred bef
 
pthatcher1
2016/02/17 21:53:38
But is it legal to do this?
var remoteOffer1 = ..
 
Taylor Brandstetter
2016/02/18 00:33:21
This is "legal", but very dangerous. Setting an ol
 
pthatcher1
2016/02/19 02:33:43
It would still make me feel a lot better if we did
 
Taylor Brandstetter
2016/02/19 21:59:26
Ok, let's say the spec DOES allow munging the ufra
 
pthatcher1
2016/02/20 05:57:25
I was thinking of the next createOffer from the lo
 
 | 
| + | 
| if (error() != ERROR_NONE) { | 
| return BadLocalSdp(desc->type(), GetSessionErrorMsg(), err_desc); | 
| } | 
| @@ -838,20 +821,30 @@ bool WebRtcSession::SetRemoteDescription(SessionDescriptionInterface* desc, | 
| return BadRemoteSdp(desc->type(), kInvalidCandidates, err_desc); | 
| } | 
| - // Check if this new SessionDescription contains new ice ufrag and password | 
| - // that indicates the remote peer requests ice restart. | 
| - bool ice_restart = | 
| - ice_restart_latch_->CheckForRemoteIceRestart(old_remote_desc.get(), desc); | 
| - // We retain all received candidates only if ICE is not restarted. | 
| - // When ICE is restarted, all previous candidates belong to an old generation | 
| - // and should not be kept. | 
| - // TODO(deadbeef): This goes against the W3C spec which says the remote | 
| - // description should only contain candidates from the last set remote | 
| - // description plus any candidates added since then. We should remove this | 
| - // once we're sure it won't break anything. | 
| - if (!ice_restart) { | 
| - WebRtcSessionDescriptionFactory::CopyCandidatesFromSessionDescription( | 
| - old_remote_desc.get(), desc); | 
| + if (old_remote_desc) { | 
| + for (const cricket::ContentInfo& content : | 
| + old_remote_desc->description()->contents()) { | 
| + // Check if this new SessionDescription contains new ICE ufrag and | 
| + // password that indicates the remote peer requests an ICE restart. | 
| + // TODO(deadbeef): When we start storing both the current and pending | 
| + // remote description, this should reset pending_ice_restarts and compare | 
| + // against the current description. | 
| + if (CheckForRemoteIceRestart(old_remote_desc.get(), desc, content.name)) { | 
| + if (action == kOffer) { | 
| + pending_ice_restarts_.insert(content.name); | 
| + } | 
| + } else { | 
| + // We retain all received candidates only if ICE is not restarted. | 
| + // When ICE is restarted, all previous candidates belong to an old | 
| + // generation and should not be kept. | 
| + // TODO(deadbeef): This goes against the W3C spec which says the remote | 
| + // description should only contain candidates from the last set remote | 
| + // description plus any candidates added since then. We should remove | 
| + // this once we're sure it won't break anything. | 
| + WebRtcSessionDescriptionFactory::CopyCandidatesFromSessionDescription( | 
| + old_remote_desc.get(), content.name, desc); | 
| + } | 
| + } | 
| } | 
| if (error() != ERROR_NONE) { | 
| @@ -1110,20 +1103,6 @@ bool WebRtcSession::GetRemoteSSLCertificate(const std::string& transport_name, | 
| return transport_controller_->GetRemoteSSLCertificate(transport_name, cert); | 
| } | 
| -cricket::BaseChannel* WebRtcSession::GetChannel( | 
| - const std::string& content_name) { | 
| - if (voice_channel() && voice_channel()->content_name() == content_name) { | 
| - return voice_channel(); | 
| - } | 
| - if (video_channel() && video_channel()->content_name() == content_name) { | 
| - return video_channel(); | 
| - } | 
| - if (data_channel() && data_channel()->content_name() == content_name) { | 
| - return data_channel(); | 
| - } | 
| - return nullptr; | 
| -} | 
| - | 
| bool WebRtcSession::EnableBundle(const cricket::ContentGroup& bundle) { | 
| const std::string* first_content_name = bundle.FirstContentName(); | 
| if (!first_content_name) { | 
| @@ -1448,12 +1427,9 @@ cricket::DataChannelType WebRtcSession::data_channel_type() const { | 
| return data_channel_type_; | 
| } | 
| -bool WebRtcSession::IceRestartPending() const { | 
| - return ice_restart_latch_->Get(); | 
| -} | 
| - | 
| -void WebRtcSession::ResetIceRestartLatch() { | 
| - ice_restart_latch_->Reset(); | 
| +bool WebRtcSession::IceRestartPending(const std::string& content_name) const { | 
| + return pending_ice_restarts_.find(content_name) != | 
| + pending_ice_restarts_.end(); | 
| } | 
| void WebRtcSession::OnCertificateReady( |