summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjokulik <jokulik@chromium.org>2015-12-08 13:42:57 -0800
committerCommit bot <commit-bot@chromium.org>2015-12-08 21:44:18 +0000
commit2324d28c4b07d5f15acd5890419b73348f97e54b (patch)
treefa77fec55a5041b4b439743af9f8a45042311d54
parent42290cb91a66566637a1715737b1961a8480b934 (diff)
downloadchromium_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}
-rw-r--r--net/quic/congestion_control/general_loss_algorithm_test.cc6
-rw-r--r--net/quic/congestion_control/tcp_loss_algorithm_test.cc6
-rw-r--r--net/quic/congestion_control/time_loss_algorithm_test.cc6
-rw-r--r--net/quic/quic_connection.cc51
-rw-r--r--net/quic/quic_connection.h7
-rw-r--r--net/quic/quic_connection_logger.cc7
-rw-r--r--net/quic/quic_connection_logger.h1
-rw-r--r--net/quic/quic_connection_test.cc14
-rw-r--r--net/quic/quic_framer.cc16
-rw-r--r--net/quic/quic_framer_test.cc12
-rw-r--r--net/quic/quic_headers_stream_test.cc34
-rw-r--r--net/quic/quic_packet_creator.cc40
-rw-r--r--net/quic/quic_packet_creator.h44
-rw-r--r--net/quic/quic_packet_creator_test.cc383
-rw-r--r--net/quic/quic_packet_generator.cc18
-rw-r--r--net/quic/quic_packet_generator.h10
-rw-r--r--net/quic/quic_protocol.cc64
-rw-r--r--net/quic/quic_protocol.h25
-rw-r--r--net/quic/quic_sent_packet_manager.cc7
-rw-r--r--net/quic/quic_sent_packet_manager.h3
-rw-r--r--net/quic/quic_sent_packet_manager_test.cc2
-rw-r--r--net/quic/quic_session.cc2
-rw-r--r--net/quic/quic_spdy_stream.h2
-rw-r--r--net/quic/quic_stream_sequencer.cc5
-rw-r--r--net/quic/quic_stream_sequencer_test.cc6
-rw-r--r--net/quic/quic_unacked_packet_map.cc5
-rw-r--r--net/quic/quic_unacked_packet_map_test.cc8
-rw-r--r--net/quic/reliable_quic_stream.cc7
-rw-r--r--net/quic/reliable_quic_stream.h4
-rw-r--r--net/quic/reliable_quic_stream_test.cc13
-rw-r--r--net/quic/spdy_utils.cc81
-rw-r--r--net/quic/spdy_utils.h21
-rw-r--r--net/quic/test_tools/crypto_test_utils.cc3
-rw-r--r--net/quic/test_tools/quic_stream_sequencer_peer.cc4
-rw-r--r--net/quic/test_tools/quic_test_utils.cc11
-rw-r--r--net/quic/test_tools/quic_test_utils.h15
-rw-r--r--net/quic/test_tools/simple_quic_framer.cc3
-rw-r--r--net/tools/quic/quic_in_memory_cache.cc29
-rw-r--r--net/tools/quic/quic_in_memory_cache.h15
-rw-r--r--net/tools/quic/quic_in_memory_cache_test.cc26
-rw-r--r--net/tools/quic/quic_spdy_client_stream.cc42
-rw-r--r--net/tools/quic/quic_spdy_client_stream.h2
-rw-r--r--net/tools/quic/quic_spdy_server_stream.cc39
-rw-r--r--net/tools/quic/quic_spdy_server_stream.h4
-rw-r--r--net/tools/quic/quic_spdy_server_stream_test.cc34
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());