| 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;
|
| }
|
|
|
|
|