| OLD | NEW |
| 1 /* | 1 /* |
| 2 * libjingle | 2 * libjingle |
| 3 * Copyright 2012 Google Inc. | 3 * Copyright 2012 Google Inc. |
| 4 * | 4 * |
| 5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions are met: | 6 * modification, are permitted provided that the following conditions are met: |
| 7 * | 7 * |
| 8 * 1. Redistributions of source code must retain the above copyright notice, | 8 * 1. Redistributions of source code must retain the above copyright notice, |
| 9 * this list of conditions and the following disclaimer. | 9 * this list of conditions and the following disclaimer. |
| 10 * 2. Redistributions in binary form must reproduce the above copyright notice, | 10 * 2. Redistributions in binary form must reproduce the above copyright notice, |
| (...skipping 456 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 467 return cricket::CF_RELAY; | 467 return cricket::CF_RELAY; |
| 468 case PeerConnectionInterface::kNoHost: | 468 case PeerConnectionInterface::kNoHost: |
| 469 return (cricket::CF_ALL & ~cricket::CF_HOST); | 469 return (cricket::CF_ALL & ~cricket::CF_HOST); |
| 470 case PeerConnectionInterface::kAll: | 470 case PeerConnectionInterface::kAll: |
| 471 return cricket::CF_ALL; | 471 return cricket::CF_ALL; |
| 472 default: ASSERT(false); | 472 default: ASSERT(false); |
| 473 } | 473 } |
| 474 return cricket::CF_NONE; | 474 return cricket::CF_NONE; |
| 475 } | 475 } |
| 476 | 476 |
| 477 // Help class used to remember if a a remote peer has requested ice restart by | 477 // Helper class used to remember if a a remote peer has requested ICE restart |
| 478 // by sending a description with new ice ufrag and password. | 478 // by sending a description with a new ice ufrag and password. |
| 479 class IceRestartAnswerLatch { | 479 class IceRestartAnswerLatch { |
| 480 public: | 480 public: |
| 481 IceRestartAnswerLatch() : ice_restart_(false) { } | 481 IceRestartAnswerLatch(cricket::MediaType media_type) |
| 482 : ice_restart_(false), media_type_(media_type) {} |
| 482 | 483 |
| 483 // Returns true if CheckForRemoteIceRestart has been called with a new session | 484 // Returns true if CheckForRemoteIceRestart has been called with a new session |
| 484 // description where ice password and ufrag has changed since last time | 485 // description where ice password and ufrag has changed since last time |
| 485 // Reset() was called. | 486 // Reset() was called. |
| 486 bool Get() const { | 487 bool Get() const { |
| 487 return ice_restart_; | 488 return ice_restart_; |
| 488 } | 489 } |
| 489 | 490 |
| 490 void Reset() { | 491 void Reset() { ice_restart_ = false; } |
| 491 if (ice_restart_) { | |
| 492 ice_restart_ = false; | |
| 493 } | |
| 494 } | |
| 495 | 492 |
| 496 bool CheckForRemoteIceRestart(const SessionDescriptionInterface* old_desc, | 493 bool CheckForRemoteIceRestart(const SessionDescriptionInterface* old_desc, |
| 497 const SessionDescriptionInterface* new_desc) { | 494 const SessionDescriptionInterface* new_desc) { |
| 498 if (!old_desc || new_desc->type() != SessionDescriptionInterface::kOffer) { | 495 if (!old_desc || new_desc->type() != SessionDescriptionInterface::kOffer) { |
| 499 return false; | 496 return false; |
| 500 } | 497 } |
| 501 const SessionDescription* new_sd = new_desc->description(); | 498 const SessionDescription* new_sd = new_desc->description(); |
| 502 const SessionDescription* old_sd = old_desc->description(); | 499 const SessionDescription* old_sd = old_desc->description(); |
| 503 const ContentInfos& contents = new_sd->contents(); | 500 const ContentInfo* cinfo = |
| 504 for (size_t index = 0; index < contents.size(); ++index) { | 501 GetFirstMediaContent(new_sd->contents(), media_type_); |
| 505 const ContentInfo* cinfo = &contents[index]; | 502 if (!cinfo || cinfo->rejected) { |
| 506 if (cinfo->rejected) { | 503 return false; |
| 507 continue; | 504 } |
| 508 } | 505 // If the content isn't rejected, check if ufrag and password has changed. |
| 509 // If the content isn't rejected, check if ufrag and password has | 506 const cricket::TransportDescription* new_transport_desc = |
| 510 // changed. | 507 new_sd->GetTransportDescriptionByName(cinfo->name); |
| 511 const cricket::TransportDescription* new_transport_desc = | 508 const cricket::TransportDescription* old_transport_desc = |
| 512 new_sd->GetTransportDescriptionByName(cinfo->name); | 509 old_sd->GetTransportDescriptionByName(cinfo->name); |
| 513 const cricket::TransportDescription* old_transport_desc = | 510 if (!new_transport_desc || !old_transport_desc) { |
| 514 old_sd->GetTransportDescriptionByName(cinfo->name); | 511 // No transport description exists. This is not an ICE restart. |
| 515 if (!new_transport_desc || !old_transport_desc) { | 512 return false; |
| 516 // No transport description exist. This is not an ice restart. | 513 } |
| 517 continue; | 514 if (cricket::IceCredentialsChanged( |
| 518 } | 515 old_transport_desc->ice_ufrag, old_transport_desc->ice_pwd, |
| 519 if (cricket::IceCredentialsChanged(old_transport_desc->ice_ufrag, | 516 new_transport_desc->ice_ufrag, new_transport_desc->ice_pwd)) { |
| 520 old_transport_desc->ice_pwd, | 517 LOG(LS_INFO) << "Remote peer requested ICE restart for media type: " |
| 521 new_transport_desc->ice_ufrag, | 518 << media_type_; |
| 522 new_transport_desc->ice_pwd)) { | 519 ice_restart_ = true; |
| 523 LOG(LS_INFO) << "Remote peer request ice restart."; | 520 return true; |
| 524 ice_restart_ = true; | |
| 525 return true; | |
| 526 } | |
| 527 } | 521 } |
| 528 return false; | 522 return false; |
| 529 } | 523 } |
| 530 | 524 |
| 531 private: | 525 private: |
| 532 bool ice_restart_; | 526 bool ice_restart_; |
| 527 cricket::MediaType media_type_; |
| 533 }; | 528 }; |
| 534 | 529 |
| 535 WebRtcSession::WebRtcSession(webrtc::MediaControllerInterface* media_controller, | 530 WebRtcSession::WebRtcSession(webrtc::MediaControllerInterface* media_controller, |
| 536 rtc::Thread* signaling_thread, | 531 rtc::Thread* signaling_thread, |
| 537 rtc::Thread* worker_thread, | 532 rtc::Thread* worker_thread, |
| 538 cricket::PortAllocator* port_allocator) | 533 cricket::PortAllocator* port_allocator) |
| 539 : signaling_thread_(signaling_thread), | 534 : signaling_thread_(signaling_thread), |
| 540 worker_thread_(worker_thread), | 535 worker_thread_(worker_thread), |
| 541 port_allocator_(port_allocator), | 536 port_allocator_(port_allocator), |
| 542 // RFC 3264: The numeric value of the session id and version in the | 537 // RFC 3264: The numeric value of the session id and version in the |
| 543 // o line MUST be representable with a "64 bit signed integer". | 538 // o line MUST be representable with a "64 bit signed integer". |
| 544 // Due to this constraint session id |sid_| is max limited to LLONG_MAX. | 539 // Due to this constraint session id |sid_| is max limited to LLONG_MAX. |
| 545 sid_(rtc::ToString(rtc::CreateRandomId64() & LLONG_MAX)), | 540 sid_(rtc::ToString(rtc::CreateRandomId64() & LLONG_MAX)), |
| 546 transport_controller_(new cricket::TransportController(signaling_thread, | 541 transport_controller_(new cricket::TransportController(signaling_thread, |
| 547 worker_thread, | 542 worker_thread, |
| 548 port_allocator)), | 543 port_allocator)), |
| 549 media_controller_(media_controller), | 544 media_controller_(media_controller), |
| 550 channel_manager_(media_controller_->channel_manager()), | 545 channel_manager_(media_controller_->channel_manager()), |
| 551 ice_observer_(NULL), | 546 ice_observer_(NULL), |
| 552 ice_connection_state_(PeerConnectionInterface::kIceConnectionNew), | 547 ice_connection_state_(PeerConnectionInterface::kIceConnectionNew), |
| 553 ice_connection_receiving_(true), | 548 ice_connection_receiving_(true), |
| 554 older_version_remote_peer_(false), | 549 older_version_remote_peer_(false), |
| 555 dtls_enabled_(false), | 550 dtls_enabled_(false), |
| 556 data_channel_type_(cricket::DCT_NONE), | 551 data_channel_type_(cricket::DCT_NONE), |
| 557 ice_restart_latch_(new IceRestartAnswerLatch), | 552 audio_ice_restart_latch_( |
| 553 new IceRestartAnswerLatch(cricket::MEDIA_TYPE_AUDIO)), |
| 554 video_ice_restart_latch_( |
| 555 new IceRestartAnswerLatch(cricket::MEDIA_TYPE_VIDEO)), |
| 556 data_ice_restart_latch_( |
| 557 new IceRestartAnswerLatch(cricket::MEDIA_TYPE_DATA)), |
| 558 metrics_observer_(NULL) { | 558 metrics_observer_(NULL) { |
| 559 transport_controller_->SetIceRole(cricket::ICEROLE_CONTROLLED); | 559 transport_controller_->SetIceRole(cricket::ICEROLE_CONTROLLED); |
| 560 transport_controller_->SignalConnectionState.connect( | 560 transport_controller_->SignalConnectionState.connect( |
| 561 this, &WebRtcSession::OnTransportControllerConnectionState); | 561 this, &WebRtcSession::OnTransportControllerConnectionState); |
| 562 transport_controller_->SignalReceiving.connect( | 562 transport_controller_->SignalReceiving.connect( |
| 563 this, &WebRtcSession::OnTransportControllerReceiving); | 563 this, &WebRtcSession::OnTransportControllerReceiving); |
| 564 transport_controller_->SignalGatheringState.connect( | 564 transport_controller_->SignalGatheringState.connect( |
| 565 this, &WebRtcSession::OnTransportControllerGatheringState); | 565 this, &WebRtcSession::OnTransportControllerGatheringState); |
| 566 transport_controller_->SignalCandidatesGathered.connect( | 566 transport_controller_->SignalCandidatesGathered.connect( |
| 567 this, &WebRtcSession::OnTransportControllerCandidatesGathered); | 567 this, &WebRtcSession::OnTransportControllerCandidatesGathered); |
| (...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 828 | 828 |
| 829 if (!UpdateSessionState(action, cricket::CS_LOCAL, err_desc)) { | 829 if (!UpdateSessionState(action, cricket::CS_LOCAL, err_desc)) { |
| 830 return false; | 830 return false; |
| 831 } | 831 } |
| 832 | 832 |
| 833 if (remote_desc_) { | 833 if (remote_desc_) { |
| 834 // Now that we have a local description, we can push down remote candidates. | 834 // Now that we have a local description, we can push down remote candidates. |
| 835 UseCandidatesInSessionDescription(remote_desc_.get()); | 835 UseCandidatesInSessionDescription(remote_desc_.get()); |
| 836 } | 836 } |
| 837 | 837 |
| 838 audio_ice_restart_latch_->Reset(); |
| 839 video_ice_restart_latch_->Reset(); |
| 840 data_ice_restart_latch_->Reset(); |
| 841 |
| 838 if (error() != ERROR_NONE) { | 842 if (error() != ERROR_NONE) { |
| 839 return BadLocalSdp(desc->type(), GetSessionErrorMsg(), err_desc); | 843 return BadLocalSdp(desc->type(), GetSessionErrorMsg(), err_desc); |
| 840 } | 844 } |
| 841 return true; | 845 return true; |
| 842 } | 846 } |
| 843 | 847 |
| 844 bool WebRtcSession::SetRemoteDescription(SessionDescriptionInterface* desc, | 848 bool WebRtcSession::SetRemoteDescription(SessionDescriptionInterface* desc, |
| 845 std::string* err_desc) { | 849 std::string* err_desc) { |
| 846 ASSERT(signaling_thread()->IsCurrent()); | 850 ASSERT(signaling_thread()->IsCurrent()); |
| 847 | 851 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 871 // NOTE: Candidates allocation will be initiated only when SetLocalDescription | 875 // NOTE: Candidates allocation will be initiated only when SetLocalDescription |
| 872 // is called. | 876 // is called. |
| 873 if (!UpdateSessionState(action, cricket::CS_REMOTE, err_desc)) { | 877 if (!UpdateSessionState(action, cricket::CS_REMOTE, err_desc)) { |
| 874 return false; | 878 return false; |
| 875 } | 879 } |
| 876 | 880 |
| 877 if (local_desc_ && !UseCandidatesInSessionDescription(desc)) { | 881 if (local_desc_ && !UseCandidatesInSessionDescription(desc)) { |
| 878 return BadRemoteSdp(desc->type(), kInvalidCandidates, err_desc); | 882 return BadRemoteSdp(desc->type(), kInvalidCandidates, err_desc); |
| 879 } | 883 } |
| 880 | 884 |
| 885 audio_ice_restart_latch_->Reset(); |
| 886 video_ice_restart_latch_->Reset(); |
| 887 data_ice_restart_latch_->Reset(); |
| 888 |
| 881 // Check if this new SessionDescription contains new ice ufrag and password | 889 // Check if this new SessionDescription contains new ice ufrag and password |
| 882 // that indicates the remote peer requests ice restart. | 890 // that indicates the remote peer requests ice restart. |
| 883 bool ice_restart = | 891 if (!audio_ice_restart_latch_->CheckForRemoteIceRestart(old_remote_desc.get(), |
| 884 ice_restart_latch_->CheckForRemoteIceRestart(old_remote_desc.get(), desc); | 892 desc)) { |
| 885 // We retain all received candidates only if ICE is not restarted. | 893 // We retain all received candidates only if ICE is not restarted. |
| 886 // When ICE is restarted, all previous candidates belong to an old generation | 894 // When ICE is restarted, all previous candidates belong to an old |
| 887 // and should not be kept. | 895 // generation |
| 888 // TODO(deadbeef): This goes against the W3C spec which says the remote | 896 // and should not be kept. |
| 889 // description should only contain candidates from the last set remote | 897 // TODO(deadbeef): This goes against the W3C spec which says the remote |
| 890 // description plus any candidates added since then. We should remove this | 898 // description should only contain candidates from the last set remote |
| 891 // once we're sure it won't break anything. | 899 // description plus any candidates added since then. We should remove this |
| 892 if (!ice_restart) { | 900 // once we're sure it won't break anything. |
| 893 WebRtcSessionDescriptionFactory::CopyCandidatesFromSessionDescription( | 901 WebRtcSessionDescriptionFactory::CopyCandidatesFromSessionDescription( |
| 894 old_remote_desc.get(), desc); | 902 old_remote_desc.get(), cricket::MEDIA_TYPE_AUDIO, desc); |
| 903 } |
| 904 if (!video_ice_restart_latch_->CheckForRemoteIceRestart(old_remote_desc.get(), |
| 905 desc)) { |
| 906 WebRtcSessionDescriptionFactory::CopyCandidatesFromSessionDescription( |
| 907 old_remote_desc.get(), cricket::MEDIA_TYPE_VIDEO, desc); |
| 908 } |
| 909 if (!data_ice_restart_latch_->CheckForRemoteIceRestart(old_remote_desc.get(), |
| 910 desc)) { |
| 911 WebRtcSessionDescriptionFactory::CopyCandidatesFromSessionDescription( |
| 912 old_remote_desc.get(), cricket::MEDIA_TYPE_DATA, desc); |
| 895 } | 913 } |
| 896 | 914 |
| 897 if (error() != ERROR_NONE) { | 915 if (error() != ERROR_NONE) { |
| 898 return BadRemoteSdp(desc->type(), GetSessionErrorMsg(), err_desc); | 916 return BadRemoteSdp(desc->type(), GetSessionErrorMsg(), err_desc); |
| 899 } | 917 } |
| 900 | 918 |
| 901 // Set the the ICE connection state to connecting since the connection may | 919 // Set the the ICE connection state to connecting since the connection may |
| 902 // become writable with peer reflexive candidates before any remote candidate | 920 // become writable with peer reflexive candidates before any remote candidate |
| 903 // is signaled. | 921 // is signaled. |
| 904 // TODO(pthatcher): This is a short-term solution for crbug/446908. A real fix | 922 // TODO(pthatcher): This is a short-term solution for crbug/446908. A real fix |
| (...skipping 563 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1468 } | 1486 } |
| 1469 | 1487 |
| 1470 bool WebRtcSession::ReadyToSendData() const { | 1488 bool WebRtcSession::ReadyToSendData() const { |
| 1471 return data_channel_ && data_channel_->ready_to_send_data(); | 1489 return data_channel_ && data_channel_->ready_to_send_data(); |
| 1472 } | 1490 } |
| 1473 | 1491 |
| 1474 cricket::DataChannelType WebRtcSession::data_channel_type() const { | 1492 cricket::DataChannelType WebRtcSession::data_channel_type() const { |
| 1475 return data_channel_type_; | 1493 return data_channel_type_; |
| 1476 } | 1494 } |
| 1477 | 1495 |
| 1478 bool WebRtcSession::IceRestartPending() const { | 1496 bool WebRtcSession::AudioIceRestartPending() const { |
| 1479 return ice_restart_latch_->Get(); | 1497 return audio_ice_restart_latch_->Get(); |
| 1480 } | 1498 } |
| 1481 | 1499 |
| 1482 void WebRtcSession::ResetIceRestartLatch() { | 1500 bool WebRtcSession::VideoIceRestartPending() const { |
| 1483 ice_restart_latch_->Reset(); | 1501 return video_ice_restart_latch_->Get(); |
| 1502 } |
| 1503 |
| 1504 bool WebRtcSession::DataIceRestartPending() const { |
| 1505 return data_ice_restart_latch_->Get(); |
| 1484 } | 1506 } |
| 1485 | 1507 |
| 1486 void WebRtcSession::OnCertificateReady( | 1508 void WebRtcSession::OnCertificateReady( |
| 1487 const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) { | 1509 const rtc::scoped_refptr<rtc::RTCCertificate>& certificate) { |
| 1488 transport_controller_->SetLocalCertificate(certificate); | 1510 transport_controller_->SetLocalCertificate(certificate); |
| 1489 } | 1511 } |
| 1490 | 1512 |
| 1491 bool WebRtcSession::waiting_for_certificate_for_testing() const { | 1513 bool WebRtcSession::waiting_for_certificate_for_testing() const { |
| 1492 return webrtc_session_desc_factory_->waiting_for_certificate_for_testing(); | 1514 return webrtc_session_desc_factory_->waiting_for_certificate_for_testing(); |
| 1493 } | 1515 } |
| (...skipping 694 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2188 } | 2210 } |
| 2189 } | 2211 } |
| 2190 | 2212 |
| 2191 void WebRtcSession::OnSentPacket_w(cricket::TransportChannel* channel, | 2213 void WebRtcSession::OnSentPacket_w(cricket::TransportChannel* channel, |
| 2192 const rtc::SentPacket& sent_packet) { | 2214 const rtc::SentPacket& sent_packet) { |
| 2193 RTC_DCHECK(worker_thread()->IsCurrent()); | 2215 RTC_DCHECK(worker_thread()->IsCurrent()); |
| 2194 media_controller_->call_w()->OnSentPacket(sent_packet); | 2216 media_controller_->call_w()->OnSentPacket(sent_packet); |
| 2195 } | 2217 } |
| 2196 | 2218 |
| 2197 } // namespace webrtc | 2219 } // namespace webrtc |
| OLD | NEW |