From 21c4b1e9ca48c46266f2e0eb4e6d55cdfeaea6cc Mon Sep 17 00:00:00 2001 From: Philipp Hancke Date: Thu, 11 Nov 2021 07:45:59 +0100 Subject: [PATCH] stats: expose relayProtocol on prflx candidate This makes relay candidates identifiable in scenarios where the TURN server is behind another entity and the peer sees a different ip address: client -> turn -> relay address -> third party relay + address -> peer In those cases, the relay candidate will become peer-reflexive since the peer sends the third party relay's address in the xor-mapped address and it is currently not easily possible to determine this is a relay candidate anymore. BUG=webrtc:13392 Change-Id: I6787339d0abdc735f8a43f636a676cccd8cadcda Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/237561 Reviewed-by: Taylor Brandstetter Reviewed-by: Harald Alvestrand Commit-Queue: Philipp Hancke Cr-Commit-Position: refs/heads/main@{#35346} --- pc/rtc_stats_collector.cc | 7 +++++-- pc/rtc_stats_collector_unittest.cc | 28 ++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/pc/rtc_stats_collector.cc b/pc/rtc_stats_collector.cc index 23e24dc849..7f815f2d93 100644 --- a/pc/rtc_stats_collector.cc +++ b/pc/rtc_stats_collector.cc @@ -728,8 +728,11 @@ const std::string& ProduceIceCandidateStats(int64_t timestamp_us, if (is_local) { candidate_stats->network_type = NetworkAdapterTypeToStatsType(candidate.network_type()); - if (candidate.type() == cricket::RELAY_PORT_TYPE) { - std::string relay_protocol = candidate.relay_protocol(); + const std::string& candidate_type = candidate.type(); + const std::string& relay_protocol = candidate.relay_protocol(); + if (candidate_type == cricket::RELAY_PORT_TYPE || + (candidate_type == cricket::PRFLX_PORT_TYPE && + !relay_protocol.empty())) { RTC_DCHECK(relay_protocol.compare("udp") == 0 || relay_protocol.compare("tcp") == 0 || relay_protocol.compare("tls") == 0); diff --git a/pc/rtc_stats_collector_unittest.cc b/pc/rtc_stats_collector_unittest.cc index 8c3c42f8ad..53387e8d95 100644 --- a/pc/rtc_stats_collector_unittest.cc +++ b/pc/rtc_stats_collector_unittest.cc @@ -1315,6 +1315,24 @@ TEST_F(RTCStatsCollectorTest, CollectRTCIceCandidateStats) { expected_a_local_relay.priority = 1; EXPECT_FALSE(*expected_a_local_relay.is_remote); + std::unique_ptr a_local_relay_prflx = CreateFakeCandidate( + "11.12.13.20", 22, "a_local_relay_prflx's protocol", + rtc::ADAPTER_TYPE_UNKNOWN, cricket::PRFLX_PORT_TYPE, 1); + a_local_relay_prflx->set_relay_protocol("udp"); + + RTCLocalIceCandidateStats expected_a_local_relay_prflx( + "RTCIceCandidate_" + a_local_relay_prflx->id(), 0); + expected_a_local_relay_prflx.transport_id = "RTCTransport_a_0"; + expected_a_local_relay_prflx.network_type = "unknown"; + expected_a_local_relay_prflx.ip = "11.12.13.20"; + expected_a_local_relay_prflx.address = "11.12.13.20"; + expected_a_local_relay_prflx.port = 22; + expected_a_local_relay_prflx.protocol = "a_local_relay_prflx's protocol"; + expected_a_local_relay_prflx.relay_protocol = "udp"; + expected_a_local_relay_prflx.candidate_type = "prflx"; + expected_a_local_relay_prflx.priority = 1; + EXPECT_FALSE(*expected_a_local_relay.is_remote); + // Candidates in the second transport stats. std::unique_ptr b_local = CreateFakeCandidate("42.42.42.42", 42, "b_local's protocol", @@ -1365,6 +1383,12 @@ TEST_F(RTCStatsCollectorTest, CollectRTCIceCandidateStats) { .local_candidate = *a_local_relay.get(); a_transport_channel_stats.ice_transport_stats.connection_infos[2] .remote_candidate = *a_remote_relay.get(); + a_transport_channel_stats.ice_transport_stats.connection_infos.push_back( + cricket::ConnectionInfo()); + a_transport_channel_stats.ice_transport_stats.connection_infos[3] + .local_candidate = *a_local_relay_prflx.get(); + a_transport_channel_stats.ice_transport_stats.connection_infos[3] + .remote_candidate = *a_remote_relay.get(); pc_->AddVoiceChannel("audio", "a"); pc_->SetTransportStats("a", a_transport_channel_stats); @@ -1399,6 +1423,10 @@ TEST_F(RTCStatsCollectorTest, CollectRTCIceCandidateStats) { ASSERT_TRUE(report->Get(expected_a_local_relay.id())); EXPECT_EQ(expected_a_local_relay, report->Get(expected_a_local_relay.id()) ->cast_to()); + ASSERT_TRUE(report->Get(expected_a_local_relay_prflx.id())); + EXPECT_EQ(expected_a_local_relay_prflx, + report->Get(expected_a_local_relay_prflx.id()) + ->cast_to()); ASSERT_TRUE(report->Get(expected_b_local.id())); EXPECT_EQ( expected_b_local,