diff --git a/api/stats/rtcstats_objects.h b/api/stats/rtcstats_objects.h index a052c17383..8371543fad 100644 --- a/api/stats/rtcstats_objects.h +++ b/api/stats/rtcstats_objects.h @@ -183,6 +183,8 @@ class RTCIceCandidatePairStats final : public RTCStats { // TODO(hbos): |RTCStatsCollector| only collects candidates that are part of // ice candidate pairs, but there could be candidates not paired with anything. // crbug.com/632723 +// TODO(qingsi): Add the stats of STUN binding requests (keepalives) and collect +// them in the new PeerConnection::GetStats. class RTCIceCandidateStats : public RTCStats { public: WEBRTC_RTCSTATS_DECL(); diff --git a/api/statstypes.cc b/api/statstypes.cc index d1637e3ffd..8a8726530c 100644 --- a/api/statstypes.cc +++ b/api/statstypes.cc @@ -430,7 +430,9 @@ const char* StatsReport::Value::display_name() const { case kStatsValueNameBandwidthLimitedResolution: return "googBandwidthLimitedResolution"; // STUN ping related attributes. + // // TODO(zhihuang) Rename these stats to follow the standards. + // Connectivity checks. case kStatsValueNameSentPingRequestsTotal: return "requestsSent"; case kStatsValueNameSentPingRequestsBeforeFirstResponse: @@ -441,6 +443,15 @@ const char* StatsReport::Value::display_name() const { return "requestsReceived"; case kStatsValueNameRecvPingResponses: return "responsesReceived"; + // STUN Keepalive pings. + case kStatsValueNameSentStunKeepaliveRequests: + return "stunKeepaliveRequestsSent"; + case kStatsValueNameRecvStunKeepaliveResponses: + return "stunKeepaliveResponsesReceived"; + case kStatsValueNameStunKeepaliveRttTotal: + return "stunKeepaliveRttTotal"; + case kStatsValueNameStunKeepaliveRttSquaredTotal: + return "stunKeepaliveRttSquaredTotal"; // Candidate related attributes. Values are taken from // http://w3c.github.io/webrtc-stats/#rtcstatstype-enum*. diff --git a/api/statstypes.h b/api/statstypes.h index 2ba8ba5fd5..9dc6154997 100644 --- a/api/statstypes.h +++ b/api/statstypes.h @@ -129,6 +129,10 @@ class StatsReport { kStatsValueNameSentPingResponses, kStatsValueNameRecvPingRequests, kStatsValueNameRecvPingResponses, + kStatsValueNameSentStunKeepaliveRequests, + kStatsValueNameRecvStunKeepaliveResponses, + kStatsValueNameStunKeepaliveRttTotal, + kStatsValueNameStunKeepaliveRttSquaredTotal, // Internal StatsValue names. kStatsValueNameAccelerateRate, diff --git a/p2p/base/fakeicetransport.h b/p2p/base/fakeicetransport.h index 556a1cda03..427481e0e2 100644 --- a/p2p/base/fakeicetransport.h +++ b/p2p/base/fakeicetransport.h @@ -146,10 +146,14 @@ class FakeIceTransport : public IceTransportInternal { } void RemoveRemoteCandidate(const Candidate& candidate) override {} - bool GetStats(ConnectionInfos* infos) override { - ConnectionInfo info; - infos->clear(); - infos->push_back(info); + bool GetStats(ConnectionInfos* candidate_pair_stats_list, + CandidateStatsList* candidate_stats_list) override { + CandidateStats candidate_stats; + ConnectionInfo candidate_pair_stats; + candidate_stats_list->clear(); + candidate_stats_list->push_back(candidate_stats); + candidate_pair_stats_list->clear(); + candidate_pair_stats_list->push_back(candidate_pair_stats); return true; } diff --git a/p2p/base/icetransportinternal.h b/p2p/base/icetransportinternal.h index 13ba3316d9..192a9d06e0 100644 --- a/p2p/base/icetransportinternal.h +++ b/p2p/base/icetransportinternal.h @@ -201,7 +201,8 @@ class IceTransportInternal : public rtc::PacketTransportInternal { virtual IceGatheringState gathering_state() const = 0; // Returns the current stats for this connection. - virtual bool GetStats(ConnectionInfos* infos) = 0; + virtual bool GetStats(ConnectionInfos* candidate_pair_stats_list, + CandidateStatsList* candidate_stats_list) = 0; // Returns RTT estimate over the currently active connection, or an empty // rtc::Optional if there is none. diff --git a/p2p/base/mockicetransport.h b/p2p/base/mockicetransport.h index 3e7aed7297..c30d797fdf 100644 --- a/p2p/base/mockicetransport.h +++ b/p2p/base/mockicetransport.h @@ -40,7 +40,9 @@ class MockIceTransport : public IceTransportInternal { MOCK_METHOD2(SetOption, int(rtc::Socket::Option opt, int value)); MOCK_METHOD0(GetError, int()); MOCK_CONST_METHOD0(GetIceRole, cricket::IceRole()); - MOCK_METHOD1(GetStats, bool(cricket::ConnectionInfos* infos)); + MOCK_METHOD2(GetStats, + bool(cricket::ConnectionInfos* candidate_pair_stats_list, + cricket::CandidateStatsList* candidate_stats_list)); IceTransportState GetState() const override { return IceTransportState::STATE_INIT; diff --git a/p2p/base/p2ptransportchannel.cc b/p2p/base/p2ptransportchannel.cc index 2ad4114c27..414ff2b764 100644 --- a/p2p/base/p2ptransportchannel.cc +++ b/p2p/base/p2ptransportchannel.cc @@ -1136,15 +1136,22 @@ int P2PTransportChannel::SendPacket(const char *data, size_t len, return sent; } -bool P2PTransportChannel::GetStats(ConnectionInfos *infos) { +bool P2PTransportChannel::GetStats(ConnectionInfos* candidate_pair_stats_list, + CandidateStatsList* candidate_stats_list) { RTC_DCHECK(network_thread_ == rtc::Thread::Current()); - // Gather connection infos. - infos->clear(); + // Gather candidate and candidate pair stats. + candidate_stats_list->clear(); + candidate_pair_stats_list->clear(); + if (!allocator_sessions_.empty()) { + allocator_session()->GetCandidateStatsFromReadyPorts(candidate_stats_list); + } + + // TODO(qingsi): Remove naming inconsistency for candidate pair/connection. for (Connection* connection : connections_) { - ConnectionInfo info = connection->stats(); - info.best_connection = (selected_connection_ == connection); - infos->push_back(std::move(info)); + ConnectionInfo candidate_pair_stats = connection->stats(); + candidate_pair_stats.best_connection = (selected_connection_ == connection); + candidate_pair_stats_list->push_back(std::move(candidate_pair_stats)); connection->set_reported(true); } diff --git a/p2p/base/p2ptransportchannel.h b/p2p/base/p2ptransportchannel.h index af5625a4b4..e4db38cb42 100644 --- a/p2p/base/p2ptransportchannel.h +++ b/p2p/base/p2ptransportchannel.h @@ -118,7 +118,8 @@ class P2PTransportChannel : public IceTransportInternal, int SetOption(rtc::Socket::Option opt, int value) override; bool GetOption(rtc::Socket::Option opt, int* value) override; int GetError() override; - bool GetStats(std::vector* stats) override; + bool GetStats(std::vector* candidate_pair_stats_list, + std::vector* candidate_stats_list) override; rtc::Optional GetRttEstimate() override; // TODO(honghaiz): Remove this method once the reference of it in diff --git a/p2p/base/p2ptransportchannel_unittest.cc b/p2p/base/p2ptransportchannel_unittest.cc index fc2b65c8b3..71c648afa9 100644 --- a/p2p/base/p2ptransportchannel_unittest.cc +++ b/p2p/base/p2ptransportchannel_unittest.cc @@ -1176,8 +1176,10 @@ TEST_F(P2PTransportChannelTest, GetStats) { kMediumTimeout, clock); TestSendRecv(&clock); ConnectionInfos infos; - ASSERT_TRUE(ep1_ch1()->GetStats(&infos)); + CandidateStatsList candidate_stats_list; + ASSERT_TRUE(ep1_ch1()->GetStats(&infos, &candidate_stats_list)); ASSERT_GE(infos.size(), 1u); + ASSERT_GE(candidate_stats_list.size(), 1u); ConnectionInfo* best_conn_info = nullptr; for (ConnectionInfo& info : infos) { if (info.best_connection) { diff --git a/p2p/base/port.cc b/p2p/base/port.cc index 5f5153facb..b142865b75 100644 --- a/p2p/base/port.cc +++ b/p2p/base/port.cc @@ -193,6 +193,16 @@ static std::string ComputeFoundation(const std::string& type, return rtc::ToString(rtc::ComputeCrc32(ost.str())); } +CandidateStats::CandidateStats() = default; + +CandidateStats::CandidateStats(const CandidateStats&) = default; + +CandidateStats::CandidateStats(Candidate candidate) { + this->candidate = candidate; +} + +CandidateStats::~CandidateStats() = default; + ConnectionInfo::ConnectionInfo() : best_connection(false), writable(false), @@ -1428,7 +1438,7 @@ void Connection::ReceivedPingResponse(int rtt, const std::string& request_id) { set_write_state(STATE_WRITABLE); set_state(IceCandidatePairState::SUCCEEDED); if (rtt_samples_ > 0) { - rtt_ = (RTT_RATIO * rtt_ + rtt) / (RTT_RATIO + 1); + rtt_ = rtc::GetNextMovingAverage(rtt_, rtt, RTT_RATIO); } else { rtt_ = rtt; } diff --git a/p2p/base/port.h b/p2p/base/port.h index 8dbeccec47..16fedb8148 100644 --- a/p2p/base/port.h +++ b/p2p/base/port.h @@ -106,6 +106,36 @@ enum class IceCandidatePairState { // frozen because we have not implemented ICE freezing logic. }; +// Stats that we can return about the port of a connection. +class StunStats { + public: + StunStats() = default; + StunStats(const StunStats&) = default; + ~StunStats() = default; + + StunStats& operator=(const StunStats& other) = default; + + int stun_binding_requests_sent = 0; + int stun_binding_responses_received = 0; + double stun_binding_rtt_ms_total = 0; + double stun_binding_rtt_ms_squared_total = 0; +}; + +// Stats that we can return about a candidate. +class CandidateStats { + public: + CandidateStats(); + explicit CandidateStats(Candidate candidate); + CandidateStats(const CandidateStats&); + ~CandidateStats(); + + Candidate candidate; + // STUN port stats if this candidate is a STUN candidate. + rtc::Optional stun_stats; +}; + +typedef std::vector CandidateStatsList; + // Stats that we can return about the connections for a transport channel. // TODO(hta): Rename to ConnectionStats struct ConnectionInfo { @@ -149,7 +179,7 @@ struct ConnectionInfo { rtc::Optional current_round_trip_time_ms; }; -// Information about all the connections of a channel. +// Information about all the candidate pairs of a channel. typedef std::vector ConnectionInfos; const char* ProtoToString(ProtocolType proto); @@ -368,6 +398,8 @@ class Port : public PortInterface, public rtc::MessageHandler, int16_t network_cost() const { return network_cost_; } + void GetStunStats(rtc::Optional* stats) override{}; + protected: enum { MSG_DESTROY_IF_DEAD = 0, MSG_FIRST_AVAILABLE }; diff --git a/p2p/base/portallocator.cc b/p2p/base/portallocator.cc index 6ef084ca63..2b9b183f01 100644 --- a/p2p/base/portallocator.cc +++ b/p2p/base/portallocator.cc @@ -79,6 +79,19 @@ bool PortAllocatorSession::IsStopped() const { return false; } +void PortAllocatorSession::GetCandidateStatsFromReadyPorts( + CandidateStatsList* candidate_stats_list) const { + auto ports = ReadyPorts(); + for (auto* port : ports) { + auto candidates = port->Candidates(); + for (const auto& candidate : candidates) { + CandidateStats candidate_stats(candidate); + port->GetStunStats(&candidate_stats.stun_stats); + candidate_stats_list->push_back(std::move(candidate_stats)); + } + } +} + uint32_t PortAllocatorSession::generation() { return generation_; } @@ -210,4 +223,11 @@ void PortAllocator::DiscardCandidatePool() { pooled_sessions_.clear(); } +void PortAllocator::GetCandidateStatsFromPooledSessions( + CandidateStatsList* candidate_stats_list) { + for (const auto& session : pooled_sessions()) { + session->GetCandidateStatsFromReadyPorts(candidate_stats_list); + } +} + } // namespace cricket diff --git a/p2p/base/portallocator.h b/p2p/base/portallocator.h index f32fa07476..95052c2db1 100644 --- a/p2p/base/portallocator.h +++ b/p2p/base/portallocator.h @@ -244,6 +244,10 @@ class PortAllocatorSession : public sigslot::has_slots<> { virtual void RegatherOnFailedNetworks() {} // Re-gathers candidates on all networks. virtual void RegatherOnAllNetworks() {} + // Get candidate-level stats from all candidates on the ready ports and return + // the stats to the given list. + virtual void GetCandidateStatsFromReadyPorts( + CandidateStatsList* candidate_stats_list) const; // Set the interval at which STUN candidates will resend STUN binding requests // on the underlying ports to keep NAT bindings open. // The default value of the interval in implementation is restored if a null @@ -476,6 +480,14 @@ class PortAllocator : public sigslot::has_slots<> { return turn_customizer_; } + // Collect candidate stats from pooled allocator sessions. This can be used to + // collect candidate stats without creating an offer/answer or setting local + // description. After the local description is set, the ownership of the + // pooled session is taken by P2PTransportChannel, and the + // candidate stats can be collected from P2PTransportChannel::GetStats. + virtual void GetCandidateStatsFromPooledSessions( + CandidateStatsList* candidate_stats_list); + protected: virtual PortAllocatorSession* CreateSessionInternal( const std::string& content_name, diff --git a/p2p/base/portinterface.h b/p2p/base/portinterface.h index e34e39abc3..49a41647cd 100644 --- a/p2p/base/portinterface.h +++ b/p2p/base/portinterface.h @@ -15,6 +15,7 @@ #include #include "api/candidate.h" +#include "api/optional.h" #include "p2p/base/transportdescription.h" #include "rtc_base/asyncpacketsocket.h" #include "rtc_base/socketaddress.h" @@ -28,6 +29,7 @@ namespace cricket { class Connection; class IceMessage; class StunMessage; +class StunStats; enum ProtocolType { PROTO_UDP, @@ -125,6 +127,8 @@ class PortInterface { virtual std::string ToString() const = 0; + virtual void GetStunStats(rtc::Optional* stats) = 0; + protected: PortInterface(); }; diff --git a/p2p/base/stunport.cc b/p2p/base/stunport.cc index 2df14b7c62..3ea1f96a7f 100644 --- a/p2p/base/stunport.cc +++ b/p2p/base/stunport.cc @@ -52,7 +52,7 @@ class StunBindingRequest : public StunRequest { RTC_LOG(LS_ERROR) << "Binding address has bad family"; } else { rtc::SocketAddress addr(addr_attr->ipaddr(), addr_attr->port()); - port_->OnStunBindingRequestSucceeded(server_addr_, addr); + port_->OnStunBindingRequestSucceeded(this->Elapsed(), server_addr_, addr); } // The keep-alive requests will be stopped after its lifetime has passed. @@ -317,6 +317,10 @@ ProtocolType UDPPort::GetProtocol() const { return PROTO_UDP; } +void UDPPort::GetStunStats(rtc::Optional* stats) { + *stats = stats_; +} + void UDPPort::set_stun_keepalive_delay(const rtc::Optional& delay) { stun_keepalive_delay_ = (delay.has_value() ? delay.value() : KEEPALIVE_DELAY); } @@ -450,6 +454,7 @@ bool UDPPort::MaybeSetDefaultLocalAddress(rtc::SocketAddress* addr) const { } void UDPPort::OnStunBindingRequestSucceeded( + int rtt_ms, const rtc::SocketAddress& stun_server_addr, const rtc::SocketAddress& stun_reflected_addr) { if (bind_request_succeeded_servers_.find(stun_server_addr) != @@ -458,6 +463,11 @@ void UDPPort::OnStunBindingRequestSucceeded( } bind_request_succeeded_servers_.insert(stun_server_addr); + RTC_DCHECK(stats_.stun_binding_responses_received < + stats_.stun_binding_requests_sent); + stats_.stun_binding_responses_received++; + stats_.stun_binding_rtt_ms_total += rtt_ms; + stats_.stun_binding_rtt_ms_squared_total += rtt_ms * rtt_ms; // If socket is shared and |stun_reflected_addr| is equal to local socket // address, or if the same address has been added by another STUN server, // then discarding the stun address. @@ -520,8 +530,10 @@ void UDPPort::MaybeSetPortCompleteOrError() { void UDPPort::OnSendPacket(const void* data, size_t size, StunRequest* req) { StunBindingRequest* sreq = static_cast(req); rtc::PacketOptions options(DefaultDscpValue()); - if (socket_->SendTo(data, size, sreq->server_addr(), options) < 0) + if (socket_->SendTo(data, size, sreq->server_addr(), options) < 0) { RTC_LOG_ERR_EX(LERROR, socket_->GetError()) << "sendto"; + } + stats_.stun_binding_requests_sent++; } bool UDPPort::HasCandidateWithAddress(const rtc::SocketAddress& addr) const { diff --git a/p2p/base/stunport.h b/p2p/base/stunport.h index eaeea3ae91..72afbd3735 100644 --- a/p2p/base/stunport.h +++ b/p2p/base/stunport.h @@ -101,6 +101,8 @@ class UDPPort : public Port { bool SupportsProtocol(const std::string& protocol) const override; ProtocolType GetProtocol() const override; + void GetStunStats(rtc::Optional* stats) override; + void set_stun_keepalive_delay(const rtc::Optional& delay); int stun_keepalive_delay() const { return stun_keepalive_delay_; @@ -206,6 +208,7 @@ class UDPPort : public Port { // Below methods handles binding request responses. void OnStunBindingRequestSucceeded( + int rtt_ms, const rtc::SocketAddress& stun_server_addr, const rtc::SocketAddress& stun_reflected_addr); void OnStunBindingOrResolveRequestFailed( @@ -240,6 +243,8 @@ class UDPPort : public Port { int stun_keepalive_delay_; int stun_keepalive_lifetime_ = INFINITE_LIFETIME; + StunStats stats_; + // This is true by default and false when // PORTALLOCATOR_DISABLE_DEFAULT_LOCAL_CANDIDATE is specified. bool emit_local_for_anyaddress_; diff --git a/pc/jseptransport.cc b/pc/jseptransport.cc index 12aad7a3f0..a6a6135b4d 100644 --- a/pc/jseptransport.cc +++ b/pc/jseptransport.cc @@ -234,7 +234,7 @@ bool JsepTransport::GetStats(TransportStats* stats) { dtls_transport->GetSslCipherSuite(&substats.ssl_cipher_suite); substats.dtls_state = dtls_transport->dtls_state(); if (!dtls_transport->ice_transport()->GetStats( - &substats.connection_infos)) { + &substats.connection_infos, &substats.candidate_stats_list)) { return false; } stats->channel_stats.push_back(substats); diff --git a/pc/jseptransport.h b/pc/jseptransport.h index 972f91bf5b..719ff7a031 100644 --- a/pc/jseptransport.h +++ b/pc/jseptransport.h @@ -39,6 +39,7 @@ struct TransportChannelStats { ~TransportChannelStats(); int component = 0; + CandidateStatsList candidate_stats_list; ConnectionInfos connection_infos; int srtp_crypto_suite = rtc::SRTP_INVALID_CRYPTO_SUITE; int ssl_cipher_suite = rtc::TLS_NULL_WITH_NULL_NULL; diff --git a/pc/peerconnection.cc b/pc/peerconnection.cc index 533e64845e..aa7146b9b7 100644 --- a/pc/peerconnection.cc +++ b/pc/peerconnection.cc @@ -4937,6 +4937,12 @@ bool PeerConnection::ReadyToSendData() const { sctp_ready_to_send_data_; } +cricket::CandidateStatsList PeerConnection::GetPooledCandidateStats() const { + cricket::CandidateStatsList candidate_states_list; + port_allocator_->GetCandidateStatsFromPooledSessions(&candidate_states_list); + return candidate_states_list; +} + std::map PeerConnection::GetTransportNamesByMid() const { std::map transport_names_by_mid; diff --git a/pc/peerconnection.h b/pc/peerconnection.h index f1dc2996a8..e6ced417c2 100644 --- a/pc/peerconnection.h +++ b/pc/peerconnection.h @@ -233,6 +233,7 @@ class PeerConnection : public PeerConnectionInternal, return sctp_transport_name_; } + cricket::CandidateStatsList GetPooledCandidateStats() const override; std::map GetTransportNamesByMid() const override; std::map GetTransportStatsByNames( const std::set& transport_names) override; diff --git a/pc/peerconnectioninternal.h b/pc/peerconnectioninternal.h index 4bca65ee24..8cf4989976 100644 --- a/pc/peerconnectioninternal.h +++ b/pc/peerconnectioninternal.h @@ -56,6 +56,8 @@ class PeerConnectionInternal : public PeerConnectionInterface { virtual rtc::Optional sctp_content_name() const = 0; virtual rtc::Optional sctp_transport_name() const = 0; + virtual cricket::CandidateStatsList GetPooledCandidateStats() const = 0; + // Returns a map from MID to transport name for all active media sections. virtual std::map GetTransportNamesByMid() const = 0; diff --git a/pc/statscollector.cc b/pc/statscollector.cc index 9a636b47b1..e7fb95b76a 100644 --- a/pc/statscollector.cc +++ b/pc/statscollector.cc @@ -670,10 +670,12 @@ StatsReport* StatsCollector::AddConnectionInfoReport( report->AddBoolean(b.name, b.value); report->AddId(StatsReport::kStatsValueNameChannelId, channel_report_id); + cricket::CandidateStats local_candidate_stats(info.local_candidate); + cricket::CandidateStats remote_candidate_stats(info.remote_candidate); report->AddId(StatsReport::kStatsValueNameLocalCandidateId, - AddCandidateReport(info.local_candidate, true)->id()); + AddCandidateReport(local_candidate_stats, true)->id()); report->AddId(StatsReport::kStatsValueNameRemoteCandidateId, - AddCandidateReport(info.remote_candidate, false)->id()); + AddCandidateReport(remote_candidate_stats, false)->id()); const Int64ForAdd int64s[] = { {StatsReport::kStatsValueNameBytesReceived, info.recv_total_bytes}, @@ -708,8 +710,9 @@ StatsReport* StatsCollector::AddConnectionInfoReport( } StatsReport* StatsCollector::AddCandidateReport( - const cricket::Candidate& candidate, + const cricket::CandidateStats& candidate_stats, bool local) { + const auto& candidate = candidate_stats.candidate; StatsReport::Id id(StatsReport::NewCandidateId(local, candidate.id())); StatsReport* report = reports_.Find(id); if (!report) { @@ -718,6 +721,18 @@ StatsReport* StatsCollector::AddCandidateReport( if (local) { report->AddString(StatsReport::kStatsValueNameCandidateNetworkType, AdapterTypeToStatsType(candidate.network_type())); + if (candidate_stats.stun_stats.has_value()) { + const auto& stun_stats = candidate_stats.stun_stats.value(); + report->AddInt64(StatsReport::kStatsValueNameSentStunKeepaliveRequests, + stun_stats.stun_binding_requests_sent); + report->AddInt64(StatsReport::kStatsValueNameRecvStunKeepaliveResponses, + stun_stats.stun_binding_responses_received); + report->AddFloat(StatsReport::kStatsValueNameStunKeepaliveRttTotal, + stun_stats.stun_binding_rtt_ms_total); + report->AddFloat( + StatsReport::kStatsValueNameStunKeepaliveRttSquaredTotal, + stun_stats.stun_binding_rtt_ms_squared_total); + } } report->AddString(StatsReport::kStatsValueNameCandidateIPAddress, candidate.address().ipaddr().ToString()); @@ -745,6 +760,13 @@ void StatsCollector::ExtractSessionInfo() { report->AddBoolean(StatsReport::kStatsValueNameInitiator, pc_->initial_offerer()); + cricket::CandidateStatsList pooled_candidate_stats_list = + pc_->GetPooledCandidateStats(); + + for (const cricket::CandidateStats& stats : pooled_candidate_stats_list) { + AddCandidateReport(stats, true); + } + std::set transport_names; for (const auto& entry : pc_->GetTransportNamesByMid()) { transport_names.insert(entry.second); @@ -808,6 +830,16 @@ void StatsCollector::ExtractSessionInfo() { rtc::SSLStreamAdapter::SslCipherSuiteToName(ssl_cipher_suite)); } + // Collect stats for non-pooled candidates. Note that the reports + // generated here supersedes the candidate reports generated in + // AddConnectionInfoReport below, and they may report candidates that are + // not paired. Also, the candidate report generated in + // AddConnectionInfoReport do not report port stats like StunStats. + for (const cricket::CandidateStats& stats : + channel_iter.candidate_stats_list) { + AddCandidateReport(stats, true); + } + int connection_id = 0; for (const cricket::ConnectionInfo& info : channel_iter.connection_infos) { diff --git a/pc/statscollector.h b/pc/statscollector.h index 681a8f0098..abd65a97f9 100644 --- a/pc/statscollector.h +++ b/pc/statscollector.h @@ -96,8 +96,9 @@ class StatsCollector { // Helper method for creating IceCandidate report. |is_local| indicates // whether this candidate is local or remote. - StatsReport* AddCandidateReport(const cricket::Candidate& candidate, - bool local); + StatsReport* AddCandidateReport( + const cricket::CandidateStats& candidate_stats, + bool local); // Adds a report for this certificate and every certificate in its chain, and // returns the leaf certificate's report (|cert|'s report). diff --git a/pc/test/fakepeerconnectionforstats.h b/pc/test/fakepeerconnectionforstats.h index c198d1de5a..c26d144ca4 100644 --- a/pc/test/fakepeerconnectionforstats.h +++ b/pc/test/fakepeerconnectionforstats.h @@ -272,6 +272,10 @@ class FakePeerConnectionForStats : public FakePeerConnectionBase { return sctp_data_channels_; } + cricket::CandidateStatsList GetPooledCandidateStats() const override { + return {}; + } + std::map GetTransportNamesByMid() const override { std::map transport_names_by_mid; if (voice_channel_) { diff --git a/rtc_base/helpers.cc b/rtc_base/helpers.cc index b0c8856615..9cb9268792 100644 --- a/rtc_base/helpers.cc +++ b/rtc_base/helpers.cc @@ -215,4 +215,8 @@ double CreateRandomDouble() { std::numeric_limits::epsilon()); } +double GetNextMovingAverage(double prev_average, double cur, double ratio) { + return (ratio * prev_average + cur) / (ratio + 1); +} + } // namespace rtc diff --git a/rtc_base/helpers.h b/rtc_base/helpers.h index e1d2ebb2aa..0100794154 100644 --- a/rtc_base/helpers.h +++ b/rtc_base/helpers.h @@ -59,6 +59,10 @@ uint32_t CreateRandomNonZeroId(); // Generates a random double between 0.0 (inclusive) and 1.0 (exclusive). double CreateRandomDouble(); +// Compute moving average with the given ratio between the previous average +// value and the current value. +double GetNextMovingAverage(double prev_average, double cur, double ratio); + } // namespace rtc #endif // RTC_BASE_HELPERS_H_