Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(62)

Side by Side Diff: webrtc/api/webrtcsession.cc

Issue 1671173002: Track pending ICE restarts independently for different media sections. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Extend ICE restart test to check that a second answer has new credentials. Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright 2012 The WebRTC project authors. All Rights Reserved. 2 * Copyright 2012 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
(...skipping 439 matching lines...) Expand 10 before | Expand all | Expand 10 after
450 return cricket::CF_RELAY; 450 return cricket::CF_RELAY;
451 case PeerConnectionInterface::kNoHost: 451 case PeerConnectionInterface::kNoHost:
452 return (cricket::CF_ALL & ~cricket::CF_HOST); 452 return (cricket::CF_ALL & ~cricket::CF_HOST);
453 case PeerConnectionInterface::kAll: 453 case PeerConnectionInterface::kAll:
454 return cricket::CF_ALL; 454 return cricket::CF_ALL;
455 default: ASSERT(false); 455 default: ASSERT(false);
456 } 456 }
457 return cricket::CF_NONE; 457 return cricket::CF_NONE;
458 } 458 }
459 459
460 // Help class used to remember if a a remote peer has requested ice restart by 460 // Returns true if |new_desc| requests an ICE restart (i.e., new ufrag/pwd).
461 // by sending a description with new ice ufrag and password. 461 bool CheckForRemoteIceRestart(const SessionDescriptionInterface* old_desc,
462 class IceRestartAnswerLatch { 462 const SessionDescriptionInterface* new_desc,
463 public: 463 const std::string& content_name) {
464 IceRestartAnswerLatch() : ice_restart_(false) { } 464 if (!old_desc) {
465
466 // Returns true if CheckForRemoteIceRestart has been called with a new session
467 // description where ice password and ufrag has changed since last time
468 // Reset() was called.
469 bool Get() const {
470 return ice_restart_;
471 }
472
473 void Reset() {
474 if (ice_restart_) {
475 ice_restart_ = false;
476 }
477 }
478
479 // This method has two purposes: 1. Return whether |new_desc| requests
480 // an ICE restart (i.e., new ufrag/pwd). 2. If it requests an ICE restart
481 // and it is an OFFER, remember this in |ice_restart_| so that the next
482 // Local Answer will be created with new ufrag and pwd.
483 bool CheckForRemoteIceRestart(const SessionDescriptionInterface* old_desc,
484 const SessionDescriptionInterface* new_desc) {
485 if (!old_desc) {
486 return false;
487 }
488 const SessionDescription* new_sd = new_desc->description();
489 const SessionDescription* old_sd = old_desc->description();
490 const ContentInfos& contents = new_sd->contents();
491 for (size_t index = 0; index < contents.size(); ++index) {
492 const ContentInfo* cinfo = &contents[index];
493 if (cinfo->rejected) {
494 continue;
495 }
496 // If the content isn't rejected, check if ufrag and password has
497 // changed.
498 const cricket::TransportDescription* new_transport_desc =
499 new_sd->GetTransportDescriptionByName(cinfo->name);
500 const cricket::TransportDescription* old_transport_desc =
501 old_sd->GetTransportDescriptionByName(cinfo->name);
502 if (!new_transport_desc || !old_transport_desc) {
503 // No transport description exist. This is not an ice restart.
504 continue;
505 }
506 if (cricket::IceCredentialsChanged(old_transport_desc->ice_ufrag,
507 old_transport_desc->ice_pwd,
508 new_transport_desc->ice_ufrag,
509 new_transport_desc->ice_pwd)) {
510 LOG(LS_INFO) << "Remote peer request ice restart.";
511 if (new_desc->type() == SessionDescriptionInterface::kOffer) {
512 ice_restart_ = true;
513 }
514 return true;
515 }
516 }
517 return false; 465 return false;
518 } 466 }
519 467 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
520 private: 468 const SessionDescription* old_sd = old_desc->description();
521 bool ice_restart_; 469 const ContentInfo* cinfo = new_sd->GetContentByName(content_name);
522 }; 470 if (!cinfo || cinfo->rejected) {
471 return false;
472 }
473 // If the content isn't rejected, check if ufrag and password has changed.
474 const cricket::TransportDescription* new_transport_desc =
475 new_sd->GetTransportDescriptionByName(content_name);
476 const cricket::TransportDescription* old_transport_desc =
477 old_sd->GetTransportDescriptionByName(content_name);
478 if (!new_transport_desc || !old_transport_desc) {
479 // No transport description exists. This is not an ICE restart.
480 return false;
481 }
482 if (cricket::IceCredentialsChanged(
483 old_transport_desc->ice_ufrag, old_transport_desc->ice_pwd,
484 new_transport_desc->ice_ufrag, new_transport_desc->ice_pwd)) {
485 LOG(LS_INFO) << "Remote peer requests ICE restart for " << content_name
486 << ".";
487 return true;
488 }
489 return false;
490 }
523 491
524 WebRtcSession::WebRtcSession(webrtc::MediaControllerInterface* media_controller, 492 WebRtcSession::WebRtcSession(webrtc::MediaControllerInterface* media_controller,
525 rtc::Thread* signaling_thread, 493 rtc::Thread* signaling_thread,
526 rtc::Thread* worker_thread, 494 rtc::Thread* worker_thread,
527 cricket::PortAllocator* port_allocator) 495 cricket::PortAllocator* port_allocator)
528 : signaling_thread_(signaling_thread), 496 : signaling_thread_(signaling_thread),
529 worker_thread_(worker_thread), 497 worker_thread_(worker_thread),
530 port_allocator_(port_allocator), 498 port_allocator_(port_allocator),
531 // RFC 3264: The numeric value of the session id and version in the 499 // RFC 3264: The numeric value of the session id and version in the
532 // o line MUST be representable with a "64 bit signed integer". 500 // o line MUST be representable with a "64 bit signed integer".
533 // Due to this constraint session id |sid_| is max limited to LLONG_MAX. 501 // Due to this constraint session id |sid_| is max limited to LLONG_MAX.
534 sid_(rtc::ToString(rtc::CreateRandomId64() & LLONG_MAX)), 502 sid_(rtc::ToString(rtc::CreateRandomId64() & LLONG_MAX)),
535 transport_controller_(new cricket::TransportController(signaling_thread, 503 transport_controller_(new cricket::TransportController(signaling_thread,
536 worker_thread, 504 worker_thread,
537 port_allocator)), 505 port_allocator)),
538 media_controller_(media_controller), 506 media_controller_(media_controller),
539 channel_manager_(media_controller_->channel_manager()), 507 channel_manager_(media_controller_->channel_manager()),
540 ice_observer_(NULL), 508 ice_observer_(NULL),
541 ice_connection_state_(PeerConnectionInterface::kIceConnectionNew), 509 ice_connection_state_(PeerConnectionInterface::kIceConnectionNew),
542 ice_connection_receiving_(true), 510 ice_connection_receiving_(true),
543 older_version_remote_peer_(false), 511 older_version_remote_peer_(false),
544 dtls_enabled_(false), 512 dtls_enabled_(false),
545 data_channel_type_(cricket::DCT_NONE), 513 data_channel_type_(cricket::DCT_NONE),
546 ice_restart_latch_(new IceRestartAnswerLatch),
547 metrics_observer_(NULL) { 514 metrics_observer_(NULL) {
548 transport_controller_->SetIceRole(cricket::ICEROLE_CONTROLLED); 515 transport_controller_->SetIceRole(cricket::ICEROLE_CONTROLLED);
549 transport_controller_->SignalConnectionState.connect( 516 transport_controller_->SignalConnectionState.connect(
550 this, &WebRtcSession::OnTransportControllerConnectionState); 517 this, &WebRtcSession::OnTransportControllerConnectionState);
551 transport_controller_->SignalReceiving.connect( 518 transport_controller_->SignalReceiving.connect(
552 this, &WebRtcSession::OnTransportControllerReceiving); 519 this, &WebRtcSession::OnTransportControllerReceiving);
553 transport_controller_->SignalGatheringState.connect( 520 transport_controller_->SignalGatheringState.connect(
554 this, &WebRtcSession::OnTransportControllerGatheringState); 521 this, &WebRtcSession::OnTransportControllerGatheringState);
555 transport_controller_->SignalCandidatesGathered.connect( 522 transport_controller_->SignalCandidatesGathered.connect(
556 this, &WebRtcSession::OnTransportControllerCandidatesGathered); 523 this, &WebRtcSession::OnTransportControllerCandidatesGathered);
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
701 } 668 }
702 669
703 void WebRtcSession::Close() { 670 void WebRtcSession::Close() {
704 SetState(STATE_CLOSED); 671 SetState(STATE_CLOSED);
705 RemoveUnusedChannels(nullptr); 672 RemoveUnusedChannels(nullptr);
706 ASSERT(!voice_channel_); 673 ASSERT(!voice_channel_);
707 ASSERT(!video_channel_); 674 ASSERT(!video_channel_);
708 ASSERT(!data_channel_); 675 ASSERT(!data_channel_);
709 } 676 }
710 677
678 cricket::BaseChannel* WebRtcSession::GetChannel(
679 const std::string& content_name) {
680 if (voice_channel() && voice_channel()->content_name() == content_name) {
681 return voice_channel();
682 }
683 if (video_channel() && video_channel()->content_name() == content_name) {
684 return video_channel();
685 }
686 if (data_channel() && data_channel()->content_name() == content_name) {
687 return data_channel();
688 }
689 return nullptr;
690 }
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
691
711 void WebRtcSession::SetSdesPolicy(cricket::SecurePolicy secure_policy) { 692 void WebRtcSession::SetSdesPolicy(cricket::SecurePolicy secure_policy) {
712 webrtc_session_desc_factory_->SetSdesPolicy(secure_policy); 693 webrtc_session_desc_factory_->SetSdesPolicy(secure_policy);
713 } 694 }
714 695
715 cricket::SecurePolicy WebRtcSession::SdesPolicy() const { 696 cricket::SecurePolicy WebRtcSession::SdesPolicy() const {
716 return webrtc_session_desc_factory_->SdesPolicy(); 697 return webrtc_session_desc_factory_->SdesPolicy();
717 } 698 }
718 699
719 bool WebRtcSession::GetSslRole(const std::string& transport_name, 700 bool WebRtcSession::GetSslRole(const std::string& transport_name,
720 rtc::SSLRole* role) { 701 rtc::SSLRole* role) {
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
788 769
789 if (!UpdateSessionState(action, cricket::CS_LOCAL, err_desc)) { 770 if (!UpdateSessionState(action, cricket::CS_LOCAL, err_desc)) {
790 return false; 771 return false;
791 } 772 }
792 773
793 if (remote_desc_) { 774 if (remote_desc_) {
794 // Now that we have a local description, we can push down remote candidates. 775 // Now that we have a local description, we can push down remote candidates.
795 UseCandidatesInSessionDescription(remote_desc_.get()); 776 UseCandidatesInSessionDescription(remote_desc_.get());
796 } 777 }
797 778
779 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
780
798 if (error() != ERROR_NONE) { 781 if (error() != ERROR_NONE) {
799 return BadLocalSdp(desc->type(), GetSessionErrorMsg(), err_desc); 782 return BadLocalSdp(desc->type(), GetSessionErrorMsg(), err_desc);
800 } 783 }
801 return true; 784 return true;
802 } 785 }
803 786
804 bool WebRtcSession::SetRemoteDescription(SessionDescriptionInterface* desc, 787 bool WebRtcSession::SetRemoteDescription(SessionDescriptionInterface* desc,
805 std::string* err_desc) { 788 std::string* err_desc) {
806 ASSERT(signaling_thread()->IsCurrent()); 789 ASSERT(signaling_thread()->IsCurrent());
807 790
(...skipping 23 matching lines...) Expand all
831 // NOTE: Candidates allocation will be initiated only when SetLocalDescription 814 // NOTE: Candidates allocation will be initiated only when SetLocalDescription
832 // is called. 815 // is called.
833 if (!UpdateSessionState(action, cricket::CS_REMOTE, err_desc)) { 816 if (!UpdateSessionState(action, cricket::CS_REMOTE, err_desc)) {
834 return false; 817 return false;
835 } 818 }
836 819
837 if (local_desc_ && !UseCandidatesInSessionDescription(desc)) { 820 if (local_desc_ && !UseCandidatesInSessionDescription(desc)) {
838 return BadRemoteSdp(desc->type(), kInvalidCandidates, err_desc); 821 return BadRemoteSdp(desc->type(), kInvalidCandidates, err_desc);
839 } 822 }
840 823
841 // Check if this new SessionDescription contains new ice ufrag and password 824 if (old_remote_desc) {
842 // that indicates the remote peer requests ice restart. 825 for (const cricket::ContentInfo& content :
843 bool ice_restart = 826 old_remote_desc->description()->contents()) {
844 ice_restart_latch_->CheckForRemoteIceRestart(old_remote_desc.get(), desc); 827 // Check if this new SessionDescription contains new ICE ufrag and
845 // We retain all received candidates only if ICE is not restarted. 828 // password that indicates the remote peer requests an ICE restart.
846 // When ICE is restarted, all previous candidates belong to an old generation 829 // TODO(deadbeef): When we start storing both the current and pending
847 // and should not be kept. 830 // remote description, this should reset pending_ice_restarts and compare
848 // TODO(deadbeef): This goes against the W3C spec which says the remote 831 // against the current description.
849 // description should only contain candidates from the last set remote 832 if (CheckForRemoteIceRestart(old_remote_desc.get(), desc, content.name)) {
850 // description plus any candidates added since then. We should remove this 833 if (action == kOffer) {
851 // once we're sure it won't break anything. 834 pending_ice_restarts_.insert(content.name);
852 if (!ice_restart) { 835 }
853 WebRtcSessionDescriptionFactory::CopyCandidatesFromSessionDescription( 836 } else {
854 old_remote_desc.get(), desc); 837 // We retain all received candidates only if ICE is not restarted.
838 // When ICE is restarted, all previous candidates belong to an old
839 // generation and should not be kept.
840 // TODO(deadbeef): This goes against the W3C spec which says the remote
841 // description should only contain candidates from the last set remote
842 // description plus any candidates added since then. We should remove
843 // this once we're sure it won't break anything.
844 WebRtcSessionDescriptionFactory::CopyCandidatesFromSessionDescription(
845 old_remote_desc.get(), content.name, desc);
846 }
847 }
855 } 848 }
856 849
857 if (error() != ERROR_NONE) { 850 if (error() != ERROR_NONE) {
858 return BadRemoteSdp(desc->type(), GetSessionErrorMsg(), err_desc); 851 return BadRemoteSdp(desc->type(), GetSessionErrorMsg(), err_desc);
859 } 852 }
860 853
861 // Set the the ICE connection state to connecting since the connection may 854 // Set the the ICE connection state to connecting since the connection may
862 // become writable with peer reflexive candidates before any remote candidate 855 // become writable with peer reflexive candidates before any remote candidate
863 // is signaled. 856 // is signaled.
864 // TODO(pthatcher): This is a short-term solution for crbug/446908. A real fix 857 // TODO(pthatcher): This is a short-term solution for crbug/446908. A real fix
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after
1103 return transport_controller_->GetLocalCertificate(transport_name, 1096 return transport_controller_->GetLocalCertificate(transport_name,
1104 certificate); 1097 certificate);
1105 } 1098 }
1106 1099
1107 bool WebRtcSession::GetRemoteSSLCertificate(const std::string& transport_name, 1100 bool WebRtcSession::GetRemoteSSLCertificate(const std::string& transport_name,
1108 rtc::SSLCertificate** cert) { 1101 rtc::SSLCertificate** cert) {
1109 ASSERT(signaling_thread()->IsCurrent()); 1102 ASSERT(signaling_thread()->IsCurrent());
1110 return transport_controller_->GetRemoteSSLCertificate(transport_name, cert); 1103 return transport_controller_->GetRemoteSSLCertificate(transport_name, cert);
1111 } 1104 }
1112 1105
1113 cricket::BaseChannel* WebRtcSession::GetChannel(
1114 const std::string& content_name) {
1115 if (voice_channel() && voice_channel()->content_name() == content_name) {
1116 return voice_channel();
1117 }
1118 if (video_channel() && video_channel()->content_name() == content_name) {
1119 return video_channel();
1120 }
1121 if (data_channel() && data_channel()->content_name() == content_name) {
1122 return data_channel();
1123 }
1124 return nullptr;
1125 }
1126
1127 bool WebRtcSession::EnableBundle(const cricket::ContentGroup& bundle) { 1106 bool WebRtcSession::EnableBundle(const cricket::ContentGroup& bundle) {
1128 const std::string* first_content_name = bundle.FirstContentName(); 1107 const std::string* first_content_name = bundle.FirstContentName();
1129 if (!first_content_name) { 1108 if (!first_content_name) {
1130 LOG(LS_WARNING) << "Tried to BUNDLE with no contents."; 1109 LOG(LS_WARNING) << "Tried to BUNDLE with no contents.";
1131 return false; 1110 return false;
1132 } 1111 }
1133 const std::string& transport_name = *first_content_name; 1112 const std::string& transport_name = *first_content_name;
1134 cricket::BaseChannel* first_channel = GetChannel(transport_name); 1113 cricket::BaseChannel* first_channel = GetChannel(transport_name);
1135 1114
1136 auto maybe_set_transport = [this, bundle, transport_name, 1115 auto maybe_set_transport = [this, bundle, transport_name,
(...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after
1441 } 1420 }
1442 1421
1443 bool WebRtcSession::ReadyToSendData() const { 1422 bool WebRtcSession::ReadyToSendData() const {
1444 return data_channel_ && data_channel_->ready_to_send_data(); 1423 return data_channel_ && data_channel_->ready_to_send_data();
1445 } 1424 }
1446 1425
1447 cricket::DataChannelType WebRtcSession::data_channel_type() const { 1426 cricket::DataChannelType WebRtcSession::data_channel_type() const {
1448 return data_channel_type_; 1427 return data_channel_type_;
1449 } 1428 }
1450 1429
1451 bool WebRtcSession::IceRestartPending() const { 1430 bool WebRtcSession::IceRestartPending(const std::string& content_name) const {
1452 return ice_restart_latch_->Get(); 1431 return pending_ice_restarts_.find(content_name) !=
1453 } 1432 pending_ice_restarts_.end();
1454
1455 void WebRtcSession::ResetIceRestartLatch() {
1456 ice_restart_latch_->Reset();
1457 } 1433 }
1458 1434
1459 void WebRtcSession::OnCertificateReady( 1435 void WebRtcSession::OnCertificateReady(
1460 const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) { 1436 const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) {
1461 transport_controller_->SetLocalCertificate(certificate); 1437 transport_controller_->SetLocalCertificate(certificate);
1462 } 1438 }
1463 1439
1464 bool WebRtcSession::waiting_for_certificate_for_testing() const { 1440 bool WebRtcSession::waiting_for_certificate_for_testing() const {
1465 return webrtc_session_desc_factory_->waiting_for_certificate_for_testing(); 1441 return webrtc_session_desc_factory_->waiting_for_certificate_for_testing();
1466 } 1442 }
(...skipping 692 matching lines...) Expand 10 before | Expand all | Expand 10 after
2159 } 2135 }
2160 } 2136 }
2161 2137
2162 void WebRtcSession::OnSentPacket_w(cricket::TransportChannel* channel, 2138 void WebRtcSession::OnSentPacket_w(cricket::TransportChannel* channel,
2163 const rtc::SentPacket& sent_packet) { 2139 const rtc::SentPacket& sent_packet) {
2164 RTC_DCHECK(worker_thread()->IsCurrent()); 2140 RTC_DCHECK(worker_thread()->IsCurrent());
2165 media_controller_->call_w()->OnSentPacket(sent_packet); 2141 media_controller_->call_w()->OnSentPacket(sent_packet);
2166 } 2142 }
2167 2143
2168 } // namespace webrtc 2144 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698