OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |