diff --git a/api/stats/rtcstats_objects.h b/api/stats/rtcstats_objects.h index 373a2cd324..14c5f24a2c 100644 --- a/api/stats/rtcstats_objects.h +++ b/api/stats/rtcstats_objects.h @@ -104,6 +104,17 @@ struct RTCIceRole { static const char* const kControlling; }; +// https://www.w3.org/TR/webrtc/#dom-rtcicetransportstate +struct RTCIceTransportState { + static const char* const kNew; + static const char* const kChecking; + static const char* const kConnected; + static const char* const kCompleted; + static const char* const kDisconnected; + static const char* const kFailed; + static const char* const kClosed; +}; + // https://w3c.github.io/webrtc-stats/#certificatestats-dict* class RTC_EXPORT RTCCertificateStats final : public RTCStats { public: @@ -710,6 +721,7 @@ class RTC_EXPORT RTCTransportStats final : public RTCStats { RTCStatsMember selected_candidate_pair_changes; RTCStatsMember ice_role; RTCStatsMember ice_local_username_fragment; + RTCStatsMember ice_state; }; } // namespace webrtc diff --git a/p2p/base/ice_transport_internal.h b/p2p/base/ice_transport_internal.h index 97ce21c164..4f74ac7ae8 100644 --- a/p2p/base/ice_transport_internal.h +++ b/p2p/base/ice_transport_internal.h @@ -50,6 +50,7 @@ struct IceTransportStats { IceRole ice_role = ICEROLE_UNKNOWN; std::string ice_local_username_fragment; + webrtc::IceTransportState ice_state = webrtc::IceTransportState::kNew; }; typedef std::vector Candidates; diff --git a/p2p/base/p2p_transport_channel.cc b/p2p/base/p2p_transport_channel.cc index c85b56fc95..47163e4e33 100644 --- a/p2p/base/p2p_transport_channel.cc +++ b/p2p/base/p2p_transport_channel.cc @@ -1666,6 +1666,7 @@ bool P2PTransportChannel::GetStats(IceTransportStats* ice_transport_stats) { ice_transport_stats->ice_role = GetIceRole(); ice_transport_stats->ice_local_username_fragment = ice_parameters_.ufrag; + ice_transport_stats->ice_state = ComputeIceTransportState(); return true; } diff --git a/pc/rtc_stats_collector.cc b/pc/rtc_stats_collector.cc index c68f019ee3..916d4a7a4c 100644 --- a/pc/rtc_stats_collector.cc +++ b/pc/rtc_stats_collector.cc @@ -243,6 +243,28 @@ const char* DtlsTransportStateToRTCDtlsTransportState( } } +const char* IceTransportStateToRTCIceTransportState(IceTransportState state) { + switch (state) { + case IceTransportState::kNew: + return RTCIceTransportState::kNew; + case IceTransportState::kChecking: + return RTCIceTransportState::kChecking; + case IceTransportState::kConnected: + return RTCIceTransportState::kConnected; + case IceTransportState::kCompleted: + return RTCIceTransportState::kCompleted; + case IceTransportState::kFailed: + return RTCIceTransportState::kFailed; + case IceTransportState::kDisconnected: + return RTCIceTransportState::kDisconnected; + case IceTransportState::kClosed: + return RTCIceTransportState::kClosed; + default: + RTC_CHECK_NOTREACHED(); + return nullptr; + } +} + const char* NetworkTypeToStatsType(rtc::AdapterType type) { switch (type) { case rtc::ADAPTER_TYPE_CELLULAR: @@ -2118,6 +2140,8 @@ void RTCStatsCollector::ProduceTransportStats_n( IceRoleToRTCIceRole(channel_stats.ice_transport_stats.ice_role); transport_stats->ice_local_username_fragment = channel_stats.ice_transport_stats.ice_local_username_fragment; + transport_stats->ice_state = IceTransportStateToRTCIceTransportState( + channel_stats.ice_transport_stats.ice_state); for (const cricket::ConnectionInfo& info : channel_stats.ice_transport_stats.connection_infos) { if (info.best_connection) { diff --git a/pc/rtc_stats_collector_unittest.cc b/pc/rtc_stats_collector_unittest.cc index 17f706f0ca..4fb4a7674f 100644 --- a/pc/rtc_stats_collector_unittest.cc +++ b/pc/rtc_stats_collector_unittest.cc @@ -2469,6 +2469,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCTransportStats) { expected_rtp_transport.selected_candidate_pair_changes = 1; expected_rtp_transport.ice_role = RTCIceRole::kUnknown; expected_rtp_transport.ice_local_username_fragment = "thelocalufrag"; + expected_rtp_transport.ice_state = RTCIceTransportState::kNew; ASSERT_TRUE(report->Get(expected_rtp_transport.id())); EXPECT_EQ( @@ -2496,6 +2497,8 @@ TEST_F(RTCStatsCollectorTest, CollectRTCTransportStats) { rtcp_transport_channel_stats.ice_transport_stats.packets_received = 4; rtcp_transport_channel_stats.ice_transport_stats.ice_local_username_fragment = "thelocalufrag"; + rtcp_transport_channel_stats.ice_transport_stats.ice_state = + IceTransportState::kChecking; pc_->SetTransportStats(kTransportName, {rtp_transport_channel_stats, rtcp_transport_channel_stats}); @@ -2515,6 +2518,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCTransportStats) { expected_rtcp_transport.selected_candidate_pair_changes = 0; expected_rtcp_transport.ice_role = RTCIceRole::kUnknown; expected_rtcp_transport.ice_local_username_fragment = "thelocalufrag"; + expected_rtcp_transport.ice_state = RTCIceTransportState::kChecking; expected_rtp_transport.rtcp_transport_stats_id = expected_rtcp_transport.id(); ASSERT_TRUE(report->Get(expected_rtp_transport.id())); @@ -2618,6 +2622,8 @@ TEST_F(RTCStatsCollectorTest, CollectRTCTransportStatsWithCrypto) { cricket::ICEROLE_CONTROLLING; rtp_transport_channel_stats.ice_transport_stats.ice_local_username_fragment = "thelocalufrag"; + rtp_transport_channel_stats.ice_transport_stats.ice_state = + IceTransportState::kConnected; // 0x2F is TLS_RSA_WITH_AES_128_CBC_SHA according to IANA rtp_transport_channel_stats.ssl_cipher_suite = 0x2F; rtp_transport_channel_stats.srtp_crypto_suite = rtc::kSrtpAes128CmSha1_80; @@ -2639,6 +2645,7 @@ TEST_F(RTCStatsCollectorTest, CollectRTCTransportStatsWithCrypto) { expected_rtp_transport.packets_received = 0; expected_rtp_transport.ice_role = RTCIceRole::kControlling; expected_rtp_transport.ice_local_username_fragment = "thelocalufrag"; + expected_rtp_transport.ice_state = "connected"; // Crypto parameters expected_rtp_transport.tls_version = "0203"; expected_rtp_transport.dtls_role = RTCDtlsRole::kClient; diff --git a/pc/rtc_stats_integrationtest.cc b/pc/rtc_stats_integrationtest.cc index db49d80d4a..4f64334ffb 100644 --- a/pc/rtc_stats_integrationtest.cc +++ b/pc/rtc_stats_integrationtest.cc @@ -1145,6 +1145,7 @@ class RTCStatsReportVerifier { transport.selected_candidate_pair_changes); verifier.TestMemberIsDefined(transport.ice_role); verifier.TestMemberIsDefined(transport.ice_local_username_fragment); + verifier.TestMemberIsDefined(transport.ice_state); return verifier.ExpectAllMembersSuccessfullyTested(); } diff --git a/stats/rtcstats_objects.cc b/stats/rtcstats_objects.cc index 44cb4c79c3..e3e2640533 100644 --- a/stats/rtcstats_objects.cc +++ b/stats/rtcstats_objects.cc @@ -72,6 +72,15 @@ const char* const RTCIceRole::kUnknown = "unknown"; const char* const RTCIceRole::kControlled = "controlled"; const char* const RTCIceRole::kControlling = "controlling"; +// https://www.w3.org/TR/webrtc/#dom-rtcicetransportstate +const char* const RTCIceTransportState::kNew = "new"; +const char* const RTCIceTransportState::kChecking = "checking"; +const char* const RTCIceTransportState::kConnected = "connected"; +const char* const RTCIceTransportState::kCompleted = "completed"; +const char* const RTCIceTransportState::kDisconnected = "disconnected"; +const char* const RTCIceTransportState::kFailed = "failed"; +const char* const RTCIceTransportState::kClosed = "closed"; + // clang-format off WEBRTC_RTCSTATS_IMPL(RTCCertificateStats, RTCStats, "certificate", &fingerprint, @@ -1099,7 +1108,8 @@ WEBRTC_RTCSTATS_IMPL(RTCTransportStats, RTCStats, "transport", &srtp_cipher, &selected_candidate_pair_changes, &ice_role, - &ice_local_username_fragment) + &ice_local_username_fragment, + &ice_state) // clang-format on RTCTransportStats::RTCTransportStats(const std::string& id, @@ -1123,7 +1133,8 @@ RTCTransportStats::RTCTransportStats(std::string&& id, int64_t timestamp_us) srtp_cipher("srtpCipher"), selected_candidate_pair_changes("selectedCandidatePairChanges"), ice_role("iceRole"), - ice_local_username_fragment("iceLocalUsernameFragment") {} + ice_local_username_fragment("iceLocalUsernameFragment"), + ice_state("iceState") {} RTCTransportStats::RTCTransportStats(const RTCTransportStats& other) : RTCStats(other.id(), other.timestamp_us()), @@ -1142,7 +1153,8 @@ RTCTransportStats::RTCTransportStats(const RTCTransportStats& other) srtp_cipher(other.srtp_cipher), selected_candidate_pair_changes(other.selected_candidate_pair_changes), ice_role(other.ice_role), - ice_local_username_fragment(other.ice_local_username_fragment) {} + ice_local_username_fragment(other.ice_local_username_fragment), + ice_state(other.ice_state) {} RTCTransportStats::~RTCTransportStats() {}