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