diff --git a/api/stats/rtcstats_objects.h b/api/stats/rtcstats_objects.h index 849ef80a5d..7742538ca7 100644 --- a/api/stats/rtcstats_objects.h +++ b/api/stats/rtcstats_objects.h @@ -170,6 +170,8 @@ class RTC_EXPORT RTCIceCandidatePairStats final : public RTCStats { RTCStatsMember writable; // TODO(hbos): Collect and populate this value. https://bugs.webrtc.org/7062 RTCStatsMember readable; + RTCStatsMember packets_sent; + RTCStatsMember packets_received; RTCStatsMember bytes_sent; RTCStatsMember bytes_received; RTCStatsMember total_round_trip_time; @@ -194,6 +196,8 @@ class RTC_EXPORT RTCIceCandidatePairStats final : public RTCStats { RTCStatsMember consent_responses_received; // TODO(hbos): Collect and populate this value. https://bugs.webrtc.org/7062 RTCStatsMember consent_responses_sent; + RTCStatsMember packets_discarded_on_send; + RTCStatsMember bytes_discarded_on_send; }; // https://w3c.github.io/webrtc-stats/#icecandidate-dict* diff --git a/p2p/base/connection.cc b/p2p/base/connection.cc index ebfe6fd5fe..f7bd47d245 100644 --- a/p2p/base/connection.cc +++ b/p2p/base/connection.cc @@ -1374,6 +1374,7 @@ int ProxyConnection::Send(const void* data, RTC_DCHECK(sent < 0); error_ = port_->GetError(); stats_.sent_discarded_packets++; + stats_.sent_discarded_bytes += size; } else { send_rate_tracker_.AddSamplesAtTime(now, sent); } diff --git a/p2p/base/connection_info.cc b/p2p/base/connection_info.cc index ebea2ab5b0..d0cd3239f1 100644 --- a/p2p/base/connection_info.cc +++ b/p2p/base/connection_info.cc @@ -19,6 +19,7 @@ ConnectionInfo::ConnectionInfo() timeout(false), new_connection(false), rtt(0), + sent_discarded_bytes(0), sent_total_bytes(0), sent_bytes_second(0), sent_discarded_packets(0), diff --git a/p2p/base/connection_info.h b/p2p/base/connection_info.h index b5e1c14433..1117595481 100644 --- a/p2p/base/connection_info.h +++ b/p2p/base/connection_info.h @@ -41,12 +41,15 @@ struct ConnectionInfo { bool timeout; // Has this connection timed out? bool new_connection; // Is this a newly created connection? size_t rtt; // The STUN RTT for this connection. - size_t sent_total_bytes; // Total bytes sent on this connection. + size_t sent_discarded_bytes; // Number of outgoing bytes discarded due to + // socket errors. + size_t sent_total_bytes; // Total bytes sent on this connection. Does not + // include discarded bytes. size_t sent_bytes_second; // Bps over the last measurement interval. size_t sent_discarded_packets; // Number of outgoing packets discarded due to // socket errors. size_t sent_total_packets; // Number of total outgoing packets attempted for - // sending. + // sending, including discarded packets. size_t sent_ping_requests_total; // Number of STUN ping request sent. size_t sent_ping_requests_before_first_response; // Number of STUN ping // sent before receiving the first response. diff --git a/p2p/base/p2p_transport_channel_unittest.cc b/p2p/base/p2p_transport_channel_unittest.cc index 0ddeb2df72..dfc3cece1e 100644 --- a/p2p/base/p2p_transport_channel_unittest.cc +++ b/p2p/base/p2p_transport_channel_unittest.cc @@ -1338,6 +1338,13 @@ TEST_F(P2PTransportChannelTest, GetStats) { kMediumTimeout, clock); // Sends and receives 10 packets. TestSendRecv(&clock); + + // Try sending a packet which is discarded due to the socket being blocked. + virtual_socket_server()->SetSendingBlocked(true); + const char* data = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; + int len = static_cast(strlen(data)); + EXPECT_EQ(-1, SendData(ep1_ch1(), data, len)); + IceTransportStats ice_transport_stats; ASSERT_TRUE(ep1_ch1()->GetStats(&ice_transport_stats)); ASSERT_GE(ice_transport_stats.connection_infos.size(), 1u); @@ -1355,9 +1362,12 @@ TEST_F(P2PTransportChannelTest, GetStats) { EXPECT_TRUE(best_conn_info->receiving); EXPECT_TRUE(best_conn_info->writable); EXPECT_FALSE(best_conn_info->timeout); - EXPECT_EQ(10U, best_conn_info->sent_total_packets); - EXPECT_EQ(0U, best_conn_info->sent_discarded_packets); + // Note that discarded packets are counted in sent_total_packets but not + // sent_total_bytes. + EXPECT_EQ(11U, best_conn_info->sent_total_packets); + EXPECT_EQ(1U, best_conn_info->sent_discarded_packets); EXPECT_EQ(10 * 36U, best_conn_info->sent_total_bytes); + 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); DestroyChannels(); diff --git a/pc/rtc_stats_collector.cc b/pc/rtc_stats_collector.cc index 1f8b28df62..7637c07c09 100644 --- a/pc/rtc_stats_collector.cc +++ b/pc/rtc_stats_collector.cc @@ -1552,8 +1552,18 @@ void RTCStatsCollector::ProduceIceCandidateAndPairStats_n( // false after a certain amount of time without a response passes. // https://crbug.com/633550 candidate_pair_stats->writable = info.writable; + // Note that sent_total_packets includes discarded packets but + // sent_total_bytes does not. + candidate_pair_stats->packets_sent = static_cast( + info.sent_total_packets - info.sent_discarded_packets); + candidate_pair_stats->packets_discarded_on_send = + static_cast(info.sent_discarded_packets); + candidate_pair_stats->packets_received = + static_cast(info.packets_received); candidate_pair_stats->bytes_sent = static_cast(info.sent_total_bytes); + candidate_pair_stats->bytes_discarded_on_send = + static_cast(info.sent_discarded_bytes); candidate_pair_stats->bytes_received = static_cast(info.recv_total_bytes); candidate_pair_stats->total_round_trip_time = diff --git a/pc/rtc_stats_collector_unittest.cc b/pc/rtc_stats_collector_unittest.cc index 8c4f0a6623..5f94d814ca 100644 --- a/pc/rtc_stats_collector_unittest.cc +++ b/pc/rtc_stats_collector_unittest.cc @@ -1421,6 +1421,10 @@ TEST_F(RTCStatsCollectorTest, CollectRTCIceCandidatePairStats) { connection_info.local_candidate = *local_candidate.get(); connection_info.remote_candidate = *remote_candidate.get(); connection_info.writable = true; + connection_info.sent_discarded_packets = 3; + connection_info.sent_total_packets = 10; + connection_info.packets_received = 51; + connection_info.sent_discarded_bytes = 7; connection_info.sent_total_bytes = 42; connection_info.recv_total_bytes = 1234; connection_info.total_round_trip_time_ms = 0; @@ -1458,8 +1462,12 @@ TEST_F(RTCStatsCollectorTest, CollectRTCIceCandidatePairStats) { expected_pair.priority = 5555; expected_pair.nominated = false; expected_pair.writable = true; + expected_pair.packets_sent = 7; + expected_pair.packets_received = 51; + expected_pair.packets_discarded_on_send = 3; expected_pair.bytes_sent = 42; expected_pair.bytes_received = 1234; + expected_pair.bytes_discarded_on_send = 7; expected_pair.total_round_trip_time = 0.0; expected_pair.requests_received = 2020; expected_pair.requests_sent = 2000; diff --git a/pc/rtc_stats_integrationtest.cc b/pc/rtc_stats_integrationtest.cc index afa50d84df..81ead00efe 100644 --- a/pc/rtc_stats_integrationtest.cc +++ b/pc/rtc_stats_integrationtest.cc @@ -489,7 +489,13 @@ class RTCStatsReportVerifier { verifier.TestMemberIsDefined(candidate_pair.nominated); verifier.TestMemberIsDefined(candidate_pair.writable); verifier.TestMemberIsUndefined(candidate_pair.readable); + verifier.TestMemberIsNonNegative(candidate_pair.packets_sent); + verifier.TestMemberIsNonNegative( + candidate_pair.packets_discarded_on_send); + verifier.TestMemberIsNonNegative(candidate_pair.packets_received); verifier.TestMemberIsNonNegative(candidate_pair.bytes_sent); + verifier.TestMemberIsNonNegative( + candidate_pair.bytes_discarded_on_send); verifier.TestMemberIsNonNegative(candidate_pair.bytes_received); verifier.TestMemberIsNonNegative( candidate_pair.total_round_trip_time); diff --git a/stats/rtcstats_objects.cc b/stats/rtcstats_objects.cc index 762011d547..961d17c7eb 100644 --- a/stats/rtcstats_objects.cc +++ b/stats/rtcstats_objects.cc @@ -173,6 +173,8 @@ WEBRTC_RTCSTATS_IMPL(RTCIceCandidatePairStats, RTCStats, "candidate-pair", &nominated, &writable, &readable, + &packets_sent, + &packets_received, &bytes_sent, &bytes_received, &total_round_trip_time, @@ -188,7 +190,9 @@ WEBRTC_RTCSTATS_IMPL(RTCIceCandidatePairStats, RTCStats, "candidate-pair", &consent_requests_received, &consent_requests_sent, &consent_responses_received, - &consent_responses_sent) + &consent_responses_sent, + &packets_discarded_on_send, + &bytes_discarded_on_send) // clang-format on RTCIceCandidatePairStats::RTCIceCandidatePairStats(const std::string& id, @@ -206,6 +210,8 @@ RTCIceCandidatePairStats::RTCIceCandidatePairStats(std::string&& id, nominated("nominated"), writable("writable"), readable("readable"), + packets_sent("packetsSent"), + packets_received("packetsReceived"), bytes_sent("bytesSent"), bytes_received("bytesReceived"), total_round_trip_time("totalRoundTripTime"), @@ -221,7 +227,9 @@ RTCIceCandidatePairStats::RTCIceCandidatePairStats(std::string&& id, consent_requests_received("consentRequestsReceived"), consent_requests_sent("consentRequestsSent"), consent_responses_received("consentResponsesReceived"), - consent_responses_sent("consentResponsesSent") {} + consent_responses_sent("consentResponsesSent"), + packets_discarded_on_send("packetsDiscardedOnSend"), + bytes_discarded_on_send("bytesDiscardedOnSend") {} RTCIceCandidatePairStats::RTCIceCandidatePairStats( const RTCIceCandidatePairStats& other) @@ -234,6 +242,8 @@ RTCIceCandidatePairStats::RTCIceCandidatePairStats( nominated(other.nominated), writable(other.writable), readable(other.readable), + packets_sent(other.packets_sent), + packets_received(other.packets_received), bytes_sent(other.bytes_sent), bytes_received(other.bytes_received), total_round_trip_time(other.total_round_trip_time), @@ -249,7 +259,9 @@ RTCIceCandidatePairStats::RTCIceCandidatePairStats( consent_requests_received(other.consent_requests_received), consent_requests_sent(other.consent_requests_sent), consent_responses_received(other.consent_responses_received), - consent_responses_sent(other.consent_responses_sent) {} + consent_responses_sent(other.consent_responses_sent), + packets_discarded_on_send(other.packets_discarded_on_send), + bytes_discarded_on_send(other.bytes_discarded_on_send) {} RTCIceCandidatePairStats::~RTCIceCandidatePairStats() {}