tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

packet_loss_stats.cc (4854B)


      1 /*
      2 *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
      3 *
      4 *  Use of this source code is governed by a BSD-style license
      5 *  that can be found in the LICENSE file in the root of the source
      6 *  tree. An additional intellectual property rights grant can be found
      7 *  in the file PATENTS.  All contributing project authors may
      8 *  be found in the AUTHORS file in the root of the source tree.
      9 */
     10 
     11 #include "modules/rtp_rtcp/source/packet_loss_stats.h"
     12 
     13 #include <cstdint>
     14 #include <iterator>
     15 #include <set>
     16 #include <vector>
     17 
     18 #include "rtc_base/checks.h"
     19 
     20 namespace webrtc {
     21 namespace {
     22 
     23 // After this many packets are added, adding additional packets will cause the
     24 // oldest packets to be pruned from the buffer.
     25 constexpr int kBufferSize = 100;
     26 
     27 }  // namespace
     28 
     29 PacketLossStats::PacketLossStats()
     30    : single_loss_historic_count_(0),
     31      multiple_loss_historic_event_count_(0),
     32      multiple_loss_historic_packet_count_(0) {}
     33 
     34 PacketLossStats::~PacketLossStats() = default;
     35 
     36 void PacketLossStats::AddLostPacket(uint16_t sequence_number) {
     37  // Detect sequence number wrap around.
     38  if (!lost_packets_buffer_.empty() &&
     39      static_cast<int>(*(lost_packets_buffer_.rbegin())) - sequence_number >
     40          0x8000) {
     41    // The buffer contains large numbers and this is a small number.
     42    lost_packets_wrapped_buffer_.insert(sequence_number);
     43  } else {
     44    lost_packets_buffer_.insert(sequence_number);
     45  }
     46  if (lost_packets_wrapped_buffer_.size() + lost_packets_buffer_.size() >
     47          kBufferSize ||
     48      (!lost_packets_wrapped_buffer_.empty() &&
     49       *(lost_packets_wrapped_buffer_.rbegin()) > 0x4000)) {
     50    PruneBuffer();
     51  }
     52 }
     53 
     54 int PacketLossStats::GetSingleLossCount() const {
     55  int single_loss_count, unused1, unused2;
     56  ComputeLossCounts(&single_loss_count, &unused1, &unused2);
     57  return single_loss_count;
     58 }
     59 
     60 int PacketLossStats::GetMultipleLossEventCount() const {
     61  int event_count, unused1, unused2;
     62  ComputeLossCounts(&unused1, &event_count, &unused2);
     63  return event_count;
     64 }
     65 
     66 int PacketLossStats::GetMultipleLossPacketCount() const {
     67  int packet_count, unused1, unused2;
     68  ComputeLossCounts(&unused1, &unused2, &packet_count);
     69  return packet_count;
     70 }
     71 
     72 void PacketLossStats::ComputeLossCounts(
     73    int* out_single_loss_count,
     74    int* out_multiple_loss_event_count,
     75    int* out_multiple_loss_packet_count) const {
     76  *out_single_loss_count = single_loss_historic_count_;
     77  *out_multiple_loss_event_count = multiple_loss_historic_event_count_;
     78  *out_multiple_loss_packet_count = multiple_loss_historic_packet_count_;
     79  if (lost_packets_buffer_.empty()) {
     80    RTC_DCHECK(lost_packets_wrapped_buffer_.empty());
     81    return;
     82  }
     83  uint16_t last_num = 0;
     84  int sequential_count = 0;
     85  std::vector<const std::set<uint16_t>*> buffers;
     86  buffers.push_back(&lost_packets_buffer_);
     87  buffers.push_back(&lost_packets_wrapped_buffer_);
     88  for (const auto* buffer : buffers) {
     89    for (auto it = buffer->begin(); it != buffer->end(); ++it) {
     90      uint16_t current_num = *it;
     91      if (sequential_count > 0 && current_num != ((last_num + 1) & 0xFFFF)) {
     92        if (sequential_count == 1) {
     93          (*out_single_loss_count)++;
     94        } else {
     95          (*out_multiple_loss_event_count)++;
     96          *out_multiple_loss_packet_count += sequential_count;
     97        }
     98        sequential_count = 0;
     99      }
    100      sequential_count++;
    101      last_num = current_num;
    102    }
    103  }
    104  if (sequential_count == 1) {
    105    (*out_single_loss_count)++;
    106  } else if (sequential_count > 1) {
    107    (*out_multiple_loss_event_count)++;
    108    *out_multiple_loss_packet_count += sequential_count;
    109  }
    110 }
    111 
    112 void PacketLossStats::PruneBuffer() {
    113  // Remove the oldest lost packet and any contiguous packets and move them
    114  // into the historic counts.
    115  auto it = lost_packets_buffer_.begin();
    116  uint16_t last_removed = 0;
    117  int remove_count = 0;
    118  // Count adjacent packets and continue counting if it is wrap around by
    119  // swapping in the wrapped buffer and letting our value wrap as well.
    120  while (remove_count == 0 || (!lost_packets_buffer_.empty() &&
    121                               *it == ((last_removed + 1) & 0xFFFF))) {
    122    last_removed = *it;
    123    remove_count++;
    124    auto to_erase = it++;
    125    lost_packets_buffer_.erase(to_erase);
    126    if (lost_packets_buffer_.empty()) {
    127      lost_packets_buffer_.swap(lost_packets_wrapped_buffer_);
    128      it = lost_packets_buffer_.begin();
    129    }
    130  }
    131  if (remove_count > 1) {
    132    multiple_loss_historic_event_count_++;
    133    multiple_loss_historic_packet_count_ += remove_count;
    134  } else {
    135    single_loss_historic_count_++;
    136  }
    137  // Continue pruning if the wrapped buffer is beyond a threshold and there are
    138  // things left in the pre-wrapped buffer.
    139  if (!lost_packets_wrapped_buffer_.empty() &&
    140      *(lost_packets_wrapped_buffer_.rbegin()) > 0x4000) {
    141    PruneBuffer();
    142  }
    143 }
    144 
    145 }  // namespace webrtc