/* * Copyright 2017 The WebRTC Project Authors. All rights reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "p2p/base/packetlossestimator.h" #include "rtc_base/checks.h" namespace cricket { PacketLossEstimator::PacketLossEstimator(int64_t consider_lost_after_ms, int64_t forget_after_ms) : consider_lost_after_ms_(consider_lost_after_ms), forget_after_ms_(forget_after_ms) { RTC_DCHECK_LT(consider_lost_after_ms, forget_after_ms); } PacketLossEstimator::~PacketLossEstimator() = default; void PacketLossEstimator::ExpectResponse(std::string id, int64_t sent_time) { tracked_packets_[id] = PacketInfo{sent_time, false}; // Called to free memory in case the client hasn't called UpdateResponseRate // in a while. MaybeForgetOldRequests(sent_time); } void PacketLossEstimator::ReceivedResponse(std::string id, int64_t received_time) { auto iter = tracked_packets_.find(id); if (iter != tracked_packets_.end()) { auto& packet_info = iter->second; packet_info.response_received = true; } // Called to free memory in case the client hasn't called UpdateResponseRate // in a while. MaybeForgetOldRequests(received_time); } void PacketLossEstimator::UpdateResponseRate(int64_t now) { int responses_expected = 0; int responses_received = 0; for (auto iter = tracked_packets_.begin(); iter != tracked_packets_.end();) { const auto& packet_info = iter->second; if (Forget(packet_info, now)) { iter = tracked_packets_.erase(iter); continue; } if (packet_info.response_received) { responses_expected += 1; responses_received += 1; } else if (ConsiderLost(packet_info, now)) { responses_expected += 1; } ++iter; } if (responses_expected > 0) { response_rate_ = static_cast(responses_received) / responses_expected; } else { response_rate_ = 1.0; } last_forgot_at_ = now; } void PacketLossEstimator::MaybeForgetOldRequests(int64_t now) { if (now - last_forgot_at_ <= forget_after_ms_) { return; } for (auto iter = tracked_packets_.begin(); iter != tracked_packets_.end();) { const auto& packet_info = iter->second; if (Forget(packet_info, now)) { iter = tracked_packets_.erase(iter); } else { ++iter; } } last_forgot_at_ = now; } bool PacketLossEstimator::ConsiderLost(const PacketInfo& packet_info, int64_t now) const { return packet_info.sent_time < now - consider_lost_after_ms_; } bool PacketLossEstimator::Forget(const PacketInfo& packet_info, int64_t now) const { return now - packet_info.sent_time > forget_after_ms_; } std::size_t PacketLossEstimator::tracked_packet_count_for_testing() const { return tracked_packets_.size(); } } // namespace cricket