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( |