diff options
author | jokulik <jokulik@chromium.org> | 2015-12-08 13:42:57 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-12-08 21:44:18 +0000 |
commit | 2324d28c4b07d5f15acd5890419b73348f97e54b (patch) | |
tree | fa77fec55a5041b4b439743af9f8a45042311d54 | |
parent | 42290cb91a66566637a1715737b1961a8480b934 (diff) | |
download | chromium_src-2324d28c4b07d5f15acd5890419b73348f97e54b.zip chromium_src-2324d28c4b07d5f15acd5890419b73348f97e54b.tar.gz chromium_src-2324d28c4b07d5f15acd5890419b73348f97e54b.tar.bz2 |
Landing Recent QUIC changes until Thu Nov 26 15:06:02 2015 +0000
relnote: Fix ASAN test failure in QUIC's CryptoHandshakeMessageTest. The last argument to SetTagList must be 0.
n/a (test only)
Merge internal change: 108792500
https://codereview.chromium.org/1499163002/
relnote: Use the kClientDataStreamId1 constant instead of hardcoded "5"
Merge internal change: 108754896
https://codereview.chromium.org/1499153002/
relnote: Retransmit non-crypto packets with forward secure encryption if the connection has gone forward secure.
Merge internal change: 108754149
https://codereview.chromium.org/1497863005/
relnote: QuicPacketCreator knows when to start FEC protection.
QuicPacketCreator:
Call MaybeStartFecProtection in ConsumeData. Move MaybeStartFecProtection from public to private.
Merge internal change: 108743696
https://codereview.chromium.org/1495263002/
relnote: Remove EncryptionLevel from QUIC's RetransmittableFrames and add it to TransmissionInfo. No functional change.
Merge internal change: 108738647
https://codereview.chromium.org/1495243002/
relnote: Add a queued_data_bytes() method to ReliableQuicStream. Not used outside of tests.
This will be used when sending Trailers. To calculate the :final-offset value the stream must sum stream_bytes_written() + queued_data_bytes().
Merge internal change: 108735153
https://codereview.chromium.org/1497113003/
relnote: Adds response trailers to the QuicInMemoryCache's Responses. Currently unused, this is preparation for adding trailers support.
Merge internal change: 108727610
https://codereview.chromium.org/1499673003/
relnote: Move encryption_level from QueuedPacket into SerializedPacket. No functional change. Not flag protected.
Merge internal change: 108726817
https://codereview.chromium.org/1502503002/
relnote: Delete ParseRequestHeaders declaration win QuicSpdyServerStream, no longer implemented.
Merge internal change: 108718393
https://codereview.chromium.org/1499043002/
relnote: Fixed typo.
Merge internal change: 108716094
https://codereview.chromium.org/1502493002/
relnote: Adds a ParseTrailers method to SpdyUtils, with some basic validation of the header keys provided.
Merge internal change: 108704942
https://codereview.chromium.org/1494403002/
relnote: Pull HTTP/2 header parsing into utility method, from QuicSpdy{Client,Server}Streams. Not used in production.
Preparation for adding a ParseTrailers method, which will sit alongside ParseHeaders in SpdyUtils.
Makes it easier to unit test, demonstrated with newly added spdy_utils_test.cc.
Slight behavior change in that the ClientStream now gets support for handling multiple content-length headers, which was added to the ServerStream recently. Otherwise should be the same.
Merge internal change: 108694474
https://codereview.chromium.org/1501493003/
relnote: Use delegrate constructors for QuicStreamFrame
Merge internal change: 108629720
https://codereview.chromium.org/1497753003/
relnote: Change QuicStreamFrame to use a const char* and a frame length instead of a StringPiece. Saves 8 bytes, no functional change.
Merge internal change: 108613884
https://codereview.chromium.org/1495093003/
relnote: Deprecate --gfe2_reloadable_flag_quic_fix_fin_accounting
Merge internal change: 108509430
https://codereview.chromium.org/1498883003/
R=rch@chromium.org
BUG=
Review URL: https://codereview.chromium.org/1502633002
Cr-Commit-Position: refs/heads/master@{#363786}
45 files changed, 698 insertions, 439 deletions
diff --git a/net/quic/congestion_control/general_loss_algorithm_test.cc b/net/quic/congestion_control/general_loss_algorithm_test.cc index 03f20a0..5e71df1 100644 --- a/net/quic/congestion_control/general_loss_algorithm_test.cc +++ b/net/quic/congestion_control/general_loss_algorithm_test.cc @@ -33,9 +33,9 @@ class GeneralLossAlgorithmTest : public ::testing::Test { void SendDataPacket(QuicPacketNumber packet_number) { packets_.push_back(new QuicEncryptedPacket(nullptr, kDefaultLength)); - SerializedPacket packet( - packet_number, PACKET_1BYTE_PACKET_NUMBER, packets_.back(), 0, - new RetransmittableFrames(ENCRYPTION_NONE), false, false); + SerializedPacket packet(packet_number, PACKET_1BYTE_PACKET_NUMBER, + packets_.back(), 0, new RetransmittableFrames(), + false, false); unacked_packets_.AddSentPacket(&packet, 0, NOT_RETRANSMISSION, clock_.Now(), 1000, true); } diff --git a/net/quic/congestion_control/tcp_loss_algorithm_test.cc b/net/quic/congestion_control/tcp_loss_algorithm_test.cc index c80f5ac..c8ace67 100644 --- a/net/quic/congestion_control/tcp_loss_algorithm_test.cc +++ b/net/quic/congestion_control/tcp_loss_algorithm_test.cc @@ -36,9 +36,9 @@ class TcpLossAlgorithmTest : public ::testing::Test { void SendDataPacket(QuicPacketNumber packet_number) { packets_.push_back(new QuicEncryptedPacket(nullptr, kDefaultLength)); - SerializedPacket packet( - packet_number, PACKET_1BYTE_PACKET_NUMBER, packets_.back(), 0, - new RetransmittableFrames(ENCRYPTION_NONE), false, false); + SerializedPacket packet(packet_number, PACKET_1BYTE_PACKET_NUMBER, + packets_.back(), 0, new RetransmittableFrames(), + false, false); unacked_packets_.AddSentPacket(&packet, 0, NOT_RETRANSMISSION, clock_.Now(), 1000, true); } diff --git a/net/quic/congestion_control/time_loss_algorithm_test.cc b/net/quic/congestion_control/time_loss_algorithm_test.cc index b718735..2240935 100644 --- a/net/quic/congestion_control/time_loss_algorithm_test.cc +++ b/net/quic/congestion_control/time_loss_algorithm_test.cc @@ -36,9 +36,9 @@ class TimeLossAlgorithmTest : public ::testing::Test { void SendDataPacket(QuicPacketNumber packet_number) { packets_.push_back(new QuicEncryptedPacket(nullptr, kDefaultLength)); - SerializedPacket packet( - packet_number, PACKET_1BYTE_PACKET_NUMBER, packets_.back(), 0, - new RetransmittableFrames(ENCRYPTION_NONE), false, false); + SerializedPacket packet(packet_number, PACKET_1BYTE_PACKET_NUMBER, + packets_.back(), 0, new RetransmittableFrames(), + false, false); unacked_packets_.AddSentPacket(&packet, 0, NOT_RETRANSMISSION, clock_.Now(), 1000, true); } diff --git a/net/quic/quic_connection.cc b/net/quic/quic_connection.cc index 2bb8d0e..6be348c 100644 --- a/net/quic/quic_connection.cc +++ b/net/quic/quic_connection.cc @@ -237,20 +237,16 @@ class MtuDiscoveryAckListener : public QuicAckListenerInterface { } // namespace -QuicConnection::QueuedPacket::QueuedPacket(SerializedPacket packet, - EncryptionLevel level) +QuicConnection::QueuedPacket::QueuedPacket(SerializedPacket packet) : serialized_packet(packet), - encryption_level(level), transmission_type(NOT_RETRANSMISSION), original_packet_number(0) {} QuicConnection::QueuedPacket::QueuedPacket( SerializedPacket packet, - EncryptionLevel level, TransmissionType transmission_type, QuicPacketNumber original_packet_number) : serialized_packet(packet), - encryption_level(level), transmission_type(transmission_type), original_packet_number(original_packet_number) {} @@ -623,6 +619,19 @@ bool QuicConnection::OnUnauthenticatedHeader(const QuicPacketHeader& header) { // routed to this QuicConnection has been redirected before control reaches // here. DCHECK_EQ(connection_id_, header.public_header.connection_id); + + // If this packet has already been seen, or the sender has told us that it + // will not be retransmitted, then stop processing the packet. + if (!received_packet_manager_.IsAwaitingPacket(header.packet_number)) { + DVLOG(1) << ENDPOINT << "Packet " << header.packet_number + << " no longer being waited for. Discarding."; + if (debug_visitor_ != nullptr) { + debug_visitor_->OnDuplicatePacket(header.packet_number); + } + ++stats_.packets_dropped; + return false; + } + return true; } @@ -678,7 +687,7 @@ bool QuicConnection::OnStreamFrame(const QuicStreamFrame& frame) { return false; } visitor_->OnStreamFrame(frame); - stats_.stream_bytes_received += frame.data.size(); + stats_.stream_bytes_received += frame.frame_length; should_last_packet_instigate_acks_ = true; return connected_; } @@ -1353,17 +1362,6 @@ bool QuicConnection::ProcessValidatedPacket(const QuicPacketHeader& header) { return false; } - // If this packet has already been seen, or the sender has told us that it - // will not be retransmitted, then stop processing the packet. - if (!received_packet_manager_.IsAwaitingPacket(header.packet_number)) { - DVLOG(1) << ENDPOINT << "Packet " << header.packet_number - << " no longer being waited for. Discarding."; - if (debug_visitor_ != nullptr) { - debug_visitor_->OnDuplicatePacket(header.packet_number); - } - return false; - } - if (version_negotiation_state_ != NEGOTIATED_VERSION) { if (perspective_ == Perspective::IS_SERVER) { if (!header.public_header.version_flag) { @@ -1462,8 +1460,8 @@ void QuicConnection::WritePendingRetransmissions() { packet_generator_.FlushAllQueuedFrames(); char buffer[kMaxPacketSize]; SerializedPacket serialized_packet = packet_generator_.ReserializeAllFrames( - pending.retransmittable_frames, pending.packet_number_length, buffer, - kMaxPacketSize); + pending.retransmittable_frames, pending.encryption_level, + pending.packet_number_length, buffer, kMaxPacketSize); if (serialized_packet.packet == nullptr) { // We failed to serialize the packet, so close the connection. // CloseConnection does not send close packet, so no infinite loop here. @@ -1473,9 +1471,8 @@ void QuicConnection::WritePendingRetransmissions() { DVLOG(1) << ENDPOINT << "Retransmitting " << pending.packet_number << " as " << serialized_packet.packet_number; - SendOrQueuePacket(QueuedPacket( - serialized_packet, pending.retransmittable_frames.encryption_level(), - pending.transmission_type, pending.packet_number)); + SendOrQueuePacket(QueuedPacket(serialized_packet, pending.transmission_type, + pending.packet_number)); } } @@ -1601,7 +1598,8 @@ bool QuicConnection::WritePacketInner(QueuedPacket* packet) { ? "data bearing " : " ack only ")) << ", encryption level: " - << QuicUtils::EncryptionLevelToString(packet->encryption_level) + << QuicUtils::EncryptionLevelToString( + packet->serialized_packet.encryption_level) << ", encrypted length:" << encrypted->length(); DVLOG(2) << ENDPOINT << "packet(" << packet_number << "): " << std::endl << QuicUtils::StringToHexASCIIDump(encrypted->AsStringPiece()); @@ -1632,8 +1630,7 @@ bool QuicConnection::WritePacketInner(QueuedPacket* packet) { // Pass the write result to the visitor. debug_visitor_->OnPacketSent( packet->serialized_packet, packet->original_packet_number, - packet->encryption_level, packet->transmission_type, - encrypted->length(), packet_send_time); + packet->transmission_type, encrypted->length(), packet_send_time); } if (packet->transmission_type == NOT_RETRANSMISSION) { time_of_last_sent_new_packet_ = packet_send_time; @@ -1694,7 +1691,7 @@ bool QuicConnection::ShouldDiscardPacket(const QueuedPacket& packet) { QuicPacketNumber packet_number = packet.serialized_packet.packet_number; if (encryption_level_ == ENCRYPTION_FORWARD_SECURE && - packet.encryption_level == ENCRYPTION_NONE) { + packet.serialized_packet.encryption_level == ENCRYPTION_NONE) { // Drop packets that are NULL encrypted since the peer won't accept them // anymore. DVLOG(1) << ENDPOINT << "Dropping NULL encrypted packet: " << packet_number @@ -1735,7 +1732,7 @@ void QuicConnection::OnSerializedPacket( // If an FEC packet is serialized with the FEC alarm set, cancel the alarm. fec_alarm_->Cancel(); } - SendOrQueuePacket(QueuedPacket(serialized_packet, encryption_level_)); + SendOrQueuePacket(QueuedPacket(serialized_packet)); } void QuicConnection::OnResetFecGroup() { diff --git a/net/quic/quic_connection.h b/net/quic/quic_connection.h index 146324b..971ec01 100644 --- a/net/quic/quic_connection.h +++ b/net/quic/quic_connection.h @@ -156,7 +156,6 @@ class NET_EXPORT_PRIVATE QuicConnectionDebugVisitor // Called when a packet has been sent. virtual void OnPacketSent(const SerializedPacket& serialized_packet, QuicPacketNumber original_packet_number, - EncryptionLevel level, TransmissionType transmission_type, size_t encrypted_length, QuicTime sent_time) {} @@ -632,17 +631,13 @@ class NET_EXPORT_PRIVATE QuicConnection protected: // Packets which have not been written to the wire. - // Owns the QuicPacket* packet. struct QueuedPacket { + explicit QueuedPacket(SerializedPacket packet); QueuedPacket(SerializedPacket packet, - EncryptionLevel level); - QueuedPacket(SerializedPacket packet, - EncryptionLevel level, TransmissionType transmission_type, QuicPacketNumber original_packet_number); SerializedPacket serialized_packet; - const EncryptionLevel encryption_level; TransmissionType transmission_type; // The packet's original packet number if it is a retransmission. // Otherwise it must be 0. diff --git a/net/quic/quic_connection_logger.cc b/net/quic/quic_connection_logger.cc index b1446a4..f4d4f6a 100644 --- a/net/quic/quic_connection_logger.cc +++ b/net/quic/quic_connection_logger.cc @@ -49,13 +49,11 @@ scoped_ptr<base::Value> NetLogQuicPacketCallback( scoped_ptr<base::Value> NetLogQuicPacketSentCallback( const SerializedPacket& serialized_packet, - EncryptionLevel level, TransmissionType transmission_type, size_t packet_size, QuicTime sent_time, NetLogCaptureMode /* capture_mode */) { scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); - dict->SetInteger("encryption_level", level); dict->SetInteger("transmission_type", transmission_type); dict->SetString("packet_number", base::Uint64ToString(serialized_packet.packet_number)); @@ -105,7 +103,7 @@ scoped_ptr<base::Value> NetLogQuicStreamFrameCallback( dict->SetInteger("stream_id", frame->stream_id); dict->SetBoolean("fin", frame->fin); dict->SetString("offset", base::Uint64ToString(frame->offset)); - dict->SetInteger("length", frame->data.size()); + dict->SetInteger("length", frame->frame_length); return dict.Pass(); } @@ -436,14 +434,13 @@ void QuicConnectionLogger::OnFrameAddedToPacket(const QuicFrame& frame) { void QuicConnectionLogger::OnPacketSent( const SerializedPacket& serialized_packet, QuicPacketNumber original_packet_number, - EncryptionLevel level, TransmissionType transmission_type, size_t encrypted_length, QuicTime sent_time) { if (original_packet_number == 0) { net_log_.AddEvent( NetLog::TYPE_QUIC_SESSION_PACKET_SENT, - base::Bind(&NetLogQuicPacketSentCallback, serialized_packet, level, + base::Bind(&NetLogQuicPacketSentCallback, serialized_packet, transmission_type, encrypted_length, sent_time)); } else { net_log_.AddEvent( diff --git a/net/quic/quic_connection_logger.h b/net/quic/quic_connection_logger.h index 358bd80..7bf86ea 100644 --- a/net/quic/quic_connection_logger.h +++ b/net/quic/quic_connection_logger.h @@ -42,7 +42,6 @@ class NET_EXPORT_PRIVATE QuicConnectionLogger // QuicConnectionDebugVisitorInterface void OnPacketSent(const SerializedPacket& serialized_packet, QuicPacketNumber original_packet_number, - EncryptionLevel level, TransmissionType transmission_type, size_t encrypted_length, QuicTime sent_time) override; diff --git a/net/quic/quic_connection_test.cc b/net/quic/quic_connection_test.cc index f33696a..cf8d3a2 100644 --- a/net/quic/quic_connection_test.cc +++ b/net/quic/quic_connection_test.cc @@ -453,17 +453,17 @@ class TestConnection : public QuicConnection { bool has_pending_frames) { RetransmittableFrames* retransmittable_frames = retransmittable == HAS_RETRANSMITTABLE_DATA - ? new RetransmittableFrames(ENCRYPTION_NONE) + ? new RetransmittableFrames() : nullptr; char buffer[kMaxPacketSize]; size_t encrypted_length = QuicConnectionPeer::GetFramer(this)->EncryptPayload( ENCRYPTION_NONE, packet_number, *packet, buffer, kMaxPacketSize); delete packet; - OnSerializedPacket( - SerializedPacket(packet_number, PACKET_6BYTE_PACKET_NUMBER, buffer, - encrypted_length, false, entropy_hash, - retransmittable_frames, has_ack, has_pending_frames)); + OnSerializedPacket(SerializedPacket( + packet_number, PACKET_6BYTE_PACKET_NUMBER, buffer, encrypted_length, + false, entropy_hash, retransmittable_frames, has_ack, + has_pending_frames, ENCRYPTION_NONE)); } QuicConsumedData SendStreamDataWithString( @@ -2374,7 +2374,7 @@ TEST_P(QuicConnectionTest, FramePackingSendv) { EXPECT_EQ(1u, writer_->stream_frames().size()); QuicStreamFrame* frame = writer_->stream_frames()[0]; EXPECT_EQ(1u, frame->stream_id); - EXPECT_EQ("ABCD", frame->data); + EXPECT_EQ("ABCD", StringPiece(frame->frame_buffer, frame->frame_length)); } TEST_P(QuicConnectionTest, FramePackingSendvQueued) { @@ -5377,6 +5377,8 @@ TEST_P(QuicConnectionTest, OnPacketHeaderDebugVisitor) { new MockQuicConnectionDebugVisitor()); connection_.set_debug_visitor(debug_visitor.get()); EXPECT_CALL(*debug_visitor, OnPacketHeader(Ref(header))).Times(1); + EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)).Times(1); + EXPECT_CALL(*debug_visitor, OnSuccessfulVersionNegotiation(_)).Times(1); connection_.OnPacketHeader(header); } diff --git a/net/quic/quic_framer.cc b/net/quic/quic_framer.cc index d7849fb..dea85da 100644 --- a/net/quic/quic_framer.cc +++ b/net/quic/quic_framer.cc @@ -1291,17 +1291,21 @@ bool QuicFramer::ProcessStreamFrame(QuicDataReader* reader, return false; } + // TODO(ianswett): Don't use StringPiece as an intermediary. + StringPiece data; if (has_data_length) { - if (!reader->ReadStringPiece16(&frame->data)) { + if (!reader->ReadStringPiece16(&data)) { set_detailed_error("Unable to read frame data."); return false; } } else { - if (!reader->ReadStringPiece(&frame->data, reader->BytesRemaining())) { + if (!reader->ReadStringPiece(&data, reader->BytesRemaining())) { set_detailed_error("Unable to read frame data."); return false; } } + frame->frame_buffer = data.data(); + frame->frame_length = static_cast<uint16>(data.length()); return true; } @@ -1768,7 +1772,7 @@ size_t QuicFramer::ComputeFrameLength( return GetMinStreamFrameSize(frame.stream_frame->stream_id, frame.stream_frame->offset, last_frame_in_packet, is_in_fec_group) + - frame.stream_frame->data.length(); + frame.stream_frame->frame_length; case ACK_FRAME: { return GetAckFrameSize(*frame.ack_frame, packet_number_length); } @@ -1886,14 +1890,14 @@ bool QuicFramer::AppendStreamFrame(const QuicStreamFrame& frame, return false; } if (!no_stream_frame_length) { - if ((frame.data.size() > numeric_limits<uint16>::max()) || - !writer->WriteUInt16(static_cast<uint16>(frame.data.size()))) { + if ((frame.frame_length > numeric_limits<uint16>::max()) || + !writer->WriteUInt16(static_cast<uint16>(frame.frame_length))) { LOG(DFATAL) << "Writing stream frame length failed"; return false; } } - if (!writer->WriteBytes(frame.data.data(), frame.data.size())) { + if (!writer->WriteBytes(frame.frame_buffer, frame.frame_length)) { LOG(DFATAL) << "Writing frame data failed."; return false; } diff --git a/net/quic/quic_framer_test.cc b/net/quic/quic_framer_test.cc index 4f7e6f4..d967c22 100644 --- a/net/quic/quic_framer_test.cc +++ b/net/quic/quic_framer_test.cc @@ -263,10 +263,11 @@ class TestQuicVisitor : public QuicFramerVisitorInterface { ++frame_count_; // Save a copy of the data so it is valid after the packet is processed. string* string_data = new string(); - frame.data.AppendToString(string_data); + StringPiece(frame.frame_buffer, frame.frame_length) + .AppendToString(string_data); stream_data_.push_back(string_data); - stream_frames_.push_back(new QuicStreamFrame( - frame.stream_id, frame.fin, frame.offset, StringPiece(*string_data))); + stream_frames_.push_back(new QuicStreamFrame(frame.stream_id, frame.fin, + frame.offset, *string_data)); return true; } @@ -444,7 +445,7 @@ class QuicFramerTest : public ::testing::TestWithParam<QuicVersion> { // Checks if the supplied string matches data in the supplied StreamFrame. void CheckStreamFrameData(string str, QuicStreamFrame* frame) { - EXPECT_EQ(str, frame->data); + EXPECT_EQ(str, string(frame->frame_buffer, frame->frame_length)); } void CheckStreamFrameBoundaries(unsigned char* packet, @@ -4540,7 +4541,8 @@ static char kTestString[] = "At least 20 characters."; static QuicStreamId kTestQuicStreamId = 1; static bool ExpectedStreamFrame(const QuicStreamFrame& frame) { return frame.stream_id == kTestQuicStreamId && !frame.fin && - frame.offset == 0 && frame.data == kTestString; + frame.offset == 0 && + string(frame.frame_buffer, frame.frame_length) == kTestString; // FIN is hard-coded false in ConstructEncryptedPacket. // Offset 0 is hard-coded in ConstructEncryptedPacket. } diff --git a/net/quic/quic_headers_stream_test.cc b/net/quic/quic_headers_stream_test.cc index 1c70050..680bdf2 100644 --- a/net/quic/quic_headers_stream_test.cc +++ b/net/quic/quic_headers_stream_test.cc @@ -328,7 +328,8 @@ TEST_P(QuicHeadersStreamTest, ProcessRawData) { &QuicHeadersStreamTest::SaveHeaderDataStringPiece))); EXPECT_CALL(session_, OnStreamHeadersComplete(stream_id, fin, frame->size())); - stream_frame_.data = StringPiece(frame->data(), frame->size()); + stream_frame_.frame_buffer = frame->data(); + stream_frame_.frame_length = frame->size(); headers_stream_->OnStreamFrame(stream_frame_); stream_frame_.offset += frame->size(); CheckHeaders(); @@ -361,7 +362,8 @@ TEST_P(QuicHeadersStreamTest, EmptyHeaderHOLBlockedTime) { EXPECT_CALL(session_, OnStreamHeaders(stream_id, _)); EXPECT_CALL(session_, OnStreamHeadersComplete(stream_id, fin, frame->size())); - stream_frame_.data = StringPiece(frame->data(), frame->size()); + stream_frame_.frame_buffer = frame->data(); + stream_frame_.frame_length = frame->size(); headers_stream_->OnStreamFrame(stream_frame_); connection_->AdvanceTime(QuicTime::Delta::FromMilliseconds(1)); stream_frame_.offset += frame->size(); @@ -393,8 +395,8 @@ TEST_P(QuicHeadersStreamTest, NonEmptyHeaderHOLBlockedTime) { } stream_frames[stream_num].stream_id = stream_frame_.stream_id; stream_frames[stream_num].offset = stream_frame_.offset; - stream_frames[stream_num].data = - StringPiece(frames[stream_num]->data(), frames[stream_num]->size()); + stream_frames[stream_num].frame_buffer = frames[stream_num]->data(); + stream_frames[stream_num].frame_length = frames[stream_num]->size(); DVLOG(1) << "make frame for stream " << stream_num << " offset " << stream_frames[stream_num].offset; stream_frame_.offset += frames[stream_num]->size(); @@ -446,7 +448,8 @@ TEST_P(QuicHeadersStreamTest, ProcessLargeRawData) { this, &QuicHeadersStreamTest::SaveHeaderDataStringPiece))); EXPECT_CALL(session_, OnStreamHeadersComplete(stream_id, fin, frame->size())); - stream_frame_.data = StringPiece(frame->data(), frame->size()); + stream_frame_.frame_buffer = frame->data(); + stream_frame_.frame_length = frame->size(); headers_stream_->OnStreamFrame(stream_frame_); stream_frame_.offset += frame->size(); CheckHeaders(); @@ -460,7 +463,8 @@ TEST_P(QuicHeadersStreamTest, ProcessBadData) { EXPECT_CALL(*connection_, SendConnectionCloseWithDetails( QUIC_INVALID_HEADERS_STREAM_DATA, _)) .Times(::testing::AnyNumber()); - stream_frame_.data = StringPiece(kBadData, strlen(kBadData)); + stream_frame_.frame_buffer = kBadData; + stream_frame_.frame_length = strlen(kBadData); headers_stream_->OnStreamFrame(stream_frame_); } @@ -472,7 +476,8 @@ TEST_P(QuicHeadersStreamTest, ProcessSpdyDataFrame) { "SPDY DATA frame received.")) .WillOnce(InvokeWithoutArgs(this, &QuicHeadersStreamTest::CloseConnection)); - stream_frame_.data = StringPiece(frame->data(), frame->size()); + stream_frame_.frame_buffer = frame->data(); + stream_frame_.frame_length = frame->size(); headers_stream_->OnStreamFrame(stream_frame_); } @@ -485,7 +490,8 @@ TEST_P(QuicHeadersStreamTest, ProcessSpdyRstStreamFrame) { "SPDY RST_STREAM frame received.")) .WillOnce(InvokeWithoutArgs(this, &QuicHeadersStreamTest::CloseConnection)); - stream_frame_.data = StringPiece(frame->data(), frame->size()); + stream_frame_.frame_buffer = frame->data(); + stream_frame_.frame_length = frame->size(); headers_stream_->OnStreamFrame(stream_frame_); } @@ -499,7 +505,8 @@ TEST_P(QuicHeadersStreamTest, ProcessSpdySettingsFrame) { "SPDY SETTINGS frame received.")) .WillOnce(InvokeWithoutArgs(this, &QuicHeadersStreamTest::CloseConnection)); - stream_frame_.data = StringPiece(frame->data(), frame->size()); + stream_frame_.frame_buffer = frame->data(); + stream_frame_.frame_length = frame->size(); headers_stream_->OnStreamFrame(stream_frame_); } @@ -511,7 +518,8 @@ TEST_P(QuicHeadersStreamTest, ProcessSpdyPingFrame) { "SPDY PING frame received.")) .WillOnce(InvokeWithoutArgs(this, &QuicHeadersStreamTest::CloseConnection)); - stream_frame_.data = StringPiece(frame->data(), frame->size()); + stream_frame_.frame_buffer = frame->data(); + stream_frame_.frame_length = frame->size(); headers_stream_->OnStreamFrame(stream_frame_); } @@ -523,7 +531,8 @@ TEST_P(QuicHeadersStreamTest, ProcessSpdyGoAwayFrame) { "SPDY GOAWAY frame received.")) .WillOnce(InvokeWithoutArgs(this, &QuicHeadersStreamTest::CloseConnection)); - stream_frame_.data = StringPiece(frame->data(), frame->size()); + stream_frame_.frame_buffer = frame->data(); + stream_frame_.frame_length = frame->size(); headers_stream_->OnStreamFrame(stream_frame_); } @@ -536,7 +545,8 @@ TEST_P(QuicHeadersStreamTest, ProcessSpdyWindowUpdateFrame) { "SPDY WINDOW_UPDATE frame received.")) .WillOnce(InvokeWithoutArgs(this, &QuicHeadersStreamTest::CloseConnection)); - stream_frame_.data = StringPiece(frame->data(), frame->size()); + stream_frame_.frame_buffer = frame->data(); + stream_frame_.frame_length = frame->size(); headers_stream_->OnStreamFrame(stream_frame_); } diff --git a/net/quic/quic_packet_creator.cc b/net/quic/quic_packet_creator.cc index 5b98958..b161335 100644 --- a/net/quic/quic_packet_creator.cc +++ b/net/quic/quic_packet_creator.cc @@ -91,7 +91,7 @@ QuicPacketCreator::QuicPacketCreator(QuicConnectionId connection_id, framer_(framer), random_bool_source_(new QuicRandomBoolSource(random_generator)), packet_number_(0), - should_fec_protect_(false), + should_fec_protect_next_packet_(false), fec_protect_(false), send_version_in_packet_(framer->perspective() == Perspective::IS_CLIENT), max_packet_length_(0), @@ -251,11 +251,16 @@ bool QuicPacketCreator::ConsumeData(QuicStreamId id, QuicStreamOffset offset, bool fin, bool needs_padding, - QuicFrame* frame) { + QuicFrame* frame, + FecProtection fec_protection) { if (!HasRoomForStreamFrame(id, offset)) { Flush(); return false; } + if (fec_protection == MUST_FEC_PROTECT) { + should_fec_protect_next_packet_ = true; + MaybeStartFecProtection(); + } CreateStreamFrame(id, iov, iov_offset, offset, fin, frame); bool success = AddFrame(*frame, /*save_retransmittable_frames=*/true, needs_padding); @@ -321,10 +326,8 @@ size_t QuicPacketCreator::CreateStreamFrame(QuicStreamId id, bool set_fin = fin && bytes_consumed == data_size; // Last frame. UniqueStreamBuffer buffer = NewStreamBuffer(bytes_consumed); CopyToBuffer(iov, iov_offset, bytes_consumed, buffer.get()); - // TODO(zhongyi): figure out the lifetime of data. Crashes on windows only. - StringPiece data(buffer.get(), bytes_consumed); - *frame = QuicFrame( - new QuicStreamFrame(id, set_fin, offset, data, std::move(buffer))); + *frame = QuicFrame(new QuicStreamFrame(id, set_fin, offset, bytes_consumed, + std::move(buffer))); return bytes_consumed; } @@ -394,6 +397,7 @@ void QuicPacketCreator::CopyToBuffer(QuicIOVector iov, SerializedPacket QuicPacketCreator::ReserializeAllFrames( const RetransmittableFrames& frames, + EncryptionLevel original_encryption_level, QuicPacketNumberLength original_length, char* buffer, size_t buffer_len) { @@ -409,8 +413,13 @@ SerializedPacket QuicPacketCreator::ReserializeAllFrames( packet_number_length_ = original_length; next_packet_number_length_ = original_length; fec_protect_ = false; - encryption_level_ = frames.encryption_level(); needs_padding_ = frames.needs_padding(); + // Only preserve the original encryption level if it's a handshake packet or + // if we haven't gone forward secure. + if (frames.HasCryptoHandshake() || + encryption_level_ != ENCRYPTION_FORWARD_SECURE) { + encryption_level_ = original_encryption_level; + } // Serialize the packet and restore the FEC and packet number length state. SerializedPacket serialized_packet = @@ -590,7 +599,8 @@ SerializedPacket QuicPacketCreator::SerializePacket( header.packet_number, header.public_header.packet_number_length, encrypted_buffer, encrypted_length, /* owns_buffer*/ false, QuicFramer::GetPacketEntropyHash(header), - queued_retransmittable_frames_.release(), has_ack, has_stop_waiting); + queued_retransmittable_frames_.release(), has_ack, has_stop_waiting, + encryption_level_); } SerializedPacket QuicPacketCreator::SerializeFec(char* buffer, @@ -620,10 +630,11 @@ SerializedPacket QuicPacketCreator::SerializeFec(char* buffer, LOG(DFATAL) << "Failed to encrypt packet number " << packet_number_; return NoPacket(); } - SerializedPacket serialized( - header.packet_number, header.public_header.packet_number_length, buffer, - encrypted_length, /* owns_buffer */ false, - QuicFramer::GetPacketEntropyHash(header), nullptr, false, false); + SerializedPacket serialized(header.packet_number, + header.public_header.packet_number_length, buffer, + encrypted_length, /* owns_buffer */ false, + QuicFramer::GetPacketEntropyHash(header), nullptr, + false, false, encryption_level_); serialized.is_fec_packet = true; return serialized; } @@ -689,8 +700,7 @@ bool QuicPacketCreator::AddFrame(const QuicFrame& frame, if (save_retransmittable_frames && ShouldRetransmit(frame)) { if (queued_retransmittable_frames_.get() == nullptr) { - queued_retransmittable_frames_.reset( - new RetransmittableFrames(encryption_level_)); + queued_retransmittable_frames_.reset(new RetransmittableFrames()); } queued_frames_.push_back(queued_retransmittable_frames_->AddFrame(frame)); } else { @@ -748,7 +758,7 @@ void QuicPacketCreator::MaybeSendFecPacketAndCloseGroup(bool force_send_fec, } } - if (!should_fec_protect_ && fec_protect_ && !IsFecGroupOpen()) { + if (!should_fec_protect_next_packet_ && fec_protect_ && !IsFecGroupOpen()) { StopFecProtectingPackets(); } } diff --git a/net/quic/quic_packet_creator.h b/net/quic/quic_packet_creator.h index a3228ab..152b44a 100644 --- a/net/quic/quic_packet_creator.h +++ b/net/quic/quic_packet_creator.h @@ -52,14 +52,11 @@ class NET_EXPORT_PRIVATE QuicPacketCreator { // return true if an FEC group is open. bool ShouldSendFec(bool force_close) const; - // Turn on FEC protection for subsequent packets. If no FEC group is currently - // open, this method flushes current open packet and then turns FEC on. - void MaybeStartFecProtection(); - // If ShouldSendFec returns true, serializes currently constructed FEC packet // and calls the delegate on the packet. Resets current FEC group if FEC // protection policy is FEC_ALARM_TRIGGER but |is_fec_timeout| is false. - // Also tries to turn off FEC protection if should_fec_protect_ is false. + // Also tries to turn off FEC protection if should_fec_protect_next_packet is + // false. void MaybeSendFecPacketAndCloseGroup(bool force_send_fec, bool is_fec_timeout); @@ -93,13 +90,15 @@ class NET_EXPORT_PRIVATE QuicPacketCreator { // If current packet is not full, converts a raw payload into a stream frame // that fits into the open packet and adds it to the packet. // The payload begins at |iov_offset| into the |iov|. + // Also tries to start FEC protection depends on |fec_protection|. bool ConsumeData(QuicStreamId id, QuicIOVector iov, size_t iov_offset, QuicStreamOffset offset, bool fin, bool needs_padding, - QuicFrame* frame); + QuicFrame* frame, + FecProtection fec_protection); // Returns true if current open packet can accommodate more stream frames of // stream |id| at |offset|, false otherwise. @@ -117,10 +116,12 @@ class NET_EXPORT_PRIVATE QuicPacketCreator { // Used for retransmitting packets to ensure they aren't too long. // Caller must ensure that any open FEC group is closed before calling this // method. - SerializedPacket ReserializeAllFrames(const RetransmittableFrames& frames, - QuicPacketNumberLength original_length, - char* buffer, - size_t buffer_len); + SerializedPacket ReserializeAllFrames( + const RetransmittableFrames& frames, + EncryptionLevel original_encryption_level, + QuicPacketNumberLength original_length, + char* buffer, + size_t buffer_len); // Serializes all added frames into a single packet and invokes the delegate_ // to further process the SerializedPacket. @@ -229,10 +230,12 @@ class NET_EXPORT_PRIVATE QuicPacketCreator { rtt_multiplier_for_fec_timeout_ = rtt_multiplier_for_fec_timeout; } - bool should_fec_protect() { return should_fec_protect_; } + bool should_fec_protect_next_packet() { + return should_fec_protect_next_packet_; + } - void set_should_fec_protect(bool should_fec_protect) { - should_fec_protect_ = should_fec_protect; + void set_should_fec_protect_next_packet(bool should_fec_protect_next_packet) { + should_fec_protect_next_packet_ = should_fec_protect_next_packet; } private: @@ -297,6 +300,10 @@ class NET_EXPORT_PRIVATE QuicPacketCreator { // Fails if |buffer_len| isn't long enough for the encrypted packet. SerializedPacket SerializePacket(char* encrypted_buffer, size_t buffer_len); + // Turn on FEC protection for subsequent packets. If no FEC group is currently + // open, this method flushes current open packet and then turns FEC on. + void MaybeStartFecProtection(); + // Turn on FEC protection for subsequently created packets. FEC should be // enabled first (max_packets_per_fec_group should be non-zero) for FEC // protection to start. @@ -326,12 +333,13 @@ class NET_EXPORT_PRIVATE QuicPacketCreator { scoped_ptr<QuicRandomBoolSource> random_bool_source_; QuicPacketNumber packet_number_; // True when creator is requested to turn on FEC protection. False otherwise. - // There could be a time difference between should_fec_protect_ is true/false - // and FEC is actually turned on/off (e.g., The creator may have an open FEC - // group even if this variable is false). - bool should_fec_protect_; + // There is a time difference between should_fec_protect_next_packet is + // true/false and FEC is actually turned on/off (e.g., The creator may have an + // open FEC group even if this variable is false). + bool should_fec_protect_next_packet_; // If true, any created packets will be FEC protected. - // TODO(fayang): Combine should_fec_protect_ and fec_protect_ to one variable. + // TODO(fayang): Combine should_fec_protect_next_packet and fec_protect_ to + // one variable. bool fec_protect_; scoped_ptr<QuicFecGroup> fec_group_; // Controls whether protocol version should be included while serializing the diff --git a/net/quic/quic_packet_creator_test.cc b/net/quic/quic_packet_creator_test.cc index 951738b..1e6d3b2 100644 --- a/net/quic/quic_packet_creator_test.cc +++ b/net/quic/quic_packet_creator_test.cc @@ -124,6 +124,9 @@ class QuicPacketCreatorTest : public ::testing::TestWithParam<TestParams> { creator_(connection_id_, &client_framer_, &mock_random_, &delegate_), serialized_packet_(creator_.NoPacket()) { creator_.set_connection_id_length(GetParam().connection_id_length); + + creator_.SetEncrypter(ENCRYPTION_INITIAL, new NullEncrypter()); + creator_.SetEncrypter(ENCRYPTION_FORWARD_SECURE, new NullEncrypter()); client_framer_.set_visitor(&framer_visitor_); client_framer_.set_received_entropy_calculator(&entropy_calculator_); server_framer_.set_visitor(&framer_visitor_); @@ -132,6 +135,14 @@ class QuicPacketCreatorTest : public ::testing::TestWithParam<TestParams> { ~QuicPacketCreatorTest() override {} + SerializedPacket SerializeAllFrames(const QuicFrames& frames) { + SerializedPacket packet = + creator_.SerializeAllFrames(frames, buffer_, kMaxPacketSize); + EXPECT_EQ(QuicPacketCreatorPeer::GetEncryptionLevel(&creator_), + packet.encryption_level); + return packet; + } + void ProcessPacket(QuicEncryptedPacket* encrypted) { server_framer_.ProcessPacket(*encrypted); } @@ -144,7 +155,8 @@ class QuicPacketCreatorTest : public ::testing::TestWithParam<TestParams> { EXPECT_EQ(STREAM_FRAME, frame.type); ASSERT_TRUE(frame.stream_frame); EXPECT_EQ(stream_id, frame.stream_frame->stream_id); - EXPECT_EQ(data, frame.stream_frame->data); + EXPECT_EQ(data, StringPiece(frame.stream_frame->frame_buffer, + frame.stream_frame->frame_length)); EXPECT_EQ(offset, frame.stream_frame->offset); EXPECT_EQ(fin, frame.stream_frame->fin); } @@ -172,19 +184,13 @@ class QuicPacketCreatorTest : public ::testing::TestWithParam<TestParams> { true, is_in_fec_group); } - // Enables and turns on FEC protection. Returns true if FEC protection is on. - bool SwitchFecProtectionOn(size_t max_packets_per_fec_group) { - creator_.set_max_packets_per_fec_group(max_packets_per_fec_group); - creator_.MaybeStartFecProtection(); - return QuicPacketCreatorPeer::IsFecProtected(&creator_); - } - QuicIOVector MakeIOVector(StringPiece s) { return ::net::MakeIOVector(s, &iov_); } static const QuicStreamOffset kOffset = 1u; + char buffer_[kMaxPacketSize]; QuicFrames frames_; QuicFramer server_framer_; QuicFramer client_framer_; @@ -207,47 +213,54 @@ INSTANTIATE_TEST_CASE_P(QuicPacketCreatorTests, ::testing::ValuesIn(GetTestParams())); TEST_P(QuicPacketCreatorTest, SerializeFrames) { - frames_.push_back(QuicFrame(new QuicAckFrame(MakeAckFrame(0u)))); - frames_.push_back( - QuicFrame(new QuicStreamFrame(0u, false, 0u, StringPiece()))); - frames_.push_back( - QuicFrame(new QuicStreamFrame(0u, true, 0u, StringPiece()))); - char buffer[kMaxPacketSize]; - SerializedPacket serialized = - creator_.SerializeAllFrames(frames_, buffer, kMaxPacketSize); - delete frames_[0].ack_frame; - delete frames_[1].stream_frame; - delete frames_[2].stream_frame; + for (int i = ENCRYPTION_NONE; i < NUM_ENCRYPTION_LEVELS; ++i) { + EncryptionLevel level = static_cast<EncryptionLevel>(i); + creator_.set_encryption_level(level); + frames_.push_back(QuicFrame(new QuicAckFrame(MakeAckFrame(0u)))); + frames_.push_back( + QuicFrame(new QuicStreamFrame(0u, false, 0u, StringPiece()))); + frames_.push_back( + QuicFrame(new QuicStreamFrame(0u, true, 0u, StringPiece()))); + SerializedPacket serialized = SerializeAllFrames(frames_); + EXPECT_EQ(level, serialized.encryption_level); + delete frames_[0].ack_frame; + delete frames_[1].stream_frame; + delete frames_[2].stream_frame; + frames_.clear(); - { - InSequence s; - EXPECT_CALL(framer_visitor_, OnPacket()); - EXPECT_CALL(framer_visitor_, OnUnauthenticatedPublicHeader(_)); - EXPECT_CALL(framer_visitor_, OnUnauthenticatedHeader(_)); - EXPECT_CALL(framer_visitor_, OnDecryptedPacket(_)); - EXPECT_CALL(framer_visitor_, OnPacketHeader(_)); - EXPECT_CALL(framer_visitor_, OnAckFrame(_)); - EXPECT_CALL(framer_visitor_, OnStreamFrame(_)); - EXPECT_CALL(framer_visitor_, OnStreamFrame(_)); - EXPECT_CALL(framer_visitor_, OnPacketComplete()); + { + InSequence s; + EXPECT_CALL(framer_visitor_, OnPacket()); + EXPECT_CALL(framer_visitor_, OnUnauthenticatedPublicHeader(_)); + EXPECT_CALL(framer_visitor_, OnUnauthenticatedHeader(_)); + EXPECT_CALL(framer_visitor_, OnDecryptedPacket(_)); + EXPECT_CALL(framer_visitor_, OnPacketHeader(_)); + EXPECT_CALL(framer_visitor_, OnAckFrame(_)); + EXPECT_CALL(framer_visitor_, OnStreamFrame(_)); + EXPECT_CALL(framer_visitor_, OnStreamFrame(_)); + EXPECT_CALL(framer_visitor_, OnPacketComplete()); + } + ProcessPacket(serialized.packet); + delete serialized.packet; } - ProcessPacket(serialized.packet); - delete serialized.packet; } TEST_P(QuicPacketCreatorTest, SerializeWithFEC) { - // Enable FEC protection, and send FEC packet every 6 packets. - EXPECT_TRUE(SwitchFecProtectionOn(6)); + // Send FEC packet every 6 packets. + creator_.set_max_packets_per_fec_group(6); // Should return false since we do not have enough packets in the FEC group to // trigger an FEC packet. ASSERT_FALSE(creator_.ShouldSendFec(/*force_close=*/false)); - - frames_.push_back( - QuicFrame(new QuicStreamFrame(0u, false, 0u, StringPiece()))); - char buffer[kMaxPacketSize]; - SerializedPacket serialized = - creator_.SerializeAllFrames(frames_, buffer, kMaxPacketSize); - delete frames_[0].stream_frame; + // Turn on FEC protection. + QuicFrame frame; + QuicIOVector io_vector(MakeIOVector("test")); + ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame, + MUST_FEC_PROTECT)); + EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(&creator_)); + // Serialize the packet. + EXPECT_CALL(delegate_, OnSerializedPacket(_)) + .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket)); + creator_.Flush(); { InSequence s; @@ -260,8 +273,8 @@ TEST_P(QuicPacketCreatorTest, SerializeWithFEC) { EXPECT_CALL(framer_visitor_, OnStreamFrame(_)); EXPECT_CALL(framer_visitor_, OnPacketComplete()); } - ProcessPacket(serialized.packet); - delete serialized.packet; + ProcessPacket(serialized_packet_.packet); + ClearSerializedPacket(&serialized_packet_); // Should return false since we do not have enough packets in the FEC group to // trigger an FEC packet. @@ -271,7 +284,6 @@ TEST_P(QuicPacketCreatorTest, SerializeWithFEC) { EXPECT_CALL(delegate_, OnSerializedPacket(_)) .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket)); - creator_.set_should_fec_protect(true); creator_.MaybeSendFecPacketAndCloseGroup(/*force_send_fec=*/true, /*is_fec_timeout=*/false); ASSERT_EQ(2u, serialized_packet_.packet_number); @@ -425,15 +437,17 @@ TEST_P(QuicPacketCreatorTest, SerializeWithFECChangingSequenceNumberLength) { // and we expect that packet number length should not change until the end // of the open FEC group. - // Enable FEC protection, and send FEC packet every 6 packets. - EXPECT_TRUE(SwitchFecProtectionOn(6)); + // Send FEC packet every 6 packets. + creator_.set_max_packets_per_fec_group(6); // Should return false since we do not have enough packets in the FEC group to // trigger an FEC packet. ASSERT_FALSE(creator_.ShouldSendFec(/*force_close=*/false)); - frames_.push_back(QuicFrame(new QuicAckFrame(MakeAckFrame(0u)))); // Generate Packet 1. - creator_.AddSavedFrame(frames_[0]); + QuicFrame frame; + QuicIOVector io_vector(MakeIOVector("test")); + ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame, + MUST_FEC_PROTECT)); // Change the packet number length mid-FEC group and it should not change. QuicPacketCreatorPeer::SetNextPacketNumberLength(&creator_, PACKET_4BYTE_PACKET_NUMBER); @@ -452,14 +466,15 @@ TEST_P(QuicPacketCreatorTest, SerializeWithFECChangingSequenceNumberLength) { EXPECT_CALL(framer_visitor_, OnDecryptedPacket(_)); EXPECT_CALL(framer_visitor_, OnPacketHeader(_)); EXPECT_CALL(framer_visitor_, OnFecProtectedPayload(_)); - EXPECT_CALL(framer_visitor_, OnAckFrame(_)); + EXPECT_CALL(framer_visitor_, OnStreamFrame(_)); EXPECT_CALL(framer_visitor_, OnPacketComplete()); } ProcessPacket(serialized_packet_.packet); ClearSerializedPacket(&serialized_packet_); // Generate Packet 2. - creator_.AddSavedFrame(frames_[0]); + ASSERT_TRUE(creator_.ConsumeData(2u, io_vector, 0u, 0u, false, false, &frame, + MUST_FEC_PROTECT)); creator_.Flush(); EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER, serialized_packet_.packet_number_length); @@ -472,7 +487,7 @@ TEST_P(QuicPacketCreatorTest, SerializeWithFECChangingSequenceNumberLength) { EXPECT_CALL(framer_visitor_, OnDecryptedPacket(_)); EXPECT_CALL(framer_visitor_, OnPacketHeader(_)); EXPECT_CALL(framer_visitor_, OnFecProtectedPayload(_)); - EXPECT_CALL(framer_visitor_, OnAckFrame(_)); + EXPECT_CALL(framer_visitor_, OnStreamFrame(_)); EXPECT_CALL(framer_visitor_, OnPacketComplete()); } ProcessPacket(serialized_packet_.packet); @@ -487,7 +502,8 @@ TEST_P(QuicPacketCreatorTest, SerializeWithFECChangingSequenceNumberLength) { // Force generation of FEC packet. EXPECT_CALL(delegate_, OnSerializedPacket(_)) .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket)); - creator_.set_should_fec_protect(true); + // Turn off FEC protection. + creator_.set_should_fec_protect_next_packet(false); creator_.MaybeSendFecPacketAndCloseGroup(/*force_send_fec=*/true, /*is_fec_timeout=*/false); EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER, @@ -508,12 +524,15 @@ TEST_P(QuicPacketCreatorTest, SerializeWithFECChangingSequenceNumberLength) { ClearSerializedPacket(&serialized_packet_); // Ensure the next FEC group starts using the new packet number length. - char buffer[kMaxPacketSize]; - SerializedPacket serialized = - creator_.SerializeAllFrames(frames_, buffer, kMaxPacketSize); - EXPECT_EQ(PACKET_4BYTE_PACKET_NUMBER, serialized.packet_number_length); - delete frames_[0].ack_frame; - ClearSerializedPacket(&serialized); + ASSERT_TRUE(creator_.ConsumeData(3u, io_vector, 0u, 0u, false, false, &frame, + MUST_FEC_PROTECT)); + EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(&creator_)); + EXPECT_CALL(delegate_, OnSerializedPacket(_)) + .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket)); + creator_.Flush(); + EXPECT_EQ(PACKET_4BYTE_PACKET_NUMBER, + serialized_packet_.packet_number_length); + ClearSerializedPacket(&serialized_packet_); } TEST_P(QuicPacketCreatorTest, ReserializeFramesWithSequenceNumberLength) { @@ -526,11 +545,12 @@ TEST_P(QuicPacketCreatorTest, ReserializeFramesWithSequenceNumberLength) { PACKET_2BYTE_PACKET_NUMBER); QuicStreamFrame* stream_frame = new QuicStreamFrame(kCryptoStreamId, /*fin=*/false, 0u, StringPiece()); - RetransmittableFrames frames(ENCRYPTION_NONE); + RetransmittableFrames frames; frames.AddFrame(QuicFrame(stream_frame)); char buffer[kMaxPacketSize]; SerializedPacket serialized = creator_.ReserializeAllFrames( - frames, PACKET_1BYTE_PACKET_NUMBER, buffer, kMaxPacketSize); + frames, ENCRYPTION_NONE, PACKET_1BYTE_PACKET_NUMBER, buffer, + kMaxPacketSize); EXPECT_EQ(PACKET_4BYTE_PACKET_NUMBER, QuicPacketCreatorPeer::NextPacketNumberLength(&creator_)); EXPECT_EQ(PACKET_2BYTE_PACKET_NUMBER, @@ -551,17 +571,48 @@ TEST_P(QuicPacketCreatorTest, ReserializeFramesWithSequenceNumberLength) { delete serialized.packet; } +TEST_P(QuicPacketCreatorTest, ReserializeCryptoFrameWithForwardSecurity) { + QuicStreamFrame* stream_frame = + new QuicStreamFrame(kCryptoStreamId, /*fin=*/false, 0u, StringPiece()); + RetransmittableFrames frames; + frames.AddFrame(QuicFrame(stream_frame)); + creator_.set_encryption_level(ENCRYPTION_FORWARD_SECURE); + char buffer[kMaxPacketSize]; + SerializedPacket serialized = creator_.ReserializeAllFrames( + frames, ENCRYPTION_NONE, + QuicPacketCreatorPeer::NextPacketNumberLength(&creator_), buffer, + kMaxPacketSize); + EXPECT_EQ(ENCRYPTION_NONE, serialized.encryption_level); + delete serialized.packet; +} + +TEST_P(QuicPacketCreatorTest, ReserializeFrameWithForwardSecurity) { + QuicStreamFrame* stream_frame = + new QuicStreamFrame(0u, /*fin=*/false, 0u, StringPiece()); + RetransmittableFrames frames; + frames.AddFrame(QuicFrame(stream_frame)); + creator_.set_encryption_level(ENCRYPTION_FORWARD_SECURE); + char buffer[kMaxPacketSize]; + SerializedPacket serialized = creator_.ReserializeAllFrames( + frames, ENCRYPTION_NONE, + QuicPacketCreatorPeer::NextPacketNumberLength(&creator_), buffer, + kMaxPacketSize); + EXPECT_EQ(ENCRYPTION_FORWARD_SECURE, serialized.encryption_level); + delete serialized.packet; +} + TEST_P(QuicPacketCreatorTest, ReserializeFramesWithPadding) { QuicFrame frame; QuicIOVector io_vector(MakeIOVector("fake handshake message data")); QuicPacketCreatorPeer::CreateStreamFrame(&creator_, kCryptoStreamId, io_vector, 0u, 0u, false, &frame); - RetransmittableFrames frames(ENCRYPTION_NONE); + RetransmittableFrames frames; frames.AddFrame(frame); frames.set_needs_padding(true); char buffer[kMaxPacketSize]; SerializedPacket serialized = creator_.ReserializeAllFrames( - frames, QuicPacketCreatorPeer::NextPacketNumberLength(&creator_), buffer, + frames, ENCRYPTION_NONE, + QuicPacketCreatorPeer::NextPacketNumberLength(&creator_), buffer, kMaxPacketSize); EXPECT_EQ(kDefaultMaxPacketSize, serialized.packet->length()); delete serialized.packet; @@ -577,15 +628,17 @@ TEST_P(QuicPacketCreatorTest, ReserializeFramesWithFullPacketAndPadding) { QuicFrame frame; QuicIOVector io_vector(MakeIOVector(data)); + UniqueStreamBuffer stream_buffer; QuicPacketCreatorPeer::CreateStreamFrame( &creator_, kCryptoStreamId, io_vector, 0, kOffset, false, &frame); - RetransmittableFrames frames(ENCRYPTION_NONE); + RetransmittableFrames frames; frames.AddFrame(frame); frames.set_needs_padding(true); char buffer[kMaxPacketSize]; SerializedPacket serialized = creator_.ReserializeAllFrames( - frames, QuicPacketCreatorPeer::NextPacketNumberLength(&creator_), - buffer, kMaxPacketSize); + frames, ENCRYPTION_NONE, + QuicPacketCreatorPeer::NextPacketNumberLength(&creator_), buffer, + kMaxPacketSize); // If there is not enough space in the packet to fit a padding frame // (1 byte) and to expand the stream frame (another 2 bytes) the packet @@ -609,9 +662,8 @@ TEST_P(QuicPacketCreatorTest, SerializeConnectionClose) { QuicFrames frames; frames.push_back(QuicFrame(&frame)); - char buffer[kMaxPacketSize]; - SerializedPacket serialized = - creator_.SerializeAllFrames(frames, buffer, kMaxPacketSize); + SerializedPacket serialized = SerializeAllFrames(frames); + EXPECT_EQ(ENCRYPTION_NONE, serialized.encryption_level); ASSERT_EQ(1u, serialized.packet_number); ASSERT_EQ(1u, creator_.packet_number()); @@ -628,36 +680,18 @@ TEST_P(QuicPacketCreatorTest, SerializeConnectionClose) { delete serialized.packet; } -TEST_P(QuicPacketCreatorTest, SwitchFecOnOffWithNoGroup) { - // Enable FEC protection. +TEST_P(QuicPacketCreatorTest, SwitchFecOnOffWithGroupInProgress) { + // Send FEC packet every 6 packets. creator_.set_max_packets_per_fec_group(6); - EXPECT_TRUE(QuicPacketCreatorPeer::IsFecEnabled(&creator_)); - EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(&creator_)); - // Turn on FEC protection. - creator_.MaybeStartFecProtection(); - EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(&creator_)); - // We have no packets in the FEC group, so no FEC packet can be created. - EXPECT_FALSE(creator_.ShouldSendFec(/*force_close=*/true)); - // Since no packets are in FEC group yet, we should be able to turn FEC - // off with no trouble. - creator_.MaybeSendFecPacketAndCloseGroup(/*force_send_fec=*/true, - /*is_fec_timeout=*/false); - EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(&creator_)); -} - -TEST_P(QuicPacketCreatorTest, SwitchFecOnOffWithGroupInProgress) { - // Enable FEC protection, and send FEC packet every 6 packets. - EXPECT_TRUE(SwitchFecProtectionOn(6)); - frames_.push_back( - QuicFrame(new QuicStreamFrame(0u, false, 0u, StringPiece()))); - char buffer[kMaxPacketSize]; - SerializedPacket serialized = - creator_.SerializeAllFrames(frames_, buffer, kMaxPacketSize); - delete frames_[0].stream_frame; - delete serialized.packet; - + QuicFrame frame; + QuicIOVector io_vector(MakeIOVector("test")); + ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame, + MUST_FEC_PROTECT)); EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(&creator_)); + EXPECT_CALL(delegate_, OnSerializedPacket(_)) + .WillOnce(Invoke(this, &QuicPacketCreatorTest::ClearSerializedPacket)); + creator_.Flush(); // We do not have enough packets in the FEC group to trigger an FEC packet. EXPECT_FALSE(creator_.ShouldSendFec(/*force_close=*/false)); // Should return true since there are packets in the FEC group. @@ -673,22 +707,22 @@ TEST_P(QuicPacketCreatorTest, SwitchFecOnOffWithGroupInProgress) { EXPECT_CALL(delegate_, OnSerializedPacket(_)) .WillOnce(Invoke(this, &QuicPacketCreatorTest::ClearSerializedPacket)); - // Switching FEC on/off should work now. + // Turn off FEC protection. + creator_.set_should_fec_protect_next_packet(false); creator_.MaybeSendFecPacketAndCloseGroup(/*force_send_fec=*/true, /*is_fec_timeout=*/false); EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(&creator_)); - creator_.MaybeStartFecProtection(); - EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(&creator_)); } TEST_P(QuicPacketCreatorTest, SwitchFecOnWithStreamFrameQueued) { // Add a stream frame to the creator. QuicFrame frame; QuicIOVector io_vector(MakeIOVector("test")); - ASSERT_TRUE( - creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame)); + ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame, + MAY_FEC_PROTECT)); + EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(&creator_)); ASSERT_TRUE(frame.stream_frame); - size_t consumed = frame.stream_frame->data.length(); + size_t consumed = frame.stream_frame->frame_length; EXPECT_EQ(4u, consumed); EXPECT_TRUE(creator_.HasPendingFrames()); @@ -702,18 +736,22 @@ TEST_P(QuicPacketCreatorTest, SwitchFecOnWithStreamFrameQueued) { // Start FEC protection after current open packet is flushed. EXPECT_CALL(delegate_, OnSerializedPacket(_)) .WillOnce(Invoke(this, &QuicPacketCreatorTest::ClearSerializedPacket)); - creator_.MaybeStartFecProtection(); - EXPECT_FALSE(creator_.HasPendingFrames()); + ASSERT_TRUE(creator_.ConsumeData(2u, io_vector, 0u, 0u, false, false, &frame, + MUST_FEC_PROTECT)); + ASSERT_TRUE(frame.stream_frame); + consumed = frame.stream_frame->frame_length; + EXPECT_EQ(4u, consumed); + EXPECT_TRUE(creator_.HasPendingFrames()); EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(&creator_)); } TEST_P(QuicPacketCreatorTest, ConsumeData) { QuicFrame frame; QuicIOVector io_vector(MakeIOVector("test")); - ASSERT_TRUE( - creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame)); + ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame, + MAY_FEC_PROTECT)); ASSERT_TRUE(frame.stream_frame); - size_t consumed = frame.stream_frame->data.length(); + size_t consumed = frame.stream_frame->frame_length; EXPECT_EQ(4u, consumed); CheckStreamFrame(frame, 1u, "test", 0u, false); EXPECT_TRUE(creator_.HasPendingFrames()); @@ -722,10 +760,10 @@ TEST_P(QuicPacketCreatorTest, ConsumeData) { TEST_P(QuicPacketCreatorTest, ConsumeDataFin) { QuicFrame frame; QuicIOVector io_vector(MakeIOVector("test")); - ASSERT_TRUE( - creator_.ConsumeData(1u, io_vector, 0u, 10u, true, false, &frame)); + ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 10u, true, false, &frame, + MAY_FEC_PROTECT)); ASSERT_TRUE(frame.stream_frame); - size_t consumed = frame.stream_frame->data.length(); + size_t consumed = frame.stream_frame->frame_length; EXPECT_EQ(4u, consumed); CheckStreamFrame(frame, 1u, "test", 10u, true); EXPECT_TRUE(creator_.HasPendingFrames()); @@ -734,14 +772,30 @@ TEST_P(QuicPacketCreatorTest, ConsumeDataFin) { TEST_P(QuicPacketCreatorTest, ConsumeDataFinOnly) { QuicFrame frame; QuicIOVector io_vector(nullptr, 0, 0); - ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, true, false, &frame)); + ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, true, false, &frame, + MAY_FEC_PROTECT)); ASSERT_TRUE(frame.stream_frame); - size_t consumed = frame.stream_frame->data.length(); + size_t consumed = frame.stream_frame->frame_length; EXPECT_EQ(0u, consumed); CheckStreamFrame(frame, 1u, string(), 0u, true); EXPECT_TRUE(creator_.HasPendingFrames()); } +TEST_P(QuicPacketCreatorTest, ConsumeDataWithFecProtect) { + creator_.set_max_packets_per_fec_group(6); + QuicFrame frame; + QuicIOVector io_vector(MakeIOVector("test")); + EXPECT_FALSE(QuicPacketCreatorPeer::IsFecProtected(&creator_)); + ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame, + MUST_FEC_PROTECT)); + ASSERT_TRUE(frame.stream_frame); + size_t consumed = frame.stream_frame->frame_length; + EXPECT_EQ(4u, consumed); + CheckStreamFrame(frame, 1u, "test", 0u, false); + EXPECT_TRUE(creator_.HasPendingFrames()); + EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(&creator_)); +} + TEST_P(QuicPacketCreatorTest, CreateAllFreeBytesForStreamFrames) { const size_t overhead = GetPacketHeaderOverhead(NOT_IN_FEC_GROUP) + GetEncryptionOverhead(); @@ -758,9 +812,10 @@ TEST_P(QuicPacketCreatorTest, CreateAllFreeBytesForStreamFrames) { .WillRepeatedly( Invoke(this, &QuicPacketCreatorTest::ClearSerializedPacket)); ASSERT_TRUE(creator_.ConsumeData(kClientDataStreamId1, io_vector, 0u, - kOffset, false, false, &frame)); + kOffset, false, false, &frame, + MAY_FEC_PROTECT)); ASSERT_TRUE(frame.stream_frame); - size_t bytes_consumed = frame.stream_frame->data.length(); + size_t bytes_consumed = frame.stream_frame->frame_length; EXPECT_LT(0u, bytes_consumed); creator_.Flush(); } @@ -798,8 +853,18 @@ TEST_P(QuicPacketCreatorTest, StreamFrameConsumption) { } TEST_P(QuicPacketCreatorTest, StreamFrameConsumptionWithFec) { - // Enable FEC protection, and send FEC packet every 6 packets. - EXPECT_TRUE(SwitchFecProtectionOn(6)); + // Send FEC packet every 6 packets. + creator_.set_max_packets_per_fec_group(6); + // Turn on FEC protection. + QuicFrame frame; + QuicIOVector io_vector(MakeIOVector("test")); + ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame, + MUST_FEC_PROTECT)); + EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(&creator_)); + // Serialize the packet. + EXPECT_CALL(delegate_, OnSerializedPacket(_)) + .WillOnce(Invoke(this, &QuicPacketCreatorTest::ClearSerializedPacket)); + creator_.Flush(); // Compute the total overhead for a single frame in packet. const size_t overhead = GetPacketHeaderOverhead(IN_FEC_GROUP) + GetEncryptionOverhead() + @@ -847,9 +912,9 @@ TEST_P(QuicPacketCreatorTest, CryptoStreamFramePacketPadding) { .WillRepeatedly( Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket)); ASSERT_TRUE(creator_.ConsumeData(kCryptoStreamId, io_vector, 0u, kOffset, - false, true, &frame)); + false, true, &frame, MAY_FEC_PROTECT)); ASSERT_TRUE(frame.stream_frame); - size_t bytes_consumed = frame.stream_frame->data.length(); + size_t bytes_consumed = frame.stream_frame->frame_length; EXPECT_LT(0u, bytes_consumed); creator_.Flush(); ASSERT_TRUE(serialized_packet_.packet); @@ -882,9 +947,10 @@ TEST_P(QuicPacketCreatorTest, NonCryptoStreamFramePacketNonPadding) { EXPECT_CALL(delegate_, OnSerializedPacket(_)) .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket)); ASSERT_TRUE(creator_.ConsumeData(kClientDataStreamId1, io_vector, 0u, - kOffset, false, false, &frame)); + kOffset, false, false, &frame, + MAY_FEC_PROTECT)); ASSERT_TRUE(frame.stream_frame); - size_t bytes_consumed = frame.stream_frame->data.length(); + size_t bytes_consumed = frame.stream_frame->frame_length; EXPECT_LT(0u, bytes_consumed); creator_.Flush(); ASSERT_TRUE(serialized_packet_.packet); @@ -976,9 +1042,7 @@ TEST_P(QuicPacketCreatorTest, SerializeFrame) { } frames_.push_back( QuicFrame(new QuicStreamFrame(0u, false, 0u, StringPiece()))); - char buffer[kMaxPacketSize]; - SerializedPacket serialized = - creator_.SerializeAllFrames(frames_, buffer, kMaxPacketSize); + SerializedPacket serialized = SerializeAllFrames(frames_); delete frames_[0].stream_frame; QuicPacketHeader header; @@ -1015,9 +1079,10 @@ TEST_P(QuicPacketCreatorTest, ConsumeDataLargerThanOneStreamFrame) { QuicIOVector io_vector(MakeIOVector(too_long_payload)); EXPECT_CALL(delegate_, OnSerializedPacket(_)) .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket)); - ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, true, false, &frame)); + ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, true, false, &frame, + MAY_FEC_PROTECT)); ASSERT_TRUE(frame.stream_frame); - size_t consumed = frame.stream_frame->data.length(); + size_t consumed = frame.stream_frame->frame_length; EXPECT_EQ(payload_length, consumed); const string payload(payload_length, 'a'); CheckStreamFrame(frame, 1u, payload, 0u, false); @@ -1047,10 +1112,10 @@ TEST_P(QuicPacketCreatorTest, AddFrameAndFlush) { QuicFrame frame; QuicIOVector io_vector(MakeIOVector("test")); - ASSERT_TRUE( - creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame)); + ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame, + MAY_FEC_PROTECT)); ASSERT_TRUE(frame.stream_frame); - size_t consumed = frame.stream_frame->data.length(); + size_t consumed = frame.stream_frame->frame_length; EXPECT_EQ(4u, consumed); EXPECT_TRUE(creator_.HasPendingFrames()); @@ -1108,10 +1173,10 @@ TEST_P(QuicPacketCreatorTest, SerializeTruncatedAckFrameWithLargePacketSize) { // Make sure that an additional stream frame can be added to the packet. QuicFrame frame; QuicIOVector io_vector(MakeIOVector("test")); - ASSERT_TRUE( - creator_.ConsumeData(2u, io_vector, 0u, 0u, false, false, &frame)); + ASSERT_TRUE(creator_.ConsumeData(2u, io_vector, 0u, 0u, false, false, &frame, + MAY_FEC_PROTECT)); ASSERT_TRUE(frame.stream_frame); - size_t consumed = frame.stream_frame->data.length(); + size_t consumed = frame.stream_frame->frame_length; EXPECT_EQ(4u, consumed); EXPECT_TRUE(creator_.HasPendingFrames()); @@ -1171,11 +1236,9 @@ TEST_P(QuicPacketCreatorTest, EntropyFlag) { frames_.push_back( QuicFrame(new QuicStreamFrame(0u, false, 0u, StringPiece()))); - char buffer[kMaxPacketSize]; for (int i = 0; i < 2; ++i) { for (int j = 0; j < 64; ++j) { - SerializedPacket serialized = - creator_.SerializeAllFrames(frames_, buffer, kMaxPacketSize); + SerializedPacket serialized = SerializeAllFrames(frames_); // Verify both BoolSource and hash algorithm. bool expected_rand_bool = (mock_random_.RandUint64() & (UINT64_C(1) << j)) != 0; @@ -1194,14 +1257,17 @@ TEST_P(QuicPacketCreatorTest, EntropyFlag) { } TEST_P(QuicPacketCreatorTest, ResetFecGroup) { - // Enable FEC protection, and send FEC packet every 6 packets. - EXPECT_TRUE(SwitchFecProtectionOn(6)); - frames_.push_back( - QuicFrame(new QuicStreamFrame(0u, false, 0u, StringPiece()))); - char buffer[kMaxPacketSize]; - SerializedPacket serialized = - creator_.SerializeAllFrames(frames_, buffer, kMaxPacketSize); - delete serialized.packet; + // Send FEC packet every 6 packets. + creator_.set_max_packets_per_fec_group(6); + // Add a stream frame and turn on FEC protection. + QuicFrame frame; + QuicIOVector io_vector(MakeIOVector("test")); + ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame, + MUST_FEC_PROTECT)); + // Serialize the packet. + EXPECT_CALL(delegate_, OnSerializedPacket(_)) + .WillOnce(Invoke(this, &QuicPacketCreatorTest::ClearSerializedPacket)); + creator_.Flush(); EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(&creator_)); EXPECT_TRUE(creator_.IsFecGroupOpen()); @@ -1214,7 +1280,7 @@ TEST_P(QuicPacketCreatorTest, ResetFecGroup) { // not fire. EXPECT_CALL(delegate_, OnResetFecGroup()).Times(1); creator_.set_fec_send_policy(FEC_ALARM_TRIGGER); - creator_.set_should_fec_protect(true); + creator_.set_should_fec_protect_next_packet(true); creator_.MaybeSendFecPacketAndCloseGroup(/*force_send_fec=*/true, /*is_fec_timeout=*/false); EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(&creator_)); @@ -1224,15 +1290,17 @@ TEST_P(QuicPacketCreatorTest, ResetFecGroup) { // Confirm that there is no FEC packet under construction. EXPECT_FALSE(creator_.ShouldSendFec(/*force_close=*/true)); - EXPECT_DFATAL(serialized = QuicPacketCreatorPeer::SerializeFec( - &creator_, buffer, kMaxPacketSize), - "SerializeFEC called but no group or zero packets in group."); - delete serialized.packet; + char buffer[kMaxPacketSize]; + EXPECT_DFATAL( + QuicPacketCreatorPeer::SerializeFec(&creator_, buffer, kMaxPacketSize), + "SerializeFEC called but no group or zero packets in group."); - // Start a new FEC packet. - serialized = creator_.SerializeAllFrames(frames_, buffer, kMaxPacketSize); - delete frames_[0].stream_frame; - delete serialized.packet; + // Create and send a new FEC protected packet. + ASSERT_TRUE(creator_.ConsumeData(2u, io_vector, 0u, 0u, false, false, &frame, + MUST_FEC_PROTECT)); + EXPECT_CALL(delegate_, OnSerializedPacket(_)) + .WillOnce(Invoke(this, &QuicPacketCreatorTest::ClearSerializedPacket)); + creator_.Flush(); EXPECT_TRUE(QuicPacketCreatorPeer::IsFecProtected(&creator_)); EXPECT_TRUE(creator_.IsFecGroupOpen()); @@ -1251,6 +1319,7 @@ TEST_P(QuicPacketCreatorTest, ResetFecGroup) { creator_.set_fec_send_policy(FEC_ANY_TRIGGER); EXPECT_CALL(delegate_, OnSerializedPacket(_)) .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket)); + creator_.set_should_fec_protect_next_packet(false); creator_.MaybeSendFecPacketAndCloseGroup(/*force_send_fec=*/true, /*is_fec_timeout=*/false); ASSERT_EQ(3u, serialized_packet_.packet_number); @@ -1258,15 +1327,15 @@ TEST_P(QuicPacketCreatorTest, ResetFecGroup) { } TEST_P(QuicPacketCreatorTest, ResetFecGroupWithQueuedFrames) { - // Enable FEC protection, and send FEC packet every 6 packets. - EXPECT_TRUE(SwitchFecProtectionOn(6)); - // Add a stream frame to the creator. + // Send FEC packet every 6 packets. + creator_.set_max_packets_per_fec_group(6); + // Add a stream frame to the creator and turn on FEC protection. QuicFrame frame; QuicIOVector io_vector(MakeIOVector("test")); - ASSERT_TRUE( - creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame)); + ASSERT_TRUE(creator_.ConsumeData(1u, io_vector, 0u, 0u, false, false, &frame, + MUST_FEC_PROTECT)); ASSERT_TRUE(frame.stream_frame); - size_t consumed = frame.stream_frame->data.length(); + size_t consumed = frame.stream_frame->frame_length; EXPECT_EQ(4u, consumed); EXPECT_TRUE(creator_.HasPendingFrames()); EXPECT_DFATAL(QuicPacketCreatorPeer::ResetFecGroup(&creator_), @@ -1281,7 +1350,7 @@ TEST_P(QuicPacketCreatorTest, ResetFecGroupWithQueuedFrames) { // not fire. EXPECT_CALL(delegate_, OnResetFecGroup()).Times(1); creator_.set_fec_send_policy(FEC_ALARM_TRIGGER); - creator_.set_should_fec_protect(true); + creator_.set_should_fec_protect_next_packet(true); creator_.MaybeSendFecPacketAndCloseGroup(/*force_send_fec=*/true, /*is_fec_timeout=*/false); EXPECT_FALSE(creator_.IsFecGroupOpen()); diff --git a/net/quic/quic_packet_generator.cc b/net/quic/quic_packet_generator.cc index 6176985..a83c62d 100644 --- a/net/quic/quic_packet_generator.cc +++ b/net/quic/quic_packet_generator.cc @@ -118,11 +118,6 @@ QuicConsumedData QuicPacketGenerator::ConsumeData( packet_creator_.Flush(); } - if (fec_protection == MUST_FEC_PROTECT) { - packet_creator_.set_should_fec_protect(true); - packet_creator_.MaybeStartFecProtection(); - } - if (!fin && (iov.total_length == 0)) { LOG(DFATAL) << "Attempt to consume empty data without FIN."; return QuicConsumedData(0, false); @@ -133,13 +128,13 @@ QuicConsumedData QuicPacketGenerator::ConsumeData( QuicFrame frame; if (!packet_creator_.ConsumeData(id, iov, total_bytes_consumed, offset + total_bytes_consumed, fin, - has_handshake, &frame)) { + has_handshake, &frame, fec_protection)) { // Current packet is full and flushed. continue; } // A stream frame is created and added. - size_t bytes_consumed = frame.stream_frame->data.length(); + size_t bytes_consumed = frame.stream_frame->frame_length; if (debug_delegate_ != nullptr) { debug_delegate_->OnFrameAddedToPacket(frame); } @@ -167,7 +162,7 @@ QuicConsumedData QuicPacketGenerator::ConsumeData( if (fec_protection == MUST_FEC_PROTECT) { // Turn off FEC protection when we're done writing protected data. DVLOG(1) << "Turning FEC protection OFF"; - packet_creator_.set_should_fec_protect(false); + packet_creator_.set_should_fec_protect_next_packet(false); } break; } @@ -364,11 +359,12 @@ QuicEncryptedPacket* QuicPacketGenerator::SerializeVersionNegotiationPacket( SerializedPacket QuicPacketGenerator::ReserializeAllFrames( const RetransmittableFrames& frames, + EncryptionLevel original_encryption_level, QuicPacketNumberLength original_length, char* buffer, size_t buffer_len) { - return packet_creator_.ReserializeAllFrames(frames, original_length, buffer, - buffer_len); + return packet_creator_.ReserializeAllFrames( + frames, original_encryption_level, original_length, buffer, buffer_len); } void QuicPacketGenerator::UpdateSequenceNumberLength( @@ -404,7 +400,7 @@ void QuicPacketGenerator::OnSerializedPacket( if (serialized_packet->packet == nullptr) { LOG(DFATAL) << "Failed to SerializePacket. fec_policy:" << fec_send_policy() << " should_fec_protect_:" - << packet_creator_.should_fec_protect(); + << packet_creator_.should_fec_protect_next_packet(); delegate_->CloseConnection(QUIC_FAILED_TO_SERIALIZE_PACKET, false); return; } diff --git a/net/quic/quic_packet_generator.h b/net/quic/quic_packet_generator.h index 4eef5d1..d217609 100644 --- a/net/quic/quic_packet_generator.h +++ b/net/quic/quic_packet_generator.h @@ -158,10 +158,12 @@ class NET_EXPORT_PRIVATE QuicPacketGenerator // Used for retransmitting packets to ensure they aren't too long. // Caller must ensure that any open FEC group is closed before calling this // method. - SerializedPacket ReserializeAllFrames(const RetransmittableFrames& frames, - QuicPacketNumberLength original_length, - char* buffer, - size_t buffer_len); + SerializedPacket ReserializeAllFrames( + const RetransmittableFrames& frames, + EncryptionLevel original_encryption_level, + QuicPacketNumberLength original_length, + char* buffer, + size_t buffer_len); // Update the packet number length to use in future packets as soon as it // can be safely changed. diff --git a/net/quic/quic_protocol.cc b/net/quic/quic_protocol.cc index 2bca0b7..19349fa 100644 --- a/net/quic/quic_protocol.cc +++ b/net/quic/quic_protocol.cc @@ -107,26 +107,56 @@ UniqueStreamBuffer NewStreamBuffer(size_t size) { return UniqueStreamBuffer(new char[size]); } -QuicStreamFrame::QuicStreamFrame() : stream_id(0), fin(false), offset(0) { -} +QuicStreamFrame::QuicStreamFrame() + : stream_id(0), + fin(false), + frame_length(0), + frame_buffer(nullptr), + offset(0), + buffer(nullptr) {} QuicStreamFrame::QuicStreamFrame(QuicStreamId stream_id, bool fin, QuicStreamOffset offset, StringPiece data) - : stream_id(stream_id), fin(fin), offset(offset), data(data) { + : QuicStreamFrame(stream_id, + fin, + offset, + data.data(), + data.length(), + nullptr) {} + +QuicStreamFrame::QuicStreamFrame(QuicStreamId stream_id, + bool fin, + QuicStreamOffset offset, + QuicPacketLength frame_length, + UniqueStreamBuffer buffer) + : QuicStreamFrame(stream_id, + fin, + offset, + nullptr, + frame_length, + std::move(buffer)) { + DCHECK(this->buffer != nullptr); + DCHECK_EQ(frame_buffer, this->buffer.get()); } QuicStreamFrame::QuicStreamFrame(QuicStreamId stream_id, bool fin, QuicStreamOffset offset, - StringPiece data, + const char* frame_buffer, + QuicPacketLength frame_length, UniqueStreamBuffer buffer) : stream_id(stream_id), fin(fin), + frame_length(frame_length), + frame_buffer(frame_buffer), offset(offset), - data(data), - buffer(std::move(buffer)) {} + buffer(std::move(buffer)) { + if (this->buffer != nullptr) { + this->frame_buffer = this->buffer.get(); + } +} QuicStreamFrame::~QuicStreamFrame() {} @@ -597,8 +627,7 @@ ostream& operator<<(ostream& os, const QuicStreamFrame& stream_frame) { os << "stream_id { " << stream_frame.stream_id << " } " << "fin { " << stream_frame.fin << " } " << "offset { " << stream_frame.offset << " } " - << "data { " << QuicUtils::StringToHexASCIIDump(stream_frame.data) - << " }\n"; + << "length { " << stream_frame.frame_length << " }\n"; return os; } @@ -695,10 +724,8 @@ StringPiece QuicPacket::Plaintext() const { length() - start_of_encrypted_data); } -RetransmittableFrames::RetransmittableFrames(EncryptionLevel level) - : encryption_level_(level), - has_crypto_handshake_(NOT_HANDSHAKE), - needs_padding_(false) { +RetransmittableFrames::RetransmittableFrames() + : has_crypto_handshake_(NOT_HANDSHAKE), needs_padding_(false) { // TODO(ianswett): Consider using an inlined vector instead, since this // is very frequently a single frame. frames_.reserve(2); @@ -783,6 +810,7 @@ SerializedPacket::SerializedPacket( retransmittable_frames(retransmittable_frames), packet_number(packet_number), packet_number_length(packet_number_length), + encryption_level(ENCRYPTION_NONE), entropy_hash(entropy_hash), is_fec_packet(false), has_ack(has_ack), @@ -797,7 +825,8 @@ SerializedPacket::SerializedPacket( QuicPacketEntropyHash entropy_hash, RetransmittableFrames* retransmittable_frames, bool has_ack, - bool has_stop_waiting) + bool has_stop_waiting, + EncryptionLevel level) : SerializedPacket(packet_number, packet_number_length, new QuicEncryptedPacket(encrypted_buffer, @@ -806,7 +835,11 @@ SerializedPacket::SerializedPacket( entropy_hash, retransmittable_frames, has_ack, - has_stop_waiting) {} + has_stop_waiting) { + // TODO(ianswett): Move into the initializer list once SerializedPacket + // no longer contains an encrypted packet. + encryption_level = level; +} SerializedPacket::~SerializedPacket() {} @@ -823,6 +856,7 @@ ostream& operator<<(ostream& os, const QuicEncryptedPacket& s) { TransmissionInfo::TransmissionInfo() : retransmittable_frames(nullptr), + encryption_level(ENCRYPTION_NONE), packet_number_length(PACKET_1BYTE_PACKET_NUMBER), bytes_sent(0), nack_count(0), @@ -836,12 +870,14 @@ TransmissionInfo::TransmissionInfo() TransmissionInfo::TransmissionInfo( RetransmittableFrames* retransmittable_frames, + EncryptionLevel level, QuicPacketNumberLength packet_number_length, TransmissionType transmission_type, QuicTime sent_time, QuicPacketLength bytes_sent, bool is_fec_packet) : retransmittable_frames(retransmittable_frames), + encryption_level(level), packet_number_length(packet_number_length), bytes_sent(bytes_sent), nack_count(0), diff --git a/net/quic/quic_protocol.h b/net/quic/quic_protocol.h index ff35074..d817599 100644 --- a/net/quic/quic_protocol.h +++ b/net/quic/quic_protocol.h @@ -728,7 +728,7 @@ struct NET_EXPORT_PRIVATE QuicStreamFrame { QuicStreamFrame(QuicStreamId stream_id, bool fin, QuicStreamOffset offset, - base::StringPiece data, + QuicPacketLength frame_length, UniqueStreamBuffer buffer); ~QuicStreamFrame(); @@ -737,12 +737,20 @@ struct NET_EXPORT_PRIVATE QuicStreamFrame { QuicStreamId stream_id; bool fin; + QuicPacketLength frame_length; + const char* frame_buffer; QuicStreamOffset offset; // Location of this data in the stream. - base::StringPiece data; // nullptr when the QuicStreamFrame is received, and non-null when sent. UniqueStreamBuffer buffer; private: + QuicStreamFrame(QuicStreamId stream_id, + bool fin, + QuicStreamOffset offset, + const char* frame_buffer, + QuicPacketLength frame_length, + UniqueStreamBuffer buffer); + DISALLOW_COPY_AND_ASSIGN(QuicStreamFrame); }; static_assert(sizeof(QuicStreamFrame) <= 64, @@ -1141,7 +1149,7 @@ class NET_EXPORT_PRIVATE QuicEncryptedPacket : public QuicData { class NET_EXPORT_PRIVATE RetransmittableFrames { public: - explicit RetransmittableFrames(EncryptionLevel level); + RetransmittableFrames(); ~RetransmittableFrames(); // Takes ownership of the frame inside |frame|. @@ -1155,17 +1163,12 @@ class NET_EXPORT_PRIVATE RetransmittableFrames { return has_crypto_handshake_; } - EncryptionLevel encryption_level() const { - return encryption_level_; - } - bool needs_padding() const { return needs_padding_; } void set_needs_padding(bool needs_padding) { needs_padding_ = needs_padding; } private: QuicFrames frames_; - const EncryptionLevel encryption_level_; IsHandshake has_crypto_handshake_; bool needs_padding_; @@ -1197,13 +1200,15 @@ struct NET_EXPORT_PRIVATE SerializedPacket { QuicPacketEntropyHash entropy_hash, RetransmittableFrames* retransmittable_frames, bool has_ack, - bool has_stop_waiting); + bool has_stop_waiting, + EncryptionLevel level); ~SerializedPacket(); QuicEncryptedPacket* packet; RetransmittableFrames* retransmittable_frames; QuicPacketNumber packet_number; QuicPacketNumberLength packet_number_length; + EncryptionLevel encryption_level; QuicPacketEntropyHash entropy_hash; bool is_fec_packet; bool has_ack; @@ -1220,6 +1225,7 @@ struct NET_EXPORT_PRIVATE TransmissionInfo { // Constructs a Transmission with a new all_tranmissions set // containing |packet_number|. TransmissionInfo(RetransmittableFrames* retransmittable_frames, + EncryptionLevel level, QuicPacketNumberLength packet_number_length, TransmissionType transmission_type, QuicTime sent_time, @@ -1229,6 +1235,7 @@ struct NET_EXPORT_PRIVATE TransmissionInfo { ~TransmissionInfo(); RetransmittableFrames* retransmittable_frames; + EncryptionLevel encryption_level; QuicPacketNumberLength packet_number_length; QuicPacketLength bytes_sent; uint16 nack_count; diff --git a/net/quic/quic_sent_packet_manager.cc b/net/quic/quic_sent_packet_manager.cc index 25d72e7..a3176cc 100644 --- a/net/quic/quic_sent_packet_manager.cc +++ b/net/quic/quic_sent_packet_manager.cc @@ -347,7 +347,7 @@ void QuicSentPacketManager::RetransmitUnackedPackets( const RetransmittableFrames* frames = it->retransmittable_frames; if (frames != nullptr && (retransmission_type == ALL_UNACKED_RETRANSMISSION || - frames->encryption_level() == ENCRYPTION_INITIAL)) { + it->encryption_level == ENCRYPTION_INITIAL)) { MarkForRetransmission(packet_number, retransmission_type); } else if (it->is_fec_packet) { // Remove FEC packets from the packet map, since we can't retransmit them. @@ -360,8 +360,8 @@ void QuicSentPacketManager::NeuterUnencryptedPackets() { QuicPacketNumber packet_number = unacked_packets_.GetLeastUnacked(); for (QuicUnackedPacketMap::const_iterator it = unacked_packets_.begin(); it != unacked_packets_.end(); ++it, ++packet_number) { - const RetransmittableFrames* frames = it->retransmittable_frames; - if (frames != nullptr && frames->encryption_level() == ENCRYPTION_NONE) { + if (it->retransmittable_frames != nullptr && + it->encryption_level == ENCRYPTION_NONE) { // Once you're forward secure, no unencrypted packets will be sent, crypto // or otherwise. Unencrypted packets are neutered and abandoned, to ensure // they are not retransmitted or considered lost from a congestion control @@ -465,6 +465,7 @@ QuicSentPacketManager::PendingRetransmission return PendingRetransmission(packet_number, transmission_type, *transmission_info.retransmittable_frames, + transmission_info.encryption_level, transmission_info.packet_number_length); } diff --git a/net/quic/quic_sent_packet_manager.h b/net/quic/quic_sent_packet_manager.h index 2b0d095..f0d990f 100644 --- a/net/quic/quic_sent_packet_manager.h +++ b/net/quic/quic_sent_packet_manager.h @@ -77,15 +77,18 @@ class NET_EXPORT_PRIVATE QuicSentPacketManager { PendingRetransmission(QuicPacketNumber packet_number, TransmissionType transmission_type, const RetransmittableFrames& retransmittable_frames, + EncryptionLevel encryption_level, QuicPacketNumberLength packet_number_length) : packet_number(packet_number), transmission_type(transmission_type), retransmittable_frames(retransmittable_frames), + encryption_level(encryption_level), packet_number_length(packet_number_length) {} QuicPacketNumber packet_number; TransmissionType transmission_type; const RetransmittableFrames& retransmittable_frames; + EncryptionLevel encryption_level; QuicPacketNumberLength packet_number_length; }; diff --git a/net/quic/quic_sent_packet_manager_test.cc b/net/quic/quic_sent_packet_manager_test.cc index 8052767..40adefa 100644 --- a/net/quic/quic_sent_packet_manager_test.cc +++ b/net/quic/quic_sent_packet_manager_test.cc @@ -185,7 +185,7 @@ class QuicSentPacketManagerTest : public ::testing::TestWithParam<bool> { packets_.push_back(new QuicEncryptedPacket(nullptr, kDefaultLength)); RetransmittableFrames* frames = nullptr; if (retransmittable) { - frames = new RetransmittableFrames(ENCRYPTION_NONE); + frames = new RetransmittableFrames(); frames->AddFrame( QuicFrame(new QuicStreamFrame(kStreamId, false, 0, StringPiece()))); } diff --git a/net/quic/quic_session.cc b/net/quic/quic_session.cc index ca11f6b..609b347 100644 --- a/net/quic/quic_session.cc +++ b/net/quic/quic_session.cc @@ -142,7 +142,7 @@ void QuicSession::OnStreamFrame(const QuicStreamFrame& frame) { // final stream byte offset sent by the peer. A frame with a FIN can give // us this offset. if (frame.fin) { - QuicStreamOffset final_byte_offset = frame.offset + frame.data.size(); + QuicStreamOffset final_byte_offset = frame.offset + frame.frame_length; UpdateFlowControlOnFinalReceivedByteOffset(stream_id, final_byte_offset); } return; diff --git a/net/quic/quic_spdy_stream.h b/net/quic/quic_spdy_stream.h index e55d6aa..81673f7 100644 --- a/net/quic/quic_spdy_stream.h +++ b/net/quic/quic_spdy_stream.h @@ -77,7 +77,7 @@ class NET_EXPORT_PRIVATE QuicSpdyStream : public ReliableQuicStream { virtual void OnStreamHeadersPriority(SpdyPriority priority); // Called by the session when decompressed headers have been completely - // delilvered to this stream. If |fin| is true, then this stream + // delivered to this stream. If |fin| is true, then this stream // should be closed; no more data will be sent by the peer. virtual void OnStreamHeadersComplete(bool fin, size_t frame_len); diff --git a/net/quic/quic_stream_sequencer.cc b/net/quic/quic_stream_sequencer.cc index 34c0d25..cfa8481 100644 --- a/net/quic/quic_stream_sequencer.cc +++ b/net/quic/quic_stream_sequencer.cc @@ -46,7 +46,7 @@ QuicStreamSequencer::~QuicStreamSequencer() {} void QuicStreamSequencer::OnStreamFrame(const QuicStreamFrame& frame) { ++num_frames_received_; const QuicStreamOffset byte_offset = frame.offset; - const size_t data_len = frame.data.length(); + const size_t data_len = frame.frame_length; if (data_len == 0 && !frame.fin) { // Stream frames must have data or a fin flag. stream_->CloseConnectionWithDetails(QUIC_INVALID_STREAM_FRAME, @@ -62,7 +62,8 @@ void QuicStreamSequencer::OnStreamFrame(const QuicStreamFrame& frame) { } size_t bytes_written; QuicErrorCode result = buffered_frames_->OnStreamData( - byte_offset, frame.data, clock_->ApproximateNow(), &bytes_written); + byte_offset, StringPiece(frame.frame_buffer, frame.frame_length), + clock_->ApproximateNow(), &bytes_written); if (result == QUIC_INVALID_STREAM_DATA) { stream_->CloseConnectionWithDetails( diff --git a/net/quic/quic_stream_sequencer_test.cc b/net/quic/quic_stream_sequencer_test.cc index 83233dc..d2b2b61 100644 --- a/net/quic/quic_stream_sequencer_test.cc +++ b/net/quic/quic_stream_sequencer_test.cc @@ -145,7 +145,8 @@ class QuicStreamSequencerTest : public ::testing::TestWithParam<bool> { QuicStreamFrame frame; frame.stream_id = 1; frame.offset = byte_offset; - frame.data = StringPiece(data); + frame.frame_buffer = data; + frame.frame_length = strlen(data); frame.fin = true; sequencer_->OnStreamFrame(frame); } @@ -154,7 +155,8 @@ class QuicStreamSequencerTest : public ::testing::TestWithParam<bool> { QuicStreamFrame frame; frame.stream_id = 1; frame.offset = byte_offset; - frame.data = StringPiece(data); + frame.frame_buffer = data; + frame.frame_length = strlen(data); frame.fin = false; sequencer_->OnStreamFrame(frame); } diff --git a/net/quic/quic_unacked_packet_map.cc b/net/quic/quic_unacked_packet_map.cc index a9a9e89..be3e8ee 100644 --- a/net/quic/quic_unacked_packet_map.cc +++ b/net/quic/quic_unacked_packet_map.cc @@ -50,8 +50,9 @@ void QuicUnackedPacketMap::AddSentPacket(SerializedPacket* packet, } TransmissionInfo info(packet->retransmittable_frames, - packet->packet_number_length, transmission_type, - sent_time, bytes_sent, packet->is_fec_packet); + packet->encryption_level, packet->packet_number_length, + transmission_type, sent_time, bytes_sent, + packet->is_fec_packet); if (old_packet_number > 0) { TransferRetransmissionInfo(old_packet_number, packet_number, transmission_type, &info); diff --git a/net/quic/quic_unacked_packet_map_test.cc b/net/quic/quic_unacked_packet_map_test.cc index 1e302e3..adbca84 100644 --- a/net/quic/quic_unacked_packet_map_test.cc +++ b/net/quic/quic_unacked_packet_map_test.cc @@ -33,16 +33,16 @@ class QuicUnackedPacketMapTest : public ::testing::Test { SerializedPacket CreateRetransmittablePacket(QuicPacketNumber packet_number) { packets_.push_back(new QuicEncryptedPacket(nullptr, kDefaultLength)); - return SerializedPacket( - packet_number, PACKET_1BYTE_PACKET_NUMBER, packets_.back(), 0, - new RetransmittableFrames(ENCRYPTION_NONE), false, false); + return SerializedPacket(packet_number, PACKET_1BYTE_PACKET_NUMBER, + packets_.back(), 0, new RetransmittableFrames(), + false, false); } SerializedPacket CreateRetransmittablePacketForStream( QuicPacketNumber packet_number, QuicStreamId stream_id) { packets_.push_back(new QuicEncryptedPacket(nullptr, kDefaultLength)); - RetransmittableFrames* frames = new RetransmittableFrames(ENCRYPTION_NONE); + RetransmittableFrames* frames = new RetransmittableFrames(); QuicStreamFrame* frame = new QuicStreamFrame(); frame->stream_id = stream_id; frames->AddFrame(QuicFrame(frame)); diff --git a/net/quic/reliable_quic_stream.cc b/net/quic/reliable_quic_stream.cc index daf0915..2682d5b 100644 --- a/net/quic/reliable_quic_stream.cc +++ b/net/quic/reliable_quic_stream.cc @@ -52,7 +52,8 @@ ReliableQuicStream::PendingData::~PendingData() { } ReliableQuicStream::ReliableQuicStream(QuicStreamId id, QuicSession* session) - : sequencer_(this, session->connection()->clock()), + : queued_data_bytes_(0), + sequencer_(this, session->connection()->clock()), id_(id), session_(session), stream_bytes_read_(0), @@ -105,7 +106,7 @@ void ReliableQuicStream::OnStreamFrame(const QuicStreamFrame& frame) { } // This count includes duplicate data received. - size_t frame_payload_size = frame.data.size(); + size_t frame_payload_size = frame.frame_length; stream_bytes_read_ += frame_payload_size; // Flow control is interested in tracking highest received offset. @@ -216,6 +217,7 @@ void ReliableQuicStream::WriteOrBufferData( if (consumed_data.bytes_consumed < data.length() || (fin && !consumed_data.fin_consumed)) { StringPiece remainder(data.substr(consumed_data.bytes_consumed)); + queued_data_bytes_ += remainder.size(); queued_data_.push_back(PendingData(remainder.as_string(), ack_listener)); } } @@ -242,6 +244,7 @@ void ReliableQuicStream::OnCanWrite() { const_cast<char*>(pending_data->data.data()) + pending_data->offset, remaining_len}; QuicConsumedData consumed_data = WritevData(&iov, 1, fin, ack_listener); + queued_data_bytes_ -= consumed_data.bytes_consumed; if (consumed_data.bytes_consumed == remaining_len && fin == consumed_data.fin_consumed) { queued_data_.pop_front(); diff --git a/net/quic/reliable_quic_stream.h b/net/quic/reliable_quic_stream.h index 096770c..3ea970b 100644 --- a/net/quic/reliable_quic_stream.h +++ b/net/quic/reliable_quic_stream.h @@ -113,6 +113,8 @@ class NET_EXPORT_PRIVATE ReliableQuicStream { bool fin_received() { return fin_received_; } bool fin_sent() { return fin_sent_; } + uint64 queued_data_bytes() const { return queued_data_bytes_; } + uint64 stream_bytes_read() const { return stream_bytes_read_; } uint64 stream_bytes_written() const { return stream_bytes_written_; } @@ -246,6 +248,8 @@ class NET_EXPORT_PRIVATE ReliableQuicStream { void MaybeSendBlocked(); std::list<PendingData> queued_data_; + // How many bytes are queued? + uint64 queued_data_bytes_; QuicStreamSequencer sequencer_; QuicStreamId id_; diff --git a/net/quic/reliable_quic_stream_test.cc b/net/quic/reliable_quic_stream_test.cc index 0fca992..7ef0def 100644 --- a/net/quic/reliable_quic_stream_test.cc +++ b/net/quic/reliable_quic_stream_test.cc @@ -195,6 +195,7 @@ TEST_F(ReliableQuicStreamTest, BlockIfOnlySomeDataConsumed) { .WillOnce(Return(QuicConsumedData(1, false))); stream_->WriteOrBufferData(StringPiece(kData1, 2), false, nullptr); ASSERT_EQ(1u, write_blocked_list_->NumBlockedStreams()); + EXPECT_EQ(1u, stream_->queued_data_bytes()); } TEST_F(ReliableQuicStreamTest, BlockIfFinNotConsumedWithData) { @@ -724,16 +725,6 @@ TEST_F(ReliableQuicStreamTest, FecSendPolicyReceivedConnectionOption) { EXPECT_EQ(FEC_PROTECT_ALWAYS, stream_->fec_policy()); } -static QuicConsumedData ConsumeAllData( - QuicStreamId id, - const QuicIOVector& data, - QuicStreamOffset offset, - bool fin, - FecProtection fec_protection, - QuicAckListenerInterface* ack_notifier_delegate) { - return QuicConsumedData(data.total_length, fin); -} - TEST_F(ReliableQuicStreamTest, EarlyResponseFinHandling) { // Verify that if the server completes the response before reading the end of // the request, the received FIN is recorded. @@ -741,7 +732,7 @@ TEST_F(ReliableQuicStreamTest, EarlyResponseFinHandling) { Initialize(kShouldProcessData); EXPECT_CALL(*connection_, SendConnectionClose(_)).Times(0); EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)) - .WillRepeatedly(Invoke(ConsumeAllData)); + .WillRepeatedly(Invoke(MockQuicSpdySession::ConsumeAllData)); // Receive data for the request. QuicStreamFrame frame1(stream_->id(), false, 0, StringPiece("Start")); diff --git a/net/quic/spdy_utils.cc b/net/quic/spdy_utils.cc index d66c200..6cfdc1e 100644 --- a/net/quic/spdy_utils.cc +++ b/net/quic/spdy_utils.cc @@ -4,12 +4,18 @@ #include "net/quic/spdy_utils.h" +#include <vector> + #include "base/memory/scoped_ptr.h" +#include "base/stl_util.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_split.h" #include "net/spdy/spdy_frame_builder.h" #include "net/spdy/spdy_framer.h" #include "net/spdy/spdy_protocol.h" using std::string; +using std::vector; namespace net { @@ -24,4 +30,79 @@ string SpdyUtils::SerializeUncompressedHeaders(const SpdyHeaderBlock& headers) { return string(block->data(), length); } +// static +bool SpdyUtils::ParseHeaders(const char* data, + uint32 data_len, + int* content_length, + SpdyHeaderBlock* headers) { + SpdyFramer framer(HTTP2); + if (!framer.ParseHeaderBlockInBuffer(data, data_len, headers) || + headers->empty()) { + return false; // Headers were invalid. + } + + if (ContainsKey(*headers, "content-length")) { + // Check whether multiple values are consistent. + base::StringPiece content_length_header = (*headers)["content-length"]; + vector<string> values = + base::SplitString(content_length_header, base::StringPiece("\0", 1), + base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); + for (const string& value : values) { + int new_value; + if (!base::StringToInt(value, &new_value) || new_value < 0) { + return false; + } + if (*content_length < 0) { + *content_length = new_value; + continue; + } + if (new_value != *content_length) { + return false; + } + } + } + + return true; +} + +// static +bool SpdyUtils::ParseTrailers(const char* data, + uint32 data_len, + size_t* final_byte_offset, + SpdyHeaderBlock* trailers) { + SpdyFramer framer(HTTP2); + if (!framer.ParseHeaderBlockInBuffer(data, data_len, trailers) || + trailers->empty()) { + DVLOG(1) << "Request Trailers are invalid."; + return false; // Trailers were invalid. + } + + // Pull out the :final-offset pseudo header which indicates the number of + // response body bytes expected. + auto it = trailers->find(":final-offset"); + if (it == trailers->end() || + !base::StringToSizeT(it->second, final_byte_offset)) { + DVLOG(1) << ":final-offset not present"; + return false; // :final-offset key must be present. + } + // :final-offset header is no longer used. + trailers->erase(it->first); + + // Trailers must not have empty keys, and must not contain pseudo headers. + for (const auto& trailer : *trailers) { + base::StringPiece key = trailer.first; + base::StringPiece value = trailer.second; + if (key.starts_with(":")) { + DVLOG(1) << "Trailers must not contain pseudo-header: '" << key << "','" + << value << "'."; + return false; + } + + // TODO(rjshade): Check for other forbidden keys, following the HTTP/2 spec. + } + + DVLOG(1) << "Successfully parsed Trailers."; + return true; +} + } // namespace net diff --git a/net/quic/spdy_utils.h b/net/quic/spdy_utils.h index 28b48db..76b667d 100644 --- a/net/quic/spdy_utils.h +++ b/net/quic/spdy_utils.h @@ -5,6 +5,7 @@ #ifndef NET_QUIC_SPDY_UTILS_H_ #define NET_QUIC_SPDY_UTILS_H_ +#include <map> #include <string> #include "net/base/net_export.h" @@ -18,6 +19,26 @@ class NET_EXPORT_PRIVATE SpdyUtils { static std::string SerializeUncompressedHeaders( const SpdyHeaderBlock& headers); + // Parses |data| as a std::string containing serialized HTTP/2 HEADERS frame, + // populating |headers| with the key->value std:pairs found. + // |content_length| will be populated with the value of the content-length + // header if one or more are present. + // Returns true on success, false if parsing fails, or invalid keys are found. + static bool ParseHeaders(const char* data, + uint32 data_len, + int* content_length, + SpdyHeaderBlock* headers); + + // Parses |data| as a std::string containing serialized HTTP/2 HEADERS frame, + // populating |trailers| with the key->value std:pairs found. + // The :final-offset header will be excluded from |trailers|, and instead the + // value will be copied to |final_byte_offset|. + // Returns true on success, false if parsing fails, or invalid keys are found. + static bool ParseTrailers(const char* data, + uint32 data_len, + size_t* final_byte_offset, + SpdyHeaderBlock* trailers); + private: DISALLOW_COPY_AND_ASSIGN(SpdyUtils); }; diff --git a/net/quic/test_tools/crypto_test_utils.cc b/net/quic/test_tools/crypto_test_utils.cc index ed34502..5f3b728 100644 --- a/net/quic/test_tools/crypto_test_utils.cc +++ b/net/quic/test_tools/crypto_test_utils.cc @@ -635,7 +635,8 @@ void CryptoTestUtils::MovePackets(PacketSavingConnection* source_conn, } for (const QuicStreamFrame* stream_frame : framer.stream_frames()) { - ASSERT_TRUE(crypto_framer.ProcessInput(stream_frame->data)); + ASSERT_TRUE(crypto_framer.ProcessInput( + StringPiece(stream_frame->frame_buffer, stream_frame->frame_length))); ASSERT_FALSE(crypto_visitor.error()); } } diff --git a/net/quic/test_tools/quic_stream_sequencer_peer.cc b/net/quic/test_tools/quic_stream_sequencer_peer.cc index fea4579..290e2ea 100644 --- a/net/quic/test_tools/quic_stream_sequencer_peer.cc +++ b/net/quic/test_tools/quic_stream_sequencer_peer.cc @@ -23,8 +23,8 @@ bool QuicStreamSequencerPeer::FrameOverlapsBufferedData( QuicFrameList* buffer, const QuicStreamFrame& frame) { list<QuicFrameList::FrameData>::iterator it = - buffer->FindInsertionPoint(frame.offset, frame.data.length()); - return buffer->FrameOverlapsBufferedData(frame.offset, frame.data.length(), + buffer->FindInsertionPoint(frame.offset, frame.frame_length); + return buffer->FrameOverlapsBufferedData(frame.offset, frame.frame_length, it); } diff --git a/net/quic/test_tools/quic_test_utils.cc b/net/quic/test_tools/quic_test_utils.cc index f46419b..7bb892f 100644 --- a/net/quic/test_tools/quic_test_utils.cc +++ b/net/quic/test_tools/quic_test_utils.cc @@ -325,6 +325,17 @@ MockQuicSpdySession::MockQuicSpdySession(QuicConnection* connection) MockQuicSpdySession::~MockQuicSpdySession() {} +// static +QuicConsumedData MockQuicSpdySession::ConsumeAllData( + QuicStreamId /*id*/, + const QuicIOVector& data, + QuicStreamOffset /*offset*/, + bool fin, + FecProtection /*fec_protection*/, + QuicAckListenerInterface* /*ack_notifier_delegate*/) { + return QuicConsumedData(data.total_length, fin); +} + TestQuicSpdyServerSession::TestQuicSpdyServerSession( QuicConnection* connection, const QuicConfig& config, diff --git a/net/quic/test_tools/quic_test_utils.h b/net/quic/test_tools/quic_test_utils.h index d78916a..443f25e 100644 --- a/net/quic/test_tools/quic_test_utils.h +++ b/net/quic/test_tools/quic_test_utils.h @@ -454,6 +454,16 @@ class MockQuicSpdySession : public QuicSpdySession { using QuicSession::ActivateStream; + // Returns a QuicConsumedData that indicates all of |data| (and |fin| if set) + // has been consumed. + static QuicConsumedData ConsumeAllData( + QuicStreamId id, + const QuicIOVector& data, + QuicStreamOffset offset, + bool fin, + FecProtection fec_protection, + QuicAckListenerInterface* ack_notifier_delegate); + private: scoped_ptr<QuicCryptoStream> crypto_stream_; @@ -693,10 +703,9 @@ class MockQuicConnectionDebugVisitor : public QuicConnectionDebugVisitor { MOCK_METHOD1(OnFrameAddedToPacket, void(const QuicFrame&)); - MOCK_METHOD6(OnPacketSent, + MOCK_METHOD5(OnPacketSent, void(const SerializedPacket&, QuicPacketNumber, - EncryptionLevel, TransmissionType, size_t encrypted_length, QuicTime)); @@ -712,6 +721,8 @@ class MockQuicConnectionDebugVisitor : public QuicConnectionDebugVisitor { MOCK_METHOD1(OnPacketHeader, void(const QuicPacketHeader& header)); + MOCK_METHOD1(OnSuccessfulVersionNegotiation, void(const QuicVersion&)); + MOCK_METHOD1(OnStreamFrame, void(const QuicStreamFrame&)); MOCK_METHOD1(OnAckFrame, void(const QuicAckFrame& frame)); diff --git a/net/quic/test_tools/simple_quic_framer.cc b/net/quic/test_tools/simple_quic_framer.cc index 60e393b..a8ce332 100644 --- a/net/quic/test_tools/simple_quic_framer.cc +++ b/net/quic/test_tools/simple_quic_framer.cc @@ -60,7 +60,8 @@ class SimpleFramerVisitor : public QuicFramerVisitorInterface { bool OnStreamFrame(const QuicStreamFrame& frame) override { // Save a copy of the data so it is valid after the packet is processed. string* string_data = new string(); - frame.data.AppendToString(string_data); + StringPiece(frame.frame_buffer, frame.frame_length) + .AppendToString(string_data); stream_data_.push_back(string_data); // TODO(ianswett): A pointer isn't necessary with emplace_back. stream_frames_.push_back(new QuicStreamFrame( diff --git a/net/tools/quic/quic_in_memory_cache.cc b/net/tools/quic/quic_in_memory_cache.cc index 0671099..fd77050 100644 --- a/net/tools/quic/quic_in_memory_cache.cc +++ b/net/tools/quic/quic_in_memory_cache.cc @@ -85,14 +85,24 @@ void QuicInMemoryCache::AddResponse(StringPiece host, StringPiece path, const SpdyHeaderBlock& response_headers, StringPiece response_body) { - AddResponseImpl(host, path, REGULAR_RESPONSE, response_headers, - response_body); + AddResponseImpl(host, path, REGULAR_RESPONSE, response_headers, response_body, + SpdyHeaderBlock()); +} + +void QuicInMemoryCache::AddResponse(StringPiece host, + StringPiece path, + const SpdyHeaderBlock& response_headers, + StringPiece response_body, + const SpdyHeaderBlock& response_trailers) { + AddResponseImpl(host, path, REGULAR_RESPONSE, response_headers, response_body, + response_trailers); } void QuicInMemoryCache::AddSpecialResponse(StringPiece host, StringPiece path, SpecialResponseType response_type) { - AddResponseImpl(host, path, response_type, SpdyHeaderBlock(), ""); + AddResponseImpl(host, path, response_type, SpdyHeaderBlock(), "", + SpdyHeaderBlock()); } QuicInMemoryCache::QuicInMemoryCache() {} @@ -187,11 +197,13 @@ QuicInMemoryCache::~QuicInMemoryCache() { STLDeleteValues(&responses_); } -void QuicInMemoryCache::AddResponseImpl(StringPiece host, - StringPiece path, - SpecialResponseType response_type, - const SpdyHeaderBlock& response_headers, - StringPiece response_body) { +void QuicInMemoryCache::AddResponseImpl( + StringPiece host, + StringPiece path, + SpecialResponseType response_type, + const SpdyHeaderBlock& response_headers, + StringPiece response_body, + const SpdyHeaderBlock& response_trailers) { string key = GetKey(host, path); if (ContainsKey(responses_, key)) { LOG(DFATAL) << "Response for '" << key << "' already exists!"; @@ -201,6 +213,7 @@ void QuicInMemoryCache::AddResponseImpl(StringPiece host, new_response->set_response_type(response_type); new_response->set_headers(response_headers); new_response->set_body(response_body); + new_response->set_trailers(response_trailers); responses_[key] = new_response; } diff --git a/net/tools/quic/quic_in_memory_cache.h b/net/tools/quic/quic_in_memory_cache.h index 5ceaf52..f6ef75b 100644 --- a/net/tools/quic/quic_in_memory_cache.h +++ b/net/tools/quic/quic_in_memory_cache.h @@ -66,6 +66,7 @@ class QuicInMemoryCache { SpecialResponseType response_type() const { return response_type_; } const SpdyHeaderBlock& headers() const { return headers_; } + const SpdyHeaderBlock& trailers() const { return trailers_; } const base::StringPiece body() const { return base::StringPiece(body_); } void set_response_type(SpecialResponseType response_type) { @@ -74,6 +75,7 @@ class QuicInMemoryCache { void set_headers(const SpdyHeaderBlock& headers) { headers_ = headers; } + void set_trailers(const SpdyHeaderBlock& trailers) { trailers_ = trailers; } void set_body(base::StringPiece body) { body.CopyToString(&body_); } @@ -81,7 +83,8 @@ class QuicInMemoryCache { private: SpecialResponseType response_type_; SpdyHeaderBlock headers_; - string body_; + SpdyHeaderBlock trailers_; + std::string body_; DISALLOW_COPY_AND_ASSIGN(Response); }; @@ -118,6 +121,13 @@ class QuicInMemoryCache { const SpdyHeaderBlock& response_headers, base::StringPiece response_body); + // Add a response, with trailers, to the cache. + void AddResponse(base::StringPiece host, + base::StringPiece path, + const SpdyHeaderBlock& response_headers, + base::StringPiece response_body, + const SpdyHeaderBlock& response_trailers); + // Simulate a special behavior at a particular path. void AddSpecialResponse(base::StringPiece host, base::StringPiece path, @@ -148,7 +158,8 @@ class QuicInMemoryCache { base::StringPiece path, SpecialResponseType response_type, const SpdyHeaderBlock& response_headers, - base::StringPiece response_body); + base::StringPiece response_body, + const SpdyHeaderBlock& response_trailers); string GetKey(base::StringPiece host, base::StringPiece path) const; diff --git a/net/tools/quic/quic_in_memory_cache_test.cc b/net/tools/quic/quic_in_memory_cache_test.cc index e42a91d..dbfc1a7 100644 --- a/net/tools/quic/quic_in_memory_cache_test.cc +++ b/net/tools/quic/quic_in_memory_cache_test.cc @@ -76,6 +76,32 @@ TEST_F(QuicInMemoryCacheTest, AddSimpleResponseGetResponse) { EXPECT_EQ(response_body.size(), response->body().length()); } +TEST_F(QuicInMemoryCacheTest, AddResponse) { + const string kRequestHost = "www.foo.com"; + const string kRequestPath = "/"; + const string kResponseBody("hello response"); + + SpdyHeaderBlock response_headers; + response_headers[":version"] = "HTTP/1.1"; + response_headers[":status"] = "200"; + response_headers["content-length"] = IntToString(kResponseBody.size()); + + SpdyHeaderBlock response_trailers; + response_trailers["key-1"] = "value-1"; + response_trailers["key-2"] = "value-2"; + response_trailers["key-3"] = "value-3"; + + QuicInMemoryCache* cache = QuicInMemoryCache::GetInstance(); + cache->AddResponse(kRequestHost, "/", response_headers, kResponseBody, + response_trailers); + + const QuicInMemoryCache::Response* response = + cache->GetResponse(kRequestHost, kRequestPath); + EXPECT_EQ(response->headers(), response_headers); + EXPECT_EQ(response->body(), kResponseBody); + EXPECT_EQ(response->trailers(), response_trailers); +} + TEST_F(QuicInMemoryCacheTest, ReadsCacheDir) { QuicInMemoryCache::GetInstance()->InitializeFromDirectory(CacheDirectory()); const QuicInMemoryCache::Response* response = diff --git a/net/tools/quic/quic_spdy_client_stream.cc b/net/tools/quic/quic_spdy_client_stream.cc index 817366c..48554b5 100644 --- a/net/tools/quic/quic_spdy_client_stream.cc +++ b/net/tools/quic/quic_spdy_client_stream.cc @@ -44,11 +44,24 @@ void QuicSpdyClientStream::OnStreamHeadersComplete(bool fin, size_t frame_len) { header_bytes_read_ = frame_len; QuicSpdyStream::OnStreamHeadersComplete(fin, frame_len); - if (!ParseResponseHeaders(decompressed_headers().data(), - decompressed_headers().length())) { + if (!SpdyUtils::ParseHeaders(decompressed_headers().data(), + decompressed_headers().length(), + &content_length_, &response_headers_)) { Reset(QUIC_BAD_APPLICATION_PAYLOAD); return; } + + string status = response_headers_[":status"].as_string(); + size_t end = status.find(" "); + if (end != string::npos) { + status.erase(end); + } + if (!StringToInt(status, &response_code_)) { + // Invalid response code. + Reset(QUIC_BAD_APPLICATION_PAYLOAD); + return; + } + MarkHeadersConsumed(decompressed_headers().length()); } @@ -77,31 +90,6 @@ void QuicSpdyClientStream::OnDataAvailable() { } } -bool QuicSpdyClientStream::ParseResponseHeaders(const char* data, - uint32 data_len) { - DCHECK(headers_decompressed()); - SpdyFramer framer(HTTP2); - if (!framer.ParseHeaderBlockInBuffer(data, data_len, &response_headers_) || - response_headers_.empty()) { - return false; // Headers were invalid. - } - - if (ContainsKey(response_headers_, "content-length") && - !StringToInt(StringPiece(response_headers_["content-length"]), - &content_length_)) { - return false; // Invalid content-length. - } - string status = response_headers_[":status"].as_string(); - size_t end = status.find(" "); - if (end != string::npos) { - status.erase(end); - } - if (!StringToInt(status, &response_code_)) { - return false; // Invalid response code. - } - return true; -} - size_t QuicSpdyClientStream::SendRequest(const SpdyHeaderBlock& headers, StringPiece body, bool fin) { diff --git a/net/tools/quic/quic_spdy_client_stream.h b/net/tools/quic/quic_spdy_client_stream.h index 6aa7824..b744c21 100644 --- a/net/tools/quic/quic_spdy_client_stream.h +++ b/net/tools/quic/quic_spdy_client_stream.h @@ -74,8 +74,6 @@ class QuicSpdyClientStream : public QuicSpdyStream { bool allow_bidirectional_data() const { return allow_bidirectional_data_; } private: - bool ParseResponseHeaders(const char* data, uint32 data_len); - // The parsed headers received from the server. SpdyHeaderBlock response_headers_; // The parsed content-length, or -1 if none is specified. diff --git a/net/tools/quic/quic_spdy_server_stream.cc b/net/tools/quic/quic_spdy_server_stream.cc index f10d040..dffed6e 100644 --- a/net/tools/quic/quic_spdy_server_stream.cc +++ b/net/tools/quic/quic_spdy_server_stream.cc @@ -32,8 +32,9 @@ QuicSpdyServerStream::~QuicSpdyServerStream() { void QuicSpdyServerStream::OnStreamHeadersComplete(bool fin, size_t frame_len) { QuicSpdyStream::OnStreamHeadersComplete(fin, frame_len); - if (!ParseRequestHeaders(decompressed_headers().data(), - decompressed_headers().length())) { + if (!SpdyUtils::ParseHeaders(decompressed_headers().data(), + decompressed_headers().length(), + &content_length_, &request_headers_)) { DVLOG(1) << "Invalid headers"; SendErrorResponse(); } @@ -89,40 +90,6 @@ void QuicSpdyServerStream::OnDataAvailable() { SendResponse(); } -bool QuicSpdyServerStream::ParseRequestHeaders(const char* data, - uint32 data_len) { - DCHECK(headers_decompressed()); - SpdyFramer framer(HTTP2); - if (!framer.ParseHeaderBlockInBuffer(data, data_len, &request_headers_) || - request_headers_.empty()) { - return false; // Headers were invalid. - } - - if (ContainsKey(request_headers_, "content-length")) { - string delimiter; - delimiter.push_back('\0'); - std::vector<string> values = - base::SplitString(request_headers_["content-length"], delimiter, - base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL); - - for (const string& value : values) { - int new_value; - if (!StringToInt(value, &new_value) || new_value < 0) { - return false; - } - if (content_length_ < 0) { - content_length_ = new_value; - continue; - } - if (new_value != content_length_) { - return false; - } - } - } - - return true; -} - void QuicSpdyServerStream::SendResponse() { if (!ContainsKey(request_headers_, ":authority") || !ContainsKey(request_headers_, ":path")) { diff --git a/net/tools/quic/quic_spdy_server_stream.h b/net/tools/quic/quic_spdy_server_stream.h index 2b3feee..708749e 100644 --- a/net/tools/quic/quic_spdy_server_stream.h +++ b/net/tools/quic/quic_spdy_server_stream.h @@ -58,10 +58,6 @@ class QuicSpdyServerStream : public QuicSpdyStream { private: friend class test::QuicSpdyServerStreamPeer; - // Parses the request headers from |data| to |request_headers_|. - // Returns false if there was an error parsing the headers. - bool ParseRequestHeaders(const char* data, uint32 data_len); - // The parsed headers received from the client. SpdyHeaderBlock request_headers_; int content_length_; diff --git a/net/tools/quic/quic_spdy_server_stream_test.cc b/net/tools/quic/quic_spdy_server_stream_test.cc index 4798fc5..1a3d988 100644 --- a/net/tools/quic/quic_spdy_server_stream_test.cc +++ b/net/tools/quic/quic_spdy_server_stream_test.cc @@ -103,7 +103,8 @@ class QuicSpdyServerStreamTest : public ::testing::TestWithParam<QuicVersion> { kInitialStreamFlowControlWindowForTest); session_.config()->SetInitialSessionFlowControlWindowToSend( kInitialSessionFlowControlWindowForTest); - stream_ = new QuicSpdyServerStreamPeer(5, &session_); + stream_ = new QuicSpdyServerStreamPeer(::net::test::kClientDataStreamId1, + &session_); // Register stream_ in dynamic_stream_map_ and pass ownership to session_. session_.ActivateStream(stream_); @@ -129,23 +130,14 @@ class QuicSpdyServerStreamTest : public ::testing::TestWithParam<QuicVersion> { string body_; }; -QuicConsumedData ConsumeAllData( - QuicStreamId /*id*/, - const QuicIOVector& data, - QuicStreamOffset /*offset*/, - bool fin, - FecProtection /*fec_protection_*/, - QuicAckListenerInterface* /*ack_notifier_delegate*/) { - return QuicConsumedData(data.total_length, fin); -} - INSTANTIATE_TEST_CASE_P(Tests, QuicSpdyServerStreamTest, ::testing::ValuesIn(QuicSupportedVersions())); TEST_P(QuicSpdyServerStreamTest, TestFraming) { - EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)).Times(AnyNumber()). - WillRepeatedly(Invoke(ConsumeAllData)); + EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)) + .Times(AnyNumber()) + .WillRepeatedly(Invoke(MockQuicSpdySession::ConsumeAllData)); stream_->OnStreamHeaders(headers_string_); stream_->OnStreamHeadersComplete(false, headers_string_.size()); stream_->OnStreamFrame( @@ -157,8 +149,9 @@ TEST_P(QuicSpdyServerStreamTest, TestFraming) { } TEST_P(QuicSpdyServerStreamTest, TestFramingOnePacket) { - EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)).Times(AnyNumber()). - WillRepeatedly(Invoke(ConsumeAllData)); + EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)) + .Times(AnyNumber()) + .WillRepeatedly(Invoke(MockQuicSpdySession::ConsumeAllData)); stream_->OnStreamHeaders(headers_string_); stream_->OnStreamHeadersComplete(false, headers_string_.size()); @@ -173,7 +166,7 @@ TEST_P(QuicSpdyServerStreamTest, TestFramingOnePacket) { TEST_P(QuicSpdyServerStreamTest, SendQuicRstStreamNoErrorInStopReading) { EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)) .Times(AnyNumber()) - .WillRepeatedly(Invoke(ConsumeAllData)); + .WillRepeatedly(Invoke(MockQuicSpdySession::ConsumeAllData)); EXPECT_FALSE(stream_->fin_received()); EXPECT_FALSE(stream_->rst_received()); @@ -193,8 +186,9 @@ TEST_P(QuicSpdyServerStreamTest, TestFramingExtraData) { string large_body = "hello world!!!!!!"; // We'll automatically write out an error (headers + body) - EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)).Times(AnyNumber()). - WillRepeatedly(Invoke(ConsumeAllData)); + EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)) + .Times(2) + .WillRepeatedly(Invoke(MockQuicSpdySession::ConsumeAllData)); EXPECT_CALL(session_, SendRstStream(_, QUIC_STREAM_NO_ERROR, _)).Times(0); stream_->OnStreamHeaders(headers_string_); @@ -327,7 +321,7 @@ TEST_P(QuicSpdyServerStreamTest, InvalidMultipleContentLength) { EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)) .Times(AnyNumber()) - .WillRepeatedly(Invoke(ConsumeAllData)); + .WillRepeatedly(Invoke(MockQuicSpdySession::ConsumeAllData)); stream_->OnStreamHeaders(headers_string_); stream_->OnStreamHeadersComplete(true, headers_string_.size()); @@ -347,7 +341,7 @@ TEST_P(QuicSpdyServerStreamTest, InvalidLeadingNullContentLength) { EXPECT_CALL(session_, WritevData(_, _, _, _, _, _)) .Times(AnyNumber()) - .WillRepeatedly(Invoke(ConsumeAllData)); + .WillRepeatedly(Invoke(MockQuicSpdySession::ConsumeAllData)); stream_->OnStreamHeaders(headers_string_); stream_->OnStreamHeadersComplete(true, headers_string_.size()); |