diff --git a/p2p/base/ice_transport_internal.h b/p2p/base/ice_transport_internal.h index 20730e1cfd..e1171d4a74 100644 --- a/p2p/base/ice_transport_internal.h +++ b/p2p/base/ice_transport_internal.h @@ -38,6 +38,15 @@ struct IceTransportStats { // Initially 0 and 1 once the first candidate pair has been selected. // The counter is increase also when "unselecting" a connection. uint32_t selected_candidate_pair_changes = 0; + + // Bytes/packets sent/received. + // note: Is not the same as sum(connection_infos.bytes_sent) + // as connections are created and destroyed while the ICE transport + // is alive. + uint64_t bytes_sent = 0; + uint64_t bytes_received = 0; + uint64_t packets_sent = 0; + uint64_t packets_received = 0; }; typedef std::vector Candidates; diff --git a/p2p/base/p2p_transport_channel.cc b/p2p/base/p2p_transport_channel.cc index 5667bc516b..f95534b3e0 100644 --- a/p2p/base/p2p_transport_channel.cc +++ b/p2p/base/p2p_transport_channel.cc @@ -1608,6 +1608,7 @@ int P2PTransportChannel::SendPacket(const char* data, return -1; } + packets_sent_++; last_sent_packet_id_ = options.packet_id; rtc::PacketOptions modified_options(options); modified_options.info_signaled_after_sent.packet_type = @@ -1616,7 +1617,10 @@ int P2PTransportChannel::SendPacket(const char* data, if (sent <= 0) { RTC_DCHECK(sent < 0); error_ = selected_connection_->GetError(); + return sent; } + + bytes_sent_ += sent; return sent; } @@ -1643,6 +1647,11 @@ bool P2PTransportChannel::GetStats(IceTransportStats* ice_transport_stats) { ice_transport_stats->selected_candidate_pair_changes = selected_candidate_pair_changes_; + + ice_transport_stats->bytes_sent = bytes_sent_; + ice_transport_stats->bytes_received = bytes_received_; + ice_transport_stats->packets_sent = packets_sent_; + ice_transport_stats->packets_received = packets_received_; return true; } @@ -2238,6 +2247,8 @@ void P2PTransportChannel::OnReadPacket(Connection* connection, if (connection == selected_connection_) { // Let the client know of an incoming packet + packets_received_++; + bytes_received_ += len; RTC_DCHECK(connection->last_data_received() >= last_data_received_ms_); last_data_received_ms_ = std::max(last_data_received_ms_, connection->last_data_received()); @@ -2249,6 +2260,8 @@ void P2PTransportChannel::OnReadPacket(Connection* connection, if (!FindConnection(connection)) return; + packets_received_++; + bytes_received_ += len; RTC_DCHECK(connection->last_data_received() >= last_data_received_ms_); last_data_received_ms_ = std::max(last_data_received_ms_, connection->last_data_received()); diff --git a/p2p/base/p2p_transport_channel.h b/p2p/base/p2p_transport_channel.h index d06234603c..a1c2de04a7 100644 --- a/p2p/base/p2p_transport_channel.h +++ b/p2p/base/p2p_transport_channel.h @@ -490,6 +490,12 @@ class RTC_EXPORT P2PTransportChannel : public IceTransportInternal { Candidate candidate, const webrtc::AsyncDnsResolverResult& result); + // Bytes/packets sent/received on this channel. + uint64_t bytes_sent_ = 0; + uint64_t bytes_received_ = 0; + uint64_t packets_sent_ = 0; + uint64_t packets_received_ = 0; + // Number of times the selected_connection_ has been modified. uint32_t selected_candidate_pair_changes_ = 0; diff --git a/p2p/base/p2p_transport_channel_unittest.cc b/p2p/base/p2p_transport_channel_unittest.cc index 0a24f8c030..79bb2a340c 100644 --- a/p2p/base/p2p_transport_channel_unittest.cc +++ b/p2p/base/p2p_transport_channel_unittest.cc @@ -1373,6 +1373,81 @@ TEST_F(P2PTransportChannelTest, GetStats) { EXPECT_EQ(36U, best_conn_info->sent_discarded_bytes); EXPECT_EQ(10 * 36U, best_conn_info->recv_total_bytes); EXPECT_EQ(10U, best_conn_info->packets_received); + + EXPECT_EQ(10 * 36U, ice_transport_stats.bytes_sent); + EXPECT_EQ(10 * 36U, ice_transport_stats.bytes_received); + + DestroyChannels(); +} + +TEST_F(P2PTransportChannelTest, GetStatsSwitchConnection) { + rtc::ScopedFakeClock clock; + IceConfig continual_gathering_config = + CreateIceConfig(1000, GATHER_CONTINUALLY); + + ConfigureEndpoints(OPEN, OPEN, kDefaultPortAllocatorFlags, + kDefaultPortAllocatorFlags); + + AddAddress(0, kAlternateAddrs[1], "rmnet0", rtc::ADAPTER_TYPE_CELLULAR); + + CreateChannels(continual_gathering_config, continual_gathering_config); + EXPECT_TRUE_SIMULATED_WAIT(ep1_ch1()->receiving() && ep1_ch1()->writable() && + ep2_ch1()->receiving() && + ep2_ch1()->writable(), + kMediumTimeout, clock); + // Sends and receives 10 packets. + TestSendRecv(&clock); + + IceTransportStats ice_transport_stats; + ASSERT_TRUE(ep1_ch1()->GetStats(&ice_transport_stats)); + ASSERT_GE(ice_transport_stats.connection_infos.size(), 2u); + ASSERT_GE(ice_transport_stats.candidate_stats_list.size(), 2u); + EXPECT_EQ(ice_transport_stats.selected_candidate_pair_changes, 1u); + + ConnectionInfo* best_conn_info = nullptr; + for (ConnectionInfo& info : ice_transport_stats.connection_infos) { + if (info.best_connection) { + best_conn_info = &info; + break; + } + } + ASSERT_TRUE(best_conn_info != nullptr); + EXPECT_TRUE(best_conn_info->new_connection); + EXPECT_TRUE(best_conn_info->receiving); + EXPECT_TRUE(best_conn_info->writable); + EXPECT_FALSE(best_conn_info->timeout); + + EXPECT_EQ(10 * 36U, best_conn_info->sent_total_bytes); + EXPECT_EQ(10 * 36U, best_conn_info->recv_total_bytes); + EXPECT_EQ(10 * 36U, ice_transport_stats.bytes_sent); + EXPECT_EQ(10 * 36U, ice_transport_stats.bytes_received); + + auto old_selected_connection = ep1_ch1()->selected_connection(); + ep1_ch1()->RemoveConnectionForTest( + const_cast(old_selected_connection)); + + EXPECT_TRUE_SIMULATED_WAIT(ep1_ch1()->selected_connection() != nullptr, + kMediumTimeout, clock); + + // Sends and receives 10 packets. + TestSendRecv(&clock); + + IceTransportStats ice_transport_stats2; + ASSERT_TRUE(ep1_ch1()->GetStats(&ice_transport_stats2)); + + int64_t sum_bytes_sent = 0; + int64_t sum_bytes_received = 0; + for (ConnectionInfo& info : ice_transport_stats.connection_infos) { + sum_bytes_sent += info.sent_total_bytes; + sum_bytes_received += info.recv_total_bytes; + } + + EXPECT_EQ(10 * 36U, sum_bytes_sent); + EXPECT_EQ(10 * 36U, sum_bytes_received); + + EXPECT_EQ(20 * 36U, ice_transport_stats2.bytes_sent); + EXPECT_EQ(20 * 36U, ice_transport_stats2.bytes_received); + DestroyChannels(); } diff --git a/pc/rtc_stats_collector.cc b/pc/rtc_stats_collector.cc index 13c62ec975..0ed8c14d51 100644 --- a/pc/rtc_stats_collector.cc +++ b/pc/rtc_stats_collector.cc @@ -2042,21 +2042,20 @@ void RTCStatsCollector::ProduceTransportStats_n( new RTCTransportStats(RTCTransportStatsIDFromTransportChannel( transport_name, channel_stats.component), timestamp_us)); - transport_stats->bytes_sent = 0; - transport_stats->packets_sent = 0; - transport_stats->bytes_received = 0; - transport_stats->packets_received = 0; + transport_stats->packets_sent = + channel_stats.ice_transport_stats.packets_sent; + transport_stats->packets_received = + channel_stats.ice_transport_stats.packets_received; + transport_stats->bytes_sent = + channel_stats.ice_transport_stats.bytes_sent; + transport_stats->bytes_received = + channel_stats.ice_transport_stats.bytes_received; transport_stats->dtls_state = DtlsTransportStateToRTCDtlsTransportState(channel_stats.dtls_state); transport_stats->selected_candidate_pair_changes = channel_stats.ice_transport_stats.selected_candidate_pair_changes; for (const cricket::ConnectionInfo& info : channel_stats.ice_transport_stats.connection_infos) { - *transport_stats->bytes_sent += info.sent_total_bytes; - *transport_stats->packets_sent += - info.sent_total_packets - info.sent_discarded_packets; - *transport_stats->bytes_received += info.recv_total_bytes; - *transport_stats->packets_received += info.packets_received; if (info.best_connection) { transport_stats->selected_candidate_pair_id = RTCIceCandidatePairStatsIDFromConnectionInfo(info); diff --git a/pc/rtc_stats_collector_unittest.cc b/pc/rtc_stats_collector_unittest.cc index d33760abcb..ec44b4dbe1 100644 --- a/pc/rtc_stats_collector_unittest.cc +++ b/pc/rtc_stats_collector_unittest.cc @@ -2419,6 +2419,10 @@ TEST_F(RTCStatsCollectorTest, CollectRTCTransportStats) { rtp_transport_channel_stats.ice_transport_stats.connection_infos.push_back( rtp_connection_info); rtp_transport_channel_stats.dtls_state = DtlsTransportState::kNew; + rtp_transport_channel_stats.ice_transport_stats.bytes_sent = 42; + rtp_transport_channel_stats.ice_transport_stats.packets_sent = 1; + rtp_transport_channel_stats.ice_transport_stats.bytes_received = 1337; + rtp_transport_channel_stats.ice_transport_stats.packets_received = 4; rtp_transport_channel_stats.ice_transport_stats .selected_candidate_pair_changes = 1; pc_->SetTransportStats(kTransportName, {rtp_transport_channel_stats}); @@ -2457,6 +2461,10 @@ TEST_F(RTCStatsCollectorTest, CollectRTCTransportStats) { rtcp_transport_channel_stats.ice_transport_stats.connection_infos.push_back( rtcp_connection_info); rtcp_transport_channel_stats.dtls_state = DtlsTransportState::kConnecting; + rtcp_transport_channel_stats.ice_transport_stats.bytes_sent = 1337; + rtcp_transport_channel_stats.ice_transport_stats.packets_sent = 1; + rtcp_transport_channel_stats.ice_transport_stats.bytes_received = 42; + rtcp_transport_channel_stats.ice_transport_stats.packets_received = 4; pc_->SetTransportStats(kTransportName, {rtp_transport_channel_stats, rtcp_transport_channel_stats}); @@ -2562,11 +2570,6 @@ TEST_F(RTCStatsCollectorTest, CollectRTCTransportStatsWithCrypto) { rtp_connection_info.best_connection = false; rtp_connection_info.local_candidate = *rtp_local_candidate.get(); rtp_connection_info.remote_candidate = *rtp_remote_candidate.get(); - rtp_connection_info.sent_total_bytes = 42; - rtp_connection_info.recv_total_bytes = 1337; - rtp_connection_info.sent_total_packets = 3; - rtp_connection_info.sent_discarded_packets = 2; - rtp_connection_info.packets_received = 4; cricket::TransportChannelStats rtp_transport_channel_stats; rtp_transport_channel_stats.component = cricket::ICE_CANDIDATE_COMPONENT_RTP; rtp_transport_channel_stats.ice_transport_stats.connection_infos.push_back( @@ -2588,12 +2591,12 @@ TEST_F(RTCStatsCollectorTest, CollectRTCTransportStatsWithCrypto) { "RTCTransport_transport_" + rtc::ToString(cricket::ICE_CANDIDATE_COMPONENT_RTP), report->timestamp_us()); - expected_rtp_transport.bytes_sent = 42; - expected_rtp_transport.packets_sent = 1; - expected_rtp_transport.bytes_received = 1337; - expected_rtp_transport.packets_received = 4; expected_rtp_transport.dtls_state = RTCDtlsTransportState::kConnected; expected_rtp_transport.selected_candidate_pair_changes = 1; + expected_rtp_transport.bytes_sent = 0; + expected_rtp_transport.bytes_received = 0; + expected_rtp_transport.packets_sent = 0; + expected_rtp_transport.packets_received = 0; // Crypto parameters expected_rtp_transport.tls_version = "0203"; expected_rtp_transport.dtls_cipher = "TLS_RSA_WITH_AES_128_CBC_SHA";