|  | // Copyright (c) 2012 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/quic/quic_protocol.h" | 
|  |  | 
|  | #include "base/stl_util.h" | 
|  | #include "net/quic/quic_flags.h" | 
|  | #include "net/quic/quic_utils.h" | 
|  |  | 
|  | using base::StringPiece; | 
|  | using std::map; | 
|  | using std::numeric_limits; | 
|  | using std::ostream; | 
|  | using std::string; | 
|  |  | 
|  | namespace net { | 
|  |  | 
|  | size_t GetPacketHeaderSize(const QuicPacketHeader& header) { | 
|  | return GetPacketHeaderSize( | 
|  | header.public_header.connection_id_length, | 
|  | header.public_header.version_flag, header.public_header.multipath_flag, | 
|  | header.public_header.packet_number_length, header.is_in_fec_group); | 
|  | } | 
|  |  | 
|  | size_t GetPacketHeaderSize(QuicConnectionIdLength connection_id_length, | 
|  | bool include_version, | 
|  | bool include_path_id, | 
|  | QuicPacketNumberLength packet_number_length, | 
|  | InFecGroup is_in_fec_group) { | 
|  | return kPublicFlagsSize + connection_id_length + | 
|  | (include_version ? kQuicVersionSize : 0) + | 
|  | (include_path_id ? kQuicPathIdSize : 0) + packet_number_length + | 
|  | kPrivateFlagsSize + | 
|  | (is_in_fec_group == IN_FEC_GROUP ? kFecGroupSize : 0); | 
|  | } | 
|  |  | 
|  | size_t GetStartOfFecProtectedData(QuicConnectionIdLength connection_id_length, | 
|  | bool include_version, | 
|  | QuicPacketNumberLength packet_number_length) { | 
|  | return GetPacketHeaderSize(connection_id_length, include_version, | 
|  | /*include_path_id=*/false, packet_number_length, | 
|  | IN_FEC_GROUP); | 
|  | } | 
|  |  | 
|  | size_t GetStartOfEncryptedData(QuicConnectionIdLength connection_id_length, | 
|  | bool include_version, | 
|  | QuicPacketNumberLength packet_number_length) { | 
|  | // Don't include the fec size, since encryption starts before private flags. | 
|  | return GetPacketHeaderSize(connection_id_length, include_version, | 
|  | /*include_path_id=*/false, packet_number_length, | 
|  | NOT_IN_FEC_GROUP) - | 
|  | kPrivateFlagsSize; | 
|  | } | 
|  |  | 
|  | QuicPacketPublicHeader::QuicPacketPublicHeader() | 
|  | : connection_id(0), | 
|  | connection_id_length(PACKET_8BYTE_CONNECTION_ID), | 
|  | multipath_flag(false), | 
|  | reset_flag(false), | 
|  | version_flag(false), | 
|  | packet_number_length(PACKET_6BYTE_PACKET_NUMBER) {} | 
|  |  | 
|  | QuicPacketPublicHeader::QuicPacketPublicHeader( | 
|  | const QuicPacketPublicHeader& other) | 
|  | : connection_id(other.connection_id), | 
|  | connection_id_length(other.connection_id_length), | 
|  | multipath_flag(other.multipath_flag), | 
|  | reset_flag(other.reset_flag), | 
|  | version_flag(other.version_flag), | 
|  | packet_number_length(other.packet_number_length), | 
|  | versions(other.versions) {} | 
|  |  | 
|  | QuicPacketPublicHeader::~QuicPacketPublicHeader() {} | 
|  |  | 
|  | QuicPacketHeader::QuicPacketHeader() | 
|  | : path_id(0), | 
|  | packet_number(0), | 
|  | fec_flag(false), | 
|  | entropy_flag(false), | 
|  | entropy_hash(0), | 
|  | is_in_fec_group(NOT_IN_FEC_GROUP), | 
|  | fec_group(0) {} | 
|  |  | 
|  | QuicPacketHeader::QuicPacketHeader(const QuicPacketPublicHeader& header) | 
|  | : public_header(header), | 
|  | path_id(0), | 
|  | packet_number(0), | 
|  | fec_flag(false), | 
|  | entropy_flag(false), | 
|  | entropy_hash(0), | 
|  | is_in_fec_group(NOT_IN_FEC_GROUP), | 
|  | fec_group(0) {} | 
|  |  | 
|  | QuicPublicResetPacket::QuicPublicResetPacket() | 
|  | : nonce_proof(0), rejected_packet_number(0) {} | 
|  |  | 
|  | QuicPublicResetPacket::QuicPublicResetPacket( | 
|  | const QuicPacketPublicHeader& header) | 
|  | : public_header(header), nonce_proof(0), rejected_packet_number(0) {} | 
|  |  | 
|  | void StreamBufferDeleter::operator()(char* buf) const { | 
|  | delete[] buf; | 
|  | } | 
|  |  | 
|  | UniqueStreamBuffer NewStreamBuffer(size_t size) { | 
|  | return UniqueStreamBuffer(new char[size]); | 
|  | } | 
|  |  | 
|  | QuicStreamFrame::QuicStreamFrame() | 
|  | : stream_id(0), | 
|  | fin(false), | 
|  | frame_length(0), | 
|  | frame_buffer(nullptr), | 
|  | offset(0), | 
|  | buffer(nullptr) {} | 
|  |  | 
|  | QuicStreamFrame::QuicStreamFrame(QuicStreamId stream_id, | 
|  | bool fin, | 
|  | QuicStreamOffset offset, | 
|  | StringPiece data) | 
|  | : QuicStreamFrame(stream_id, | 
|  | fin, | 
|  | offset, | 
|  | data.data(), | 
|  | data.length(), | 
|  | nullptr) {} | 
|  |  | 
|  | QuicStreamFrame::QuicStreamFrame(QuicStreamId stream_id, | 
|  | bool fin, | 
|  | QuicStreamOffset offset, | 
|  | QuicPacketLength frame_length, | 
|  | UniqueStreamBuffer buffer) | 
|  | : QuicStreamFrame(stream_id, | 
|  | fin, | 
|  | offset, | 
|  | nullptr, | 
|  | frame_length, | 
|  | std::move(buffer)) { | 
|  | DCHECK(this->buffer != nullptr); | 
|  | DCHECK_EQ(frame_buffer, this->buffer.get()); | 
|  | } | 
|  |  | 
|  | QuicStreamFrame::QuicStreamFrame(QuicStreamId stream_id, | 
|  | bool fin, | 
|  | QuicStreamOffset offset, | 
|  | const char* frame_buffer, | 
|  | QuicPacketLength frame_length, | 
|  | UniqueStreamBuffer buffer) | 
|  | : stream_id(stream_id), | 
|  | fin(fin), | 
|  | frame_length(frame_length), | 
|  | frame_buffer(frame_buffer), | 
|  | offset(offset), | 
|  | buffer(std::move(buffer)) { | 
|  | if (this->buffer != nullptr) { | 
|  | this->frame_buffer = this->buffer.get(); | 
|  | } | 
|  | } | 
|  |  | 
|  | QuicStreamFrame::~QuicStreamFrame() {} | 
|  |  | 
|  | uint32 MakeQuicTag(char a, char b, char c, char d) { | 
|  | return static_cast<uint32>(a) | | 
|  | static_cast<uint32>(b) << 8 | | 
|  | static_cast<uint32>(c) << 16 | | 
|  | static_cast<uint32>(d) << 24; | 
|  | } | 
|  |  | 
|  | bool ContainsQuicTag(const QuicTagVector& tag_vector, QuicTag tag) { | 
|  | return std::find(tag_vector.begin(), tag_vector.end(),  tag) | 
|  | != tag_vector.end(); | 
|  | } | 
|  |  | 
|  | QuicVersionVector QuicSupportedVersions() { | 
|  | QuicVersionVector supported_versions; | 
|  | for (size_t i = 0; i < arraysize(kSupportedQuicVersions); ++i) { | 
|  | supported_versions.push_back(kSupportedQuicVersions[i]); | 
|  | } | 
|  | return supported_versions; | 
|  | } | 
|  |  | 
|  | QuicTag QuicVersionToQuicTag(const QuicVersion version) { | 
|  | switch (version) { | 
|  | case QUIC_VERSION_25: | 
|  | return MakeQuicTag('Q', '0', '2', '5'); | 
|  | case QUIC_VERSION_26: | 
|  | return MakeQuicTag('Q', '0', '2', '6'); | 
|  | case QUIC_VERSION_27: | 
|  | return MakeQuicTag('Q', '0', '2', '7'); | 
|  | case QUIC_VERSION_28: | 
|  | return MakeQuicTag('Q', '0', '2', '8'); | 
|  | case QUIC_VERSION_29: | 
|  | return MakeQuicTag('Q', '0', '2', '9'); | 
|  | case QUIC_VERSION_30: | 
|  | return MakeQuicTag('Q', '0', '3', '0'); | 
|  | default: | 
|  | // This shold be an ERROR because we should never attempt to convert an | 
|  | // invalid QuicVersion to be written to the wire. | 
|  | LOG(ERROR) << "Unsupported QuicVersion: " << version; | 
|  | return 0; | 
|  | } | 
|  | } | 
|  |  | 
|  | QuicVersion QuicTagToQuicVersion(const QuicTag version_tag) { | 
|  | for (size_t i = 0; i < arraysize(kSupportedQuicVersions); ++i) { | 
|  | if (version_tag == QuicVersionToQuicTag(kSupportedQuicVersions[i])) { | 
|  | return kSupportedQuicVersions[i]; | 
|  | } | 
|  | } | 
|  | // Reading from the client so this should not be considered an ERROR. | 
|  | DVLOG(1) << "Unsupported QuicTag version: " | 
|  | << QuicUtils::TagToString(version_tag); | 
|  | return QUIC_VERSION_UNSUPPORTED; | 
|  | } | 
|  |  | 
|  | #define RETURN_STRING_LITERAL(x) \ | 
|  | case x: \ | 
|  | return #x | 
|  |  | 
|  | string QuicVersionToString(const QuicVersion version) { | 
|  | switch (version) { | 
|  | RETURN_STRING_LITERAL(QUIC_VERSION_25); | 
|  | RETURN_STRING_LITERAL(QUIC_VERSION_26); | 
|  | RETURN_STRING_LITERAL(QUIC_VERSION_27); | 
|  | RETURN_STRING_LITERAL(QUIC_VERSION_28); | 
|  | RETURN_STRING_LITERAL(QUIC_VERSION_29); | 
|  | RETURN_STRING_LITERAL(QUIC_VERSION_30); | 
|  | default: | 
|  | return "QUIC_VERSION_UNSUPPORTED"; | 
|  | } | 
|  | } | 
|  |  | 
|  | string QuicVersionVectorToString(const QuicVersionVector& versions) { | 
|  | string result = ""; | 
|  | for (size_t i = 0; i < versions.size(); ++i) { | 
|  | if (i != 0) { | 
|  | result.append(","); | 
|  | } | 
|  | result.append(QuicVersionToString(versions[i])); | 
|  | } | 
|  | return result; | 
|  | } | 
|  |  | 
|  | ostream& operator<<(ostream& os, const Perspective& s) { | 
|  | if (s == Perspective::IS_SERVER) { | 
|  | os << "IS_SERVER"; | 
|  | } else { | 
|  | os << "IS_CLIENT"; | 
|  | } | 
|  | return os; | 
|  | } | 
|  |  | 
|  | ostream& operator<<(ostream& os, const QuicPacketHeader& header) { | 
|  | os << "{ connection_id: " << header.public_header.connection_id | 
|  | << ", connection_id_length:" << header.public_header.connection_id_length | 
|  | << ", packet_number_length:" << header.public_header.packet_number_length | 
|  | << ", multipath_flag: " << header.public_header.multipath_flag | 
|  | << ", reset_flag: " << header.public_header.reset_flag | 
|  | << ", version_flag: " << header.public_header.version_flag; | 
|  | if (header.public_header.version_flag) { | 
|  | os << " version: "; | 
|  | for (size_t i = 0; i < header.public_header.versions.size(); ++i) { | 
|  | os << header.public_header.versions[i] << " "; | 
|  | } | 
|  | } | 
|  | os << ", fec_flag: " << header.fec_flag | 
|  | << ", entropy_flag: " << header.entropy_flag | 
|  | << ", entropy hash: " << static_cast<int>(header.entropy_hash) | 
|  | << ", path_id: " << header.path_id | 
|  | << ", packet_number: " << header.packet_number | 
|  | << ", is_in_fec_group:" << header.is_in_fec_group | 
|  | << ", fec_group: " << header.fec_group << "}\n"; | 
|  | return os; | 
|  | } | 
|  |  | 
|  | bool IsAwaitingPacket(const QuicAckFrame& ack_frame, | 
|  | QuicPacketNumber packet_number) { | 
|  | return packet_number > ack_frame.largest_observed || | 
|  | ack_frame.missing_packets.Contains(packet_number); | 
|  | } | 
|  |  | 
|  | QuicStopWaitingFrame::QuicStopWaitingFrame() | 
|  | : entropy_hash(0), | 
|  | least_unacked(0) { | 
|  | } | 
|  |  | 
|  | QuicStopWaitingFrame::~QuicStopWaitingFrame() {} | 
|  |  | 
|  | QuicAckFrame::QuicAckFrame() | 
|  | : entropy_hash(0), | 
|  | is_truncated(false), | 
|  | largest_observed(0), | 
|  | delta_time_largest_observed(QuicTime::Delta::Infinite()), | 
|  | latest_revived_packet(0) {} | 
|  |  | 
|  | QuicAckFrame::~QuicAckFrame() {} | 
|  |  | 
|  | QuicRstStreamErrorCode AdjustErrorForVersion(QuicRstStreamErrorCode error_code, | 
|  | QuicVersion /*version*/) { | 
|  | return error_code; | 
|  | } | 
|  |  | 
|  | QuicRstStreamFrame::QuicRstStreamFrame() | 
|  | : stream_id(0), error_code(QUIC_STREAM_NO_ERROR), byte_offset(0) {} | 
|  |  | 
|  | QuicRstStreamFrame::QuicRstStreamFrame(QuicStreamId stream_id, | 
|  | QuicRstStreamErrorCode error_code, | 
|  | QuicStreamOffset bytes_written) | 
|  | : stream_id(stream_id), | 
|  | error_code(error_code), | 
|  | byte_offset(bytes_written) { | 
|  | DCHECK_LE(error_code, numeric_limits<uint8>::max()); | 
|  | } | 
|  |  | 
|  | QuicConnectionCloseFrame::QuicConnectionCloseFrame() | 
|  | : error_code(QUIC_NO_ERROR) { | 
|  | } | 
|  |  | 
|  | QuicFrame::QuicFrame() {} | 
|  |  | 
|  | QuicFrame::QuicFrame(QuicPaddingFrame padding_frame) | 
|  | : type(PADDING_FRAME), padding_frame(padding_frame) {} | 
|  |  | 
|  | QuicFrame::QuicFrame(QuicStreamFrame* stream_frame) | 
|  | : type(STREAM_FRAME), stream_frame(stream_frame) {} | 
|  |  | 
|  | QuicFrame::QuicFrame(QuicAckFrame* frame) : type(ACK_FRAME), ack_frame(frame) {} | 
|  |  | 
|  | QuicFrame::QuicFrame(QuicMtuDiscoveryFrame frame) | 
|  | : type(MTU_DISCOVERY_FRAME), mtu_discovery_frame(frame) {} | 
|  |  | 
|  | QuicFrame::QuicFrame(QuicStopWaitingFrame* frame) | 
|  | : type(STOP_WAITING_FRAME), stop_waiting_frame(frame) {} | 
|  |  | 
|  | QuicFrame::QuicFrame(QuicPingFrame frame) | 
|  | : type(PING_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) {} | 
|  |  | 
|  | ostream& operator<<(ostream& os, const QuicStopWaitingFrame& sent_info) { | 
|  | os << "entropy_hash: " << static_cast<int>(sent_info.entropy_hash) | 
|  | << " least_unacked: " << sent_info.least_unacked; | 
|  | return os; | 
|  | } | 
|  |  | 
|  | PacketNumberQueue::const_iterator::const_iterator( | 
|  | IntervalSet<QuicPacketNumber>::const_iterator interval_set_iter, | 
|  | QuicPacketNumber first, | 
|  | QuicPacketNumber last) | 
|  | : interval_set_iter_(interval_set_iter), current_(first), last_(last) {} | 
|  |  | 
|  | PacketNumberQueue::const_iterator::const_iterator(const const_iterator& other) = | 
|  | default; | 
|  | // TODO(rtenneti): on windows RValue reference gives errors. | 
|  | // PacketNumberQueue::const_iterator::const_iterator(const_iterator&& other) = | 
|  | //    default; | 
|  | PacketNumberQueue::const_iterator::~const_iterator() {} | 
|  |  | 
|  | PacketNumberQueue::const_iterator& PacketNumberQueue::const_iterator::operator=( | 
|  | const const_iterator& other) = default; | 
|  | // TODO(rtenneti): on windows RValue reference gives errors. | 
|  | // PacketNumberQueue::const_iterator& | 
|  | // PacketNumberQueue::const_iterator::operator=( | 
|  | //    const_iterator&& other) = default; | 
|  |  | 
|  | bool PacketNumberQueue::const_iterator::operator!=( | 
|  | const const_iterator& other) const { | 
|  | return current_ != other.current_; | 
|  | } | 
|  |  | 
|  | bool PacketNumberQueue::const_iterator::operator==( | 
|  | const const_iterator& other) const { | 
|  | return current_ == other.current_; | 
|  | } | 
|  |  | 
|  | PacketNumberQueue::const_iterator::value_type | 
|  | PacketNumberQueue::const_iterator:: | 
|  | operator*() const { | 
|  | return current_; | 
|  | } | 
|  |  | 
|  | PacketNumberQueue::const_iterator& PacketNumberQueue::const_iterator:: | 
|  | operator++() { | 
|  | ++current_; | 
|  | if (current_ < last_) { | 
|  | if (current_ >= interval_set_iter_->max()) { | 
|  | ++interval_set_iter_; | 
|  | current_ = interval_set_iter_->min(); | 
|  | } | 
|  | } else { | 
|  | current_ = last_; | 
|  | } | 
|  | return *this; | 
|  | } | 
|  |  | 
|  | PacketNumberQueue::const_iterator PacketNumberQueue::const_iterator::operator++( | 
|  | int /* postincrement */) { | 
|  | PacketNumberQueue::const_iterator preincrement(*this); | 
|  | operator++(); | 
|  | return preincrement; | 
|  | } | 
|  |  | 
|  | PacketNumberQueue::PacketNumberQueue() = default; | 
|  | PacketNumberQueue::PacketNumberQueue(const PacketNumberQueue& other) = default; | 
|  | // TODO(rtenneti): on windows RValue reference gives errors. | 
|  | // PacketNumberQueue::PacketNumberQueue(PacketNumberQueue&& other) = default; | 
|  | PacketNumberQueue::~PacketNumberQueue() {} | 
|  |  | 
|  | PacketNumberQueue& PacketNumberQueue::operator=( | 
|  | const PacketNumberQueue& other) = default; | 
|  | // TODO(rtenneti): on windows RValue reference gives errors. | 
|  | // PacketNumberQueue& PacketNumberQueue::operator=(PacketNumberQueue&& other) = | 
|  | //    default; | 
|  |  | 
|  | void PacketNumberQueue::Add(QuicPacketNumber packet_number) { | 
|  | packet_number_intervals_.Add(packet_number, packet_number + 1); | 
|  | } | 
|  |  | 
|  | void PacketNumberQueue::Add(QuicPacketNumber lower, QuicPacketNumber higher) { | 
|  | packet_number_intervals_.Add(lower, higher); | 
|  | } | 
|  |  | 
|  | void PacketNumberQueue::Remove(QuicPacketNumber packet_number) { | 
|  | packet_number_intervals_.Difference(packet_number, packet_number + 1); | 
|  | } | 
|  |  | 
|  | bool PacketNumberQueue::RemoveUpTo(QuicPacketNumber higher) { | 
|  | if (Empty()) { | 
|  | return false; | 
|  | } | 
|  | const QuicPacketNumber old_min = Min(); | 
|  | packet_number_intervals_.Difference(0, higher); | 
|  | return Empty() || old_min != Min(); | 
|  | } | 
|  |  | 
|  | bool PacketNumberQueue::Contains(QuicPacketNumber packet_number) const { | 
|  | return packet_number_intervals_.Contains(packet_number); | 
|  | } | 
|  |  | 
|  | bool PacketNumberQueue::Empty() const { | 
|  | return packet_number_intervals_.Empty(); | 
|  | } | 
|  |  | 
|  | QuicPacketNumber PacketNumberQueue::Min() const { | 
|  | DCHECK(!Empty()); | 
|  | return packet_number_intervals_.begin()->min(); | 
|  | } | 
|  |  | 
|  | QuicPacketNumber PacketNumberQueue::Max() const { | 
|  | DCHECK(!Empty()); | 
|  | return packet_number_intervals_.rbegin()->max() - 1; | 
|  | } | 
|  |  | 
|  | size_t PacketNumberQueue::NumPacketsSlow() const { | 
|  | size_t num_packets = 0; | 
|  | for (const auto& interval : packet_number_intervals_) { | 
|  | num_packets += interval.Length(); | 
|  | } | 
|  | return num_packets; | 
|  | } | 
|  |  | 
|  | PacketNumberQueue::const_iterator PacketNumberQueue::begin() const { | 
|  | QuicPacketNumber first; | 
|  | QuicPacketNumber last; | 
|  | if (packet_number_intervals_.Empty()) { | 
|  | first = 0; | 
|  | last = 0; | 
|  | } else { | 
|  | first = packet_number_intervals_.begin()->min(); | 
|  | last = packet_number_intervals_.rbegin()->max(); | 
|  | } | 
|  | return const_iterator(packet_number_intervals_.begin(), first, last); | 
|  | } | 
|  |  | 
|  | PacketNumberQueue::const_iterator PacketNumberQueue::end() const { | 
|  | QuicPacketNumber last = packet_number_intervals_.Empty() | 
|  | ? 0 | 
|  | : packet_number_intervals_.rbegin()->max(); | 
|  | return const_iterator(packet_number_intervals_.end(), last, last); | 
|  | } | 
|  |  | 
|  | PacketNumberQueue::const_iterator PacketNumberQueue::lower_bound( | 
|  | QuicPacketNumber packet_number) const { | 
|  | QuicPacketNumber first; | 
|  | QuicPacketNumber last; | 
|  | if (packet_number_intervals_.Empty()) { | 
|  | first = 0; | 
|  | last = 0; | 
|  | return const_iterator(packet_number_intervals_.begin(), first, last); | 
|  | } | 
|  | if (!packet_number_intervals_.Contains(packet_number)) { | 
|  | return end(); | 
|  | } | 
|  | IntervalSet<QuicPacketNumber>::const_iterator it = | 
|  | packet_number_intervals_.Find(packet_number); | 
|  | first = packet_number; | 
|  | last = packet_number_intervals_.rbegin()->max(); | 
|  | return const_iterator(it, first, last); | 
|  | } | 
|  |  | 
|  | ostream& operator<<(ostream& os, const PacketNumberQueue& q) { | 
|  | for (QuicPacketNumber packet_number : q) { | 
|  | os << packet_number << " "; | 
|  | } | 
|  | return os; | 
|  | } | 
|  |  | 
|  | ostream& operator<<(ostream& os, const QuicAckFrame& ack_frame) { | 
|  | os << "entropy_hash: " << static_cast<int>(ack_frame.entropy_hash) | 
|  | << " largest_observed: " << ack_frame.largest_observed | 
|  | << " delta_time_largest_observed: " | 
|  | << ack_frame.delta_time_largest_observed.ToMicroseconds() | 
|  | << " missing_packets: [ " << ack_frame.missing_packets | 
|  | << " ] is_truncated: " << ack_frame.is_truncated | 
|  | << " revived_packet: " << ack_frame.latest_revived_packet | 
|  | << " received_packets: [ "; | 
|  | for (const std::pair<QuicPacketNumber, QuicTime>& p : | 
|  | ack_frame.received_packet_times) { | 
|  | os << p.first << " at " << p.second.ToDebuggingValue() << " "; | 
|  | } | 
|  | os << " ]"; | 
|  | return os; | 
|  | } | 
|  |  | 
|  | ostream& operator<<(ostream& os, const QuicFrame& frame) { | 
|  | switch (frame.type) { | 
|  | case PADDING_FRAME: { | 
|  | os << "type { 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 } "; | 
|  | break; | 
|  | } | 
|  | case MTU_DISCOVERY_FRAME: { | 
|  | os << "type { MTU_DISCOVERY_FRAME } "; | 
|  | break; | 
|  | } | 
|  | default: { | 
|  | LOG(ERROR) << "Unknown frame type: " << frame.type; | 
|  | break; | 
|  | } | 
|  | } | 
|  | return os; | 
|  | } | 
|  |  | 
|  | ostream& operator<<(ostream& os, const QuicRstStreamFrame& rst_frame) { | 
|  | os << "stream_id { " << rst_frame.stream_id << " } " | 
|  | << "error_code { " << rst_frame.error_code << " }\n"; | 
|  | return os; | 
|  | } | 
|  |  | 
|  | ostream& operator<<(ostream& os, | 
|  | const QuicConnectionCloseFrame& connection_close_frame) { | 
|  | os << "error_code { " << connection_close_frame.error_code << " } " | 
|  | << "error_details { " << connection_close_frame.error_details << " }\n"; | 
|  | return os; | 
|  | } | 
|  |  | 
|  | ostream& operator<<(ostream& os, const QuicGoAwayFrame& goaway_frame) { | 
|  | os << "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; | 
|  | } | 
|  |  | 
|  | ostream& operator<<(ostream& os, | 
|  | const QuicWindowUpdateFrame& window_update_frame) { | 
|  | os << "stream_id { " << window_update_frame.stream_id << " } " | 
|  | << "byte_offset { " << window_update_frame.byte_offset << " }\n"; | 
|  | return os; | 
|  | } | 
|  |  | 
|  | ostream& operator<<(ostream& os, const QuicBlockedFrame& blocked_frame) { | 
|  | os << "stream_id { " << blocked_frame.stream_id << " }\n"; | 
|  | return os; | 
|  | } | 
|  |  | 
|  | ostream& operator<<(ostream& os, const QuicStreamFrame& stream_frame) { | 
|  | os << "stream_id { " << stream_frame.stream_id << " } " | 
|  | << "fin { " << stream_frame.fin << " } " | 
|  | << "offset { " << stream_frame.offset << " } " | 
|  | << "length { " << stream_frame.frame_length << " }\n"; | 
|  | return os; | 
|  | } | 
|  |  | 
|  | QuicGoAwayFrame::QuicGoAwayFrame() | 
|  | : error_code(QUIC_NO_ERROR), | 
|  | last_good_stream_id(0) { | 
|  | } | 
|  |  | 
|  | QuicGoAwayFrame::QuicGoAwayFrame(QuicErrorCode error_code, | 
|  | QuicStreamId last_good_stream_id, | 
|  | const string& reason) | 
|  | : error_code(error_code), | 
|  | last_good_stream_id(last_good_stream_id), | 
|  | reason_phrase(reason) { | 
|  | DCHECK_LE(error_code, numeric_limits<uint8>::max()); | 
|  | } | 
|  |  | 
|  | QuicData::QuicData(const char* buffer, | 
|  | size_t length) | 
|  | : buffer_(buffer), | 
|  | length_(length), | 
|  | owns_buffer_(false) { | 
|  | } | 
|  |  | 
|  | QuicData::QuicData(char* buffer, | 
|  | size_t length, | 
|  | bool owns_buffer) | 
|  | : buffer_(buffer), | 
|  | length_(length), | 
|  | owns_buffer_(owns_buffer) { | 
|  | } | 
|  |  | 
|  | QuicData::~QuicData() { | 
|  | if (owns_buffer_) { | 
|  | delete [] const_cast<char*>(buffer_); | 
|  | } | 
|  | } | 
|  |  | 
|  | QuicWindowUpdateFrame::QuicWindowUpdateFrame(QuicStreamId stream_id, | 
|  | QuicStreamOffset byte_offset) | 
|  | : stream_id(stream_id), | 
|  | byte_offset(byte_offset) {} | 
|  |  | 
|  | QuicBlockedFrame::QuicBlockedFrame(QuicStreamId stream_id) | 
|  | : stream_id(stream_id) {} | 
|  |  | 
|  | QuicPacket::QuicPacket(char* buffer, | 
|  | size_t length, | 
|  | bool owns_buffer, | 
|  | QuicConnectionIdLength connection_id_length, | 
|  | bool includes_version, | 
|  | QuicPacketNumberLength packet_number_length) | 
|  | : QuicData(buffer, length, owns_buffer), | 
|  | buffer_(buffer), | 
|  | connection_id_length_(connection_id_length), | 
|  | includes_version_(includes_version), | 
|  | packet_number_length_(packet_number_length) {} | 
|  |  | 
|  | QuicEncryptedPacket::QuicEncryptedPacket(const char* buffer, | 
|  | size_t length) | 
|  | : QuicData(buffer, length) { | 
|  | } | 
|  |  | 
|  | QuicEncryptedPacket::QuicEncryptedPacket(char* buffer, | 
|  | size_t length, | 
|  | bool owns_buffer) | 
|  | : QuicData(buffer, length, owns_buffer) { | 
|  | } | 
|  |  | 
|  | StringPiece QuicPacket::FecProtectedData() const { | 
|  | const size_t start_of_fec = GetStartOfFecProtectedData( | 
|  | connection_id_length_, includes_version_, packet_number_length_); | 
|  | return StringPiece(data() + start_of_fec, length() - start_of_fec); | 
|  | } | 
|  |  | 
|  | StringPiece QuicPacket::AssociatedData() const { | 
|  | return StringPiece( | 
|  | data() + kStartOfHashData, | 
|  | GetStartOfEncryptedData(connection_id_length_, includes_version_, | 
|  | packet_number_length_) - | 
|  | kStartOfHashData); | 
|  | } | 
|  |  | 
|  | StringPiece QuicPacket::BeforePlaintext() const { | 
|  | return StringPiece( | 
|  | data(), GetStartOfEncryptedData(connection_id_length_, includes_version_, | 
|  | packet_number_length_)); | 
|  | } | 
|  |  | 
|  | StringPiece QuicPacket::Plaintext() const { | 
|  | const size_t start_of_encrypted_data = GetStartOfEncryptedData( | 
|  | connection_id_length_, includes_version_, packet_number_length_); | 
|  | return StringPiece(data() + start_of_encrypted_data, | 
|  | length() - start_of_encrypted_data); | 
|  | } | 
|  |  | 
|  | RetransmittableFrames::RetransmittableFrames() | 
|  | : has_crypto_handshake_(NOT_HANDSHAKE), needs_padding_(false) { | 
|  | // TODO(ianswett): Consider using an inlined vector instead, since this | 
|  | // is very frequently a single frame. | 
|  | frames_.reserve(2); | 
|  | } | 
|  |  | 
|  | RetransmittableFrames::~RetransmittableFrames() { | 
|  | for (QuicFrame& frame : frames_) { | 
|  | 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: | 
|  | break; | 
|  | case STREAM_FRAME: | 
|  | delete frame.stream_frame; | 
|  | break; | 
|  | case ACK_FRAME: | 
|  | delete frame.ack_frame; | 
|  | break; | 
|  | case STOP_WAITING_FRAME: | 
|  | delete frame.stop_waiting_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 WINDOW_UPDATE_FRAME: | 
|  | delete frame.window_update_frame; | 
|  | break; | 
|  | case BLOCKED_FRAME: | 
|  | delete frame.blocked_frame; | 
|  | break; | 
|  | case NUM_FRAME_TYPES: | 
|  | DCHECK(false) << "Cannot delete type: " << frame.type; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | const QuicFrame& RetransmittableFrames::AddFrame(const QuicFrame& frame) { | 
|  | if (frame.type == STREAM_FRAME && | 
|  | frame.stream_frame->stream_id == kCryptoStreamId) { | 
|  | has_crypto_handshake_ = IS_HANDSHAKE; | 
|  | } | 
|  | frames_.push_back(frame); | 
|  | return frame; | 
|  | } | 
|  |  | 
|  | void RetransmittableFrames::RemoveFramesForStream(QuicStreamId stream_id) { | 
|  | QuicFrames::iterator it = frames_.begin(); | 
|  | while (it != frames_.end()) { | 
|  | if (it->type != STREAM_FRAME || it->stream_frame->stream_id != stream_id) { | 
|  | ++it; | 
|  | continue; | 
|  | } | 
|  | delete it->stream_frame; | 
|  | it = frames_.erase(it); | 
|  | } | 
|  | } | 
|  |  | 
|  | AckListenerWrapper::AckListenerWrapper(QuicAckListenerInterface* listener, | 
|  | QuicPacketLength data_length) | 
|  | : ack_listener(listener), length(data_length) { | 
|  | DCHECK(listener != nullptr); | 
|  | } | 
|  |  | 
|  | AckListenerWrapper::~AckListenerWrapper() {} | 
|  |  | 
|  | SerializedPacket::SerializedPacket( | 
|  | QuicPacketNumber packet_number, | 
|  | QuicPacketNumberLength packet_number_length, | 
|  | QuicEncryptedPacket* packet, | 
|  | QuicPacketEntropyHash entropy_hash, | 
|  | RetransmittableFrames* retransmittable_frames, | 
|  | bool has_ack, | 
|  | bool has_stop_waiting) | 
|  | : packet(packet), | 
|  | retransmittable_frames(retransmittable_frames), | 
|  | packet_number(packet_number), | 
|  | packet_number_length(packet_number_length), | 
|  | encryption_level(ENCRYPTION_NONE), | 
|  | entropy_hash(entropy_hash), | 
|  | is_fec_packet(false), | 
|  | has_ack(has_ack), | 
|  | has_stop_waiting(has_stop_waiting) {} | 
|  |  | 
|  | SerializedPacket::SerializedPacket( | 
|  | QuicPacketNumber packet_number, | 
|  | QuicPacketNumberLength packet_number_length, | 
|  | char* encrypted_buffer, | 
|  | size_t encrypted_length, | 
|  | bool owns_buffer, | 
|  | QuicPacketEntropyHash entropy_hash, | 
|  | RetransmittableFrames* retransmittable_frames, | 
|  | bool has_ack, | 
|  | bool has_stop_waiting, | 
|  | EncryptionLevel level) | 
|  | : SerializedPacket(packet_number, | 
|  | packet_number_length, | 
|  | new QuicEncryptedPacket(encrypted_buffer, | 
|  | encrypted_length, | 
|  | owns_buffer), | 
|  | entropy_hash, | 
|  | retransmittable_frames, | 
|  | has_ack, | 
|  | has_stop_waiting) { | 
|  | // TODO(ianswett): Move into the initializer list once SerializedPacket | 
|  | // no longer contains an encrypted packet. | 
|  | encryption_level = level; | 
|  | } | 
|  |  | 
|  | SerializedPacket::~SerializedPacket() {} | 
|  |  | 
|  | QuicEncryptedPacket* QuicEncryptedPacket::Clone() const { | 
|  | char* buffer = new char[this->length()]; | 
|  | memcpy(buffer, this->data(), this->length()); | 
|  | return new QuicEncryptedPacket(buffer, this->length(), true); | 
|  | } | 
|  |  | 
|  | ostream& operator<<(ostream& os, const QuicEncryptedPacket& s) { | 
|  | os << s.length() << "-byte data"; | 
|  | return os; | 
|  | } | 
|  |  | 
|  | TransmissionInfo::TransmissionInfo() | 
|  | : retransmittable_frames(nullptr), | 
|  | encryption_level(ENCRYPTION_NONE), | 
|  | packet_number_length(PACKET_1BYTE_PACKET_NUMBER), | 
|  | bytes_sent(0), | 
|  | nack_count(0), | 
|  | sent_time(QuicTime::Zero()), | 
|  | transmission_type(NOT_RETRANSMISSION), | 
|  | in_flight(false), | 
|  | is_unackable(false), | 
|  | is_fec_packet(false), | 
|  | all_transmissions(nullptr), | 
|  | retransmission(0) {} | 
|  |  | 
|  | TransmissionInfo::TransmissionInfo( | 
|  | RetransmittableFrames* retransmittable_frames, | 
|  | EncryptionLevel level, | 
|  | QuicPacketNumberLength packet_number_length, | 
|  | TransmissionType transmission_type, | 
|  | QuicTime sent_time, | 
|  | QuicPacketLength bytes_sent, | 
|  | bool is_fec_packet) | 
|  | : retransmittable_frames(retransmittable_frames), | 
|  | encryption_level(level), | 
|  | packet_number_length(packet_number_length), | 
|  | bytes_sent(bytes_sent), | 
|  | nack_count(0), | 
|  | sent_time(sent_time), | 
|  | transmission_type(transmission_type), | 
|  | in_flight(false), | 
|  | is_unackable(false), | 
|  | is_fec_packet(is_fec_packet), | 
|  | all_transmissions(nullptr), | 
|  | retransmission(0) {} | 
|  |  | 
|  | TransmissionInfo::~TransmissionInfo() {} | 
|  |  | 
|  | }  // namespace net |