diff options
Diffstat (limited to 'chromium/net/quic/quic_framer.cc')
-rw-r--r-- | chromium/net/quic/quic_framer.cc | 849 |
1 files changed, 439 insertions, 410 deletions
diff --git a/chromium/net/quic/quic_framer.cc b/chromium/net/quic/quic_framer.cc index cfc8c95774b..cc02882ddc9 100644 --- a/chromium/net/quic/quic_framer.cc +++ b/chromium/net/quic/quic_framer.cc @@ -13,6 +13,8 @@ using base::StringPiece; using std::make_pair; using std::map; +using std::max; +using std::min; using std::numeric_limits; using std::string; @@ -20,19 +22,6 @@ namespace net { namespace { -// TODO(jri): Remove uses of QuicFrameTypeOld when -// QUIC versions < 10 are no longer supported. -enum QuicFrameTypeOld { - PADDING_FRAME_OLD = 0, - STREAM_FRAME_OLD, - ACK_FRAME_OLD, - CONGESTION_FEEDBACK_FRAME_OLD, - RST_STREAM_FRAME_OLD, - CONNECTION_CLOSE_FRAME_OLD, - GOAWAY_FRAME_OLD, - NUM_FRAME_TYPES_OLD -}; - // Mask to select the lowest 48 bits of a sequence number. const QuicPacketSequenceNumber k6ByteSequenceNumberMask = GG_UINT64_C(0x0000FFFFFFFFFFFF); @@ -46,6 +35,10 @@ const QuicPacketSequenceNumber k1ByteSequenceNumberMask = const QuicGuid k1ByteGuidMask = GG_UINT64_C(0x00000000000000FF); const QuicGuid k4ByteGuidMask = GG_UINT64_C(0x00000000FFFFFFFF); +// Number of bits the sequence number length bits are shifted from the right +// edge of the public header. +const uint8 kPublicHeaderSequenceNumberShift = 4; + // New Frame Types, QUIC v. >= 10: // There are two interpretations for the Frame Type byte in the QUIC protocol, // resulting in two Frame Types: Special Frame Types and Regular Frame Types. @@ -72,16 +65,6 @@ const uint8 kQuicFrameTypeStreamMask = 0x80; const uint8 kQuicFrameTypeAckMask = 0x40; const uint8 kQuicFrameTypeCongestionFeedbackMask = 0x20; -// Mask to determine if it's a special frame type(Stream, Ack, or -// Congestion Control) by checking if the first bit is 0, then shifting right. -// TODO(jri): Remove kQuicFrameType0BitMask constant from v. 10 onwards. -// Replaced by kQuicFrameTypeStream defined above. -const uint8 kQuicFrameType0BitMask = 0x01; - -// Default frame type shift and mask. -const uint8 kQuicDefaultFrameTypeShift = 3; -const uint8 kQuicDefaultFrameTypeMask = 0x07; - // Stream frame relative shifts and masks for interpreting the stream flags. // StreamID may be 1, 2, 3, or 4 bytes. const uint8 kQuicStreamIdShift = 2; @@ -99,8 +82,15 @@ const uint8 kQuicStreamDataLengthMask = 0x01; const uint8 kQuicStreamFinShift = 1; const uint8 kQuicStreamFinMask = 0x01; +// Sequence number size shift used in AckFrames. +const uint8 kQuicSequenceNumberLengthShift = 2; + +// Acks may be truncated. +const uint8 kQuicAckTruncatedShift = 1; +const uint8 kQuicAckTruncatedMask = 0x01; -const uint32 kInvalidDeltaTime = 0xffffffff; +// Acks may not have any nacks. +const uint8 kQuicHasNacksMask = 0x01; // Returns the absolute value of the difference between |a| and |b|. QuicPacketSequenceNumber Delta(QuicPacketSequenceNumber a, @@ -120,21 +110,24 @@ QuicPacketSequenceNumber ClosestTo(QuicPacketSequenceNumber target, } // namespace -QuicFramer::QuicFramer(QuicVersion version, +QuicFramer::QuicFramer(const QuicVersionVector& supported_versions, QuicTime creation_time, bool is_server) : visitor_(NULL), fec_builder_(NULL), + entropy_calculator_(NULL), error_(QUIC_NO_ERROR), last_sequence_number_(0), last_serialized_guid_(0), - quic_version_(version), - decrypter_(QuicDecrypter::Create(kNULL)), + supported_versions_(supported_versions), alternative_decrypter_latch_(false), is_server_(is_server), creation_time_(creation_time) { - DCHECK(IsSupportedVersion(version)); - encrypter_[ENCRYPTION_NONE].reset(QuicEncrypter::Create(kNULL)); + DCHECK(!supported_versions.empty()); + quic_version_ = supported_versions_[0]; + decrypter_.reset(QuicDecrypter::Create(kNULL)); + encrypter_[ENCRYPTION_NONE].reset( + QuicEncrypter::Create(kNULL)); } QuicFramer::~QuicFramer() {} @@ -150,11 +143,13 @@ size_t QuicFramer::GetMinStreamFrameSize(QuicVersion version, } // static -size_t QuicFramer::GetMinAckFrameSize() { +size_t QuicFramer::GetMinAckFrameSize( + QuicVersion version, + QuicSequenceNumberLength sequence_number_length, + QuicSequenceNumberLength largest_observed_length) { return kQuicFrameTypeSize + kQuicEntropyHashSize + - PACKET_6BYTE_SEQUENCE_NUMBER + kQuicEntropyHashSize + - PACKET_6BYTE_SEQUENCE_NUMBER + kQuicDeltaTimeLargestObservedSize + - kNumberOfMissingPacketsSize; + sequence_number_length + kQuicEntropyHashSize + + largest_observed_length + kQuicDeltaTimeLargestObservedSize; } // static @@ -165,8 +160,7 @@ size_t QuicFramer::GetMinRstStreamFrameSize() { // static size_t QuicFramer::GetMinConnectionCloseFrameSize() { - return kQuicFrameTypeSize + kQuicErrorCodeSize + kQuicErrorDetailsLengthSize + - GetMinAckFrameSize(); + return kQuicFrameTypeSize + kQuicErrorCodeSize + kQuicErrorDetailsLengthSize; } // static @@ -176,16 +170,6 @@ size_t QuicFramer::GetMinGoAwayFrameSize() { } // static -// TODO(satyamshekhar): 16 - Crypto hash for integrity. Not a static value. Use -// QuicEncrypter::GetMaxPlaintextSize. -// 16 is a conservative estimate in the case of AEAD_AES_128_GCM_12, which uses -// 12-byte tags. -size_t QuicFramer::GetMaxUnackedPackets(QuicPacketHeader header) { - return (kMaxPacketSize - GetPacketHeaderSize(header) - - GetMinAckFrameSize() - 16) / PACKET_6BYTE_SEQUENCE_NUMBER; -} - -// static size_t QuicFramer::GetStreamIdSize(QuicStreamId stream_id) { // Sizes are 1 through 4 bytes. for (int i = 1; i <= 4; ++i) { @@ -223,20 +207,20 @@ size_t QuicFramer::GetVersionNegotiationPacketSize(size_t number_versions) { } // static -bool QuicFramer::CanTruncate(const QuicFrame& frame, size_t free_bytes) { - // TODO(ianswett): GetMinConnectionCloseFrameSize may be incorrect, because - // checking for it here results in frames not being added, but the resulting - // frames do actually fit. +bool QuicFramer::CanTruncate( + QuicVersion version, const QuicFrame& frame, size_t free_bytes) { if ((frame.type == ACK_FRAME || frame.type == CONNECTION_CLOSE_FRAME) && - free_bytes >= GetMinAckFrameSize()) { + free_bytes >= GetMinAckFrameSize(version, + PACKET_6BYTE_SEQUENCE_NUMBER, + PACKET_6BYTE_SEQUENCE_NUMBER)) { return true; } return false; } bool QuicFramer::IsSupportedVersion(const QuicVersion version) const { - for (size_t i = 0; i < arraysize(kSupportedQuicVersions); ++i) { - if (version == kSupportedQuicVersions[i]) { + for (size_t i = 0; i < supported_versions_.size(); ++i) { + if (version == supported_versions_[i]) { return true; } } @@ -244,43 +228,43 @@ bool QuicFramer::IsSupportedVersion(const QuicVersion version) const { } size_t QuicFramer::GetSerializedFrameLength( - const QuicFrame& frame, size_t free_bytes, bool first_frame) { + const QuicFrame& frame, + size_t free_bytes, + bool first_frame, + bool last_frame, + QuicSequenceNumberLength sequence_number_length) { if (frame.type == PADDING_FRAME) { // PADDING implies end of packet. return free_bytes; } - // See if it fits as the non-last frame. - size_t frame_len = ComputeFrameLength(frame, false); - // STREAM frames save two bytes when they're the last frame in the packet. - if (frame_len > free_bytes && frame.type == STREAM_FRAME) { - frame_len = ComputeFrameLength(frame, true); - } + size_t frame_len = + ComputeFrameLength(frame, last_frame, sequence_number_length); if (frame_len > free_bytes) { // Only truncate the first frame in a packet, so if subsequent ones go // over, stop including more frames. if (!first_frame) { return 0; } - if (CanTruncate(frame, free_bytes)) { + if (CanTruncate(quic_version_, frame, free_bytes)) { // Truncate the frame so the packet will not exceed kMaxPacketSize. // Note that we may not use every byte of the writer in this case. - DLOG(INFO) << "Truncating large frame"; + DVLOG(1) << "Truncating large frame"; return free_bytes; } } return frame_len; } +QuicFramer::AckFrameInfo::AckFrameInfo() : max_delta(0) { } + +QuicFramer::AckFrameInfo::~AckFrameInfo() { } + QuicPacketEntropyHash QuicFramer::GetPacketEntropyHash( const QuicPacketHeader& header) const { - if (!header.entropy_flag) { - // TODO(satyamshekhar): Return some more better value here (something that - // is not a constant). - return 0; - } - return 1 << (header.packet_sequence_number % 8); + return header.entropy_flag << (header.packet_sequence_number % 8); } +// Test only. SerializedPacket QuicFramer::BuildUnsizedDataPacket( const QuicPacketHeader& header, const QuicFrames& frames) { @@ -288,8 +272,11 @@ SerializedPacket QuicFramer::BuildUnsizedDataPacket( size_t packet_size = GetPacketHeaderSize(header); for (size_t i = 0; i < frames.size(); ++i) { DCHECK_LE(packet_size, max_plaintext_size); + bool first_frame = i == 0; + bool last_frame = i == frames.size() - 1; const size_t frame_size = GetSerializedFrameLength( - frames[i], max_plaintext_size - packet_size, i == 0); + frames[i], max_plaintext_size - packet_size, first_frame, last_frame, + header.public_header.sequence_number_length); DCHECK(frame_size); packet_size += frame_size; } @@ -303,7 +290,7 @@ SerializedPacket QuicFramer::BuildDataPacket( QuicDataWriter writer(packet_size); const SerializedPacket kNoPacket( 0, PACKET_1BYTE_SEQUENCE_NUMBER, NULL, 0, NULL); - if (!WritePacketHeader(header, &writer)) { + if (!AppendPacketHeader(header, &writer)) { return kNoPacket; } @@ -326,7 +313,8 @@ SerializedPacket QuicFramer::BuildDataPacket( } break; case ACK_FRAME: - if (!AppendAckFramePayload(*frame.ack_frame, &writer)) { + if (!AppendAckFramePayloadAndTypeByte( + header, *frame.ack_frame, &writer)) { return kNoPacket; } break; @@ -388,7 +376,7 @@ SerializedPacket QuicFramer::BuildFecPacket(const QuicPacketHeader& header, QuicDataWriter writer(len); const SerializedPacket kNoPacket( 0, PACKET_1BYTE_SEQUENCE_NUMBER, NULL, 0, NULL); - if (!WritePacketHeader(header, &writer)) { + if (!AppendPacketHeader(header, &writer)) { return kNoPacket; } @@ -465,8 +453,6 @@ QuicEncryptedPacket* QuicFramer::BuildVersionNegotiationPacket( } bool QuicFramer::ProcessPacket(const QuicEncryptedPacket& packet) { - // TODO(satyamshekhar): Don't RaiseError (and close the connection) for - // invalid (unauthenticated) packets. DCHECK(!reader_.get()); reader_.reset(new QuicDataReader(packet.data(), packet.length())); @@ -476,6 +462,7 @@ bool QuicFramer::ProcessPacket(const QuicEncryptedPacket& packet) { QuicPacketPublicHeader public_header; if (!ProcessPublicHeader(&public_header)) { DLOG(WARNING) << "Unable to process public header."; + DCHECK_NE("", detailed_error_); return RaiseError(QUIC_INVALID_PACKET_HEADER); } @@ -522,7 +509,6 @@ bool QuicFramer::ProcessDataPacket( const QuicEncryptedPacket& packet) { QuicPacketHeader header(public_header); if (!ProcessPacketHeader(&header, packet)) { - DCHECK_NE(QUIC_NO_ERROR, error_); // ProcessPacketHeader sets the error. DLOG(WARNING) << "Unable to process data packet header."; return false; } @@ -543,7 +529,7 @@ bool QuicFramer::ProcessDataPacket( StringPiece payload = reader_->PeekRemainingPayload(); visitor_->OnFecProtectedPayload(payload); } - if (!ProcessFrameData()) { + if (!ProcessFrameData(header)) { DCHECK_NE(QUIC_NO_ERROR, error_); // ProcessFrameData sets the error. DLOG(WARNING) << "Unable to process frame data."; return false; @@ -594,7 +580,7 @@ bool QuicFramer::ProcessRevivedPacket(QuicPacketHeader* header, } reader_.reset(new QuicDataReader(payload.data(), payload.length())); - if (!ProcessFrameData()) { + if (!ProcessFrameData(*header)) { DCHECK_NE(QUIC_NO_ERROR, error_); // ProcessFrameData sets the error. DLOG(WARNING) << "Unable to process frame data."; return false; @@ -605,8 +591,8 @@ bool QuicFramer::ProcessRevivedPacket(QuicPacketHeader* header, return true; } -bool QuicFramer::WritePacketHeader(const QuicPacketHeader& header, - QuicDataWriter* writer) { +bool QuicFramer::AppendPacketHeader(const QuicPacketHeader& header, + QuicDataWriter* writer) { DCHECK(header.fec_group > 0 || header.is_in_fec_group == NOT_IN_FEC_GROUP); uint8 public_flags = 0; if (header.public_header.reset_flag) { @@ -615,20 +601,10 @@ bool QuicFramer::WritePacketHeader(const QuicPacketHeader& header, if (header.public_header.version_flag) { public_flags |= PACKET_PUBLIC_FLAGS_VERSION; } - switch (header.public_header.sequence_number_length) { - case PACKET_1BYTE_SEQUENCE_NUMBER: - public_flags |= PACKET_PUBLIC_FLAGS_1BYTE_SEQUENCE; - break; - case PACKET_2BYTE_SEQUENCE_NUMBER: - public_flags |= PACKET_PUBLIC_FLAGS_2BYTE_SEQUENCE; - break; - case PACKET_4BYTE_SEQUENCE_NUMBER: - public_flags |= PACKET_PUBLIC_FLAGS_4BYTE_SEQUENCE; - break; - case PACKET_6BYTE_SEQUENCE_NUMBER: - public_flags |= PACKET_PUBLIC_FLAGS_6BYTE_SEQUENCE; - break; - } + + public_flags |= + GetSequenceNumberFlags(header.public_header.sequence_number_length) + << kPublicHeaderSequenceNumberShift; switch (header.public_header.guid_length) { case PACKET_0BYTE_GUID: @@ -641,7 +617,7 @@ bool QuicFramer::WritePacketHeader(const QuicPacketHeader& header, return false; } if (!writer->WriteUInt8(header.public_header.guid & k1ByteGuidMask)) { - return false; + return false; } break; case PACKET_4BYTE_GUID: @@ -794,20 +770,9 @@ bool QuicFramer::ProcessPublicHeader( break; } - switch (public_flags & PACKET_PUBLIC_FLAGS_6BYTE_SEQUENCE) { - case PACKET_PUBLIC_FLAGS_6BYTE_SEQUENCE: - public_header->sequence_number_length = PACKET_6BYTE_SEQUENCE_NUMBER; - break; - case PACKET_PUBLIC_FLAGS_4BYTE_SEQUENCE: - public_header->sequence_number_length = PACKET_4BYTE_SEQUENCE_NUMBER; - break; - case PACKET_PUBLIC_FLAGS_2BYTE_SEQUENCE: - public_header->sequence_number_length = PACKET_2BYTE_SEQUENCE_NUMBER; - break; - case PACKET_PUBLIC_FLAGS_1BYTE_SEQUENCE: - public_header->sequence_number_length = PACKET_1BYTE_SEQUENCE_NUMBER; - break; - } + public_header->sequence_number_length = + ReadSequenceNumberLength( + public_flags >> kPublicHeaderSequenceNumberShift); // Read the version only if the packet is from the client. // version flag from the server means version negotiation packet. @@ -848,6 +813,91 @@ bool QuicFramer::ReadGuidFromPacket(const QuicEncryptedPacket& packet, return reader.ReadUInt64(guid); } +// static +QuicSequenceNumberLength QuicFramer::ReadSequenceNumberLength(uint8 flags) { + switch (flags & PACKET_FLAGS_6BYTE_SEQUENCE) { + case PACKET_FLAGS_6BYTE_SEQUENCE: + return PACKET_6BYTE_SEQUENCE_NUMBER; + case PACKET_FLAGS_4BYTE_SEQUENCE: + return PACKET_4BYTE_SEQUENCE_NUMBER; + case PACKET_FLAGS_2BYTE_SEQUENCE: + return PACKET_2BYTE_SEQUENCE_NUMBER; + case PACKET_FLAGS_1BYTE_SEQUENCE: + return PACKET_1BYTE_SEQUENCE_NUMBER; + default: + LOG(DFATAL) << "Unreachable case statement."; + return PACKET_6BYTE_SEQUENCE_NUMBER; + } +} + +// static +QuicSequenceNumberLength QuicFramer::GetMinSequenceNumberLength( + QuicPacketSequenceNumber sequence_number) { + if (sequence_number < 1 << (PACKET_1BYTE_SEQUENCE_NUMBER * 8)) { + return PACKET_1BYTE_SEQUENCE_NUMBER; + } else if (sequence_number < 1 << (PACKET_2BYTE_SEQUENCE_NUMBER * 8)) { + return PACKET_2BYTE_SEQUENCE_NUMBER; + } else if (sequence_number < + GG_UINT64_C(1) << (PACKET_4BYTE_SEQUENCE_NUMBER * 8)) { + return PACKET_4BYTE_SEQUENCE_NUMBER; + } else { + return PACKET_6BYTE_SEQUENCE_NUMBER; + } +} + +// static +uint8 QuicFramer::GetSequenceNumberFlags( + QuicSequenceNumberLength sequence_number_length) { + switch (sequence_number_length) { + case PACKET_1BYTE_SEQUENCE_NUMBER: + return PACKET_FLAGS_1BYTE_SEQUENCE; + case PACKET_2BYTE_SEQUENCE_NUMBER: + return PACKET_FLAGS_2BYTE_SEQUENCE; + case PACKET_4BYTE_SEQUENCE_NUMBER: + return PACKET_FLAGS_4BYTE_SEQUENCE; + case PACKET_6BYTE_SEQUENCE_NUMBER: + return PACKET_FLAGS_6BYTE_SEQUENCE; + default: + LOG(DFATAL) << "Unreachable case statement."; + return PACKET_FLAGS_6BYTE_SEQUENCE; + } +} + +// static +QuicFramer::AckFrameInfo QuicFramer::GetAckFrameInfo( + const QuicAckFrame& frame) { + const ReceivedPacketInfo& received_info = frame.received_info; + + AckFrameInfo ack_info; + if (!received_info.missing_packets.empty()) { + DCHECK_GE(received_info.largest_observed, + *received_info.missing_packets.rbegin()); + size_t cur_range_length = 0; + SequenceNumberSet::const_iterator iter = + received_info.missing_packets.begin(); + QuicPacketSequenceNumber last_missing = *iter; + ++iter; + for (; iter != received_info.missing_packets.end(); ++iter) { + if (cur_range_length != numeric_limits<uint8>::max() && + *iter == (last_missing + 1)) { + ++cur_range_length; + } else { + ack_info.nack_ranges[last_missing - cur_range_length] + = cur_range_length; + cur_range_length = 0; + } + ack_info.max_delta = max(ack_info.max_delta, *iter - last_missing); + last_missing = *iter; + } + // Include the last nack range. + ack_info.nack_ranges[last_missing - cur_range_length] = cur_range_length; + // Include the range to the largest observed. + ack_info.max_delta = max(ack_info.max_delta, + received_info.largest_observed - last_missing); + } + return ack_info; +} + bool QuicFramer::ProcessPacketHeader( QuicPacketHeader* header, const QuicEncryptedPacket& packet) { @@ -862,6 +912,10 @@ bool QuicFramer::ProcessPacketHeader( return RaiseError(QUIC_INVALID_PACKET_HEADER); } + if (!visitor_->OnUnauthenticatedHeader(*header)) { + return false; + } + if (!DecryptPayload(*header, packet)) { set_detailed_error("Unable to decrypt payload."); return RaiseError(QUIC_DECRYPTION_FAILURE); @@ -920,7 +974,7 @@ bool QuicFramer::ProcessPacketSequenceNumber( return true; } -bool QuicFramer::ProcessFrameData() { +bool QuicFramer::ProcessFrameData(const QuicPacketHeader& header) { if (reader_->IsDoneReading()) { set_detailed_error("Packet has no frames."); return RaiseError(QUIC_MISSING_PAYLOAD); @@ -932,223 +986,107 @@ bool QuicFramer::ProcessFrameData() { return RaiseError(QUIC_INVALID_FRAME_DATA); } - // TODO(jri): Remove this entire if block when support for - // QUIC version < 10 removed. - if (version() < QUIC_VERSION_10) { - // Special frame type processing for QUIC version < 10. - if ((frame_type & kQuicFrameType0BitMask) == 0) { + if (frame_type & kQuicFrameTypeSpecialMask) { + // Stream Frame + if (frame_type & kQuicFrameTypeStreamMask) { QuicStreamFrame frame; if (!ProcessStreamFrame(frame_type, &frame)) { return RaiseError(QUIC_INVALID_STREAM_DATA); } if (!visitor_->OnStreamFrame(frame)) { - DLOG(INFO) << "Visitor asked to stop further processing."; + DVLOG(1) << "Visitor asked to stop further processing."; // Returning true since there was no parsing error. return true; } continue; } - frame_type >>= 1; - if ((frame_type & kQuicFrameType0BitMask) == 0) { + // Ack Frame + if (frame_type & kQuicFrameTypeAckMask) { QuicAckFrame frame; - if (!ProcessAckFrame(&frame)) { + if (!ProcessAckFrame(header, frame_type, &frame)) { return RaiseError(QUIC_INVALID_ACK_DATA); } if (!visitor_->OnAckFrame(frame)) { - DLOG(INFO) << "Visitor asked to stop further processing."; + DVLOG(1) << "Visitor asked to stop further processing."; // Returning true since there was no parsing error. return true; } continue; } - frame_type >>= 1; - if ((frame_type & kQuicFrameType0BitMask) == 0) { + // Congestion Feedback Frame + if (frame_type & kQuicFrameTypeCongestionFeedbackMask) { QuicCongestionFeedbackFrame frame; if (!ProcessQuicCongestionFeedbackFrame(&frame)) { return RaiseError(QUIC_INVALID_CONGESTION_FEEDBACK_DATA); } if (!visitor_->OnCongestionFeedbackFrame(frame)) { - DLOG(INFO) << "Visitor asked to stop further processing."; + DVLOG(1) << "Visitor asked to stop further processing."; // Returning true since there was no parsing error. return true; } continue; } - frame_type >>= 1; - switch (frame_type) { - // STREAM_FRAME, ACK_FRAME, and CONGESTION_FEEDBACK_FRAME are handled - // above. - case PADDING_FRAME_OLD: - // We're done with the packet. - return true; - - case RST_STREAM_FRAME_OLD: { - QuicRstStreamFrame frame; - if (!ProcessRstStreamFrame(&frame)) { - return RaiseError(QUIC_INVALID_RST_STREAM_DATA); - } - if (!visitor_->OnRstStreamFrame(frame)) { - DLOG(INFO) << "Visitor asked to stop further processing."; - // Returning true since there was no parsing error. - return true; - } - continue; - } - - case CONNECTION_CLOSE_FRAME_OLD: { - QuicConnectionCloseFrame frame; - if (!ProcessConnectionCloseFrame(&frame)) { - return RaiseError(QUIC_INVALID_CONNECTION_CLOSE_DATA); - } + // This was a special frame type that did not match any + // of the known ones. Error. + set_detailed_error("Illegal frame type."); + DLOG(WARNING) << "Illegal frame type: " + << static_cast<int>(frame_type); + return RaiseError(QUIC_INVALID_FRAME_DATA); + } - if (!visitor_->OnAckFrame(frame.ack_frame)) { - DLOG(INFO) << "Visitor asked to stop further processing."; - // Returning true since there was no parsing error. - return true; - } + switch (frame_type) { + case PADDING_FRAME: + // We're done with the packet. + return true; - if (!visitor_->OnConnectionCloseFrame(frame)) { - DLOG(INFO) << "Visitor asked to stop further processing."; - // Returning true since there was no parsing error. - return true; - } - continue; + case RST_STREAM_FRAME: { + QuicRstStreamFrame frame; + if (!ProcessRstStreamFrame(&frame)) { + return RaiseError(QUIC_INVALID_RST_STREAM_DATA); } - - case GOAWAY_FRAME_OLD: { - QuicGoAwayFrame goaway_frame; - if (!ProcessGoAwayFrame(&goaway_frame)) { - return RaiseError(QUIC_INVALID_GOAWAY_DATA); - } - if (!visitor_->OnGoAwayFrame(goaway_frame)) { - DLOG(INFO) << "Visitor asked to stop further processing."; - // Returning true since there was no parsing error. - return true; - } - continue; + if (!visitor_->OnRstStreamFrame(frame)) { + DVLOG(1) << "Visitor asked to stop further processing."; + // Returning true since there was no parsing error. + return true; } - - set_detailed_error("Illegal frame type."); - DLOG(WARNING) << "Illegal frame type: " - << static_cast<int>(frame_type); - return RaiseError(QUIC_INVALID_FRAME_DATA); + continue; } - } else { - // TODO(jri): Retain this else block when support for - // QUIC version < 10 removed. Remove above if block. - - // Special frame type processing for QUIC version >= 10. - if (frame_type & kQuicFrameTypeSpecialMask) { - // Stream Frame - if (frame_type & kQuicFrameTypeStreamMask) { - QuicStreamFrame frame; - if (!ProcessStreamFrame(frame_type, &frame)) { - return RaiseError(QUIC_INVALID_STREAM_DATA); - } - if (!visitor_->OnStreamFrame(frame)) { - DLOG(INFO) << "Visitor asked to stop further processing."; - // Returning true since there was no parsing error. - return true; - } - continue; + + case CONNECTION_CLOSE_FRAME: { + QuicConnectionCloseFrame frame; + if (!ProcessConnectionCloseFrame(&frame)) { + return RaiseError(QUIC_INVALID_CONNECTION_CLOSE_DATA); } - // Ack Frame - if (frame_type & kQuicFrameTypeAckMask) { - QuicAckFrame frame; - if (!ProcessAckFrame(&frame)) { - return RaiseError(QUIC_INVALID_ACK_DATA); - } - if (!visitor_->OnAckFrame(frame)) { - DLOG(INFO) << "Visitor asked to stop further processing."; - // Returning true since there was no parsing error. - return true; - } - continue; + if (!visitor_->OnConnectionCloseFrame(frame)) { + DVLOG(1) << "Visitor asked to stop further processing."; + // Returning true since there was no parsing error. + return true; } + continue; + } - // Congestion Feedback Frame - if (frame_type & kQuicFrameTypeCongestionFeedbackMask) { - QuicCongestionFeedbackFrame frame; - if (!ProcessQuicCongestionFeedbackFrame(&frame)) { - return RaiseError(QUIC_INVALID_CONGESTION_FEEDBACK_DATA); - } - if (!visitor_->OnCongestionFeedbackFrame(frame)) { - DLOG(INFO) << "Visitor asked to stop further processing."; - // Returning true since there was no parsing error. - return true; - } - continue; + case GOAWAY_FRAME: { + QuicGoAwayFrame goaway_frame; + if (!ProcessGoAwayFrame(&goaway_frame)) { + return RaiseError(QUIC_INVALID_GOAWAY_DATA); + } + if (!visitor_->OnGoAwayFrame(goaway_frame)) { + DVLOG(1) << "Visitor asked to stop further processing."; + // Returning true since there was no parsing error. + return true; } + continue; + } - // This was a special frame type that did not match any - // of the known ones. Error. + default: set_detailed_error("Illegal frame type."); DLOG(WARNING) << "Illegal frame type: " << static_cast<int>(frame_type); return RaiseError(QUIC_INVALID_FRAME_DATA); - } - - switch (frame_type) { - case PADDING_FRAME: - // We're done with the packet. - return true; - - case RST_STREAM_FRAME: { - QuicRstStreamFrame frame; - if (!ProcessRstStreamFrame(&frame)) { - return RaiseError(QUIC_INVALID_RST_STREAM_DATA); - } - if (!visitor_->OnRstStreamFrame(frame)) { - DLOG(INFO) << "Visitor asked to stop further processing."; - // Returning true since there was no parsing error. - return true; - } - continue; - } - - case CONNECTION_CLOSE_FRAME: { - QuicConnectionCloseFrame frame; - if (!ProcessConnectionCloseFrame(&frame)) { - return RaiseError(QUIC_INVALID_CONNECTION_CLOSE_DATA); - } - - if (!visitor_->OnAckFrame(frame.ack_frame)) { - DLOG(INFO) << "Visitor asked to stop further processing."; - // Returning true since there was no parsing error. - return true; - } - - if (!visitor_->OnConnectionCloseFrame(frame)) { - DLOG(INFO) << "Visitor asked to stop further processing."; - // Returning true since there was no parsing error. - return true; - } - continue; - } - - case GOAWAY_FRAME: { - QuicGoAwayFrame goaway_frame; - if (!ProcessGoAwayFrame(&goaway_frame)) { - return RaiseError(QUIC_INVALID_GOAWAY_DATA); - } - if (!visitor_->OnGoAwayFrame(goaway_frame)) { - DLOG(INFO) << "Visitor asked to stop further processing."; - // Returning true since there was no parsing error. - return true; - } - continue; - } - - default: - set_detailed_error("Illegal frame type."); - DLOG(WARNING) << "Illegal frame type: " - << static_cast<int>(frame_type); - return RaiseError(QUIC_INVALID_FRAME_DATA); - } } } @@ -1159,12 +1097,7 @@ bool QuicFramer::ProcessStreamFrame(uint8 frame_type, QuicStreamFrame* frame) { uint8 stream_flags = frame_type; - // TODO(jri): Remove if block after support for ver. < 10 removed. - if (version() < QUIC_VERSION_10) { - stream_flags >>= 1; - } else { - stream_flags &= ~kQuicFrameTypeStreamMask; - } + stream_flags &= ~kQuicFrameTypeStreamMask; // Read from right to left: StreamID, Offset, Data Length, Fin. const uint8 stream_id_length = (stream_flags & kQuicStreamIDLengthMask) + 1; @@ -1195,86 +1128,129 @@ bool QuicFramer::ProcessStreamFrame(uint8 frame_type, return false; } + StringPiece frame_data; if (has_data_length) { - if (!reader_->ReadStringPiece16(&frame->data)) { + if (!reader_->ReadStringPiece16(&frame_data)) { set_detailed_error("Unable to read frame data."); return false; } } else { - if (!reader_->ReadStringPiece(&frame->data, reader_->BytesRemaining())) { + if (!reader_->ReadStringPiece(&frame_data, reader_->BytesRemaining())) { set_detailed_error("Unable to read frame data."); return false; } } + // Point frame to the right data. + frame->data.Clear(); + if (!frame_data.empty()) { + frame->data.Append(const_cast<char*>(frame_data.data()), frame_data.size()); + } return true; } -bool QuicFramer::ProcessAckFrame(QuicAckFrame* frame) { - if (!ProcessSentInfo(&frame->sent_info)) { +bool QuicFramer::ProcessAckFrame(const QuicPacketHeader& header, + uint8 frame_type, + QuicAckFrame* frame) { + if (!ProcessSentInfo(header, &frame->sent_info)) { return false; } - if (!ProcessReceivedInfo(&frame->received_info)) { + if (!ProcessReceivedInfo(frame_type, &frame->received_info)) { return false; } return true; } -bool QuicFramer::ProcessReceivedInfo(ReceivedPacketInfo* received_info) { +bool QuicFramer::ProcessReceivedInfo(uint8 frame_type, + ReceivedPacketInfo* received_info) { + // Determine the three lengths from the frame type: largest observed length, + // missing sequence number length, and missing range length. + const QuicSequenceNumberLength missing_sequence_number_length = + ReadSequenceNumberLength(frame_type); + frame_type >>= kQuicSequenceNumberLengthShift; + const QuicSequenceNumberLength largest_observed_sequence_number_length = + ReadSequenceNumberLength(frame_type); + frame_type >>= kQuicSequenceNumberLengthShift; + received_info->is_truncated = frame_type & kQuicAckTruncatedMask; + frame_type >>= kQuicAckTruncatedShift; + bool has_nacks = frame_type & kQuicHasNacksMask; + if (!reader_->ReadBytes(&received_info->entropy_hash, 1)) { set_detailed_error("Unable to read entropy hash for received packets."); return false; } - if (!ProcessPacketSequenceNumber(PACKET_6BYTE_SEQUENCE_NUMBER, - &received_info->largest_observed)) { - set_detailed_error("Unable to read largest observed."); - return false; + if (!reader_->ReadBytes(&received_info->largest_observed, + largest_observed_sequence_number_length)) { + set_detailed_error("Unable to read largest observed."); + return false; } - uint32 delta_time_largest_observed_us; - if (!reader_->ReadUInt32(&delta_time_largest_observed_us)) { + uint64 delta_time_largest_observed_us; + if (!reader_->ReadUFloat16(&delta_time_largest_observed_us)) { set_detailed_error("Unable to read delta time largest observed."); return false; } - if (delta_time_largest_observed_us == kInvalidDeltaTime) { + if (delta_time_largest_observed_us == kUFloat16MaxValue) { received_info->delta_time_largest_observed = QuicTime::Delta::Infinite(); } else { received_info->delta_time_largest_observed = QuicTime::Delta::FromMicroseconds(delta_time_largest_observed_us); } - uint8 num_missing_packets; - if (!reader_->ReadBytes(&num_missing_packets, 1)) { - set_detailed_error("Unable to read num missing packets."); + if (!has_nacks) { + return true; + } + + uint8 num_missing_ranges; + if (!reader_->ReadBytes(&num_missing_ranges, 1)) { + set_detailed_error("Unable to read num missing packet ranges."); return false; } - for (int i = 0; i < num_missing_packets; ++i) { - QuicPacketSequenceNumber sequence_number; - if (!ProcessPacketSequenceNumber(PACKET_6BYTE_SEQUENCE_NUMBER, - &sequence_number)) { - set_detailed_error("Unable to read sequence number in missing packets."); + QuicPacketSequenceNumber last_sequence_number = + received_info->largest_observed; + for (size_t i = 0; i < num_missing_ranges; ++i) { + QuicPacketSequenceNumber missing_delta = 0; + if (!reader_->ReadBytes(&missing_delta, missing_sequence_number_length)) { + set_detailed_error("Unable to read missing sequence number delta."); return false; } - received_info->missing_packets.insert(sequence_number); + last_sequence_number -= missing_delta; + QuicPacketSequenceNumber range_length = 0; + if (!reader_->ReadBytes(&range_length, PACKET_1BYTE_SEQUENCE_NUMBER)) { + set_detailed_error("Unable to read missing sequence number range."); + return false; + } + for (size_t i = 0; i <= range_length; ++i) { + received_info->missing_packets.insert(last_sequence_number - i); + } + // Subtract an extra 1 to ensure ranges are represented efficiently and + // can't overlap by 1 sequence number. This allows a missing_delta of 0 + // to represent an adjacent nack range. + last_sequence_number -= (range_length + 1); } return true; } -bool QuicFramer::ProcessSentInfo(SentPacketInfo* sent_info) { +bool QuicFramer::ProcessSentInfo(const QuicPacketHeader& header, + SentPacketInfo* sent_info) { if (!reader_->ReadBytes(&sent_info->entropy_hash, 1)) { set_detailed_error("Unable to read entropy hash for sent packets."); return false; } - if (!ProcessPacketSequenceNumber(PACKET_6BYTE_SEQUENCE_NUMBER, - &sent_info->least_unacked)) { - set_detailed_error("Unable to read least unacked."); + QuicPacketSequenceNumber least_unacked_delta = 0; + if (!reader_->ReadBytes(&least_unacked_delta, + header.public_header.sequence_number_length)) { + set_detailed_error("Unable to read least unacked delta."); return false; } + DCHECK_GE(header.packet_sequence_number, least_unacked_delta); + sent_info->least_unacked = + header.packet_sequence_number - least_unacked_delta; return true; } @@ -1324,7 +1300,7 @@ bool QuicFramer::ProcessQuicCongestionFeedbackFrame( inter_arrival->received_packet_times.insert( make_pair(smallest_received, time_received)); - for (int i = 0; i < num_received_packets - 1; ++i) { + for (uint8 i = 0; i < num_received_packets - 1; ++i) { uint16 sequence_delta; if (!reader_->ReadUInt16(&sequence_delta)) { set_detailed_error( @@ -1362,6 +1338,7 @@ bool QuicFramer::ProcessQuicCongestionFeedbackFrame( "Unable to read accumulated number of lost packets."); return false; } + // TODO(ianswett): Remove receive window, since it's constant. uint16 receive_window = 0; if (!reader_->ReadUInt16(&receive_window)) { set_detailed_error("Unable to read receive window."); @@ -1433,11 +1410,6 @@ bool QuicFramer::ProcessConnectionCloseFrame(QuicConnectionCloseFrame* frame) { } frame->error_details = error_details.as_string(); - if (!ProcessAckFrame(&frame->ack_frame)) { - DLOG(WARNING) << "Unable to process ack frame."; - return false; - } - return true; } @@ -1552,9 +1524,7 @@ QuicEncryptedPacket* QuicFramer::EncryptPacket( size_t QuicFramer::GetMaxPlaintextSize(size_t ciphertext_size) { // In order to keep the code simple, we don't have the current encryption - // level to hand. At the moment, the NullEncrypter has a tag length of 16 - // bytes and AES-GCM has a tag length of 12. We take the minimum plaintext - // length just to be safe. + // level to hand. Both the NullEncrypter and AES-GCM have a tag length of 12. size_t min_plaintext_size = ciphertext_size; for (int i = ENCRYPTION_NONE; i < NUM_ENCRYPTION_LEVELS; i++) { @@ -1613,19 +1583,36 @@ bool QuicFramer::DecryptPayload(const QuicPacketHeader& header, return true; } -size_t QuicFramer::ComputeFrameLength(const QuicFrame& frame, - bool last_frame_in_packet) { +size_t QuicFramer::GetAckFrameSize( + const QuicAckFrame& ack, + QuicSequenceNumberLength sequence_number_length) { + AckFrameInfo ack_info = GetAckFrameInfo(ack); + QuicSequenceNumberLength largest_observed_length = + GetMinSequenceNumberLength(ack.received_info.largest_observed); + QuicSequenceNumberLength missing_sequence_number_length = + GetMinSequenceNumberLength(ack_info.max_delta); + + return GetMinAckFrameSize(quic_version_, + sequence_number_length, + largest_observed_length) + + (ack_info.nack_ranges.empty() ? 0 : kNumberOfMissingPacketsSize) + + ack_info.nack_ranges.size() * + (missing_sequence_number_length + PACKET_1BYTE_SEQUENCE_NUMBER); +} + +size_t QuicFramer::ComputeFrameLength( + const QuicFrame& frame, + bool last_frame_in_packet, + QuicSequenceNumberLength sequence_number_length) { switch (frame.type) { case STREAM_FRAME: return GetMinStreamFrameSize(quic_version_, frame.stream_frame->stream_id, frame.stream_frame->offset, last_frame_in_packet) + - frame.stream_frame->data.size(); + frame.stream_frame->data.TotalBufferSize(); case ACK_FRAME: { - const QuicAckFrame& ack = *frame.ack_frame; - return GetMinAckFrameSize() + PACKET_6BYTE_SEQUENCE_NUMBER * - ack.received_info.missing_packets.size(); + return GetAckFrameSize(*frame.ack_frame, sequence_number_length); } case CONGESTION_FEEDBACK_FRAME: { size_t len = kQuicFrameTypeSize; @@ -1656,7 +1643,7 @@ size_t QuicFramer::ComputeFrameLength(const QuicFrame& frame, break; default: set_detailed_error("Illegal feedback type."); - DLOG(INFO) << "Illegal feedback type: " << congestion_feedback.type; + DVLOG(1) << "Illegal feedback type: " << congestion_feedback.type; break; } return len; @@ -1664,13 +1651,9 @@ size_t QuicFramer::ComputeFrameLength(const QuicFrame& frame, case RST_STREAM_FRAME: return GetMinRstStreamFrameSize() + frame.rst_stream_frame->error_details.size(); - case CONNECTION_CLOSE_FRAME: { - const QuicAckFrame& ack = frame.connection_close_frame->ack_frame; + case CONNECTION_CLOSE_FRAME: return GetMinConnectionCloseFrameSize() + - frame.connection_close_frame->error_details.size() + - PACKET_6BYTE_SEQUENCE_NUMBER * - ack.received_info.missing_packets.size(); - } + frame.connection_close_frame->error_details.size(); case GOAWAY_FRAME: return GetMinGoAwayFrameSize() + frame.goaway_frame->reason_phrase.size(); case PADDING_FRAME: @@ -1712,45 +1695,18 @@ bool QuicFramer::AppendTypeByte(const QuicFrame& frame, // stream id 2 bits. type_byte <<= kQuicStreamIdShift; type_byte |= GetStreamIdSize(frame.stream_frame->stream_id) - 1; - - // TODO(jri): Remove if block when support for QUIC ver. < 10 removed. - if (version() < QUIC_VERSION_10) { - type_byte <<= 1; // Leaves the last bit as a 0. - } else { - type_byte |= kQuicFrameTypeStreamMask; // Set Stream Frame Type to 1. - } - break; - } - case ACK_FRAME: { - // TODO(ianswett): Use extra 5 bits in the ack framing. - // TODO(jri): Remove if block when support for QUIC ver. < 10 removed. - if (version() < QUIC_VERSION_10) { - type_byte = 0x01; - } else { - type_byte = kQuicFrameTypeAckMask; - } + type_byte |= kQuicFrameTypeStreamMask; // Set Stream Frame Type to 1. break; } + case ACK_FRAME: + return true; case CONGESTION_FEEDBACK_FRAME: { // TODO(ianswett): Use extra 5 bits in the congestion feedback framing. - // TODO(jri): Remove if block when support for QUIC ver. < 10 removed. - if (version() < QUIC_VERSION_10) { - type_byte = 0x03; - } else { - type_byte = kQuicFrameTypeCongestionFeedbackMask; - } + type_byte = kQuicFrameTypeCongestionFeedbackMask; break; } default: type_byte = frame.type; - // TODO(jri): Remove if block when support for QUIC ver. < 10 removed. - if (version() < QUIC_VERSION_10) { - if (type_byte > 0) { - type_byte += 3; - } - type_byte = (type_byte << kQuicDefaultFrameTypeShift) | - kQuicDefaultFrameTypeMask; - } break; } @@ -1801,16 +1757,24 @@ bool QuicFramer::AppendStreamFramePayload( return false; } if (!last_frame_in_packet) { - if (!writer->WriteUInt16(frame.data.size())) { + if (!writer->WriteUInt16(frame.data.TotalBufferSize())) { return false; } } - if (!writer->WriteBytes(frame.data.data(), frame.data.size())) { + + if (!writer->WriteIOVector(frame.data)) { return false; } return true; } +// static +bool QuicFramer::HasVersionFlag(const QuicEncryptedPacket& packet) { + return packet.length() > 0 && + (packet.data()[0] & PACKET_PUBLIC_FLAGS_VERSION) != 0; +} + +// static QuicPacketSequenceNumber QuicFramer::CalculateLargestObserved( const SequenceNumberSet& missing_packets, SequenceNumberSet::const_iterator largest_written) { @@ -1828,77 +1792,143 @@ QuicPacketSequenceNumber QuicFramer::CalculateLargestObserved( return *largest_written; } -// TODO(ianswett): Use varints or another more compact approach for all deltas. -bool QuicFramer::AppendAckFramePayload( +void QuicFramer::set_version(const QuicVersion version) { + DCHECK(IsSupportedVersion(version)); + quic_version_ = version; +} + +bool QuicFramer::AppendAckFramePayloadAndTypeByte( + const QuicPacketHeader& header, const QuicAckFrame& frame, QuicDataWriter* writer) { + AckFrameInfo ack_info = GetAckFrameInfo(frame); + QuicPacketSequenceNumber ack_largest_observed = + frame.received_info.largest_observed; + QuicSequenceNumberLength largest_observed_length = + GetMinSequenceNumberLength(ack_largest_observed); + QuicSequenceNumberLength missing_sequence_number_length = + GetMinSequenceNumberLength(ack_info.max_delta); + // Determine whether we need to truncate ranges. + size_t available_range_bytes = writer->capacity() - writer->length() - + GetMinAckFrameSize(quic_version_, + header.public_header.sequence_number_length, + largest_observed_length); + size_t max_num_ranges = available_range_bytes / + (missing_sequence_number_length + PACKET_1BYTE_SEQUENCE_NUMBER); + max_num_ranges = + min(static_cast<size_t>(numeric_limits<uint8>::max()), max_num_ranges); + bool truncated = ack_info.nack_ranges.size() > max_num_ranges; + DVLOG_IF(1, truncated) << "Truncating ack from " + << ack_info.nack_ranges.size() << " ranges to " + << max_num_ranges; + + // Write out the type byte by setting the low order bits and doing shifts + // to make room for the next bit flags to be set. + // Whether there are any nacks. + uint8 type_byte = ack_info.nack_ranges.empty() ? 0 : kQuicHasNacksMask; + + // truncating bit. + type_byte <<= kQuicAckTruncatedShift; + type_byte |= truncated ? kQuicAckTruncatedMask : 0; + + // Largest observed sequence number length. + type_byte <<= kQuicSequenceNumberLengthShift; + type_byte |= GetSequenceNumberFlags(largest_observed_length); + + // Missing sequence number length. + type_byte <<= kQuicSequenceNumberLengthShift; + type_byte |= GetSequenceNumberFlags(missing_sequence_number_length); + + type_byte |= kQuicFrameTypeAckMask; + + if (!writer->WriteUInt8(type_byte)) { + return false; + } + // TODO(satyamshekhar): Decide how often we really should send this // entropy_hash update. if (!writer->WriteUInt8(frame.sent_info.entropy_hash)) { return false; } - if (!AppendPacketSequenceNumber(PACKET_6BYTE_SEQUENCE_NUMBER, - frame.sent_info.least_unacked, writer)) { + DCHECK_GE(header.packet_sequence_number, frame.sent_info.least_unacked); + const QuicPacketSequenceNumber least_unacked_delta = + header.packet_sequence_number - frame.sent_info.least_unacked; + if (!AppendPacketSequenceNumber(header.public_header.sequence_number_length, + least_unacked_delta, writer)) { return false; } - size_t received_entropy_offset = writer->length(); - if (!writer->WriteUInt8(frame.received_info.entropy_hash)) { + const ReceivedPacketInfo& received_info = frame.received_info; + QuicPacketEntropyHash ack_entropy_hash = received_info.entropy_hash; + NackRangeMap::reverse_iterator ack_iter = ack_info.nack_ranges.rbegin(); + if (truncated) { + // Skip the nack ranges which the truncated ack won't include and set + // a correct largest observed for the truncated ack. + for (size_t i = 1; i < (ack_info.nack_ranges.size() - max_num_ranges); + ++i) { + ++ack_iter; + } + // If the last range is followed by acks, include them. + // If the last range is followed by another range, specify the end of the + // range as the largest_observed. + ack_largest_observed = ack_iter->first - 1; + // Also update the entropy so it matches the largest observed. + ack_entropy_hash = entropy_calculator_->EntropyHash(ack_largest_observed); + ++ack_iter; + } + + if (!writer->WriteUInt8(ack_entropy_hash)) { return false; } - size_t largest_observed_offset = writer->length(); - if (!AppendPacketSequenceNumber(PACKET_6BYTE_SEQUENCE_NUMBER, - frame.received_info.largest_observed, - writer)) { + if (!AppendPacketSequenceNumber(largest_observed_length, + ack_largest_observed, writer)) { return false; } - uint32 delta_time_largest_observed_us = kInvalidDeltaTime; - if (!frame.received_info.delta_time_largest_observed.IsInfinite()) { + + uint64 delta_time_largest_observed_us = kUFloat16MaxValue; + if (!received_info.delta_time_largest_observed.IsInfinite()) { + DCHECK_LE(0u, + frame.received_info.delta_time_largest_observed.ToMicroseconds()); delta_time_largest_observed_us = - frame.received_info.delta_time_largest_observed.ToMicroseconds(); + received_info.delta_time_largest_observed.ToMicroseconds(); } - size_t delta_time_largest_observed_offset = writer->length(); - if (!writer->WriteUInt32(delta_time_largest_observed_us)) { + if (!writer->WriteUFloat16(delta_time_largest_observed_us)) { return false; } - // We don't check for overflowing uint8 here, because we only can fit 192 acks - // per packet, so if we overflow we will be truncated. - uint8 num_missing_packets = frame.received_info.missing_packets.size(); - size_t num_missing_packets_offset = writer->length(); - if (!writer->WriteBytes(&num_missing_packets, 1)) { + if (ack_info.nack_ranges.empty()) { + return true; + } + + const uint8 num_missing_ranges = + min(ack_info.nack_ranges.size(), max_num_ranges); + if (!writer->WriteBytes(&num_missing_ranges, 1)) { return false; } - SequenceNumberSet::const_iterator it = - frame.received_info.missing_packets.begin(); - int num_missing_packets_written = 0; - for (; it != frame.received_info.missing_packets.end(); ++it) { - if (!AppendPacketSequenceNumber(PACKET_6BYTE_SEQUENCE_NUMBER, - *it, writer)) { - // We are truncating. - QuicPacketSequenceNumber largest_observed = - CalculateLargestObserved(frame.received_info.missing_packets, --it); - // Overwrite entropy hash for received packets. - writer->WriteUInt8ToOffset( - entropy_calculator_->EntropyHash(largest_observed), - received_entropy_offset); - // Overwrite largest_observed. - writer->WriteUInt48ToOffset(largest_observed & k6ByteSequenceNumberMask, - largest_observed_offset); - writer->WriteUInt32ToOffset(kInvalidDeltaTime, - delta_time_largest_observed_offset); - writer->WriteUInt8ToOffset(num_missing_packets_written, - num_missing_packets_offset); - return true; + int num_ranges_written = 0; + QuicPacketSequenceNumber last_sequence_written = ack_largest_observed; + for (; ack_iter != ack_info.nack_ranges.rend(); ++ack_iter) { + // Calculate the delta to the last number in the range. + QuicPacketSequenceNumber missing_delta = + last_sequence_written - (ack_iter->first + ack_iter->second); + if (!AppendPacketSequenceNumber(missing_sequence_number_length, + missing_delta, writer)) { + return false; + } + if (!AppendPacketSequenceNumber(PACKET_1BYTE_SEQUENCE_NUMBER, + ack_iter->second, writer)) { + return false; } - ++num_missing_packets_written; - DCHECK_GE(numeric_limits<uint8>::max(), num_missing_packets_written); + // Subtract 1 so a missing_delta of 0 means an adjacent range. + last_sequence_written = ack_iter->first - 1; + ++num_ranges_written; } + DCHECK_EQ(num_missing_ranges, num_ranges_written); return true; } @@ -2020,7 +2050,6 @@ bool QuicFramer::AppendConnectionCloseFramePayload( if (!writer->WriteStringPiece16(frame.error_details)) { return false; } - AppendAckFramePayload(frame.ack_frame, writer); return true; } @@ -2041,7 +2070,7 @@ bool QuicFramer::AppendGoAwayFramePayload(const QuicGoAwayFrame& frame, } bool QuicFramer::RaiseError(QuicErrorCode error) { - DLOG(INFO) << detailed_error_; + DVLOG(1) << detailed_error_; set_error(error); visitor_->OnError(this); reader_.reset(NULL); |