summaryrefslogtreecommitdiffstats
path: root/net/quic/quic_framer.cc
diff options
context:
space:
mode:
authorrch@chromium.org <rch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-02-25 05:27:03 +0000
committerrch@chromium.org <rch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-02-25 05:27:03 +0000
commit9db4439170f43fb458827d4731ac24211ddb6ecf (patch)
tree94d350faaa0024fd030fdd9c0d4f41bff86d4139 /net/quic/quic_framer.cc
parent5729f4ac33ddeb87b632c858b4a502f43392c938 (diff)
downloadchromium_src-9db4439170f43fb458827d4731ac24211ddb6ecf.zip
chromium_src-9db4439170f43fb458827d4731ac24211ddb6ecf.tar.gz
chromium_src-9db4439170f43fb458827d4731ac24211ddb6ecf.tar.bz2
Land recent QUIC changes.
Reviving entropy flag of missing packet. Merge internal change: 42912121 Fix bug in QuicConnection::OnCanWrite in which the packet generator never flushed the packets when the visitor did not write all bytes. Merge internal change: 42919513 Clarify the SendAlarm behavior of the TestHelper in QuicConnectionTests. In particular, it is important that if we set a send alarm for a delay of Zero, that IsSendAlarmSet() returns true. Merge internal change: 42908913 Fix bug in SimpleQuicFramerVisitor which did not make a copy of StreamFrame data. Merge internal change: 42880797 Use the QuicPacketGenerator in QuicConnection. Merge internal change: 42861764 Add new files Create a new QuicPacketGenerator class to encapsulate the write side operation of a QuicConnection. It provides methods for enqueing control frames, consuming stream data, and sending acks and feedback. It does just-in-time serialization. Also adds a new test-only simple framer which provides an easy mechanism for parsing packets to verify they contain correct contents. Merge internal change: 42813986 Add missing files Implementing logic for checking entropy of received packets and setting entropy on outgoing packets. Merge internal change: 42715914 Fixing a bug where when QuicPacketCreator queues a stream frame, the underlying string is not immediately owned, which can cause issues if SendStreamData doesn't always flush packets before exiting. Merge internal change: 42649091 Add the SetKey, SetNoncePrefix, GetKeySize, and GetNoncePrefixSize methods to the QuicEncrypter and QuicDecrypter interfaces. Specify the format of the nonce for AEAD algorithms. Add a |packet_sequence_number| argument to QuicEncrypter::Encrypt and QuicDecrypter::Decrypt. This requires passing the packet sequence number to QuicFramer::EncryptPacket and QuicFramer::DecryptPayload. Merge internal change: 42641062 Move all logic out of ReceivedInfo. Now it is just a plain struct that is used to represent the state of the received packets info. Also, fixes the following bug: i) Packet 7 8 get lost, largest observed packet is 6. ii) Packet 9 arrives with an AckFrame which has least unacked as 9. iii) We clear 7 8 from missing packets. iv) While adding packet 9 we reinsert 7 and 8 as missing packets since largest observed is 6. Merge internal change: 42556974 Make framer return SerializedPacket instead of QuicPacket. Merge internal change: 42551314 Add SendConnectionClosePacket method to QuicConnection Merge internal change: 42474257 Removing offset from the reset stream frame. Merge internal change: 42436913 Fix for when the end of a frame leave too few bytes for the next header Merge internal change: 42435044 Bug fix for packet loss in inter arrival. Added min drift threshold for inter arrival. Merge internal change: 42391696 Add missing file. Use linked_hash_map to store UnackedPackets: simplifies and optimizes the code. Merge internal change: 42381785 Bugfix "Flaky tests due to QuicTime not initialized" Removed DCHECK that due to timing was invalid Merge internal change: 42374053 Fix TSAN test failure. Merge internal change: 42371302 A simple tcp tail drop like implementation. Merge internal change: 42314912 Adding the GoAway Frame. Merge internal change: 42291652 Chromium review fixes. Merge internal change: 42290161 Implement framing for entropy in AckFrame. Merge internal change: 42286308 Make QuicPacketCreator return SerializedPacket struct. Merge internal change: 42240179 Fix for incoming duplicate packet. Avoids NACKing a duplicate. Merge internal change: 42150291 Remove QuicConnectionVisitorInterface::AckedPackets and use the existing SequenceSet typedef instead. Renamed SequenceSet to SequenceNumberSet to be more readable. Merge internal change: 42147690 Made ramp up bitrate in inter arrival aware of the current send rate. Merge internal change: 42118607 Style fix of full_packet. Merge internal change: 42057032 Packing multiple streams together in a single packet from OnCanWrite. Merge internal change: 42054845 Change the representation of public and private flags to explicts bools. Using enums turns out to be problematic because ENUM1 | ENUM2 can not be assigned to EnumType. I discovered this problem in attempting to implement version negotiation. Merge internal change: 42042022 Various small QUIC cleanups after merging to Chrome. Merge internal change: 42041347 Start using QuicClock Now where needed and sending it around instead of querying it multiple times. This CL also fixes the reports of incoming lost packets which had been lost. Merge internal change: 41944659 Fix mock clock. Adding Now function back to QuicClock but now as a more accurate now Merge internal change: 41909929 Rename of function Now to ApproximateNow to allow us to differentiate between the two in the future. Merge internal change: 41909178 TBR=jar@chromium.org R=jar@chromium.org BUG= Review URL: https://chromiumcodereview.appspot.com/12334063 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@184374 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/quic/quic_framer.cc')
-rw-r--r--net/quic/quic_framer.cc260
1 files changed, 193 insertions, 67 deletions
diff --git a/net/quic/quic_framer.cc b/net/quic/quic_framer.cc
index a794701..db3de8d5 100644
--- a/net/quic/quic_framer.cc
+++ b/net/quic/quic_framer.cc
@@ -86,8 +86,19 @@ size_t QuicFramer::GetSerializedFrameLength(
return frame_len;
}
-QuicPacket* QuicFramer::ConstructFrameDataPacket(const QuicPacketHeader& header,
- const QuicFrames& frames) {
+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);
+}
+
+SerializedPacket QuicFramer::ConstructFrameDataPacket(
+ const QuicPacketHeader& header,
+ const QuicFrames& frames) {
const size_t max_plaintext_size = GetMaxPlaintextSize(kMaxPacketSize);
size_t packet_size = kPacketHeaderSize;
for (size_t i = 0; i < frames.size(); ++i) {
@@ -100,18 +111,20 @@ QuicPacket* QuicFramer::ConstructFrameDataPacket(const QuicPacketHeader& header,
return ConstructFrameDataPacket(header, frames, packet_size);
}
-QuicPacket* QuicFramer::ConstructFrameDataPacket(const QuicPacketHeader& header,
- const QuicFrames& frames,
- size_t packet_size) {
+SerializedPacket QuicFramer::ConstructFrameDataPacket(
+ const QuicPacketHeader& header,
+ const QuicFrames& frames,
+ size_t packet_size) {
QuicDataWriter writer(packet_size);
+ SerializedPacket kNoPacket = SerializedPacket(0, NULL, 0, NULL);
if (!WritePacketHeader(header, &writer)) {
- return NULL;
+ return kNoPacket;
}
for (size_t i = 0; i < frames.size(); ++i) {
const QuicFrame& frame = frames[i];
if (!writer.WriteUInt8(frame.type)) {
- return NULL;
+ return kNoPacket;
}
switch (frame.type) {
@@ -120,34 +133,39 @@ QuicPacket* QuicFramer::ConstructFrameDataPacket(const QuicPacketHeader& header,
break;
case STREAM_FRAME:
if (!AppendStreamFramePayload(*frame.stream_frame, &writer)) {
- return NULL;
+ return kNoPacket;
}
break;
case ACK_FRAME:
if (!AppendAckFramePayload(*frame.ack_frame, &writer)) {
- return NULL;
+ return kNoPacket;
}
break;
case CONGESTION_FEEDBACK_FRAME:
if (!AppendQuicCongestionFeedbackFramePayload(
*frame.congestion_feedback_frame, &writer)) {
- return NULL;
+ return kNoPacket;
}
break;
case RST_STREAM_FRAME:
if (!AppendRstStreamFramePayload(*frame.rst_stream_frame, &writer)) {
- return NULL;
+ return kNoPacket;
}
break;
case CONNECTION_CLOSE_FRAME:
if (!AppendConnectionCloseFramePayload(
*frame.connection_close_frame, &writer)) {
- return NULL;
+ return kNoPacket;
+ }
+ break;
+ case GOAWAY_FRAME:
+ if (!AppendGoAwayFramePayload(*frame.goaway_frame, &writer)) {
+ return kNoPacket;
}
break;
default:
RaiseError(QUIC_INVALID_FRAME_DATA);
- return NULL;
+ return kNoPacket;
}
}
@@ -163,32 +181,35 @@ QuicPacket* QuicFramer::ConstructFrameDataPacket(const QuicPacketHeader& header,
packet->FecProtectedData());
}
- return packet;
+ return SerializedPacket(header.packet_sequence_number, packet,
+ GetPacketEntropyHash(header), NULL);
}
-QuicPacket* QuicFramer::ConstructFecPacket(const QuicPacketHeader& header,
- const QuicFecData& fec) {
+SerializedPacket QuicFramer::ConstructFecPacket(const QuicPacketHeader& header,
+ const QuicFecData& fec) {
size_t len = kPacketHeaderSize;
len += fec.redundancy.length();
QuicDataWriter writer(len);
-
+ SerializedPacket kNoPacket = SerializedPacket(0, NULL, 0, NULL);
if (!WritePacketHeader(header, &writer)) {
- return NULL;
+ return kNoPacket;
}
if (!writer.WriteBytes(fec.redundancy.data(), fec.redundancy.length())) {
- return NULL;
+ return kNoPacket;
}
- return QuicPacket::NewFecPacket(writer.take(), len, true);
+ return SerializedPacket(header.packet_sequence_number,
+ QuicPacket::NewFecPacket(writer.take(), len, true),
+ GetPacketEntropyHash(header), NULL);
}
// static
QuicEncryptedPacket* QuicFramer::ConstructPublicResetPacket(
const QuicPublicResetPacket& packet) {
- DCHECK_EQ(PACKET_PUBLIC_FLAGS_RST,
- PACKET_PUBLIC_FLAGS_RST & packet.public_header.flags);
+ DCHECK(packet.public_header.reset_flag);
+ DCHECK(!packet.public_header.version_flag);
size_t len = kPublicResetPacketSize;
QuicDataWriter writer(len);
@@ -196,7 +217,7 @@ QuicEncryptedPacket* QuicFramer::ConstructPublicResetPacket(
return NULL;
}
- uint8 flags = static_cast<uint8>(packet.public_header.flags);
+ uint8 flags = static_cast<uint8>(PACKET_PUBLIC_FLAGS_RST);
if (!writer.WriteUInt8(flags)) {
return NULL;
}
@@ -226,7 +247,7 @@ bool QuicFramer::ProcessPacket(const QuicEncryptedPacket& packet) {
}
bool rv;
- if (public_header.flags & PACKET_PUBLIC_FLAGS_RST) {
+ if (public_header.reset_flag) {
rv = ProcessPublicResetPacket(public_header);
} else {
rv = ProcessDataPacket(public_header, packet);
@@ -257,7 +278,7 @@ bool QuicFramer::ProcessDataPacket(
}
// Handle the payload.
- if ((header.private_flags & PACKET_PRIVATE_FLAGS_FEC) == 0) {
+ if (!header.fec_flag) {
if (header.fec_group != 0) {
StringPiece payload = reader_->PeekRemainingPayload();
visitor_->OnFecProtectedPayload(payload);
@@ -295,13 +316,16 @@ bool QuicFramer::ProcessPublicResetPacket(
return true;
}
-bool QuicFramer::ProcessRevivedPacket(const QuicPacketHeader& header,
+bool QuicFramer::ProcessRevivedPacket(QuicPacketHeader* header,
StringPiece payload) {
DCHECK(!reader_.get());
visitor_->OnRevivedPacket();
- visitor_->OnPacketHeader(header);
+ header->entropy_hash = GetPacketEntropyHash(*header);
+
+ // TODO(satyamshekhar): Don't process if the visitor refuses the header.
+ visitor_->OnPacketHeader(*header);
if (payload.length() > kMaxPacketSize) {
set_detailed_error("Revived packet too large.");
@@ -326,7 +350,13 @@ bool QuicFramer::WritePacketHeader(const QuicPacketHeader& header,
return false;
}
- uint8 flags = static_cast<uint8>(header.public_header.flags);
+ uint8 flags = 0;
+ if (header.public_header.reset_flag) {
+ flags |= PACKET_PUBLIC_FLAGS_RST;
+ }
+ if (header.public_header.version_flag) {
+ flags |= PACKET_PUBLIC_FLAGS_VERSION;
+ }
if (!writer->WriteUInt8(flags)) {
return false;
}
@@ -335,7 +365,16 @@ bool QuicFramer::WritePacketHeader(const QuicPacketHeader& header,
return false;
}
- flags = static_cast<uint8>(header.private_flags);
+ flags = 0;
+ if (header.fec_flag) {
+ flags |= PACKET_PRIVATE_FLAGS_FEC;
+ }
+ if (header.entropy_flag) {
+ flags |= PACKET_PRIVATE_FLAGS_ENTROPY;
+ }
+ if (header.fec_entropy_flag) {
+ flags |= PACKET_PRIVATE_FLAGS_FEC_ENTROPY;
+ }
if (!writer->WriteUInt8(flags)) {
return false;
}
@@ -361,7 +400,7 @@ bool QuicFramer::WritePacketHeader(const QuicPacketHeader& header,
QuicPacketSequenceNumber QuicFramer::CalculatePacketSequenceNumberFromWire(
QuicPacketSequenceNumber packet_sequence_number) const {
- // The new sequence number might have wrapped to the next epoc, or
+ // The new sequence number 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 sequence number closest to the
// previous sequence number.
@@ -393,7 +432,10 @@ bool QuicFramer::ProcessPublicHeader(QuicPacketPublicHeader* public_header) {
return false;
}
- public_header->flags = static_cast<QuicPacketPublicFlags>(public_flags);
+ public_header->reset_flag = (public_flags & PACKET_PUBLIC_FLAGS_RST) != 0;
+ public_header->version_flag =
+ (public_flags & PACKET_PUBLIC_FLAGS_VERSION) != 0;
+
return true;
}
@@ -417,7 +459,7 @@ bool QuicFramer::ProcessPacketHeader(
return false;
}
- if (!DecryptPayload(packet)) {
+ if (!DecryptPayload(header->packet_sequence_number, packet)) {
DLOG(WARNING) << "Unable to decrypt payload.";
return RaiseError(QUIC_DECRYPTION_FAILURE);
}
@@ -433,7 +475,10 @@ bool QuicFramer::ProcessPacketHeader(
return false;
}
- header->private_flags = static_cast<QuicPacketPrivateFlags>(private_flags);
+ header->fec_flag = (private_flags & PACKET_PRIVATE_FLAGS_FEC) != 0;
+ header->entropy_flag = (private_flags & PACKET_PRIVATE_FLAGS_ENTROPY) != 0;
+ header->fec_entropy_flag =
+ (private_flags & PACKET_PRIVATE_FLAGS_FEC_ENTROPY) != 0;
uint8 first_fec_protected_packet_offset;
if (!reader_->ReadBytes(&first_fec_protected_packet_offset, 1)) {
@@ -443,6 +488,7 @@ bool QuicFramer::ProcessPacketHeader(
header->fec_group = first_fec_protected_packet_offset == kNoFecOffset ? 0 :
header->packet_sequence_number - first_fec_protected_packet_offset;
+ header->entropy_hash = GetPacketEntropyHash(*header);
// Set the last sequence number after we have decrypted the packet
// so we are confident is not attacker controlled.
last_sequence_number_ = header->packet_sequence_number;
@@ -505,6 +551,11 @@ bool QuicFramer::ProcessFrameData() {
return RaiseError(QUIC_INVALID_CONNECTION_CLOSE_DATA);
}
break;
+ case GOAWAY_FRAME:
+ if (!ProcessGoAwayFrame()) {
+ return RaiseError(QUIC_INVALID_GOAWAY_DATA);
+ }
+ break;
default:
set_detailed_error("Illegal frame type.");
DLOG(WARNING) << "Illegal frame type: "
@@ -560,6 +611,11 @@ bool QuicFramer::ProcessAckFrame(QuicAckFrame* frame) {
}
bool QuicFramer::ProcessReceivedInfo(ReceivedPacketInfo* received_info) {
+ if (!reader_->ReadBytes(&received_info->entropy_hash, 1)) {
+ set_detailed_error("Unable to read entropy hash for received packets.");
+ return false;
+ }
+
if (!ProcessPacketSequenceNumber(&received_info->largest_observed)) {
set_detailed_error("Unable to read largest observed.");
return false;
@@ -584,6 +640,11 @@ bool QuicFramer::ProcessReceivedInfo(ReceivedPacketInfo* received_info) {
}
bool QuicFramer::ProcessSentInfo(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(&sent_info->least_unacked)) {
set_detailed_error("Unable to read least unacked.");
return false;
@@ -700,11 +761,6 @@ bool QuicFramer::ProcessRstStreamFrame() {
return false;
}
- if (!reader_->ReadUInt64(&frame.offset)) {
- set_detailed_error("Unable to read offset in rst frame.");
- return false;
- }
-
uint32 error_code;
if (!reader_->ReadUInt32(&error_code)) {
set_detailed_error("Unable to read rst stream error code.");
@@ -749,8 +805,39 @@ bool QuicFramer::ProcessConnectionCloseFrame() {
return true;
}
-QuicEncryptedPacket* QuicFramer::EncryptPacket(const QuicPacket& packet) {
- scoped_ptr<QuicData> out(encrypter_->Encrypt(packet.AssociatedData(),
+bool QuicFramer::ProcessGoAwayFrame() {
+ QuicGoAwayFrame frame;
+
+ uint32 error_code;
+ if (!reader_->ReadUInt32(&error_code)) {
+ set_detailed_error("Unable to read go away error code.");
+ return false;
+ }
+ frame.error_code = static_cast<QuicErrorCode>(error_code);
+
+ uint32 stream_id;
+ if (!reader_->ReadUInt32(&stream_id)) {
+ set_detailed_error("Unable to read last good stream id.");
+ return false;
+ }
+ frame.last_good_stream_id = static_cast<QuicErrorCode>(stream_id);
+
+ StringPiece reason_phrase;
+ if (!reader_->ReadStringPiece16(&reason_phrase)) {
+ set_detailed_error("Unable to read goaway reason.");
+ return false;
+ }
+ frame.reason_phrase = reason_phrase.as_string();
+
+ visitor_->OnGoAwayFrame(frame);
+ return true;
+}
+
+QuicEncryptedPacket* QuicFramer::EncryptPacket(
+ QuicPacketSequenceNumber packet_sequence_number,
+ const QuicPacket& packet) {
+ scoped_ptr<QuicData> out(encrypter_->Encrypt(packet_sequence_number,
+ packet.AssociatedData(),
packet.Plaintext()));
if (out.get() == NULL) {
RaiseError(QUIC_ENCRYPTION_FAILURE);
@@ -768,13 +855,15 @@ size_t QuicFramer::GetMaxPlaintextSize(size_t ciphertext_size) {
return encrypter_->GetMaxPlaintextSize(ciphertext_size);
}
-bool QuicFramer::DecryptPayload(const QuicEncryptedPacket& packet) {
+bool QuicFramer::DecryptPayload(QuicPacketSequenceNumber sequence_number,
+ const QuicEncryptedPacket& packet) {
StringPiece encrypted;
if (!reader_->ReadStringPiece(&encrypted, reader_->BytesRemaining())) {
return false;
}
DCHECK(decrypter_.get() != NULL);
- decrypted_.reset(decrypter_->Decrypt(packet.AssociatedData(), encrypted));
+ decrypted_.reset(decrypter_->Decrypt(sequence_number,
+ packet.AssociatedData(), encrypted));
if (decrypted_.get() == NULL) {
return false;
}
@@ -789,34 +878,36 @@ size_t QuicFramer::ComputeFramePayloadLength(const QuicFrame& frame) {
// same as sizeof(member_wire_format).
switch (frame.type) {
case STREAM_FRAME:
- len += 4; // stream id
- len += 1; // fin
- len += 8; // offset
- len += 2; // space for the 16 bit length
+ len += 4; // Stream id of the frame.
+ len += 1; // A byte for fin.
+ len += 8; // Byte offset.
+ len += 2; // Space for the 16 bit length.
len += frame.stream_frame->data.size();
break;
case ACK_FRAME: {
const QuicAckFrame& ack = *frame.ack_frame;
- len += 6; // largest observed packet sequence number
- len += 1; // num missing packets
+ len += 1; // Commutative hash of entropy of the packets received.
+ len += 6; // Least packet sequence number awaiting an ack.
+ len += 1; // Hash of entropy of the packets sent up to largest observed.
+ len += 6; // Largest observed packet sequence number.
+ len += 1; // Number of missing packets.
len += 6 * ack.received_info.missing_packets.size();
- len += 6; // least packet sequence number awaiting an ack
break;
}
case CONGESTION_FEEDBACK_FRAME: {
const QuicCongestionFeedbackFrame& congestion_feedback =
*frame.congestion_feedback_frame;
- len += 1; // congestion feedback type
+ len += 1; // Congestion feedback type.
switch (congestion_feedback.type) {
case kInterArrival: {
const CongestionFeedbackMessageInterArrival& inter_arrival =
congestion_feedback.inter_arrival;
len += 2;
- len += 1; // num received packets
+ len += 1; // Number received packets.
if (inter_arrival.received_packet_times.size() > 0) {
- len += 6; // smallest received
- len += 8; // time
+ len += 6; // Smallest received.
+ len += 8; // Time.
// 2 bytes per sequence number delta plus 4 bytes per delta time.
len += 6 * (inter_arrival.received_packet_times.size() - 1);
}
@@ -836,19 +927,24 @@ size_t QuicFramer::ComputeFramePayloadLength(const QuicFrame& frame) {
break;
}
case RST_STREAM_FRAME:
- len += 4; // stream id
- len += 8; // offset
- len += 4; // error code
- len += 2; // error details size
+ len += 4; // Stream id of the frame.
+ len += 4; // Error code.
+ len += 2; // Error details size.
len += frame.rst_stream_frame->error_details.size();
break;
case CONNECTION_CLOSE_FRAME:
- len += 4; // error code
- len += 2; // error details size
+ len += 4; // Error code.
+ len += 2; // Error details size.
len += frame.connection_close_frame->error_details.size();
len += ComputeFramePayloadLength(
QuicFrame(&frame.connection_close_frame->ack_frame));
break;
+ case GOAWAY_FRAME:
+ len += 4; // error code
+ len += 4; // last good stream id
+ len += 2; // reason phrase length
+ len += frame.goaway_frame->reason_phrase.size();
+ break;
default:
set_detailed_error("Illegal frame type.");
DLOG(INFO) << "Illegal frame type: " << frame.type;
@@ -891,9 +987,9 @@ bool QuicFramer::AppendStreamFramePayload(
}
QuicPacketSequenceNumber QuicFramer::CalculateLargestObserved(
- const SequenceSet& missing_packets,
- SequenceSet::const_iterator largest_written) {
- SequenceSet::const_iterator it = largest_written;
+ const SequenceNumberSet& missing_packets,
+ SequenceNumberSet::const_iterator largest_written) {
+ SequenceNumberSet::const_iterator it = largest_written;
QuicPacketSequenceNumber previous_missing = *it;
++it;
@@ -911,10 +1007,21 @@ QuicPacketSequenceNumber QuicFramer::CalculateLargestObserved(
bool QuicFramer::AppendAckFramePayload(
const QuicAckFrame& frame,
QuicDataWriter* writer) {
+ // 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(frame.sent_info.least_unacked, writer)) {
return false;
}
+ size_t received_entropy_offset = writer->length();
+ if (!writer->WriteUInt8(frame.received_info.entropy_hash)) {
+ return false;
+ }
+
size_t largest_observed_offset = writer->length();
if (!AppendPacketSequenceNumber(frame.received_info.largest_observed,
writer)) {
@@ -929,13 +1036,19 @@ bool QuicFramer::AppendAckFramePayload(
return false;
}
- SequenceSet::const_iterator it = frame.received_info.missing_packets.begin();
+ 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(*it, writer)) {
- // We are truncating. Overwrite largest_observed.
+ // We are truncating.
QuicPacketSequenceNumber largest_observed =
CalculateLargestObserved(frame.received_info.missing_packets, --it);
+ // Overwrite entropy hash for received packets.
+ writer->WriteUInt8ToOffset(
+ entropy_calculator_->ReceivedEntropyHash(largest_observed),
+ received_entropy_offset);
+ // Overwrite largest_observed.
writer->WriteUInt48ToOffset(largest_observed & kSequenceNumberMask,
largest_observed_offset);
writer->WriteUInt8ToOffset(num_missing_packets_written,
@@ -1045,9 +1158,6 @@ bool QuicFramer::AppendRstStreamFramePayload(
if (!writer->WriteUInt32(frame.stream_id)) {
return false;
}
- if (!writer->WriteUInt64(frame.offset)) {
- return false;
- }
uint32 error_code = static_cast<uint32>(frame.error_code);
if (!writer->WriteUInt32(error_code)) {
@@ -1074,6 +1184,22 @@ bool QuicFramer::AppendConnectionCloseFramePayload(
return true;
}
+bool QuicFramer::AppendGoAwayFramePayload(const QuicGoAwayFrame& frame,
+ QuicDataWriter* writer) {
+ uint32 error_code = static_cast<uint32>(frame.error_code);
+ if (!writer->WriteUInt32(error_code)) {
+ return false;
+ }
+ uint32 stream_id = static_cast<uint32>(frame.last_good_stream_id);
+ if (!writer->WriteUInt32(stream_id)) {
+ return false;
+ }
+ if (!writer->WriteStringPiece16(frame.reason_phrase)) {
+ return false;
+ }
+ return true;
+}
+
bool QuicFramer::RaiseError(QuicErrorCode error) {
DLOG(INFO) << detailed_error_;
set_error(error);