aboutsummaryrefslogtreecommitdiff
path: root/modules/congestion_controller/bbr/data_transfer_tracker.cc
blob: 5de85efb8b02b550fdc79525278b9c67b08a2e2d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
/*
 *  Copyright (c) 2018 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 "modules/congestion_controller/bbr/data_transfer_tracker.h"

#include "rtc_base/checks.h"
#include "rtc_base/logging.h"

namespace webrtc {
namespace bbr {

DataTransferTracker::DataTransferTracker() {}

DataTransferTracker::~DataTransferTracker() {}

void DataTransferTracker::AddSample(DataSize size_delta,
                                    Timestamp send_time,
                                    Timestamp ack_time) {
  size_sum_ += size_delta;

  RTC_DCHECK(samples_.empty() || send_time >= samples_.back().send_time);
  RTC_DCHECK(samples_.empty() || ack_time >= samples_.back().ack_time);

  if (!samples_.empty() && ack_time == samples_.back().ack_time) {
    samples_.back().send_time = send_time;
    samples_.back().size_sum = size_sum_;
  } else {
    Sample new_sample;
    new_sample.ack_time = ack_time;
    new_sample.send_time = send_time;
    new_sample.size_delta = size_delta;
    new_sample.size_sum = size_sum_;
    samples_.push_back(new_sample);
  }
}

void DataTransferTracker::ClearOldSamples(Timestamp excluding_end) {
  while (!samples_.empty() && samples_.front().ack_time < excluding_end) {
    samples_.pop_front();
  }
}

DataTransferTracker::Result DataTransferTracker::GetRatesByAckTime(
    Timestamp covered_start,
    Timestamp including_end) {
  Result res;
  // Last sample before covered_start.
  const Sample* window_begin = nullptr;
  // Sample at end time or first sample after end time-
  const Sample* window_end = nullptr;
  // To handle the case when the first sample is after covered_start.
  if (samples_.front().ack_time < including_end)
    window_begin = &samples_.front();
  // To handle the case when the last sample is before including_end.
  if (samples_.back().ack_time > covered_start)
    window_end = &samples_.back();
  for (const auto& sample : samples_) {
    if (sample.ack_time < covered_start) {
      window_begin = &sample;
    } else if (sample.ack_time >= including_end) {
      window_end = &sample;
      break;
    }
  }
  if (window_begin != nullptr && window_end != nullptr) {
    res.acked_data = window_end->size_sum - window_begin->size_sum;
    res.send_timespan = window_end->send_time - window_begin->send_time;
    res.ack_timespan = window_end->ack_time - window_begin->ack_time;
  } else {
    res.acked_data = DataSize::Zero();
    res.ack_timespan = including_end - covered_start;
    res.send_timespan = TimeDelta::Zero();
  }
  return res;
}

}  // namespace bbr
}  // namespace webrtc