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(); |
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 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
685 } | 652 } |
686 | 653 |
687 void WebRtcSession::Close() { | 654 void WebRtcSession::Close() { |
688 SetState(STATE_CLOSED); | 655 SetState(STATE_CLOSED); |
689 RemoveUnusedChannels(nullptr); | 656 RemoveUnusedChannels(nullptr); |
690 ASSERT(!voice_channel_); | 657 ASSERT(!voice_channel_); |
691 ASSERT(!video_channel_); | 658 ASSERT(!video_channel_); |
692 ASSERT(!data_channel_); | 659 ASSERT(!data_channel_); |
693 } | 660 } |
694 | 661 |
| 662 cricket::BaseChannel* WebRtcSession::GetChannel( |
| 663 const std::string& content_name) { |
| 664 if (voice_channel() && voice_channel()->content_name() == content_name) { |
| 665 return voice_channel(); |
| 666 } |
| 667 if (video_channel() && video_channel()->content_name() == content_name) { |
| 668 return video_channel(); |
| 669 } |
| 670 if (data_channel() && data_channel()->content_name() == content_name) { |
| 671 return data_channel(); |
| 672 } |
| 673 return nullptr; |
| 674 } |
| 675 |
695 void WebRtcSession::SetSdesPolicy(cricket::SecurePolicy secure_policy) { | 676 void WebRtcSession::SetSdesPolicy(cricket::SecurePolicy secure_policy) { |
696 webrtc_session_desc_factory_->SetSdesPolicy(secure_policy); | 677 webrtc_session_desc_factory_->SetSdesPolicy(secure_policy); |
697 } | 678 } |
698 | 679 |
699 cricket::SecurePolicy WebRtcSession::SdesPolicy() const { | 680 cricket::SecurePolicy WebRtcSession::SdesPolicy() const { |
700 return webrtc_session_desc_factory_->SdesPolicy(); | 681 return webrtc_session_desc_factory_->SdesPolicy(); |
701 } | 682 } |
702 | 683 |
703 bool WebRtcSession::GetSslRole(const std::string& transport_name, | 684 bool WebRtcSession::GetSslRole(const std::string& transport_name, |
704 rtc::SSLRole* role) { | 685 rtc::SSLRole* role) { |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
772 | 753 |
773 if (!UpdateSessionState(action, cricket::CS_LOCAL, err_desc)) { | 754 if (!UpdateSessionState(action, cricket::CS_LOCAL, err_desc)) { |
774 return false; | 755 return false; |
775 } | 756 } |
776 | 757 |
777 if (remote_desc_) { | 758 if (remote_desc_) { |
778 // Now that we have a local description, we can push down remote candidates. | 759 // Now that we have a local description, we can push down remote candidates. |
779 UseCandidatesInSessionDescription(remote_desc_.get()); | 760 UseCandidatesInSessionDescription(remote_desc_.get()); |
780 } | 761 } |
781 | 762 |
| 763 pending_ice_restarts_.clear(); |
| 764 |
782 if (error() != ERROR_NONE) { | 765 if (error() != ERROR_NONE) { |
783 return BadLocalSdp(desc->type(), GetSessionErrorMsg(), err_desc); | 766 return BadLocalSdp(desc->type(), GetSessionErrorMsg(), err_desc); |
784 } | 767 } |
785 return true; | 768 return true; |
786 } | 769 } |
787 | 770 |
788 bool WebRtcSession::SetRemoteDescription(SessionDescriptionInterface* desc, | 771 bool WebRtcSession::SetRemoteDescription(SessionDescriptionInterface* desc, |
789 std::string* err_desc) { | 772 std::string* err_desc) { |
790 ASSERT(signaling_thread()->IsCurrent()); | 773 ASSERT(signaling_thread()->IsCurrent()); |
791 | 774 |
(...skipping 23 matching lines...) Expand all Loading... |
815 // NOTE: Candidates allocation will be initiated only when SetLocalDescription | 798 // NOTE: Candidates allocation will be initiated only when SetLocalDescription |
816 // is called. | 799 // is called. |
817 if (!UpdateSessionState(action, cricket::CS_REMOTE, err_desc)) { | 800 if (!UpdateSessionState(action, cricket::CS_REMOTE, err_desc)) { |
818 return false; | 801 return false; |
819 } | 802 } |
820 | 803 |
821 if (local_desc_ && !UseCandidatesInSessionDescription(desc)) { | 804 if (local_desc_ && !UseCandidatesInSessionDescription(desc)) { |
822 return BadRemoteSdp(desc->type(), kInvalidCandidates, err_desc); | 805 return BadRemoteSdp(desc->type(), kInvalidCandidates, err_desc); |
823 } | 806 } |
824 | 807 |
825 // Check if this new SessionDescription contains new ice ufrag and password | 808 if (old_remote_desc) { |
826 // that indicates the remote peer requests ice restart. | 809 for (const cricket::ContentInfo& content : |
827 bool ice_restart = | 810 old_remote_desc->description()->contents()) { |
828 ice_restart_latch_->CheckForRemoteIceRestart(old_remote_desc.get(), desc); | 811 // Check if this new SessionDescription contains new ICE ufrag and |
829 // We retain all received candidates only if ICE is not restarted. | 812 // password that indicates the remote peer requests an ICE restart. |
830 // When ICE is restarted, all previous candidates belong to an old generation | 813 // TODO(deadbeef): When we start storing both the current and pending |
831 // and should not be kept. | 814 // remote description, this should reset pending_ice_restarts and compare |
832 // TODO(deadbeef): This goes against the W3C spec which says the remote | 815 // against the current description. |
833 // description should only contain candidates from the last set remote | 816 if (CheckForRemoteIceRestart(old_remote_desc.get(), desc, content.name)) { |
834 // description plus any candidates added since then. We should remove this | 817 if (action == kOffer) { |
835 // once we're sure it won't break anything. | 818 pending_ice_restarts_.insert(content.name); |
836 if (!ice_restart) { | 819 } |
837 WebRtcSessionDescriptionFactory::CopyCandidatesFromSessionDescription( | 820 } else { |
838 old_remote_desc.get(), desc); | 821 // We retain all received candidates only if ICE is not restarted. |
| 822 // When ICE is restarted, all previous candidates belong to an old |
| 823 // generation and should not be kept. |
| 824 // TODO(deadbeef): This goes against the W3C spec which says the remote |
| 825 // description should only contain candidates from the last set remote |
| 826 // description plus any candidates added since then. We should remove |
| 827 // this once we're sure it won't break anything. |
| 828 WebRtcSessionDescriptionFactory::CopyCandidatesFromSessionDescription( |
| 829 old_remote_desc.get(), content.name, desc); |
| 830 } |
| 831 } |
839 } | 832 } |
840 | 833 |
841 if (error() != ERROR_NONE) { | 834 if (error() != ERROR_NONE) { |
842 return BadRemoteSdp(desc->type(), GetSessionErrorMsg(), err_desc); | 835 return BadRemoteSdp(desc->type(), GetSessionErrorMsg(), err_desc); |
843 } | 836 } |
844 | 837 |
845 // Set the the ICE connection state to connecting since the connection may | 838 // Set the the ICE connection state to connecting since the connection may |
846 // become writable with peer reflexive candidates before any remote candidate | 839 // become writable with peer reflexive candidates before any remote candidate |
847 // is signaled. | 840 // is signaled. |
848 // TODO(pthatcher): This is a short-term solution for crbug/446908. A real fix | 841 // 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... |
1087 return transport_controller_->GetLocalCertificate(transport_name, | 1080 return transport_controller_->GetLocalCertificate(transport_name, |
1088 certificate); | 1081 certificate); |
1089 } | 1082 } |
1090 | 1083 |
1091 bool WebRtcSession::GetRemoteSSLCertificate(const std::string& transport_name, | 1084 bool WebRtcSession::GetRemoteSSLCertificate(const std::string& transport_name, |
1092 rtc::SSLCertificate** cert) { | 1085 rtc::SSLCertificate** cert) { |
1093 ASSERT(signaling_thread()->IsCurrent()); | 1086 ASSERT(signaling_thread()->IsCurrent()); |
1094 return transport_controller_->GetRemoteSSLCertificate(transport_name, cert); | 1087 return transport_controller_->GetRemoteSSLCertificate(transport_name, cert); |
1095 } | 1088 } |
1096 | 1089 |
1097 cricket::BaseChannel* WebRtcSession::GetChannel( | |
1098 const std::string& content_name) { | |
1099 if (voice_channel() && voice_channel()->content_name() == content_name) { | |
1100 return voice_channel(); | |
1101 } | |
1102 if (video_channel() && video_channel()->content_name() == content_name) { | |
1103 return video_channel(); | |
1104 } | |
1105 if (data_channel() && data_channel()->content_name() == content_name) { | |
1106 return data_channel(); | |
1107 } | |
1108 return nullptr; | |
1109 } | |
1110 | |
1111 bool WebRtcSession::EnableBundle(const cricket::ContentGroup& bundle) { | 1090 bool WebRtcSession::EnableBundle(const cricket::ContentGroup& bundle) { |
1112 const std::string* first_content_name = bundle.FirstContentName(); | 1091 const std::string* first_content_name = bundle.FirstContentName(); |
1113 if (!first_content_name) { | 1092 if (!first_content_name) { |
1114 LOG(LS_WARNING) << "Tried to BUNDLE with no contents."; | 1093 LOG(LS_WARNING) << "Tried to BUNDLE with no contents."; |
1115 return false; | 1094 return false; |
1116 } | 1095 } |
1117 const std::string& transport_name = *first_content_name; | 1096 const std::string& transport_name = *first_content_name; |
1118 cricket::BaseChannel* first_channel = GetChannel(transport_name); | 1097 cricket::BaseChannel* first_channel = GetChannel(transport_name); |
1119 | 1098 |
1120 auto maybe_set_transport = [this, bundle, transport_name, | 1099 auto maybe_set_transport = [this, bundle, transport_name, |
(...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1425 } | 1404 } |
1426 | 1405 |
1427 bool WebRtcSession::ReadyToSendData() const { | 1406 bool WebRtcSession::ReadyToSendData() const { |
1428 return data_channel_ && data_channel_->ready_to_send_data(); | 1407 return data_channel_ && data_channel_->ready_to_send_data(); |
1429 } | 1408 } |
1430 | 1409 |
1431 cricket::DataChannelType WebRtcSession::data_channel_type() const { | 1410 cricket::DataChannelType WebRtcSession::data_channel_type() const { |
1432 return data_channel_type_; | 1411 return data_channel_type_; |
1433 } | 1412 } |
1434 | 1413 |
1435 bool WebRtcSession::IceRestartPending() const { | 1414 bool WebRtcSession::IceRestartPending(const std::string& content_name) const { |
1436 return ice_restart_latch_->Get(); | 1415 return pending_ice_restarts_.find(content_name) != |
1437 } | 1416 pending_ice_restarts_.end(); |
1438 | |
1439 void WebRtcSession::ResetIceRestartLatch() { | |
1440 ice_restart_latch_->Reset(); | |
1441 } | 1417 } |
1442 | 1418 |
1443 void WebRtcSession::OnCertificateReady( | 1419 void WebRtcSession::OnCertificateReady( |
1444 const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) { | 1420 const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) { |
1445 transport_controller_->SetLocalCertificate(certificate); | 1421 transport_controller_->SetLocalCertificate(certificate); |
1446 } | 1422 } |
1447 | 1423 |
1448 bool WebRtcSession::waiting_for_certificate_for_testing() const { | 1424 bool WebRtcSession::waiting_for_certificate_for_testing() const { |
1449 return webrtc_session_desc_factory_->waiting_for_certificate_for_testing(); | 1425 return webrtc_session_desc_factory_->waiting_for_certificate_for_testing(); |
1450 } | 1426 } |
(...skipping 692 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2143 } | 2119 } |
2144 } | 2120 } |
2145 | 2121 |
2146 void WebRtcSession::OnSentPacket_w(cricket::TransportChannel* channel, | 2122 void WebRtcSession::OnSentPacket_w(cricket::TransportChannel* channel, |
2147 const rtc::SentPacket& sent_packet) { | 2123 const rtc::SentPacket& sent_packet) { |
2148 RTC_DCHECK(worker_thread()->IsCurrent()); | 2124 RTC_DCHECK(worker_thread()->IsCurrent()); |
2149 media_controller_->call_w()->OnSentPacket(sent_packet); | 2125 media_controller_->call_w()->OnSentPacket(sent_packet); |
2150 } | 2126 } |
2151 | 2127 |
2152 } // namespace webrtc | 2128 } // namespace webrtc |
OLD | NEW |