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
diff --git a/quic/core/frames/quic_ack_frame.h b/quic/core/frames/quic_ack_frame.h
new file mode 100644
index 0000000..771d93e
--- /dev/null
+++ b/quic/core/frames/quic_ack_frame.h
@@ -0,0 +1,144 @@
+// 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.
+
+#ifndef QUICHE_QUIC_CORE_FRAMES_QUIC_ACK_FRAME_H_
+#define QUICHE_QUIC_CORE_FRAMES_QUIC_ACK_FRAME_H_
+
+#include <ostream>
+
+#include "net/third_party/quiche/src/quic/core/quic_interval.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
+
+namespace quic {
+
+// A sequence of packet numbers where each number is unique. Intended to be used
+// in a sliding window fashion, where smaller old packet numbers are removed and
+// larger new packet numbers are added, with the occasional random access.
+class QUIC_EXPORT_PRIVATE PacketNumberQueue {
+ public:
+ PacketNumberQueue();
+ PacketNumberQueue(const PacketNumberQueue& other);
+ PacketNumberQueue(PacketNumberQueue&& other);
+ ~PacketNumberQueue();
+
+ PacketNumberQueue& operator=(const PacketNumberQueue& other);
+ PacketNumberQueue& operator=(PacketNumberQueue&& other);
+
+ typedef QuicDeque<QuicInterval<QuicPacketNumber>>::const_iterator
+ const_iterator;
+ typedef QuicDeque<QuicInterval<QuicPacketNumber>>::const_reverse_iterator
+ const_reverse_iterator;
+
+ // Adds |packet_number| to the set of packets in the queue.
+ void Add(QuicPacketNumber packet_number);
+
+ // Adds packets between [lower, higher) to the set of packets in the queue. It
+ // is undefined behavior to call this with |higher| < |lower|.
+ void AddRange(QuicPacketNumber lower, QuicPacketNumber higher);
+
+ // Removes packets with values less than |higher| from the set of packets in
+ // the queue. Returns true if packets were removed.
+ bool RemoveUpTo(QuicPacketNumber higher);
+
+ // Removes the smallest interval in the queue.
+ void RemoveSmallestInterval();
+
+ // Clear this packet number queue.
+ void Clear();
+
+ // Returns true if the queue contains |packet_number|.
+ bool Contains(QuicPacketNumber packet_number) const;
+
+ // Returns true if the queue is empty.
+ bool Empty() const;
+
+ // Returns the minimum packet number stored in the queue. It is undefined
+ // behavior to call this if the queue is empty.
+ QuicPacketNumber Min() const;
+
+ // Returns the maximum packet number stored in the queue. It is undefined
+ // behavior to call this if the queue is empty.
+ QuicPacketNumber Max() const;
+
+ // Returns the number of unique packets stored in the queue. Inefficient; only
+ // exposed for testing.
+ QuicPacketCount NumPacketsSlow() const;
+
+ // Returns the number of disjoint packet number intervals contained in the
+ // queue.
+ size_t NumIntervals() const;
+
+ // Returns the length of last interval.
+ QuicPacketCount LastIntervalLength() const;
+
+ // Returns iterators over the packet number intervals.
+ const_iterator begin() const;
+ const_iterator end() const;
+ const_reverse_iterator rbegin() const;
+ const_reverse_iterator rend() const;
+
+ friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(
+ std::ostream& os,
+ const PacketNumberQueue& q);
+
+ private:
+ QuicDeque<QuicInterval<QuicPacketNumber>> packet_number_deque_;
+};
+
+struct QUIC_EXPORT_PRIVATE QuicAckFrame {
+ QuicAckFrame();
+ QuicAckFrame(const QuicAckFrame& other);
+ ~QuicAckFrame();
+
+ void Clear();
+
+ friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(
+ std::ostream& os,
+ const QuicAckFrame& ack_frame);
+
+ // The highest packet number we've observed from the peer. When |packets| is
+ // not empty, it should always be equal to packets.Max(). The |LargestAcked|
+ // function ensures this invariant in debug mode.
+ QuicPacketNumber largest_acked;
+
+ // Time elapsed since largest_observed() was received until this Ack frame was
+ // sent.
+ QuicTime::Delta ack_delay_time;
+
+ // Vector of <packet_number, time> for when packets arrived.
+ PacketTimeVector received_packet_times;
+
+ // Set of packets.
+ PacketNumberQueue packets;
+
+ // ECN counters, used only in version 99's ACK frame and valid only when
+ // |ecn_counters_populated| is true.
+ bool ecn_counters_populated;
+ QuicPacketCount ect_0_count;
+ QuicPacketCount ect_1_count;
+ QuicPacketCount ecn_ce_count;
+};
+
+// The highest acked packet number we've observed from the peer. If no packets
+// have been observed, return 0.
+inline QUIC_EXPORT_PRIVATE QuicPacketNumber
+LargestAcked(const QuicAckFrame& frame) {
+ DCHECK(frame.packets.Empty() || frame.packets.Max() == frame.largest_acked);
+ return frame.largest_acked;
+}
+
+// True if the packet number is greater than largest_observed or is listed
+// as missing.
+// Always returns false for packet numbers less than least_unacked.
+QUIC_EXPORT_PRIVATE bool IsAwaitingPacket(
+ const QuicAckFrame& ack_frame,
+ QuicPacketNumber packet_number,
+ QuicPacketNumber peer_least_packet_awaiting_ack);
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_FRAMES_QUIC_ACK_FRAME_H_
diff --git a/quic/core/frames/quic_application_close_frame.cc b/quic/core/frames/quic_application_close_frame.cc
new file mode 100644
index 0000000..2535655
--- /dev/null
+++ b/quic/core/frames/quic_application_close_frame.cc
@@ -0,0 +1,19 @@
+// 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_application_close_frame.h"
+
+namespace quic {
+
+QuicApplicationCloseFrame::QuicApplicationCloseFrame()
+ : error_code(QUIC_NO_ERROR) {}
+
+std::ostream& operator<<(std::ostream& os,
+ const QuicApplicationCloseFrame& frame) {
+ os << "{ error_code: " << frame.error_code << ", error_details: '"
+ << frame.error_details << "' }\n";
+ return os;
+}
+
+} // namespace quic
diff --git a/quic/core/frames/quic_application_close_frame.h b/quic/core/frames/quic_application_close_frame.h
new file mode 100644
index 0000000..b9b84dd
--- /dev/null
+++ b/quic/core/frames/quic_application_close_frame.h
@@ -0,0 +1,29 @@
+// 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.
+
+#ifndef QUICHE_QUIC_CORE_FRAMES_QUIC_APPLICATION_CLOSE_FRAME_H_
+#define QUICHE_QUIC_CORE_FRAMES_QUIC_APPLICATION_CLOSE_FRAME_H_
+
+#include <ostream>
+
+#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_string.h"
+
+namespace quic {
+
+struct QUIC_EXPORT_PRIVATE QuicApplicationCloseFrame {
+ QuicApplicationCloseFrame();
+
+ friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(
+ std::ostream& os,
+ const QuicApplicationCloseFrame& frame);
+
+ QuicErrorCode error_code;
+ QuicString error_details;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_FRAMES_QUIC_APPLICATION_CLOSE_FRAME_H_
diff --git a/quic/core/frames/quic_blocked_frame.cc b/quic/core/frames/quic_blocked_frame.cc
new file mode 100644
index 0000000..41ba144
--- /dev/null
+++ b/quic/core/frames/quic_blocked_frame.cc
@@ -0,0 +1,31 @@
+// 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_blocked_frame.h"
+#include "net/third_party/quiche/src/quic/core/quic_constants.h"
+
+namespace quic {
+
+QuicBlockedFrame::QuicBlockedFrame()
+ : control_frame_id(kInvalidControlFrameId), stream_id(0), offset(0) {}
+
+QuicBlockedFrame::QuicBlockedFrame(QuicControlFrameId control_frame_id,
+ QuicStreamId stream_id)
+ : control_frame_id(control_frame_id), stream_id(stream_id), offset(0) {}
+
+QuicBlockedFrame::QuicBlockedFrame(QuicControlFrameId control_frame_id,
+ QuicStreamId stream_id,
+ QuicStreamOffset offset)
+ : control_frame_id(control_frame_id),
+ stream_id(stream_id),
+ offset(offset) {}
+
+std::ostream& operator<<(std::ostream& os,
+ const QuicBlockedFrame& blocked_frame) {
+ os << "{ control_frame_id: " << blocked_frame.control_frame_id
+ << ", stream_id: " << blocked_frame.stream_id << " }\n";
+ return os;
+}
+
+} // namespace quic
diff --git a/quic/core/frames/quic_blocked_frame.h b/quic/core/frames/quic_blocked_frame.h
new file mode 100644
index 0000000..a4be664
--- /dev/null
+++ b/quic/core/frames/quic_blocked_frame.h
@@ -0,0 +1,51 @@
+// 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.
+
+#ifndef QUICHE_QUIC_CORE_FRAMES_QUIC_BLOCKED_FRAME_H_
+#define QUICHE_QUIC_CORE_FRAMES_QUIC_BLOCKED_FRAME_H_
+
+#include <ostream>
+
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+
+namespace quic {
+
+// The BLOCKED frame is used to indicate to the remote endpoint that this
+// endpoint believes itself to be flow-control blocked but otherwise ready to
+// send data. The BLOCKED frame is purely advisory and optional.
+// Based on SPDY's BLOCKED frame (undocumented as of 2014-01-28).
+struct QUIC_EXPORT_PRIVATE QuicBlockedFrame {
+ QuicBlockedFrame();
+ QuicBlockedFrame(QuicControlFrameId control_frame_id, QuicStreamId stream_id);
+ QuicBlockedFrame(QuicControlFrameId control_frame_id,
+ QuicStreamId stream_id,
+ QuicStreamOffset offset);
+
+ friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(
+ std::ostream& os,
+ const QuicBlockedFrame& b);
+
+ // A unique identifier of this control frame. 0 when this frame is received,
+ // and non-zero when sent.
+ QuicControlFrameId control_frame_id;
+
+ // The stream this frame applies to. 0 is a special case meaning the overall
+ // connection rather than a specific stream.
+ //
+ // For IETF QUIC, the stream_id controls whether an IETF QUIC
+ // BLOCKED or STREAM_BLOCKED frame is generated.
+ // If stream_id is 0 then a BLOCKED frame is generated and transmitted,
+ // if non-0, a STREAM_BLOCKED.
+ // TODO(fkastenholz): This should be converted to use
+ // QuicUtils::GetInvalidStreamId to get the correct invalid stream id value
+ // and not rely on 0.
+ QuicStreamId stream_id;
+
+ // For Google QUIC, the offset is ignored.
+ QuicStreamOffset offset;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_FRAMES_QUIC_BLOCKED_FRAME_H_
diff --git a/quic/core/frames/quic_connection_close_frame.cc b/quic/core/frames/quic_connection_close_frame.cc
new file mode 100644
index 0000000..51969c6
--- /dev/null
+++ b/quic/core/frames/quic_connection_close_frame.cc
@@ -0,0 +1,35 @@
+// 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_connection_close_frame.h"
+
+namespace quic {
+
+QuicConnectionCloseFrame::QuicConnectionCloseFrame()
+ : error_code(QUIC_NO_ERROR), frame_type(0) {}
+
+QuicConnectionCloseFrame::QuicConnectionCloseFrame(QuicErrorCode error_code,
+ QuicString error_details)
+ : error_code(error_code),
+ error_details(std::move(error_details)),
+ frame_type(0) {}
+
+QuicConnectionCloseFrame::QuicConnectionCloseFrame(
+ QuicIetfTransportErrorCodes ietf_error_code,
+ QuicString error_details,
+ uint64_t frame_type)
+ : ietf_error_code(ietf_error_code),
+ error_details(std::move(error_details)),
+ frame_type(frame_type) {}
+
+std::ostream& operator<<(
+ std::ostream& os,
+ const QuicConnectionCloseFrame& connection_close_frame) {
+ os << "{ error_code: " << connection_close_frame.error_code
+ << ", error_details: '" << connection_close_frame.error_details
+ << "', frame_type: " << connection_close_frame.frame_type << "}\n";
+ return os;
+}
+
+} // namespace quic
diff --git a/quic/core/frames/quic_connection_close_frame.h b/quic/core/frames/quic_connection_close_frame.h
new file mode 100644
index 0000000..2bbbe73
--- /dev/null
+++ b/quic/core/frames/quic_connection_close_frame.h
@@ -0,0 +1,46 @@
+// 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.
+
+#ifndef QUICHE_QUIC_CORE_FRAMES_QUIC_CONNECTION_CLOSE_FRAME_H_
+#define QUICHE_QUIC_CORE_FRAMES_QUIC_CONNECTION_CLOSE_FRAME_H_
+
+#include <ostream>
+
+#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_string.h"
+
+namespace quic {
+
+struct QUIC_EXPORT_PRIVATE QuicConnectionCloseFrame {
+ QuicConnectionCloseFrame();
+ QuicConnectionCloseFrame(QuicErrorCode error_code, QuicString error_details);
+ QuicConnectionCloseFrame(QuicIetfTransportErrorCodes ietf_error_code,
+ QuicString error_details,
+ uint64_t frame_type);
+
+ friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(
+ std::ostream& os,
+ const QuicConnectionCloseFrame& c);
+
+ // Set error_code or ietf_error_code based on the transport version
+ // currently in use.
+ union {
+ // IETF QUIC has a different set of error codes. Include both
+ // code-sets.
+ QuicErrorCode error_code;
+ QuicIetfTransportErrorCodes ietf_error_code;
+ };
+ QuicString error_details;
+
+ // Contains the type of frame that triggered the connection close. Made a
+ // uint64, as opposed to the QuicIetfFrameType, to support possible
+ // extensions as well as reporting invalid frame types received from the peer.
+ uint64_t frame_type;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_FRAMES_QUIC_CONNECTION_CLOSE_FRAME_H_
diff --git a/quic/core/frames/quic_crypto_frame.cc b/quic/core/frames/quic_crypto_frame.cc
new file mode 100644
index 0000000..9d602bc
--- /dev/null
+++ b/quic/core/frames/quic_crypto_frame.cc
@@ -0,0 +1,42 @@
+// Copyright (c) 2018 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_crypto_frame.h"
+
+#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
+
+namespace quic {
+
+QuicCryptoFrame::QuicCryptoFrame()
+ : QuicCryptoFrame(ENCRYPTION_NONE, 0, nullptr, 0) {}
+
+QuicCryptoFrame::QuicCryptoFrame(EncryptionLevel level,
+ QuicStreamOffset offset,
+ QuicPacketLength data_length)
+ : QuicCryptoFrame(level, offset, nullptr, data_length) {}
+
+QuicCryptoFrame::QuicCryptoFrame(EncryptionLevel level,
+ QuicStreamOffset offset,
+ QuicStringPiece data)
+ : QuicCryptoFrame(level, offset, data.data(), data.length()) {}
+
+QuicCryptoFrame::QuicCryptoFrame(EncryptionLevel level,
+ QuicStreamOffset offset,
+ const char* data_buffer,
+ QuicPacketLength data_length)
+ : level(level),
+ data_length(data_length),
+ data_buffer(data_buffer),
+ offset(offset) {}
+
+QuicCryptoFrame::~QuicCryptoFrame() {}
+
+std::ostream& operator<<(std::ostream& os,
+ const QuicCryptoFrame& stream_frame) {
+ os << "{ offset: " << stream_frame.offset
+ << ", length: " << stream_frame.data_length << " }\n";
+ return os;
+}
+
+} // namespace quic
diff --git a/quic/core/frames/quic_crypto_frame.h b/quic/core/frames/quic_crypto_frame.h
new file mode 100644
index 0000000..a3968fe
--- /dev/null
+++ b/quic/core/frames/quic_crypto_frame.h
@@ -0,0 +1,51 @@
+// Copyright (c) 2018 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.
+
+#ifndef QUICHE_QUIC_CORE_FRAMES_QUIC_CRYPTO_FRAME_H_
+#define QUICHE_QUIC_CORE_FRAMES_QUIC_CRYPTO_FRAME_H_
+
+#include <memory>
+#include <ostream>
+
+#include "net/third_party/quiche/src/quic/core/quic_buffer_allocator.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+
+namespace quic {
+
+struct QUIC_EXPORT_PRIVATE QuicCryptoFrame {
+ QuicCryptoFrame();
+ QuicCryptoFrame(EncryptionLevel level,
+ QuicStreamOffset offset,
+ QuicPacketLength data_length);
+ QuicCryptoFrame(EncryptionLevel level,
+ QuicStreamOffset offset,
+ QuicStringPiece data);
+ ~QuicCryptoFrame();
+
+ friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
+ const QuicCryptoFrame& s);
+
+ // When writing a crypto frame to a packet, the packet must be encrypted at
+ // |level|. When a crypto frame is read, the encryption level of the packet it
+ // was received in is put in |level|.
+ EncryptionLevel level;
+ QuicPacketLength data_length;
+ // When reading, |data_buffer| points to the data that was received in the
+ // frame. |data_buffer| is not used when writing.
+ const char* data_buffer;
+ QuicStreamOffset offset; // Location of this data in the stream.
+
+ QuicCryptoFrame(EncryptionLevel level,
+ QuicStreamOffset offset,
+ const char* data_buffer,
+ QuicPacketLength data_length);
+};
+static_assert(sizeof(QuicCryptoFrame) <= 64,
+ "Keep the QuicCryptoFrame size to a cacheline.");
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_FRAMES_QUIC_CRYPTO_FRAME_H_
diff --git a/quic/core/frames/quic_frame.cc b/quic/core/frames/quic_frame.cc
new file mode 100644
index 0000000..fbe54cd
--- /dev/null
+++ b/quic/core/frames/quic_frame.cc
@@ -0,0 +1,349 @@
+// 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_frame.h"
+
+#include "net/third_party/quiche/src/quic/core/quic_constants.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
+
+namespace quic {
+
+QuicFrame::QuicFrame() {}
+
+QuicFrame::QuicFrame(QuicPaddingFrame padding_frame)
+ : padding_frame(padding_frame) {}
+
+QuicFrame::QuicFrame(QuicStreamFrame stream_frame)
+ : stream_frame(stream_frame) {}
+
+QuicFrame::QuicFrame(QuicCryptoFrame* crypto_frame)
+ : type(CRYPTO_FRAME), crypto_frame(crypto_frame) {}
+
+QuicFrame::QuicFrame(QuicAckFrame* frame) : type(ACK_FRAME), ack_frame(frame) {}
+
+QuicFrame::QuicFrame(QuicMtuDiscoveryFrame frame)
+ : mtu_discovery_frame(frame) {}
+
+QuicFrame::QuicFrame(QuicStopWaitingFrame frame) : stop_waiting_frame(frame) {}
+
+QuicFrame::QuicFrame(QuicPingFrame frame) : ping_frame(frame) {}
+
+QuicFrame::QuicFrame(QuicRstStreamFrame* frame)
+ : type(RST_STREAM_FRAME), rst_stream_frame(frame) {}
+
+QuicFrame::QuicFrame(QuicConnectionCloseFrame* frame)
+ : type(CONNECTION_CLOSE_FRAME), connection_close_frame(frame) {}
+
+QuicFrame::QuicFrame(QuicGoAwayFrame* frame)
+ : type(GOAWAY_FRAME), goaway_frame(frame) {}
+
+QuicFrame::QuicFrame(QuicWindowUpdateFrame* frame)
+ : type(WINDOW_UPDATE_FRAME), window_update_frame(frame) {}
+
+QuicFrame::QuicFrame(QuicBlockedFrame* frame)
+ : type(BLOCKED_FRAME), blocked_frame(frame) {}
+
+QuicFrame::QuicFrame(QuicApplicationCloseFrame* frame)
+ : type(APPLICATION_CLOSE_FRAME), application_close_frame(frame) {}
+
+QuicFrame::QuicFrame(QuicNewConnectionIdFrame* frame)
+ : type(NEW_CONNECTION_ID_FRAME), new_connection_id_frame(frame) {}
+
+QuicFrame::QuicFrame(QuicRetireConnectionIdFrame* frame)
+ : type(RETIRE_CONNECTION_ID_FRAME), retire_connection_id_frame(frame) {}
+
+QuicFrame::QuicFrame(QuicMaxStreamIdFrame frame) : max_stream_id_frame(frame) {}
+
+QuicFrame::QuicFrame(QuicStreamIdBlockedFrame frame)
+ : stream_id_blocked_frame(frame) {}
+
+QuicFrame::QuicFrame(QuicPathResponseFrame* frame)
+ : type(PATH_RESPONSE_FRAME), path_response_frame(frame) {}
+
+QuicFrame::QuicFrame(QuicPathChallengeFrame* frame)
+ : type(PATH_CHALLENGE_FRAME), path_challenge_frame(frame) {}
+
+QuicFrame::QuicFrame(QuicStopSendingFrame* frame)
+ : type(STOP_SENDING_FRAME), stop_sending_frame(frame) {}
+
+QuicFrame::QuicFrame(QuicMessageFrame* frame)
+ : type(MESSAGE_FRAME), message_frame(frame) {}
+
+QuicFrame::QuicFrame(QuicNewTokenFrame* frame)
+ : type(NEW_TOKEN_FRAME), new_token_frame(frame) {}
+
+void DeleteFrames(QuicFrames* frames) {
+ for (QuicFrame& frame : *frames) {
+ DeleteFrame(&frame);
+ }
+ frames->clear();
+}
+
+void DeleteFrame(QuicFrame* frame) {
+ switch (frame->type) {
+ // Frames smaller than a pointer are inlined, so don't need to be deleted.
+ case PADDING_FRAME:
+ case MTU_DISCOVERY_FRAME:
+ case PING_FRAME:
+ case MAX_STREAM_ID_FRAME:
+ case STOP_WAITING_FRAME:
+ case STREAM_ID_BLOCKED_FRAME:
+ case STREAM_FRAME:
+ break;
+ case ACK_FRAME:
+ delete frame->ack_frame;
+ break;
+ case RST_STREAM_FRAME:
+ delete frame->rst_stream_frame;
+ break;
+ case CONNECTION_CLOSE_FRAME:
+ delete frame->connection_close_frame;
+ break;
+ case GOAWAY_FRAME:
+ delete frame->goaway_frame;
+ break;
+ case BLOCKED_FRAME:
+ delete frame->blocked_frame;
+ break;
+ case WINDOW_UPDATE_FRAME:
+ delete frame->window_update_frame;
+ break;
+ case PATH_CHALLENGE_FRAME:
+ delete frame->path_challenge_frame;
+ break;
+ case STOP_SENDING_FRAME:
+ delete frame->stop_sending_frame;
+ break;
+ case APPLICATION_CLOSE_FRAME:
+ delete frame->application_close_frame;
+ break;
+ case NEW_CONNECTION_ID_FRAME:
+ delete frame->new_connection_id_frame;
+ break;
+ case RETIRE_CONNECTION_ID_FRAME:
+ delete frame->retire_connection_id_frame;
+ break;
+ case PATH_RESPONSE_FRAME:
+ delete frame->path_response_frame;
+ break;
+ case MESSAGE_FRAME:
+ delete frame->message_frame;
+ break;
+ case CRYPTO_FRAME:
+ delete frame->crypto_frame;
+ break;
+ case NEW_TOKEN_FRAME:
+ delete frame->new_token_frame;
+ break;
+
+ case NUM_FRAME_TYPES:
+ DCHECK(false) << "Cannot delete type: " << frame->type;
+ }
+}
+
+void RemoveFramesForStream(QuicFrames* frames, QuicStreamId stream_id) {
+ auto it = frames->begin();
+ while (it != frames->end()) {
+ if (it->type != STREAM_FRAME || it->stream_frame.stream_id != stream_id) {
+ ++it;
+ continue;
+ }
+ it = frames->erase(it);
+ }
+}
+
+bool IsControlFrame(QuicFrameType type) {
+ switch (type) {
+ case RST_STREAM_FRAME:
+ case GOAWAY_FRAME:
+ case WINDOW_UPDATE_FRAME:
+ case BLOCKED_FRAME:
+ case STREAM_ID_BLOCKED_FRAME:
+ case MAX_STREAM_ID_FRAME:
+ case PING_FRAME:
+ case STOP_SENDING_FRAME:
+ return true;
+ default:
+ return false;
+ }
+}
+
+QuicControlFrameId GetControlFrameId(const QuicFrame& frame) {
+ switch (frame.type) {
+ case RST_STREAM_FRAME:
+ return frame.rst_stream_frame->control_frame_id;
+ case GOAWAY_FRAME:
+ return frame.goaway_frame->control_frame_id;
+ case WINDOW_UPDATE_FRAME:
+ return frame.window_update_frame->control_frame_id;
+ case BLOCKED_FRAME:
+ return frame.blocked_frame->control_frame_id;
+ case STREAM_ID_BLOCKED_FRAME:
+ return frame.stream_id_blocked_frame.control_frame_id;
+ case MAX_STREAM_ID_FRAME:
+ return frame.max_stream_id_frame.control_frame_id;
+ case PING_FRAME:
+ return frame.ping_frame.control_frame_id;
+ case STOP_SENDING_FRAME:
+ return frame.stop_sending_frame->control_frame_id;
+ default:
+ return kInvalidControlFrameId;
+ }
+}
+
+void SetControlFrameId(QuicControlFrameId control_frame_id, QuicFrame* frame) {
+ switch (frame->type) {
+ case RST_STREAM_FRAME:
+ frame->rst_stream_frame->control_frame_id = control_frame_id;
+ return;
+ case GOAWAY_FRAME:
+ frame->goaway_frame->control_frame_id = control_frame_id;
+ return;
+ case WINDOW_UPDATE_FRAME:
+ frame->window_update_frame->control_frame_id = control_frame_id;
+ return;
+ case BLOCKED_FRAME:
+ frame->blocked_frame->control_frame_id = control_frame_id;
+ return;
+ case PING_FRAME:
+ frame->ping_frame.control_frame_id = control_frame_id;
+ return;
+ case STREAM_ID_BLOCKED_FRAME:
+ frame->stream_id_blocked_frame.control_frame_id = control_frame_id;
+ return;
+ case MAX_STREAM_ID_FRAME:
+ frame->max_stream_id_frame.control_frame_id = control_frame_id;
+ return;
+ case STOP_SENDING_FRAME:
+ frame->stop_sending_frame->control_frame_id = control_frame_id;
+ return;
+ default:
+ QUIC_BUG
+ << "Try to set control frame id of a frame without control frame id";
+ }
+}
+
+QuicFrame CopyRetransmittableControlFrame(const QuicFrame& frame) {
+ QuicFrame copy;
+ switch (frame.type) {
+ case RST_STREAM_FRAME:
+ copy = QuicFrame(new QuicRstStreamFrame(*frame.rst_stream_frame));
+ break;
+ case GOAWAY_FRAME:
+ copy = QuicFrame(new QuicGoAwayFrame(*frame.goaway_frame));
+ break;
+ case WINDOW_UPDATE_FRAME:
+ copy = QuicFrame(new QuicWindowUpdateFrame(*frame.window_update_frame));
+ break;
+ case BLOCKED_FRAME:
+ copy = QuicFrame(new QuicBlockedFrame(*frame.blocked_frame));
+ break;
+ case PING_FRAME:
+ copy = QuicFrame(QuicPingFrame(frame.ping_frame.control_frame_id));
+ break;
+ case STOP_SENDING_FRAME:
+ copy = QuicFrame(new QuicStopSendingFrame(*frame.stop_sending_frame));
+ break;
+ case STREAM_ID_BLOCKED_FRAME:
+ copy = QuicFrame(QuicStreamIdBlockedFrame(frame.stream_id_blocked_frame));
+ break;
+ case MAX_STREAM_ID_FRAME:
+ copy = QuicFrame(QuicMaxStreamIdFrame(frame.max_stream_id_frame));
+ break;
+ default:
+ QUIC_BUG << "Try to copy a non-retransmittable control frame: " << frame;
+ copy = QuicFrame(QuicPingFrame(kInvalidControlFrameId));
+ break;
+ }
+ return copy;
+}
+
+std::ostream& operator<<(std::ostream& os, const QuicFrame& frame) {
+ switch (frame.type) {
+ case PADDING_FRAME: {
+ os << "type { PADDING_FRAME } " << frame.padding_frame;
+ break;
+ }
+ case RST_STREAM_FRAME: {
+ os << "type { RST_STREAM_FRAME } " << *(frame.rst_stream_frame);
+ break;
+ }
+ case CONNECTION_CLOSE_FRAME: {
+ os << "type { CONNECTION_CLOSE_FRAME } "
+ << *(frame.connection_close_frame);
+ break;
+ }
+ case GOAWAY_FRAME: {
+ os << "type { GOAWAY_FRAME } " << *(frame.goaway_frame);
+ break;
+ }
+ case WINDOW_UPDATE_FRAME: {
+ os << "type { WINDOW_UPDATE_FRAME } " << *(frame.window_update_frame);
+ break;
+ }
+ case BLOCKED_FRAME: {
+ os << "type { BLOCKED_FRAME } " << *(frame.blocked_frame);
+ break;
+ }
+ case STREAM_FRAME: {
+ os << "type { STREAM_FRAME } " << frame.stream_frame;
+ break;
+ }
+ case ACK_FRAME: {
+ os << "type { ACK_FRAME } " << *(frame.ack_frame);
+ break;
+ }
+ case STOP_WAITING_FRAME: {
+ os << "type { STOP_WAITING_FRAME } " << frame.stop_waiting_frame;
+ break;
+ }
+ case PING_FRAME: {
+ os << "type { PING_FRAME } " << frame.ping_frame;
+ break;
+ }
+ case MTU_DISCOVERY_FRAME: {
+ os << "type { MTU_DISCOVERY_FRAME } ";
+ break;
+ }
+ case APPLICATION_CLOSE_FRAME:
+ os << "type { APPLICATION_CLOSE } " << *(frame.application_close_frame);
+ break;
+ case NEW_CONNECTION_ID_FRAME:
+ os << "type { NEW_CONNECTION_ID } " << *(frame.new_connection_id_frame);
+ break;
+ case RETIRE_CONNECTION_ID_FRAME:
+ os << "type { RETIRE_CONNECTION_ID } "
+ << *(frame.retire_connection_id_frame);
+ break;
+ case MAX_STREAM_ID_FRAME:
+ os << "type { MAX_STREAM_ID } " << frame.max_stream_id_frame;
+ break;
+ case STREAM_ID_BLOCKED_FRAME:
+ os << "type { STREAM_ID_BLOCKED } " << frame.stream_id_blocked_frame;
+ break;
+ case PATH_RESPONSE_FRAME:
+ os << "type { PATH_RESPONSE } " << *(frame.path_response_frame);
+ break;
+ case PATH_CHALLENGE_FRAME:
+ os << "type { PATH_CHALLENGE } " << *(frame.path_challenge_frame);
+ break;
+ case STOP_SENDING_FRAME:
+ os << "type { STOP_SENDING } " << *(frame.stop_sending_frame);
+ break;
+ case MESSAGE_FRAME:
+ os << "type { MESSAGE_FRAME }" << *(frame.message_frame);
+ break;
+ case NEW_TOKEN_FRAME:
+ os << "type { NEW_TOKEN_FRAME }" << *(frame.new_token_frame);
+ break;
+ default: {
+ QUIC_LOG(ERROR) << "Unknown frame type: " << frame.type;
+ break;
+ }
+ }
+ return os;
+}
+
+} // namespace quic
diff --git a/quic/core/frames/quic_frame.h b/quic/core/frames/quic_frame.h
new file mode 100644
index 0000000..d753862
--- /dev/null
+++ b/quic/core/frames/quic_frame.h
@@ -0,0 +1,148 @@
+// 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.
+
+#ifndef QUICHE_QUIC_CORE_FRAMES_QUIC_FRAME_H_
+#define QUICHE_QUIC_CORE_FRAMES_QUIC_FRAME_H_
+
+#include <ostream>
+#include <vector>
+
+#include "net/third_party/quiche/src/quic/core/frames/quic_ack_frame.h"
+#include "net/third_party/quiche/src/quic/core/frames/quic_application_close_frame.h"
+#include "net/third_party/quiche/src/quic/core/frames/quic_blocked_frame.h"
+#include "net/third_party/quiche/src/quic/core/frames/quic_connection_close_frame.h"
+#include "net/third_party/quiche/src/quic/core/frames/quic_crypto_frame.h"
+#include "net/third_party/quiche/src/quic/core/frames/quic_goaway_frame.h"
+#include "net/third_party/quiche/src/quic/core/frames/quic_max_stream_id_frame.h"
+#include "net/third_party/quiche/src/quic/core/frames/quic_message_frame.h"
+#include "net/third_party/quiche/src/quic/core/frames/quic_mtu_discovery_frame.h"
+#include "net/third_party/quiche/src/quic/core/frames/quic_new_connection_id_frame.h"
+#include "net/third_party/quiche/src/quic/core/frames/quic_new_token_frame.h"
+#include "net/third_party/quiche/src/quic/core/frames/quic_padding_frame.h"
+#include "net/third_party/quiche/src/quic/core/frames/quic_path_challenge_frame.h"
+#include "net/third_party/quiche/src/quic/core/frames/quic_path_response_frame.h"
+#include "net/third_party/quiche/src/quic/core/frames/quic_ping_frame.h"
+#include "net/third_party/quiche/src/quic/core/frames/quic_retire_connection_id_frame.h"
+#include "net/third_party/quiche/src/quic/core/frames/quic_rst_stream_frame.h"
+#include "net/third_party/quiche/src/quic/core/frames/quic_stop_sending_frame.h"
+#include "net/third_party/quiche/src/quic/core/frames/quic_stop_waiting_frame.h"
+#include "net/third_party/quiche/src/quic/core/frames/quic_stream_frame.h"
+#include "net/third_party/quiche/src/quic/core/frames/quic_stream_id_blocked_frame.h"
+#include "net/third_party/quiche/src/quic/core/frames/quic_window_update_frame.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+
+namespace quic {
+
+struct QUIC_EXPORT_PRIVATE QuicFrame {
+ QuicFrame();
+ // Please keep the constructors in the same order as the union below.
+ explicit QuicFrame(QuicPaddingFrame padding_frame);
+ explicit QuicFrame(QuicMtuDiscoveryFrame frame);
+ explicit QuicFrame(QuicPingFrame frame);
+ explicit QuicFrame(QuicMaxStreamIdFrame frame);
+ explicit QuicFrame(QuicStopWaitingFrame frame);
+ explicit QuicFrame(QuicStreamIdBlockedFrame frame);
+ explicit QuicFrame(QuicStreamFrame stream_frame);
+
+ explicit QuicFrame(QuicAckFrame* frame);
+ explicit QuicFrame(QuicRstStreamFrame* frame);
+ explicit QuicFrame(QuicConnectionCloseFrame* frame);
+ explicit QuicFrame(QuicGoAwayFrame* frame);
+ explicit QuicFrame(QuicWindowUpdateFrame* frame);
+ explicit QuicFrame(QuicBlockedFrame* frame);
+ explicit QuicFrame(QuicApplicationCloseFrame* frame);
+ explicit QuicFrame(QuicNewConnectionIdFrame* frame);
+ explicit QuicFrame(QuicRetireConnectionIdFrame* frame);
+ explicit QuicFrame(QuicNewTokenFrame* frame);
+ explicit QuicFrame(QuicPathResponseFrame* frame);
+ explicit QuicFrame(QuicPathChallengeFrame* frame);
+ explicit QuicFrame(QuicStopSendingFrame* frame);
+ explicit QuicFrame(QuicMessageFrame* message_frame);
+ explicit QuicFrame(QuicCryptoFrame* crypto_frame);
+
+ QUIC_EXPORT_PRIVATE friend std::ostream& operator<<(std::ostream& os,
+ const QuicFrame& frame);
+
+ union {
+ // Inlined frames.
+ // Overlapping inlined frames have a |type| field at the same 0 offset as
+ // QuicFrame does for out of line frames below, allowing use of the
+ // remaining 7 bytes after offset for frame-type specific fields.
+ QuicPaddingFrame padding_frame;
+ QuicMtuDiscoveryFrame mtu_discovery_frame;
+ QuicPingFrame ping_frame;
+ QuicMaxStreamIdFrame max_stream_id_frame;
+ QuicStopWaitingFrame stop_waiting_frame;
+ QuicStreamIdBlockedFrame stream_id_blocked_frame;
+ QuicStreamFrame stream_frame;
+
+ // Out of line frames.
+ struct {
+ QuicFrameType type;
+
+ // TODO(wub): These frames can also be inlined without increasing the size
+ // of QuicFrame: QuicRstStreamFrame, QuicWindowUpdateFrame,
+ // QuicBlockedFrame, QuicPathResponseFrame, QuicPathChallengeFrame and
+ // QuicStopSendingFrame.
+ union {
+ QuicAckFrame* ack_frame;
+ QuicRstStreamFrame* rst_stream_frame;
+ QuicConnectionCloseFrame* connection_close_frame;
+ QuicGoAwayFrame* goaway_frame;
+ QuicWindowUpdateFrame* window_update_frame;
+ QuicBlockedFrame* blocked_frame;
+ QuicApplicationCloseFrame* application_close_frame;
+ QuicNewConnectionIdFrame* new_connection_id_frame;
+ QuicRetireConnectionIdFrame* retire_connection_id_frame;
+ QuicPathResponseFrame* path_response_frame;
+ QuicPathChallengeFrame* path_challenge_frame;
+ QuicStopSendingFrame* stop_sending_frame;
+ QuicMessageFrame* message_frame;
+ QuicCryptoFrame* crypto_frame;
+ QuicNewTokenFrame* new_token_frame;
+ };
+ };
+ };
+};
+
+static_assert(sizeof(QuicFrame) <= 24,
+ "Frames larger than 24 bytes should be referenced by pointer.");
+static_assert(offsetof(QuicStreamFrame, type) == offsetof(QuicFrame, type),
+ "Offset of |type| must match in QuicFrame and QuicStreamFrame");
+
+// A inline size of 1 is chosen to optimize the typical use case of
+// 1-stream-frame in QuicTransmissionInfo.retransmittable_frames.
+typedef QuicInlinedVector<QuicFrame, 1> QuicFrames;
+
+// Deletes all the sub-frames contained in |frames|.
+QUIC_EXPORT_PRIVATE void DeleteFrames(QuicFrames* frames);
+
+// Delete the sub-frame contained in |frame|.
+QUIC_EXPORT_PRIVATE void DeleteFrame(QuicFrame* frame);
+
+// Deletes all the QuicStreamFrames for the specified |stream_id|.
+QUIC_EXPORT_PRIVATE void RemoveFramesForStream(QuicFrames* frames,
+ QuicStreamId stream_id);
+
+// Returns true if |type| is a retransmittable control frame.
+QUIC_EXPORT_PRIVATE bool IsControlFrame(QuicFrameType type);
+
+// Returns control_frame_id of |frame|. Returns kInvalidControlFrameId if
+// |frame| does not have a valid control_frame_id.
+QUIC_EXPORT_PRIVATE QuicControlFrameId
+GetControlFrameId(const QuicFrame& frame);
+
+// Sets control_frame_id of |frame| to |control_frame_id|.
+QUIC_EXPORT_PRIVATE void SetControlFrameId(QuicControlFrameId control_frame_id,
+ QuicFrame* frame);
+
+// Returns a copy of |frame|.
+QUIC_EXPORT_PRIVATE QuicFrame
+CopyRetransmittableControlFrame(const QuicFrame& frame);
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_FRAMES_QUIC_FRAME_H_
diff --git a/quic/core/frames/quic_frames_test.cc b/quic/core/frames/quic_frames_test.cc
new file mode 100644
index 0000000..986b3c5
--- /dev/null
+++ b/quic/core/frames/quic_frames_test.cc
@@ -0,0 +1,638 @@
+// 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/frames/quic_blocked_frame.h"
+#include "net/third_party/quiche/src/quic/core/frames/quic_connection_close_frame.h"
+#include "net/third_party/quiche/src/quic/core/frames/quic_frame.h"
+#include "net/third_party/quiche/src/quic/core/frames/quic_goaway_frame.h"
+#include "net/third_party/quiche/src/quic/core/frames/quic_mtu_discovery_frame.h"
+#include "net/third_party/quiche/src/quic/core/frames/quic_padding_frame.h"
+#include "net/third_party/quiche/src/quic/core/frames/quic_ping_frame.h"
+#include "net/third_party/quiche/src/quic/core/frames/quic_rst_stream_frame.h"
+#include "net/third_party/quiche/src/quic/core/frames/quic_stop_waiting_frame.h"
+#include "net/third_party/quiche/src/quic/core/frames/quic_stream_frame.h"
+#include "net/third_party/quiche/src/quic/core/frames/quic_window_update_frame.h"
+#include "net/third_party/quiche/src/quic/core/quic_interval.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+
+namespace quic {
+namespace test {
+namespace {
+
+class QuicFramesTest : public QuicTest {};
+
+TEST_F(QuicFramesTest, AckFrameToString) {
+ QuicAckFrame frame;
+ frame.largest_acked = QuicPacketNumber(5);
+ frame.ack_delay_time = QuicTime::Delta::FromMicroseconds(3);
+ frame.packets.Add(QuicPacketNumber(4));
+ frame.packets.Add(QuicPacketNumber(5));
+ frame.received_packet_times = {
+ {QuicPacketNumber(6),
+ QuicTime::Zero() + QuicTime::Delta::FromMicroseconds(7)}};
+ std::ostringstream stream;
+ stream << frame;
+ EXPECT_EQ(
+ "{ largest_acked: 5, ack_delay_time: 3, packets: [ 4 5 ], "
+ "received_packets: [ 6 at 7 ], ecn_counters_populated: 0 }\n",
+ stream.str());
+ QuicFrame quic_frame(&frame);
+ EXPECT_FALSE(IsControlFrame(quic_frame.type));
+}
+
+TEST_F(QuicFramesTest, BigAckFrameToString) {
+ QuicAckFrame frame;
+ frame.largest_acked = QuicPacketNumber(500);
+ frame.ack_delay_time = QuicTime::Delta::FromMicroseconds(3);
+ frame.packets.AddRange(QuicPacketNumber(4), QuicPacketNumber(501));
+ frame.received_packet_times = {
+ {QuicPacketNumber(500),
+ QuicTime::Zero() + QuicTime::Delta::FromMicroseconds(7)}};
+ std::ostringstream stream;
+ stream << frame;
+ EXPECT_EQ(
+ "{ largest_acked: 500, ack_delay_time: 3, packets: [ 4...500 ], "
+ "received_packets: [ 500 at 7 ], ecn_counters_populated: 0 }\n",
+ stream.str());
+ QuicFrame quic_frame(&frame);
+ EXPECT_FALSE(IsControlFrame(quic_frame.type));
+}
+
+TEST_F(QuicFramesTest, PaddingFrameToString) {
+ QuicPaddingFrame frame;
+ frame.num_padding_bytes = 1;
+ std::ostringstream stream;
+ stream << frame;
+ EXPECT_EQ("{ num_padding_bytes: 1 }\n", stream.str());
+ QuicFrame quic_frame(frame);
+ EXPECT_FALSE(IsControlFrame(quic_frame.type));
+}
+
+TEST_F(QuicFramesTest, RstStreamFrameToString) {
+ QuicRstStreamFrame rst_stream;
+ QuicFrame frame(&rst_stream);
+ SetControlFrameId(1, &frame);
+ EXPECT_EQ(1u, GetControlFrameId(frame));
+ rst_stream.stream_id = 1;
+ rst_stream.error_code = QUIC_STREAM_CANCELLED;
+ std::ostringstream stream;
+ stream << rst_stream;
+ EXPECT_EQ("{ control_frame_id: 1, stream_id: 1, error_code: 6 }\n",
+ stream.str());
+ EXPECT_TRUE(IsControlFrame(frame.type));
+}
+
+TEST_F(QuicFramesTest, StopSendingFrameToString) {
+ QuicStopSendingFrame stop_sending;
+ QuicFrame frame(&stop_sending);
+ SetControlFrameId(1, &frame);
+ EXPECT_EQ(1u, GetControlFrameId(frame));
+ stop_sending.stream_id = 321;
+ stop_sending.application_error_code = QUIC_STREAM_CANCELLED;
+ std::ostringstream stream;
+ stream << stop_sending;
+ EXPECT_EQ(
+ "{ control_frame_id: 1, stream_id: 321, application_error_code: 6 }\n",
+ stream.str());
+ EXPECT_TRUE(IsControlFrame(frame.type));
+}
+
+TEST_F(QuicFramesTest, StreamIdBlockedFrameToString) {
+ QuicStreamIdBlockedFrame stream_id_blocked;
+ QuicFrame frame(stream_id_blocked);
+ SetControlFrameId(1, &frame);
+ EXPECT_EQ(1u, GetControlFrameId(frame));
+ // QuicStreamIdBlocked is copied into a QuicFrame (as opposed to putting a
+ // pointer to it into QuicFrame) so need to work with the copy in |frame| and
+ // not the original one, stream_id_blocked.
+ frame.stream_id_blocked_frame.stream_id = 321;
+ std::ostringstream stream;
+ stream << frame.stream_id_blocked_frame;
+ EXPECT_EQ("{ control_frame_id: 1, stream id: 321 }\n", stream.str());
+ EXPECT_TRUE(IsControlFrame(frame.type));
+}
+
+TEST_F(QuicFramesTest, MaxStreamIdFrameToString) {
+ QuicMaxStreamIdFrame max_stream_id;
+ QuicFrame frame(max_stream_id);
+ SetControlFrameId(1, &frame);
+ EXPECT_EQ(1u, GetControlFrameId(frame));
+ // QuicMaxStreamId is copied into a QuicFrame (as opposed to putting a
+ // pointer to it into QuicFrame) so need to work with the copy in |frame| and
+ // not the original one, max_stream_id.
+ frame.max_stream_id_frame.max_stream_id = 321;
+ std::ostringstream stream;
+ stream << frame.max_stream_id_frame;
+ EXPECT_EQ("{ control_frame_id: 1, stream_id: 321 }\n", stream.str());
+ EXPECT_TRUE(IsControlFrame(frame.type));
+}
+
+TEST_F(QuicFramesTest, ConnectionCloseFrameToString) {
+ QuicConnectionCloseFrame frame;
+ frame.error_code = QUIC_NETWORK_IDLE_TIMEOUT;
+ frame.error_details = "No recent network activity.";
+ std::ostringstream stream;
+ stream << frame;
+ EXPECT_EQ(
+ "{ error_code: 25, error_details: 'No recent network activity.', "
+ "frame_type: 0"
+ "}\n",
+ stream.str());
+ QuicFrame quic_frame(&frame);
+ EXPECT_FALSE(IsControlFrame(quic_frame.type));
+}
+
+TEST_F(QuicFramesTest, GoAwayFrameToString) {
+ QuicGoAwayFrame goaway_frame;
+ QuicFrame frame(&goaway_frame);
+ SetControlFrameId(2, &frame);
+ EXPECT_EQ(2u, GetControlFrameId(frame));
+ goaway_frame.error_code = QUIC_NETWORK_IDLE_TIMEOUT;
+ goaway_frame.last_good_stream_id = 2;
+ goaway_frame.reason_phrase = "Reason";
+ std::ostringstream stream;
+ stream << goaway_frame;
+ EXPECT_EQ(
+ "{ control_frame_id: 2, error_code: 25, last_good_stream_id: 2, "
+ "reason_phrase: "
+ "'Reason' }\n",
+ stream.str());
+ EXPECT_TRUE(IsControlFrame(frame.type));
+}
+
+TEST_F(QuicFramesTest, WindowUpdateFrameToString) {
+ QuicWindowUpdateFrame window_update;
+ QuicFrame frame(&window_update);
+ SetControlFrameId(3, &frame);
+ EXPECT_EQ(3u, GetControlFrameId(frame));
+ std::ostringstream stream;
+ window_update.stream_id = 1;
+ window_update.byte_offset = 2;
+ stream << window_update;
+ EXPECT_EQ("{ control_frame_id: 3, stream_id: 1, byte_offset: 2 }\n",
+ stream.str());
+ EXPECT_TRUE(IsControlFrame(frame.type));
+}
+
+TEST_F(QuicFramesTest, BlockedFrameToString) {
+ QuicBlockedFrame blocked;
+ QuicFrame frame(&blocked);
+ SetControlFrameId(4, &frame);
+ EXPECT_EQ(4u, GetControlFrameId(frame));
+ blocked.stream_id = 1;
+ std::ostringstream stream;
+ stream << blocked;
+ EXPECT_EQ("{ control_frame_id: 4, stream_id: 1 }\n", stream.str());
+ EXPECT_TRUE(IsControlFrame(frame.type));
+}
+
+TEST_F(QuicFramesTest, PingFrameToString) {
+ QuicPingFrame ping;
+ QuicFrame frame(ping);
+ SetControlFrameId(5, &frame);
+ EXPECT_EQ(5u, GetControlFrameId(frame));
+ std::ostringstream stream;
+ stream << frame.ping_frame;
+ EXPECT_EQ("{ control_frame_id: 5 }\n", stream.str());
+ EXPECT_TRUE(IsControlFrame(frame.type));
+}
+
+TEST_F(QuicFramesTest, StreamFrameToString) {
+ QuicStreamFrame frame;
+ frame.stream_id = 1;
+ frame.fin = false;
+ frame.offset = 2;
+ frame.data_length = 3;
+ std::ostringstream stream;
+ stream << frame;
+ EXPECT_EQ("{ stream_id: 1, fin: 0, offset: 2, length: 3 }\n", stream.str());
+ EXPECT_FALSE(IsControlFrame(frame.type));
+}
+
+TEST_F(QuicFramesTest, StopWaitingFrameToString) {
+ QuicStopWaitingFrame frame;
+ frame.least_unacked = QuicPacketNumber(2);
+ std::ostringstream stream;
+ stream << frame;
+ EXPECT_EQ("{ least_unacked: 2 }\n", stream.str());
+ QuicFrame quic_frame(frame);
+ EXPECT_FALSE(IsControlFrame(quic_frame.type));
+}
+
+TEST_F(QuicFramesTest, IsAwaitingPacket) {
+ QuicAckFrame ack_frame1;
+ ack_frame1.largest_acked = QuicPacketNumber(10u);
+ ack_frame1.packets.AddRange(QuicPacketNumber(1), QuicPacketNumber(11));
+ EXPECT_TRUE(
+ IsAwaitingPacket(ack_frame1, QuicPacketNumber(11u), QuicPacketNumber()));
+ EXPECT_FALSE(
+ IsAwaitingPacket(ack_frame1, QuicPacketNumber(1u), QuicPacketNumber()));
+
+ ack_frame1.packets.Add(QuicPacketNumber(12));
+ EXPECT_TRUE(
+ IsAwaitingPacket(ack_frame1, QuicPacketNumber(11u), QuicPacketNumber()));
+
+ QuicAckFrame ack_frame2;
+ ack_frame2.largest_acked = QuicPacketNumber(100u);
+ ack_frame2.packets.AddRange(QuicPacketNumber(21), QuicPacketNumber(100));
+ EXPECT_FALSE(IsAwaitingPacket(ack_frame2, QuicPacketNumber(11u),
+ QuicPacketNumber(20u)));
+ EXPECT_FALSE(IsAwaitingPacket(ack_frame2, QuicPacketNumber(80u),
+ QuicPacketNumber(20u)));
+ EXPECT_TRUE(IsAwaitingPacket(ack_frame2, QuicPacketNumber(101u),
+ QuicPacketNumber(20u)));
+
+ ack_frame2.packets.AddRange(QuicPacketNumber(102), QuicPacketNumber(200));
+ EXPECT_TRUE(IsAwaitingPacket(ack_frame2, QuicPacketNumber(101u),
+ QuicPacketNumber(20u)));
+}
+
+TEST_F(QuicFramesTest, AddPacket) {
+ QuicAckFrame ack_frame1;
+ ack_frame1.packets.Add(QuicPacketNumber(1));
+ ack_frame1.packets.Add(QuicPacketNumber(99));
+
+ EXPECT_EQ(2u, ack_frame1.packets.NumIntervals());
+ EXPECT_EQ(QuicPacketNumber(1u), ack_frame1.packets.Min());
+ EXPECT_EQ(QuicPacketNumber(99u), ack_frame1.packets.Max());
+
+ std::vector<QuicInterval<QuicPacketNumber>> expected_intervals;
+ expected_intervals.emplace_back(
+ QuicInterval<QuicPacketNumber>(QuicPacketNumber(1), QuicPacketNumber(2)));
+ expected_intervals.emplace_back(QuicInterval<QuicPacketNumber>(
+ QuicPacketNumber(99), QuicPacketNumber(100)));
+
+ const std::vector<QuicInterval<QuicPacketNumber>> actual_intervals(
+ ack_frame1.packets.begin(), ack_frame1.packets.end());
+
+ EXPECT_EQ(expected_intervals, actual_intervals);
+
+ ack_frame1.packets.Add(QuicPacketNumber(20));
+ const std::vector<QuicInterval<QuicPacketNumber>> actual_intervals2(
+ ack_frame1.packets.begin(), ack_frame1.packets.end());
+
+ std::vector<QuicInterval<QuicPacketNumber>> expected_intervals2;
+ expected_intervals2.emplace_back(
+ QuicInterval<QuicPacketNumber>(QuicPacketNumber(1), QuicPacketNumber(2)));
+ expected_intervals2.emplace_back(QuicInterval<QuicPacketNumber>(
+ QuicPacketNumber(20), QuicPacketNumber(21)));
+ expected_intervals2.emplace_back(QuicInterval<QuicPacketNumber>(
+ QuicPacketNumber(99), QuicPacketNumber(100)));
+
+ EXPECT_EQ(3u, ack_frame1.packets.NumIntervals());
+ EXPECT_EQ(expected_intervals2, actual_intervals2);
+
+ ack_frame1.packets.Add(QuicPacketNumber(19));
+ ack_frame1.packets.Add(QuicPacketNumber(21));
+
+ const std::vector<QuicInterval<QuicPacketNumber>> actual_intervals3(
+ ack_frame1.packets.begin(), ack_frame1.packets.end());
+
+ std::vector<QuicInterval<QuicPacketNumber>> expected_intervals3;
+ expected_intervals3.emplace_back(
+ QuicInterval<QuicPacketNumber>(QuicPacketNumber(1), QuicPacketNumber(2)));
+ expected_intervals3.emplace_back(QuicInterval<QuicPacketNumber>(
+ QuicPacketNumber(19), QuicPacketNumber(22)));
+ expected_intervals3.emplace_back(QuicInterval<QuicPacketNumber>(
+ QuicPacketNumber(99), QuicPacketNumber(100)));
+
+ EXPECT_EQ(expected_intervals3, actual_intervals3);
+
+ ack_frame1.packets.Add(QuicPacketNumber(20));
+
+ const std::vector<QuicInterval<QuicPacketNumber>> actual_intervals4(
+ ack_frame1.packets.begin(), ack_frame1.packets.end());
+
+ EXPECT_EQ(expected_intervals3, actual_intervals4);
+
+ QuicAckFrame ack_frame2;
+ ack_frame2.packets.Add(QuicPacketNumber(20));
+ ack_frame2.packets.Add(QuicPacketNumber(40));
+ ack_frame2.packets.Add(QuicPacketNumber(60));
+ ack_frame2.packets.Add(QuicPacketNumber(10));
+ ack_frame2.packets.Add(QuicPacketNumber(80));
+
+ const std::vector<QuicInterval<QuicPacketNumber>> actual_intervals5(
+ ack_frame2.packets.begin(), ack_frame2.packets.end());
+
+ std::vector<QuicInterval<QuicPacketNumber>> expected_intervals5;
+ expected_intervals5.emplace_back(QuicInterval<QuicPacketNumber>(
+ QuicPacketNumber(10), QuicPacketNumber(11)));
+ expected_intervals5.emplace_back(QuicInterval<QuicPacketNumber>(
+ QuicPacketNumber(20), QuicPacketNumber(21)));
+ expected_intervals5.emplace_back(QuicInterval<QuicPacketNumber>(
+ QuicPacketNumber(40), QuicPacketNumber(41)));
+ expected_intervals5.emplace_back(QuicInterval<QuicPacketNumber>(
+ QuicPacketNumber(60), QuicPacketNumber(61)));
+ expected_intervals5.emplace_back(QuicInterval<QuicPacketNumber>(
+ QuicPacketNumber(80), QuicPacketNumber(81)));
+
+ EXPECT_EQ(expected_intervals5, actual_intervals5);
+}
+
+TEST_F(QuicFramesTest, AddInterval) {
+ QuicAckFrame ack_frame1;
+ ack_frame1.packets.AddRange(QuicPacketNumber(1), QuicPacketNumber(10));
+ ack_frame1.packets.AddRange(QuicPacketNumber(50), QuicPacketNumber(100));
+
+ EXPECT_EQ(2u, ack_frame1.packets.NumIntervals());
+ EXPECT_EQ(QuicPacketNumber(1u), ack_frame1.packets.Min());
+ EXPECT_EQ(QuicPacketNumber(99u), ack_frame1.packets.Max());
+
+ std::vector<QuicInterval<QuicPacketNumber>> expected_intervals;
+ expected_intervals.emplace_back(QuicInterval<QuicPacketNumber>(
+ QuicPacketNumber(1), QuicPacketNumber(10)));
+ expected_intervals.emplace_back(QuicInterval<QuicPacketNumber>(
+ QuicPacketNumber(50), QuicPacketNumber(100)));
+
+ const std::vector<QuicInterval<QuicPacketNumber>> actual_intervals(
+ ack_frame1.packets.begin(), ack_frame1.packets.end());
+
+ EXPECT_EQ(expected_intervals, actual_intervals);
+
+ // Ensure adding a range within the existing ranges fails.
+ EXPECT_QUIC_BUG(
+ ack_frame1.packets.AddRange(QuicPacketNumber(20), QuicPacketNumber(30)),
+ "");
+
+ const std::vector<QuicInterval<QuicPacketNumber>> actual_intervals2(
+ ack_frame1.packets.begin(), ack_frame1.packets.end());
+
+ std::vector<QuicInterval<QuicPacketNumber>> expected_intervals2;
+ expected_intervals2.emplace_back(QuicInterval<QuicPacketNumber>(
+ QuicPacketNumber(1), QuicPacketNumber(10)));
+ expected_intervals2.emplace_back(QuicInterval<QuicPacketNumber>(
+ QuicPacketNumber(50), QuicPacketNumber(100)));
+
+ EXPECT_EQ(expected_intervals2.size(), ack_frame1.packets.NumIntervals());
+ EXPECT_EQ(expected_intervals2, actual_intervals2);
+
+ // Add ranges at both ends.
+ QuicAckFrame ack_frame2;
+ ack_frame2.packets.AddRange(QuicPacketNumber(20), QuicPacketNumber(25));
+ ack_frame2.packets.AddRange(QuicPacketNumber(40), QuicPacketNumber(45));
+ ack_frame2.packets.AddRange(QuicPacketNumber(60), QuicPacketNumber(65));
+ ack_frame2.packets.AddRange(QuicPacketNumber(10), QuicPacketNumber(15));
+ ack_frame2.packets.AddRange(QuicPacketNumber(80), QuicPacketNumber(85));
+
+ const std::vector<QuicInterval<QuicPacketNumber>> actual_intervals8(
+ ack_frame2.packets.begin(), ack_frame2.packets.end());
+
+ std::vector<QuicInterval<QuicPacketNumber>> expected_intervals8;
+ expected_intervals8.emplace_back(QuicInterval<QuicPacketNumber>(
+ QuicPacketNumber(10), QuicPacketNumber(15)));
+ expected_intervals8.emplace_back(QuicInterval<QuicPacketNumber>(
+ QuicPacketNumber(20), QuicPacketNumber(25)));
+ expected_intervals8.emplace_back(QuicInterval<QuicPacketNumber>(
+ QuicPacketNumber(40), QuicPacketNumber(45)));
+ expected_intervals8.emplace_back(QuicInterval<QuicPacketNumber>(
+ QuicPacketNumber(60), QuicPacketNumber(65)));
+ expected_intervals8.emplace_back(QuicInterval<QuicPacketNumber>(
+ QuicPacketNumber(80), QuicPacketNumber(85)));
+
+ EXPECT_EQ(expected_intervals8, actual_intervals8);
+}
+
+TEST_F(QuicFramesTest, AddAdjacentForward) {
+ QuicAckFrame ack_frame1;
+ ack_frame1.packets.Add(QuicPacketNumber(49));
+ ack_frame1.packets.AddRange(QuicPacketNumber(50), QuicPacketNumber(60));
+ ack_frame1.packets.AddRange(QuicPacketNumber(60), QuicPacketNumber(70));
+ ack_frame1.packets.AddRange(QuicPacketNumber(70), QuicPacketNumber(100));
+
+ std::vector<QuicInterval<QuicPacketNumber>> expected_intervals;
+ expected_intervals.emplace_back(QuicInterval<QuicPacketNumber>(
+ QuicPacketNumber(49), QuicPacketNumber(100)));
+
+ const std::vector<QuicInterval<QuicPacketNumber>> actual_intervals(
+ ack_frame1.packets.begin(), ack_frame1.packets.end());
+
+ EXPECT_EQ(expected_intervals, actual_intervals);
+}
+
+TEST_F(QuicFramesTest, AddAdjacentReverse) {
+ QuicAckFrame ack_frame1;
+ ack_frame1.packets.AddRange(QuicPacketNumber(70), QuicPacketNumber(100));
+ ack_frame1.packets.AddRange(QuicPacketNumber(60), QuicPacketNumber(70));
+ ack_frame1.packets.AddRange(QuicPacketNumber(50), QuicPacketNumber(60));
+ ack_frame1.packets.Add(QuicPacketNumber(49));
+
+ std::vector<QuicInterval<QuicPacketNumber>> expected_intervals;
+ expected_intervals.emplace_back(QuicInterval<QuicPacketNumber>(
+ QuicPacketNumber(49), QuicPacketNumber(100)));
+
+ const std::vector<QuicInterval<QuicPacketNumber>> actual_intervals(
+ ack_frame1.packets.begin(), ack_frame1.packets.end());
+
+ EXPECT_EQ(expected_intervals, actual_intervals);
+}
+
+TEST_F(QuicFramesTest, RemoveSmallestInterval) {
+ QuicAckFrame ack_frame1;
+ ack_frame1.largest_acked = QuicPacketNumber(100u);
+ ack_frame1.packets.AddRange(QuicPacketNumber(51), QuicPacketNumber(60));
+ ack_frame1.packets.AddRange(QuicPacketNumber(71), QuicPacketNumber(80));
+ ack_frame1.packets.AddRange(QuicPacketNumber(91), QuicPacketNumber(100));
+ ack_frame1.packets.RemoveSmallestInterval();
+ EXPECT_EQ(2u, ack_frame1.packets.NumIntervals());
+ EXPECT_EQ(QuicPacketNumber(71u), ack_frame1.packets.Min());
+ EXPECT_EQ(QuicPacketNumber(99u), ack_frame1.packets.Max());
+
+ ack_frame1.packets.RemoveSmallestInterval();
+ EXPECT_EQ(1u, ack_frame1.packets.NumIntervals());
+ EXPECT_EQ(QuicPacketNumber(91u), ack_frame1.packets.Min());
+ EXPECT_EQ(QuicPacketNumber(99u), ack_frame1.packets.Max());
+}
+
+class PacketNumberQueueTest : public QuicTest {};
+
+// Tests that a queue contains the expected data after calls to Add().
+TEST_F(PacketNumberQueueTest, AddRange) {
+ PacketNumberQueue queue;
+ queue.AddRange(QuicPacketNumber(1), QuicPacketNumber(51));
+ queue.Add(QuicPacketNumber(53));
+
+ EXPECT_FALSE(queue.Contains(QuicPacketNumber()));
+ for (int i = 1; i < 51; ++i) {
+ EXPECT_TRUE(queue.Contains(QuicPacketNumber(i)));
+ }
+ EXPECT_FALSE(queue.Contains(QuicPacketNumber(51)));
+ EXPECT_FALSE(queue.Contains(QuicPacketNumber(52)));
+ EXPECT_TRUE(queue.Contains(QuicPacketNumber(53)));
+ EXPECT_FALSE(queue.Contains(QuicPacketNumber(54)));
+ EXPECT_EQ(51u, queue.NumPacketsSlow());
+ EXPECT_EQ(QuicPacketNumber(1u), queue.Min());
+ EXPECT_EQ(QuicPacketNumber(53u), queue.Max());
+
+ queue.Add(QuicPacketNumber(70));
+ EXPECT_EQ(QuicPacketNumber(70u), queue.Max());
+}
+
+// Tests Contains function
+TEST_F(PacketNumberQueueTest, Contains) {
+ PacketNumberQueue queue;
+ EXPECT_FALSE(queue.Contains(QuicPacketNumber()));
+ queue.AddRange(QuicPacketNumber(5), QuicPacketNumber(10));
+ queue.Add(QuicPacketNumber(20));
+
+ for (int i = 1; i < 5; ++i) {
+ EXPECT_FALSE(queue.Contains(QuicPacketNumber(i)));
+ }
+
+ for (int i = 5; i < 10; ++i) {
+ EXPECT_TRUE(queue.Contains(QuicPacketNumber(i)));
+ }
+ for (int i = 10; i < 20; ++i) {
+ EXPECT_FALSE(queue.Contains(QuicPacketNumber(i)));
+ }
+ EXPECT_TRUE(queue.Contains(QuicPacketNumber(20)));
+ EXPECT_FALSE(queue.Contains(QuicPacketNumber(21)));
+
+ PacketNumberQueue queue2;
+ EXPECT_FALSE(queue2.Contains(QuicPacketNumber(1)));
+ for (int i = 1; i < 51; ++i) {
+ queue2.Add(QuicPacketNumber(2 * i));
+ }
+ EXPECT_FALSE(queue2.Contains(QuicPacketNumber()));
+ for (int i = 1; i < 51; ++i) {
+ if (i % 2 == 0) {
+ EXPECT_TRUE(queue2.Contains(QuicPacketNumber(i)));
+ } else {
+ EXPECT_FALSE(queue2.Contains(QuicPacketNumber(i)));
+ }
+ }
+ EXPECT_FALSE(queue2.Contains(QuicPacketNumber(101)));
+}
+
+// Tests that a queue contains the expected data after calls to RemoveUpTo().
+TEST_F(PacketNumberQueueTest, Removal) {
+ PacketNumberQueue queue;
+ EXPECT_FALSE(queue.Contains(QuicPacketNumber(51)));
+ queue.AddRange(QuicPacketNumber(1), QuicPacketNumber(100));
+
+ EXPECT_TRUE(queue.RemoveUpTo(QuicPacketNumber(51)));
+ EXPECT_FALSE(queue.RemoveUpTo(QuicPacketNumber(51)));
+
+ EXPECT_FALSE(queue.Contains(QuicPacketNumber()));
+ for (int i = 1; i < 51; ++i) {
+ EXPECT_FALSE(queue.Contains(QuicPacketNumber(i)));
+ }
+ for (int i = 51; i < 100; ++i) {
+ EXPECT_TRUE(queue.Contains(QuicPacketNumber(i)));
+ }
+ EXPECT_EQ(49u, queue.NumPacketsSlow());
+ EXPECT_EQ(QuicPacketNumber(51u), queue.Min());
+ EXPECT_EQ(QuicPacketNumber(99u), queue.Max());
+
+ PacketNumberQueue queue2;
+ queue2.AddRange(QuicPacketNumber(1), QuicPacketNumber(5));
+ EXPECT_TRUE(queue2.RemoveUpTo(QuicPacketNumber(3)));
+ EXPECT_TRUE(queue2.RemoveUpTo(QuicPacketNumber(50)));
+ EXPECT_TRUE(queue2.Empty());
+}
+
+// Tests that a queue is empty when all of its elements are removed.
+TEST_F(PacketNumberQueueTest, Empty) {
+ PacketNumberQueue queue;
+ EXPECT_TRUE(queue.Empty());
+ EXPECT_EQ(0u, queue.NumPacketsSlow());
+
+ queue.AddRange(QuicPacketNumber(1), QuicPacketNumber(100));
+ EXPECT_TRUE(queue.RemoveUpTo(QuicPacketNumber(100)));
+ EXPECT_TRUE(queue.Empty());
+ EXPECT_EQ(0u, queue.NumPacketsSlow());
+}
+
+// Tests that logging the state of a PacketNumberQueue does not crash.
+TEST_F(PacketNumberQueueTest, LogDoesNotCrash) {
+ std::ostringstream oss;
+ PacketNumberQueue queue;
+ oss << queue;
+
+ queue.Add(QuicPacketNumber(1));
+ queue.AddRange(QuicPacketNumber(50), QuicPacketNumber(100));
+ oss << queue;
+}
+
+// Tests that the iterators returned from a packet queue iterate over the queue.
+TEST_F(PacketNumberQueueTest, Iterators) {
+ PacketNumberQueue queue;
+ queue.AddRange(QuicPacketNumber(1), QuicPacketNumber(100));
+
+ const std::vector<QuicInterval<QuicPacketNumber>> actual_intervals(
+ queue.begin(), queue.end());
+
+ PacketNumberQueue queue2;
+ for (int i = 1; i < 100; i++) {
+ queue2.AddRange(QuicPacketNumber(i), QuicPacketNumber(i + 1));
+ }
+
+ const std::vector<QuicInterval<QuicPacketNumber>> actual_intervals2(
+ queue2.begin(), queue2.end());
+
+ std::vector<QuicInterval<QuicPacketNumber>> expected_intervals;
+ expected_intervals.emplace_back(QuicInterval<QuicPacketNumber>(
+ QuicPacketNumber(1), QuicPacketNumber(100)));
+ EXPECT_EQ(expected_intervals, actual_intervals);
+ EXPECT_EQ(expected_intervals, actual_intervals2);
+ EXPECT_EQ(actual_intervals, actual_intervals2);
+}
+
+TEST_F(PacketNumberQueueTest, ReversedIterators) {
+ PacketNumberQueue queue;
+ queue.AddRange(QuicPacketNumber(1), QuicPacketNumber(100));
+ PacketNumberQueue queue2;
+ for (int i = 1; i < 100; i++) {
+ queue2.AddRange(QuicPacketNumber(i), QuicPacketNumber(i + 1));
+ }
+ const std::vector<QuicInterval<QuicPacketNumber>> actual_intervals(
+ queue.rbegin(), queue.rend());
+ const std::vector<QuicInterval<QuicPacketNumber>> actual_intervals2(
+ queue2.rbegin(), queue2.rend());
+
+ std::vector<QuicInterval<QuicPacketNumber>> expected_intervals;
+ expected_intervals.emplace_back(QuicInterval<QuicPacketNumber>(
+ QuicPacketNumber(1), QuicPacketNumber(100)));
+
+ EXPECT_EQ(expected_intervals, actual_intervals);
+ EXPECT_EQ(expected_intervals, actual_intervals2);
+ EXPECT_EQ(actual_intervals, actual_intervals2);
+
+ PacketNumberQueue queue3;
+ for (int i = 1; i < 20; i++) {
+ queue3.Add(QuicPacketNumber(2 * i));
+ }
+
+ auto begin = queue3.begin();
+ auto end = queue3.end();
+ --end;
+ auto rbegin = queue3.rbegin();
+ auto rend = queue3.rend();
+ --rend;
+
+ EXPECT_EQ(*begin, *rend);
+ EXPECT_EQ(*rbegin, *end);
+}
+
+TEST_F(PacketNumberQueueTest, IntervalLengthAndRemoveInterval) {
+ PacketNumberQueue queue;
+ queue.AddRange(QuicPacketNumber(1), QuicPacketNumber(10));
+ queue.AddRange(QuicPacketNumber(20), QuicPacketNumber(30));
+ queue.AddRange(QuicPacketNumber(40), QuicPacketNumber(50));
+ EXPECT_EQ(3u, queue.NumIntervals());
+ EXPECT_EQ(10u, queue.LastIntervalLength());
+
+ EXPECT_TRUE(queue.RemoveUpTo(QuicPacketNumber(25)));
+ EXPECT_EQ(2u, queue.NumIntervals());
+ EXPECT_EQ(10u, queue.LastIntervalLength());
+ EXPECT_EQ(QuicPacketNumber(25u), queue.Min());
+ EXPECT_EQ(QuicPacketNumber(49u), queue.Max());
+}
+
+} // namespace
+} // namespace test
+} // namespace quic
diff --git a/quic/core/frames/quic_goaway_frame.cc b/quic/core/frames/quic_goaway_frame.cc
new file mode 100644
index 0000000..ff034f0
--- /dev/null
+++ b/quic/core/frames/quic_goaway_frame.cc
@@ -0,0 +1,34 @@
+// 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_goaway_frame.h"
+#include "net/third_party/quiche/src/quic/core/quic_constants.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_string.h"
+
+namespace quic {
+
+QuicGoAwayFrame::QuicGoAwayFrame()
+ : control_frame_id(kInvalidControlFrameId),
+ error_code(QUIC_NO_ERROR),
+ last_good_stream_id(0) {}
+
+QuicGoAwayFrame::QuicGoAwayFrame(QuicControlFrameId control_frame_id,
+ QuicErrorCode error_code,
+ QuicStreamId last_good_stream_id,
+ const QuicString& reason)
+ : control_frame_id(control_frame_id),
+ error_code(error_code),
+ last_good_stream_id(last_good_stream_id),
+ reason_phrase(reason) {}
+
+std::ostream& operator<<(std::ostream& os,
+ const QuicGoAwayFrame& goaway_frame) {
+ os << "{ control_frame_id: " << goaway_frame.control_frame_id
+ << ", error_code: " << goaway_frame.error_code
+ << ", last_good_stream_id: " << goaway_frame.last_good_stream_id
+ << ", reason_phrase: '" << goaway_frame.reason_phrase << "' }\n";
+ return os;
+}
+
+} // namespace quic
diff --git a/quic/core/frames/quic_goaway_frame.h b/quic/core/frames/quic_goaway_frame.h
new file mode 100644
index 0000000..085e915
--- /dev/null
+++ b/quic/core/frames/quic_goaway_frame.h
@@ -0,0 +1,36 @@
+// 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.
+
+#ifndef QUICHE_QUIC_CORE_FRAMES_QUIC_GOAWAY_FRAME_H_
+#define QUICHE_QUIC_CORE_FRAMES_QUIC_GOAWAY_FRAME_H_
+
+#include <ostream>
+
+#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_string.h"
+
+namespace quic {
+
+struct QUIC_EXPORT_PRIVATE QuicGoAwayFrame {
+ QuicGoAwayFrame();
+ QuicGoAwayFrame(QuicControlFrameId control_frame_id,
+ QuicErrorCode error_code,
+ QuicStreamId last_good_stream_id,
+ const QuicString& reason);
+
+ friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
+ const QuicGoAwayFrame& g);
+
+ // A unique identifier of this control frame. 0 when this frame is received,
+ // and non-zero when sent.
+ QuicControlFrameId control_frame_id;
+ QuicErrorCode error_code;
+ QuicStreamId last_good_stream_id;
+ QuicString reason_phrase;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_FRAMES_QUIC_GOAWAY_FRAME_H_
diff --git a/quic/core/frames/quic_inlined_frame.h b/quic/core/frames/quic_inlined_frame.h
new file mode 100644
index 0000000..08c4869
--- /dev/null
+++ b/quic/core/frames/quic_inlined_frame.h
@@ -0,0 +1,30 @@
+// Copyright (c) 2018 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.
+
+#ifndef QUICHE_QUIC_CORE_FRAMES_QUIC_INLINED_FRAME_H_
+#define QUICHE_QUIC_CORE_FRAMES_QUIC_INLINED_FRAME_H_
+
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+
+namespace quic {
+
+// QuicInlinedFrame is the base class of all frame types that is inlined in the
+// QuicFrame class. It gurantees all inlined frame types contain a 'type' field
+// at offset 0, such that QuicFrame.type can get the correct frame type for both
+// inline and out-of-line frame types.
+template <typename DerivedT>
+struct QUIC_EXPORT_PRIVATE QuicInlinedFrame {
+ QuicInlinedFrame(QuicFrameType type) : type(type) {
+ static_assert(offsetof(DerivedT, type) == 0,
+ "type must be the first field.");
+ static_assert(sizeof(DerivedT) <= 24,
+ "Frames larger than 24 bytes should not be inlined.");
+ }
+ QuicFrameType type;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_FRAMES_QUIC_INLINED_FRAME_H_
diff --git a/quic/core/frames/quic_max_stream_id_frame.cc b/quic/core/frames/quic_max_stream_id_frame.cc
new file mode 100644
index 0000000..19270e8
--- /dev/null
+++ b/quic/core/frames/quic_max_stream_id_frame.cc
@@ -0,0 +1,25 @@
+// 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_max_stream_id_frame.h"
+
+namespace quic {
+
+QuicMaxStreamIdFrame::QuicMaxStreamIdFrame()
+ : QuicInlinedFrame(MAX_STREAM_ID_FRAME),
+ control_frame_id(kInvalidControlFrameId) {}
+
+QuicMaxStreamIdFrame::QuicMaxStreamIdFrame(QuicControlFrameId control_frame_id,
+ QuicStreamId max_stream_id)
+ : QuicInlinedFrame(MAX_STREAM_ID_FRAME),
+ control_frame_id(control_frame_id),
+ max_stream_id(max_stream_id) {}
+
+std::ostream& operator<<(std::ostream& os, const QuicMaxStreamIdFrame& frame) {
+ os << "{ control_frame_id: " << frame.control_frame_id
+ << ", stream_id: " << frame.max_stream_id << " }\n";
+ return os;
+}
+
+} // namespace quic
diff --git a/quic/core/frames/quic_max_stream_id_frame.h b/quic/core/frames/quic_max_stream_id_frame.h
new file mode 100644
index 0000000..6177687
--- /dev/null
+++ b/quic/core/frames/quic_max_stream_id_frame.h
@@ -0,0 +1,40 @@
+// 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.
+
+#ifndef QUICHE_QUIC_CORE_FRAMES_QUIC_MAX_STREAM_ID_FRAME_H_
+#define QUICHE_QUIC_CORE_FRAMES_QUIC_MAX_STREAM_ID_FRAME_H_
+
+#include <ostream>
+
+#include "net/third_party/quiche/src/quic/core/frames/quic_inlined_frame.h"
+#include "net/third_party/quiche/src/quic/core/quic_constants.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+
+namespace quic {
+
+// IETF format MAX_STREAM_ID frame.
+// This frame is used by the sender to inform the peer of the largest
+// stream id that the peer may open and that the sender will accept.
+struct QUIC_EXPORT_PRIVATE QuicMaxStreamIdFrame
+ : public QuicInlinedFrame<QuicMaxStreamIdFrame> {
+ QuicMaxStreamIdFrame();
+ QuicMaxStreamIdFrame(QuicControlFrameId control_frame_id,
+ QuicStreamId max_stream_id);
+
+ friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(
+ std::ostream& os,
+ const QuicMaxStreamIdFrame& frame);
+
+ // A unique identifier of this control frame. 0 when this frame is received,
+ // and non-zero when sent.
+ QuicControlFrameId control_frame_id;
+
+ // The maximum stream id to support.
+ QuicStreamId max_stream_id;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_FRAMES_QUIC_MAX_STREAM_ID_FRAME_H_
diff --git a/quic/core/frames/quic_message_frame.cc b/quic/core/frames/quic_message_frame.cc
new file mode 100644
index 0000000..c0de272
--- /dev/null
+++ b/quic/core/frames/quic_message_frame.cc
@@ -0,0 +1,29 @@
+// Copyright (c) 2018 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_message_frame.h"
+
+#include "net/third_party/quiche/src/quic/core/quic_constants.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
+
+namespace quic {
+
+QuicMessageFrame::QuicMessageFrame()
+ : message_id(0), data(nullptr), message_length(0) {}
+
+QuicMessageFrame::QuicMessageFrame(QuicMessageId message_id)
+ : message_id(message_id), data(nullptr), message_length(0) {}
+
+QuicMessageFrame::QuicMessageFrame(const char* data, QuicPacketLength length)
+ : message_id(0), data(data), message_length(length) {}
+
+QuicMessageFrame::~QuicMessageFrame() {}
+
+std::ostream& operator<<(std::ostream& os, const QuicMessageFrame& s) {
+ os << " message_id: " << s.message_id
+ << ", message_length: " << s.message_length << " }\n";
+ return os;
+}
+
+} // namespace quic
diff --git a/quic/core/frames/quic_message_frame.h b/quic/core/frames/quic_message_frame.h
new file mode 100644
index 0000000..4accff2
--- /dev/null
+++ b/quic/core/frames/quic_message_frame.h
@@ -0,0 +1,49 @@
+// Copyright (c) 2018 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.
+
+#ifndef QUICHE_QUIC_CORE_FRAMES_QUIC_MESSAGE_FRAME_H_
+#define QUICHE_QUIC_CORE_FRAMES_QUIC_MESSAGE_FRAME_H_
+
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_mem_slice.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+
+namespace quic {
+
+typedef QuicInlinedVector<QuicMemSlice, 1> QuicMessageData;
+
+struct QUIC_EXPORT_PRIVATE QuicMessageFrame {
+ QuicMessageFrame();
+ explicit QuicMessageFrame(QuicMessageId message_id);
+ QuicMessageFrame(const char* data, QuicPacketLength length);
+
+ QuicMessageFrame(const QuicMessageFrame& other) = delete;
+ QuicMessageFrame& operator=(const QuicMessageFrame& other) = delete;
+
+ QuicMessageFrame(QuicMessageFrame&& other) = default;
+ QuicMessageFrame& operator=(QuicMessageFrame&& other) = default;
+
+ ~QuicMessageFrame();
+
+ friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(
+ std::ostream& os,
+ const QuicMessageFrame& s);
+
+ // message_id is only used on the sender side and does not get serialized on
+ // wire.
+ QuicMessageId message_id;
+ // Not owned, only used on read path.
+ const char* data;
+ // Total length of message_data, must be fit into one packet.
+ QuicPacketLength message_length;
+
+ // The actual message data which is reference counted, used on write path.
+ QuicMessageData message_data;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_FRAMES_QUIC_MESSAGE_FRAME_H_
diff --git a/quic/core/frames/quic_mtu_discovery_frame.h b/quic/core/frames/quic_mtu_discovery_frame.h
new file mode 100644
index 0000000..330df21
--- /dev/null
+++ b/quic/core/frames/quic_mtu_discovery_frame.h
@@ -0,0 +1,23 @@
+// 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.
+
+#ifndef QUICHE_QUIC_CORE_FRAMES_QUIC_MTU_DISCOVERY_FRAME_H_
+#define QUICHE_QUIC_CORE_FRAMES_QUIC_MTU_DISCOVERY_FRAME_H_
+
+#include "net/third_party/quiche/src/quic/core/frames/quic_inlined_frame.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+
+namespace quic {
+
+// A path MTU discovery frame contains no payload and is serialized as a ping
+// frame.
+struct QUIC_EXPORT_PRIVATE QuicMtuDiscoveryFrame
+ : public QuicInlinedFrame<QuicMtuDiscoveryFrame> {
+ QuicMtuDiscoveryFrame() : QuicInlinedFrame(MTU_DISCOVERY_FRAME) {}
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_FRAMES_QUIC_MTU_DISCOVERY_FRAME_H_
diff --git a/quic/core/frames/quic_new_connection_id_frame.cc b/quic/core/frames/quic_new_connection_id_frame.cc
new file mode 100644
index 0000000..b7f63e2
--- /dev/null
+++ b/quic/core/frames/quic_new_connection_id_frame.cc
@@ -0,0 +1,33 @@
+// 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_new_connection_id_frame.h"
+#include "net/third_party/quiche/src/quic/core/quic_constants.h"
+
+namespace quic {
+
+QuicNewConnectionIdFrame::QuicNewConnectionIdFrame()
+ : control_frame_id(kInvalidControlFrameId),
+ connection_id(EmptyQuicConnectionId()),
+ sequence_number(0) {}
+
+QuicNewConnectionIdFrame::QuicNewConnectionIdFrame(
+ QuicControlFrameId control_frame_id,
+ QuicConnectionId connection_id,
+ QuicConnectionIdSequenceNumber sequence_number,
+ const QuicUint128 stateless_reset_token)
+ : control_frame_id(control_frame_id),
+ connection_id(connection_id),
+ sequence_number(sequence_number),
+ stateless_reset_token(stateless_reset_token) {}
+
+std::ostream& operator<<(std::ostream& os,
+ const QuicNewConnectionIdFrame& frame) {
+ os << "{ control_frame_id: " << frame.control_frame_id
+ << ", connection_id: " << frame.connection_id
+ << ", sequence_number: " << frame.sequence_number << " }\n";
+ return os;
+}
+
+} // namespace quic
diff --git a/quic/core/frames/quic_new_connection_id_frame.h b/quic/core/frames/quic_new_connection_id_frame.h
new file mode 100644
index 0000000..1948d22
--- /dev/null
+++ b/quic/core/frames/quic_new_connection_id_frame.h
@@ -0,0 +1,37 @@
+// 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.
+
+#ifndef QUICHE_QUIC_CORE_FRAMES_QUIC_NEW_CONNECTION_ID_FRAME_H_
+#define QUICHE_QUIC_CORE_FRAMES_QUIC_NEW_CONNECTION_ID_FRAME_H_
+
+#include <ostream>
+
+#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_uint128.h"
+
+namespace quic {
+
+struct QUIC_EXPORT_PRIVATE QuicNewConnectionIdFrame {
+ QuicNewConnectionIdFrame();
+ QuicNewConnectionIdFrame(QuicControlFrameId control_frame_id,
+ QuicConnectionId connection_id,
+ QuicConnectionIdSequenceNumber sequence_number,
+ const QuicUint128 stateless_reset_token);
+
+ friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(
+ std::ostream& os,
+ const QuicNewConnectionIdFrame& frame);
+
+ // A unique identifier of this control frame. 0 when this frame is received,
+ // and non-zero when sent.
+ QuicControlFrameId control_frame_id;
+ QuicConnectionId connection_id;
+ QuicConnectionIdSequenceNumber sequence_number;
+ QuicUint128 stateless_reset_token;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_FRAMES_QUIC_NEW_CONNECTION_ID_FRAME_H_
diff --git a/quic/core/frames/quic_new_token_frame.cc b/quic/core/frames/quic_new_token_frame.cc
new file mode 100644
index 0000000..c2f4e74
--- /dev/null
+++ b/quic/core/frames/quic_new_token_frame.cc
@@ -0,0 +1,24 @@
+// Copyright (c) 2018 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_new_token_frame.h"
+#include "net/third_party/quiche/src/quic/core/quic_constants.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
+
+namespace quic {
+
+QuicNewTokenFrame::QuicNewTokenFrame()
+ : control_frame_id(kInvalidControlFrameId) {}
+
+QuicNewTokenFrame::QuicNewTokenFrame(QuicControlFrameId control_frame_id,
+ QuicString token)
+ : control_frame_id(control_frame_id), token(token) {}
+
+std::ostream& operator<<(std::ostream& os, const QuicNewTokenFrame& s) {
+ os << "{ control_frame_id: " << s.control_frame_id << ", token: " << s.token
+ << " }\n";
+ return os;
+}
+
+} // namespace quic
diff --git a/quic/core/frames/quic_new_token_frame.h b/quic/core/frames/quic_new_token_frame.h
new file mode 100644
index 0000000..6fb0ea4
--- /dev/null
+++ b/quic/core/frames/quic_new_token_frame.h
@@ -0,0 +1,37 @@
+// Copyright (c) 2018 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.
+
+#ifndef QUICHE_QUIC_CORE_FRAMES_QUIC_NEW_TOKEN_FRAME_H_
+#define QUICHE_QUIC_CORE_FRAMES_QUIC_NEW_TOKEN_FRAME_H_
+
+#include <memory>
+#include <ostream>
+
+#include "net/third_party/quiche/src/quic/core/quic_buffer_allocator.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+
+namespace quic {
+
+struct QUIC_EXPORT_PRIVATE QuicNewTokenFrame {
+ QuicNewTokenFrame();
+ QuicNewTokenFrame(QuicControlFrameId control_frame_id, QuicString token);
+
+ friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(
+ std::ostream& os,
+ const QuicNewTokenFrame& s);
+
+ // A unique identifier of this control frame. 0 when this frame is received,
+ // and non-zero when sent.
+ QuicControlFrameId control_frame_id;
+
+ QuicString token;
+};
+static_assert(sizeof(QuicNewTokenFrame) <= 64,
+ "Keep the QuicNewTokenFrame size to a cacheline.");
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_FRAMES_QUIC_NEW_TOKEN_FRAME_H_
diff --git a/quic/core/frames/quic_padding_frame.cc b/quic/core/frames/quic_padding_frame.cc
new file mode 100644
index 0000000..098a664
--- /dev/null
+++ b/quic/core/frames/quic_padding_frame.cc
@@ -0,0 +1,15 @@
+// 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_padding_frame.h"
+
+namespace quic {
+
+std::ostream& operator<<(std::ostream& os,
+ const QuicPaddingFrame& padding_frame) {
+ os << "{ num_padding_bytes: " << padding_frame.num_padding_bytes << " }\n";
+ return os;
+}
+
+} // namespace quic
diff --git a/quic/core/frames/quic_padding_frame.h b/quic/core/frames/quic_padding_frame.h
new file mode 100644
index 0000000..03e0a40
--- /dev/null
+++ b/quic/core/frames/quic_padding_frame.h
@@ -0,0 +1,35 @@
+// 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.
+
+#ifndef QUICHE_QUIC_CORE_FRAMES_QUIC_PADDING_FRAME_H_
+#define QUICHE_QUIC_CORE_FRAMES_QUIC_PADDING_FRAME_H_
+
+#include <cstdint>
+#include <ostream>
+
+#include "net/third_party/quiche/src/quic/core/frames/quic_inlined_frame.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+
+namespace quic {
+
+// A padding frame contains no payload.
+struct QUIC_EXPORT_PRIVATE QuicPaddingFrame
+ : public QuicInlinedFrame<QuicPaddingFrame> {
+ QuicPaddingFrame() : QuicInlinedFrame(PADDING_FRAME), num_padding_bytes(-1) {}
+ explicit QuicPaddingFrame(int num_padding_bytes)
+ : QuicInlinedFrame(PADDING_FRAME), num_padding_bytes(num_padding_bytes) {}
+
+ friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(
+ std::ostream& os,
+ const QuicPaddingFrame& s);
+
+ // -1: full padding to the end of a max-sized packet
+ // otherwise: only pad up to num_padding_bytes bytes
+ int num_padding_bytes;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_FRAMES_QUIC_PADDING_FRAME_H_
diff --git a/quic/core/frames/quic_path_challenge_frame.cc b/quic/core/frames/quic_path_challenge_frame.cc
new file mode 100644
index 0000000..c1ca6a8
--- /dev/null
+++ b/quic/core/frames/quic_path_challenge_frame.cc
@@ -0,0 +1,37 @@
+// Copyright (c) 2018 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_path_challenge_frame.h"
+#include "net/third_party/quiche/src/quic/core/quic_constants.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
+
+namespace quic {
+
+QuicPathChallengeFrame::QuicPathChallengeFrame()
+ : control_frame_id(kInvalidControlFrameId) {}
+
+QuicPathChallengeFrame::QuicPathChallengeFrame(
+ QuicControlFrameId control_frame_id,
+ const QuicPathFrameBuffer& data_buff)
+ : control_frame_id(control_frame_id) {
+ memcpy(data_buffer.data(), data_buff.data(), data_buffer.size());
+}
+
+QuicPathChallengeFrame::~QuicPathChallengeFrame() {}
+
+std::ostream& operator<<(std::ostream& os,
+ const QuicPathChallengeFrame& frame) {
+ os << "{ control_frame_id: " << frame.control_frame_id
+ << ", data: " << static_cast<unsigned>(frame.data_buffer[0]) << " "
+ << static_cast<unsigned>(frame.data_buffer[1]) << " "
+ << static_cast<unsigned>(frame.data_buffer[2]) << " "
+ << static_cast<unsigned>(frame.data_buffer[3]) << " "
+ << static_cast<unsigned>(frame.data_buffer[4]) << " "
+ << static_cast<unsigned>(frame.data_buffer[5]) << " "
+ << static_cast<unsigned>(frame.data_buffer[6]) << " "
+ << static_cast<unsigned>(frame.data_buffer[7]) << " }\n";
+ return os;
+}
+
+} // namespace quic
diff --git a/quic/core/frames/quic_path_challenge_frame.h b/quic/core/frames/quic_path_challenge_frame.h
new file mode 100644
index 0000000..46a010a
--- /dev/null
+++ b/quic/core/frames/quic_path_challenge_frame.h
@@ -0,0 +1,36 @@
+// Copyright (c) 2018 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.
+
+#ifndef QUICHE_QUIC_CORE_FRAMES_QUIC_PATH_CHALLENGE_FRAME_H_
+#define QUICHE_QUIC_CORE_FRAMES_QUIC_PATH_CHALLENGE_FRAME_H_
+
+#include <memory>
+#include <ostream>
+
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+
+namespace quic {
+
+// Size of the entire IETF Quic Path Challenge frame.
+const size_t kQuicPathChallengeFrameSize = kQuicPathFrameBufferSize;
+
+struct QUIC_EXPORT_PRIVATE QuicPathChallengeFrame {
+ QuicPathChallengeFrame();
+ QuicPathChallengeFrame(QuicControlFrameId control_frame_id,
+ const QuicPathFrameBuffer& data_buff);
+ ~QuicPathChallengeFrame();
+
+ friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(
+ std::ostream& os,
+ const QuicPathChallengeFrame& frame);
+
+ // A unique identifier of this control frame. 0 when this frame is received,
+ // and non-zero when sent.
+ QuicControlFrameId control_frame_id;
+
+ QuicPathFrameBuffer data_buffer;
+};
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_FRAMES_QUIC_PATH_CHALLENGE_FRAME_H_
diff --git a/quic/core/frames/quic_path_response_frame.cc b/quic/core/frames/quic_path_response_frame.cc
new file mode 100644
index 0000000..85e9712
--- /dev/null
+++ b/quic/core/frames/quic_path_response_frame.cc
@@ -0,0 +1,36 @@
+// Copyright (c) 2018 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_path_response_frame.h"
+#include "net/third_party/quiche/src/quic/core/quic_constants.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
+
+namespace quic {
+
+QuicPathResponseFrame::QuicPathResponseFrame()
+ : control_frame_id(kInvalidControlFrameId) {}
+
+QuicPathResponseFrame::QuicPathResponseFrame(
+ QuicControlFrameId control_frame_id,
+ const QuicPathFrameBuffer& data_buff)
+ : control_frame_id(control_frame_id) {
+ memcpy(data_buffer.data(), data_buff.data(), data_buffer.size());
+}
+
+QuicPathResponseFrame::~QuicPathResponseFrame() {}
+
+std::ostream& operator<<(std::ostream& os, const QuicPathResponseFrame& frame) {
+ os << "{ control_frame_id: " << frame.control_frame_id
+ << ", data: " << static_cast<unsigned>(frame.data_buffer[0]) << " "
+ << static_cast<unsigned>(frame.data_buffer[1]) << " "
+ << static_cast<unsigned>(frame.data_buffer[2]) << " "
+ << static_cast<unsigned>(frame.data_buffer[3]) << " "
+ << static_cast<unsigned>(frame.data_buffer[4]) << " "
+ << static_cast<unsigned>(frame.data_buffer[5]) << " "
+ << static_cast<unsigned>(frame.data_buffer[6]) << " "
+ << static_cast<unsigned>(frame.data_buffer[7]) << " }\n";
+ return os;
+}
+
+} // namespace quic
diff --git a/quic/core/frames/quic_path_response_frame.h b/quic/core/frames/quic_path_response_frame.h
new file mode 100644
index 0000000..e953ad8
--- /dev/null
+++ b/quic/core/frames/quic_path_response_frame.h
@@ -0,0 +1,36 @@
+// Copyright (c) 2018 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.
+
+#ifndef QUICHE_QUIC_CORE_FRAMES_QUIC_PATH_RESPONSE_FRAME_H_
+#define QUICHE_QUIC_CORE_FRAMES_QUIC_PATH_RESPONSE_FRAME_H_
+
+#include <memory>
+#include <ostream>
+
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+
+namespace quic {
+
+// Size of the entire IETF Quic Path Response frame.
+const size_t kQuicPathResponseFrameSize = kQuicPathFrameBufferSize;
+
+struct QUIC_EXPORT_PRIVATE QuicPathResponseFrame {
+ QuicPathResponseFrame();
+ QuicPathResponseFrame(QuicControlFrameId control_frame_id,
+ const QuicPathFrameBuffer& data_buff);
+ ~QuicPathResponseFrame();
+
+ friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(
+ std::ostream& os,
+ const QuicPathResponseFrame& frame);
+
+ // A unique identifier of this control frame. 0 when this frame is received,
+ // and non-zero when sent.
+ QuicControlFrameId control_frame_id;
+
+ QuicPathFrameBuffer data_buffer;
+};
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_FRAMES_QUIC_PATH_RESPONSE_FRAME_H_
diff --git a/quic/core/frames/quic_ping_frame.cc b/quic/core/frames/quic_ping_frame.cc
new file mode 100644
index 0000000..d31efb0
--- /dev/null
+++ b/quic/core/frames/quic_ping_frame.cc
@@ -0,0 +1,20 @@
+// Copyright (c) 2017 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_ping_frame.h"
+
+namespace quic {
+
+QuicPingFrame::QuicPingFrame()
+ : QuicInlinedFrame(PING_FRAME), control_frame_id(kInvalidControlFrameId) {}
+
+QuicPingFrame::QuicPingFrame(QuicControlFrameId control_frame_id)
+ : QuicInlinedFrame(PING_FRAME), control_frame_id(control_frame_id) {}
+
+std::ostream& operator<<(std::ostream& os, const QuicPingFrame& ping_frame) {
+ os << "{ control_frame_id: " << ping_frame.control_frame_id << " }\n";
+ return os;
+}
+
+} // namespace quic
diff --git a/quic/core/frames/quic_ping_frame.h b/quic/core/frames/quic_ping_frame.h
new file mode 100644
index 0000000..352d079
--- /dev/null
+++ b/quic/core/frames/quic_ping_frame.h
@@ -0,0 +1,33 @@
+// 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.
+
+#ifndef QUICHE_QUIC_CORE_FRAMES_QUIC_PING_FRAME_H_
+#define QUICHE_QUIC_CORE_FRAMES_QUIC_PING_FRAME_H_
+
+#include "net/third_party/quiche/src/quic/core/frames/quic_inlined_frame.h"
+#include "net/third_party/quiche/src/quic/core/quic_constants.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+
+namespace quic {
+
+// A ping frame contains no payload, though it is retransmittable,
+// and ACK'd just like other normal frames.
+struct QUIC_EXPORT_PRIVATE QuicPingFrame
+ : public QuicInlinedFrame<QuicPingFrame> {
+ QuicPingFrame();
+ explicit QuicPingFrame(QuicControlFrameId control_frame_id);
+
+ friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(
+ std::ostream& os,
+ const QuicPingFrame& ping_frame);
+
+ // A unique identifier of this control frame. 0 when this frame is received,
+ // and non-zero when sent.
+ QuicControlFrameId control_frame_id;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_FRAMES_QUIC_PING_FRAME_H_
diff --git a/quic/core/frames/quic_retire_connection_id_frame.cc b/quic/core/frames/quic_retire_connection_id_frame.cc
new file mode 100644
index 0000000..6828ce4
--- /dev/null
+++ b/quic/core/frames/quic_retire_connection_id_frame.cc
@@ -0,0 +1,25 @@
+// Copyright (c) 2019 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_retire_connection_id_frame.h"
+#include "net/third_party/quiche/src/quic/core/quic_constants.h"
+
+namespace quic {
+
+QuicRetireConnectionIdFrame::QuicRetireConnectionIdFrame()
+ : control_frame_id(kInvalidControlFrameId), sequence_number(0) {}
+
+QuicRetireConnectionIdFrame::QuicRetireConnectionIdFrame(
+ QuicControlFrameId control_frame_id,
+ QuicConnectionIdSequenceNumber sequence_number)
+ : control_frame_id(control_frame_id), sequence_number(sequence_number) {}
+
+std::ostream& operator<<(std::ostream& os,
+ const QuicRetireConnectionIdFrame& frame) {
+ os << "{ control_frame_id: " << frame.control_frame_id
+ << ", sequence_number: " << frame.sequence_number << " }\n";
+ return os;
+}
+
+} // namespace quic
diff --git a/quic/core/frames/quic_retire_connection_id_frame.h b/quic/core/frames/quic_retire_connection_id_frame.h
new file mode 100644
index 0000000..79521f6
--- /dev/null
+++ b/quic/core/frames/quic_retire_connection_id_frame.h
@@ -0,0 +1,33 @@
+// Copyright (c) 2019 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.
+
+#ifndef QUICHE_QUIC_CORE_FRAMES_QUIC_RETIRE_CONNECTION_ID_FRAME_H_
+#define QUICHE_QUIC_CORE_FRAMES_QUIC_RETIRE_CONNECTION_ID_FRAME_H_
+
+#include <ostream>
+
+#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_uint128.h"
+
+namespace quic {
+
+struct QUIC_EXPORT_PRIVATE QuicRetireConnectionIdFrame {
+ QuicRetireConnectionIdFrame();
+ QuicRetireConnectionIdFrame(QuicControlFrameId control_frame_id,
+ QuicConnectionIdSequenceNumber sequence_number);
+
+ friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(
+ std::ostream& os,
+ const QuicRetireConnectionIdFrame& frame);
+
+ // A unique identifier of this control frame. 0 when this frame is received,
+ // and non-zero when sent.
+ QuicControlFrameId control_frame_id;
+ QuicConnectionIdSequenceNumber sequence_number;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_FRAMES_QUIC_RETIRE_CONNECTION_ID_FRAME_H_
diff --git a/quic/core/frames/quic_rst_stream_frame.cc b/quic/core/frames/quic_rst_stream_frame.cc
new file mode 100644
index 0000000..7fbf365
--- /dev/null
+++ b/quic/core/frames/quic_rst_stream_frame.cc
@@ -0,0 +1,42 @@
+// 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_rst_stream_frame.h"
+#include "net/third_party/quiche/src/quic/core/quic_constants.h"
+
+namespace quic {
+
+QuicRstStreamFrame::QuicRstStreamFrame()
+ : control_frame_id(kInvalidControlFrameId),
+ stream_id(0),
+ error_code(QUIC_STREAM_NO_ERROR),
+ byte_offset(0) {}
+
+QuicRstStreamFrame::QuicRstStreamFrame(QuicControlFrameId control_frame_id,
+ QuicStreamId stream_id,
+ QuicRstStreamErrorCode error_code,
+ QuicStreamOffset bytes_written)
+ : control_frame_id(control_frame_id),
+ stream_id(stream_id),
+ error_code(error_code),
+ byte_offset(bytes_written) {}
+
+QuicRstStreamFrame::QuicRstStreamFrame(QuicControlFrameId control_frame_id,
+ QuicStreamId stream_id,
+ uint16_t ietf_error_code,
+ QuicStreamOffset bytes_written)
+ : control_frame_id(control_frame_id),
+ stream_id(stream_id),
+ ietf_error_code(ietf_error_code),
+ byte_offset(bytes_written) {}
+
+std::ostream& operator<<(std::ostream& os,
+ const QuicRstStreamFrame& rst_frame) {
+ os << "{ control_frame_id: " << rst_frame.control_frame_id
+ << ", stream_id: " << rst_frame.stream_id
+ << ", error_code: " << rst_frame.error_code << " }\n";
+ return os;
+}
+
+} // namespace quic
diff --git a/quic/core/frames/quic_rst_stream_frame.h b/quic/core/frames/quic_rst_stream_frame.h
new file mode 100644
index 0000000..0957614
--- /dev/null
+++ b/quic/core/frames/quic_rst_stream_frame.h
@@ -0,0 +1,54 @@
+// 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.
+
+#ifndef QUICHE_QUIC_CORE_FRAMES_QUIC_RST_STREAM_FRAME_H_
+#define QUICHE_QUIC_CORE_FRAMES_QUIC_RST_STREAM_FRAME_H_
+
+#include <ostream>
+
+#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+
+namespace quic {
+
+struct QUIC_EXPORT_PRIVATE QuicRstStreamFrame {
+ QuicRstStreamFrame();
+ QuicRstStreamFrame(QuicControlFrameId control_frame_id,
+ QuicStreamId stream_id,
+ QuicRstStreamErrorCode error_code,
+ QuicStreamOffset bytes_written);
+ QuicRstStreamFrame(QuicControlFrameId control_frame_id,
+ QuicStreamId stream_id,
+ uint16_t ietf_error_code,
+ QuicStreamOffset bytes_written);
+
+ friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(
+ std::ostream& os,
+ const QuicRstStreamFrame& r);
+
+ // A unique identifier of this control frame. 0 when this frame is received,
+ // and non-zero when sent.
+ QuicControlFrameId control_frame_id;
+
+ QuicStreamId stream_id;
+
+ // Caller must know whether IETF- or Google- QUIC is in use and
+ // set the appropriate error code.
+ union {
+ QuicRstStreamErrorCode error_code;
+ // In IETF QUIC the code is up to the app on top of quic, so is
+ // more general than QuicRstStreamErrorCode allows.
+ uint16_t ietf_error_code;
+ };
+
+ // Used to update flow control windows. On termination of a stream, both
+ // endpoints must inform the peer of the number of bytes they have sent on
+ // that stream. This can be done through normal termination (data packet with
+ // FIN) or through a RST.
+ QuicStreamOffset byte_offset;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_FRAMES_QUIC_RST_STREAM_FRAME_H_
diff --git a/quic/core/frames/quic_stop_sending_frame.cc b/quic/core/frames/quic_stop_sending_frame.cc
new file mode 100644
index 0000000..1afd512
--- /dev/null
+++ b/quic/core/frames/quic_stop_sending_frame.cc
@@ -0,0 +1,30 @@
+// Copyright (c) 2018 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_stop_sending_frame.h"
+#include "net/third_party/quiche/src/quic/core/quic_constants.h"
+
+namespace quic {
+
+QuicStopSendingFrame::QuicStopSendingFrame()
+ : control_frame_id(kInvalidControlFrameId),
+ stream_id(0),
+ application_error_code(0) {}
+
+QuicStopSendingFrame::QuicStopSendingFrame(
+ QuicControlFrameId control_frame_id,
+ QuicStreamId stream_id,
+ QuicApplicationErrorCode application_error_code)
+ : control_frame_id(control_frame_id),
+ stream_id(stream_id),
+ application_error_code(application_error_code) {}
+
+std::ostream& operator<<(std::ostream& os, const QuicStopSendingFrame& frame) {
+ os << "{ control_frame_id: " << frame.control_frame_id
+ << ", stream_id: " << frame.stream_id
+ << ", application_error_code: " << frame.application_error_code << " }\n";
+ return os;
+}
+
+} // namespace quic
diff --git a/quic/core/frames/quic_stop_sending_frame.h b/quic/core/frames/quic_stop_sending_frame.h
new file mode 100644
index 0000000..7ca639d
--- /dev/null
+++ b/quic/core/frames/quic_stop_sending_frame.h
@@ -0,0 +1,34 @@
+// Copyright (c) 2018 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.
+
+#ifndef QUICHE_QUIC_CORE_FRAMES_QUIC_STOP_SENDING_FRAME_H_
+#define QUICHE_QUIC_CORE_FRAMES_QUIC_STOP_SENDING_FRAME_H_
+
+#include <ostream>
+
+#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+
+namespace quic {
+
+struct QUIC_EXPORT_PRIVATE QuicStopSendingFrame {
+ QuicStopSendingFrame();
+ QuicStopSendingFrame(QuicControlFrameId control_frame_id,
+ QuicStreamId stream_id,
+ QuicApplicationErrorCode application_error_code);
+
+ friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(
+ std::ostream& os,
+ const QuicStopSendingFrame& frame);
+
+ // A unique identifier of this control frame. 0 when this frame is received,
+ // and non-zero when sent.
+ QuicControlFrameId control_frame_id;
+ QuicStreamId stream_id;
+ QuicApplicationErrorCode application_error_code;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_FRAMES_QUIC_STOP_SENDING_FRAME_H_
diff --git a/quic/core/frames/quic_stop_waiting_frame.cc b/quic/core/frames/quic_stop_waiting_frame.cc
new file mode 100644
index 0000000..02e0a62
--- /dev/null
+++ b/quic/core/frames/quic_stop_waiting_frame.cc
@@ -0,0 +1,20 @@
+// 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_stop_waiting_frame.h"
+
+#include "net/third_party/quiche/src/quic/core/quic_constants.h"
+
+namespace quic {
+
+QuicStopWaitingFrame::QuicStopWaitingFrame()
+ : QuicInlinedFrame(STOP_WAITING_FRAME) {}
+
+std::ostream& operator<<(std::ostream& os,
+ const QuicStopWaitingFrame& sent_info) {
+ os << "{ least_unacked: " << sent_info.least_unacked << " }\n";
+ return os;
+}
+
+} // namespace quic
diff --git a/quic/core/frames/quic_stop_waiting_frame.h b/quic/core/frames/quic_stop_waiting_frame.h
new file mode 100644
index 0000000..84bfc2a
--- /dev/null
+++ b/quic/core/frames/quic_stop_waiting_frame.h
@@ -0,0 +1,30 @@
+// 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.
+
+#ifndef QUICHE_QUIC_CORE_FRAMES_QUIC_STOP_WAITING_FRAME_H_
+#define QUICHE_QUIC_CORE_FRAMES_QUIC_STOP_WAITING_FRAME_H_
+
+#include <ostream>
+
+#include "net/third_party/quiche/src/quic/core/frames/quic_inlined_frame.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+
+namespace quic {
+
+struct QUIC_EXPORT_PRIVATE QuicStopWaitingFrame
+ : public QuicInlinedFrame<QuicStopWaitingFrame> {
+ QuicStopWaitingFrame();
+
+ friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(
+ std::ostream& os,
+ const QuicStopWaitingFrame& s);
+
+ // The lowest packet we've sent which is unacked, and we expect an ack for.
+ QuicPacketNumber least_unacked;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_FRAMES_QUIC_STOP_WAITING_FRAME_H_
diff --git a/quic/core/frames/quic_stream_frame.cc b/quic/core/frames/quic_stream_frame.cc
new file mode 100644
index 0000000..b9413c7
--- /dev/null
+++ b/quic/core/frames/quic_stream_frame.cc
@@ -0,0 +1,46 @@
+// 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_stream_frame.h"
+
+#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
+
+namespace quic {
+
+QuicStreamFrame::QuicStreamFrame()
+ : QuicStreamFrame(-1, false, 0, nullptr, 0) {}
+
+QuicStreamFrame::QuicStreamFrame(QuicStreamId stream_id,
+ bool fin,
+ QuicStreamOffset offset,
+ QuicStringPiece data)
+ : QuicStreamFrame(stream_id, fin, offset, data.data(), data.length()) {}
+
+QuicStreamFrame::QuicStreamFrame(QuicStreamId stream_id,
+ bool fin,
+ QuicStreamOffset offset,
+ QuicPacketLength data_length)
+ : QuicStreamFrame(stream_id, fin, offset, nullptr, data_length) {}
+
+QuicStreamFrame::QuicStreamFrame(QuicStreamId stream_id,
+ bool fin,
+ QuicStreamOffset offset,
+ const char* data_buffer,
+ QuicPacketLength data_length)
+ : QuicInlinedFrame(STREAM_FRAME),
+ fin(fin),
+ data_length(data_length),
+ stream_id(stream_id),
+ data_buffer(data_buffer),
+ offset(offset) {}
+
+std::ostream& operator<<(std::ostream& os,
+ const QuicStreamFrame& stream_frame) {
+ os << "{ stream_id: " << stream_frame.stream_id
+ << ", fin: " << stream_frame.fin << ", offset: " << stream_frame.offset
+ << ", length: " << stream_frame.data_length << " }\n";
+ return os;
+}
+
+} // namespace quic
diff --git a/quic/core/frames/quic_stream_frame.h b/quic/core/frames/quic_stream_frame.h
new file mode 100644
index 0000000..6cd510d
--- /dev/null
+++ b/quic/core/frames/quic_stream_frame.h
@@ -0,0 +1,51 @@
+// 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.
+
+#ifndef QUICHE_QUIC_CORE_FRAMES_QUIC_STREAM_FRAME_H_
+#define QUICHE_QUIC_CORE_FRAMES_QUIC_STREAM_FRAME_H_
+
+#include <memory>
+#include <ostream>
+
+#include "net/third_party/quiche/src/quic/core/frames/quic_inlined_frame.h"
+#include "net/third_party/quiche/src/quic/core/quic_buffer_allocator.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+
+namespace quic {
+
+struct QUIC_EXPORT_PRIVATE QuicStreamFrame
+ : public QuicInlinedFrame<QuicStreamFrame> {
+ QuicStreamFrame();
+ QuicStreamFrame(QuicStreamId stream_id,
+ bool fin,
+ QuicStreamOffset offset,
+ QuicStringPiece data);
+ QuicStreamFrame(QuicStreamId stream_id,
+ bool fin,
+ QuicStreamOffset offset,
+ QuicPacketLength data_length);
+
+ friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
+ const QuicStreamFrame& s);
+
+ bool fin;
+ QuicPacketLength data_length;
+ QuicStreamId stream_id;
+ const char* data_buffer; // Not owned.
+ QuicStreamOffset offset; // Location of this data in the stream.
+
+ QuicStreamFrame(QuicStreamId stream_id,
+ bool fin,
+ QuicStreamOffset offset,
+ const char* data_buffer,
+ QuicPacketLength data_length);
+};
+static_assert(sizeof(QuicStreamFrame) <= 64,
+ "Keep the QuicStreamFrame size to a cacheline.");
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_FRAMES_QUIC_STREAM_FRAME_H_
diff --git a/quic/core/frames/quic_stream_id_blocked_frame.cc b/quic/core/frames/quic_stream_id_blocked_frame.cc
new file mode 100644
index 0000000..627ad2a
--- /dev/null
+++ b/quic/core/frames/quic_stream_id_blocked_frame.cc
@@ -0,0 +1,27 @@
+// 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_stream_id_blocked_frame.h"
+
+namespace quic {
+
+QuicStreamIdBlockedFrame::QuicStreamIdBlockedFrame()
+ : QuicInlinedFrame(STREAM_ID_BLOCKED_FRAME),
+ control_frame_id(kInvalidControlFrameId) {}
+
+QuicStreamIdBlockedFrame::QuicStreamIdBlockedFrame(
+ QuicControlFrameId control_frame_id,
+ QuicStreamId stream_id)
+ : QuicInlinedFrame(STREAM_ID_BLOCKED_FRAME),
+ control_frame_id(control_frame_id),
+ stream_id(stream_id) {}
+
+std::ostream& operator<<(std::ostream& os,
+ const QuicStreamIdBlockedFrame& frame) {
+ os << "{ control_frame_id: " << frame.control_frame_id
+ << ", stream id: " << frame.stream_id << " }\n";
+ return os;
+}
+
+} // namespace quic
diff --git a/quic/core/frames/quic_stream_id_blocked_frame.h b/quic/core/frames/quic_stream_id_blocked_frame.h
new file mode 100644
index 0000000..f9ccca2
--- /dev/null
+++ b/quic/core/frames/quic_stream_id_blocked_frame.h
@@ -0,0 +1,40 @@
+// 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.
+
+#ifndef QUICHE_QUIC_CORE_FRAMES_QUIC_STREAM_ID_BLOCKED_FRAME_H_
+#define QUICHE_QUIC_CORE_FRAMES_QUIC_STREAM_ID_BLOCKED_FRAME_H_
+
+#include <ostream>
+
+#include "net/third_party/quiche/src/quic/core/frames/quic_inlined_frame.h"
+#include "net/third_party/quiche/src/quic/core/quic_constants.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+
+namespace quic {
+
+// IETF format STREAM_ID_BLOCKED frame.
+// The sender uses this to inform the peer that the sender wished to
+// open a new stream but was blocked from doing so due due to the
+// maximum stream ID limit set by the peer (via a MAX_STREAM_ID frame)
+struct QUIC_EXPORT_PRIVATE QuicStreamIdBlockedFrame
+ : public QuicInlinedFrame<QuicStreamIdBlockedFrame> {
+ QuicStreamIdBlockedFrame();
+ QuicStreamIdBlockedFrame(QuicControlFrameId control_frame_id,
+ QuicStreamId stream_id);
+
+ friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(
+ std::ostream& os,
+ const QuicStreamIdBlockedFrame& frame);
+
+ // A unique identifier of this control frame. 0 when this frame is received,
+ // and non-zero when sent.
+ QuicControlFrameId control_frame_id;
+
+ QuicStreamId stream_id;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_FRAMES_QUIC_STREAM_ID_BLOCKED_FRAME_H_
diff --git a/quic/core/frames/quic_window_update_frame.cc b/quic/core/frames/quic_window_update_frame.cc
new file mode 100644
index 0000000..07e3168
--- /dev/null
+++ b/quic/core/frames/quic_window_update_frame.cc
@@ -0,0 +1,29 @@
+// 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_window_update_frame.h"
+#include "net/third_party/quiche/src/quic/core/quic_constants.h"
+
+namespace quic {
+
+QuicWindowUpdateFrame::QuicWindowUpdateFrame()
+ : control_frame_id(kInvalidControlFrameId) {}
+
+QuicWindowUpdateFrame::QuicWindowUpdateFrame(
+ QuicControlFrameId control_frame_id,
+ QuicStreamId stream_id,
+ QuicStreamOffset byte_offset)
+ : control_frame_id(control_frame_id),
+ stream_id(stream_id),
+ byte_offset(byte_offset) {}
+
+std::ostream& operator<<(std::ostream& os,
+ const QuicWindowUpdateFrame& window_update_frame) {
+ os << "{ control_frame_id: " << window_update_frame.control_frame_id
+ << ", stream_id: " << window_update_frame.stream_id
+ << ", byte_offset: " << window_update_frame.byte_offset << " }\n";
+ return os;
+}
+
+} // namespace quic
diff --git a/quic/core/frames/quic_window_update_frame.h b/quic/core/frames/quic_window_update_frame.h
new file mode 100644
index 0000000..73163ce
--- /dev/null
+++ b/quic/core/frames/quic_window_update_frame.h
@@ -0,0 +1,48 @@
+// 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.
+
+#ifndef QUICHE_QUIC_CORE_FRAMES_QUIC_WINDOW_UPDATE_FRAME_H_
+#define QUICHE_QUIC_CORE_FRAMES_QUIC_WINDOW_UPDATE_FRAME_H_
+
+#include <ostream>
+
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+
+namespace quic {
+
+// Flow control updates per-stream and at the connection level.
+// Based on SPDY's WINDOW_UPDATE frame, but uses an absolute byte offset rather
+// than a window delta.
+// TODO(rjshade): A possible future optimization is to make stream_id and
+// byte_offset variable length, similar to stream frames.
+struct QUIC_EXPORT_PRIVATE QuicWindowUpdateFrame {
+ QuicWindowUpdateFrame();
+ QuicWindowUpdateFrame(QuicControlFrameId control_frame_id,
+ QuicStreamId stream_id,
+ QuicStreamOffset byte_offset);
+
+ friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(
+ std::ostream& os,
+ const QuicWindowUpdateFrame& w);
+
+ // A unique identifier of this control frame. 0 when this frame is received,
+ // and non-zero when sent.
+ QuicControlFrameId control_frame_id;
+
+ // The stream this frame applies to. 0 is a special case meaning the overall
+ // connection rather than a specific stream.
+ QuicStreamId stream_id;
+
+ // Byte offset in the stream or connection. The receiver of this frame must
+ // not send data which would result in this offset being exceeded.
+ //
+ // TODO(fkastenholz): Rename this to max_data and change the type to
+ // QuicByteCount because the IETF defines this as the "maximum
+ // amount of data that can be sent".
+ QuicStreamOffset byte_offset;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_FRAMES_QUIC_WINDOW_UPDATE_FRAME_H_