// 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_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.sequence_number_length, header.is_in_fec_group); } size_t GetPacketHeaderSize(QuicConnectionIdLength connection_id_length, bool include_version, QuicSequenceNumberLength sequence_number_length, InFecGroup is_in_fec_group) { return kPublicFlagsSize + connection_id_length + (include_version ? kQuicVersionSize : 0) + sequence_number_length + kPrivateFlagsSize + (is_in_fec_group == IN_FEC_GROUP ? kFecGroupSize : 0); } size_t GetStartOfFecProtectedData( QuicConnectionIdLength connection_id_length, bool include_version, QuicSequenceNumberLength sequence_number_length) { return GetPacketHeaderSize(connection_id_length, include_version, sequence_number_length, IN_FEC_GROUP); } size_t GetStartOfEncryptedData( QuicConnectionIdLength connection_id_length, bool include_version, QuicSequenceNumberLength sequence_number_length) { // Don't include the fec size, since encryption starts before private flags. return GetPacketHeaderSize(connection_id_length, include_version, sequence_number_length, NOT_IN_FEC_GROUP) - kPrivateFlagsSize; } QuicPacketPublicHeader::QuicPacketPublicHeader() : connection_id(0), connection_id_length(PACKET_8BYTE_CONNECTION_ID), reset_flag(false), version_flag(false), sequence_number_length(PACKET_6BYTE_SEQUENCE_NUMBER) { } QuicPacketPublicHeader::QuicPacketPublicHeader( const QuicPacketPublicHeader& other) : connection_id(other.connection_id), connection_id_length(other.connection_id_length), reset_flag(other.reset_flag), version_flag(other.version_flag), sequence_number_length(other.sequence_number_length), versions(other.versions) { } QuicPacketPublicHeader::~QuicPacketPublicHeader() {} QuicPacketHeader::QuicPacketHeader() : fec_flag(false), entropy_flag(false), entropy_hash(0), packet_sequence_number(0), is_in_fec_group(NOT_IN_FEC_GROUP), fec_group(0) { } QuicPacketHeader::QuicPacketHeader(const QuicPacketPublicHeader& header) : public_header(header), fec_flag(false), entropy_flag(false), entropy_hash(0), packet_sequence_number(0), is_in_fec_group(NOT_IN_FEC_GROUP), fec_group(0) { } QuicPublicResetPacket::QuicPublicResetPacket() : nonce_proof(0), rejected_sequence_number(0) {} QuicPublicResetPacket::QuicPublicResetPacket( const QuicPacketPublicHeader& header) : public_header(header), nonce_proof(0), rejected_sequence_number(0) {} QuicStreamFrame::QuicStreamFrame() : stream_id(0), fin(false), offset(0), notifier(NULL) {} QuicStreamFrame::QuicStreamFrame(const QuicStreamFrame& frame) : stream_id(frame.stream_id), fin(frame.fin), offset(frame.offset), data(frame.data), notifier(frame.notifier) { } QuicStreamFrame::QuicStreamFrame(QuicStreamId stream_id, bool fin, QuicStreamOffset offset, IOVector data) : stream_id(stream_id), fin(fin), offset(offset), data(data), notifier(NULL) { } string* QuicStreamFrame::GetDataAsString() const { string* data_string = new string(); data_string->reserve(data.TotalBufferSize()); for (size_t i = 0; i < data.Size(); ++i) { data_string->append(static_cast(data.iovec()[i].iov_base), data.iovec()[i].iov_len); } DCHECK_EQ(data_string->size(), data.TotalBufferSize()); return data_string; } uint32 MakeQuicTag(char a, char b, char c, char d) { return static_cast(a) | static_cast(b) << 8 | static_cast(c) << 16 | static_cast(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_15: return MakeQuicTag('Q', '0', '1', '5'); case QUIC_VERSION_16: return MakeQuicTag('Q', '0', '1', '6'); case QUIC_VERSION_17: return MakeQuicTag('Q', '0', '1', '7'); case QUIC_VERSION_18: return MakeQuicTag('Q', '0', '1', '8'); case QUIC_VERSION_19: return MakeQuicTag('Q', '0', '1', '9'); case QUIC_VERSION_20: return MakeQuicTag('Q', '0', '2', '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_15); RETURN_STRING_LITERAL(QUIC_VERSION_16); RETURN_STRING_LITERAL(QUIC_VERSION_17); RETURN_STRING_LITERAL(QUIC_VERSION_18); RETURN_STRING_LITERAL(QUIC_VERSION_19); RETURN_STRING_LITERAL(QUIC_VERSION_20); 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 QuicPacketHeader& header) { os << "{ connection_id: " << header.public_header.connection_id << ", connection_id_length:" << header.public_header.connection_id_length << ", sequence_number_length:" << header.public_header.sequence_number_length << ", 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[0] << " "; } } os << ", fec_flag: " << header.fec_flag << ", entropy_flag: " << header.entropy_flag << ", entropy hash: " << static_cast(header.entropy_hash) << ", sequence_number: " << header.packet_sequence_number << ", is_in_fec_group:" << header.is_in_fec_group << ", fec_group: " << header.fec_group<< "}\n"; return os; } ReceivedPacketInfo::ReceivedPacketInfo() : entropy_hash(0), largest_observed(0), delta_time_largest_observed(QuicTime::Delta::Infinite()), is_truncated(false) {} ReceivedPacketInfo::~ReceivedPacketInfo() {} bool IsAwaitingPacket(const ReceivedPacketInfo& received_info, QuicPacketSequenceNumber sequence_number) { return sequence_number > received_info.largest_observed || ContainsKey(received_info.missing_packets, sequence_number); } void InsertMissingPacketsBetween(ReceivedPacketInfo* received_info, QuicPacketSequenceNumber lower, QuicPacketSequenceNumber higher) { for (QuicPacketSequenceNumber i = lower; i < higher; ++i) { received_info->missing_packets.insert(i); } } QuicStopWaitingFrame::QuicStopWaitingFrame() : entropy_hash(0), least_unacked(0) { } QuicStopWaitingFrame::~QuicStopWaitingFrame() {} QuicAckFrame::QuicAckFrame() {} CongestionFeedbackMessageTCP::CongestionFeedbackMessageTCP() : receive_window(0) { } CongestionFeedbackMessageInterArrival::CongestionFeedbackMessageInterArrival() { } CongestionFeedbackMessageInterArrival:: ~CongestionFeedbackMessageInterArrival() {} QuicCongestionFeedbackFrame::QuicCongestionFeedbackFrame() : type(kTCP) {} QuicCongestionFeedbackFrame::~QuicCongestionFeedbackFrame() {} QuicRstStreamErrorCode AdjustErrorForVersion( QuicRstStreamErrorCode error_code, QuicVersion version) { switch (error_code) { case QUIC_RST_FLOW_CONTROL_ACCOUNTING: if (version <= QUIC_VERSION_17) { return QUIC_STREAM_NO_ERROR; } break; default: return error_code; } return error_code; } QuicRstStreamFrame::QuicRstStreamFrame() : stream_id(0), error_code(QUIC_STREAM_NO_ERROR) { } 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::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(QuicCongestionFeedbackFrame* frame) : type(CONGESTION_FEEDBACK_FRAME), congestion_feedback_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) { } QuicFecData::QuicFecData() : fec_group(0) {} ostream& operator<<(ostream& os, const QuicStopWaitingFrame& sent_info) { os << "entropy_hash: " << static_cast(sent_info.entropy_hash) << " least_unacked: " << sent_info.least_unacked; return os; } ostream& operator<<(ostream& os, const ReceivedPacketInfo& received_info) { os << "entropy_hash: " << static_cast(received_info.entropy_hash) << " is_truncated: " << received_info.is_truncated << " largest_observed: " << received_info.largest_observed << " delta_time_largest_observed: " << received_info.delta_time_largest_observed.ToMicroseconds() << " missing_packets: [ "; for (SequenceNumberSet::const_iterator it = received_info.missing_packets.begin(); it != received_info.missing_packets.end(); ++it) { os << *it << " "; } os << " ] revived_packets: [ "; for (SequenceNumberSet::const_iterator it = received_info.revived_packets.begin(); it != received_info.revived_packets.end(); ++it) { os << *it << " "; } 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 CONGESTION_FEEDBACK_FRAME: { os << "type { CONGESTION_FEEDBACK_FRAME } " << *(frame.congestion_feedback_frame); break; } case STOP_WAITING_FRAME: { os << "type { STOP_WAITING_FRAME } " << *(frame.stop_waiting_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 << " } " << "error_details { " << rst_frame.error_details << " }\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 << " } " << "data { " << QuicUtils::StringToHexASCIIDump(*(stream_frame.GetDataAsString())) << " }\n"; return os; } ostream& operator<<(ostream& os, const QuicAckFrame& ack_frame) { os << "sent info { " << ack_frame.sent_info << " } " << "received info { " << ack_frame.received_info << " }\n"; return os; } ostream& operator<<(ostream& os, const QuicCongestionFeedbackFrame& congestion_frame) { os << "type: " << congestion_frame.type; switch (congestion_frame.type) { case kInterArrival: { const CongestionFeedbackMessageInterArrival& inter_arrival = congestion_frame.inter_arrival; os << " received packets: [ "; for (TimeMap::const_iterator it = inter_arrival.received_packet_times.begin(); it != inter_arrival.received_packet_times.end(); ++it) { os << it->first << "@" << it->second.ToDebuggingValue() << " "; } os << "]"; break; } case kFixRate: { os << " bitrate_in_bytes_per_second: " << congestion_frame.fix_rate.bitrate.ToBytesPerSecond(); break; } case kTCP: { const CongestionFeedbackMessageTCP& tcp = congestion_frame.tcp; os << " receive_window: " << tcp.receive_window; break; } case kTCPBBR: { LOG(DFATAL) << "TCPBBR is not yet supported."; break; } } return os; } CongestionFeedbackMessageFixRate::CongestionFeedbackMessageFixRate() : bitrate(QuicBandwidth::Zero()) { } 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::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(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, QuicSequenceNumberLength sequence_number_length, bool is_fec_packet) : QuicData(buffer, length, owns_buffer), buffer_(buffer), is_fec_packet_(is_fec_packet), connection_id_length_(connection_id_length), includes_version_(includes_version), sequence_number_length_(sequence_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_, sequence_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_, sequence_number_length_) - kStartOfHashData); } StringPiece QuicPacket::BeforePlaintext() const { return StringPiece(data(), GetStartOfEncryptedData(connection_id_length_, includes_version_, sequence_number_length_)); } StringPiece QuicPacket::Plaintext() const { const size_t start_of_encrypted_data = GetStartOfEncryptedData( connection_id_length_, includes_version_, sequence_number_length_); return StringPiece(data() + start_of_encrypted_data, length() - start_of_encrypted_data); } RetransmittableFrames::RetransmittableFrames() : encryption_level_(NUM_ENCRYPTION_LEVELS) { } RetransmittableFrames::~RetransmittableFrames() { for (QuicFrames::iterator it = frames_.begin(); it != frames_.end(); ++it) { switch (it->type) { case PADDING_FRAME: delete it->padding_frame; break; case STREAM_FRAME: delete it->stream_frame; break; case ACK_FRAME: delete it->ack_frame; break; case CONGESTION_FEEDBACK_FRAME: delete it->congestion_feedback_frame; break; case STOP_WAITING_FRAME: delete it->stop_waiting_frame; break; case PING_FRAME: delete it->ping_frame; break; case RST_STREAM_FRAME: delete it->rst_stream_frame; break; case CONNECTION_CLOSE_FRAME: delete it->connection_close_frame; break; case GOAWAY_FRAME: delete it->goaway_frame; break; case WINDOW_UPDATE_FRAME: delete it->window_update_frame; break; case BLOCKED_FRAME: delete it->blocked_frame; break; case NUM_FRAME_TYPES: DCHECK(false) << "Cannot delete type: " << it->type; } } STLDeleteElements(&stream_data_); } const QuicFrame& RetransmittableFrames::AddStreamFrame( QuicStreamFrame* stream_frame) { // Make an owned copy of the stream frame's data. stream_data_.push_back(stream_frame->GetDataAsString()); // Ensure the stream frame's IOVector points to the owned copy of the data. stream_frame->data.Clear(); stream_frame->data.Append(const_cast(stream_data_.back()->data()), stream_data_.back()->size()); frames_.push_back(QuicFrame(stream_frame)); return frames_.back(); } const QuicFrame& RetransmittableFrames::AddNonStreamFrame( const QuicFrame& frame) { DCHECK_NE(frame.type, STREAM_FRAME); frames_.push_back(frame); return frames_.back(); } IsHandshake RetransmittableFrames::HasCryptoHandshake() const { for (size_t i = 0; i < frames().size(); ++i) { if (frames()[i].type == STREAM_FRAME && frames()[i].stream_frame->stream_id == kCryptoStreamId) { return IS_HANDSHAKE; } } return NOT_HANDSHAKE; } void RetransmittableFrames::set_encryption_level(EncryptionLevel level) { encryption_level_ = level; } SerializedPacket::SerializedPacket( QuicPacketSequenceNumber sequence_number, QuicSequenceNumberLength sequence_number_length, QuicPacket* packet, QuicPacketEntropyHash entropy_hash, RetransmittableFrames* retransmittable_frames) : sequence_number(sequence_number), sequence_number_length(sequence_number_length), packet(packet), entropy_hash(entropy_hash), retransmittable_frames(retransmittable_frames) { } 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(NULL), sequence_number_length(PACKET_1BYTE_SEQUENCE_NUMBER), sent_time(QuicTime::Zero()), bytes_sent(0), nack_count(0), transmission_type(NOT_RETRANSMISSION), all_transmissions(NULL), in_flight(false) {} TransmissionInfo::TransmissionInfo( RetransmittableFrames* retransmittable_frames, QuicPacketSequenceNumber sequence_number, QuicSequenceNumberLength sequence_number_length) : retransmittable_frames(retransmittable_frames), sequence_number_length(sequence_number_length), sent_time(QuicTime::Zero()), bytes_sent(0), nack_count(0), transmission_type(NOT_RETRANSMISSION), all_transmissions(new SequenceNumberSet), in_flight(false) { all_transmissions->insert(sequence_number); } TransmissionInfo::TransmissionInfo( RetransmittableFrames* retransmittable_frames, QuicPacketSequenceNumber sequence_number, QuicSequenceNumberLength sequence_number_length, TransmissionType transmission_type, SequenceNumberSet* all_transmissions) : retransmittable_frames(retransmittable_frames), sequence_number_length(sequence_number_length), sent_time(QuicTime::Zero()), bytes_sent(0), nack_count(0), transmission_type(transmission_type), all_transmissions(all_transmissions), in_flight(false) { all_transmissions->insert(sequence_number); } } // namespace net