Chromium Code Reviews| 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 |