| // 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 |