Project import generated by Copybara.
PiperOrigin-RevId: 237361882
Change-Id: I109a68f44db867b20f8c6a7732b0ce657133e52a
diff --git a/quic/core/frames/quic_ack_frame.cc b/quic/core/frames/quic_ack_frame.cc
new file mode 100644
index 0000000..389f1c0
--- /dev/null
+++ b/quic/core/frames/quic_ack_frame.cc
@@ -0,0 +1,326 @@
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/core/frames/quic_ack_frame.h"
+
+#include "net/third_party/quiche/src/quic/core/quic_constants.h"
+#include "net/third_party/quiche/src/quic/core/quic_interval.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
+
+namespace quic {
+
+namespace {
+
+const QuicPacketCount kMaxPrintRange = 128;
+
+uint64_t PacketNumberIntervalLength(
+ const QuicInterval<QuicPacketNumber>& interval) {
+ if (interval.Empty()) {
+ return 0u;
+ }
+ return interval.max() - interval.min();
+}
+} // namespace
+
+bool IsAwaitingPacket(const QuicAckFrame& ack_frame,
+ QuicPacketNumber packet_number,
+ QuicPacketNumber peer_least_packet_awaiting_ack) {
+ DCHECK(packet_number.IsInitialized());
+ return (!peer_least_packet_awaiting_ack.IsInitialized() ||
+ packet_number >= peer_least_packet_awaiting_ack) &&
+ !ack_frame.packets.Contains(packet_number);
+}
+
+QuicAckFrame::QuicAckFrame()
+ : ack_delay_time(QuicTime::Delta::Infinite()),
+ ecn_counters_populated(false),
+ ect_0_count(0),
+ ect_1_count(0),
+ ecn_ce_count(0) {}
+
+QuicAckFrame::QuicAckFrame(const QuicAckFrame& other) = default;
+
+QuicAckFrame::~QuicAckFrame() {}
+
+std::ostream& operator<<(std::ostream& os, const QuicAckFrame& ack_frame) {
+ os << "{ largest_acked: " << LargestAcked(ack_frame)
+ << ", ack_delay_time: " << ack_frame.ack_delay_time.ToMicroseconds()
+ << ", packets: [ " << ack_frame.packets << " ]"
+ << ", received_packets: [ ";
+ for (const std::pair<QuicPacketNumber, QuicTime>& p :
+ ack_frame.received_packet_times) {
+ os << p.first << " at " << p.second.ToDebuggingValue() << " ";
+ }
+ os << " ]";
+ os << ", ecn_counters_populated: " << ack_frame.ecn_counters_populated;
+ if (ack_frame.ecn_counters_populated) {
+ os << ", ect_0_count: " << ack_frame.ect_0_count
+ << ", ect_1_count: " << ack_frame.ect_1_count
+ << ", ecn_ce_count: " << ack_frame.ecn_ce_count;
+ }
+
+ os << " }\n";
+ return os;
+}
+
+void QuicAckFrame::Clear() {
+ largest_acked.Clear();
+ ack_delay_time = QuicTime::Delta::Infinite();
+ received_packet_times.clear();
+ packets.Clear();
+}
+
+PacketNumberQueue::PacketNumberQueue() {}
+PacketNumberQueue::PacketNumberQueue(const PacketNumberQueue& other) = default;
+PacketNumberQueue::PacketNumberQueue(PacketNumberQueue&& other) = default;
+PacketNumberQueue::~PacketNumberQueue() {}
+
+PacketNumberQueue& PacketNumberQueue::operator=(
+ const PacketNumberQueue& other) = default;
+PacketNumberQueue& PacketNumberQueue::operator=(PacketNumberQueue&& other) =
+ default;
+
+void PacketNumberQueue::Add(QuicPacketNumber packet_number) {
+ if (!packet_number.IsInitialized()) {
+ return;
+ }
+ // Check if the deque is empty
+ if (packet_number_deque_.empty()) {
+ packet_number_deque_.push_front(
+ QuicInterval<QuicPacketNumber>(packet_number, packet_number + 1));
+ return;
+ }
+ QuicInterval<QuicPacketNumber> back = packet_number_deque_.back();
+
+ // Check for the typical case,
+ // when the next packet in order is acked
+ if (back.max() == packet_number) {
+ packet_number_deque_.back().SetMax(packet_number + 1);
+ return;
+ }
+ // Check if the next packet in order is skipped
+ if (back.max() < packet_number) {
+ packet_number_deque_.push_back(
+ QuicInterval<QuicPacketNumber>(packet_number, packet_number + 1));
+ return;
+ }
+
+ QuicInterval<QuicPacketNumber> front = packet_number_deque_.front();
+ // Check if the packet can be popped on the front
+ if (front.min() > packet_number + 1) {
+ packet_number_deque_.push_front(
+ QuicInterval<QuicPacketNumber>(packet_number, packet_number + 1));
+ return;
+ }
+ if (front.min() == packet_number + 1) {
+ packet_number_deque_.front().SetMin(packet_number);
+ return;
+ }
+
+ int i = packet_number_deque_.size() - 1;
+ // Iterating through the queue backwards
+ // to find a proper place for the packet
+ while (i >= 0) {
+ QuicInterval<QuicPacketNumber> packet_interval = packet_number_deque_[i];
+ DCHECK(packet_interval.min() < packet_interval.max());
+ // Check if the packet is contained in an interval already
+ if (packet_interval.Contains(packet_number)) {
+ return;
+ }
+
+ // Check if the packet can extend an interval.
+ if (packet_interval.max() == packet_number) {
+ packet_number_deque_[i].SetMax(packet_number + 1);
+ return;
+ }
+ // Check if the packet can extend an interval
+ // and merge two intervals if needed.
+ // There is no need to merge an interval in the previous
+ // if statement, as all merges will happen here.
+ if (packet_interval.min() == packet_number + 1) {
+ packet_number_deque_[i].SetMin(packet_number);
+ if (i > 0 && packet_number == packet_number_deque_[i - 1].max()) {
+ packet_number_deque_[i - 1].SetMax(packet_interval.max());
+ packet_number_deque_.erase(packet_number_deque_.begin() + i);
+ }
+ return;
+ }
+
+ // Check if we need to make a new interval for the packet
+ if (packet_interval.max() < packet_number + 1) {
+ packet_number_deque_.insert(
+ packet_number_deque_.begin() + i + 1,
+ QuicInterval<QuicPacketNumber>(packet_number, packet_number + 1));
+ return;
+ }
+ i--;
+ }
+}
+
+void PacketNumberQueue::AddRange(QuicPacketNumber lower,
+ QuicPacketNumber higher) {
+ if (!lower.IsInitialized() || !higher.IsInitialized() || lower >= higher) {
+ return;
+ }
+ if (packet_number_deque_.empty()) {
+ packet_number_deque_.push_front(
+ QuicInterval<QuicPacketNumber>(lower, higher));
+ return;
+ }
+ QuicInterval<QuicPacketNumber> back = packet_number_deque_.back();
+
+ if (back.max() == lower) {
+ // Check for the typical case,
+ // when the next packet in order is acked
+ packet_number_deque_.back().SetMax(higher);
+ return;
+ }
+ if (back.max() < lower) {
+ // Check if the next packet in order is skipped
+ packet_number_deque_.push_back(
+ QuicInterval<QuicPacketNumber>(lower, higher));
+ return;
+ }
+ QuicInterval<QuicPacketNumber> front = packet_number_deque_.front();
+ // Check if the packets are being added in reverse order
+ if (front.min() == higher) {
+ packet_number_deque_.front().SetMin(lower);
+ } else if (front.min() > higher) {
+ packet_number_deque_.push_front(
+ QuicInterval<QuicPacketNumber>(lower, higher));
+
+ } else {
+ // Ranges must be above or below all existing ranges.
+ QUIC_BUG << "AddRange only supports adding packets above or below the "
+ << "current min:" << Min() << " and max:" << Max()
+ << ", but adding [" << lower << "," << higher << ")";
+ }
+}
+
+bool PacketNumberQueue::RemoveUpTo(QuicPacketNumber higher) {
+ if (!higher.IsInitialized() || Empty()) {
+ return false;
+ }
+ const QuicPacketNumber old_min = Min();
+ while (!packet_number_deque_.empty()) {
+ QuicInterval<QuicPacketNumber> front = packet_number_deque_.front();
+ if (front.max() < higher) {
+ packet_number_deque_.pop_front();
+ } else if (front.min() < higher && front.max() >= higher) {
+ packet_number_deque_.front().SetMin(higher);
+ if (front.max() == higher) {
+ packet_number_deque_.pop_front();
+ }
+ break;
+ } else {
+ break;
+ }
+ }
+
+ return Empty() || old_min != Min();
+}
+
+void PacketNumberQueue::RemoveSmallestInterval() {
+ QUIC_BUG_IF(packet_number_deque_.size() < 2)
+ << (Empty() ? "No intervals to remove."
+ : "Can't remove the last interval.");
+ packet_number_deque_.pop_front();
+}
+
+void PacketNumberQueue::Clear() {
+ packet_number_deque_.clear();
+}
+
+bool PacketNumberQueue::Contains(QuicPacketNumber packet_number) const {
+ if (!packet_number.IsInitialized() || packet_number_deque_.empty()) {
+ return false;
+ }
+ if (packet_number_deque_.front().min() > packet_number ||
+ packet_number_deque_.back().max() <= packet_number) {
+ return false;
+ }
+ for (QuicInterval<QuicPacketNumber> interval : packet_number_deque_) {
+ if (interval.Contains(packet_number)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool PacketNumberQueue::Empty() const {
+ return packet_number_deque_.empty();
+}
+
+QuicPacketNumber PacketNumberQueue::Min() const {
+ DCHECK(!Empty());
+ return packet_number_deque_.front().min();
+}
+
+QuicPacketNumber PacketNumberQueue::Max() const {
+ DCHECK(!Empty());
+ return packet_number_deque_.back().max() - 1;
+}
+
+QuicPacketCount PacketNumberQueue::NumPacketsSlow() const {
+ QuicPacketCount n_packets = 0;
+ for (QuicInterval<QuicPacketNumber> interval : packet_number_deque_) {
+ n_packets += PacketNumberIntervalLength(interval);
+ }
+ return n_packets;
+}
+
+size_t PacketNumberQueue::NumIntervals() const {
+ return packet_number_deque_.size();
+}
+
+PacketNumberQueue::const_iterator PacketNumberQueue::begin() const {
+ return packet_number_deque_.begin();
+}
+
+PacketNumberQueue::const_iterator PacketNumberQueue::end() const {
+ return packet_number_deque_.end();
+}
+
+PacketNumberQueue::const_reverse_iterator PacketNumberQueue::rbegin() const {
+ return packet_number_deque_.rbegin();
+}
+
+PacketNumberQueue::const_reverse_iterator PacketNumberQueue::rend() const {
+ return packet_number_deque_.rend();
+}
+
+QuicPacketCount PacketNumberQueue::LastIntervalLength() const {
+ DCHECK(!Empty());
+ return PacketNumberIntervalLength(packet_number_deque_.back());
+}
+
+// Largest min...max range for packet numbers where we print the numbers
+// explicitly. If bigger than this, we print as a range [a,d] rather
+// than [a b c d]
+
+std::ostream& operator<<(std::ostream& os, const PacketNumberQueue& q) {
+ for (const QuicInterval<QuicPacketNumber>& interval : q) {
+ // Print as a range if there is a pathological condition.
+ if ((interval.min() >= interval.max()) ||
+ (interval.max() - interval.min() > kMaxPrintRange)) {
+ // If min>max, it's really a bug, so QUIC_BUG it to
+ // catch it in development.
+ QUIC_BUG_IF(interval.min() >= interval.max())
+ << "Ack Range minimum (" << interval.min() << "Not less than max ("
+ << interval.max() << ")";
+ // print range as min...max rather than full list.
+ // in the event of a bug, the list could be very big.
+ os << interval.min() << "..." << (interval.max() - 1) << " ";
+ } else {
+ for (QuicPacketNumber packet_number = interval.min();
+ packet_number < interval.max(); ++packet_number) {
+ os << packet_number << " ";
+ }
+ }
+ }
+ return os;
+}
+
+} // namespace quic