Index: net/quic/quic_packet_creator.cc |
diff --git a/net/quic/quic_packet_creator.cc b/net/quic/quic_packet_creator.cc |
index c9f1d24cb11475e61eb4f91d84ba24ede67d9495..e91efa21b2b037fecf8eca3cd3a1dd8a304ca71f 100644 |
--- a/net/quic/quic_packet_creator.cc |
+++ b/net/quic/quic_packet_creator.cc |
@@ -8,6 +8,7 @@ |
#include "base/logging.h" |
#include "net/quic/crypto/quic_random.h" |
#include "net/quic/quic_ack_notifier.h" |
+#include "net/quic/quic_data_writer.h" |
#include "net/quic/quic_fec_group.h" |
#include "net/quic/quic_utils.h" |
@@ -262,28 +263,33 @@ size_t QuicPacketCreator::CreateStreamFrame(QuicStreamId id, |
} |
SerializedPacket QuicPacketCreator::ReserializeAllFrames( |
- const QuicFrames& frames, |
+ const RetransmittableFrames& frames, |
QuicSequenceNumberLength original_length) { |
DCHECK(fec_group_.get() == nullptr); |
const QuicSequenceNumberLength saved_length = sequence_number_length_; |
const QuicSequenceNumberLength saved_next_length = |
next_sequence_number_length_; |
const bool saved_should_fec_protect = should_fec_protect_; |
+ const EncryptionLevel default_encryption_level = encryption_level_; |
- // Temporarily set the sequence number length and stop FEC protection. |
+ // Temporarily set the sequence number length, stop FEC protection, |
+ // and change the encryption level. |
sequence_number_length_ = original_length; |
next_sequence_number_length_ = original_length; |
should_fec_protect_ = false; |
+ encryption_level_ = frames.encryption_level(); |
// Serialize the packet and restore the FEC and sequence number length state. |
- SerializedPacket serialized_packet = SerializeAllFrames(frames); |
+ SerializedPacket serialized_packet = SerializeAllFrames(frames.frames()); |
sequence_number_length_ = saved_length; |
next_sequence_number_length_ = saved_next_length; |
should_fec_protect_ = saved_should_fec_protect; |
+ encryption_level_ = default_encryption_level; |
return serialized_packet; |
} |
+// TODO(ianswett): Remove this method, because it's test only. |
SerializedPacket QuicPacketCreator::SerializeAllFrames( |
const QuicFrames& frames) { |
// TODO(satyamshekhar): Verify that this DCHECK won't fail. What about queued |
@@ -292,8 +298,8 @@ SerializedPacket QuicPacketCreator::SerializeAllFrames( |
DCHECK_EQ(0u, queued_frames_.size()); |
LOG_IF(DFATAL, frames.empty()) |
<< "Attempt to serialize empty packet"; |
- for (size_t i = 0; i < frames.size(); ++i) { |
- bool success = AddFrame(frames[i], false); |
+ for (const QuicFrame& frame : frames) { |
+ bool success = AddFrame(frame, false); |
DCHECK(success); |
} |
SerializedPacket packet = SerializePacket(); |
@@ -367,19 +373,43 @@ SerializedPacket QuicPacketCreator::SerializePacket() { |
bool possibly_truncated_by_length = packet_size_ == max_plaintext_size && |
queued_frames_.size() == 1 && |
queued_frames_.back().type == ACK_FRAME; |
- SerializedPacket serialized = |
- framer_->BuildDataPacket(header, queued_frames_, packet_size_); |
- LOG_IF(DFATAL, !serialized.packet) |
- << "Failed to serialize " << queued_frames_.size() << " frames."; |
+ char buffer[kMaxPacketSize]; |
+ scoped_ptr<QuicPacket> packet; |
+ // Use the packet_size_ instead of the buffer size to ensure smaller |
+ // packet sizes are properly used. |
+ scoped_ptr<char[]> large_buffer; |
+ if (packet_size_ <= kMaxPacketSize) { |
+ packet.reset( |
+ framer_->BuildDataPacket(header, queued_frames_, buffer, packet_size_)); |
+ } else { |
+ large_buffer.reset(new char[packet_size_]); |
+ packet.reset(framer_->BuildDataPacket(header, queued_frames_, |
+ large_buffer.get(), packet_size_)); |
+ } |
+ LOG_IF(DFATAL, packet == nullptr) << "Failed to serialize " |
+ << queued_frames_.size() << " frames."; |
// Because of possible truncation, we can't be confident that our |
// packet size calculation worked correctly. |
if (!possibly_truncated_by_length) { |
- DCHECK_EQ(packet_size_, serialized.packet->length()); |
+ DCHECK_EQ(packet_size_, packet->length()); |
+ } |
+ // Immediately encrypt the packet, to ensure we don't encrypt the same packet |
+ // sequence number multiple times. |
+ QuicEncryptedPacket* encrypted = |
+ framer_->EncryptPacket(encryption_level_, sequence_number_, *packet); |
+ if (encrypted == nullptr) { |
+ LOG(DFATAL) << "Failed to encrypt packet number " << sequence_number_; |
+ SerializedPacket kNoPacket(0, PACKET_1BYTE_SEQUENCE_NUMBER, nullptr, 0, |
+ nullptr); |
+ return kNoPacket; |
} |
+ |
packet_size_ = 0; |
queued_frames_.clear(); |
- serialized.retransmittable_frames = queued_retransmittable_frames_.release(); |
- return serialized; |
+ return SerializedPacket(header.packet_sequence_number, |
+ header.public_header.sequence_number_length, |
+ encrypted, QuicFramer::GetPacketEntropyHash(header), |
+ queued_retransmittable_frames_.release()); |
} |
SerializedPacket QuicPacketCreator::SerializeFec() { |
@@ -396,12 +426,27 @@ SerializedPacket QuicPacketCreator::SerializeFec() { |
QuicFecData fec_data; |
fec_data.fec_group = fec_group_->min_protected_packet(); |
fec_data.redundancy = fec_group_->payload_parity(); |
- SerializedPacket serialized = framer_->BuildFecPacket(header, fec_data); |
+ scoped_ptr<QuicPacket> packet(framer_->BuildFecPacket(header, fec_data)); |
fec_group_.reset(nullptr); |
packet_size_ = 0; |
- LOG_IF(DFATAL, !serialized.packet) |
+ LOG_IF(DFATAL, packet == nullptr) |
<< "Failed to serialize fec packet for group:" << fec_data.fec_group; |
- DCHECK_GE(max_packet_length_, serialized.packet->length()); |
+ DCHECK_GE(max_packet_length_, packet->length()); |
+ // Immediately encrypt the packet, to ensure we don't encrypt the same packet |
+ // sequence number multiple times. |
+ QuicEncryptedPacket* encrypted = |
+ framer_->EncryptPacket(encryption_level_, sequence_number_, *packet); |
+ if (encrypted == nullptr) { |
+ LOG(DFATAL) << "Failed to encrypt packet number " << sequence_number_; |
+ SerializedPacket kNoPacket(0, PACKET_1BYTE_SEQUENCE_NUMBER, nullptr, 0, |
+ nullptr); |
+ return kNoPacket; |
+ } |
+ SerializedPacket serialized( |
+ header.packet_sequence_number, |
+ header.public_header.sequence_number_length, encrypted, |
+ QuicFramer::GetPacketEntropyHash(header), nullptr); |
+ serialized.is_fec_packet = true; |
return serialized; |
} |