diff --git a/pc/peer_connection.cc b/pc/peer_connection.cc index 4953494d88..55b264e1c5 100644 --- a/pc/peer_connection.cc +++ b/pc/peer_connection.cc @@ -2295,7 +2295,7 @@ void PeerConnection::SetLocalDescription( } } - NoteUsageEvent(UsageEvent::SET_LOCAL_DESCRIPTION_CALLED); + NoteUsageEvent(UsageEvent::SET_LOCAL_DESCRIPTION_SUCCEEDED); } RTCError PeerConnection::ApplyLocalDescription( @@ -2669,7 +2669,7 @@ void PeerConnection::SetRemoteDescription( } observer->OnSetRemoteDescriptionComplete(RTCError::OK()); - NoteUsageEvent(UsageEvent::SET_REMOTE_DESCRIPTION_CALLED); + NoteUsageEvent(UsageEvent::SET_REMOTE_DESCRIPTION_SUCCEEDED); } RTCError PeerConnection::ApplyRemoteDescription( @@ -3695,13 +3695,7 @@ bool PeerConnection::AddIceCandidate( if (ready) { bool result = UseCandidate(ice_candidate); if (result) { - NoteUsageEvent(UsageEvent::REMOTE_CANDIDATE_ADDED); - if (ice_candidate->candidate().address().IsUnresolvedIP()) { - NoteUsageEvent(UsageEvent::REMOTE_MDNS_CANDIDATE_ADDED); - } - if (ice_candidate->candidate().address().IsPrivateIP()) { - NoteUsageEvent(UsageEvent::REMOTE_PRIVATE_CANDIDATE_ADDED); - } + NoteUsageEvent(UsageEvent::ADD_ICE_CANDIDATE_SUCCEEDED); NoteAddIceCandidateResult(kAddIceCandidateSuccess); } else { NoteAddIceCandidateResult(kAddIceCandidateFailNotUsable); @@ -4245,15 +4239,7 @@ void PeerConnection::OnIceCandidate( if (IsClosed()) { return; } - NoteUsageEvent(UsageEvent::CANDIDATE_COLLECTED); - if (candidate->candidate().type() == LOCAL_PORT_TYPE && - candidate->candidate().address().IsPrivateIP()) { - NoteUsageEvent(UsageEvent::PRIVATE_CANDIDATE_COLLECTED); - } - if (candidate->candidate().type() == LOCAL_PORT_TYPE && - candidate->candidate().address().IsUnresolvedIP()) { - NoteUsageEvent(UsageEvent::MDNS_CANDIDATE_COLLECTED); - } + ReportIceCandidateCollected(candidate->candidate()); Observer()->OnIceCandidate(candidate.get()); } @@ -4280,6 +4266,7 @@ void PeerConnection::OnSelectedCandidatePairChanged( if (IsClosed()) { return; } + Observer()->OnIceSelectedCandidatePairChanged(event); } @@ -6344,6 +6331,7 @@ bool PeerConnection::UseCandidate(const IceCandidateInterface* candidate) { RTCError error = transport_controller_->AddRemoteCandidates( result.value()->name, candidates); if (error.ok()) { + ReportRemoteIceCandidateAdded(candidate->candidate()); // Candidates successfully submitted for checking. if (ice_connection_state_ == PeerConnectionInterface::kIceConnectionNew || ice_connection_state_ == @@ -6954,6 +6942,34 @@ void PeerConnection::ReportSdpFormatReceived( kSdpFormatReceivedMax); } +void PeerConnection::ReportIceCandidateCollected( + const cricket::Candidate& candidate) { + NoteUsageEvent(UsageEvent::CANDIDATE_COLLECTED); + if (candidate.address().IsPrivateIP()) { + NoteUsageEvent(UsageEvent::PRIVATE_CANDIDATE_COLLECTED); + } + if (candidate.address().IsUnresolvedIP()) { + NoteUsageEvent(UsageEvent::MDNS_CANDIDATE_COLLECTED); + } + if (candidate.address().family() == AF_INET6) { + NoteUsageEvent(UsageEvent::IPV6_CANDIDATE_COLLECTED); + } +} + +void PeerConnection::ReportRemoteIceCandidateAdded( + const cricket::Candidate& candidate) { + NoteUsageEvent(UsageEvent::REMOTE_CANDIDATE_ADDED); + if (candidate.address().IsPrivateIP()) { + NoteUsageEvent(UsageEvent::REMOTE_PRIVATE_CANDIDATE_ADDED); + } + if (candidate.address().IsUnresolvedIP()) { + NoteUsageEvent(UsageEvent::REMOTE_MDNS_CANDIDATE_ADDED); + } + if (candidate.address().family() == AF_INET6) { + NoteUsageEvent(UsageEvent::REMOTE_IPV6_CANDIDATE_ADDED); + } +} + void PeerConnection::NoteUsageEvent(UsageEvent event) { RTC_DCHECK_RUN_ON(signaling_thread()); usage_event_accumulator_ |= static_cast(event); @@ -6965,10 +6981,10 @@ void PeerConnection::ReportUsagePattern() const { usage_event_accumulator_, static_cast(UsageEvent::MAX_VALUE)); const int bad_bits = - static_cast(UsageEvent::SET_LOCAL_DESCRIPTION_CALLED) | + static_cast(UsageEvent::SET_LOCAL_DESCRIPTION_SUCCEEDED) | static_cast(UsageEvent::CANDIDATE_COLLECTED); const int good_bits = - static_cast(UsageEvent::SET_REMOTE_DESCRIPTION_CALLED) | + static_cast(UsageEvent::SET_REMOTE_DESCRIPTION_SUCCEEDED) | static_cast(UsageEvent::REMOTE_CANDIDATE_ADDED) | static_cast(UsageEvent::ICE_STATE_CONNECTED); if ((usage_event_accumulator_ & bad_bits) == bad_bits && diff --git a/pc/peer_connection.h b/pc/peer_connection.h index bca03ef3fd..af86b01984 100644 --- a/pc/peer_connection.h +++ b/pc/peer_connection.h @@ -64,23 +64,45 @@ class PeerConnection : public PeerConnectionInternal, public rtc::MessageHandler, public sigslot::has_slots<> { public: + // A bit in the usage pattern is registered when its defining event occurs at + // least once. enum class UsageEvent : int { TURN_SERVER_ADDED = 0x01, STUN_SERVER_ADDED = 0x02, DATA_ADDED = 0x04, AUDIO_ADDED = 0x08, VIDEO_ADDED = 0x10, - SET_LOCAL_DESCRIPTION_CALLED = 0x20, - SET_REMOTE_DESCRIPTION_CALLED = 0x40, + // |SetLocalDescription| returns successfully. + SET_LOCAL_DESCRIPTION_SUCCEEDED = 0x20, + // |SetRemoteDescription| returns successfully. + SET_REMOTE_DESCRIPTION_SUCCEEDED = 0x40, + // A local candidate (with type host, server-reflexive, or relay) is + // collected. CANDIDATE_COLLECTED = 0x80, - REMOTE_CANDIDATE_ADDED = 0x100, + // A remote candidate is successfully added via |AddIceCandidate|. + ADD_ICE_CANDIDATE_SUCCEEDED = 0x100, ICE_STATE_CONNECTED = 0x200, CLOSE_CALLED = 0x400, + // A local candidate with private IP is collected. PRIVATE_CANDIDATE_COLLECTED = 0x800, + // A remote candidate with private IP is added, either via AddiceCandidate + // or from the remote description. REMOTE_PRIVATE_CANDIDATE_ADDED = 0x1000, + // A local mDNS candidate is collected. MDNS_CANDIDATE_COLLECTED = 0x2000, + // A remote mDNS candidate is added, either via AddIceCandidate or from the + // remote description. REMOTE_MDNS_CANDIDATE_ADDED = 0x4000, - MAX_VALUE = 0x8000, + // A local candidate with IPv6 address is collected. + IPV6_CANDIDATE_COLLECTED = 0x8000, + // A remote candidate with IPv6 address is added, either via AddIceCandidate + // or from the remote description. + REMOTE_IPV6_CANDIDATE_ADDED = 0x10000, + // A remote candidate (with type host, server-reflexive, or relay) is + // successfully added, either via AddIceCandidate or from the remote + // description. + REMOTE_CANDIDATE_ADDED = 0x20000, + MAX_VALUE = 0x40000, }; explicit PeerConnection(PeerConnectionFactory* factory, @@ -1070,6 +1092,10 @@ class PeerConnection : public PeerConnectionInternal, void ReportNegotiatedCiphers(const cricket::TransportStats& stats, const std::set& media_types) RTC_RUN_ON(signaling_thread()); + void ReportIceCandidateCollected(const cricket::Candidate& candidate) + RTC_RUN_ON(signaling_thread()); + void ReportRemoteIceCandidateAdded(const cricket::Candidate& candidate) + RTC_RUN_ON(signaling_thread()); void NoteUsageEvent(UsageEvent event); void ReportUsagePattern() const RTC_RUN_ON(signaling_thread()); diff --git a/pc/peer_connection_histogram_unittest.cc b/pc/peer_connection_histogram_unittest.cc index 2f997aecbd..c566d746fb 100644 --- a/pc/peer_connection_histogram_unittest.cc +++ b/pc/peer_connection_histogram_unittest.cc @@ -18,6 +18,7 @@ #include "absl/types/optional.h" #include "api/call/call_factory_interface.h" #include "api/jsep.h" +#include "api/jsep_session_description.h" #include "api/peer_connection_interface.h" #include "api/peer_connection_proxy.h" #include "api/rtc_error.h" @@ -32,6 +33,7 @@ #include "pc/peer_connection_wrapper.h" #include "pc/sdp_utils.h" #include "pc/test/mock_peer_connection_observers.h" +#include "pc/webrtc_sdp.h" #include "rtc_base/arraysize.h" #include "rtc_base/checks.h" #include "rtc_base/fake_mdns_responder.h" @@ -57,6 +59,8 @@ static constexpr int kDefaultTimeout = 10000; static const rtc::SocketAddress kLocalAddrs[2] = { rtc::SocketAddress("1.1.1.1", 0), rtc::SocketAddress("2.2.2.2", 0)}; static const rtc::SocketAddress kPrivateLocalAddress("10.1.1.1", 0); +static const rtc::SocketAddress kPrivateIpv6LocalAddress("fd12:3456:789a:1::1", + 0); int MakeUsageFingerprint(std::set events) { int signature = 0; @@ -121,8 +125,11 @@ class ObserverForUsageHistogramTest : public MockPeerConnectionObserver { interesting_usage_detected_ = absl::optional(); } + bool candidate_gathered() const { return candidate_gathered_; } + private: absl::optional interesting_usage_detected_; + bool candidate_gathered_ = false; RawWrapperPtr candidate_target_; // Note: Not thread-safe against deletions. }; @@ -206,6 +213,10 @@ class PeerConnectionWrapperForUsageHistogramTest return true; } + webrtc::PeerConnectionInterface::IceGatheringState ice_gathering_state() { + return pc()->ice_gathering_state(); + } + private: // Candidates that have been sent but not yet configured std::vector> @@ -214,10 +225,11 @@ class PeerConnectionWrapperForUsageHistogramTest void ObserverForUsageHistogramTest::OnIceCandidate( const webrtc::IceCandidateInterface* candidate) { + // If target is not set, ignore. This happens in one-ended unit tests. if (candidate_target_) { this->candidate_target_->AddOrBufferIceCandidate(candidate); } - // If target is not set, ignore. This happens in one-ended unit tests. + candidate_gathered_ = true; } class PeerConnectionUsageHistogramTest : public ::testing::Test { @@ -282,6 +294,19 @@ class PeerConnectionUsageHistogramTest : public ::testing::Test { std::move(port_allocator), false); } + WrapperPtr CreatePeerConnectionWithPrivateIpv6LocalAddresses() { + auto* fake_network = NewFakeNetwork(); + fake_network->AddInterface(NextLocalAddress()); + fake_network->AddInterface(kPrivateIpv6LocalAddress); + + auto port_allocator = + absl::make_unique(fake_network); + + return CreatePeerConnection(RTCConfiguration(), + PeerConnectionFactoryInterface::Options(), + std::move(port_allocator), false); + } + WrapperPtr CreatePeerConnection( const RTCConfiguration& config, const PeerConnectionFactoryInterface::Options factory_options, @@ -385,11 +410,12 @@ TEST_F(PeerConnectionUsageHistogramTest, FingerprintAudioVideo) { int expected_fingerprint = MakeUsageFingerprint( {PeerConnection::UsageEvent::AUDIO_ADDED, PeerConnection::UsageEvent::VIDEO_ADDED, - PeerConnection::UsageEvent::SET_LOCAL_DESCRIPTION_CALLED, - PeerConnection::UsageEvent::SET_REMOTE_DESCRIPTION_CALLED, + PeerConnection::UsageEvent::SET_LOCAL_DESCRIPTION_SUCCEEDED, + PeerConnection::UsageEvent::SET_REMOTE_DESCRIPTION_SUCCEEDED, PeerConnection::UsageEvent::CANDIDATE_COLLECTED, - PeerConnection::UsageEvent::REMOTE_CANDIDATE_ADDED, + PeerConnection::UsageEvent::ADD_ICE_CANDIDATE_SUCCEEDED, PeerConnection::UsageEvent::ICE_STATE_CONNECTED, + PeerConnection::UsageEvent::REMOTE_CANDIDATE_ADDED, PeerConnection::UsageEvent::CLOSE_CALLED}); // In this case, we may or may not have PRIVATE_CANDIDATE_COLLECTED, // depending on the machine configuration. @@ -405,32 +431,8 @@ TEST_F(PeerConnectionUsageHistogramTest, FingerprintAudioVideo) { 2); } -// Test getting the usage fingerprint when there are no host candidates. -TEST_F(PeerConnectionUsageHistogramTest, FingerprintWithNoHostCandidates) { - RTCConfiguration config; - config.type = PeerConnectionInterface::kNoHost; - auto caller = CreatePeerConnection(config); - auto callee = CreatePeerConnection(config); - caller->AddAudioTrack("audio"); - caller->AddVideoTrack("video"); - ASSERT_TRUE(caller->ConnectTo(callee.get())); - caller->pc()->Close(); - callee->pc()->Close(); - int expected_fingerprint = MakeUsageFingerprint( - {PeerConnection::UsageEvent::AUDIO_ADDED, - PeerConnection::UsageEvent::VIDEO_ADDED, - PeerConnection::UsageEvent::SET_LOCAL_DESCRIPTION_CALLED, - PeerConnection::UsageEvent::SET_REMOTE_DESCRIPTION_CALLED, - PeerConnection::UsageEvent::CANDIDATE_COLLECTED, - PeerConnection::UsageEvent::REMOTE_CANDIDATE_ADDED, - PeerConnection::UsageEvent::ICE_STATE_CONNECTED, - PeerConnection::UsageEvent::CLOSE_CALLED}); - EXPECT_EQ(2, webrtc::metrics::NumSamples(kUsagePatternMetric)); - EXPECT_EQ( - 2, webrtc::metrics::NumEvents(kUsagePatternMetric, expected_fingerprint)); -} - -// Test getting the usage fingerprint when there are no host candidates. +// Test getting the usage fingerprint when the caller collects an mDNS +// candidate. TEST_F(PeerConnectionUsageHistogramTest, FingerprintWithMdnsCaller) { RTCConfiguration config; @@ -447,23 +449,25 @@ TEST_F(PeerConnectionUsageHistogramTest, FingerprintWithMdnsCaller) { int expected_fingerprint_caller = MakeUsageFingerprint( {PeerConnection::UsageEvent::AUDIO_ADDED, PeerConnection::UsageEvent::VIDEO_ADDED, - PeerConnection::UsageEvent::SET_LOCAL_DESCRIPTION_CALLED, - PeerConnection::UsageEvent::SET_REMOTE_DESCRIPTION_CALLED, + PeerConnection::UsageEvent::SET_LOCAL_DESCRIPTION_SUCCEEDED, + PeerConnection::UsageEvent::SET_REMOTE_DESCRIPTION_SUCCEEDED, PeerConnection::UsageEvent::CANDIDATE_COLLECTED, PeerConnection::UsageEvent::MDNS_CANDIDATE_COLLECTED, - PeerConnection::UsageEvent::REMOTE_CANDIDATE_ADDED, + PeerConnection::UsageEvent::ADD_ICE_CANDIDATE_SUCCEEDED, PeerConnection::UsageEvent::ICE_STATE_CONNECTED, + PeerConnection::UsageEvent::REMOTE_CANDIDATE_ADDED, PeerConnection::UsageEvent::CLOSE_CALLED}); int expected_fingerprint_callee = MakeUsageFingerprint( {PeerConnection::UsageEvent::AUDIO_ADDED, PeerConnection::UsageEvent::VIDEO_ADDED, - PeerConnection::UsageEvent::SET_LOCAL_DESCRIPTION_CALLED, - PeerConnection::UsageEvent::SET_REMOTE_DESCRIPTION_CALLED, + PeerConnection::UsageEvent::SET_LOCAL_DESCRIPTION_SUCCEEDED, + PeerConnection::UsageEvent::SET_REMOTE_DESCRIPTION_SUCCEEDED, PeerConnection::UsageEvent::CANDIDATE_COLLECTED, - PeerConnection::UsageEvent::REMOTE_CANDIDATE_ADDED, + PeerConnection::UsageEvent::ADD_ICE_CANDIDATE_SUCCEEDED, PeerConnection::UsageEvent::REMOTE_MDNS_CANDIDATE_ADDED, PeerConnection::UsageEvent::ICE_STATE_CONNECTED, + PeerConnection::UsageEvent::REMOTE_CANDIDATE_ADDED, PeerConnection::UsageEvent::CLOSE_CALLED}); EXPECT_EQ(2, webrtc::metrics::NumSamples(kUsagePatternMetric)); @@ -473,6 +477,8 @@ TEST_F(PeerConnectionUsageHistogramTest, FingerprintWithMdnsCaller) { expected_fingerprint_callee)); } +// Test getting the usage fingerprint when the callee collects an mDNS +// candidate. TEST_F(PeerConnectionUsageHistogramTest, FingerprintWithMdnsCallee) { RTCConfiguration config; @@ -489,23 +495,25 @@ TEST_F(PeerConnectionUsageHistogramTest, FingerprintWithMdnsCallee) { int expected_fingerprint_caller = MakeUsageFingerprint( {PeerConnection::UsageEvent::AUDIO_ADDED, PeerConnection::UsageEvent::VIDEO_ADDED, - PeerConnection::UsageEvent::SET_LOCAL_DESCRIPTION_CALLED, - PeerConnection::UsageEvent::SET_REMOTE_DESCRIPTION_CALLED, + PeerConnection::UsageEvent::SET_LOCAL_DESCRIPTION_SUCCEEDED, + PeerConnection::UsageEvent::SET_REMOTE_DESCRIPTION_SUCCEEDED, PeerConnection::UsageEvent::CANDIDATE_COLLECTED, - PeerConnection::UsageEvent::REMOTE_CANDIDATE_ADDED, + PeerConnection::UsageEvent::ADD_ICE_CANDIDATE_SUCCEEDED, PeerConnection::UsageEvent::REMOTE_MDNS_CANDIDATE_ADDED, PeerConnection::UsageEvent::ICE_STATE_CONNECTED, + PeerConnection::UsageEvent::REMOTE_CANDIDATE_ADDED, PeerConnection::UsageEvent::CLOSE_CALLED}); int expected_fingerprint_callee = MakeUsageFingerprint( {PeerConnection::UsageEvent::AUDIO_ADDED, PeerConnection::UsageEvent::VIDEO_ADDED, - PeerConnection::UsageEvent::SET_LOCAL_DESCRIPTION_CALLED, - PeerConnection::UsageEvent::SET_REMOTE_DESCRIPTION_CALLED, + PeerConnection::UsageEvent::SET_LOCAL_DESCRIPTION_SUCCEEDED, + PeerConnection::UsageEvent::SET_REMOTE_DESCRIPTION_SUCCEEDED, PeerConnection::UsageEvent::CANDIDATE_COLLECTED, PeerConnection::UsageEvent::MDNS_CANDIDATE_COLLECTED, - PeerConnection::UsageEvent::REMOTE_CANDIDATE_ADDED, + PeerConnection::UsageEvent::ADD_ICE_CANDIDATE_SUCCEEDED, PeerConnection::UsageEvent::ICE_STATE_CONNECTED, + PeerConnection::UsageEvent::REMOTE_CANDIDATE_ADDED, PeerConnection::UsageEvent::CLOSE_CALLED}); EXPECT_EQ(2, webrtc::metrics::NumSamples(kUsagePatternMetric)); @@ -526,11 +534,12 @@ TEST_F(PeerConnectionUsageHistogramTest, FingerprintDataOnly) { callee->pc()->Close(); int expected_fingerprint = MakeUsageFingerprint( {PeerConnection::UsageEvent::DATA_ADDED, - PeerConnection::UsageEvent::SET_LOCAL_DESCRIPTION_CALLED, - PeerConnection::UsageEvent::SET_REMOTE_DESCRIPTION_CALLED, + PeerConnection::UsageEvent::SET_LOCAL_DESCRIPTION_SUCCEEDED, + PeerConnection::UsageEvent::SET_REMOTE_DESCRIPTION_SUCCEEDED, PeerConnection::UsageEvent::CANDIDATE_COLLECTED, - PeerConnection::UsageEvent::REMOTE_CANDIDATE_ADDED, + PeerConnection::UsageEvent::ADD_ICE_CANDIDATE_SUCCEEDED, PeerConnection::UsageEvent::ICE_STATE_CONNECTED, + PeerConnection::UsageEvent::REMOTE_CANDIDATE_ADDED, PeerConnection::UsageEvent::CLOSE_CALLED}); EXPECT_EQ(2, webrtc::metrics::NumSamples(kUsagePatternMetric)); EXPECT_TRUE( @@ -601,22 +610,24 @@ TEST_F(PeerConnectionUsageHistogramTest, FingerprintWithPrivateIPCaller) { int expected_fingerprint_caller = MakeUsageFingerprint( {PeerConnection::UsageEvent::AUDIO_ADDED, - PeerConnection::UsageEvent::SET_LOCAL_DESCRIPTION_CALLED, - PeerConnection::UsageEvent::SET_REMOTE_DESCRIPTION_CALLED, + PeerConnection::UsageEvent::SET_LOCAL_DESCRIPTION_SUCCEEDED, + PeerConnection::UsageEvent::SET_REMOTE_DESCRIPTION_SUCCEEDED, PeerConnection::UsageEvent::CANDIDATE_COLLECTED, PeerConnection::UsageEvent::PRIVATE_CANDIDATE_COLLECTED, - PeerConnection::UsageEvent::REMOTE_CANDIDATE_ADDED, + PeerConnection::UsageEvent::ADD_ICE_CANDIDATE_SUCCEEDED, PeerConnection::UsageEvent::ICE_STATE_CONNECTED, + PeerConnection::UsageEvent::REMOTE_CANDIDATE_ADDED, PeerConnection::UsageEvent::CLOSE_CALLED}); int expected_fingerprint_callee = MakeUsageFingerprint( {PeerConnection::UsageEvent::AUDIO_ADDED, - PeerConnection::UsageEvent::SET_LOCAL_DESCRIPTION_CALLED, - PeerConnection::UsageEvent::SET_REMOTE_DESCRIPTION_CALLED, + PeerConnection::UsageEvent::SET_LOCAL_DESCRIPTION_SUCCEEDED, + PeerConnection::UsageEvent::SET_REMOTE_DESCRIPTION_SUCCEEDED, PeerConnection::UsageEvent::CANDIDATE_COLLECTED, - PeerConnection::UsageEvent::REMOTE_CANDIDATE_ADDED, + PeerConnection::UsageEvent::ADD_ICE_CANDIDATE_SUCCEEDED, PeerConnection::UsageEvent::REMOTE_PRIVATE_CANDIDATE_ADDED, PeerConnection::UsageEvent::ICE_STATE_CONNECTED, + PeerConnection::UsageEvent::REMOTE_CANDIDATE_ADDED, PeerConnection::UsageEvent::CLOSE_CALLED}); EXPECT_EQ(2, webrtc::metrics::NumSamples(kUsagePatternMetric)); @@ -626,9 +637,9 @@ TEST_F(PeerConnectionUsageHistogramTest, FingerprintWithPrivateIPCaller) { expected_fingerprint_callee)); } -TEST_F(PeerConnectionUsageHistogramTest, FingerprintWithPrivateIPCallee) { +TEST_F(PeerConnectionUsageHistogramTest, FingerprintWithPrivateIpv6Callee) { auto caller = CreatePeerConnection(); - auto callee = CreatePeerConnectionWithPrivateLocalAddresses(); + auto callee = CreatePeerConnectionWithPrivateIpv6LocalAddresses(); caller->AddAudioTrack("audio"); ASSERT_TRUE(caller->ConnectTo(callee.get())); caller->pc()->Close(); @@ -636,20 +647,24 @@ TEST_F(PeerConnectionUsageHistogramTest, FingerprintWithPrivateIPCallee) { int expected_fingerprint_caller = MakeUsageFingerprint( {PeerConnection::UsageEvent::AUDIO_ADDED, - PeerConnection::UsageEvent::SET_LOCAL_DESCRIPTION_CALLED, - PeerConnection::UsageEvent::SET_REMOTE_DESCRIPTION_CALLED, + PeerConnection::UsageEvent::SET_LOCAL_DESCRIPTION_SUCCEEDED, + PeerConnection::UsageEvent::SET_REMOTE_DESCRIPTION_SUCCEEDED, PeerConnection::UsageEvent::CANDIDATE_COLLECTED, - PeerConnection::UsageEvent::REMOTE_CANDIDATE_ADDED, + PeerConnection::UsageEvent::ADD_ICE_CANDIDATE_SUCCEEDED, PeerConnection::UsageEvent::REMOTE_PRIVATE_CANDIDATE_ADDED, PeerConnection::UsageEvent::ICE_STATE_CONNECTED, + PeerConnection::UsageEvent::REMOTE_CANDIDATE_ADDED, + PeerConnection::UsageEvent::REMOTE_IPV6_CANDIDATE_ADDED, PeerConnection::UsageEvent::CLOSE_CALLED}); int expected_fingerprint_callee = MakeUsageFingerprint( {PeerConnection::UsageEvent::AUDIO_ADDED, - PeerConnection::UsageEvent::SET_LOCAL_DESCRIPTION_CALLED, - PeerConnection::UsageEvent::SET_REMOTE_DESCRIPTION_CALLED, + PeerConnection::UsageEvent::SET_LOCAL_DESCRIPTION_SUCCEEDED, + PeerConnection::UsageEvent::SET_REMOTE_DESCRIPTION_SUCCEEDED, PeerConnection::UsageEvent::CANDIDATE_COLLECTED, PeerConnection::UsageEvent::PRIVATE_CANDIDATE_COLLECTED, + PeerConnection::UsageEvent::IPV6_CANDIDATE_COLLECTED, + PeerConnection::UsageEvent::ADD_ICE_CANDIDATE_SUCCEEDED, PeerConnection::UsageEvent::REMOTE_CANDIDATE_ADDED, PeerConnection::UsageEvent::ICE_STATE_CONNECTED, PeerConnection::UsageEvent::CLOSE_CALLED}); @@ -663,6 +678,84 @@ TEST_F(PeerConnectionUsageHistogramTest, FingerprintWithPrivateIPCallee) { #ifndef WEBRTC_ANDROID #ifdef HAVE_SCTP +// Test that the usage pattern bits for adding remote (private IPv6) candidates +// are set when the remote candidates are retrieved from the Offer SDP instead +// of trickled ICE messages. +TEST_F(PeerConnectionUsageHistogramTest, + AddRemoteCandidatesFromRemoteDescription) { + // We construct the following data-channel-only scenario. The caller collects + // IPv6 private local candidates and appends them in the Offer as in + // non-trickled sessions. The callee collects mDNS candidates that are not + // contained in the Answer as in Trickle ICE. Only the Offer and Answer are + // signaled and we expect a connection with prflx remote candidates at the + // caller side. + auto caller = CreatePeerConnectionWithPrivateIpv6LocalAddresses(); + auto callee = CreatePeerConnectionWithMdns(RTCConfiguration()); + caller->CreateDataChannel("test_channel"); + ASSERT_TRUE(caller->SetLocalDescription(caller->CreateOffer())); + // Wait until the gathering completes so that the session description would + // have contained ICE candidates. + EXPECT_EQ_WAIT(webrtc::PeerConnectionInterface::kIceGatheringComplete, + caller->ice_gathering_state(), kDefaultTimeout); + EXPECT_TRUE(caller->observer()->candidate_gathered()); + // Get the current offer that contains candidates and pass it to the callee. + // + // Note that we cannot use CloneSessionDescription on |cur_offer| to obtain an + // SDP with candidates. The method above does not strictly copy everything, in + // particular, not copying the ICE candidates. + // TODO(qingsi): Technically, this is a bug. Fix it. + auto cur_offer = caller->pc()->local_description(); + ASSERT_TRUE(cur_offer); + std::string sdp_with_candidates_str; + cur_offer->ToString(&sdp_with_candidates_str); + auto offer = absl::make_unique(SdpType::kOffer); + ASSERT_TRUE(SdpDeserialize(sdp_with_candidates_str, offer.get(), + nullptr /* error */)); + ASSERT_TRUE(callee->SetRemoteDescription(std::move(offer))); + + // By default, the Answer created does not contain ICE candidates. + auto answer = callee->CreateAnswer(); + callee->SetLocalDescription(CloneSessionDescription(answer.get())); + caller->SetRemoteDescription(std::move(answer)); + EXPECT_TRUE_WAIT(caller->IsConnected(), kDefaultTimeout); + EXPECT_TRUE_WAIT(callee->IsConnected(), kDefaultTimeout); + // The callee needs to process the open message to have the data channel open. + EXPECT_TRUE_WAIT(callee->observer()->last_datachannel_ != nullptr, + kDefaultTimeout); + caller->pc()->Close(); + callee->pc()->Close(); + + // The caller should not have added any remote candidate either via + // AddIceCandidate or from the remote description. + int expected_fingerprint_caller = MakeUsageFingerprint( + {PeerConnection::UsageEvent::DATA_ADDED, + PeerConnection::UsageEvent::SET_LOCAL_DESCRIPTION_SUCCEEDED, + PeerConnection::UsageEvent::SET_REMOTE_DESCRIPTION_SUCCEEDED, + PeerConnection::UsageEvent::CANDIDATE_COLLECTED, + PeerConnection::UsageEvent::PRIVATE_CANDIDATE_COLLECTED, + PeerConnection::UsageEvent::IPV6_CANDIDATE_COLLECTED, + PeerConnection::UsageEvent::ICE_STATE_CONNECTED, + PeerConnection::UsageEvent::CLOSE_CALLED}); + + int expected_fingerprint_callee = MakeUsageFingerprint( + {PeerConnection::UsageEvent::DATA_ADDED, + PeerConnection::UsageEvent::SET_LOCAL_DESCRIPTION_SUCCEEDED, + PeerConnection::UsageEvent::SET_REMOTE_DESCRIPTION_SUCCEEDED, + PeerConnection::UsageEvent::CANDIDATE_COLLECTED, + PeerConnection::UsageEvent::MDNS_CANDIDATE_COLLECTED, + PeerConnection::UsageEvent::REMOTE_CANDIDATE_ADDED, + PeerConnection::UsageEvent::REMOTE_PRIVATE_CANDIDATE_ADDED, + PeerConnection::UsageEvent::REMOTE_IPV6_CANDIDATE_ADDED, + PeerConnection::UsageEvent::ICE_STATE_CONNECTED, + PeerConnection::UsageEvent::CLOSE_CALLED}); + + EXPECT_EQ(2, webrtc::metrics::NumSamples(kUsagePatternMetric)); + EXPECT_EQ(1, webrtc::metrics::NumEvents(kUsagePatternMetric, + expected_fingerprint_caller)); + EXPECT_EQ(1, webrtc::metrics::NumEvents(kUsagePatternMetric, + expected_fingerprint_callee)); +} + TEST_F(PeerConnectionUsageHistogramTest, NotableUsageNoted) { auto caller = CreatePeerConnection(); caller->CreateDataChannel("foo"); @@ -670,7 +763,7 @@ TEST_F(PeerConnectionUsageHistogramTest, NotableUsageNoted) { caller->pc()->Close(); int expected_fingerprint = MakeUsageFingerprint( {PeerConnection::UsageEvent::DATA_ADDED, - PeerConnection::UsageEvent::SET_LOCAL_DESCRIPTION_CALLED, + PeerConnection::UsageEvent::SET_LOCAL_DESCRIPTION_SUCCEEDED, PeerConnection::UsageEvent::CANDIDATE_COLLECTED, PeerConnection::UsageEvent::CLOSE_CALLED}); EXPECT_EQ(1, webrtc::metrics::NumSamples(kUsagePatternMetric)); @@ -689,7 +782,7 @@ TEST_F(PeerConnectionUsageHistogramTest, NotableUsageOnEventFiring) { caller->GenerateOfferAndCollectCandidates(); int expected_fingerprint = MakeUsageFingerprint( {PeerConnection::UsageEvent::DATA_ADDED, - PeerConnection::UsageEvent::SET_LOCAL_DESCRIPTION_CALLED, + PeerConnection::UsageEvent::SET_LOCAL_DESCRIPTION_SUCCEEDED, PeerConnection::UsageEvent::CANDIDATE_COLLECTED}); EXPECT_EQ(0, webrtc::metrics::NumSamples(kUsagePatternMetric)); caller->GetInternalPeerConnection()->RequestUsagePatternReportForTesting(); @@ -711,7 +804,7 @@ TEST_F(PeerConnectionUsageHistogramTest, caller->GenerateOfferAndCollectCandidates(); int expected_fingerprint = MakeUsageFingerprint( {PeerConnection::UsageEvent::DATA_ADDED, - PeerConnection::UsageEvent::SET_LOCAL_DESCRIPTION_CALLED, + PeerConnection::UsageEvent::SET_LOCAL_DESCRIPTION_SUCCEEDED, PeerConnection::UsageEvent::CANDIDATE_COLLECTED, PeerConnection::UsageEvent::CLOSE_CALLED}); EXPECT_EQ(0, webrtc::metrics::NumSamples(kUsagePatternMetric));