| Index: net/quic/quic_framer.cc
|
| diff --git a/net/quic/quic_framer.cc b/net/quic/quic_framer.cc
|
| index fe705015c1ed98e677ca81155c5c6e6ba9a58ead..84c6b308417e6a0b036c4c8cce36a729ec0d3d7e 100644
|
| --- a/net/quic/quic_framer.cc
|
| +++ b/net/quic/quic_framer.cc
|
| @@ -132,16 +132,6 @@ QuicSequenceNumberLength ReadSequenceNumberLength(uint8 flags) {
|
| }
|
| }
|
|
|
| -bool CanTruncate(const QuicFrame& frame, size_t free_bytes) {
|
| - if ((frame.type == ACK_FRAME || frame.type == CONNECTION_CLOSE_FRAME) &&
|
| - free_bytes >=
|
| - QuicFramer::GetMinAckFrameSize(PACKET_6BYTE_SEQUENCE_NUMBER,
|
| - PACKET_6BYTE_SEQUENCE_NUMBER)) {
|
| - return true;
|
| - }
|
| - return false;
|
| -}
|
| -
|
| } // namespace
|
|
|
| bool QuicFramerVisitorInterface::OnWindowUpdateFrame(
|
| @@ -168,7 +158,8 @@ QuicFramer::QuicFramer(const QuicVersionVector& supported_versions,
|
| alternative_decrypter_latch_(false),
|
| is_server_(is_server),
|
| validate_flags_(true),
|
| - creation_time_(creation_time) {
|
| + creation_time_(creation_time),
|
| + last_timestamp_(QuicTime::Delta::Zero()) {
|
| DCHECK(!supported_versions.empty());
|
| quic_version_ = supported_versions_[0];
|
| decrypter_.reset(QuicDecrypter::Create(kNULL));
|
| @@ -302,7 +293,10 @@ size_t QuicFramer::GetSerializedFrameLength(
|
| if (!first_frame) {
|
| return 0;
|
| }
|
| - if (CanTruncate(frame, free_bytes)) {
|
| + bool can_truncate = frame.type == ACK_FRAME &&
|
| + free_bytes >= GetMinAckFrameSize(PACKET_6BYTE_SEQUENCE_NUMBER,
|
| + PACKET_6BYTE_SEQUENCE_NUMBER);
|
| + if (can_truncate) {
|
| // Truncate the frame so the packet will not exceed kMaxPacketSize.
|
| // Note that we may not use every byte of the writer in this case.
|
| DVLOG(1) << "Truncating large frame, free bytes: " << free_bytes;
|
| @@ -807,6 +801,30 @@ bool QuicFramer::AppendPacketHeader(const QuicPacketHeader& header,
|
| return true;
|
| }
|
|
|
| +const QuicTime::Delta QuicFramer::CalculateTimestampFromWire(
|
| + uint32 time_delta_us) {
|
| + // The new time_delta might have wrapped to the next epoch, or it
|
| + // might have reverse wrapped to the previous epoch, or it might
|
| + // remain in the same epoch. Select the time closest to the previous
|
| + // time.
|
| + //
|
| + // epoch_delta is the delta between epochs. A delta is 4 bytes of
|
| + // microseconds.
|
| + const uint64 epoch_delta = GG_UINT64_C(1) << 32;
|
| + uint64 epoch = last_timestamp_.ToMicroseconds() & ~(epoch_delta - 1);
|
| + // Wrapping is safe here because a wrapped value will not be ClosestTo below.
|
| + uint64 prev_epoch = epoch - epoch_delta;
|
| + uint64 next_epoch = epoch + epoch_delta;
|
| +
|
| + uint64 time = ClosestTo(last_timestamp_.ToMicroseconds(),
|
| + epoch + time_delta_us,
|
| + ClosestTo(last_timestamp_.ToMicroseconds(),
|
| + prev_epoch + time_delta_us,
|
| + next_epoch + time_delta_us));
|
| +
|
| + return QuicTime::Delta::FromMicroseconds(time);
|
| +}
|
| +
|
| QuicPacketSequenceNumber QuicFramer::CalculatePacketSequenceNumberFromWire(
|
| QuicSequenceNumberLength sequence_number_length,
|
| QuicPacketSequenceNumber packet_sequence_number) const {
|
| @@ -1110,8 +1128,12 @@ bool QuicFramer::ProcessFrameData(const QuicPacketHeader& header) {
|
|
|
| // Congestion Feedback Frame
|
| if (frame_type & kQuicFrameTypeCongestionFeedbackMask) {
|
| + if (quic_version_ > QUIC_VERSION_22) {
|
| + set_detailed_error("Congestion Feedback Frame has been deprecated.");
|
| + DLOG(WARNING) << "Congestion Feedback Frame has been deprecated.";
|
| + }
|
| QuicCongestionFeedbackFrame frame;
|
| - if (!ProcessQuicCongestionFeedbackFrame(&frame)) {
|
| + if (!ProcessCongestionFeedbackFrame(&frame)) {
|
| return RaiseError(QUIC_INVALID_CONGESTION_FEEDBACK_DATA);
|
| }
|
| if (!visitor_->OnCongestionFeedbackFrame(frame)) {
|
| @@ -1333,6 +1355,10 @@ bool QuicFramer::ProcessAckFrame(uint8 frame_type, QuicAckFrame* ack_frame) {
|
| QuicTime::Delta::FromMicroseconds(delta_time_largest_observed_us);
|
| }
|
|
|
| + if (!ProcessTimestampsInAckFrame(ack_frame)) {
|
| + return false;
|
| + }
|
| +
|
| if (!has_nacks) {
|
| return true;
|
| }
|
| @@ -1386,6 +1412,64 @@ bool QuicFramer::ProcessAckFrame(uint8 frame_type, QuicAckFrame* ack_frame) {
|
| return true;
|
| }
|
|
|
| +bool QuicFramer::ProcessTimestampsInAckFrame(QuicAckFrame* ack_frame) {
|
| + if (version() > QUIC_VERSION_22 && !ack_frame->is_truncated) {
|
| + uint8 num_received_packets;
|
| + if (!reader_->ReadBytes(&num_received_packets, 1)) {
|
| + set_detailed_error("Unable to read num received packets.");
|
| + return false;
|
| + }
|
| +
|
| + if (num_received_packets > 0) {
|
| + uint8 delta_from_largest_observed;
|
| + if (!reader_->ReadBytes(&delta_from_largest_observed,
|
| + PACKET_1BYTE_SEQUENCE_NUMBER)) {
|
| + set_detailed_error(
|
| + "Unable to read sequence delta in received packets.");
|
| + return false;
|
| + }
|
| + QuicPacketSequenceNumber seq_num = ack_frame->largest_observed -
|
| + delta_from_largest_observed;
|
| +
|
| + // Time delta from the framer creation.
|
| + uint32 time_delta_us;
|
| + if (!reader_->ReadBytes(&time_delta_us, sizeof(time_delta_us))) {
|
| + set_detailed_error("Unable to read time delta in received packets.");
|
| + return false;
|
| + }
|
| +
|
| + last_timestamp_ = CalculateTimestampFromWire(time_delta_us);
|
| +
|
| + ack_frame->received_packet_times.push_back(
|
| + make_pair(seq_num, creation_time_.Add(last_timestamp_)));
|
| +
|
| + for (uint8 i = 1; i < num_received_packets; ++i) {
|
| + if (!reader_->ReadBytes(&delta_from_largest_observed,
|
| + PACKET_1BYTE_SEQUENCE_NUMBER)) {
|
| + set_detailed_error(
|
| + "Unable to read sequence delta in received packets.");
|
| + return false;
|
| + }
|
| + seq_num = ack_frame->largest_observed - delta_from_largest_observed;
|
| +
|
| + // Time delta from the previous timestamp.
|
| + uint64 incremental_time_delta_us;
|
| + if (!reader_->ReadUFloat16(&incremental_time_delta_us)) {
|
| + set_detailed_error(
|
| + "Unable to read incremental time delta in received packets.");
|
| + return false;
|
| + }
|
| +
|
| + last_timestamp_ = last_timestamp_.Add(
|
| + QuicTime::Delta::FromMicroseconds(incremental_time_delta_us));
|
| + ack_frame->received_packet_times.push_back(
|
| + make_pair(seq_num, creation_time_.Add(last_timestamp_)));
|
| + }
|
| + }
|
| + }
|
| + return true;
|
| +}
|
| +
|
| bool QuicFramer::ProcessStopWaitingFrame(const QuicPacketHeader& header,
|
| QuicStopWaitingFrame* stop_waiting) {
|
| if (!reader_->ReadBytes(&stop_waiting->entropy_hash, 1)) {
|
| @@ -1406,7 +1490,7 @@ bool QuicFramer::ProcessStopWaitingFrame(const QuicPacketHeader& header,
|
| return true;
|
| }
|
|
|
| -bool QuicFramer::ProcessQuicCongestionFeedbackFrame(
|
| +bool QuicFramer::ProcessCongestionFeedbackFrame(
|
| QuicCongestionFeedbackFrame* frame) {
|
| uint8 feedback_type;
|
| if (!reader_->ReadBytes(&feedback_type, 1)) {
|
| @@ -1417,10 +1501,6 @@ bool QuicFramer::ProcessQuicCongestionFeedbackFrame(
|
| static_cast<CongestionFeedbackType>(feedback_type);
|
|
|
| switch (frame->type) {
|
| - case kTimestamp: {
|
| - set_detailed_error("Timestamp feedback not supported.");
|
| - return false;
|
| - }
|
| case kTCP: {
|
| CongestionFeedbackMessageTCP* tcp = &frame->tcp;
|
| uint16 receive_window = 0;
|
| @@ -1716,6 +1796,24 @@ size_t QuicFramer::GetAckFrameSize(
|
| ack_size += min(ack.revived_packets.size(),
|
| kMaxRevivedPackets) * largest_observed_length;
|
| }
|
| +
|
| + // In version 23, if the ack will be truncated due to too many nack ranges,
|
| + // then do not include the number of timestamps (1 byte).
|
| + if (version() > QUIC_VERSION_22 &&
|
| + ack_info.nack_ranges.size() <= kMaxNackRanges) {
|
| + // 1 byte for the number of timestamps.
|
| + ack_size += 1;
|
| + if (ack.received_packet_times.size() > 0) {
|
| + // 1 byte for sequence number, 4 bytes for timestamp for the first
|
| + // packet.
|
| + ack_size += 5;
|
| +
|
| + // 1 byte for sequence number, 2 bytes for timestamp for the other
|
| + // packets.
|
| + ack_size += 3 * (ack.received_packet_times.size() - 1);
|
| + }
|
| + }
|
| +
|
| return ack_size;
|
| }
|
|
|
| @@ -1741,10 +1839,6 @@ size_t QuicFramer::ComputeFrameLength(
|
| len += 1; // Congestion feedback type.
|
|
|
| switch (congestion_feedback.type) {
|
| - case kTimestamp: {
|
| - set_detailed_error("Timestamp feedback not supported.");
|
| - break;
|
| - }
|
| case kTCP:
|
| len += 2; // Receive window.
|
| break;
|
| @@ -1977,6 +2071,13 @@ bool QuicFramer::AppendAckFrameAndTypeByte(
|
| return false;
|
| }
|
|
|
| + // Timestamp goes at the end of the required fields.
|
| + if (version() > QUIC_VERSION_22 && !truncated) {
|
| + if (!AppendTimestampToAckFrame(frame, writer)) {
|
| + return false;
|
| + }
|
| + }
|
| +
|
| if (ack_info.nack_ranges.empty()) {
|
| return true;
|
| }
|
| @@ -2038,10 +2139,6 @@ bool QuicFramer::AppendCongestionFeedbackFrame(
|
| }
|
|
|
| switch (frame.type) {
|
| - case kTimestamp: {
|
| - // Timestamp feedback not supported.
|
| - return false;
|
| - }
|
| case kTCP: {
|
| const CongestionFeedbackMessageTCP& tcp = frame.tcp;
|
| DCHECK_LE(tcp.receive_window, 1u << 20);
|
| @@ -2059,6 +2156,72 @@ bool QuicFramer::AppendCongestionFeedbackFrame(
|
| return true;
|
| }
|
|
|
| +bool QuicFramer::AppendTimestampToAckFrame(const QuicAckFrame& frame,
|
| + QuicDataWriter* writer) {
|
| + DCHECK_GE(version(), QUIC_VERSION_23);
|
| + DCHECK_GE(numeric_limits<uint8>::max(), frame.received_packet_times.size());
|
| + // num_received_packets is only 1 byte.
|
| + if (frame.received_packet_times.size() > numeric_limits<uint8>::max()) {
|
| + return false;
|
| + }
|
| +
|
| + uint8 num_received_packets = frame.received_packet_times.size();
|
| +
|
| + if (!writer->WriteBytes(&num_received_packets, 1)) {
|
| + return false;
|
| + }
|
| + if (num_received_packets == 0) {
|
| + return true;
|
| + }
|
| +
|
| + PacketTimeList::const_iterator it = frame.received_packet_times.begin();
|
| + QuicPacketSequenceNumber sequence_number = it->first;
|
| + QuicPacketSequenceNumber delta_from_largest_observed =
|
| + frame.largest_observed - sequence_number;
|
| +
|
| + DCHECK_GE(numeric_limits<uint8>::max(), delta_from_largest_observed);
|
| + if (delta_from_largest_observed > numeric_limits<uint8>::max()) {
|
| + return false;
|
| + }
|
| +
|
| + if (!writer->WriteUInt8(
|
| + delta_from_largest_observed & k1ByteSequenceNumberMask)) {
|
| + return false;
|
| + }
|
| +
|
| + // Use the lowest 4 bytes of the time delta from the creation_time_.
|
| + const uint64 time_epoch_delta_us = GG_UINT64_C(1) << 32;
|
| + uint32 time_delta_us =
|
| + static_cast<uint32>(it->second.Subtract(creation_time_).ToMicroseconds()
|
| + & (time_epoch_delta_us - 1));
|
| + if (!writer->WriteBytes(&time_delta_us, sizeof(time_delta_us))) {
|
| + return false;
|
| + }
|
| +
|
| + QuicTime prev_time = it->second;
|
| +
|
| + for (++it; it != frame.received_packet_times.end(); ++it) {
|
| + sequence_number = it->first;
|
| + delta_from_largest_observed = frame.largest_observed - sequence_number;
|
| +
|
| + if (delta_from_largest_observed > numeric_limits<uint8>::max()) {
|
| + return false;
|
| + }
|
| +
|
| + if (!writer->WriteUInt8(
|
| + delta_from_largest_observed & k1ByteSequenceNumberMask)) {
|
| + return false;
|
| + }
|
| +
|
| + uint64 time_delta_us = it->second.Subtract(prev_time).ToMicroseconds();
|
| + prev_time = it->second;
|
| + if (!writer->WriteUFloat16(time_delta_us)) {
|
| + return false;
|
| + }
|
| + }
|
| + return true;
|
| +}
|
| +
|
| bool QuicFramer::AppendStopWaitingFrame(
|
| const QuicPacketHeader& header,
|
| const QuicStopWaitingFrame& frame,
|
|
|