Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(493)

Unified Diff: net/quic/quic_framer.cc

Issue 478153003: Change the wire format of the ack frame to include a compressed version (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase TOT and pass clock to QuicTestPacketMaker and use it in AckPacket Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/quic/quic_framer.h ('k') | net/quic/quic_framer_test.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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,
« no previous file with comments | « net/quic/quic_framer.h ('k') | net/quic/quic_framer_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698