Index: net/quic/quic_framer.cc |
diff --git a/net/quic/quic_framer.cc b/net/quic/quic_framer.cc |
index 5cde3c23fcf3851ca7612ca13075fa524fe4d59c..4ff23a41500ac9388dd074a3c77eadbfaa8d1aea 100644 |
--- a/net/quic/quic_framer.cc |
+++ b/net/quic/quic_framer.cc |
@@ -17,7 +17,6 @@ |
#include "net/quic/quic_socket_address_coder.h" |
using base::StringPiece; |
-using std::make_pair; |
using std::map; |
using std::max; |
using std::min; |
@@ -310,33 +309,31 @@ QuicFramer::AckFrameInfo::AckFrameInfo() : max_delta(0) {} |
QuicFramer::AckFrameInfo::~AckFrameInfo() {} |
+// static |
QuicPacketEntropyHash QuicFramer::GetPacketEntropyHash( |
- const QuicPacketHeader& header) const { |
+ const QuicPacketHeader& header) { |
return header.entropy_flag << (header.packet_sequence_number % 8); |
} |
-SerializedPacket QuicFramer::BuildDataPacket( |
- const QuicPacketHeader& header, |
- const QuicFrames& frames, |
- size_t packet_size) { |
- QuicDataWriter writer(packet_size); |
- const SerializedPacket kNoPacket(0, PACKET_1BYTE_SEQUENCE_NUMBER, nullptr, 0, |
- nullptr); |
+QuicPacket* QuicFramer::BuildDataPacket(const QuicPacketHeader& header, |
+ const QuicFrames& frames, |
+ char* buffer, |
+ size_t packet_length) { |
+ QuicDataWriter writer(packet_length, buffer); |
if (!AppendPacketHeader(header, &writer)) { |
LOG(DFATAL) << "AppendPacketHeader failed"; |
- return kNoPacket; |
+ return nullptr; |
} |
- for (size_t i = 0; i < frames.size(); ++i) { |
- const QuicFrame& frame = frames[i]; |
- |
+ size_t i = 0; |
+ for (const QuicFrame& frame : frames) { |
// Determine if we should write stream frame length in header. |
const bool no_stream_frame_length = |
(header.is_in_fec_group == NOT_IN_FEC_GROUP) && |
(i == frames.size() - 1); |
if (!AppendTypeByte(frame, no_stream_frame_length, &writer)) { |
LOG(DFATAL) << "AppendTypeByte failed"; |
- return kNoPacket; |
+ return nullptr; |
} |
switch (frame.type) { |
@@ -347,21 +344,21 @@ SerializedPacket QuicFramer::BuildDataPacket( |
if (!AppendStreamFrame( |
*frame.stream_frame, no_stream_frame_length, &writer)) { |
LOG(DFATAL) << "AppendStreamFrame failed"; |
- return kNoPacket; |
+ return nullptr; |
} |
break; |
case ACK_FRAME: |
if (!AppendAckFrameAndTypeByte( |
header, *frame.ack_frame, &writer)) { |
LOG(DFATAL) << "AppendAckFrameAndTypeByte failed"; |
- return kNoPacket; |
+ return nullptr; |
} |
break; |
case STOP_WAITING_FRAME: |
if (!AppendStopWaitingFrame( |
header, *frame.stop_waiting_frame, &writer)) { |
LOG(DFATAL) << "AppendStopWaitingFrame failed"; |
- return kNoPacket; |
+ return nullptr; |
} |
break; |
case PING_FRAME: |
@@ -370,89 +367,79 @@ SerializedPacket QuicFramer::BuildDataPacket( |
case RST_STREAM_FRAME: |
if (!AppendRstStreamFrame(*frame.rst_stream_frame, &writer)) { |
LOG(DFATAL) << "AppendRstStreamFrame failed"; |
- return kNoPacket; |
+ return nullptr; |
} |
break; |
case CONNECTION_CLOSE_FRAME: |
if (!AppendConnectionCloseFrame( |
*frame.connection_close_frame, &writer)) { |
LOG(DFATAL) << "AppendConnectionCloseFrame failed"; |
- return kNoPacket; |
+ return nullptr; |
} |
break; |
case GOAWAY_FRAME: |
if (!AppendGoAwayFrame(*frame.goaway_frame, &writer)) { |
LOG(DFATAL) << "AppendGoAwayFrame failed"; |
- return kNoPacket; |
+ return nullptr; |
} |
break; |
case WINDOW_UPDATE_FRAME: |
if (!AppendWindowUpdateFrame(*frame.window_update_frame, &writer)) { |
LOG(DFATAL) << "AppendWindowUpdateFrame failed"; |
- return kNoPacket; |
+ return nullptr; |
} |
break; |
case BLOCKED_FRAME: |
if (!AppendBlockedFrame(*frame.blocked_frame, &writer)) { |
LOG(DFATAL) << "AppendBlockedFrame failed"; |
- return kNoPacket; |
+ return nullptr; |
} |
break; |
default: |
RaiseError(QUIC_INVALID_FRAME_DATA); |
LOG(DFATAL) << "QUIC_INVALID_FRAME_DATA"; |
- return kNoPacket; |
+ return nullptr; |
} |
+ ++i; |
} |
- // Save the length before writing, because take clears it. |
- const size_t len = writer.length(); |
- // Less than or equal because truncated acks end up with max_plaintex_size |
- // length, even though they're typically slightly shorter. |
- DCHECK_LE(len, packet_size); |
- QuicPacket* packet = QuicPacket::NewDataPacket( |
- writer.take(), len, true, header.public_header.connection_id_length, |
- header.public_header.version_flag, |
- header.public_header.sequence_number_length); |
+ QuicPacket* packet = |
+ new QuicPacket(writer.data(), writer.length(), false, |
+ header.public_header.connection_id_length, |
+ header.public_header.version_flag, |
+ header.public_header.sequence_number_length); |
if (fec_builder_) { |
fec_builder_->OnBuiltFecProtectedPayload(header, |
packet->FecProtectedData()); |
} |
- return SerializedPacket(header.packet_sequence_number, |
- header.public_header.sequence_number_length, packet, |
- GetPacketEntropyHash(header), nullptr); |
+ return packet; |
} |
-SerializedPacket QuicFramer::BuildFecPacket(const QuicPacketHeader& header, |
- const QuicFecData& fec) { |
+QuicPacket* QuicFramer::BuildFecPacket(const QuicPacketHeader& header, |
+ const QuicFecData& fec) { |
DCHECK_EQ(IN_FEC_GROUP, header.is_in_fec_group); |
DCHECK_NE(0u, header.fec_group); |
size_t len = GetPacketHeaderSize(header); |
len += fec.redundancy.length(); |
- QuicDataWriter writer(len); |
- const SerializedPacket kNoPacket(0, PACKET_1BYTE_SEQUENCE_NUMBER, nullptr, 0, |
- nullptr); |
+ scoped_ptr<char[]> buffer(new char[len]); |
+ QuicDataWriter writer(len, buffer.get()); |
if (!AppendPacketHeader(header, &writer)) { |
LOG(DFATAL) << "AppendPacketHeader failed"; |
- return kNoPacket; |
+ return nullptr; |
} |
if (!writer.WriteBytes(fec.redundancy.data(), fec.redundancy.length())) { |
LOG(DFATAL) << "Failed to add FEC"; |
- return kNoPacket; |
+ return nullptr; |
} |
- return SerializedPacket( |
- header.packet_sequence_number, |
- header.public_header.sequence_number_length, |
- QuicPacket::NewFecPacket(writer.take(), len, true, |
- header.public_header.connection_id_length, |
- header.public_header.version_flag, |
- header.public_header.sequence_number_length), |
- GetPacketEntropyHash(header), nullptr); |
+ return new QuicPacket(buffer.release(), len, true, |
+ header.public_header.connection_id_length, |
+ header.public_header.version_flag, |
+ header.public_header.sequence_number_length); |
} |
// static |
@@ -477,7 +464,8 @@ QuicEncryptedPacket* QuicFramer::BuildPublicResetPacket( |
size_t len = |
kPublicFlagsSize + PACKET_8BYTE_CONNECTION_ID + reset_serialized.length(); |
- QuicDataWriter writer(len); |
+ scoped_ptr<char[]> buffer(new char[len]); |
+ QuicDataWriter writer(len, buffer.get()); |
uint8 flags = static_cast<uint8>(PACKET_PUBLIC_FLAGS_RST | |
PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID); |
@@ -493,7 +481,7 @@ QuicEncryptedPacket* QuicFramer::BuildPublicResetPacket( |
return nullptr; |
} |
- return new QuicEncryptedPacket(writer.take(), len, true); |
+ return new QuicEncryptedPacket(buffer.release(), len, true); |
} |
QuicEncryptedPacket* QuicFramer::BuildVersionNegotiationPacket( |
@@ -501,7 +489,8 @@ QuicEncryptedPacket* QuicFramer::BuildVersionNegotiationPacket( |
const QuicVersionVector& supported_versions) { |
DCHECK(header.version_flag); |
size_t len = GetVersionNegotiationPacketSize(supported_versions.size()); |
- QuicDataWriter writer(len); |
+ scoped_ptr<char[]> buffer(new char[len]); |
+ QuicDataWriter writer(len, buffer.get()); |
uint8 flags = static_cast<uint8>(PACKET_PUBLIC_FLAGS_VERSION | |
PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID); |
@@ -519,7 +508,7 @@ QuicEncryptedPacket* QuicFramer::BuildVersionNegotiationPacket( |
} |
} |
- return new QuicEncryptedPacket(writer.take(), len, true); |
+ return new QuicEncryptedPacket(buffer.release(), len, true); |
} |
bool QuicFramer::ProcessPacket(const QuicEncryptedPacket& packet) { |
@@ -555,8 +544,16 @@ bool QuicFramer::ProcessPacket(const QuicEncryptedPacket& packet) { |
rv = ProcessVersionNegotiationPacket(&public_header); |
} else if (public_header.reset_flag) { |
rv = ProcessPublicResetPacket(public_header); |
+ } else if (packet.length() <= kMaxPacketSize) { |
+ char buffer[kMaxPacketSize]; |
+ rv = ProcessDataPacket(public_header, packet, buffer, kMaxPacketSize); |
} else { |
- rv = ProcessDataPacket(public_header, packet); |
+ scoped_ptr<char[]> large_buffer(new char[packet.length()]); |
+ rv = ProcessDataPacket(public_header, packet, large_buffer.get(), |
+ packet.length()); |
+ LOG_IF(DFATAL, rv) << "QUIC should never successfully process packets " |
+ << "larger than kMaxPacketSize. packet size:" |
+ << packet.length(); |
} |
reader_.reset(nullptr); |
@@ -580,11 +577,12 @@ bool QuicFramer::ProcessVersionNegotiationPacket( |
return true; |
} |
-bool QuicFramer::ProcessDataPacket( |
- const QuicPacketPublicHeader& public_header, |
- const QuicEncryptedPacket& packet) { |
+bool QuicFramer::ProcessDataPacket(const QuicPacketPublicHeader& public_header, |
+ const QuicEncryptedPacket& packet, |
+ char* decrypted_buffer, |
+ size_t buffer_length) { |
QuicPacketHeader header(public_header); |
- if (!ProcessPacketHeader(&header, packet)) { |
+ if (!ProcessPacketHeader(&header, packet, decrypted_buffer, buffer_length)) { |
DLOG(WARNING) << "Unable to process data packet header."; |
return false; |
} |
@@ -998,9 +996,10 @@ QuicFramer::AckFrameInfo QuicFramer::GetAckFrameInfo( |
return ack_info; |
} |
-bool QuicFramer::ProcessPacketHeader( |
- QuicPacketHeader* header, |
- const QuicEncryptedPacket& packet) { |
+bool QuicFramer::ProcessPacketHeader(QuicPacketHeader* header, |
+ const QuicEncryptedPacket& packet, |
+ char* decrypted_buffer, |
+ size_t buffer_length) { |
if (!ProcessPacketSequenceNumber(header->public_header.sequence_number_length, |
&header->packet_sequence_number)) { |
set_detailed_error("Unable to read sequence number."); |
@@ -1016,7 +1015,7 @@ bool QuicFramer::ProcessPacketHeader( |
return false; |
} |
- if (!DecryptPayload(*header, packet)) { |
+ if (!DecryptPayload(*header, packet, decrypted_buffer, buffer_length)) { |
set_detailed_error("Unable to decrypt payload."); |
return RaiseError(QUIC_DECRYPTION_FAILURE); |
} |
@@ -1407,7 +1406,7 @@ bool QuicFramer::ProcessTimestampsInAckFrame(QuicAckFrame* ack_frame) { |
last_timestamp_ = CalculateTimestampFromWire(time_delta_us); |
ack_frame->received_packet_times.push_back( |
- make_pair(seq_num, creation_time_.Add(last_timestamp_))); |
+ std::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, |
@@ -1429,7 +1428,7 @@ bool QuicFramer::ProcessTimestampsInAckFrame(QuicAckFrame* ack_frame) { |
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_))); |
+ std::make_pair(seq_num, creation_time_.Add(last_timestamp_))); |
} |
} |
} |
@@ -1623,19 +1622,27 @@ QuicEncryptedPacket* QuicFramer::EncryptPacket( |
const QuicPacket& packet) { |
DCHECK(encrypter_[level].get() != nullptr); |
- scoped_ptr<QuicData> out(encrypter_[level]->EncryptPacket( |
- packet_sequence_number, packet.AssociatedData(), packet.Plaintext())); |
- if (out.get() == nullptr) { |
- RaiseError(QUIC_ENCRYPTION_FAILURE); |
- return nullptr; |
- } |
+ // Allocate a large enough buffer for the header and the encrypted data. |
+ const size_t encrypted_len = |
+ encrypter_[level]->GetCiphertextSize(packet.Plaintext().length()); |
StringPiece header_data = packet.BeforePlaintext(); |
- size_t len = header_data.length() + out->length(); |
+ const size_t len = header_data.length() + encrypted_len; |
+ // TODO(ianswett): Consider allocating this on the stack in the typical case. |
char* buffer = new char[len]; |
- // TODO(rch): eliminate this buffer copy by passing in a buffer to Encrypt(). |
+ // Copy in the header, because the encrypter only populates the encrypted |
+ // plaintext content. |
memcpy(buffer, header_data.data(), header_data.length()); |
- memcpy(buffer + header_data.length(), out->data(), out->length()); |
- return new QuicEncryptedPacket(buffer, len, true); |
+ // Encrypt the plaintext into the buffer. |
+ size_t output_length = 0; |
+ if (!encrypter_[level]->EncryptPacket( |
+ packet_sequence_number, packet.AssociatedData(), packet.Plaintext(), |
+ buffer + header_data.length(), &output_length, encrypted_len)) { |
+ RaiseError(QUIC_ENCRYPTION_FAILURE); |
+ return nullptr; |
+ } |
+ |
+ return new QuicEncryptedPacket(buffer, header_data.length() + output_length, |
+ true); |
} |
size_t QuicFramer::GetMaxPlaintextSize(size_t ciphertext_size) { |
@@ -1656,32 +1663,26 @@ size_t QuicFramer::GetMaxPlaintextSize(size_t ciphertext_size) { |
} |
bool QuicFramer::DecryptPayload(const QuicPacketHeader& header, |
- const QuicEncryptedPacket& packet) { |
- StringPiece encrypted; |
- if (!reader_->ReadStringPiece(&encrypted, reader_->BytesRemaining())) { |
- return false; |
- } |
+ const QuicEncryptedPacket& packet, |
+ char* decrypted_buffer, |
+ size_t buffer_length) { |
+ StringPiece encrypted = reader_->ReadRemainingPayload(); |
DCHECK(decrypter_.get() != nullptr); |
- decrypted_.reset(decrypter_->DecryptPacket( |
- header.packet_sequence_number, |
- GetAssociatedDataFromEncryptedPacket( |
- packet, |
- header.public_header.connection_id_length, |
- header.public_header.version_flag, |
- header.public_header.sequence_number_length), |
- encrypted)); |
- if (decrypted_.get() != nullptr) { |
+ const StringPiece& associated_data = GetAssociatedDataFromEncryptedPacket( |
+ packet, header.public_header.connection_id_length, |
+ header.public_header.version_flag, |
+ header.public_header.sequence_number_length); |
+ size_t decrypted_length = 0; |
+ bool success = decrypter_->DecryptPacket( |
+ header.packet_sequence_number, associated_data, encrypted, |
+ decrypted_buffer, &decrypted_length, buffer_length); |
+ if (success) { |
visitor_->OnDecryptedPacket(decrypter_level_); |
} else if (alternative_decrypter_.get() != nullptr) { |
- decrypted_.reset(alternative_decrypter_->DecryptPacket( |
- header.packet_sequence_number, |
- GetAssociatedDataFromEncryptedPacket( |
- packet, |
- header.public_header.connection_id_length, |
- header.public_header.version_flag, |
- header.public_header.sequence_number_length), |
- encrypted)); |
- if (decrypted_.get() != nullptr) { |
+ success = alternative_decrypter_->DecryptPacket( |
+ header.packet_sequence_number, associated_data, encrypted, |
+ decrypted_buffer, &decrypted_length, buffer_length); |
+ if (success) { |
visitor_->OnDecryptedPacket(alternative_decrypter_level_); |
if (alternative_decrypter_latch_) { |
// Switch to the alternative decrypter and latch so that we cannot |
@@ -1699,13 +1700,13 @@ bool QuicFramer::DecryptPayload(const QuicPacketHeader& header, |
} |
} |
- if (decrypted_.get() == nullptr) { |
+ if (!success) { |
DLOG(WARNING) << "DecryptPacket failed for sequence_number:" |
<< header.packet_sequence_number; |
return false; |
} |
- reader_.reset(new QuicDataReader(decrypted_->data(), decrypted_->length())); |
+ reader_.reset(new QuicDataReader(decrypted_buffer, decrypted_length)); |
return true; |
} |