Project import generated by Copybara.
PiperOrigin-RevId: 235760953
Change-Id: I302811f663a1f4772520f3fa3148e54851e0227a
diff --git a/http2/decoder/payload_decoders/altsvc_payload_decoder_test.cc b/http2/decoder/payload_decoders/altsvc_payload_decoder_test.cc
index bf928d3..0221328 100644
--- a/http2/decoder/payload_decoders/altsvc_payload_decoder_test.cc
+++ b/http2/decoder/payload_decoders/altsvc_payload_decoder_test.cc
@@ -96,10 +96,9 @@
const uint32_t value_length_;
};
-INSTANTIATE_TEST_CASE_P(VariousOriginAndValueLengths,
- AltSvcPayloadLengthTests,
- ::testing::Combine(::testing::Values(0, 1, 3, 65535),
- ::testing::Values(0, 1, 3, 65537)));
+INSTANTIATE_TEST_SUITE_P(VariousOriginAndValueLengths, AltSvcPayloadLengthTests,
+ ::testing::Combine(::testing::Values(0, 1, 3, 65535),
+ ::testing::Values(0, 1, 3, 65537)));
TEST_P(AltSvcPayloadLengthTests, ValidOriginAndValueLength) {
Http2String origin = Random().RandString(origin_length_);
diff --git a/http2/decoder/payload_decoders/continuation_payload_decoder_test.cc b/http2/decoder/payload_decoders/continuation_payload_decoder_test.cc
index 63888d3..6e81828 100644
--- a/http2/decoder/payload_decoders/continuation_payload_decoder_test.cc
+++ b/http2/decoder/payload_decoders/continuation_payload_decoder_test.cc
@@ -67,9 +67,8 @@
const uint32_t length_;
};
-INSTANTIATE_TEST_CASE_P(VariousLengths,
- ContinuationPayloadDecoderTest,
- ::testing::Values(0, 1, 2, 3, 4, 5, 6));
+INSTANTIATE_TEST_SUITE_P(VariousLengths, ContinuationPayloadDecoderTest,
+ ::testing::Values(0, 1, 2, 3, 4, 5, 6));
TEST_P(ContinuationPayloadDecoderTest, ValidLength) {
Http2String hpack_payload = Random().RandString(length_);
diff --git a/http2/decoder/payload_decoders/data_payload_decoder_test.cc b/http2/decoder/payload_decoders/data_payload_decoder_test.cc
index e5253b9..0622f17 100644
--- a/http2/decoder/payload_decoders/data_payload_decoder_test.cc
+++ b/http2/decoder/payload_decoders/data_payload_decoder_test.cc
@@ -98,9 +98,8 @@
}
};
-INSTANTIATE_TEST_CASE_P(VariousPadLengths,
- DataPayloadDecoderTest,
- ::testing::Values(0, 1, 2, 3, 4, 254, 255, 256));
+INSTANTIATE_TEST_SUITE_P(VariousPadLengths, DataPayloadDecoderTest,
+ ::testing::Values(0, 1, 2, 3, 4, 254, 255, 256));
TEST_P(DataPayloadDecoderTest, VariousDataPayloadSizes) {
for (size_t data_size : {0, 1, 2, 3, 255, 256, 1024}) {
diff --git a/http2/decoder/payload_decoders/goaway_payload_decoder_test.cc b/http2/decoder/payload_decoders/goaway_payload_decoder_test.cc
index 1df5214..c90cdcc 100644
--- a/http2/decoder/payload_decoders/goaway_payload_decoder_test.cc
+++ b/http2/decoder/payload_decoders/goaway_payload_decoder_test.cc
@@ -83,9 +83,8 @@
const uint32_t length_;
};
-INSTANTIATE_TEST_CASE_P(VariousLengths,
- GoAwayOpaqueDataLengthTests,
- ::testing::Values(0, 1, 2, 3, 4, 5, 6));
+INSTANTIATE_TEST_SUITE_P(VariousLengths, GoAwayOpaqueDataLengthTests,
+ ::testing::Values(0, 1, 2, 3, 4, 5, 6));
TEST_P(GoAwayOpaqueDataLengthTests, ValidLength) {
Http2GoAwayFields goaway;
diff --git a/http2/decoder/payload_decoders/headers_payload_decoder_test.cc b/http2/decoder/payload_decoders/headers_payload_decoder_test.cc
index a6fcb65..cb58b8e 100644
--- a/http2/decoder/payload_decoders/headers_payload_decoder_test.cc
+++ b/http2/decoder/payload_decoders/headers_payload_decoder_test.cc
@@ -94,9 +94,8 @@
HeadersPayloadDecoderPeer,
Listener> {};
-INSTANTIATE_TEST_CASE_P(VariousPadLengths,
- HeadersPayloadDecoderTest,
- ::testing::Values(0, 1, 2, 3, 4, 254, 255, 256));
+INSTANTIATE_TEST_SUITE_P(VariousPadLengths, HeadersPayloadDecoderTest,
+ ::testing::Values(0, 1, 2, 3, 4, 254, 255, 256));
// Decode various sizes of (fake) HPACK payload, both with and without the
// PRIORITY flag set.
diff --git a/http2/decoder/payload_decoders/push_promise_payload_decoder_test.cc b/http2/decoder/payload_decoders/push_promise_payload_decoder_test.cc
index 9d55a80..94220f7 100644
--- a/http2/decoder/payload_decoders/push_promise_payload_decoder_test.cc
+++ b/http2/decoder/payload_decoders/push_promise_payload_decoder_test.cc
@@ -87,9 +87,8 @@
PushPromisePayloadDecoderPeer,
Listener> {};
-INSTANTIATE_TEST_CASE_P(VariousPadLengths,
- PushPromisePayloadDecoderTest,
- ::testing::Values(0, 1, 2, 3, 4, 254, 255, 256));
+INSTANTIATE_TEST_SUITE_P(VariousPadLengths, PushPromisePayloadDecoderTest,
+ ::testing::Values(0, 1, 2, 3, 4, 254, 255, 256));
// Payload contains the required Http2PushPromiseFields, followed by some
// (fake) HPACK payload.
diff --git a/http2/decoder/payload_decoders/unknown_payload_decoder_test.cc b/http2/decoder/payload_decoders/unknown_payload_decoder_test.cc
index 7ba95f7..f9d203a 100644
--- a/http2/decoder/payload_decoders/unknown_payload_decoder_test.cc
+++ b/http2/decoder/payload_decoders/unknown_payload_decoder_test.cc
@@ -77,9 +77,8 @@
const uint32_t length_;
};
-INSTANTIATE_TEST_CASE_P(VariousLengths,
- UnknownPayloadDecoderTest,
- ::testing::Values(0, 1, 2, 3, 255, 256));
+INSTANTIATE_TEST_SUITE_P(VariousLengths, UnknownPayloadDecoderTest,
+ ::testing::Values(0, 1, 2, 3, 255, 256));
TEST_P(UnknownPayloadDecoderTest, ValidLength) {
Http2String unknown_payload = Random().RandString(length_);
diff --git a/http2/hpack/decoder/hpack_decoder_test.cc b/http2/hpack/decoder/hpack_decoder_test.cc
index 563e977..83a0ede 100644
--- a/http2/hpack/decoder/hpack_decoder_test.cc
+++ b/http2/hpack/decoder/hpack_decoder_test.cc
@@ -224,7 +224,7 @@
bool saw_start_ = false;
bool saw_end_ = false;
};
-INSTANTIATE_TEST_CASE_P(AllWays, HpackDecoderTest, ::testing::Bool());
+INSTANTIATE_TEST_SUITE_P(AllWays, HpackDecoderTest, ::testing::Bool());
// Test based on RFC 7541, section C.3: Request Examples without Huffman Coding.
// This section shows several consecutive header lists, corresponding to HTTP
diff --git a/http2/hpack/decoder/hpack_entry_decoder_test.cc b/http2/hpack/decoder/hpack_entry_decoder_test.cc
index 7249bd5..b447e82 100644
--- a/http2/hpack/decoder/hpack_entry_decoder_test.cc
+++ b/http2/hpack/decoder/hpack_entry_decoder_test.cc
@@ -157,9 +157,8 @@
const HpackEntryType entry_type_;
};
-INSTANTIATE_TEST_CASE_P(
- AllLiteralTypes,
- HpackLiteralEntryDecoderTest,
+INSTANTIATE_TEST_SUITE_P(
+ AllLiteralTypes, HpackLiteralEntryDecoderTest,
testing::Values(HpackEntryType::kIndexedLiteralHeader,
HpackEntryType::kUnindexedLiteralHeader,
HpackEntryType::kNeverIndexedLiteralHeader));
diff --git a/http2/hpack/huffman/hpack_huffman_transcoder_test.cc b/http2/hpack/huffman/hpack_huffman_transcoder_test.cc
index cfd73b5..2791d6a 100644
--- a/http2/hpack/huffman/hpack_huffman_transcoder_test.cc
+++ b/http2/hpack/huffman/hpack_huffman_transcoder_test.cc
@@ -139,9 +139,9 @@
const char c_;
};
-INSTANTIATE_TEST_CASE_P(HpackHuffmanTranscoderAdjacentCharTest,
- HpackHuffmanTranscoderAdjacentCharTest,
- ::testing::Range(0, 256));
+INSTANTIATE_TEST_SUITE_P(HpackHuffmanTranscoderAdjacentCharTest,
+ HpackHuffmanTranscoderAdjacentCharTest,
+ ::testing::Range(0, 256));
// Test c_ adjacent to every other character, both before and after.
TEST_P(HpackHuffmanTranscoderAdjacentCharTest, RoundTripAdjacentChar) {
@@ -169,11 +169,11 @@
const size_t length_;
};
-INSTANTIATE_TEST_CASE_P(
- HpackHuffmanTranscoderRepeatedCharTest,
- HpackHuffmanTranscoderRepeatedCharTest,
- ::testing::Combine(::testing::Range(0, 256),
- ::testing::Values(1, 2, 3, 4, 8, 16, 32)));
+INSTANTIATE_TEST_SUITE_P(HpackHuffmanTranscoderRepeatedCharTest,
+ HpackHuffmanTranscoderRepeatedCharTest,
+ ::testing::Combine(::testing::Range(0, 256),
+ ::testing::Values(1, 2, 3, 4, 8, 16,
+ 32)));
TEST_P(HpackHuffmanTranscoderRepeatedCharTest, RoundTripRepeatedChar) {
ASSERT_TRUE(TranscodeAndValidateSeveralWays(MakeString()));
diff --git a/http2/hpack/varint/hpack_varint_decoder_test.cc b/http2/hpack/varint/hpack_varint_decoder_test.cc
index 32a4a30..2d589fd 100644
--- a/http2/hpack/varint/hpack_varint_decoder_test.cc
+++ b/http2/hpack/varint/hpack_varint_decoder_test.cc
@@ -107,9 +107,8 @@
uint8_t prefix_length_;
};
-INSTANTIATE_TEST_CASE_P(
- HpackVarintDecoderTest,
- HpackVarintDecoderTest,
+INSTANTIATE_TEST_SUITE_P(
+ HpackVarintDecoderTest, HpackVarintDecoderTest,
::testing::Combine(
// Bits of the first byte not part of the prefix should be ignored.
::testing::Values(0b00000000, 0b11111111, 0b10101010),
diff --git a/http2/http2_structures_test.cc b/http2/http2_structures_test.cc
index 30ebb36..78107f7 100644
--- a/http2/http2_structures_test.cc
+++ b/http2/http2_structures_test.cc
@@ -163,10 +163,9 @@
};
class IsEndStreamTest : public Http2FrameHeaderTypeAndFlagTest {};
-INSTANTIATE_TEST_CASE_P(IsEndStream,
- IsEndStreamTest,
- Combine(ValuesIn(ValidFrameTypes()),
- Values(~Http2FrameFlag::END_STREAM, 0xff)));
+INSTANTIATE_TEST_SUITE_P(IsEndStream, IsEndStreamTest,
+ Combine(ValuesIn(ValidFrameTypes()),
+ Values(~Http2FrameFlag::END_STREAM, 0xff)));
TEST_P(IsEndStreamTest, IsEndStream) {
const bool is_set =
(flags_ & Http2FrameFlag::END_STREAM) == Http2FrameFlag::END_STREAM;
@@ -201,10 +200,9 @@
}
class IsACKTest : public Http2FrameHeaderTypeAndFlagTest {};
-INSTANTIATE_TEST_CASE_P(IsAck,
- IsACKTest,
- Combine(ValuesIn(ValidFrameTypes()),
- Values(~Http2FrameFlag::ACK, 0xff)));
+INSTANTIATE_TEST_SUITE_P(IsAck, IsACKTest,
+ Combine(ValuesIn(ValidFrameTypes()),
+ Values(~Http2FrameFlag::ACK, 0xff)));
TEST_P(IsACKTest, IsAck) {
const bool is_set = (flags_ & Http2FrameFlag::ACK) == Http2FrameFlag::ACK;
Http2String flags_string;
@@ -238,10 +236,9 @@
}
class IsEndHeadersTest : public Http2FrameHeaderTypeAndFlagTest {};
-INSTANTIATE_TEST_CASE_P(IsEndHeaders,
- IsEndHeadersTest,
- Combine(ValuesIn(ValidFrameTypes()),
- Values(~Http2FrameFlag::END_HEADERS, 0xff)));
+INSTANTIATE_TEST_SUITE_P(IsEndHeaders, IsEndHeadersTest,
+ Combine(ValuesIn(ValidFrameTypes()),
+ Values(~Http2FrameFlag::END_HEADERS, 0xff)));
TEST_P(IsEndHeadersTest, IsEndHeaders) {
const bool is_set =
(flags_ & Http2FrameFlag::END_HEADERS) == Http2FrameFlag::END_HEADERS;
@@ -279,10 +276,9 @@
}
class IsPaddedTest : public Http2FrameHeaderTypeAndFlagTest {};
-INSTANTIATE_TEST_CASE_P(IsPadded,
- IsPaddedTest,
- Combine(ValuesIn(ValidFrameTypes()),
- Values(~Http2FrameFlag::PADDED, 0xff)));
+INSTANTIATE_TEST_SUITE_P(IsPadded, IsPaddedTest,
+ Combine(ValuesIn(ValidFrameTypes()),
+ Values(~Http2FrameFlag::PADDED, 0xff)));
TEST_P(IsPaddedTest, IsPadded) {
const bool is_set =
(flags_ & Http2FrameFlag::PADDED) == Http2FrameFlag::PADDED;
@@ -318,10 +314,9 @@
}
class HasPriorityTest : public Http2FrameHeaderTypeAndFlagTest {};
-INSTANTIATE_TEST_CASE_P(HasPriority,
- HasPriorityTest,
- Combine(ValuesIn(ValidFrameTypes()),
- Values(~Http2FrameFlag::PRIORITY, 0xff)));
+INSTANTIATE_TEST_SUITE_P(HasPriority, HasPriorityTest,
+ Combine(ValuesIn(ValidFrameTypes()),
+ Values(~Http2FrameFlag::PRIORITY, 0xff)));
TEST_P(HasPriorityTest, HasPriority) {
const bool is_set =
(flags_ & Http2FrameFlag::PRIORITY) == Http2FrameFlag::PRIORITY;
diff --git a/quic/core/chlo_extractor.cc b/quic/core/chlo_extractor.cc
index b44aa9c..caf0af1 100644
--- a/quic/core/chlo_extractor.cc
+++ b/quic/core/chlo_extractor.cc
@@ -39,6 +39,7 @@
bool OnUnauthenticatedHeader(const QuicPacketHeader& header) override;
void OnDecryptedPacket(EncryptionLevel level) override {}
bool OnPacketHeader(const QuicPacketHeader& header) override;
+ void OnCoalescedPacket(const QuicEncryptedPacket& packet) override;
bool OnStreamFrame(const QuicStreamFrame& frame) override;
bool OnCryptoFrame(const QuicCryptoFrame& frame) override;
bool OnAckFrameStart(QuicPacketNumber largest_acked,
@@ -75,6 +76,9 @@
void OnError(CryptoFramer* framer) override;
void OnHandshakeMessage(const CryptoHandshakeMessage& message) override;
+ // Shared implementation between OnStreamFrame and OnCryptoFrame.
+ bool OnHandshakeData(QuicStringPiece data);
+
bool found_chlo() { return found_chlo_; }
bool chlo_contains_tags() { return chlo_contains_tags_; }
@@ -119,39 +123,56 @@
bool ChloFramerVisitor::OnPacketHeader(const QuicPacketHeader& header) {
return true;
}
+void ChloFramerVisitor::OnCoalescedPacket(const QuicEncryptedPacket& packet) {}
bool ChloFramerVisitor::OnStreamFrame(const QuicStreamFrame& frame) {
+ if (framer_->transport_version() >= QUIC_VERSION_47) {
+ // CHLO will be sent in CRYPTO frames in v47 and above.
+ return false;
+ }
QuicStringPiece data(frame.data_buffer, frame.data_length);
if (frame.stream_id ==
QuicUtils::GetCryptoStreamId(framer_->transport_version()) &&
frame.offset == 0 && QuicTextUtils::StartsWith(data, "CHLO")) {
- CryptoFramer crypto_framer;
- crypto_framer.set_visitor(this);
- if (!crypto_framer.ProcessInput(data)) {
- return false;
- }
- // Interrogate the crypto framer and see if there are any
- // intersecting tags between what we saw in the maybe-CHLO and the
- // indicator set.
- for (const QuicTag tag : create_session_tag_indicators_) {
- if (crypto_framer.HasTag(tag)) {
- chlo_contains_tags_ = true;
- }
- }
- if (chlo_contains_tags_ && delegate_) {
- // Unfortunately, because this is a partial CHLO,
- // OnHandshakeMessage was never called, so the ALPN was never
- // extracted. Fake it up a bit and send it to the delegate so that
- // the correct dispatch can happen.
- crypto_framer.ForceHandshake();
- }
+ return OnHandshakeData(data);
}
-
return true;
}
bool ChloFramerVisitor::OnCryptoFrame(const QuicCryptoFrame& frame) {
- // TODO(nharper): Implement.
- return false;
+ if (framer_->transport_version() < QUIC_VERSION_47) {
+ // CHLO will be in stream frames before v47.
+ return false;
+ }
+ QuicStringPiece data(frame.data_buffer, frame.data_length);
+ if (frame.offset == 0 && QuicTextUtils::StartsWith(data, "CHLO")) {
+ return OnHandshakeData(data);
+ }
+ return true;
+}
+
+bool ChloFramerVisitor::OnHandshakeData(QuicStringPiece data) {
+ CryptoFramer crypto_framer;
+ crypto_framer.set_visitor(this);
+ if (!crypto_framer.ProcessInput(data)) {
+ return false;
+ }
+ // Interrogate the crypto framer and see if there are any
+ // intersecting tags between what we saw in the maybe-CHLO and the
+ // indicator set.
+ for (const QuicTag tag : create_session_tag_indicators_) {
+ if (crypto_framer.HasTag(tag)) {
+ chlo_contains_tags_ = true;
+ }
+ }
+ if (chlo_contains_tags_ && delegate_) {
+ // Unfortunately, because this is a partial CHLO,
+ // OnHandshakeMessage was never called, so the ALPN was never
+ // extracted. Fake it up a bit and send it to the delegate so that
+ // the correct dispatch can happen.
+ crypto_framer.ForceHandshake();
+ }
+
+ return true;
}
bool ChloFramerVisitor::OnAckFrameStart(QuicPacketNumber /*largest_acked*/,
diff --git a/quic/core/chlo_extractor_test.cc b/quic/core/chlo_extractor_test.cc
index d16050b..e8b6483 100644
--- a/quic/core/chlo_extractor_test.cc
+++ b/quic/core/chlo_extractor_test.cc
@@ -53,14 +53,35 @@
header_.reset_flag = false;
header_.packet_number_length = PACKET_4BYTE_PACKET_NUMBER;
header_.packet_number = QuicPacketNumber(1);
+ if (QuicVersionHasLongHeaderLengths(header_.version.transport_version)) {
+ header_.retry_token_length_length = VARIABLE_LENGTH_INTEGER_LENGTH_1;
+ header_.length_length = VARIABLE_LENGTH_INTEGER_LENGTH_2;
+ }
}
- void MakePacket(const QuicStreamFrame& stream_frame) {
- QuicFrame frame(stream_frame);
+ void MakePacket(ParsedQuicVersion version,
+ QuicStringPiece data,
+ bool munge_offset,
+ bool munge_stream_id) {
QuicFrames frames;
- frames.push_back(frame);
+ size_t offset = 0;
+ if (munge_offset) {
+ offset++;
+ }
QuicFramer framer(SupportedVersions(header_.version), QuicTime::Zero(),
Perspective::IS_CLIENT);
+ if (version.transport_version < QUIC_VERSION_47 || munge_stream_id) {
+ QuicStreamId stream_id =
+ QuicUtils::GetCryptoStreamId(version.transport_version);
+ if (munge_stream_id) {
+ stream_id++;
+ }
+ frames.push_back(
+ QuicFrame(QuicStreamFrame(stream_id, false, offset, data)));
+ } else {
+ frames.push_back(
+ QuicFrame(new QuicCryptoFrame(ENCRYPTION_NONE, offset, data)));
+ }
std::unique_ptr<QuicPacket> packet(
BuildUnsizedDataPacket(&framer, header_, frames));
EXPECT_TRUE(packet != nullptr);
@@ -70,6 +91,7 @@
ASSERT_NE(0u, encrypted_length);
packet_ = QuicMakeUnique<QuicEncryptedPacket>(buffer_, encrypted_length);
EXPECT_TRUE(packet_ != nullptr);
+ DeleteFrames(&frames);
}
protected:
@@ -86,11 +108,19 @@
QuicString client_hello_str(client_hello.GetSerialized().AsStringPiece());
// Construct a CHLO with each supported version
for (ParsedQuicVersion version : AllSupportedVersions()) {
+ SCOPED_TRACE(version);
ParsedQuicVersionVector versions(SupportedVersions(version));
header_.version = version;
- MakePacket(
- QuicStreamFrame(QuicUtils::GetCryptoStreamId(version.transport_version),
- false, 0, client_hello_str));
+ if (QuicVersionHasLongHeaderLengths(version.transport_version) &&
+ header_.version_flag) {
+ header_.retry_token_length_length = VARIABLE_LENGTH_INTEGER_LENGTH_1;
+ header_.length_length = VARIABLE_LENGTH_INTEGER_LENGTH_2;
+ } else {
+ header_.retry_token_length_length = VARIABLE_LENGTH_INTEGER_LENGTH_0;
+ header_.length_length = VARIABLE_LENGTH_INTEGER_LENGTH_0;
+ }
+ MakePacket(version, client_hello_str, /*munge_offset*/ false,
+ /*munge_stream_id*/ false);
EXPECT_TRUE(ChloExtractor::Extract(*packet_, versions, {}, &delegate_))
<< ParsedQuicVersionToString(version);
EXPECT_EQ(version.transport_version, delegate_.transport_version());
@@ -105,10 +135,8 @@
client_hello.set_tag(kCHLO);
QuicString client_hello_str(client_hello.GetSerialized().AsStringPiece());
- MakePacket(QuicStreamFrame(QuicUtils::GetCryptoStreamId(
- AllSupportedVersions()[0].transport_version) +
- 1,
- false, 0, client_hello_str));
+ MakePacket(AllSupportedVersions()[0], client_hello_str,
+ /*munge_offset*/ false, /*munge_stream_id*/ true);
EXPECT_FALSE(
ChloExtractor::Extract(*packet_, AllSupportedVersions(), {}, &delegate_));
}
@@ -118,17 +146,15 @@
client_hello.set_tag(kCHLO);
QuicString client_hello_str(client_hello.GetSerialized().AsStringPiece());
- MakePacket(QuicStreamFrame(
- QuicUtils::GetCryptoStreamId(AllSupportedVersions()[0].transport_version),
- false, 1, client_hello_str));
+ MakePacket(AllSupportedVersions()[0], client_hello_str, /*munge_offset*/ true,
+ /*munge_stream_id*/ false);
EXPECT_FALSE(
ChloExtractor::Extract(*packet_, AllSupportedVersions(), {}, &delegate_));
}
TEST_F(ChloExtractorTest, DoesNotFindInvalidChlo) {
- MakePacket(QuicStreamFrame(
- QuicUtils::GetCryptoStreamId(AllSupportedVersions()[0].transport_version),
- false, 0, "foo"));
+ MakePacket(AllSupportedVersions()[0], "foo", /*munge_offset*/ false,
+ /*munge_stream_id*/ true);
EXPECT_FALSE(
ChloExtractor::Extract(*packet_, AllSupportedVersions(), {}, &delegate_));
}
diff --git a/quic/core/congestion_control/general_loss_algorithm.cc b/quic/core/congestion_control/general_loss_algorithm.cc
index 27a3ab8..8cd5e71 100644
--- a/quic/core/congestion_control/general_loss_algorithm.cc
+++ b/quic/core/congestion_control/general_loss_algorithm.cc
@@ -32,7 +32,7 @@
GeneralLossAlgorithm::GeneralLossAlgorithm(LossDetectionType loss_type)
: loss_detection_timeout_(QuicTime::Zero()),
least_in_flight_(1),
- faster_detect_loss_(GetQuicReloadableFlag(quic_faster_detect_loss)) {
+ packet_number_space_(NUM_PACKET_NUMBER_SPACES) {
SetLossDetectionType(loss_type);
}
@@ -64,16 +64,14 @@
const AckedPacketVector& packets_acked,
LostPacketVector* packets_lost) {
loss_detection_timeout_ = QuicTime::Zero();
- if (faster_detect_loss_ && !packets_acked.empty() &&
+ if (!packets_acked.empty() &&
packets_acked.front().packet_number == least_in_flight_) {
if (least_in_flight_ + packets_acked.size() - 1 == largest_newly_acked) {
// Optimization for the case when no packet is missing.
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_faster_detect_loss, 1, 3);
least_in_flight_ = largest_newly_acked + 1;
largest_previously_acked_ = largest_newly_acked;
return;
}
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_faster_detect_loss, 2, 3);
// There is hole in acked_packets, increment least_in_flight_ if possible.
for (const auto& acked : packets_acked) {
if (acked.packet_number != least_in_flight_) {
@@ -89,34 +87,29 @@
max_rtt + (max_rtt >> reordering_shift_));
QuicPacketNumber packet_number = unacked_packets.GetLeastUnacked();
auto it = unacked_packets.begin();
- if (faster_detect_loss_) {
- if (least_in_flight_.IsInitialized() && least_in_flight_ >= packet_number) {
- if (least_in_flight_ > unacked_packets.largest_sent_packet() + 1) {
- QUIC_BUG << "least_in_flight: " << least_in_flight_
- << " is greater than largest_sent_packet + 1: "
- << unacked_packets.largest_sent_packet() + 1;
- } else {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_faster_detect_loss, 3, 3);
- it += (least_in_flight_ - packet_number);
- packet_number = least_in_flight_;
- }
- }
- // Clear least_in_flight_.
- least_in_flight_.Clear();
- } else {
- if (largest_lost_.IsInitialized() && largest_lost_ >= packet_number) {
- if (largest_lost_ > unacked_packets.largest_sent_packet()) {
- QUIC_BUG << "largest_lost: " << largest_lost_
- << " is greater than largest_sent_packet: "
- << unacked_packets.largest_sent_packet();
- } else {
- it += (largest_lost_ - packet_number + 1);
- packet_number = largest_lost_ + 1;
- }
+ if (least_in_flight_.IsInitialized() && least_in_flight_ >= packet_number) {
+ if (least_in_flight_ > unacked_packets.largest_sent_packet() + 1) {
+ QUIC_BUG << "least_in_flight: " << least_in_flight_
+ << " is greater than largest_sent_packet + 1: "
+ << unacked_packets.largest_sent_packet() + 1;
+ } else {
+ it += (least_in_flight_ - packet_number);
+ packet_number = least_in_flight_;
}
}
+ // Clear least_in_flight_.
+ least_in_flight_.Clear();
+ DCHECK(!unacked_packets.use_uber_loss_algorithm() ||
+ packet_number_space_ ==
+ unacked_packets.GetPacketNumberSpace(largest_newly_acked));
for (; it != unacked_packets.end() && packet_number <= largest_newly_acked;
++it, ++packet_number) {
+ if (unacked_packets.use_uber_loss_algorithm() &&
+ unacked_packets.GetPacketNumberSpace(it->encryption_level) !=
+ packet_number_space_) {
+ // Skip packets of different packet number space.
+ continue;
+ }
if (!it->in_flight) {
continue;
}
@@ -144,8 +137,18 @@
// Only early retransmit(RFC5827) when the last packet gets acked and
// there are retransmittable packets in flight.
// This also implements a timer-protected variant of FACK.
- if (unacked_packets.largest_sent_retransmittable_packet() <=
- largest_newly_acked ||
+ QuicPacketNumber largest_sent_retransmittable_packet;
+ if (unacked_packets.use_uber_loss_algorithm()) {
+ // Use largest_sent_retransmittable_packet of corresponding packet number
+ // space for timer based loss detection.
+ largest_sent_retransmittable_packet =
+ unacked_packets.GetLargestSentRetransmittableOfPacketNumberSpace(
+ packet_number_space_);
+ } else {
+ largest_sent_retransmittable_packet =
+ unacked_packets.largest_sent_retransmittable_packet();
+ }
+ if (largest_sent_retransmittable_packet <= largest_newly_acked ||
loss_type_ == kTime || loss_type_ == kAdaptiveTime) {
QuicTime when_lost = it->sent_time + loss_delay;
if (time < when_lost) {
@@ -176,11 +179,6 @@
least_in_flight_ = largest_newly_acked + 1;
}
largest_previously_acked_ = largest_newly_acked;
- if (!packets_lost->empty()) {
- DCHECK(!largest_lost_.IsInitialized() ||
- largest_lost_ < packets_lost->back().packet_number);
- largest_lost_ = packets_lost->back().packet_number;
- }
}
QuicTime GeneralLossAlgorithm::GetLossTimeout() const {
@@ -225,4 +223,14 @@
} while (proposed_extra_time < extra_time_needed && reordering_shift_ > 0);
}
+void GeneralLossAlgorithm::SetPacketNumberSpace(
+ PacketNumberSpace packet_number_space) {
+ if (packet_number_space_ < NUM_PACKET_NUMBER_SPACES) {
+ QUIC_BUG << "Cannot switch packet_number_space";
+ return;
+ }
+
+ packet_number_space_ = packet_number_space;
+}
+
} // namespace quic
diff --git a/quic/core/congestion_control/general_loss_algorithm.h b/quic/core/congestion_control/general_loss_algorithm.h
index 0d8e565..a2bcadd 100644
--- a/quic/core/congestion_control/general_loss_algorithm.h
+++ b/quic/core/congestion_control/general_loss_algorithm.h
@@ -55,6 +55,8 @@
const RttStats& rtt_stats,
QuicPacketNumber spurious_retransmission) override;
+ void SetPacketNumberSpace(PacketNumberSpace packet_number_space);
+
int reordering_shift() const { return reordering_shift_; }
private:
@@ -71,15 +73,11 @@
int reordering_shift_;
// The largest newly acked from the previous call to DetectLosses.
QuicPacketNumber largest_previously_acked_;
- // The largest lost packet.
- // TODO(fayang): Remove this variable when deprecating
- // quic_faster_detect_loss.
- QuicPacketNumber largest_lost_;
// The least in flight packet. Loss detection should start from this. Please
// note, least_in_flight_ could be largest packet ever sent + 1.
QuicPacketNumber least_in_flight_;
- // Latched value of quic_faster_detect_loss flag.
- const bool faster_detect_loss_;
+ // This is only used when quic_use_uber_loss_algorithm is true.
+ PacketNumberSpace packet_number_space_;
};
} // namespace quic
diff --git a/quic/core/congestion_control/general_loss_algorithm_test.cc b/quic/core/congestion_control/general_loss_algorithm_test.cc
index 2cd19a7..91a25da 100644
--- a/quic/core/congestion_control/general_loss_algorithm_test.cc
+++ b/quic/core/congestion_control/general_loss_algorithm_test.cc
@@ -23,10 +23,13 @@
class GeneralLossAlgorithmTest : public QuicTest {
protected:
- GeneralLossAlgorithmTest() {
+ GeneralLossAlgorithmTest() : unacked_packets_(Perspective::IS_CLIENT) {
rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(100),
QuicTime::Delta::Zero(), clock_.Now());
EXPECT_LT(0, rtt_stats_.smoothed_rtt().ToMicroseconds());
+ if (unacked_packets_.use_uber_loss_algorithm()) {
+ loss_algorithm_.SetPacketNumberSpace(HANDSHAKE_DATA);
+ }
}
~GeneralLossAlgorithmTest() override {}
@@ -54,9 +57,12 @@
void VerifyLosses(uint64_t largest_newly_acked,
const AckedPacketVector& packets_acked,
const std::vector<uint64_t>& losses_expected) {
- if (!unacked_packets_.largest_acked().IsInitialized() ||
- QuicPacketNumber(largest_newly_acked) >
- unacked_packets_.largest_acked()) {
+ if (unacked_packets_.use_uber_loss_algorithm()) {
+ unacked_packets_.MaybeUpdateLargestAckedOfPacketNumberSpace(
+ ENCRYPTION_NONE, QuicPacketNumber(largest_newly_acked));
+ } else if (!unacked_packets_.largest_acked().IsInitialized() ||
+ QuicPacketNumber(largest_newly_acked) >
+ unacked_packets_.largest_acked()) {
unacked_packets_.IncreaseLargestAcked(
QuicPacketNumber(largest_newly_acked));
}
@@ -208,7 +214,12 @@
clock_.AdvanceTime(rtt_stats_.smoothed_rtt());
// Early retransmit when the final packet gets acked and the first is nacked.
- unacked_packets_.IncreaseLargestAcked(QuicPacketNumber(2));
+ if (unacked_packets_.use_uber_loss_algorithm()) {
+ unacked_packets_.MaybeUpdateLargestAckedOfPacketNumberSpace(
+ ENCRYPTION_NONE, QuicPacketNumber(2));
+ } else {
+ unacked_packets_.IncreaseLargestAcked(QuicPacketNumber(2));
+ }
unacked_packets_.RemoveFromInFlight(QuicPacketNumber(2));
packets_acked.push_back(
AckedPacket(QuicPacketNumber(2), kMaxPacketSize, QuicTime::Zero()));
@@ -226,7 +237,12 @@
clock_.AdvanceTime(rtt_stats_.smoothed_rtt());
// Early retransmit when the final packet gets acked and the first is nacked.
- unacked_packets_.IncreaseLargestAcked(QuicPacketNumber(2));
+ if (unacked_packets_.use_uber_loss_algorithm()) {
+ unacked_packets_.MaybeUpdateLargestAckedOfPacketNumberSpace(
+ ENCRYPTION_NONE, QuicPacketNumber(2));
+ } else {
+ unacked_packets_.IncreaseLargestAcked(QuicPacketNumber(2));
+ }
unacked_packets_.RemoveFromInFlight(QuicPacketNumber(2));
packets_acked.push_back(
AckedPacket(QuicPacketNumber(2), kMaxPacketSize, QuicTime::Zero()));
@@ -253,7 +269,12 @@
AckedPacketVector packets_acked;
// Wait another RTT and ack 2.
clock_.AdvanceTime(rtt_stats_.smoothed_rtt());
- unacked_packets_.IncreaseLargestAcked(QuicPacketNumber(2));
+ if (unacked_packets_.use_uber_loss_algorithm()) {
+ unacked_packets_.MaybeUpdateLargestAckedOfPacketNumberSpace(
+ ENCRYPTION_NONE, QuicPacketNumber(2));
+ } else {
+ unacked_packets_.IncreaseLargestAcked(QuicPacketNumber(2));
+ }
unacked_packets_.RemoveFromInFlight(QuicPacketNumber(2));
packets_acked.push_back(
AckedPacket(QuicPacketNumber(2), kMaxPacketSize, QuicTime::Zero()));
diff --git a/quic/core/congestion_control/send_algorithm_test.cc b/quic/core/congestion_control/send_algorithm_test.cc
index 6001690..d7bfd85 100644
--- a/quic/core/congestion_control/send_algorithm_test.cc
+++ b/quic/core/congestion_control/send_algorithm_test.cc
@@ -268,10 +268,9 @@
SendAlgorithmInterface* sender_;
};
-INSTANTIATE_TEST_CASE_P(SendAlgorithmTests,
- SendAlgorithmTest,
- ::testing::ValuesIn(GetTestParams()),
- TestParamToString);
+INSTANTIATE_TEST_SUITE_P(SendAlgorithmTests, SendAlgorithmTest,
+ ::testing::ValuesIn(GetTestParams()),
+ TestParamToString);
// Test a simple long data transfer in the default setup.
TEST_P(SendAlgorithmTest, SimpleWiredNetworkTransfer) {
diff --git a/quic/core/congestion_control/uber_loss_algorithm.cc b/quic/core/congestion_control/uber_loss_algorithm.cc
new file mode 100644
index 0000000..8db151b
--- /dev/null
+++ b/quic/core/congestion_control/uber_loss_algorithm.cc
@@ -0,0 +1,86 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/core/congestion_control/uber_loss_algorithm.h"
+
+#include <algorithm>
+
+namespace quic {
+
+UberLossAlgorithm::UberLossAlgorithm() : UberLossAlgorithm(kNack) {}
+
+UberLossAlgorithm::UberLossAlgorithm(LossDetectionType loss_type)
+ : loss_type_(loss_type) {
+ SetLossDetectionType(loss_type);
+ for (int8_t i = INITIAL_DATA; i < NUM_PACKET_NUMBER_SPACES; ++i) {
+ general_loss_algorithms_[i].SetPacketNumberSpace(
+ static_cast<PacketNumberSpace>(i));
+ }
+}
+
+LossDetectionType UberLossAlgorithm::GetLossDetectionType() const {
+ return loss_type_;
+}
+
+void UberLossAlgorithm::SetLossDetectionType(LossDetectionType loss_type) {
+ loss_type_ = loss_type;
+ for (auto& loss_algorithm : general_loss_algorithms_) {
+ loss_algorithm.SetLossDetectionType(loss_type);
+ }
+}
+
+void UberLossAlgorithm::DetectLosses(
+ const QuicUnackedPacketMap& unacked_packets,
+ QuicTime time,
+ const RttStats& rtt_stats,
+ QuicPacketNumber /*largest_newly_acked*/,
+ const AckedPacketVector& packets_acked,
+ LostPacketVector* packets_lost) {
+ DCHECK(unacked_packets.use_uber_loss_algorithm());
+ for (int8_t i = INITIAL_DATA; i < NUM_PACKET_NUMBER_SPACES; ++i) {
+ const QuicPacketNumber largest_acked =
+ unacked_packets.GetLargestAckedOfPacketNumberSpace(
+ static_cast<PacketNumberSpace>(i));
+ if (!largest_acked.IsInitialized() ||
+ unacked_packets.GetLeastUnacked() > largest_acked) {
+ // Skip detecting losses if no packet has been received for this packet
+ // number space or the least_unacked is greater than largest_acked.
+ continue;
+ }
+
+ general_loss_algorithms_[i].DetectLosses(unacked_packets, time, rtt_stats,
+ largest_acked, packets_acked,
+ packets_lost);
+ }
+}
+
+QuicTime UberLossAlgorithm::GetLossTimeout() const {
+ QuicTime loss_timeout = QuicTime::Zero();
+ // Returns the earliest non-zero loss timeout.
+ for (int8_t i = INITIAL_DATA; i < NUM_PACKET_NUMBER_SPACES; ++i) {
+ const QuicTime timeout = general_loss_algorithms_[i].GetLossTimeout();
+ if (!loss_timeout.IsInitialized()) {
+ loss_timeout = timeout;
+ continue;
+ }
+ if (timeout.IsInitialized()) {
+ loss_timeout = std::min(loss_timeout, timeout);
+ }
+ }
+ return loss_timeout;
+}
+
+void UberLossAlgorithm::SpuriousRetransmitDetected(
+ const QuicUnackedPacketMap& unacked_packets,
+ QuicTime time,
+ const RttStats& rtt_stats,
+ QuicPacketNumber spurious_retransmission) {
+ DCHECK(unacked_packets.use_uber_loss_algorithm());
+ general_loss_algorithms_[unacked_packets.GetPacketNumberSpace(
+ spurious_retransmission)]
+ .SpuriousRetransmitDetected(unacked_packets, time, rtt_stats,
+ spurious_retransmission);
+}
+
+} // namespace quic
diff --git a/quic/core/congestion_control/uber_loss_algorithm.h b/quic/core/congestion_control/uber_loss_algorithm.h
new file mode 100644
index 0000000..dddbcb3
--- /dev/null
+++ b/quic/core/congestion_control/uber_loss_algorithm.h
@@ -0,0 +1,53 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_QUIC_CORE_CONGESTION_CONTROL_UBER_LOSS_ALGORITHM_H_
+#define QUICHE_QUIC_CORE_CONGESTION_CONTROL_UBER_LOSS_ALGORITHM_H_
+
+#include "net/third_party/quiche/src/quic/core/congestion_control/general_loss_algorithm.h"
+
+namespace quic {
+
+// This class comprises multiple loss algorithms, each per packet number space.
+class QUIC_EXPORT_PRIVATE UberLossAlgorithm : public LossDetectionInterface {
+ public:
+ UberLossAlgorithm();
+ explicit UberLossAlgorithm(LossDetectionType loss_type);
+ UberLossAlgorithm(const UberLossAlgorithm&) = delete;
+ UberLossAlgorithm& operator=(const UberLossAlgorithm&) = delete;
+ ~UberLossAlgorithm() override {}
+
+ LossDetectionType GetLossDetectionType() const override;
+
+ // Switches the loss detection type to |loss_type| and resets loss algorithm
+ // for all packet number spaces.
+ void SetLossDetectionType(LossDetectionType loss_type);
+
+ // Detects lost packets.
+ void DetectLosses(const QuicUnackedPacketMap& unacked_packets,
+ QuicTime time,
+ const RttStats& rtt_stats,
+ QuicPacketNumber largest_newly_acked,
+ const AckedPacketVector& packets_acked,
+ LostPacketVector* packets_lost) override;
+
+ // Returns the earliest time the early retransmit timer should be active.
+ QuicTime GetLossTimeout() const override;
+
+ // Increases the loss detection threshold for time loss detection.
+ void SpuriousRetransmitDetected(
+ const QuicUnackedPacketMap& unacked_packets,
+ QuicTime time,
+ const RttStats& rtt_stats,
+ QuicPacketNumber spurious_retransmission) override;
+
+ private:
+ LossDetectionType loss_type_;
+ // One loss algorithm per packet number space.
+ GeneralLossAlgorithm general_loss_algorithms_[NUM_PACKET_NUMBER_SPACES];
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_CONGESTION_CONTROL_UBER_LOSS_ALGORITHM_H_
diff --git a/quic/core/congestion_control/uber_loss_algorithm_test.cc b/quic/core/congestion_control/uber_loss_algorithm_test.cc
new file mode 100644
index 0000000..9aa2041
--- /dev/null
+++ b/quic/core/congestion_control/uber_loss_algorithm_test.cc
@@ -0,0 +1,159 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/core/congestion_control/uber_loss_algorithm.h"
+
+#include "net/third_party/quiche/src/quic/core/congestion_control/rtt_stats.h"
+#include "net/third_party/quiche/src/quic/core/quic_utils.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+#include "net/third_party/quiche/src/quic/test_tools/mock_clock.h"
+#include "net/third_party/quiche/src/quic/test_tools/quic_unacked_packet_map_peer.h"
+
+namespace quic {
+namespace test {
+namespace {
+
+// Default packet length.
+const uint32_t kDefaultLength = 1000;
+
+class UberLossAlgorithmTest : public QuicTest {
+ protected:
+ UberLossAlgorithmTest() {
+ SetQuicReloadableFlag(quic_use_uber_loss_algorithm, true);
+ unacked_packets_ =
+ QuicMakeUnique<QuicUnackedPacketMap>(Perspective::IS_CLIENT);
+ rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(100),
+ QuicTime::Delta::Zero(), clock_.Now());
+ EXPECT_LT(0, rtt_stats_.smoothed_rtt().ToMicroseconds());
+ }
+
+ void SendPacket(uint64_t packet_number, EncryptionLevel encryption_level) {
+ QuicStreamFrame frame;
+ frame.stream_id =
+ encryption_level == ENCRYPTION_NONE
+ ? QuicUtils::GetCryptoStreamId(
+ CurrentSupportedVersions()[0].transport_version)
+ : QuicUtils::GetHeadersStreamId(
+ CurrentSupportedVersions()[0].transport_version);
+ SerializedPacket packet(QuicPacketNumber(packet_number),
+ PACKET_1BYTE_PACKET_NUMBER, nullptr, kDefaultLength,
+ false, false);
+ packet.encryption_level = encryption_level;
+ packet.retransmittable_frames.push_back(QuicFrame(frame));
+ unacked_packets_->AddSentPacket(&packet, QuicPacketNumber(),
+ NOT_RETRANSMISSION, clock_.Now(), true);
+ }
+
+ void AckPackets(const std::vector<uint64_t>& packets_acked) {
+ packets_acked_.clear();
+ for (uint64_t acked : packets_acked) {
+ unacked_packets_->RemoveFromInFlight(QuicPacketNumber(acked));
+ packets_acked_.push_back(AckedPacket(QuicPacketNumber(acked),
+ kMaxPacketSize, QuicTime::Zero()));
+ }
+ }
+
+ void VerifyLosses(uint64_t largest_newly_acked,
+ const AckedPacketVector& packets_acked,
+ const std::vector<uint64_t>& losses_expected) {
+ LostPacketVector lost_packets;
+ loss_algorithm_.DetectLosses(*unacked_packets_, clock_.Now(), rtt_stats_,
+ QuicPacketNumber(largest_newly_acked),
+ packets_acked, &lost_packets);
+ ASSERT_EQ(losses_expected.size(), lost_packets.size());
+ for (size_t i = 0; i < losses_expected.size(); ++i) {
+ EXPECT_EQ(lost_packets[i].packet_number,
+ QuicPacketNumber(losses_expected[i]));
+ }
+ }
+
+ MockClock clock_;
+ std::unique_ptr<QuicUnackedPacketMap> unacked_packets_;
+ RttStats rtt_stats_;
+ UberLossAlgorithm loss_algorithm_;
+ AckedPacketVector packets_acked_;
+};
+
+TEST_F(UberLossAlgorithmTest, ScenarioA) {
+ // This test mimics a scenario: client sends 1-CHLO, 2-0RTT, 3-0RTT,
+ // timeout and retransmits 4-CHLO. Server acks packet 1 (ack gets lost).
+ // Server receives and buffers packets 2 and 3. Server receives packet 4 and
+ // processes handshake asynchronously, so server acks 4 and cannot process
+ // packets 2 and 3.
+ SendPacket(1, ENCRYPTION_NONE);
+ SendPacket(2, ENCRYPTION_ZERO_RTT);
+ SendPacket(3, ENCRYPTION_ZERO_RTT);
+ unacked_packets_->RemoveFromInFlight(QuicPacketNumber(1));
+ SendPacket(4, ENCRYPTION_NONE);
+
+ AckPackets({1, 4});
+ unacked_packets_->MaybeUpdateLargestAckedOfPacketNumberSpace(
+ ENCRYPTION_NONE, QuicPacketNumber(4));
+ // Verify no packet is detected lost.
+ VerifyLosses(4, packets_acked_, std::vector<uint64_t>{});
+ EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
+}
+
+TEST_F(UberLossAlgorithmTest, ScenarioB) {
+ // This test mimics a scenario: client sends 3-0RTT, 4-0RTT, receives SHLO,
+ // sends 5-1RTT, 6-1RTT.
+ SendPacket(3, ENCRYPTION_ZERO_RTT);
+ SendPacket(4, ENCRYPTION_ZERO_RTT);
+ SendPacket(5, ENCRYPTION_FORWARD_SECURE);
+ SendPacket(6, ENCRYPTION_FORWARD_SECURE);
+
+ AckPackets({4});
+ unacked_packets_->MaybeUpdateLargestAckedOfPacketNumberSpace(
+ ENCRYPTION_ZERO_RTT, QuicPacketNumber(4));
+ // No packet loss by acking 4.
+ VerifyLosses(4, packets_acked_, std::vector<uint64_t>{});
+ EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
+
+ // Acking 6 causes 3 to be detected loss.
+ AckPackets({6});
+ unacked_packets_->MaybeUpdateLargestAckedOfPacketNumberSpace(
+ ENCRYPTION_FORWARD_SECURE, QuicPacketNumber(6));
+ VerifyLosses(6, packets_acked_, std::vector<uint64_t>{3});
+ EXPECT_EQ(clock_.Now() + 1.25 * rtt_stats_.smoothed_rtt(),
+ loss_algorithm_.GetLossTimeout());
+ packets_acked_.clear();
+
+ clock_.AdvanceTime(1.25 * rtt_stats_.latest_rtt());
+ // Verify 5 will be early retransmitted.
+ VerifyLosses(6, packets_acked_, {5});
+}
+
+TEST_F(UberLossAlgorithmTest, ScenarioC) {
+ // This test mimics a scenario: server sends 1-SHLO, 2-1RTT, 3-1RTT, 4-1RTT
+ // and retransmit 4-SHLO. Client receives and buffers packet 4. Client
+ // receives packet 5 and processes 4.
+ QuicUnackedPacketMapPeer::SetPerspective(unacked_packets_.get(),
+ Perspective::IS_SERVER);
+ SendPacket(1, ENCRYPTION_ZERO_RTT);
+ SendPacket(2, ENCRYPTION_FORWARD_SECURE);
+ SendPacket(3, ENCRYPTION_FORWARD_SECURE);
+ SendPacket(4, ENCRYPTION_FORWARD_SECURE);
+ unacked_packets_->RemoveFromInFlight(QuicPacketNumber(1));
+ SendPacket(5, ENCRYPTION_ZERO_RTT);
+
+ AckPackets({4, 5});
+ unacked_packets_->MaybeUpdateLargestAckedOfPacketNumberSpace(
+ ENCRYPTION_FORWARD_SECURE, QuicPacketNumber(4));
+ unacked_packets_->MaybeUpdateLargestAckedOfPacketNumberSpace(
+ ENCRYPTION_ZERO_RTT, QuicPacketNumber(5));
+ // No packet loss by acking 5.
+ VerifyLosses(5, packets_acked_, std::vector<uint64_t>{});
+ EXPECT_EQ(clock_.Now() + 1.25 * rtt_stats_.smoothed_rtt(),
+ loss_algorithm_.GetLossTimeout());
+ packets_acked_.clear();
+
+ clock_.AdvanceTime(1.25 * rtt_stats_.latest_rtt());
+ // Verify 2 and 3 will be early retransmitted.
+ VerifyLosses(5, packets_acked_, std::vector<uint64_t>{2, 3});
+}
+
+} // namespace
+} // namespace test
+} // namespace quic
diff --git a/quic/core/crypto/aead_base_decrypter.cc b/quic/core/crypto/aead_base_decrypter.cc
index 51cfa26..53bd0f0 100644
--- a/quic/core/crypto/aead_base_decrypter.cc
+++ b/quic/core/crypto/aead_base_decrypter.cc
@@ -141,8 +141,7 @@
return true;
}
-bool AeadBaseDecrypter::DecryptPacket(QuicTransportVersion /*version*/,
- uint64_t packet_number,
+bool AeadBaseDecrypter::DecryptPacket(uint64_t packet_number,
QuicStringPiece associated_data,
QuicStringPiece ciphertext,
char* output,
diff --git a/quic/core/crypto/aead_base_decrypter.h b/quic/core/crypto/aead_base_decrypter.h
index b4906b8..d374722 100644
--- a/quic/core/crypto/aead_base_decrypter.h
+++ b/quic/core/crypto/aead_base_decrypter.h
@@ -35,8 +35,7 @@
bool SetIV(QuicStringPiece iv) override;
bool SetPreliminaryKey(QuicStringPiece key) override;
bool SetDiversificationNonce(const DiversificationNonce& nonce) override;
- bool DecryptPacket(QuicTransportVersion version,
- uint64_t packet_number,
+ bool DecryptPacket(uint64_t packet_number,
QuicStringPiece associated_data,
QuicStringPiece ciphertext,
char* output,
diff --git a/quic/core/crypto/aead_base_encrypter.cc b/quic/core/crypto/aead_base_encrypter.cc
index 199851e..405292e 100644
--- a/quic/core/crypto/aead_base_encrypter.cc
+++ b/quic/core/crypto/aead_base_encrypter.cc
@@ -123,8 +123,7 @@
return true;
}
-bool AeadBaseEncrypter::EncryptPacket(QuicTransportVersion /*version*/,
- uint64_t packet_number,
+bool AeadBaseEncrypter::EncryptPacket(uint64_t packet_number,
QuicStringPiece associated_data,
QuicStringPiece plaintext,
char* output,
diff --git a/quic/core/crypto/aead_base_encrypter.h b/quic/core/crypto/aead_base_encrypter.h
index 255bd87..316d24e 100644
--- a/quic/core/crypto/aead_base_encrypter.h
+++ b/quic/core/crypto/aead_base_encrypter.h
@@ -33,8 +33,7 @@
bool SetKey(QuicStringPiece key) override;
bool SetNoncePrefix(QuicStringPiece nonce_prefix) override;
bool SetIV(QuicStringPiece iv) override;
- bool EncryptPacket(QuicTransportVersion version,
- uint64_t packet_number,
+ bool EncryptPacket(uint64_t packet_number,
QuicStringPiece associated_data,
QuicStringPiece plaintext,
char* output,
diff --git a/quic/core/crypto/aes_128_gcm_12_decrypter_test.cc b/quic/core/crypto/aes_128_gcm_12_decrypter_test.cc
index eb2fa5e..6513e45 100644
--- a/quic/core/crypto/aes_128_gcm_12_decrypter_test.cc
+++ b/quic/core/crypto/aes_128_gcm_12_decrypter_test.cc
@@ -212,8 +212,8 @@
std::unique_ptr<char[]> output(new char[ciphertext.length()]);
size_t output_length = 0;
const bool success = decrypter->DecryptPacket(
- QuicTransportVersionMax(), packet_number, associated_data, ciphertext,
- output.get(), &output_length, ciphertext.length());
+ packet_number, associated_data, ciphertext, output.get(), &output_length,
+ ciphertext.length());
if (!success) {
return nullptr;
}
diff --git a/quic/core/crypto/aes_128_gcm_decrypter_test.cc b/quic/core/crypto/aes_128_gcm_decrypter_test.cc
index ef66204..300e8a2 100644
--- a/quic/core/crypto/aes_128_gcm_decrypter_test.cc
+++ b/quic/core/crypto/aes_128_gcm_decrypter_test.cc
@@ -206,9 +206,9 @@
decrypter->SetIV(nonce);
std::unique_ptr<char[]> output(new char[ciphertext.length()]);
size_t output_length = 0;
- const bool success = decrypter->DecryptPacket(
- QuicTransportVersionMax(), 0, associated_data, ciphertext, output.get(),
- &output_length, ciphertext.length());
+ const bool success =
+ decrypter->DecryptPacket(0, associated_data, ciphertext, output.get(),
+ &output_length, ciphertext.length());
if (!success) {
return nullptr;
}
diff --git a/quic/core/crypto/aes_128_gcm_encrypter_test.cc b/quic/core/crypto/aes_128_gcm_encrypter_test.cc
index 79276ca..959cb9d 100644
--- a/quic/core/crypto/aes_128_gcm_encrypter_test.cc
+++ b/quic/core/crypto/aes_128_gcm_encrypter_test.cc
@@ -233,8 +233,8 @@
Aes128GcmEncrypter encrypter;
ASSERT_TRUE(encrypter.SetKey(key));
ASSERT_TRUE(encrypter.SetIV(iv));
- ASSERT_TRUE(encrypter.EncryptPacket(QUIC_VERSION_43, packet_num, aad, pt,
- out.data(), &out_size, out.size()));
+ ASSERT_TRUE(encrypter.EncryptPacket(packet_num, aad, pt, out.data(),
+ &out_size, out.size()));
EXPECT_EQ(out_size, out.size());
test::CompareCharArraysWithHexError("ciphertext", out.data(), out.size(),
ct.data(), ct.size());
diff --git a/quic/core/crypto/aes_256_gcm_decrypter_test.cc b/quic/core/crypto/aes_256_gcm_decrypter_test.cc
index b25b66b..cb5f702 100644
--- a/quic/core/crypto/aes_256_gcm_decrypter_test.cc
+++ b/quic/core/crypto/aes_256_gcm_decrypter_test.cc
@@ -210,9 +210,9 @@
decrypter->SetIV(nonce);
std::unique_ptr<char[]> output(new char[ciphertext.length()]);
size_t output_length = 0;
- const bool success = decrypter->DecryptPacket(
- QuicTransportVersionMax(), 0, associated_data, ciphertext, output.get(),
- &output_length, ciphertext.length());
+ const bool success =
+ decrypter->DecryptPacket(0, associated_data, ciphertext, output.get(),
+ &output_length, ciphertext.length());
if (!success) {
return nullptr;
}
diff --git a/quic/core/crypto/chacha20_poly1305_decrypter_test.cc b/quic/core/crypto/chacha20_poly1305_decrypter_test.cc
index a0c3cbe..5f5ae01 100644
--- a/quic/core/crypto/chacha20_poly1305_decrypter_test.cc
+++ b/quic/core/crypto/chacha20_poly1305_decrypter_test.cc
@@ -125,8 +125,8 @@
std::unique_ptr<char[]> output(new char[ciphertext.length()]);
size_t output_length = 0;
const bool success = decrypter->DecryptPacket(
- QuicTransportVersionMax(), packet_number, associated_data, ciphertext,
- output.get(), &output_length, ciphertext.length());
+ packet_number, associated_data, ciphertext, output.get(), &output_length,
+ ciphertext.length());
if (!success) {
return nullptr;
}
diff --git a/quic/core/crypto/chacha20_poly1305_encrypter_test.cc b/quic/core/crypto/chacha20_poly1305_encrypter_test.cc
index 8d9a900..d8c27bf 100644
--- a/quic/core/crypto/chacha20_poly1305_encrypter_test.cc
+++ b/quic/core/crypto/chacha20_poly1305_encrypter_test.cc
@@ -101,14 +101,14 @@
QuicString plaintext = "plaintext";
char encrypted[1024];
size_t len;
- ASSERT_TRUE(encrypter.EncryptPacket(QuicTransportVersionMax(), packet_number,
- associated_data, plaintext, encrypted,
- &len, QUIC_ARRAYSIZE(encrypted)));
+ ASSERT_TRUE(encrypter.EncryptPacket(packet_number, associated_data, plaintext,
+ encrypted, &len,
+ QUIC_ARRAYSIZE(encrypted)));
QuicStringPiece ciphertext(encrypted, len);
char decrypted[1024];
- ASSERT_TRUE(decrypter.DecryptPacket(QuicTransportVersionMax(), packet_number,
- associated_data, ciphertext, decrypted,
- &len, QUIC_ARRAYSIZE(decrypted)));
+ ASSERT_TRUE(decrypter.DecryptPacket(packet_number, associated_data,
+ ciphertext, decrypted, &len,
+ QUIC_ARRAYSIZE(decrypted)));
}
TEST_F(ChaCha20Poly1305EncrypterTest, Encrypt) {
diff --git a/quic/core/crypto/chacha20_poly1305_tls_decrypter_test.cc b/quic/core/crypto/chacha20_poly1305_tls_decrypter_test.cc
index 824c2dd..dd74539 100644
--- a/quic/core/crypto/chacha20_poly1305_tls_decrypter_test.cc
+++ b/quic/core/crypto/chacha20_poly1305_tls_decrypter_test.cc
@@ -119,9 +119,9 @@
decrypter->SetIV(nonce);
std::unique_ptr<char[]> output(new char[ciphertext.length()]);
size_t output_length = 0;
- const bool success = decrypter->DecryptPacket(
- QuicTransportVersionMax(), 0, associated_data, ciphertext, output.get(),
- &output_length, ciphertext.length());
+ const bool success =
+ decrypter->DecryptPacket(0, associated_data, ciphertext, output.get(),
+ &output_length, ciphertext.length());
if (!success) {
return nullptr;
}
diff --git a/quic/core/crypto/chacha20_poly1305_tls_encrypter_test.cc b/quic/core/crypto/chacha20_poly1305_tls_encrypter_test.cc
index bc7c6c4..905472b 100644
--- a/quic/core/crypto/chacha20_poly1305_tls_encrypter_test.cc
+++ b/quic/core/crypto/chacha20_poly1305_tls_encrypter_test.cc
@@ -100,14 +100,14 @@
QuicString plaintext = "plaintext";
char encrypted[1024];
size_t len;
- ASSERT_TRUE(encrypter.EncryptPacket(QuicTransportVersionMax(), packet_number,
- associated_data, plaintext, encrypted,
- &len, QUIC_ARRAYSIZE(encrypted)));
+ ASSERT_TRUE(encrypter.EncryptPacket(packet_number, associated_data, plaintext,
+ encrypted, &len,
+ QUIC_ARRAYSIZE(encrypted)));
QuicStringPiece ciphertext(encrypted, len);
char decrypted[1024];
- ASSERT_TRUE(decrypter.DecryptPacket(QuicTransportVersionMax(), packet_number,
- associated_data, ciphertext, decrypted,
- &len, QUIC_ARRAYSIZE(decrypted)));
+ ASSERT_TRUE(decrypter.DecryptPacket(packet_number, associated_data,
+ ciphertext, decrypted, &len,
+ QUIC_ARRAYSIZE(decrypted)));
}
TEST_F(ChaCha20Poly1305TlsEncrypterTest, Encrypt) {
diff --git a/quic/core/crypto/crypto_message_printer_bin.cc b/quic/core/crypto/crypto_message_printer_bin.cc
index f70c1c2..f14abb0 100644
--- a/quic/core/crypto/crypto_message_printer_bin.cc
+++ b/quic/core/crypto/crypto_message_printer_bin.cc
@@ -1,3 +1,7 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
// Dumps the contents of a QUIC crypto handshake message in a human readable
// format.
//
diff --git a/quic/core/crypto/crypto_protocol.h b/quic/core/crypto/crypto_protocol.h
index 5795119..b6a1e90 100644
--- a/quic/core/crypto/crypto_protocol.h
+++ b/quic/core/crypto/crypto_protocol.h
@@ -261,9 +261,6 @@
// Universal tags
const QuicTag kPAD = TAG('P', 'A', 'D', '\0'); // Padding
-// Server push tags
-const QuicTag kSPSH = TAG('S', 'P', 'S', 'H'); // Support server push.
-
// Stats collection tags
const QuicTag kEPID = TAG('E', 'P', 'I', 'D'); // Endpoint identifier.
diff --git a/quic/core/crypto/crypto_server_test.cc b/quic/core/crypto/crypto_server_test.cc
index c2c4041..4ed169e 100644
--- a/quic/core/crypto/crypto_server_test.cc
+++ b/quic/core/crypto/crypto_server_test.cc
@@ -236,7 +236,7 @@
void ShouldSucceed(const CryptoHandshakeMessage& message) {
bool called = false;
- QuicSocketAddress server_address;
+ QuicSocketAddress server_address(QuicIpAddress::Any4(), 5);
config_.ValidateClientHello(
message, client_address_.host(), server_address,
supported_versions_.front().transport_version, &clock_, signed_config_,
@@ -254,7 +254,7 @@
void ShouldFailMentioning(const char* error_substr,
const CryptoHandshakeMessage& message,
bool* called) {
- QuicSocketAddress server_address;
+ QuicSocketAddress server_address(QuicIpAddress::Any4(), 5);
config_.ValidateClientHello(
message, client_address_.host(), server_address,
supported_versions_.front().transport_version, &clock_, signed_config_,
@@ -312,7 +312,7 @@
QuicReferenceCountedPointer<ValidateCallback::Result> result,
bool should_succeed,
const char* error_substr) {
- QuicSocketAddress server_address;
+ QuicSocketAddress server_address(QuicIpAddress::Any4(), 5);
QuicConnectionId server_designated_connection_id =
TestConnectionId(rand_for_id_generation_.RandUint64());
bool called;
@@ -415,9 +415,8 @@
std::unique_ptr<CryptoHandshakeMessage> server_config_;
};
-INSTANTIATE_TEST_CASE_P(CryptoServerTests,
- CryptoServerTest,
- ::testing::ValuesIn(GetTestParams()));
+INSTANTIATE_TEST_SUITE_P(CryptoServerTests, CryptoServerTest,
+ ::testing::ValuesIn(GetTestParams()));
TEST_P(CryptoServerTest, BadSNI) {
// clang-format off
diff --git a/quic/core/crypto/crypto_utils.cc b/quic/core/crypto/crypto_utils.cc
index 46d172f..4f6a61d 100644
--- a/quic/core/crypto/crypto_utils.cc
+++ b/quic/core/crypto/crypto_utils.cc
@@ -107,24 +107,10 @@
std::vector<uint8_t> handshake_secret;
handshake_secret.resize(EVP_MAX_MD_SIZE);
size_t handshake_secret_len;
- bool hkdf_extract_success;
- if (!QuicConnectionIdSupportsVariableLength(perspective)) {
- uint64_t connection_id64 = QuicConnectionIdToUInt64(connection_id);
- uint8_t connection_id_bytes[sizeof(connection_id64)];
- for (size_t i = 0; i < sizeof(connection_id64); ++i) {
- connection_id_bytes[i] =
- (connection_id64 >> ((sizeof(connection_id64) - i - 1) * 8)) & 0xff;
- }
- hkdf_extract_success =
- HKDF_extract(handshake_secret.data(), &handshake_secret_len, hash,
- connection_id_bytes, QUIC_ARRAYSIZE(connection_id_bytes),
- kInitialSalt, QUIC_ARRAYSIZE(kInitialSalt));
- } else {
- hkdf_extract_success = HKDF_extract(
- handshake_secret.data(), &handshake_secret_len, hash,
- reinterpret_cast<const uint8_t*>(connection_id.data()),
- connection_id.length(), kInitialSalt, QUIC_ARRAYSIZE(kInitialSalt));
- }
+ const bool hkdf_extract_success = HKDF_extract(
+ handshake_secret.data(), &handshake_secret_len, hash,
+ reinterpret_cast<const uint8_t*>(connection_id.data()),
+ connection_id.length(), kInitialSalt, QUIC_ARRAYSIZE(kInitialSalt));
QUIC_BUG_IF(!hkdf_extract_success)
<< "HKDF_extract failed when creating initial crypters";
handshake_secret.resize(handshake_secret_len);
diff --git a/quic/core/crypto/null_decrypter.cc b/quic/core/crypto/null_decrypter.cc
index 0c108b6..288d3c4 100644
--- a/quic/core/crypto/null_decrypter.cc
+++ b/quic/core/crypto/null_decrypter.cc
@@ -38,8 +38,7 @@
return true;
}
-bool NullDecrypter::DecryptPacket(QuicTransportVersion version,
- uint64_t /*packet_number*/,
+bool NullDecrypter::DecryptPacket(uint64_t /*packet_number*/,
QuicStringPiece associated_data,
QuicStringPiece ciphertext,
char* output,
@@ -58,7 +57,7 @@
QUIC_BUG << "Output buffer must be larger than the plaintext.";
return false;
}
- if (hash != ComputeHash(version, associated_data, plaintext)) {
+ if (hash != ComputeHash(associated_data, plaintext)) {
return false;
}
// Copy the plaintext to output.
@@ -97,21 +96,15 @@
return true;
}
-QuicUint128 NullDecrypter::ComputeHash(QuicTransportVersion version,
- const QuicStringPiece data1,
+QuicUint128 NullDecrypter::ComputeHash(const QuicStringPiece data1,
const QuicStringPiece data2) const {
QuicUint128 correct_hash;
- if (version > QUIC_VERSION_35) {
- if (perspective_ == Perspective::IS_CLIENT) {
- // Peer is a server.
- correct_hash = QuicUtils::FNV1a_128_Hash_Three(data1, data2, "Server");
-
- } else {
- // Peer is a client.
- correct_hash = QuicUtils::FNV1a_128_Hash_Three(data1, data2, "Client");
- }
+ if (perspective_ == Perspective::IS_CLIENT) {
+ // Peer is a server.
+ correct_hash = QuicUtils::FNV1a_128_Hash_Three(data1, data2, "Server");
} else {
- correct_hash = QuicUtils::FNV1a_128_Hash_Two(data1, data2);
+ // Peer is a client.
+ correct_hash = QuicUtils::FNV1a_128_Hash_Three(data1, data2, "Client");
}
QuicUint128 mask = MakeQuicUint128(UINT64_C(0x0), UINT64_C(0xffffffff));
mask <<= 96;
diff --git a/quic/core/crypto/null_decrypter.h b/quic/core/crypto/null_decrypter.h
index 3996eb7..8381987 100644
--- a/quic/core/crypto/null_decrypter.h
+++ b/quic/core/crypto/null_decrypter.h
@@ -35,8 +35,7 @@
bool SetIV(QuicStringPiece iv) override;
bool SetPreliminaryKey(QuicStringPiece key) override;
bool SetDiversificationNonce(const DiversificationNonce& nonce) override;
- bool DecryptPacket(QuicTransportVersion version,
- uint64_t packet_number,
+ bool DecryptPacket(uint64_t packet_number,
QuicStringPiece associated_data,
QuicStringPiece ciphertext,
char* output,
@@ -51,9 +50,7 @@
private:
bool ReadHash(QuicDataReader* reader, QuicUint128* hash);
- QuicUint128 ComputeHash(QuicTransportVersion version,
- QuicStringPiece data1,
- QuicStringPiece data2) const;
+ QuicUint128 ComputeHash(QuicStringPiece data1, QuicStringPiece data2) const;
Perspective perspective_;
};
diff --git a/quic/core/crypto/null_decrypter_test.cc b/quic/core/crypto/null_decrypter_test.cc
index dd62a5c..09b1aaf 100644
--- a/quic/core/crypto/null_decrypter_test.cc
+++ b/quic/core/crypto/null_decrypter_test.cc
@@ -15,18 +15,35 @@
TEST_F(NullDecrypterTest, DecryptClient) {
unsigned char expected[] = {
// fnv hash
- 0x97, 0xdc, 0x27, 0x2f, 0x18, 0xa8, 0x56, 0x73, 0xdf, 0x8d, 0x1d, 0xd0,
+ 0x97,
+ 0xdc,
+ 0x27,
+ 0x2f,
+ 0x18,
+ 0xa8,
+ 0x56,
+ 0x73,
+ 0xdf,
+ 0x8d,
+ 0x1d,
+ 0xd0,
// payload
- 'g', 'o', 'o', 'd', 'b', 'y', 'e', '!',
+ 'g',
+ 'o',
+ 'o',
+ 'd',
+ 'b',
+ 'y',
+ 'e',
+ '!',
};
const char* data = reinterpret_cast<const char*>(expected);
size_t len = QUIC_ARRAYSIZE(expected);
NullDecrypter decrypter(Perspective::IS_SERVER);
char buffer[256];
size_t length = 0;
- ASSERT_TRUE(decrypter.DecryptPacket(QUIC_VERSION_39, 0, "hello world!",
- QuicStringPiece(data, len), buffer,
- &length, 256));
+ ASSERT_TRUE(decrypter.DecryptPacket(
+ 0, "hello world!", QuicStringPiece(data, len), buffer, &length, 256));
EXPECT_LT(0u, length);
EXPECT_EQ("goodbye!", QuicStringPiece(buffer, length));
}
@@ -34,56 +51,35 @@
TEST_F(NullDecrypterTest, DecryptServer) {
unsigned char expected[] = {
// fnv hash
- 0x63, 0x5e, 0x08, 0x03, 0x32, 0x80, 0x8f, 0x73, 0xdf, 0x8d, 0x1d, 0x1a,
+ 0x63,
+ 0x5e,
+ 0x08,
+ 0x03,
+ 0x32,
+ 0x80,
+ 0x8f,
+ 0x73,
+ 0xdf,
+ 0x8d,
+ 0x1d,
+ 0x1a,
// payload
- 'g', 'o', 'o', 'd', 'b', 'y', 'e', '!',
+ 'g',
+ 'o',
+ 'o',
+ 'd',
+ 'b',
+ 'y',
+ 'e',
+ '!',
};
const char* data = reinterpret_cast<const char*>(expected);
size_t len = QUIC_ARRAYSIZE(expected);
NullDecrypter decrypter(Perspective::IS_CLIENT);
char buffer[256];
size_t length = 0;
- ASSERT_TRUE(decrypter.DecryptPacket(QUIC_VERSION_39, 0, "hello world!",
- QuicStringPiece(data, len), buffer,
- &length, 256));
- EXPECT_LT(0u, length);
- EXPECT_EQ("goodbye!", QuicStringPiece(buffer, length));
-}
-
-TEST_F(NullDecrypterTest, DecryptClientPre37) {
- unsigned char expected[] = {
- // fnv hash
- 0xa0, 0x6f, 0x44, 0x8a, 0x44, 0xf8, 0x18, 0x3b, 0x47, 0x91, 0xb2, 0x13,
- // payload
- 'g', 'o', 'o', 'd', 'b', 'y', 'e', '!',
- };
- const char* data = reinterpret_cast<const char*>(expected);
- size_t len = QUIC_ARRAYSIZE(expected);
- NullDecrypter decrypter(Perspective::IS_CLIENT);
- char buffer[256];
- size_t length = 0;
- ASSERT_TRUE(decrypter.DecryptPacket(QUIC_VERSION_35, 0, "hello world!",
- QuicStringPiece(data, len), buffer,
- &length, 256));
- EXPECT_LT(0u, length);
- EXPECT_EQ("goodbye!", QuicStringPiece(buffer, length));
-}
-
-TEST_F(NullDecrypterTest, DecryptServerPre37) {
- unsigned char expected[] = {
- // fnv hash
- 0xa0, 0x6f, 0x44, 0x8a, 0x44, 0xf8, 0x18, 0x3b, 0x47, 0x91, 0xb2, 0x13,
- // payload
- 'g', 'o', 'o', 'd', 'b', 'y', 'e', '!',
- };
- const char* data = reinterpret_cast<const char*>(expected);
- size_t len = QUIC_ARRAYSIZE(expected);
- NullDecrypter decrypter(Perspective::IS_SERVER);
- char buffer[256];
- size_t length = 0;
- ASSERT_TRUE(decrypter.DecryptPacket(QUIC_VERSION_35, 0, "hello world!",
- QuicStringPiece(data, len), buffer,
- &length, 256));
+ ASSERT_TRUE(decrypter.DecryptPacket(
+ 0, "hello world!", QuicStringPiece(data, len), buffer, &length, 256));
EXPECT_LT(0u, length);
EXPECT_EQ("goodbye!", QuicStringPiece(buffer, length));
}
@@ -91,18 +87,35 @@
TEST_F(NullDecrypterTest, BadHash) {
unsigned char expected[] = {
// fnv hash
- 0x46, 0x11, 0xea, 0x5f, 0xcf, 0x1d, 0x66, 0x5b, 0xba, 0xf0, 0xbc, 0xfd,
+ 0x46,
+ 0x11,
+ 0xea,
+ 0x5f,
+ 0xcf,
+ 0x1d,
+ 0x66,
+ 0x5b,
+ 0xba,
+ 0xf0,
+ 0xbc,
+ 0xfd,
// payload
- 'g', 'o', 'o', 'd', 'b', 'y', 'e', '!',
+ 'g',
+ 'o',
+ 'o',
+ 'd',
+ 'b',
+ 'y',
+ 'e',
+ '!',
};
const char* data = reinterpret_cast<const char*>(expected);
size_t len = QUIC_ARRAYSIZE(expected);
NullDecrypter decrypter(Perspective::IS_CLIENT);
char buffer[256];
size_t length = 0;
- ASSERT_FALSE(decrypter.DecryptPacket(QUIC_VERSION_35, 0, "hello world!",
- QuicStringPiece(data, len), buffer,
- &length, 256));
+ ASSERT_FALSE(decrypter.DecryptPacket(
+ 0, "hello world!", QuicStringPiece(data, len), buffer, &length, 256));
}
TEST_F(NullDecrypterTest, ShortInput) {
@@ -115,9 +128,8 @@
NullDecrypter decrypter(Perspective::IS_CLIENT);
char buffer[256];
size_t length = 0;
- ASSERT_FALSE(decrypter.DecryptPacket(QUIC_VERSION_35, 0, "hello world!",
- QuicStringPiece(data, len), buffer,
- &length, 256));
+ ASSERT_FALSE(decrypter.DecryptPacket(
+ 0, "hello world!", QuicStringPiece(data, len), buffer, &length, 256));
}
} // namespace test
diff --git a/quic/core/crypto/null_encrypter.cc b/quic/core/crypto/null_encrypter.cc
index e4a165f..9819a31 100644
--- a/quic/core/crypto/null_encrypter.cc
+++ b/quic/core/crypto/null_encrypter.cc
@@ -26,8 +26,7 @@
return iv.empty();
}
-bool NullEncrypter::EncryptPacket(QuicTransportVersion version,
- uint64_t /*packet_number*/,
+bool NullEncrypter::EncryptPacket(uint64_t /*packet_number*/,
QuicStringPiece associated_data,
QuicStringPiece plaintext,
char* output,
@@ -38,16 +37,12 @@
return false;
}
QuicUint128 hash;
- if (version > QUIC_VERSION_35) {
- if (perspective_ == Perspective::IS_SERVER) {
- hash =
- QuicUtils::FNV1a_128_Hash_Three(associated_data, plaintext, "Server");
- } else {
- hash =
- QuicUtils::FNV1a_128_Hash_Three(associated_data, plaintext, "Client");
- }
+ if (perspective_ == Perspective::IS_SERVER) {
+ hash =
+ QuicUtils::FNV1a_128_Hash_Three(associated_data, plaintext, "Server");
} else {
- hash = QuicUtils::FNV1a_128_Hash_Two(associated_data, plaintext);
+ hash =
+ QuicUtils::FNV1a_128_Hash_Three(associated_data, plaintext, "Client");
}
// TODO(ianswett): memmove required for in place encryption. Placing the
// hash at the end would allow use of memcpy, doing nothing for in place.
diff --git a/quic/core/crypto/null_encrypter.h b/quic/core/crypto/null_encrypter.h
index 01ecd45..fe4487d 100644
--- a/quic/core/crypto/null_encrypter.h
+++ b/quic/core/crypto/null_encrypter.h
@@ -29,8 +29,7 @@
bool SetKey(QuicStringPiece key) override;
bool SetNoncePrefix(QuicStringPiece nonce_prefix) override;
bool SetIV(QuicStringPiece iv) override;
- bool EncryptPacket(QuicTransportVersion version,
- uint64_t packet_number,
+ bool EncryptPacket(uint64_t packet_number,
QuicStringPiece associated_data,
QuicStringPiece plaintext,
char* output,
diff --git a/quic/core/crypto/null_encrypter_test.cc b/quic/core/crypto/null_encrypter_test.cc
index 6dd4c98..fd95cc6 100644
--- a/quic/core/crypto/null_encrypter_test.cc
+++ b/quic/core/crypto/null_encrypter_test.cc
@@ -15,16 +15,33 @@
TEST_F(NullEncrypterTest, EncryptClient) {
unsigned char expected[] = {
// fnv hash
- 0x97, 0xdc, 0x27, 0x2f, 0x18, 0xa8, 0x56, 0x73, 0xdf, 0x8d, 0x1d, 0xd0,
+ 0x97,
+ 0xdc,
+ 0x27,
+ 0x2f,
+ 0x18,
+ 0xa8,
+ 0x56,
+ 0x73,
+ 0xdf,
+ 0x8d,
+ 0x1d,
+ 0xd0,
// payload
- 'g', 'o', 'o', 'd', 'b', 'y', 'e', '!',
+ 'g',
+ 'o',
+ 'o',
+ 'd',
+ 'b',
+ 'y',
+ 'e',
+ '!',
};
char encrypted[256];
size_t encrypted_len = 0;
NullEncrypter encrypter(Perspective::IS_CLIENT);
- ASSERT_TRUE(encrypter.EncryptPacket(QUIC_VERSION_39, 0, "hello world!",
- "goodbye!", encrypted, &encrypted_len,
- 256));
+ ASSERT_TRUE(encrypter.EncryptPacket(0, "hello world!", "goodbye!", encrypted,
+ &encrypted_len, 256));
test::CompareCharArraysWithHexError(
"encrypted data", encrypted, encrypted_len,
reinterpret_cast<const char*>(expected), QUIC_ARRAYSIZE(expected));
@@ -33,52 +50,33 @@
TEST_F(NullEncrypterTest, EncryptServer) {
unsigned char expected[] = {
// fnv hash
- 0x63, 0x5e, 0x08, 0x03, 0x32, 0x80, 0x8f, 0x73, 0xdf, 0x8d, 0x1d, 0x1a,
+ 0x63,
+ 0x5e,
+ 0x08,
+ 0x03,
+ 0x32,
+ 0x80,
+ 0x8f,
+ 0x73,
+ 0xdf,
+ 0x8d,
+ 0x1d,
+ 0x1a,
// payload
- 'g', 'o', 'o', 'd', 'b', 'y', 'e', '!',
+ 'g',
+ 'o',
+ 'o',
+ 'd',
+ 'b',
+ 'y',
+ 'e',
+ '!',
};
char encrypted[256];
size_t encrypted_len = 0;
NullEncrypter encrypter(Perspective::IS_SERVER);
- ASSERT_TRUE(encrypter.EncryptPacket(QUIC_VERSION_39, 0, "hello world!",
- "goodbye!", encrypted, &encrypted_len,
- 256));
- test::CompareCharArraysWithHexError(
- "encrypted data", encrypted, encrypted_len,
- reinterpret_cast<const char*>(expected), QUIC_ARRAYSIZE(expected));
-}
-
-TEST_F(NullEncrypterTest, EncryptClientPre37) {
- unsigned char expected[] = {
- // fnv hash
- 0xa0, 0x6f, 0x44, 0x8a, 0x44, 0xf8, 0x18, 0x3b, 0x47, 0x91, 0xb2, 0x13,
- // payload
- 'g', 'o', 'o', 'd', 'b', 'y', 'e', '!',
- };
- char encrypted[256];
- size_t encrypted_len = 0;
- NullEncrypter encrypter(Perspective::IS_CLIENT);
- ASSERT_TRUE(encrypter.EncryptPacket(QUIC_VERSION_35, 0, "hello world!",
- "goodbye!", encrypted, &encrypted_len,
- 256));
- test::CompareCharArraysWithHexError(
- "encrypted data", encrypted, encrypted_len,
- reinterpret_cast<const char*>(expected), QUIC_ARRAYSIZE(expected));
-}
-
-TEST_F(NullEncrypterTest, EncryptServerPre37) {
- unsigned char expected[] = {
- // fnv hash
- 0xa0, 0x6f, 0x44, 0x8a, 0x44, 0xf8, 0x18, 0x3b, 0x47, 0x91, 0xb2, 0x13,
- // payload
- 'g', 'o', 'o', 'd', 'b', 'y', 'e', '!',
- };
- char encrypted[256];
- size_t encrypted_len = 0;
- NullEncrypter encrypter(Perspective::IS_SERVER);
- ASSERT_TRUE(encrypter.EncryptPacket(QUIC_VERSION_35, 0, "hello world!",
- "goodbye!", encrypted, &encrypted_len,
- 256));
+ ASSERT_TRUE(encrypter.EncryptPacket(0, "hello world!", "goodbye!", encrypted,
+ &encrypted_len, 256));
test::CompareCharArraysWithHexError(
"encrypted data", encrypted, encrypted_len,
reinterpret_cast<const char*>(expected), QUIC_ARRAYSIZE(expected));
diff --git a/quic/core/crypto/quic_crypto_client_config.cc b/quic/core/crypto/quic_crypto_client_config.cc
index 56447bb..0bf1b41 100644
--- a/quic/core/crypto/quic_crypto_client_config.cc
+++ b/quic/core/crypto/quic_crypto_client_config.cc
@@ -657,14 +657,7 @@
const QuicData& client_hello_serialized = out->GetSerialized();
hkdf_input.append(QuicCryptoConfig::kCETVLabel,
strlen(QuicCryptoConfig::kCETVLabel) + 1);
- if (!QuicConnectionIdSupportsVariableLength(Perspective::IS_CLIENT)) {
- const uint64_t connection_id64_net =
- QuicEndian::HostToNet64(QuicConnectionIdToUInt64(connection_id));
- hkdf_input.append(reinterpret_cast<const char*>(&connection_id64_net),
- sizeof(connection_id64_net));
- } else {
hkdf_input.append(connection_id.data(), connection_id.length());
- }
hkdf_input.append(client_hello_serialized.data(),
client_hello_serialized.length());
hkdf_input.append(cached->server_config());
@@ -696,8 +689,7 @@
std::unique_ptr<char[]> output(new char[encrypted_len]);
size_t output_size = 0;
if (!crypters.encrypter->EncryptPacket(
- preferred_version.transport_version, 0 /* packet number */,
- QuicStringPiece() /* associated data */,
+ 0 /* packet number */, QuicStringPiece() /* associated data */,
cetv_plaintext.AsStringPiece(), output.get(), &output_size,
encrypted_len)) {
*error_details = "Packet encryption failed";
@@ -715,16 +707,8 @@
// out_params->hkdf_input_suffix
// out_params->initial_crypters
out_params->hkdf_input_suffix.clear();
- if (!QuicConnectionIdSupportsVariableLength(Perspective::IS_CLIENT)) {
- const uint64_t connection_id64_net =
- QuicEndian::HostToNet64(QuicConnectionIdToUInt64(connection_id));
- out_params->hkdf_input_suffix.append(
- reinterpret_cast<const char*>(&connection_id64_net),
- sizeof(connection_id64_net));
- } else {
out_params->hkdf_input_suffix.append(connection_id.data(),
connection_id.length());
- }
const QuicData& client_hello_serialized = out->GetSerialized();
out_params->hkdf_input_suffix.append(client_hello_serialized.data(),
client_hello_serialized.length());
@@ -857,15 +841,7 @@
if (rej.tag() == kSREJ) {
QuicConnectionId connection_id;
- if (!QuicConnectionIdSupportsVariableLength(Perspective::IS_CLIENT)) {
- uint64_t connection_id64;
- if (rej.GetUint64(kRCID, &connection_id64) != QUIC_NO_ERROR) {
- *error_details = "Missing kRCID";
- return QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND;
- }
- connection_id64 = QuicEndian::NetToHost64(connection_id64);
- connection_id = QuicConnectionIdFromUInt64(connection_id64);
- } else {
+
QuicStringPiece connection_id_bytes;
if (!rej.GetStringPiece(kRCID, &connection_id_bytes)) {
*error_details = "Missing kRCID";
@@ -880,7 +856,6 @@
*error_details = "Bad kRCID length";
return QUIC_CRYPTO_INTERNAL_ERROR;
}
- }
cached->add_server_designated_connection_id(connection_id);
if (!nonce.empty()) {
cached->add_server_nonce(QuicString(nonce));
diff --git a/quic/core/crypto/quic_crypto_server_config.cc b/quic/core/crypto/quic_crypto_server_config.cc
index 851f8e3..af67166 100644
--- a/quic/core/crypto/quic_crypto_server_config.cc
+++ b/quic/core/crypto/quic_crypto_server_config.cc
@@ -77,7 +77,7 @@
std::unique_ptr<KeyExchange> Create(QuicString /*server_config_id*/,
QuicTag type,
- QuicStringPiece private_key) {
+ QuicStringPiece private_key) override {
if (private_key.empty()) {
QUIC_LOG(WARNING) << "Server config contains key exchange method without "
"corresponding private key: "
@@ -876,10 +876,6 @@
<< "ProcessClientHelloAfterGetProof: attempted to use connection ID "
<< connection_id << " which is invalid with version "
<< QuicVersionToString(version.transport_version);
- if (!QuicConnectionIdSupportsVariableLength(Perspective::IS_SERVER)) {
- connection_id = QuicConnectionIdFromUInt64(
- QuicEndian::HostToNet64(QuicConnectionIdToUInt64(connection_id)));
- }
ProcessClientHelloHelper helper(&done_cb);
if (found_error) {
@@ -1020,21 +1016,10 @@
QuicString hkdf_suffix;
const QuicData& client_hello_serialized = client_hello.GetSerialized();
- if (!QuicConnectionIdSupportsVariableLength(Perspective::IS_SERVER)) {
- // connection_id is already passed in in network byte order.
- const uint64_t connection_id64_net =
- QuicConnectionIdToUInt64(connection_id);
- hkdf_suffix.reserve(sizeof(connection_id64_net) +
- client_hello_serialized.length() +
- requested_config->serialized.size());
- hkdf_suffix.append(reinterpret_cast<const char*>(&connection_id64_net),
- sizeof(connection_id64_net));
- } else {
hkdf_suffix.reserve(connection_id.length() +
client_hello_serialized.length() +
requested_config->serialized.size());
hkdf_suffix.append(connection_id.data(), connection_id.length());
- }
hkdf_suffix.append(client_hello_serialized.data(),
client_hello_serialized.length());
hkdf_suffix.append(requested_config->serialized);
@@ -1057,15 +1042,7 @@
QuicString hkdf_input;
hkdf_input.append(QuicCryptoConfig::kCETVLabel,
strlen(QuicCryptoConfig::kCETVLabel) + 1);
- if (!QuicConnectionIdSupportsVariableLength(Perspective::IS_SERVER)) {
- // connection_id is already passed in in network byte order.
- const uint64_t connection_id64_net =
- QuicConnectionIdToUInt64(connection_id);
- hkdf_input.append(reinterpret_cast<const char*>(&connection_id64_net),
- sizeof(connection_id64_net));
- } else {
- hkdf_input.append(connection_id.data(), connection_id.length());
- }
+ hkdf_input.append(connection_id.data(), connection_id.length());
hkdf_input.append(client_hello_copy_serialized.data(),
client_hello_copy_serialized.length());
hkdf_input.append(requested_config->serialized);
@@ -1084,9 +1061,8 @@
char plaintext[kMaxPacketSize];
size_t plaintext_length = 0;
const bool success = crypters.decrypter->DecryptPacket(
- QUIC_VERSION_35, 0 /* packet number */,
- QuicStringPiece() /* associated data */, cetv_ciphertext, plaintext,
- &plaintext_length, kMaxPacketSize);
+ 0 /* packet number */, QuicStringPiece() /* associated data */,
+ cetv_ciphertext, plaintext, &plaintext_length, kMaxPacketSize);
if (!success) {
helper.Fail(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER,
"CETV decryption failure");
@@ -1613,10 +1589,6 @@
<< "with server-designated connection ID "
<< server_designated_connection_id;
out->set_tag(kSREJ);
- if (!QuicConnectionIdSupportsVariableLength(Perspective::IS_SERVER)) {
- out->SetValue(kRCID, QuicEndian::HostToNet64(QuicConnectionIdToUInt64(
- server_designated_connection_id)));
- } else {
if (!QuicUtils::IsConnectionIdValidForVersion(
server_designated_connection_id, version)) {
QUIC_BUG << "Tried to send server designated connection ID "
@@ -1628,7 +1600,6 @@
out->SetStringPiece(
kRCID, QuicStringPiece(server_designated_connection_id.data(),
server_designated_connection_id.length()));
- }
} else {
out->set_tag(kREJ);
}
@@ -2078,6 +2049,7 @@
bool QuicCryptoServerConfig::IsNextConfigReady(QuicWallTime now) const {
if (GetQuicReloadableFlag(quic_fix_config_rotation)) {
+ QUIC_RELOADABLE_FLAG_COUNT(quic_fix_config_rotation);
return !next_config_promotion_time_.IsZero() &&
!next_config_promotion_time_.IsAfter(now);
}
diff --git a/quic/core/crypto/quic_decrypter.h b/quic/core/crypto/quic_decrypter.h
index 892504c..c7c2ccc 100644
--- a/quic/core/crypto/quic_decrypter.h
+++ b/quic/core/crypto/quic_decrypter.h
@@ -53,8 +53,7 @@
// to form the nonce.
// TODO(wtc): add a way for DecryptPacket to report decryption failure due
// to non-authentic inputs, as opposed to other reasons for failure.
- virtual bool DecryptPacket(QuicTransportVersion version,
- uint64_t packet_number,
+ virtual bool DecryptPacket(uint64_t packet_number,
QuicStringPiece associated_data,
QuicStringPiece ciphertext,
char* output,
diff --git a/quic/core/crypto/quic_encrypter.h b/quic/core/crypto/quic_encrypter.h
index 591021e..cb53e33 100644
--- a/quic/core/crypto/quic_encrypter.h
+++ b/quic/core/crypto/quic_encrypter.h
@@ -34,8 +34,7 @@
// SetNoncePrefix() to form the nonce. |output| must not overlap with
// |associated_data|. If |output| overlaps with |plaintext| then
// |plaintext| must be <= |output|.
- virtual bool EncryptPacket(QuicTransportVersion version,
- uint64_t packet_number,
+ virtual bool EncryptPacket(uint64_t packet_number,
QuicStringPiece associated_data,
QuicStringPiece plaintext,
char* output,
diff --git a/quic/core/frames/quic_ack_frame.cc b/quic/core/frames/quic_ack_frame.cc
index 5f47b3f..389f1c0 100644
--- a/quic/core/frames/quic_ack_frame.cc
+++ b/quic/core/frames/quic_ack_frame.cc
@@ -5,9 +5,9 @@
#include "net/third_party/quiche/src/quic/core/frames/quic_ack_frame.h"
#include "net/third_party/quiche/src/quic/core/quic_constants.h"
+#include "net/third_party/quiche/src/quic/core/quic_interval.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_interval.h"
namespace quic {
diff --git a/quic/core/frames/quic_ack_frame.h b/quic/core/frames/quic_ack_frame.h
index 4dcfc3d..771d93e 100644
--- a/quic/core/frames/quic_ack_frame.h
+++ b/quic/core/frames/quic_ack_frame.h
@@ -7,11 +7,11 @@
#include <ostream>
+#include "net/third_party/quiche/src/quic/core/quic_interval.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_interval.h"
namespace quic {
diff --git a/quic/core/frames/quic_frames_test.cc b/quic/core/frames/quic_frames_test.cc
index af9c40b..8099ccc 100644
--- a/quic/core/frames/quic_frames_test.cc
+++ b/quic/core/frames/quic_frames_test.cc
@@ -14,8 +14,8 @@
#include "net/third_party/quiche/src/quic/core/frames/quic_stop_waiting_frame.h"
#include "net/third_party/quiche/src/quic/core/frames/quic_stream_frame.h"
#include "net/third_party/quiche/src/quic/core/frames/quic_window_update_frame.h"
+#include "net/third_party/quiche/src/quic/core/quic_interval.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_interval.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
diff --git a/quic/core/frames/quic_message_frame.cc b/quic/core/frames/quic_message_frame.cc
index 79a23fe..c0de272 100644
--- a/quic/core/frames/quic_message_frame.cc
+++ b/quic/core/frames/quic_message_frame.cc
@@ -9,17 +9,20 @@
namespace quic {
-QuicMessageFrame::QuicMessageFrame() : message_id(0) {}
+QuicMessageFrame::QuicMessageFrame()
+ : message_id(0), data(nullptr), message_length(0) {}
-QuicMessageFrame::QuicMessageFrame(QuicMessageId message_id,
- QuicStringPiece message_data)
- : message_id(message_id), message_data(message_data) {}
+QuicMessageFrame::QuicMessageFrame(QuicMessageId message_id)
+ : message_id(message_id), data(nullptr), message_length(0) {}
+
+QuicMessageFrame::QuicMessageFrame(const char* data, QuicPacketLength length)
+ : message_id(0), data(data), message_length(length) {}
QuicMessageFrame::~QuicMessageFrame() {}
std::ostream& operator<<(std::ostream& os, const QuicMessageFrame& s) {
os << " message_id: " << s.message_id
- << ", message_length: " << s.message_data.length() << " }\n";
+ << ", message_length: " << s.message_length << " }\n";
return os;
}
diff --git a/quic/core/frames/quic_message_frame.h b/quic/core/frames/quic_message_frame.h
index 6458a11..4accff2 100644
--- a/quic/core/frames/quic_message_frame.h
+++ b/quic/core/frames/quic_message_frame.h
@@ -6,14 +6,26 @@
#define QUICHE_QUIC_CORE_FRAMES_QUIC_MESSAGE_FRAME_H_
#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_mem_slice.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
namespace quic {
+typedef QuicInlinedVector<QuicMemSlice, 1> QuicMessageData;
+
struct QUIC_EXPORT_PRIVATE QuicMessageFrame {
QuicMessageFrame();
- QuicMessageFrame(QuicMessageId message_id, QuicStringPiece message_data);
+ explicit QuicMessageFrame(QuicMessageId message_id);
+ QuicMessageFrame(const char* data, QuicPacketLength length);
+
+ QuicMessageFrame(const QuicMessageFrame& other) = delete;
+ QuicMessageFrame& operator=(const QuicMessageFrame& other) = delete;
+
+ QuicMessageFrame(QuicMessageFrame&& other) = default;
+ QuicMessageFrame& operator=(QuicMessageFrame&& other) = default;
+
~QuicMessageFrame();
friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(
@@ -23,8 +35,13 @@
// message_id is only used on the sender side and does not get serialized on
// wire.
QuicMessageId message_id;
- // The actual data.
- QuicString message_data;
+ // Not owned, only used on read path.
+ const char* data;
+ // Total length of message_data, must be fit into one packet.
+ QuicPacketLength message_length;
+
+ // The actual message data which is reference counted, used on write path.
+ QuicMessageData message_data;
};
} // namespace quic
diff --git a/quic/core/frames/quic_retire_connection_id_frame.cc b/quic/core/frames/quic_retire_connection_id_frame.cc
index a507269..6828ce4 100644
--- a/quic/core/frames/quic_retire_connection_id_frame.cc
+++ b/quic/core/frames/quic_retire_connection_id_frame.cc
@@ -1,3 +1,7 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
#include "net/third_party/quiche/src/quic/core/frames/quic_retire_connection_id_frame.h"
#include "net/third_party/quiche/src/quic/core/quic_constants.h"
diff --git a/quic/core/frames/quic_retire_connection_id_frame.h b/quic/core/frames/quic_retire_connection_id_frame.h
index 7bce51c..79521f6 100644
--- a/quic/core/frames/quic_retire_connection_id_frame.h
+++ b/quic/core/frames/quic_retire_connection_id_frame.h
@@ -1,3 +1,7 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
#ifndef QUICHE_QUIC_CORE_FRAMES_QUIC_RETIRE_CONNECTION_ID_FRAME_H_
#define QUICHE_QUIC_CORE_FRAMES_QUIC_RETIRE_CONNECTION_ID_FRAME_H_
diff --git a/quic/core/http/end_to_end_test.cc b/quic/core/http/end_to_end_test.cc
index 132da8e..adf82c9 100644
--- a/quic/core/http/end_to_end_test.cc
+++ b/quic/core/http/end_to_end_test.cc
@@ -10,8 +10,6 @@
#include <utility>
#include <vector>
-#include "gfe/gfe2/base/epoll_server.h"
-#include "net/util/netutil.h"
#include "net/third_party/quiche/src/quic/core/crypto/null_encrypter.h"
#include "net/third_party/quiche/src/quic/core/http/quic_spdy_client_stream.h"
#include "net/third_party/quiche/src/quic/core/quic_epoll_connection_helper.h"
@@ -26,6 +24,7 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_port_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_sleep.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
@@ -139,18 +138,21 @@
ParsedQuicVersionVector all_supported_versions =
FilterSupportedVersions(AllSupportedVersions());
- // Buckets are separated by the handshake protocol (QUIC crypto or TLS) in
- // use, since if the handshake protocol changes, the ClientHello/CHLO must be
+ // Buckets are separated by versions: versions prior to QUIC_VERSION_47 use
+ // STREAM frames for the handshake, and only have QUIC crypto as the handshake
+ // protocol. Version 47 and greater use CRYPTO frames for the handshake, and
+ // must also be split based on the handshake protocol. If the handshake
+ // protocol (QUIC crypto or TLS) changes, the ClientHello/CHLO must be
// reconstructed for the correct protocol.
- ParsedQuicVersionVector version_buckets[2];
+ ParsedQuicVersionVector version_buckets[3];
for (const ParsedQuicVersion& version : all_supported_versions) {
- // Versions: 35+
- // QUIC_VERSION_35 allows endpoints to independently set stream limit.
- if (version.handshake_protocol == PROTOCOL_TLS1_3) {
+ if (version.transport_version < QUIC_VERSION_47) {
+ version_buckets[0].push_back(version);
+ } else if (version.handshake_protocol == PROTOCOL_QUIC_CRYPTO) {
version_buckets[1].push_back(version);
} else {
- version_buckets[0].push_back(version);
+ version_buckets[2].push_back(version);
}
}
@@ -273,7 +275,7 @@
: initialized_(false),
connect_to_server_on_initialize_(true),
server_address_(
- QuicSocketAddress(TestLoopback(), net_util::PickUnusedPortOrDie())),
+ QuicSocketAddress(TestLoopback(), QuicPickUnusedPortOrDie())),
server_hostname_("test.example.com"),
client_writer_(nullptr),
server_writer_(nullptr),
@@ -313,9 +315,7 @@
AddToCache("/bar", 200, kBarResponseBody);
}
- ~EndToEndTest() override {
- net_util::RecycleUnusedPort(server_address_.port());
- }
+ ~EndToEndTest() override { QuicRecyclePort(server_address_.port()); }
virtual void CreateClientWithWriter() {
client_.reset(CreateQuicClient(client_writer_));
@@ -404,9 +404,6 @@
copt.push_back(kTPCC);
}
- if (support_server_push_) {
- copt.push_back(kSPSH);
- }
if (GetParam().client_supports_stateless_rejects) {
copt.push_back(kSREJ);
}
@@ -602,13 +599,15 @@
}
QuicStreamId GetNthClientInitiatedBidirectionalId(int n) {
- return QuicSpdySessionPeer::GetNthClientInitiatedBidirectionalStreamId(
- *client_->client()->client_session(), n);
+ return GetNthClientInitiatedBidirectionalStreamId(
+ client_->client()->client_session()->connection()->transport_version(),
+ n);
}
QuicStreamId GetNthServerInitiatedBidirectionalId(int n) {
- return QuicSpdySessionPeer::GetNthServerInitiatedBidirectionalStreamId(
- *client_->client()->client_session(), n);
+ return GetNthServerInitiatedBidirectionalStreamId(
+ client_->client()->client_session()->connection()->transport_version(),
+ n);
}
ScopedEnvironmentForThreads environment_;
@@ -639,21 +638,21 @@
};
// Run all end to end tests with all supported versions.
-INSTANTIATE_TEST_CASE_P(EndToEndTests,
- EndToEndTest,
- ::testing::ValuesIn(GetTestParams(false, false)));
+INSTANTIATE_TEST_SUITE_P(EndToEndTests,
+ EndToEndTest,
+ ::testing::ValuesIn(GetTestParams(false, false)));
class EndToEndTestWithTls : public EndToEndTest {};
-INSTANTIATE_TEST_CASE_P(EndToEndTestsWithTls,
- EndToEndTestWithTls,
- ::testing::ValuesIn(GetTestParams(true, false)));
+INSTANTIATE_TEST_SUITE_P(EndToEndTestsWithTls,
+ EndToEndTestWithTls,
+ ::testing::ValuesIn(GetTestParams(true, false)));
class EndToEndTestWithStatelessReject : public EndToEndTest {};
-INSTANTIATE_TEST_CASE_P(WithStatelessReject,
- EndToEndTestWithStatelessReject,
- ::testing::ValuesIn(GetTestParams(false, true)));
+INSTANTIATE_TEST_SUITE_P(WithStatelessReject,
+ EndToEndTestWithStatelessReject,
+ ::testing::ValuesIn(GetTestParams(false, true)));
TEST_P(EndToEndTestWithTls, HandshakeSuccessful) {
ASSERT_TRUE(Initialize());
@@ -709,25 +708,6 @@
client_->client()->GetNumSentClientHellos());
}
-// TODO(dschinazi) remove this test once the flags are deprecated
-TEST_P(EndToEndTest, SimpleRequestResponseVariableLengthConnectionIDClient) {
- SetQuicRestartFlag(quic_variable_length_connection_ids_client, true);
- SetQuicRestartFlag(quic_variable_length_connection_ids_server, false);
- ASSERT_TRUE(Initialize());
-
- EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
- EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
- int expected_num_client_hellos = 2;
- if (ServerSendsVersionNegotiation()) {
- ++expected_num_client_hellos;
- if (BothSidesSupportStatelessRejects()) {
- ++expected_num_client_hellos;
- }
- }
- EXPECT_EQ(expected_num_client_hellos,
- client_->client()->GetNumSentClientHellos());
-}
-
TEST_P(EndToEndTest, SimpleRequestResponseZeroConnectionID) {
QuicConnectionId connection_id = QuicUtils::CreateZeroConnectionId(
GetParam().negotiated_version.transport_version);
@@ -750,25 +730,6 @@
GetParam().negotiated_version.transport_version));
}
-// TODO(dschinazi) remove this test once the flags are deprecated
-TEST_P(EndToEndTest, SimpleRequestResponseVariableLengthConnectionIDServer) {
- SetQuicRestartFlag(quic_variable_length_connection_ids_client, false);
- SetQuicRestartFlag(quic_variable_length_connection_ids_server, true);
- ASSERT_TRUE(Initialize());
-
- EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
- EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
- int expected_num_client_hellos = 2;
- if (ServerSendsVersionNegotiation()) {
- ++expected_num_client_hellos;
- if (BothSidesSupportStatelessRejects()) {
- ++expected_num_client_hellos;
- }
- }
- EXPECT_EQ(expected_num_client_hellos,
- client_->client()->GetNumSentClientHellos());
-}
-
TEST_P(EndToEndTest, SimpleRequestResponseWithLargeReject) {
chlo_multiplier_ = 1;
ASSERT_TRUE(Initialize());
@@ -1360,7 +1321,7 @@
// Make sure that the stream has data pending so that it will be marked as
// write blocked when it receives a stream level WINDOW_UPDATE.
- stream->WriteOrBufferBody("hello", false, nullptr);
+ stream->WriteOrBufferBody("hello", false);
// The stream now attempts to write, fails because it is still connection
// level flow control blocked, and is added to the write blocked list.
@@ -1949,7 +1910,7 @@
// Open a data stream to make sure the stream level flow control is updated.
QuicSpdyClientStream* stream = client_->GetOrCreateStream();
- stream->WriteOrBufferBody("hello", false, nullptr);
+ stream->WriteOrBufferBody("hello", false);
// Client should have the right values for server's receive window.
EXPECT_EQ(kServerStreamIFCW,
@@ -2005,7 +1966,7 @@
// Open a data stream to make sure the stream level flow control is updated.
QuicSpdyClientStream* stream = client_->GetOrCreateStream();
- stream->WriteOrBufferBody("hello", false, nullptr);
+ stream->WriteOrBufferBody("hello", false);
// Client should have the right values for server's receive window.
EXPECT_EQ(kExpectedStreamIFCW,
@@ -2045,9 +2006,14 @@
QuicCryptoStream* crypto_stream = QuicSessionPeer::GetMutableCryptoStream(
client_->client()->client_session());
- EXPECT_LT(
- QuicFlowControllerPeer::SendWindowSize(crypto_stream->flow_controller()),
- kStreamIFCW);
+ // In v47 and later, the crypto handshake (sent in CRYPTO frames) is not
+ // subject to flow control.
+ if (client_->client()->client_session()->connection()->transport_version() <
+ QUIC_VERSION_47) {
+ EXPECT_LT(QuicFlowControllerPeer::SendWindowSize(
+ crypto_stream->flow_controller()),
+ kStreamIFCW);
+ }
EXPECT_EQ(kSessionIFCW,
QuicFlowControllerPeer::SendWindowSize(
client_->client()->client_session()->flow_controller()));
@@ -2223,20 +2189,9 @@
QuicString request_string =
"a request body bigger than one packet" + QuicString(kMaxPacketSize, '.');
- // Calculate header length for version 99, so that the ack listener know how
- // many actual bytes will be acked.
- QuicByteCount header_length = 0;
- if (client_->client()->client_session()->connection()->transport_version() ==
- QUIC_VERSION_99) {
- HttpEncoder encoder;
- std::unique_ptr<char[]> buf;
- header_length =
- encoder.SerializeDataFrameHeader(request_string.length(), &buf);
- }
-
// The TestAckListener will cause a failure if not notified.
QuicReferenceCountedPointer<TestAckListener> ack_listener(
- new TestAckListener(request_string.length() + header_length));
+ new TestAckListener(request_string.length()));
// Send the request, and register the delegate for ACKs.
client_->SendData(request_string, true, ack_listener);
@@ -2875,9 +2830,9 @@
};
// Run all server push end to end tests with all supported versions.
-INSTANTIATE_TEST_CASE_P(EndToEndTestsServerPush,
- EndToEndTestServerPush,
- ::testing::ValuesIn(GetTestParams(false, false)));
+INSTANTIATE_TEST_SUITE_P(EndToEndTestsServerPush,
+ EndToEndTestServerPush,
+ ::testing::ValuesIn(GetTestParams(false, false)));
TEST_P(EndToEndTestServerPush, ServerPush) {
ASSERT_TRUE(Initialize());
@@ -3266,7 +3221,6 @@
QuicConnection* client_connection =
client_->client()->client_session()->connection();
client_connection->set_debug_visitor(&observer);
- QuicTransportVersion version = client_connection->transport_version();
// 100KB body.
QuicString body(100 * 1024, 'a');
SpdyHeaderBlock headers;
@@ -3278,12 +3232,8 @@
EXPECT_EQ(kFooResponseBody,
client_->SendCustomSynchronousRequest(headers, body));
client_->Disconnect();
- if (version != QUIC_VERSION_35) {
- EXPECT_LT(0u, observer.num_window_update_frames());
- EXPECT_EQ(0u, observer.num_ping_frames());
- } else {
- EXPECT_EQ(0u, observer.num_window_update_frames());
- }
+ EXPECT_LT(0u, observer.num_window_update_frames());
+ EXPECT_EQ(0u, observer.num_ping_frames());
}
TEST_P(EndToEndTest, SendStatelessResetTokenInShlo) {
@@ -3506,13 +3456,12 @@
// 1 MB body.
QuicString body(1024 * 1024, 'a');
- stream->WriteOrBufferBody(body, true, nullptr);
+ stream->WriteOrBufferBody(body, true);
client_->WaitForResponse();
EXPECT_EQ(QUIC_STREAM_TTL_EXPIRED, client_->stream_error());
}
TEST_P(EndToEndTest, SendMessages) {
- SetQuicReloadableFlag(quic_fix_mark_for_loss_retransmission, true);
ASSERT_TRUE(Initialize());
EXPECT_TRUE(client_->client()->WaitForCryptoHandshakeConfirmed());
QuicSession* client_session = client_->client()->client_session();
@@ -3529,22 +3478,30 @@
QuicStringPiece message_buffer(message_string);
QuicRandom* random =
QuicConnectionPeer::GetHelper(client_connection)->GetRandomGenerator();
+ QuicMemSliceStorage storage(nullptr, 0, nullptr, 0);
{
QuicConnection::ScopedPacketFlusher flusher(
client_session->connection(), QuicConnection::SEND_ACK_IF_PENDING);
// Verify the largest message gets successfully sent.
EXPECT_EQ(MessageResult(MESSAGE_STATUS_SUCCESS, 1),
- client_session->SendMessage(
+ client_session->SendMessage(MakeSpan(
+ client_session->connection()
+ ->helper()
+ ->GetStreamSendBufferAllocator(),
QuicStringPiece(message_buffer.data(),
- client_session->GetLargestMessagePayload())));
+ client_session->GetLargestMessagePayload()),
+ &storage)));
// Send more messages with size (0, largest_payload] until connection is
// write blocked.
const int kTestMaxNumberOfMessages = 100;
for (size_t i = 2; i <= kTestMaxNumberOfMessages; ++i) {
size_t message_length =
random->RandUint64() % client_session->GetLargestMessagePayload() + 1;
- MessageResult result = client_session->SendMessage(
- QuicStringPiece(message_buffer.data(), message_length));
+ MessageResult result = client_session->SendMessage(MakeSpan(
+ client_session->connection()
+ ->helper()
+ ->GetStreamSendBufferAllocator(),
+ QuicStringPiece(message_buffer.data(), message_length), &storage));
if (result.status == MESSAGE_STATUS_BLOCKED) {
// Connection is write blocked.
break;
@@ -3554,12 +3511,17 @@
}
client_->WaitForDelayedAcks();
- EXPECT_EQ(MESSAGE_STATUS_TOO_LARGE,
- client_session
- ->SendMessage(QuicStringPiece(
- message_buffer.data(),
- client_session->GetLargestMessagePayload() + 1))
- .status);
+ EXPECT_EQ(
+ MESSAGE_STATUS_TOO_LARGE,
+ client_session
+ ->SendMessage(MakeSpan(
+ client_session->connection()
+ ->helper()
+ ->GetStreamSendBufferAllocator(),
+ QuicStringPiece(message_buffer.data(),
+ client_session->GetLargestMessagePayload() + 1),
+ &storage))
+ .status);
EXPECT_EQ(QUIC_NO_ERROR, client_->connection_error());
}
@@ -3580,9 +3542,9 @@
PacketReorderingWriter* reorder_writer_;
};
-INSTANTIATE_TEST_CASE_P(EndToEndPacketReorderingTests,
- EndToEndPacketReorderingTest,
- testing::ValuesIn(GetTestParams(false, false)));
+INSTANTIATE_TEST_SUITE_P(EndToEndPacketReorderingTests,
+ EndToEndPacketReorderingTest,
+ testing::ValuesIn(GetTestParams(false, false)));
TEST_P(EndToEndPacketReorderingTest, ReorderedConnectivityProbing) {
ASSERT_TRUE(Initialize());
diff --git a/quic/core/http/http_decoder.cc b/quic/core/http/http_decoder.cc
index 345f2cb..e697821 100644
--- a/quic/core/http/http_decoder.cc
+++ b/quic/core/http/http_decoder.cc
@@ -22,7 +22,7 @@
}
// Length of the type field of HTTP/3 frames.
-static const size_t kFrameTypeLength = 1;
+static const QuicByteCount kFrameTypeLength = 1;
} // namespace
@@ -40,9 +40,9 @@
HttpDecoder::~HttpDecoder() {}
-size_t HttpDecoder::ProcessInput(const char* data, size_t len) {
+QuicByteCount HttpDecoder::ProcessInput(const char* data, QuicByteCount len) {
has_payload_ = false;
- QuicDataReader reader(data, len, NETWORK_BYTE_ORDER);
+ QuicDataReader reader(data, len);
while (error_ == QUIC_NO_ERROR && reader.BytesRemaining() != 0) {
switch (state_) {
case STATE_READING_FRAME_LENGTH:
@@ -75,7 +75,7 @@
return;
}
QuicDataReader length_reader(length_buffer_.data(),
- current_length_field_size_, NETWORK_BYTE_ORDER);
+ current_length_field_size_);
if (!length_reader.ReadVarInt62(¤t_frame_length_)) {
RaiseError(QUIC_INTERNAL_ERROR, "Unable to read frame length");
visitor_->OnError(this);
@@ -105,8 +105,8 @@
Http3FrameLengths(current_length_field_size_ + kFrameTypeLength,
current_frame_length_));
}
- size_t bytes_to_read =
- std::min<size_t>(remaining_frame_length_, reader->BytesRemaining());
+ QuicByteCount bytes_to_read = std::min<QuicByteCount>(
+ remaining_frame_length_, reader->BytesRemaining());
QuicStringPiece payload;
if (!reader->ReadStringPiece(&payload, bytes_to_read)) {
RaiseError(QUIC_INTERNAL_ERROR, "Unable to read data");
@@ -126,8 +126,8 @@
if (current_frame_length_ == remaining_frame_length_) {
visitor_->OnHeadersFrameStart();
}
- size_t bytes_to_read =
- std::min<size_t>(remaining_frame_length_, reader->BytesRemaining());
+ QuicByteCount bytes_to_read = std::min<QuicByteCount>(
+ remaining_frame_length_, reader->BytesRemaining());
QuicStringPiece payload;
if (!reader->ReadStringPiece(&payload, bytes_to_read)) {
RaiseError(QUIC_INTERNAL_ERROR, "Unable to read data");
@@ -138,7 +138,7 @@
if (remaining_frame_length_ == 0) {
state_ = STATE_READING_FRAME_LENGTH;
current_length_field_size_ = 0;
- visitor_->OnHeadersFrameEnd();
+ visitor_->OnHeadersFrameEnd(current_frame_length_);
}
return;
}
@@ -148,8 +148,7 @@
BufferFramePayload(reader);
if (remaining_frame_length_ == 0) {
PriorityFrame frame;
- QuicDataReader reader(buffer_.data(), current_frame_length_,
- NETWORK_BYTE_ORDER);
+ QuicDataReader reader(buffer_.data(), current_frame_length_);
if (!ParsePriorityFrame(&reader, &frame)) {
return;
}
@@ -164,8 +163,7 @@
BufferFramePayload(reader);
if (remaining_frame_length_ == 0) {
CancelPushFrame frame;
- QuicDataReader reader(buffer_.data(), current_frame_length_,
- NETWORK_BYTE_ORDER);
+ QuicDataReader reader(buffer_.data(), current_frame_length_);
if (!reader.ReadVarInt62(&frame.push_id)) {
RaiseError(QUIC_INTERNAL_ERROR, "Unable to read push_id");
return;
@@ -184,8 +182,7 @@
BufferFramePayload(reader);
if (remaining_frame_length_ == 0) {
SettingsFrame frame;
- QuicDataReader reader(buffer_.data(), current_frame_length_,
- NETWORK_BYTE_ORDER);
+ QuicDataReader reader(buffer_.data(), current_frame_length_);
if (!ParseSettingsFrame(&reader, &frame)) {
return;
}
@@ -197,7 +194,7 @@
}
case 0x5: { // PUSH_PROMISE
if (current_frame_length_ == remaining_frame_length_) {
- size_t bytes_remaining = reader->BytesRemaining();
+ QuicByteCount bytes_remaining = reader->BytesRemaining();
PushId push_id;
// TODO(rch): Handle partial delivery of this field.
if (!reader->ReadVarInt62(&push_id)) {
@@ -207,8 +204,8 @@
remaining_frame_length_ -= bytes_remaining - reader->BytesRemaining();
visitor_->OnPushPromiseFrameStart(push_id);
}
- size_t bytes_to_read =
- std::min<size_t>(remaining_frame_length_, reader->BytesRemaining());
+ QuicByteCount bytes_to_read = std::min<QuicByteCount>(
+ remaining_frame_length_, reader->BytesRemaining());
if (bytes_to_read == 0) {
return;
}
@@ -230,8 +227,7 @@
BufferFramePayload(reader);
if (remaining_frame_length_ == 0) {
GoAwayFrame frame;
- QuicDataReader reader(buffer_.data(), current_frame_length_,
- NETWORK_BYTE_ORDER);
+ QuicDataReader reader(buffer_.data(), current_frame_length_);
uint64_t stream_id;
if (!reader.ReadVarInt62(&stream_id)) {
RaiseError(QUIC_INTERNAL_ERROR, "Unable to read GOAWAY stream_id");
@@ -249,8 +245,7 @@
// TODO(rch): Handle partial delivery.
BufferFramePayload(reader);
if (remaining_frame_length_ == 0) {
- QuicDataReader reader(buffer_.data(), current_frame_length_,
- NETWORK_BYTE_ORDER);
+ QuicDataReader reader(buffer_.data(), current_frame_length_);
MaxPushIdFrame frame;
if (!reader.ReadVarInt62(&frame.push_id)) {
RaiseError(QUIC_INTERNAL_ERROR, "Unable to read push_id");
@@ -268,8 +263,7 @@
if (remaining_frame_length_ != 0) {
return;
}
- QuicDataReader reader(buffer_.data(), current_frame_length_,
- NETWORK_BYTE_ORDER);
+ QuicDataReader reader(buffer_.data(), current_frame_length_);
DuplicatePushFrame frame;
if (!reader.ReadVarInt62(&frame.push_id)) {
RaiseError(QUIC_INTERNAL_ERROR, "Unable to read push_id");
@@ -305,8 +299,8 @@
}
void HttpDecoder::DiscardFramePayload(QuicDataReader* reader) {
- size_t bytes_to_read =
- std::min<size_t>(remaining_frame_length_, reader->BytesRemaining());
+ QuicByteCount bytes_to_read = std::min<QuicByteCount>(
+ remaining_frame_length_, reader->BytesRemaining());
QuicStringPiece payload;
if (!reader->ReadStringPiece(&payload, bytes_to_read)) {
RaiseError(QUIC_INTERNAL_ERROR, "Unable to read frame payload");
@@ -324,8 +318,8 @@
buffer_.erase(buffer_.size());
buffer_.reserve(current_frame_length_);
}
- size_t bytes_to_read =
- std::min<size_t>(remaining_frame_length_, reader->BytesRemaining());
+ QuicByteCount bytes_to_read = std::min<QuicByteCount>(
+ remaining_frame_length_, reader->BytesRemaining());
if (!reader->ReadBytes(
&(buffer_[0]) + current_frame_length_ - remaining_frame_length_,
bytes_to_read)) {
@@ -349,8 +343,8 @@
length_buffer_.erase(length_buffer_.size());
length_buffer_.reserve(current_length_field_size_);
}
- size_t bytes_to_read = std::min<size_t>(remaining_length_field_length_,
- reader->BytesRemaining());
+ QuicByteCount bytes_to_read = std::min<QuicByteCount>(
+ remaining_length_field_length_, reader->BytesRemaining());
if (!reader->ReadBytes(&(length_buffer_[0]) + current_length_field_size_ -
remaining_length_field_length_,
bytes_to_read)) {
diff --git a/quic/core/http/http_decoder.h b/quic/core/http/http_decoder.h
index a5f41b5..910d189 100644
--- a/quic/core/http/http_decoder.h
+++ b/quic/core/http/http_decoder.h
@@ -9,6 +9,7 @@
#include "net/third_party/quiche/src/quic/core/http/http_frames.h"
#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
@@ -20,7 +21,7 @@
// |header_length| stores number of bytes header occupies.
// |payload_length| stores number of bytes payload occupies.
struct QUIC_EXPORT_PRIVATE Http3FrameLengths {
- Http3FrameLengths(uint64_t header, uint64_t payload)
+ Http3FrameLengths(QuicByteCount header, QuicByteCount payload)
: header_length(header), payload_length(payload) {}
bool operator==(const Http3FrameLengths& other) const {
@@ -76,7 +77,8 @@
// multiple times for a single frame.
virtual void OnHeadersFramePayload(QuicStringPiece payload) = 0;
// Called when a HEADERS frame has been completely processed.
- virtual void OnHeadersFrameEnd() = 0;
+ // |frame_len| is the length of the HEADERS frame payload.
+ virtual void OnHeadersFrameEnd(QuicByteCount frame_len) = 0;
// Called when a PUSH_PROMISE frame has been recevied for |push_id|.
virtual void OnPushPromiseFrameStart(PushId push_id) = 0;
@@ -104,7 +106,7 @@
// Processes the input and invokes the visitor for any frames.
// Returns the number of bytes consumed, or 0 if there was an error, in which
// case error() should be consulted.
- size_t ProcessInput(const char* data, size_t len);
+ QuicByteCount ProcessInput(const char* data, QuicByteCount len);
bool has_payload() { return has_payload_; }
@@ -158,13 +160,13 @@
// Type of the frame currently being parsed.
uint8_t current_frame_type_;
// Size of the frame's length field.
- uint64_t current_length_field_size_;
+ QuicByteCount current_length_field_size_;
// Remaining length that's needed for the frame's length field.
- uint64_t remaining_length_field_length_;
+ QuicByteCount remaining_length_field_length_;
// Length of the payload of the frame currently being parsed.
- uint64_t current_frame_length_;
+ QuicByteCount current_frame_length_;
// Remaining payload bytes to be parsed.
- uint64_t remaining_frame_length_;
+ QuicByteCount remaining_frame_length_;
// Last error.
QuicErrorCode error_;
// The issue which caused |error_|
diff --git a/quic/core/http/http_decoder_test.cc b/quic/core/http/http_decoder_test.cc
index c2b303c..c6d7d9f 100644
--- a/quic/core/http/http_decoder_test.cc
+++ b/quic/core/http/http_decoder_test.cc
@@ -31,7 +31,7 @@
MOCK_METHOD0(OnHeadersFrameStart, void());
MOCK_METHOD1(OnHeadersFramePayload, void(QuicStringPiece payload));
- MOCK_METHOD0(OnHeadersFrameEnd, void());
+ MOCK_METHOD1(OnHeadersFrameEnd, void(QuicByteCount frame_len));
MOCK_METHOD1(OnPushPromiseFrameStart, void(PushId push_id));
MOCK_METHOD1(OnPushPromiseFramePayload, void(QuicStringPiece payload));
@@ -84,7 +84,7 @@
TEST_F(HttpDecoderTest, ReservedFramesLargePayload) {
for (int n = 0; n < 8; ++n) {
const uint8_t type = 0xB + 0x1F * n;
- const size_t payload_size = 256;
+ const QuicByteCount payload_size = 256;
char input[payload_size + 3] = {// length
0x40 + 0x01, 0x00,
// type
@@ -383,7 +383,7 @@
InSequence s;
EXPECT_CALL(visitor_, OnHeadersFrameStart());
EXPECT_CALL(visitor_, OnHeadersFramePayload(QuicStringPiece("Headers")));
- EXPECT_CALL(visitor_, OnHeadersFrameEnd());
+ EXPECT_CALL(visitor_, OnHeadersFrameEnd(7));
EXPECT_EQ(QUIC_ARRAYSIZE(input),
decoder_.ProcessInput(input, QUIC_ARRAYSIZE(input)));
EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
@@ -398,7 +398,7 @@
EXPECT_CALL(visitor_, OnHeadersFramePayload(QuicStringPiece("e")));
EXPECT_CALL(visitor_, OnHeadersFramePayload(QuicStringPiece("r")));
EXPECT_CALL(visitor_, OnHeadersFramePayload(QuicStringPiece("s")));
- EXPECT_CALL(visitor_, OnHeadersFrameEnd());
+ EXPECT_CALL(visitor_, OnHeadersFrameEnd(7));
for (char c : input) {
EXPECT_EQ(1u, decoder_.ProcessInput(&c, 1));
}
diff --git a/quic/core/http/http_encoder.cc b/quic/core/http/http_encoder.cc
index 7c07838..d2d1699 100644
--- a/quic/core/http/http_encoder.cc
+++ b/quic/core/http/http_encoder.cc
@@ -66,7 +66,7 @@
QuicDataWriter::GetVarInt62Len(payload_length) + kFrameTypeLength;
output->reset(new char[header_length]);
- QuicDataWriter writer(header_length, output->get(), NETWORK_BYTE_ORDER);
+ QuicDataWriter writer(header_length, output->get());
if (WriteFrameHeader(payload_length, HttpFrameType::DATA, &writer)) {
return header_length;
@@ -82,7 +82,7 @@
QuicDataWriter::GetVarInt62Len(payload_length) + kFrameTypeLength;
output->reset(new char[header_length]);
- QuicDataWriter writer(header_length, output->get(), NETWORK_BYTE_ORDER);
+ QuicDataWriter writer(header_length, output->get());
if (WriteFrameHeader(payload_length, HttpFrameType::HEADERS, &writer)) {
return header_length;
@@ -101,7 +101,7 @@
QuicByteCount total_length = GetTotalLength(payload_length);
output->reset(new char[total_length]);
- QuicDataWriter writer(total_length, output->get(), NETWORK_BYTE_ORDER);
+ QuicDataWriter writer(total_length, output->get());
if (!WriteFrameHeader(payload_length, HttpFrameType::PRIORITY, &writer)) {
return 0;
@@ -132,7 +132,7 @@
QuicByteCount total_length = GetTotalLength(payload_length);
output->reset(new char[total_length]);
- QuicDataWriter writer(total_length, output->get(), NETWORK_BYTE_ORDER);
+ QuicDataWriter writer(total_length, output->get());
if (WriteFrameHeader(payload_length, HttpFrameType::CANCEL_PUSH, &writer) &&
writer.WriteVarInt62(cancel_push.push_id)) {
@@ -154,7 +154,7 @@
QuicByteCount total_length = GetTotalLength(payload_length);
output->reset(new char[total_length]);
- QuicDataWriter writer(total_length, output->get(), NETWORK_BYTE_ORDER);
+ QuicDataWriter writer(total_length, output->get());
if (!WriteFrameHeader(payload_length, HttpFrameType::SETTINGS, &writer)) {
return 0;
@@ -181,7 +181,7 @@
QuicDataWriter::GetVarInt62Len(push_promise.push_id);
output->reset(new char[total_length]);
- QuicDataWriter writer(total_length, output->get(), NETWORK_BYTE_ORDER);
+ QuicDataWriter writer(total_length, output->get());
if (WriteFrameHeader(payload_length, HttpFrameType::PUSH_PROMISE, &writer) &&
writer.WriteVarInt62(push_promise.push_id)) {
@@ -198,7 +198,7 @@
QuicByteCount total_length = GetTotalLength(payload_length);
output->reset(new char[total_length]);
- QuicDataWriter writer(total_length, output->get(), NETWORK_BYTE_ORDER);
+ QuicDataWriter writer(total_length, output->get());
if (WriteFrameHeader(payload_length, HttpFrameType::GOAWAY, &writer) &&
writer.WriteVarInt62(goaway.stream_id)) {
@@ -215,7 +215,7 @@
QuicByteCount total_length = GetTotalLength(payload_length);
output->reset(new char[total_length]);
- QuicDataWriter writer(total_length, output->get(), NETWORK_BYTE_ORDER);
+ QuicDataWriter writer(total_length, output->get());
if (WriteFrameHeader(payload_length, HttpFrameType::MAX_PUSH_ID, &writer) &&
writer.WriteVarInt62(max_push_id.push_id)) {
@@ -232,7 +232,7 @@
QuicByteCount total_length = GetTotalLength(payload_length);
output->reset(new char[total_length]);
- QuicDataWriter writer(total_length, output->get(), NETWORK_BYTE_ORDER);
+ QuicDataWriter writer(total_length, output->get());
if (WriteFrameHeader(payload_length, HttpFrameType::DUPLICATE_PUSH,
&writer) &&
diff --git a/quic/core/http/quic_client_promised_info_test.cc b/quic/core/http/quic_client_promised_info_test.cc
index 2cf3f76..2a7b1b0 100644
--- a/quic/core/http/quic_client_promised_info_test.cc
+++ b/quic/core/http/quic_client_promised_info_test.cc
@@ -84,8 +84,8 @@
headers_["content-length"] = "11";
stream_ = QuicMakeUnique<QuicSpdyClientStream>(
- QuicSpdySessionPeer::GetNthClientInitiatedBidirectionalStreamId(
- session_, 0),
+ GetNthClientInitiatedBidirectionalStreamId(
+ connection_->transport_version(), 0),
&session_, BIDIRECTIONAL);
stream_visitor_ = QuicMakeUnique<StreamVisitor>();
stream_->set_visitor(stream_visitor_.get());
@@ -99,9 +99,8 @@
promise_url_ = SpdyUtils::GetPromisedUrlFromHeaders(push_promise_);
client_request_ = push_promise_.Clone();
- promise_id_ =
- QuicSpdySessionPeer::GetNthServerInitiatedUnidirectionalStreamId(
- session_, 0);
+ promise_id_ = GetNthServerInitiatedUnidirectionalStreamId(
+ connection_->transport_version(), 0);
}
class StreamVisitor : public QuicSpdyClientStream::Visitor {
diff --git a/quic/core/http/quic_client_push_promise_index_test.cc b/quic/core/http/quic_client_push_promise_index_test.cc
index 0ddde61..b68b41f 100644
--- a/quic/core/http/quic_client_push_promise_index_test.cc
+++ b/quic/core/http/quic_client_push_promise_index_test.cc
@@ -54,12 +54,11 @@
&alarm_factory_,
Perspective::IS_CLIENT)),
session_(connection_->supported_versions(), connection_, &index_),
- promised_(
- &session_,
- QuicSpdySessionPeer::GetNthServerInitiatedUnidirectionalStreamId(
- session_,
- 0),
- url_) {
+ promised_(&session_,
+ GetNthServerInitiatedUnidirectionalStreamId(
+ connection_->transport_version(),
+ 0),
+ url_) {
request_[":path"] = "/bar";
request_[":authority"] = "www.google.com";
request_[":version"] = "HTTP/1.1";
diff --git a/quic/core/http/quic_headers_stream.cc b/quic/core/http/quic_headers_stream.cc
index 09d8797..9c99ab7 100644
--- a/quic/core/http/quic_headers_stream.cc
+++ b/quic/core/http/quic_headers_stream.cc
@@ -60,7 +60,8 @@
bool QuicHeadersStream::OnStreamFrameAcked(QuicStreamOffset offset,
QuicByteCount data_length,
bool fin_acked,
- QuicTime::Delta ack_delay_time) {
+ QuicTime::Delta ack_delay_time,
+ QuicByteCount* newly_acked_length) {
QuicIntervalSet<QuicStreamOffset> newly_acked(offset, offset + data_length);
newly_acked.Difference(bytes_acked());
for (const auto& acked : newly_acked) {
@@ -104,7 +105,7 @@
unacked_headers_.pop_front();
}
return QuicStream::OnStreamFrameAcked(offset, data_length, fin_acked,
- ack_delay_time);
+ ack_delay_time, newly_acked_length);
}
void QuicHeadersStream::OnStreamFrameRetransmitted(QuicStreamOffset offset,
diff --git a/quic/core/http/quic_headers_stream.h b/quic/core/http/quic_headers_stream.h
index 4abfb01..abc0aeb 100644
--- a/quic/core/http/quic_headers_stream.h
+++ b/quic/core/http/quic_headers_stream.h
@@ -43,7 +43,8 @@
bool OnStreamFrameAcked(QuicStreamOffset offset,
QuicByteCount data_length,
bool fin_acked,
- QuicTime::Delta ack_delay_time) override;
+ QuicTime::Delta ack_delay_time,
+ QuicByteCount* newly_acked_length) override;
void OnStreamFrameRetransmitted(QuicStreamOffset offset,
QuicByteCount data_length,
diff --git a/quic/core/http/quic_headers_stream_test.cc b/quic/core/http/quic_headers_stream_test.cc
index 1bbb9e4..b6409b1 100644
--- a/quic/core/http/quic_headers_stream_test.cc
+++ b/quic/core/http/quic_headers_stream_test.cc
@@ -195,21 +195,19 @@
EXPECT_EQ(transport_version(), session_.connection()->transport_version());
EXPECT_TRUE(headers_stream_ != nullptr);
connection_->AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
- client_id_1_ =
- QuicSpdySessionPeer::GetNthClientInitiatedBidirectionalStreamId(
- session_, 0);
- client_id_2_ =
- QuicSpdySessionPeer::GetNthClientInitiatedBidirectionalStreamId(
- session_, 1);
- client_id_3_ =
- QuicSpdySessionPeer::GetNthClientInitiatedBidirectionalStreamId(
- session_, 2);
- next_stream_id_ = QuicSpdySessionPeer::StreamIdDelta(session_);
+ client_id_1_ = GetNthClientInitiatedBidirectionalStreamId(
+ connection_->transport_version(), 0);
+ client_id_2_ = GetNthClientInitiatedBidirectionalStreamId(
+ connection_->transport_version(), 1);
+ client_id_3_ = GetNthClientInitiatedBidirectionalStreamId(
+ connection_->transport_version(), 2);
+ next_stream_id_ =
+ QuicUtils::StreamIdDelta(connection_->transport_version());
}
QuicStreamId GetNthClientInitiatedId(int n) {
- return QuicSpdySessionPeer::GetNthClientInitiatedBidirectionalStreamId(
- session_, n);
+ return GetNthClientInitiatedBidirectionalStreamId(
+ connection_->transport_version(), n);
}
QuicConsumedData SaveIov(size_t write_length) {
@@ -278,9 +276,8 @@
connection_->transport_version()),
_, _, NO_FIN))
.WillOnce(WithArgs<2>(Invoke(this, &QuicHeadersStreamTest::SaveIov)));
- QuicSpdySessionPeer::WriteHeadersImpl(
- &session_, stream_id, headers_.Clone(), fin,
- Spdy3PriorityToHttp2Weight(priority), 0, false, nullptr);
+ QuicSpdySessionPeer::WriteHeadersOnHeadersStream(
+ &session_, stream_id, headers_.Clone(), fin, priority, nullptr);
// Parse the outgoing data and check that it matches was was written.
if (is_request) {
@@ -363,9 +360,8 @@
};
// Run all tests with each version and perspective (client or server).
-INSTANTIATE_TEST_CASE_P(Tests,
- QuicHeadersStreamTest,
- ::testing::ValuesIn(GetTestParams()));
+INSTANTIATE_TEST_SUITE_P(Tests, QuicHeadersStreamTest,
+ ::testing::ValuesIn(GetTestParams()));
TEST_P(QuicHeadersStreamTest, StreamId) {
EXPECT_EQ(QuicUtils::GetHeadersStreamId(connection_->transport_version()),
@@ -833,27 +829,34 @@
headers_stream_->OnStreamFrameRetransmitted(28, 7, false);
// Packets are acked in order: 2, 3, 1.
+ QuicByteCount newly_acked_length = 0;
EXPECT_CALL(*ack_listener3, OnPacketAcked(7, _));
EXPECT_CALL(*ack_listener2, OnPacketAcked(7, _));
- EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(21, 7, false,
- QuicTime::Delta::Zero()));
- EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(28, 7, false,
- QuicTime::Delta::Zero()));
+ EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
+ 21, 7, false, QuicTime::Delta::Zero(), &newly_acked_length));
+ EXPECT_EQ(7u, newly_acked_length);
+ EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
+ 28, 7, false, QuicTime::Delta::Zero(), &newly_acked_length));
+ EXPECT_EQ(7u, newly_acked_length);
EXPECT_CALL(*ack_listener3, OnPacketAcked(7, _));
- EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(35, 7, false,
- QuicTime::Delta::Zero()));
+ EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
+ 35, 7, false, QuicTime::Delta::Zero(), &newly_acked_length));
+ EXPECT_EQ(7u, newly_acked_length);
EXPECT_CALL(*ack_listener1, OnPacketAcked(7, _));
EXPECT_CALL(*ack_listener1, OnPacketAcked(7, _));
- EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(0, 7, false,
- QuicTime::Delta::Zero()));
- EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(7, 7, false,
- QuicTime::Delta::Zero()));
+ EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
+ 0, 7, false, QuicTime::Delta::Zero(), &newly_acked_length));
+ EXPECT_EQ(7u, newly_acked_length);
+ EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
+ 7, 7, false, QuicTime::Delta::Zero(), &newly_acked_length));
+ EXPECT_EQ(7u, newly_acked_length);
// Unsent data is acked.
EXPECT_CALL(*ack_listener2, OnPacketAcked(7, _));
- EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(14, 10, false,
- QuicTime::Delta::Zero()));
+ EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
+ 14, 10, false, QuicTime::Delta::Zero(), &newly_acked_length));
+ EXPECT_EQ(7u, newly_acked_length);
}
TEST_P(QuicHeadersStreamTest, FrameContainsMultipleHeaders) {
@@ -884,21 +887,25 @@
headers_stream_->OnStreamFrameRetransmitted(0, 17, false);
// Frames are acked in order: 2, 3, 1.
+ QuicByteCount newly_acked_length = 0;
EXPECT_CALL(*ack_listener2, OnPacketAcked(4, _));
EXPECT_CALL(*ack_listener3, OnPacketAcked(7, _));
EXPECT_CALL(*ack_listener2, OnPacketAcked(2, _));
- EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(17, 13, false,
- QuicTime::Delta::Zero()));
+ EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
+ 17, 13, false, QuicTime::Delta::Zero(), &newly_acked_length));
+ EXPECT_EQ(13u, newly_acked_length);
EXPECT_CALL(*ack_listener2, OnPacketAcked(5, _));
EXPECT_CALL(*ack_listener3, OnPacketAcked(7, _));
- EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(30, 12, false,
- QuicTime::Delta::Zero()));
+ EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
+ 30, 12, false, QuicTime::Delta::Zero(), &newly_acked_length));
+ EXPECT_EQ(12u, newly_acked_length);
EXPECT_CALL(*ack_listener1, OnPacketAcked(14, _));
EXPECT_CALL(*ack_listener2, OnPacketAcked(3, _));
- EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(0, 17, false,
- QuicTime::Delta::Zero()));
+ EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
+ 0, 17, false, QuicTime::Delta::Zero(), &newly_acked_length));
+ EXPECT_EQ(17u, newly_acked_length);
}
TEST_P(QuicHeadersStreamTest, HeadersGetAckedMultipleTimes) {
@@ -924,30 +931,36 @@
headers_stream_->WriteOrBufferData("Header9", false, ack_listener3);
// Ack [15, 20), [5, 25), [10, 17), [0, 12) and [22, 42).
+ QuicByteCount newly_acked_length = 0;
EXPECT_CALL(*ack_listener2, OnPacketAcked(5, _));
- EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(15, 5, false,
- QuicTime::Delta::Zero()));
+ EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
+ 15, 5, false, QuicTime::Delta::Zero(), &newly_acked_length));
+ EXPECT_EQ(5u, newly_acked_length);
EXPECT_CALL(*ack_listener1, OnPacketAcked(9, _));
EXPECT_CALL(*ack_listener2, OnPacketAcked(1, _));
EXPECT_CALL(*ack_listener2, OnPacketAcked(1, _));
EXPECT_CALL(*ack_listener3, OnPacketAcked(4, _));
- EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(5, 20, false,
- QuicTime::Delta::Zero()));
+ EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
+ 5, 20, false, QuicTime::Delta::Zero(), &newly_acked_length));
+ EXPECT_EQ(15u, newly_acked_length);
// Duplicate ack.
- EXPECT_FALSE(headers_stream_->OnStreamFrameAcked(10, 7, false,
- QuicTime::Delta::Zero()));
+ EXPECT_FALSE(headers_stream_->OnStreamFrameAcked(
+ 10, 7, false, QuicTime::Delta::Zero(), &newly_acked_length));
+ EXPECT_EQ(0u, newly_acked_length);
EXPECT_CALL(*ack_listener1, OnPacketAcked(5, _));
- EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(0, 12, false,
- QuicTime::Delta::Zero()));
+ EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
+ 0, 12, false, QuicTime::Delta::Zero(), &newly_acked_length));
+ EXPECT_EQ(5u, newly_acked_length);
EXPECT_CALL(*ack_listener3, OnPacketAcked(3, _));
EXPECT_CALL(*ack_listener2, OnPacketAcked(7, _));
EXPECT_CALL(*ack_listener3, OnPacketAcked(7, _));
- EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(22, 20, false,
- QuicTime::Delta::Zero()));
+ EXPECT_TRUE(headers_stream_->OnStreamFrameAcked(
+ 22, 20, false, QuicTime::Delta::Zero(), &newly_acked_length));
+ EXPECT_EQ(17u, newly_acked_length);
}
} // namespace
diff --git a/quic/core/http/quic_server_session_base.cc b/quic/core/http/quic_server_session_base.cc
index 40b43dc..b18b1fa 100644
--- a/quic/core/http/quic_server_session_base.cc
+++ b/quic/core/http/quic_server_session_base.cc
@@ -55,11 +55,6 @@
bandwidth_resumption_enabled_ =
last_bandwidth_resumption || max_bandwidth_resumption;
- if (connection()->transport_version() < QUIC_VERSION_35) {
- set_server_push_enabled(
- ContainsQuicTag(config()->ReceivedConnectionOptions(), kSPSH));
- }
-
// If the client has provided a bandwidth estimate from the same serving
// region as this server, then decide whether to use the data for bandwidth
// resumption.
diff --git a/quic/core/http/quic_server_session_base_test.cc b/quic/core/http/quic_server_session_base_test.cc
index 9f36e37..2b75f70 100644
--- a/quic/core/http/quic_server_session_base_test.cc
+++ b/quic/core/http/quic_server_session_base_test.cc
@@ -65,7 +65,7 @@
compressed_certs_cache),
quic_simple_server_backend_(quic_simple_server_backend) {}
- ~TestServerSession() override { delete connection(); };
+ ~TestServerSession() override { delete connection(); }
protected:
QuicSpdyStream* CreateIncomingStream(QuicStreamId id) override {
@@ -157,13 +157,13 @@
}
QuicStreamId GetNthClientInitiatedBidirectionalId(int n) {
- return QuicSpdySessionPeer::GetNthClientInitiatedBidirectionalStreamId(
- *session_, n);
+ return GetNthClientInitiatedBidirectionalStreamId(
+ connection_->transport_version(), n);
}
QuicStreamId GetNthServerInitiatedUnidirectionalId(int n) {
- return QuicSpdySessionPeer::GetNthServerInitiatedUnidirectionalStreamId(
- *session_, n);
+ return quic::test::GetNthServerInitiatedUnidirectionalStreamId(
+ connection_->transport_version(), n);
}
QuicTransportVersion transport_version() const {
@@ -188,6 +188,7 @@
EXPECT_CALL(owner_, OnStopSendingReceived(_)).Times(1);
// Expect the RESET_STREAM that is generated in response to receiving a
// STOP_SENDING.
+ EXPECT_CALL(*connection_, SendControlFrame(_));
EXPECT_CALL(*connection_, OnStreamReset(stream_id, rst_stream_code));
session_->OnStopSendingFrame(stop_sending);
}
@@ -222,9 +223,8 @@
reference.previous_connection_state());
}
-INSTANTIATE_TEST_CASE_P(Tests,
- QuicServerSessionBaseTest,
- ::testing::ValuesIn(AllSupportedVersions()));
+INSTANTIATE_TEST_SUITE_P(Tests, QuicServerSessionBaseTest,
+ ::testing::ValuesIn(AllSupportedVersions()));
TEST_P(QuicServerSessionBaseTest, CloseStreamDueToReset) {
// Open a stream, then reset it.
// Send two bytes of payload to open it.
@@ -238,10 +238,14 @@
GetNthClientInitiatedBidirectionalId(0),
QUIC_ERROR_PROCESSING_STREAM, 0);
EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1);
- EXPECT_CALL(*connection_, SendControlFrame(_));
- EXPECT_CALL(*connection_,
- OnStreamReset(GetNthClientInitiatedBidirectionalId(0),
- QUIC_RST_ACKNOWLEDGEMENT));
+ if (transport_version() != QUIC_VERSION_99) {
+ // For non-version 99, the RESET_STREAM will do the full close.
+ // Set up expects accordingly.
+ EXPECT_CALL(*connection_, SendControlFrame(_));
+ EXPECT_CALL(*connection_,
+ OnStreamReset(GetNthClientInitiatedBidirectionalId(0),
+ QUIC_RST_ACKNOWLEDGEMENT));
+ }
visitor_->OnRstStream(rst1);
// For version-99 will create and receive a stop-sending, completing
@@ -265,10 +269,14 @@
GetNthClientInitiatedBidirectionalId(0),
QUIC_ERROR_PROCESSING_STREAM, 0);
EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1);
- EXPECT_CALL(*connection_, SendControlFrame(_));
- EXPECT_CALL(*connection_,
- OnStreamReset(GetNthClientInitiatedBidirectionalId(0),
- QUIC_RST_ACKNOWLEDGEMENT));
+ if (transport_version() != QUIC_VERSION_99) {
+ // For non-version 99, the RESET_STREAM will do the full close.
+ // Set up expects accordingly.
+ EXPECT_CALL(*connection_, SendControlFrame(_));
+ EXPECT_CALL(*connection_,
+ OnStreamReset(GetNthClientInitiatedBidirectionalId(0),
+ QUIC_RST_ACKNOWLEDGEMENT));
+ }
visitor_->OnRstStream(rst1);
// For version-99 will create and receive a stop-sending, completing
@@ -303,10 +311,14 @@
GetNthClientInitiatedBidirectionalId(0),
QUIC_ERROR_PROCESSING_STREAM, 0);
EXPECT_CALL(owner_, OnRstStreamReceived(_)).Times(1);
- EXPECT_CALL(*connection_, SendControlFrame(_));
- EXPECT_CALL(*connection_,
- OnStreamReset(GetNthClientInitiatedBidirectionalId(0),
- QUIC_RST_ACKNOWLEDGEMENT));
+ if (transport_version() != QUIC_VERSION_99) {
+ // For non-version 99, the RESET_STREAM will do the full close.
+ // Set up expects accordingly.
+ EXPECT_CALL(*connection_, SendControlFrame(_));
+ EXPECT_CALL(*connection_,
+ OnStreamReset(GetNthClientInitiatedBidirectionalId(0),
+ QUIC_RST_ACKNOWLEDGEMENT));
+ }
visitor_->OnRstStream(rst);
// For version-99 will create and receive a stop-sending, completing
@@ -350,7 +362,7 @@
for (size_t i = 0; i < kMaxStreamsForTest; ++i) {
EXPECT_TRUE(QuicServerSessionBasePeer::GetOrCreateDynamicStream(
session_.get(), stream_id));
- stream_id += QuicSpdySessionPeer::StreamIdDelta(*session_);
+ stream_id += QuicUtils::StreamIdDelta(connection_->transport_version());
}
if (transport_version() != QUIC_VERSION_99) {
@@ -359,11 +371,11 @@
for (size_t i = 0; i < kMaxStreamsMinimumIncrement; ++i) {
EXPECT_TRUE(QuicServerSessionBasePeer::GetOrCreateDynamicStream(
session_.get(), stream_id));
- stream_id += QuicSpdySessionPeer::StreamIdDelta(*session_);
+ stream_id += QuicUtils::StreamIdDelta(connection_->transport_version());
}
}
// Now violate the server's internal stream limit.
- stream_id += QuicSpdySessionPeer::StreamIdDelta(*session_);
+ stream_id += QuicUtils::StreamIdDelta(connection_->transport_version());
if (transport_version() != QUIC_VERSION_99) {
// For non-version 99, QUIC responds to an attempt to exceed the stream
@@ -395,7 +407,8 @@
session_.get(), GetNthClientInitiatedBidirectionalId(0)));
// Establish available streams up to the server's limit.
- QuicStreamId next_id = QuicSpdySessionPeer::StreamIdDelta(*session_);
+ QuicStreamId next_id =
+ QuicUtils::StreamIdDelta(connection_->transport_version());
const int kLimitingStreamId =
GetNthClientInitiatedBidirectionalId(kAvailableStreamLimit + 1);
if (transport_version() != QUIC_VERSION_99) {
@@ -665,9 +678,8 @@
QuicCryptoServerConfigPeer crypto_config_peer_;
};
-INSTANTIATE_TEST_CASE_P(StreamMemberLifetimeTests,
- StreamMemberLifetimeTest,
- ::testing::ValuesIn(AllSupportedVersions()));
+INSTANTIATE_TEST_SUITE_P(StreamMemberLifetimeTests, StreamMemberLifetimeTest,
+ ::testing::ValuesIn(AllSupportedVersions()));
// Trigger an operation which causes an async invocation of
// ProofSource::GetProof. Delay the completion of the operation until after the
diff --git a/quic/core/http/quic_spdy_client_session_test.cc b/quic/core/http/quic_spdy_client_session_test.cc
index a9d6c62..84229fd 100644
--- a/quic/core/http/quic_spdy_client_session_test.cc
+++ b/quic/core/http/quic_spdy_client_session_test.cc
@@ -108,12 +108,10 @@
push_promise_[":method"] = "GET";
push_promise_[":scheme"] = "https";
promise_url_ = SpdyUtils::GetPromisedUrlFromHeaders(push_promise_);
- promised_stream_id_ =
- QuicSpdySessionPeer::GetNthServerInitiatedUnidirectionalStreamId(
- *session_, 0);
- associated_stream_id_ =
- QuicSpdySessionPeer::GetNthClientInitiatedBidirectionalStreamId(
- *session_, 0);
+ promised_stream_id_ = GetNthServerInitiatedUnidirectionalStreamId(
+ connection_->transport_version(), 0);
+ associated_stream_id_ = GetNthClientInitiatedBidirectionalStreamId(
+ connection_->transport_version(), 0);
}
// The function ensures that A) the max stream id frames get properly deleted
@@ -172,9 +170,8 @@
QuicStreamId associated_stream_id_;
};
-INSTANTIATE_TEST_CASE_P(Tests,
- QuicSpdyClientSessionTest,
- ::testing::ValuesIn(AllSupportedVersions()));
+INSTANTIATE_TEST_SUITE_P(Tests, QuicSpdyClientSessionTest,
+ ::testing::ValuesIn(AllSupportedVersions()));
TEST_P(QuicSpdyClientSessionTest, CryptoConnect) {
CompleteCryptoHandshake();
@@ -281,9 +278,8 @@
// Note that this is to be the second stream created, but GetNth... starts
// numbering at 0 (the first stream is 0, second is 1...)
- QuicMaxStreamIdFrame frame(
- 0, QuicSpdySessionPeer::GetNthClientInitiatedBidirectionalStreamId(
- *session_, 1));
+ QuicMaxStreamIdFrame frame(0, GetNthClientInitiatedBidirectionalStreamId(
+ connection_->transport_version(), 1));
session_->OnMaxStreamIdFrame(frame);
}
stream = session_->CreateOutgoingBidirectionalStream();
@@ -350,9 +346,8 @@
if (GetParam().transport_version == QUIC_VERSION_99) {
// Note that this is to be the second stream created, but GetNth... starts
// numbering at 0 (the first stream is 0, second is 1...)
- QuicMaxStreamIdFrame frame(
- 0, QuicSpdySessionPeer::GetNthClientInitiatedBidirectionalStreamId(
- *session_, 1));
+ QuicMaxStreamIdFrame frame(0, GetNthClientInitiatedBidirectionalStreamId(
+ connection_->transport_version(), 1));
session_->OnMaxStreamIdFrame(frame);
}
stream = session_->CreateOutgoingBidirectionalStream();
@@ -454,7 +449,7 @@
QuicReceivedPacket valid_packet(buf, 2, QuicTime::Zero(), false);
// Close connection shouldn't be called.
EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
- if (connection_->transport_version() > QUIC_VERSION_46) {
+ if (connection_->transport_version() > QUIC_VERSION_44) {
// Illegal fixed bit value.
EXPECT_CALL(*connection_, OnError(_)).Times(1);
}
@@ -539,7 +534,8 @@
EXPECT_CALL(*stream, OnPromiseHeaderList(promised_stream_id_, _, _));
session_->OnPromiseHeaderList(associated_stream_id_, promised_stream_id_, 0,
QuicHeaderList());
- associated_stream_id_ += QuicSpdySessionPeer::StreamIdDelta(*session_);
+ associated_stream_id_ +=
+ QuicUtils::StreamIdDelta(connection_->transport_version());
EXPECT_CALL(*connection_,
CloseConnection(QUIC_INVALID_STREAM_ID,
"Received push stream id lesser or equal to the"
@@ -557,9 +553,8 @@
session_->CreateOutgoingBidirectionalStream());
// Promise an illegal (outgoing) stream id.
- promised_stream_id_ =
- QuicSpdySessionPeer::GetNthClientInitiatedBidirectionalStreamId(*session_,
- 0);
+ promised_stream_id_ = GetNthClientInitiatedBidirectionalStreamId(
+ connection_->transport_version(), 0);
EXPECT_CALL(
*connection_,
CloseConnection(QUIC_INVALID_STREAM_ID,
@@ -615,7 +610,8 @@
EXPECT_NE(session_->GetPromisedById(promised_stream_id_), nullptr);
EXPECT_NE(session_->GetPromisedByUrl(promise_url_), nullptr);
- promised_stream_id_ += QuicSpdySessionPeer::StreamIdDelta(*session_);
+ promised_stream_id_ +=
+ QuicUtils::StreamIdDelta(connection_->transport_version());
EXPECT_CALL(*connection_, SendControlFrame(_));
EXPECT_CALL(*connection_,
OnStreamReset(promised_stream_id_, QUIC_DUPLICATE_PROMISE_URL));
@@ -632,7 +628,8 @@
push_promise_[":path"] = QuicStringPrintf("/bar%zu", i);
QuicStreamId id =
- promised_stream_id_ + i * QuicSpdySessionPeer::StreamIdDelta(*session_);
+ promised_stream_id_ +
+ i * QuicUtils::StreamIdDelta(connection_->transport_version());
EXPECT_TRUE(
session_->HandlePromised(associated_stream_id_, id, push_promise_));
@@ -648,7 +645,8 @@
push_promise_[":path"] = QuicStringPrintf("/bar%d", i);
QuicStreamId id =
- promised_stream_id_ + i * QuicSpdySessionPeer::StreamIdDelta(*session_);
+ promised_stream_id_ +
+ i * QuicUtils::StreamIdDelta(connection_->transport_version());
EXPECT_CALL(*connection_, SendControlFrame(_));
EXPECT_CALL(*connection_, OnStreamReset(id, QUIC_REFUSED_STREAM));
EXPECT_FALSE(
@@ -780,9 +778,8 @@
} else {
EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
}
- session_->GetOrCreateStream(
- QuicSpdySessionPeer::GetNthServerInitiatedBidirectionalStreamId(*session_,
- 0));
+ session_->GetOrCreateStream(GetNthServerInitiatedBidirectionalStreamId(
+ connection_->transport_version(), 0));
}
} // namespace
diff --git a/quic/core/http/quic_spdy_client_stream.cc b/quic/core/http/quic_spdy_client_stream.cc
index 21a09d6..d4e8a69 100644
--- a/quic/core/http/quic_spdy_client_stream.cc
+++ b/quic/core/http/quic_spdy_client_stream.cc
@@ -151,7 +151,7 @@
bytes_sent += header_bytes_written_;
if (!body.empty()) {
- WriteOrBufferBody(body, fin, nullptr);
+ WriteOrBufferBody(body, fin);
}
return bytes_sent;
diff --git a/quic/core/http/quic_spdy_client_stream_test.cc b/quic/core/http/quic_spdy_client_stream_test.cc
index ded2d7d..059558b 100644
--- a/quic/core/http/quic_spdy_client_stream_test.cc
+++ b/quic/core/http/quic_spdy_client_stream_test.cc
@@ -75,8 +75,8 @@
headers_["content-length"] = "11";
stream_ = QuicMakeUnique<QuicSpdyClientStream>(
- QuicSpdySessionPeer::GetNthClientInitiatedBidirectionalStreamId(
- session_, 0),
+ GetNthClientInitiatedBidirectionalStreamId(
+ connection_->transport_version(), 0),
&session_, BIDIRECTIONAL);
stream_visitor_ = QuicMakeUnique<StreamVisitor>();
stream_->set_visitor(stream_visitor_.get());
@@ -101,9 +101,8 @@
HttpEncoder encoder_;
};
-INSTANTIATE_TEST_CASE_P(Tests,
- QuicSpdyClientStreamTest,
- ::testing::ValuesIn(AllSupportedVersions()));
+INSTANTIATE_TEST_SUITE_P(Tests, QuicSpdyClientStreamTest,
+ ::testing::ValuesIn(AllSupportedVersions()));
TEST_P(QuicSpdyClientStreamTest, TestReceivingIllegalResponseStatusCode) {
headers_[":status"] = "200 ok";
@@ -125,7 +124,7 @@
QuicByteCount header_length =
encoder_.SerializeDataFrameHeader(body_.length(), &buffer);
QuicString header = QuicString(buffer.get(), header_length);
- QuicString data = connection_->transport_version() == QUIC_VERSION_99
+ QuicString data = VersionHasDataFrameHeader(connection_->transport_version())
? header + body_
: body_;
stream_->OnStreamFrame(
@@ -156,7 +155,7 @@
QuicByteCount header_length =
encoder_.SerializeDataFrameHeader(body_.length(), &buffer);
QuicString header = QuicString(buffer.get(), header_length);
- QuicString data = connection_->transport_version() == QUIC_VERSION_99
+ QuicString data = VersionHasDataFrameHeader(connection_->transport_version())
? header + body_
: body_;
stream_->OnStreamFrame(
@@ -180,7 +179,7 @@
QuicByteCount header_length =
encoder_.SerializeDataFrameHeader(large_body.length(), &buffer);
QuicString header = QuicString(buffer.get(), header_length);
- QuicString data = connection_->transport_version() == QUIC_VERSION_99
+ QuicString data = VersionHasDataFrameHeader(connection_->transport_version())
? header + large_body
: large_body;
EXPECT_CALL(*connection_, SendControlFrame(_));
@@ -219,7 +218,7 @@
QuicByteCount header_length =
encoder_.SerializeDataFrameHeader(body_.length(), &buffer);
QuicString header = QuicString(buffer.get(), header_length);
- QuicString data = connection_->transport_version() == QUIC_VERSION_99
+ QuicString data = VersionHasDataFrameHeader(connection_->transport_version())
? header + body_
: body_;
stream_->OnStreamFrame(
diff --git a/quic/core/http/quic_spdy_server_stream_base_test.cc b/quic/core/http/quic_spdy_server_stream_base_test.cc
index 51abf0c..4e1aa1b 100644
--- a/quic/core/http/quic_spdy_server_stream_base_test.cc
+++ b/quic/core/http/quic_spdy_server_stream_base_test.cc
@@ -32,8 +32,8 @@
&alarm_factory_,
Perspective::IS_SERVER)) {
stream_ = new TestQuicSpdyServerStream(
- QuicSpdySessionPeer::GetNthClientInitiatedBidirectionalStreamId(
- session_, 0),
+ GetNthClientInitiatedBidirectionalStreamId(
+ session_.connection()->transport_version(), 0),
&session_, BIDIRECTIONAL);
session_.ActivateStream(QuicWrapUnique(stream_));
helper_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
@@ -58,7 +58,21 @@
EXPECT_FALSE(stream_->reading_stopped());
EXPECT_CALL(session_, SendRstStream(_, QUIC_STREAM_NO_ERROR, _)).Times(0);
- EXPECT_CALL(session_, SendRstStream(_, QUIC_RST_ACKNOWLEDGEMENT, _)).Times(1);
+
+ if (session_.connection()->transport_version() != QUIC_VERSION_99) {
+ EXPECT_CALL(session_, SendRstStream(_, QUIC_RST_ACKNOWLEDGEMENT, _))
+ .Times(1);
+ } else {
+ // Intercept & check that the call to the QuicConnection's OnStreamReast
+ // has correct stream ID and error code -- for V99/IETF Quic, it should
+ // have the STREAM_CANCELLED error code, not RST_ACK... Capture
+ // OnStreamReset (rather than SendRstStream) because the V99 path bypasses
+ // SendRstStream, calling SendRstStreamInner directly. Mocking
+ // SendRstStreamInner is problematic since the test relies on it to perform
+ // the closing operations and getting the stream in the correct state.
+ EXPECT_CALL(*(static_cast<MockQuicConnection*>(session_.connection())),
+ OnStreamReset(stream_->id(), QUIC_STREAM_CANCELLED));
+ }
QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream_->id(),
QUIC_STREAM_CANCELLED, 1234);
stream_->OnStreamReset(rst_frame);
diff --git a/quic/core/http/quic_spdy_session.cc b/quic/core/http/quic_spdy_session.cc
index bc3cf5c..824ecfa 100644
--- a/quic/core/http/quic_spdy_session.cc
+++ b/quic/core/http/quic_spdy_session.cc
@@ -347,6 +347,11 @@
QuicUtils::GetHeadersStreamId(connection()->transport_version()));
}
+ if (VersionUsesQpack(connection()->transport_version())) {
+ qpack_encoder_ = QuicMakeUnique<QpackEncoder>(this, this);
+ qpack_decoder_ = QuicMakeUnique<QpackDecoder>(this, this);
+ }
+
headers_stream_ = QuicMakeUnique<QuicHeadersStream>((this));
DCHECK_EQ(QuicUtils::GetHeadersStreamId(connection()->transport_version()),
headers_stream_->id());
@@ -360,6 +365,34 @@
set_max_decode_buffer_size_bytes(2 * max_inbound_header_list_size_);
}
+void QuicSpdySession::OnDecoderStreamError(QuicStringPiece error_message) {
+ DCHECK(VersionUsesQpack(connection()->transport_version()));
+
+ // TODO(112770235): Signal connection error on decoder stream errors.
+ QUIC_NOTREACHED();
+}
+
+void QuicSpdySession::WriteEncoderStreamData(QuicStringPiece data) {
+ DCHECK(VersionUsesQpack(connection()->transport_version()));
+
+ // TODO(112770235): Send encoder stream data on encoder stream.
+ QUIC_NOTREACHED();
+}
+
+void QuicSpdySession::OnEncoderStreamError(QuicStringPiece error_message) {
+ DCHECK(VersionUsesQpack(connection()->transport_version()));
+
+ // TODO(112770235): Signal connection error on encoder stream errors.
+ QUIC_NOTREACHED();
+}
+
+void QuicSpdySession::WriteDecoderStreamData(QuicStringPiece data) {
+ DCHECK(VersionUsesQpack(connection()->transport_version()));
+
+ // TODO(112770235): Send decoder stream data on decoder stream.
+ QUIC_NOTREACHED();
+}
+
void QuicSpdySession::OnStreamHeadersPriority(QuicStreamId stream_id,
SpdyPriority priority) {
QuicSpdyStream* stream = GetSpdyDataStream(stream_id);
@@ -424,38 +457,16 @@
iov.iov_len);
}
-size_t QuicSpdySession::WriteHeaders(
+size_t QuicSpdySession::WriteHeadersOnHeadersStream(
QuicStreamId id,
SpdyHeaderBlock headers,
bool fin,
SpdyPriority priority,
QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
- return WriteHeadersImpl(
- id, std::move(headers), fin, Spdy3PriorityToHttp2Weight(priority),
- /*parent_stream_id=*/0, /*exclusive=*/false, std::move(ack_listener));
-}
-
-size_t QuicSpdySession::WriteHeadersImpl(
- QuicStreamId id,
- SpdyHeaderBlock headers,
- bool fin,
- int weight,
- QuicStreamId parent_stream_id,
- bool exclusive,
- QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
- SpdyHeadersIR headers_frame(id, std::move(headers));
- headers_frame.set_fin(fin);
- if (perspective() == Perspective::IS_CLIENT) {
- headers_frame.set_has_priority(true);
- headers_frame.set_weight(weight);
- headers_frame.set_parent_stream_id(parent_stream_id);
- headers_frame.set_exclusive(exclusive);
- }
- SpdySerializedFrame frame(spdy_framer_.SerializeFrame(headers_frame));
- headers_stream_->WriteOrBufferData(
- QuicStringPiece(frame.data(), frame.size()), false,
- std::move(ack_listener));
- return frame.size();
+ return WriteHeadersOnHeadersStreamImpl(
+ id, std::move(headers), fin,
+ /* parent_stream_id = */ 0, Spdy3PriorityToHttp2Weight(priority),
+ /* exclusive = */ false, std::move(ack_listener));
}
size_t QuicSpdySession::WritePriority(QuicStreamId id,
@@ -502,6 +513,18 @@
return frame.size();
}
+QpackEncoder* QuicSpdySession::qpack_encoder() {
+ DCHECK(VersionUsesQpack(connection()->transport_version()));
+
+ return qpack_encoder_.get();
+}
+
+QpackDecoder* QuicSpdySession::qpack_decoder() {
+ DCHECK(VersionUsesQpack(connection()->transport_version()));
+
+ return qpack_decoder_.get();
+}
+
QuicSpdyStream* QuicSpdySession::GetSpdyDataStream(
const QuicStreamId stream_id) {
return static_cast<QuicSpdyStream*>(GetOrCreateDynamicStream(stream_id));
@@ -519,6 +542,29 @@
return !QuicUtils::IsBidirectionalStreamId(id);
}
+size_t QuicSpdySession::WriteHeadersOnHeadersStreamImpl(
+ QuicStreamId id,
+ spdy::SpdyHeaderBlock headers,
+ bool fin,
+ QuicStreamId parent_stream_id,
+ int weight,
+ bool exclusive,
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
+ SpdyHeadersIR headers_frame(id, std::move(headers));
+ headers_frame.set_fin(fin);
+ if (perspective() == Perspective::IS_CLIENT) {
+ headers_frame.set_has_priority(true);
+ headers_frame.set_parent_stream_id(parent_stream_id);
+ headers_frame.set_weight(weight);
+ headers_frame.set_exclusive(exclusive);
+ }
+ SpdySerializedFrame frame(spdy_framer_.SerializeFrame(headers_frame));
+ headers_stream_->WriteOrBufferData(
+ QuicStringPiece(frame.data(), frame.size()), false,
+ std::move(ack_listener));
+ return frame.size();
+}
+
void QuicSpdySession::OnPromiseHeaderList(QuicStreamId stream_id,
QuicStreamId promised_stream_id,
size_t frame_len,
diff --git a/quic/core/http/quic_spdy_session.h b/quic/core/http/quic_spdy_session.h
index 2874e26..363edf3 100644
--- a/quic/core/http/quic_spdy_session.h
+++ b/quic/core/http/quic_spdy_session.h
@@ -12,7 +12,12 @@
#include "net/third_party/quiche/src/quic/core/http/quic_header_list.h"
#include "net/third_party/quiche/src/quic/core/http/quic_headers_stream.h"
#include "net/third_party/quiche/src/quic/core/http/quic_spdy_stream.h"
+#include "net/third_party/quiche/src/quic/core/qpack/qpack_decoder.h"
+#include "net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_sender.h"
+#include "net/third_party/quiche/src/quic/core/qpack/qpack_encoder.h"
+#include "net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_sender.h"
#include "net/third_party/quiche/src/quic/core/quic_session.h"
+#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
@@ -44,7 +49,12 @@
};
// A QUIC session with a headers stream.
-class QUIC_EXPORT_PRIVATE QuicSpdySession : public QuicSession {
+class QUIC_EXPORT_PRIVATE QuicSpdySession
+ : public QuicSession,
+ public QpackEncoder::DecoderStreamErrorDelegate,
+ public QpackEncoderStreamSender::Delegate,
+ public QpackDecoder::EncoderStreamErrorDelegate,
+ public QpackDecoderStreamSender::Delegate {
public:
// Does not take ownership of |connection| or |visitor|.
QuicSpdySession(QuicConnection* connection,
@@ -58,6 +68,18 @@
void Initialize() override;
+ // QpackEncoder::DecoderStreamErrorDelegate implementation.
+ void OnDecoderStreamError(QuicStringPiece error_message) override;
+
+ // QpackEncoderStreamSender::Delegate implemenation.
+ void WriteEncoderStreamData(QuicStringPiece data) override;
+
+ // QpackDecoder::EncoderStreamErrorDelegate implementation.
+ void OnEncoderStreamError(QuicStringPiece error_message) override;
+
+ // QpackDecoderStreamSender::Delegate implementation.
+ void WriteDecoderStreamData(QuicStringPiece data) override;
+
// Called by |headers_stream_| when headers with a priority have been
// received for a stream. This method will only be called for server streams.
virtual void OnStreamHeadersPriority(QuicStreamId stream_id,
@@ -79,7 +101,7 @@
size_t frame_len,
const QuicHeaderList& header_list);
- // Callbed by |headers_stream_| when a PRIORITY frame has been received for a
+ // Called by |headers_stream_| when a PRIORITY frame has been received for a
// stream. This method will only be called for server streams.
virtual void OnPriorityFrame(QuicStreamId stream_id,
spdy::SpdyPriority priority);
@@ -91,7 +113,7 @@
// If |fin| is true, then no more data will be sent for the stream |id|.
// If provided, |ack_notifier_delegate| will be registered to be notified when
// we have seen ACKs for all packets resulting from this call.
- virtual size_t WriteHeaders(
+ virtual size_t WriteHeadersOnHeadersStream(
QuicStreamId id,
spdy::SpdyHeaderBlock headers,
bool fin,
@@ -116,6 +138,8 @@
// Sends SETTINGS_MAX_HEADER_LIST_SIZE SETTINGS frame.
size_t SendMaxHeaderListSize(size_t value);
+ QpackEncoder* qpack_encoder();
+ QpackDecoder* qpack_decoder();
QuicHeadersStream* headers_stream() { return headers_stream_.get(); }
bool server_push_enabled() const { return server_push_enabled_; }
@@ -157,15 +181,12 @@
// Overridden to buffer incoming streams for version 99.
bool ShouldBufferIncomingStream(QuicStreamId id) const override;
- // This was formerly QuicHeadersStream::WriteHeaders. Needs to be
- // separate from QuicSpdySession::WriteHeaders because tests call
- // this but mock the latter.
- size_t WriteHeadersImpl(
+ size_t WriteHeadersOnHeadersStreamImpl(
QuicStreamId id,
spdy::SpdyHeaderBlock headers,
bool fin,
- int weight,
QuicStreamId parent_stream_id,
+ int weight,
bool exclusive,
QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener);
@@ -226,6 +247,10 @@
// Called when the size of the compressed frame payload is available.
void OnCompressedFrameSize(size_t frame_len);
+ std::unique_ptr<QpackEncoder> qpack_encoder_;
+ std::unique_ptr<QpackDecoder> qpack_decoder_;
+
+ // TODO(123528590): Remove this member.
std::unique_ptr<QuicHeadersStream> headers_stream_;
// The maximum size of a header block that will be accepted from the peer,
diff --git a/quic/core/http/quic_spdy_session_test.cc b/quic/core/http/quic_spdy_session_test.cc
index affa07a..d9c4ab1 100644
--- a/quic/core/http/quic_spdy_session_test.cc
+++ b/quic/core/http/quic_spdy_session_test.cc
@@ -98,6 +98,8 @@
MOCK_METHOD0(OnCanWrite, void());
+ bool HasPendingCryptoRetransmission() override { return false; }
+
MOCK_CONST_METHOD0(HasPendingRetransmission, bool());
private:
@@ -187,7 +189,8 @@
TestStream* stream = new TestStream(
id, this,
DetermineStreamType(id, connection()->transport_version(),
- /*is_incoming=*/true, BIDIRECTIONAL));
+ perspective(), /*is_incoming=*/true,
+ BIDIRECTIONAL));
ActivateStream(QuicWrapUnique(stream));
return stream;
}
@@ -195,10 +198,11 @@
TestStream* CreateIncomingStream(PendingStream pending) override {
QuicStreamId id = pending.id();
- TestStream* stream = new TestStream(
- std::move(pending), this,
- DetermineStreamType(id, connection()->transport_version(),
- /*is_incoming=*/true, BIDIRECTIONAL));
+ TestStream* stream =
+ new TestStream(std::move(pending), this,
+ DetermineStreamType(
+ id, connection()->transport_version(), perspective(),
+ /*is_incoming=*/true, BIDIRECTIONAL));
ActivateStream(QuicWrapUnique(stream));
return stream;
}
@@ -342,7 +346,7 @@
}
void CloseStream(QuicStreamId id) {
- if (transport_version() != QUIC_VERSION_99) {
+ if (!IsVersion99()) {
EXPECT_CALL(*connection_, SendControlFrame(_))
.WillOnce(Invoke(&session_, &TestSession::ClearControlFrame));
} else {
@@ -360,18 +364,19 @@
return connection_->transport_version();
}
+ bool IsVersion99() const { return transport_version() == QUIC_VERSION_99; }
+
QuicStreamId GetNthClientInitiatedBidirectionalId(int n) {
- return QuicSpdySessionPeer::GetNthClientInitiatedBidirectionalStreamId(
- session_, n);
+ return GetNthClientInitiatedBidirectionalStreamId(transport_version(), n);
}
QuicStreamId GetNthServerInitiatedBidirectionalId(int n) {
- return QuicSpdySessionPeer::GetNthServerInitiatedBidirectionalStreamId(
- session_, n);
+ return GetNthServerInitiatedBidirectionalStreamId(
+ connection_->transport_version(), n);
}
QuicStreamId IdDelta() {
- return QuicSpdySessionPeer::StreamIdDelta(session_);
+ return QuicUtils::StreamIdDelta(connection_->transport_version());
}
MockQuicConnectionHelper helper_;
@@ -388,12 +393,12 @@
: QuicSpdySessionTestBase(Perspective::IS_SERVER) {}
};
-INSTANTIATE_TEST_CASE_P(Tests,
- QuicSpdySessionTestServer,
- ::testing::ValuesIn(AllSupportedVersions()));
+INSTANTIATE_TEST_SUITE_P(Tests,
+ QuicSpdySessionTestServer,
+ ::testing::ValuesIn(AllSupportedVersions()));
TEST_P(QuicSpdySessionTestServer, ShouldBufferIncomingStreamUnidirectional) {
- if (connection_->transport_version() != QUIC_VERSION_99) {
+ if (!IsVersion99()) {
return;
}
EXPECT_TRUE(session_.ShouldBufferIncomingStream(
@@ -402,7 +407,7 @@
}
TEST_P(QuicSpdySessionTestServer, ShouldBufferIncomingStreamBidirectional) {
- if (connection_->transport_version() != QUIC_VERSION_99) {
+ if (!IsVersion99()) {
return;
}
EXPECT_FALSE(session_.ShouldBufferIncomingStream(
@@ -416,7 +421,7 @@
}
TEST_P(QuicSpdySessionTestServer, SelfAddress) {
- EXPECT_EQ(QuicSocketAddress(), session_.self_address());
+ EXPECT_TRUE(session_.self_address().IsInitialized());
}
TEST_P(QuicSpdySessionTestServer, IsCryptoHandshakeConfirmed) {
@@ -481,7 +486,7 @@
}
TEST_P(QuicSpdySessionTestServer, MaximumAvailableOpenedStreams) {
- if (transport_version() == QUIC_VERSION_99) {
+ if (IsVersion99()) {
// For IETF QUIC, we should be able to obtain the max allowed
// stream ID, the next ID should fail. Since the actual limit
// is not the number of open streams, we allocate the max and the max+2.
@@ -532,7 +537,7 @@
// A stream ID which is too large to create.
stream_id2 = GetNthClientInitiatedBidirectionalId(
2 * session_.MaxAvailableBidirectionalStreams() + 4);
- if (transport_version() == QUIC_VERSION_99) {
+ if (IsVersion99()) {
EXPECT_CALL(*connection_, CloseConnection(QUIC_INVALID_STREAM_ID, _, _));
} else {
EXPECT_CALL(*connection_,
@@ -670,7 +675,7 @@
}
TEST_P(QuicSpdySessionTestServer, OnCanWriteBundlesStreams) {
- if (transport_version() == QUIC_VERSION_99) {
+ if (IsVersion99()) {
EXPECT_CALL(*connection_, SendControlFrame(_))
.WillRepeatedly(Invoke(
this, &QuicSpdySessionTestServer::ClearMaxStreamIdControlFrame));
@@ -776,8 +781,6 @@
MockPacketWriter* writer = static_cast<MockPacketWriter*>(
QuicConnectionPeer::GetWriter(session_.connection()));
EXPECT_CALL(*writer, IsWriteBlocked()).WillRepeatedly(Return(true));
- EXPECT_CALL(*writer, IsWriteBlockedDataBuffered())
- .WillRepeatedly(Return(true));
EXPECT_CALL(*writer, WritePacket(_, _, _, _, _)).Times(0);
TestStream* stream2 = session_.CreateOutgoingBidirectionalStream();
@@ -908,7 +911,7 @@
}
TEST_P(QuicSpdySessionTestServer, SendGoAway) {
- if (transport_version() == QUIC_VERSION_99) {
+ if (IsVersion99()) {
// GoAway frames are not in version 99
return;
}
@@ -932,7 +935,7 @@
}
TEST_P(QuicSpdySessionTestServer, DoNotSendGoAwayTwice) {
- if (connection_->transport_version() == QUIC_VERSION_99) {
+ if (IsVersion99()) {
// TODO(b/118808809): Enable this test for version 99 when GOAWAY is
// supported.
return;
@@ -945,7 +948,7 @@
}
TEST_P(QuicSpdySessionTestServer, InvalidGoAway) {
- if (connection_->transport_version() == QUIC_VERSION_99) {
+ if (IsVersion99()) {
// TODO(b/118808809): Enable this test for version 99 when GOAWAY is
// supported.
return;
@@ -967,7 +970,7 @@
EXPECT_CALL(*connection_,
SendConnectivityProbingResponsePacket(new_peer_address));
- if (transport_version() == QUIC_VERSION_99) {
+ if (IsVersion99()) {
// Need to explicitly do this to emulate the reception of a PathChallenge,
// which stores its payload for use in generating the response.
connection_->OnPathChallengeFrame(
@@ -995,8 +998,12 @@
EXPECT_EQ(1u, session_.GetNumOpenIncomingStreams());
EXPECT_CALL(*connection_, SendControlFrame(_));
- EXPECT_CALL(*connection_,
- OnStreamReset(GetNthClientInitiatedBidirectionalId(0), _));
+ if (!IsVersion99()) {
+ // For version99, OnStreamReset gets called because of the STOP_SENDING,
+ // below. EXPECT the call there.
+ EXPECT_CALL(*connection_,
+ OnStreamReset(GetNthClientInitiatedBidirectionalId(0), _));
+ }
QuicRstStreamFrame rst1(kInvalidControlFrameId,
GetNthClientInitiatedBidirectionalId(0),
QUIC_ERROR_PROCESSING_STREAM, 0);
@@ -1005,7 +1012,7 @@
// Create and inject a STOP_SENDING frame. In GOOGLE QUIC, receiving a
// RST_STREAM frame causes a two-way close. For IETF QUIC, RST_STREAM causes a
// one-way close.
- if (transport_version() == QUIC_VERSION_99) {
+ if (IsVersion99()) {
// Only needed for version 99/IETF QUIC.
QuicStopSendingFrame stop_sending(
kInvalidControlFrameId, GetNthClientInitiatedBidirectionalId(0),
@@ -1088,7 +1095,7 @@
EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
EXPECT_CALL(*connection_, SendControlFrame(_)).Times(AtLeast(1));
- stream2->WriteOrBufferBody(body, false, nullptr);
+ stream2->WriteOrBufferBody(body, false);
EXPECT_TRUE(stream2->flow_controller()->IsBlocked());
EXPECT_TRUE(session_.IsConnectionFlowControlBlocked());
EXPECT_TRUE(session_.IsStreamFlowControlBlocked());
@@ -1106,6 +1113,11 @@
TEST_P(QuicSpdySessionTestServer,
HandshakeUnblocksFlowControlBlockedCryptoStream) {
+ if (GetParam().transport_version >= QUIC_VERSION_47) {
+ // QUIC version 47 onwards uses CRYPTO frames for the handshake, so this
+ // test doesn't make sense for those versions.
+ return;
+ }
// Test that if the crypto stream is flow control blocked, then if the SHLO
// contains a larger send window offset, the stream becomes unblocked.
session_.set_writev_consumes_all_data(true);
@@ -1118,10 +1130,9 @@
EXPECT_FALSE(headers_stream->flow_controller()->IsBlocked());
EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
- if (transport_version() == QUIC_VERSION_99) {
+ if (IsVersion99()) {
EXPECT_CALL(*connection_, SendControlFrame(_))
- .Times(1)
- .WillRepeatedly(Invoke(&session_, &TestSession::ClearControlFrame));
+ .WillOnce(Invoke(&session_, &TestSession::ClearControlFrame));
} else {
EXPECT_CALL(*connection_, SendControlFrame(_))
.WillOnce(Invoke(&session_, &TestSession::ClearControlFrame));
@@ -1190,12 +1201,14 @@
EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
headers["header"] = QuicStrCat(random.RandUint64(), random.RandUint64(),
random.RandUint64());
- session_.WriteHeaders(stream_id, headers.Clone(), true, 0, nullptr);
+ session_.WriteHeadersOnHeadersStream(stream_id, headers.Clone(), true, 0,
+ nullptr);
stream_id += IdDelta();
}
// Write once more to ensure that the headers stream has buffered data. The
// random headers may have exactly filled the flow control window.
- session_.WriteHeaders(stream_id, std::move(headers), true, 0, nullptr);
+ session_.WriteHeadersOnHeadersStream(stream_id, std::move(headers), true, 0,
+ nullptr);
EXPECT_TRUE(headers_stream->HasBufferedData());
EXPECT_TRUE(headers_stream->flow_controller()->IsBlocked());
@@ -1231,25 +1244,21 @@
const QuicStreamOffset kByteOffset =
1 + kInitialSessionFlowControlWindowForTest / 2;
- if (transport_version() != QUIC_VERSION_99) {
- EXPECT_CALL(*connection_, SendControlFrame(_))
- .Times(2)
- .WillRepeatedly(Invoke(&session_, &TestSession::ClearControlFrame));
- } else {
- // V99 has an additional, STOP_SENDING, frame and an additional RST_STREAM
- // (the response to the STOP_SENDING) frame.
- EXPECT_CALL(*connection_, SendControlFrame(_))
- .Times(4)
- .WillRepeatedly(Invoke(&session_, &TestSession::ClearControlFrame));
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .Times(2)
+ .WillRepeatedly(Invoke(&session_, &TestSession::ClearControlFrame));
+ if (!IsVersion99()) {
+ // For version99 the call to OnStreamReset happens as a result of receiving
+ // the STOP_SENDING, so set up the EXPECT there.
+ EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
}
- EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream->id(),
QUIC_STREAM_CANCELLED, kByteOffset);
session_.OnRstStream(rst_frame);
// Create and inject a STOP_SENDING frame. In GOOGLE QUIC, receiving a
// RST_STREAM frame causes a two-way close. For IETF QUIC, RST_STREAM causes a
// one-way close.
- if (transport_version() == QUIC_VERSION_99) {
+ if (IsVersion99()) {
// Only needed for version 99/IETF QUIC.
QuicStopSendingFrame stop_sending(
kInvalidControlFrameId, stream->id(),
@@ -1457,12 +1466,13 @@
GetNthClientInitiatedBidirectionalId(kMaxStreams);
// Create kMaxStreams data streams, and close them all without receiving a
// FIN or a RST_STREAM from the client.
- const QuicStreamId kNextId = QuicSpdySessionPeer::StreamIdDelta(session_);
+ const QuicStreamId kNextId =
+ QuicUtils::StreamIdDelta(connection_->transport_version());
for (QuicStreamId i = kFirstStreamId; i < kFinalStreamId; i += kNextId) {
QuicStreamFrame data1(i, false, 0, QuicStringPiece("HT"));
session_.OnStreamFrame(data1);
// EXPECT_EQ(1u, session_.GetNumOpenStreams());
- if (transport_version() != QUIC_VERSION_99) {
+ if (!IsVersion99()) {
EXPECT_CALL(*connection_, SendControlFrame(_))
.WillOnce(Invoke(&session_, &TestSession::ClearControlFrame));
} else {
@@ -1478,7 +1488,7 @@
session_.CloseStream(i);
}
// Try and open a stream that exceeds the limit.
- if (transport_version() != QUIC_VERSION_99) {
+ if (!IsVersion99()) {
// On versions other than 99, opening such a stream results in a
// RST_STREAM.
EXPECT_CALL(*connection_, SendControlFrame(_)).Times(1);
@@ -1499,7 +1509,7 @@
// Verify that a draining stream (which has received a FIN but not consumed
// it) does not count against the open quota (because it is closed from the
// protocol point of view).
- if (transport_version() == QUIC_VERSION_99) {
+ if (IsVersion99()) {
// Version 99 will result in a MAX_STREAM_ID frame as streams are consumed
// (via the OnStreamFrame call) and then released (via
// StreamDraining). Eventually this node will believe that the peer is
@@ -1532,9 +1542,9 @@
: QuicSpdySessionTestBase(Perspective::IS_CLIENT) {}
};
-INSTANTIATE_TEST_CASE_P(Tests,
- QuicSpdySessionTestClient,
- ::testing::ValuesIn(AllSupportedVersions()));
+INSTANTIATE_TEST_SUITE_P(Tests,
+ QuicSpdySessionTestClient,
+ ::testing::ValuesIn(AllSupportedVersions()));
TEST_P(QuicSpdySessionTestClient, AvailableStreamsClient) {
ASSERT_TRUE(session_.GetOrCreateDynamicStream(
@@ -1658,11 +1668,18 @@
// Lost data on cryption stream, streams 2 and 4.
EXPECT_CALL(*stream4, HasPendingRetransmission()).WillOnce(Return(true));
- EXPECT_CALL(*crypto_stream, HasPendingRetransmission())
- .WillOnce(Return(true));
+ if (connection_->transport_version() < QUIC_VERSION_47) {
+ EXPECT_CALL(*crypto_stream, HasPendingRetransmission())
+ .WillOnce(Return(true));
+ }
EXPECT_CALL(*stream2, HasPendingRetransmission()).WillOnce(Return(true));
session_.OnFrameLost(QuicFrame(frame3));
- session_.OnFrameLost(QuicFrame(frame1));
+ if (connection_->transport_version() < QUIC_VERSION_47) {
+ session_.OnFrameLost(QuicFrame(frame1));
+ } else {
+ QuicCryptoFrame crypto_frame(ENCRYPTION_NONE, 0, 1300);
+ session_.OnFrameLost(QuicFrame(&crypto_frame));
+ }
session_.OnFrameLost(QuicFrame(frame2));
EXPECT_TRUE(session_.WillingAndAbleToWrite());
@@ -1674,9 +1691,11 @@
// stream go first.
// Do not check congestion window when crypto stream has lost data.
EXPECT_CALL(*send_algorithm, CanSend(_)).Times(0);
- EXPECT_CALL(*crypto_stream, OnCanWrite());
- EXPECT_CALL(*crypto_stream, HasPendingRetransmission())
- .WillOnce(Return(false));
+ if (connection_->transport_version() < QUIC_VERSION_47) {
+ EXPECT_CALL(*crypto_stream, OnCanWrite());
+ EXPECT_CALL(*crypto_stream, HasPendingRetransmission())
+ .WillOnce(Return(false));
+ }
// Check congestion window for non crypto streams.
EXPECT_CALL(*send_algorithm, CanSend(_)).WillOnce(Return(true));
EXPECT_CALL(*stream4, OnCanWrite());
diff --git a/quic/core/http/quic_spdy_stream.cc b/quic/core/http/quic_spdy_stream.cc
index eb8135a..9e9f1b7 100644
--- a/quic/core/http/quic_spdy_stream.cc
+++ b/quic/core/http/quic_spdy_stream.cc
@@ -81,7 +81,9 @@
CloseConnectionOnWrongFrame("Headers");
}
- void OnHeadersFrameEnd() override { CloseConnectionOnWrongFrame("Headers"); }
+ void OnHeadersFrameEnd(QuicByteCount frame_len) override {
+ CloseConnectionOnWrongFrame("Headers");
+ }
void OnPushPromiseFrameStart(PushId push_id) override {
CloseConnectionOnWrongFrame("Push Promise");
@@ -121,7 +123,7 @@
trailers_consumed_(false),
http_decoder_visitor_(new HttpDecoderVisitor(this)),
body_buffer_(sequencer()),
- total_header_bytes_written_(0) {
+ ack_listener_(nullptr) {
DCHECK_NE(QuicUtils::GetCryptoStreamId(
spdy_session->connection()->transport_version()),
id);
@@ -129,7 +131,8 @@
// are complete.
sequencer()->SetBlockedUntilFlush();
- if (spdy_session_->connection()->transport_version() == QUIC_VERSION_99) {
+ if (VersionHasDataFrameHeader(
+ spdy_session_->connection()->transport_version())) {
sequencer()->set_level_triggered(true);
}
decoder_.set_visitor(http_decoder_visitor_.get());
@@ -146,7 +149,7 @@
trailers_consumed_(false),
http_decoder_visitor_(new HttpDecoderVisitor(this)),
body_buffer_(sequencer()),
- total_header_bytes_written_(0) {
+ ack_listener_(nullptr) {
DCHECK_NE(QuicUtils::GetCryptoStreamId(
spdy_session->connection()->transport_version()),
id());
@@ -154,7 +157,8 @@
// are complete.
sequencer()->SetBlockedUntilFlush();
- if (spdy_session_->connection()->transport_version() == QUIC_VERSION_99) {
+ if (VersionHasDataFrameHeader(
+ spdy_session_->connection()->transport_version())) {
sequencer()->set_level_triggered(true);
}
decoder_.set_visitor(http_decoder_visitor_.get());
@@ -166,8 +170,8 @@
SpdyHeaderBlock header_block,
bool fin,
QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
- size_t bytes_written = spdy_session_->WriteHeaders(
- id(), std::move(header_block), fin, priority(), std::move(ack_listener));
+ size_t bytes_written =
+ WriteHeadersImpl(std::move(header_block), fin, std::move(ack_listener));
if (fin) {
// TODO(rch): Add test to ensure fin_sent_ is set whenever a fin is sent.
set_fin_sent(true);
@@ -176,28 +180,32 @@
return bytes_written;
}
-void QuicSpdyStream::WriteOrBufferBody(
- QuicStringPiece data,
- bool fin,
- QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
- if (spdy_session_->connection()->transport_version() != QUIC_VERSION_99 ||
+void QuicSpdyStream::WriteOrBufferBody(QuicStringPiece data, bool fin) {
+ if (!VersionHasDataFrameHeader(
+ spdy_session_->connection()->transport_version()) ||
data.length() == 0) {
- WriteOrBufferData(data, fin, std::move(ack_listener));
+ WriteOrBufferData(data, fin, nullptr);
return;
}
QuicConnection::ScopedPacketFlusher flusher(
spdy_session_->connection(), QuicConnection::SEND_ACK_IF_PENDING);
+
+ // Write frame header.
std::unique_ptr<char[]> buffer;
QuicByteCount header_length =
encoder_.SerializeDataFrameHeader(data.length(), &buffer);
- WriteOrBufferData(QuicStringPiece(buffer.get(), header_length), false,
- nullptr);
+ unacked_frame_headers_offsets_.Add(
+ send_buffer().stream_offset(),
+ send_buffer().stream_offset() + header_length);
QUIC_DLOG(INFO) << "Stream " << id() << " is writing header of length "
<< header_length;
- total_header_bytes_written_ += header_length;
- WriteOrBufferData(data, fin, std::move(ack_listener));
+ WriteOrBufferData(QuicStringPiece(buffer.get(), header_length), false,
+ nullptr);
+
+ // Write body.
QUIC_DLOG(INFO) << "Stream " << id() << " is writing body of length "
<< data.length();
+ WriteOrBufferData(data, fin, nullptr);
}
size_t QuicSpdyStream::WriteTrailers(
@@ -221,8 +229,7 @@
// trailers are the last thing to be sent on a stream.
const bool kFin = true;
size_t bytes_written =
- spdy_session_->WriteHeaders(id(), std::move(trailer_block), kFin,
- priority(), std::move(ack_listener));
+ WriteHeadersImpl(std::move(trailer_block), kFin, std::move(ack_listener));
set_fin_sent(kFin);
// Trailers are the last thing to be sent on a stream, but if there is still
@@ -250,7 +257,8 @@
QuicConsumedData QuicSpdyStream::WriteBodySlices(QuicMemSliceSpan slices,
bool fin) {
- if (spdy_session_->connection()->transport_version() != QUIC_VERSION_99 ||
+ if (!VersionHasDataFrameHeader(
+ spdy_session_->connection()->transport_version()) ||
slices.empty()) {
return WriteMemSlices(slices, fin);
}
@@ -264,23 +272,30 @@
QuicConnection::ScopedPacketFlusher flusher(
spdy_session_->connection(), QuicConnection::SEND_ACK_IF_PENDING);
+
+ // Write frame header.
struct iovec header_iov = {static_cast<void*>(buffer.get()), header_length};
QuicMemSliceStorage storage(
&header_iov, 1,
spdy_session_->connection()->helper()->GetStreamSendBufferAllocator(),
GetQuicFlag(FLAGS_quic_send_buffer_max_data_slice_size));
- WriteMemSlices(storage.ToSpan(), false);
+ unacked_frame_headers_offsets_.Add(
+ send_buffer().stream_offset(),
+ send_buffer().stream_offset() + header_length);
QUIC_DLOG(INFO) << "Stream " << id() << " is writing header of length "
<< header_length;
- total_header_bytes_written_ += header_length;
- QUIC_DLOG(INFO) << "Stream" << id() << " is writing body of length "
+ WriteMemSlices(storage.ToSpan(), false);
+
+ // Write body.
+ QUIC_DLOG(INFO) << "Stream " << id() << " is writing body of length "
<< slices.total_length();
return WriteMemSlices(slices, fin);
}
size_t QuicSpdyStream::Readv(const struct iovec* iov, size_t iov_len) {
DCHECK(FinishedReadingHeaders());
- if (spdy_session_->connection()->transport_version() != QUIC_VERSION_99) {
+ if (!VersionHasDataFrameHeader(
+ spdy_session_->connection()->transport_version())) {
return sequencer()->Readv(iov, iov_len);
}
return body_buffer_.ReadBody(iov, iov_len);
@@ -288,7 +303,8 @@
int QuicSpdyStream::GetReadableRegions(iovec* iov, size_t iov_len) const {
DCHECK(FinishedReadingHeaders());
- if (spdy_session_->connection()->transport_version() != QUIC_VERSION_99) {
+ if (!VersionHasDataFrameHeader(
+ spdy_session_->connection()->transport_version())) {
return sequencer()->GetReadableRegions(iov, iov_len);
}
return body_buffer_.PeekBody(iov, iov_len);
@@ -296,8 +312,10 @@
void QuicSpdyStream::MarkConsumed(size_t num_bytes) {
DCHECK(FinishedReadingHeaders());
- if (spdy_session_->connection()->transport_version() != QUIC_VERSION_99) {
- return sequencer()->MarkConsumed(num_bytes);
+ if (!VersionHasDataFrameHeader(
+ spdy_session_->connection()->transport_version())) {
+ sequencer()->MarkConsumed(num_bytes);
+ return;
}
body_buffer_.MarkBodyConsumed(num_bytes);
}
@@ -310,7 +328,8 @@
}
bool QuicSpdyStream::HasBytesToRead() const {
- if (spdy_session_->connection()->transport_version() != QUIC_VERSION_99) {
+ if (!VersionHasDataFrameHeader(
+ spdy_session_->connection()->transport_version())) {
return sequencer()->HasBytesToRead();
}
return body_buffer_.HasBytesToRead();
@@ -321,7 +340,8 @@
}
uint64_t QuicSpdyStream::total_body_bytes_read() const {
- if (spdy_session_->connection()->transport_version() == QUIC_VERSION_99) {
+ if (VersionHasDataFrameHeader(
+ spdy_session_->connection()->transport_version())) {
return body_buffer_.total_body_bytes_received();
}
return sequencer()->NumBytesConsumed();
@@ -424,6 +444,14 @@
QuicStreamFrame(id(), fin, final_byte_offset, QuicStringPiece()));
}
+size_t QuicSpdyStream::WriteHeadersImpl(
+ spdy::SpdyHeaderBlock header_block,
+ bool fin,
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
+ return spdy_session_->WriteHeadersOnHeadersStream(
+ id(), std::move(header_block), fin, priority(), std::move(ack_listener));
+}
+
void QuicSpdyStream::OnPriorityFrame(SpdyPriority priority) {
DCHECK_EQ(Perspective::IS_SERVER, session()->connection()->perspective());
SetPriority(priority);
@@ -442,7 +470,8 @@
}
void QuicSpdyStream::OnDataAvailable() {
- if (session()->connection()->transport_version() != QUIC_VERSION_99) {
+ if (!VersionHasDataFrameHeader(
+ session()->connection()->transport_version())) {
OnBodyAvailable();
return;
}
@@ -543,5 +572,52 @@
<< body_buffer_.total_body_bytes_received();
}
+bool QuicSpdyStream::OnStreamFrameAcked(QuicStreamOffset offset,
+ QuicByteCount data_length,
+ bool fin_acked,
+ QuicTime::Delta ack_delay_time,
+ QuicByteCount* newly_acked_length) {
+ const bool new_data_acked = QuicStream::OnStreamFrameAcked(
+ offset, data_length, fin_acked, ack_delay_time, newly_acked_length);
+
+ const QuicByteCount newly_acked_header_length =
+ GetNumFrameHeadersInInterval(offset, data_length);
+ DCHECK_LE(newly_acked_header_length, *newly_acked_length);
+ unacked_frame_headers_offsets_.Difference(offset, offset + data_length);
+ if (ack_listener_ != nullptr && new_data_acked) {
+ ack_listener_->OnPacketAcked(
+ *newly_acked_length - newly_acked_header_length, ack_delay_time);
+ }
+ return new_data_acked;
+}
+
+void QuicSpdyStream::OnStreamFrameRetransmitted(QuicStreamOffset offset,
+ QuicByteCount data_length,
+ bool fin_retransmitted) {
+ QuicStream::OnStreamFrameRetransmitted(offset, data_length,
+ fin_retransmitted);
+
+ const QuicByteCount retransmitted_header_length =
+ GetNumFrameHeadersInInterval(offset, data_length);
+ DCHECK_LE(retransmitted_header_length, data_length);
+
+ if (ack_listener_ != nullptr) {
+ ack_listener_->OnPacketRetransmitted(data_length -
+ retransmitted_header_length);
+ }
+}
+
+QuicByteCount QuicSpdyStream::GetNumFrameHeadersInInterval(
+ QuicStreamOffset offset,
+ QuicByteCount data_length) const {
+ QuicByteCount header_acked_length = 0;
+ QuicIntervalSet<QuicStreamOffset> newly_acked(offset, offset + data_length);
+ newly_acked.Intersection(unacked_frame_headers_offsets_);
+ for (const auto& interval : newly_acked) {
+ header_acked_length += interval.Length();
+ }
+ return header_acked_length;
+}
+
#undef ENDPOINT // undef for jumbo builds
} // namespace quic
diff --git a/quic/core/http/quic_spdy_stream.h b/quic/core/http/quic_spdy_stream.h
index eccec56..2bad21a 100644
--- a/quic/core/http/quic_spdy_stream.h
+++ b/quic/core/http/quic_spdy_stream.h
@@ -31,6 +31,7 @@
namespace quic {
namespace test {
+class QuicSpdyStreamPeer;
class QuicStreamPeer;
} // namespace test
@@ -117,10 +118,7 @@
QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener);
// Sends |data| to the peer, or buffers if it can't be sent immediately.
- void WriteOrBufferBody(
- QuicStringPiece data,
- bool fin,
- QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener);
+ void WriteOrBufferBody(QuicStringPiece data, bool fin);
// Writes the trailers contained in |trailer_block| to the dedicated
// headers stream. Trailers will always have the FIN set.
@@ -128,6 +126,18 @@
spdy::SpdyHeaderBlock trailer_block,
QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener);
+ // Override to report newly acked bytes via ack_listener_.
+ bool OnStreamFrameAcked(QuicStreamOffset offset,
+ QuicByteCount data_length,
+ bool fin_acked,
+ QuicTime::Delta ack_delay_time,
+ QuicByteCount* newly_acked_length) override;
+
+ // Override to report bytes retransmitted via ack_listener_.
+ void OnStreamFrameRetransmitted(QuicStreamOffset offset,
+ QuicByteCount data_length,
+ bool fin_retransmitted) override;
+
// Does the same thing as WriteOrBufferBody except this method takes iovec
// as the data input. Right now it only calls WritevData.
// TODO(renjietang): Write data frame header before writing body.
@@ -166,10 +176,6 @@
bool headers_decompressed() const { return headers_decompressed_; }
- size_t total_header_bytes_written() const {
- return total_header_bytes_written_;
- }
-
// Returns total amount of body bytes that have been read.
uint64_t total_body_bytes_read() const;
@@ -210,16 +216,36 @@
virtual void OnTrailingHeadersComplete(bool fin,
size_t frame_len,
const QuicHeaderList& header_list);
+ virtual size_t WriteHeadersImpl(
+ spdy::SpdyHeaderBlock header_block,
+ bool fin,
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener);
+
QuicSpdySession* spdy_session() const { return spdy_session_; }
Visitor* visitor() { return visitor_; }
void set_headers_decompressed(bool val) { headers_decompressed_ = val; }
+ void set_ack_listener(
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
+ ack_listener_ = std::move(ack_listener);
+ }
+
+ const QuicIntervalSet<QuicStreamOffset>& unacked_frame_headers_offsets() {
+ return unacked_frame_headers_offsets_;
+ }
+
private:
+ friend class test::QuicSpdyStreamPeer;
friend class test::QuicStreamPeer;
friend class QuicStreamUtils;
class HttpDecoderVisitor;
+ // Given the interval marked by [|offset|, |offset| + |data_length|), return
+ // the number of frame header bytes contained in it.
+ QuicByteCount GetNumFrameHeadersInInterval(QuicStreamOffset offset,
+ QuicByteCount data_length) const;
+
QuicSpdySession* spdy_session_;
Visitor* visitor_;
@@ -244,8 +270,13 @@
std::unique_ptr<HttpDecoderVisitor> http_decoder_visitor_;
// Buffer that contains decoded data of the stream.
QuicSpdyStreamBodyBuffer body_buffer_;
- // Total bytes of header written to the stream.
- size_t total_header_bytes_written_;
+
+ // Ack listener of this stream, and it is notified when any of written bytes
+ // are acked or retransmitted.
+ QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener_;
+
+ // Offset of unacked frame headers.
+ QuicIntervalSet<QuicStreamOffset> unacked_frame_headers_offsets_;
};
} // namespace quic
diff --git a/quic/core/http/quic_spdy_stream_test.cc b/quic/core/http/quic_spdy_stream_test.cc
index 07bb9ed..1aabe0e 100644
--- a/quic/core/http/quic_spdy_stream_test.cc
+++ b/quic/core/http/quic_spdy_stream_test.cc
@@ -12,6 +12,7 @@
#include "net/third_party/quiche/src/quic/core/quic_connection.h"
#include "net/third_party/quiche/src/quic/core/quic_stream_sequencer_buffer.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
+#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/core/quic_write_blocked_list.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
@@ -24,6 +25,7 @@
#include "net/third_party/quiche/src/quic/test_tools/quic_flow_controller_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_session_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h"
+#include "net/third_party/quiche/src/quic/test_tools/quic_spdy_stream_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_stream_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
@@ -32,7 +34,7 @@
using spdy::SpdyHeaderBlock;
using spdy::SpdyPriority;
using testing::_;
-using testing::AnyNumber;
+using testing::AtLeast;
using testing::Invoke;
using testing::Return;
using testing::StrictMock;
@@ -50,6 +52,11 @@
bool should_process_data)
: QuicSpdyStream(id, session, BIDIRECTIONAL),
should_process_data_(should_process_data) {}
+ ~TestStream() override = default;
+
+ using QuicSpdyStream::set_ack_listener;
+ using QuicStream::CloseWriteSide;
+ using QuicStream::WriteOrBufferData;
void OnBodyAvailable() override {
if (!should_process_data_) {
@@ -63,14 +70,23 @@
data_ += QuicString(buffer, bytes_read);
}
- using QuicSpdyStream::set_ack_listener;
- using QuicStream::CloseWriteSide;
- using QuicStream::WriteOrBufferData;
+ MOCK_METHOD1(WriteHeadersMock, void(bool fin));
+
+ size_t WriteHeadersImpl(spdy::SpdyHeaderBlock header_block,
+ bool fin,
+ QuicReferenceCountedPointer<QuicAckListenerInterface>
+ ack_listener) override {
+ saved_headers_ = std::move(header_block);
+ WriteHeadersMock(fin);
+ return 0;
+ }
const QuicString& data() const { return data_; }
+ const spdy::SpdyHeaderBlock& saved_headers() const { return saved_headers_; }
private:
bool should_process_data_;
+ spdy::SpdyHeaderBlock saved_headers_;
QuicString data_;
};
@@ -128,17 +144,21 @@
}
void Initialize(bool stream_should_process_data) {
- connection_ = new testing::StrictMock<MockQuicConnection>(
+ connection_ = new StrictMock<MockQuicConnection>(
&helper_, &alarm_factory_, Perspective::IS_SERVER,
SupportedVersions(GetParam()));
- session_ =
- QuicMakeUnique<testing::StrictMock<MockQuicSpdySession>>(connection_);
+ session_ = QuicMakeUnique<StrictMock<MockQuicSpdySession>>(connection_);
session_->Initialize();
- stream_ = new TestStream(GetNthClientInitiatedBidirectionalId(0),
- session_.get(), stream_should_process_data);
+ ON_CALL(*session_, WritevData(_, _, _, _, _))
+ .WillByDefault(Invoke(MockQuicSession::ConsumeData));
+
+ stream_ =
+ new StrictMock<TestStream>(GetNthClientInitiatedBidirectionalId(0),
+ session_.get(), stream_should_process_data);
session_->ActivateStream(QuicWrapUnique(stream_));
- stream2_ = new TestStream(GetNthClientInitiatedBidirectionalId(1),
- session_.get(), stream_should_process_data);
+ stream2_ =
+ new StrictMock<TestStream>(GetNthClientInitiatedBidirectionalId(1),
+ session_.get(), stream_should_process_data);
session_->ActivateStream(QuicWrapUnique(stream2_));
}
@@ -149,8 +169,12 @@
}
QuicStreamId GetNthClientInitiatedBidirectionalId(int n) {
- return QuicSpdySessionPeer::GetNthClientInitiatedBidirectionalStreamId(
- *session_, n);
+ return GetNthClientInitiatedBidirectionalStreamId(
+ connection_->transport_version(), n);
+ }
+
+ bool HasFrameHeader() const {
+ return VersionHasDataFrameHeader(connection_->transport_version());
}
protected:
@@ -168,9 +192,8 @@
HttpEncoder encoder_;
};
-INSTANTIATE_TEST_CASE_P(Tests,
- QuicSpdyStreamTest,
- ::testing::ValuesIn(AllSupportedVersions()));
+INSTANTIATE_TEST_SUITE_P(Tests, QuicSpdyStreamTest,
+ ::testing::ValuesIn(AllSupportedVersions()));
TEST_P(QuicSpdyStreamTest, ProcessHeaderList) {
Initialize(kShouldProcessData);
@@ -288,9 +311,7 @@
QuicByteCount header_length =
encoder_.SerializeDataFrameHeader(body.length(), &buffer);
QuicString header = QuicString(buffer.get(), header_length);
- QuicString data = connection_->transport_version() == QUIC_VERSION_99
- ? header + body
- : body;
+ QuicString data = HasFrameHeader() ? header + body : body;
EXPECT_EQ("", stream_->data());
QuicHeaderList headers = ProcessHeaders(false, headers_);
@@ -310,9 +331,7 @@
QuicByteCount header_length =
encoder_.SerializeDataFrameHeader(body.length(), &buffer);
QuicString header = QuicString(buffer.get(), header_length);
- QuicString data = connection_->transport_version() == QUIC_VERSION_99
- ? header + body
- : body;
+ QuicString data = HasFrameHeader() ? header + body : body;
for (size_t fragment_size = 1; fragment_size < data.size(); ++fragment_size) {
Initialize(kShouldProcessData);
@@ -338,9 +357,7 @@
QuicByteCount header_length =
encoder_.SerializeDataFrameHeader(body.length(), &buffer);
QuicString header = QuicString(buffer.get(), header_length);
- QuicString data = connection_->transport_version() == QUIC_VERSION_99
- ? header + body
- : body;
+ QuicString data = HasFrameHeader() ? header + body : body;
for (size_t split_point = 1; split_point < data.size() - 1; ++split_point) {
Initialize(kShouldProcessData);
@@ -371,9 +388,7 @@
QuicByteCount header_length =
encoder_.SerializeDataFrameHeader(body.length(), &buf);
QuicString header = QuicString(buf.get(), header_length);
- QuicString data = connection_->transport_version() == QUIC_VERSION_99
- ? header + body
- : body;
+ QuicString data = HasFrameHeader() ? header + body : body;
ProcessHeaders(false, headers_);
QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), false, 0,
@@ -399,9 +414,7 @@
QuicByteCount header_length =
encoder_.SerializeDataFrameHeader(body.length(), &buf);
QuicString header = QuicString(buf.get(), header_length);
- QuicString data = connection_->transport_version() == QUIC_VERSION_99
- ? header + body
- : body;
+ QuicString data = HasFrameHeader() ? header + body : body;
ProcessHeaders(false, headers_);
QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), false, 0,
QuicStringPiece(data));
@@ -428,9 +441,7 @@
QuicByteCount header_length =
encoder_.SerializeDataFrameHeader(body.length(), &buf);
QuicString header = QuicString(buf.get(), header_length);
- QuicString data = connection_->transport_version() == QUIC_VERSION_99
- ? header + body
- : body;
+ QuicString data = HasFrameHeader() ? header + body : body;
ProcessHeaders(false, headers_);
QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), false, 0,
@@ -456,13 +467,9 @@
QuicByteCount header_length =
encoder_.SerializeDataFrameHeader(body1.length(), &buf);
QuicString header = QuicString(buf.get(), header_length);
- QuicString data1 = connection_->transport_version() == QUIC_VERSION_99
- ? header + body1
- : body1;
+ QuicString data1 = HasFrameHeader() ? header + body1 : body1;
header_length = encoder_.SerializeDataFrameHeader(body2.length(), &buf);
- QuicString data2 = connection_->transport_version() == QUIC_VERSION_99
- ? header + body2
- : body2;
+ QuicString data2 = HasFrameHeader() ? header + body2 : body2;
ProcessHeaders(false, headers_);
QuicStreamFrame frame1(GetNthClientInitiatedBidirectionalId(0), false, 0,
@@ -486,9 +493,7 @@
QuicByteCount header_length =
encoder_.SerializeDataFrameHeader(body.length(), &buf);
QuicString header = QuicString(buf.get(), header_length);
- QuicString data = connection_->transport_version() == QUIC_VERSION_99
- ? header + body
- : body;
+ QuicString data = HasFrameHeader() ? header + body : body;
ProcessHeaders(false, headers_);
QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), false, 0,
@@ -516,9 +521,7 @@
QuicByteCount header_length =
encoder_.SerializeDataFrameHeader(body.length(), &buf);
QuicString header = QuicString(buf.get(), header_length);
- QuicString data = connection_->transport_version() == QUIC_VERSION_99
- ? header + body
- : body;
+ QuicString data = HasFrameHeader() ? header + body : body;
ProcessHeaders(false, headers_);
QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), false, 0,
@@ -558,17 +561,15 @@
// Try to send more data than the flow control limit allows.
const uint64_t kOverflow = 15;
QuicString body(kWindow + kOverflow, 'a');
- bool is_version_99 = connection_->transport_version() == QUIC_VERSION_99;
- const uint64_t kHeaderLength = is_version_99 ? 2 : 0;
- if (is_version_99) {
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
- .WillOnce(Return(QuicConsumedData(2, false)));
+ const uint64_t kHeaderLength = HasFrameHeader() ? 2 : 0;
+ if (HasFrameHeader()) {
+ EXPECT_CALL(*session_, WritevData(_, _, kHeaderLength, _, NO_FIN));
}
EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
.WillOnce(Return(QuicConsumedData(kWindow - kHeaderLength, true)));
EXPECT_CALL(*connection_, SendControlFrame(_));
- stream_->WriteOrBufferBody(body, false, nullptr);
+ stream_->WriteOrBufferBody(body, false);
// Should have sent as much as possible, resulting in no send window left.
EXPECT_EQ(0u,
@@ -605,7 +606,7 @@
QuicByteCount header_length = 0;
QuicString data;
- if (connection_->transport_version() == QUIC_VERSION_99) {
+ if (HasFrameHeader()) {
std::unique_ptr<char[]> buffer;
header_length = encoder_.SerializeDataFrameHeader(body.length(), &buffer);
QuicString header = QuicString(buffer.get(), header_length);
@@ -654,7 +655,7 @@
QuicByteCount header_length = 0;
QuicString data;
- if (connection_->transport_version() == QUIC_VERSION_99) {
+ if (HasFrameHeader()) {
std::unique_ptr<char[]> buffer;
header_length = encoder_.SerializeDataFrameHeader(body.length(), &buffer);
QuicString header = QuicString(buffer.get(), header_length);
@@ -723,7 +724,7 @@
QuicString data2;
QuicString body2(1, 'a');
- if (connection_->transport_version() == QUIC_VERSION_99) {
+ if (HasFrameHeader()) {
body = QuicString(kWindow / 4 - 2, 'a');
std::unique_ptr<char[]> buffer;
header_length = encoder_.SerializeDataFrameHeader(body.length(), &buffer);
@@ -777,9 +778,7 @@
QuicByteCount header_length =
encoder_.SerializeDataFrameHeader(body.length(), &buf);
QuicString header = QuicString(buf.get(), header_length);
- QuicString data = connection_->transport_version() == QUIC_VERSION_99
- ? header + body
- : body;
+ QuicString data = HasFrameHeader() ? header + body : body;
QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), false, 0,
QuicStringPiece(data));
EXPECT_CALL(*connection_,
@@ -822,9 +821,7 @@
QuicByteCount header_length =
encoder_.SerializeDataFrameHeader(body.length(), &buf);
QuicString header = QuicString(buf.get(), header_length);
- QuicString data = connection_->transport_version() == QUIC_VERSION_99
- ? header + body
- : body;
+ QuicString data = HasFrameHeader() ? header + body : body;
EXPECT_LT(data.size(), kStreamWindow);
QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), false, 0,
@@ -853,10 +850,9 @@
EXPECT_CALL(*connection_,
SendBlocked(GetNthClientInitiatedBidirectionalId(0)))
.Times(0);
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
- .WillOnce(Return(QuicConsumedData(0, fin)));
+ EXPECT_CALL(*session_, WritevData(_, _, 0, _, FIN));
- stream_->WriteOrBufferBody(body, fin, nullptr);
+ stream_->WriteOrBufferBody(body, fin);
}
TEST_P(QuicSpdyStreamTest, ReceivingTrailersViaHeaderList) {
@@ -915,9 +911,7 @@
QuicByteCount header_length =
encoder_.SerializeDataFrameHeader(body.length(), &buf);
QuicString header = QuicString(buf.get(), header_length);
- QuicString data = connection_->transport_version() == QUIC_VERSION_99
- ? header + body
- : body;
+ QuicString data = HasFrameHeader() ? header + body : body;
// Receive trailing headers.
SpdyHeaderBlock trailers_block;
@@ -1052,9 +1046,7 @@
QuicByteCount header_length =
encoder_.SerializeDataFrameHeader(body.length(), &buf);
QuicString header = QuicString(buf.get(), header_length);
- QuicString data = connection_->transport_version() == QUIC_VERSION_99
- ? header + body
- : body;
+ QuicString data = HasFrameHeader() ? header + body : body;
QuicStreamFrame frame(GetNthClientInitiatedBidirectionalId(0), /*fin=*/true,
0, data);
@@ -1067,18 +1059,15 @@
// Test that writing trailers will send a FIN, as Trailers are the last thing
// to be sent on a stream.
Initialize(kShouldProcessData);
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
- .Times(AnyNumber())
- .WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
// Write the initial headers, without a FIN.
- EXPECT_CALL(*session_, WriteHeadersMock(_, _, _, _, _));
+ EXPECT_CALL(*stream_, WriteHeadersMock(false));
stream_->WriteHeaders(SpdyHeaderBlock(), /*fin=*/false, nullptr);
// Writing trailers implicitly sends a FIN.
SpdyHeaderBlock trailers;
trailers["trailer key"] = "trailer value";
- EXPECT_CALL(*session_, WriteHeadersMock(_, _, true, _, _));
+ EXPECT_CALL(*stream_, WriteHeadersMock(true));
stream_->WriteTrailers(std::move(trailers), nullptr);
EXPECT_TRUE(stream_->fin_sent());
}
@@ -1087,23 +1076,21 @@
// Test that when writing trailers, the trailers that are actually sent to the
// peer contain the final offset field indicating last byte of data.
Initialize(kShouldProcessData);
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
- .Times(AnyNumber())
- .WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
// Write the initial headers.
- EXPECT_CALL(*session_, WriteHeadersMock(_, _, _, _, _));
+ EXPECT_CALL(*stream_, WriteHeadersMock(false));
stream_->WriteHeaders(SpdyHeaderBlock(), /*fin=*/false, nullptr);
// Write non-zero body data to force a non-zero final offset.
- QuicString body(1024, 'x'); // 1 MB
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _)).Times(AtLeast(1));
+ QuicString body(1024, 'x'); // 1 kB
QuicByteCount header_length = 0;
- if (connection_->transport_version() == QUIC_VERSION_99) {
+ if (HasFrameHeader()) {
std::unique_ptr<char[]> buf;
header_length = encoder_.SerializeDataFrameHeader(body.length(), &buf);
}
- stream_->WriteOrBufferBody(body, false, nullptr);
+ stream_->WriteOrBufferBody(body, false);
// The final offset field in the trailing headers is populated with the
// number of body bytes written (including queued bytes).
@@ -1112,31 +1099,29 @@
SpdyHeaderBlock trailers_with_offset(trailers.Clone());
trailers_with_offset[kFinalOffsetHeaderKey] =
QuicTextUtils::Uint64ToString(body.length() + header_length);
- EXPECT_CALL(*session_, WriteHeadersMock(_, _, true, _, _));
+ EXPECT_CALL(*stream_, WriteHeadersMock(true));
stream_->WriteTrailers(std::move(trailers), nullptr);
- EXPECT_EQ(trailers_with_offset, session_->GetWriteHeaders());
+ EXPECT_EQ(trailers_with_offset, stream_->saved_headers());
}
TEST_P(QuicSpdyStreamTest, WritingTrailersClosesWriteSide) {
// Test that if trailers are written after all other data has been written
// (headers and body), that this closes the stream for writing.
Initialize(kShouldProcessData);
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
- .Times(AnyNumber())
- .WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
// Write the initial headers.
- EXPECT_CALL(*session_, WriteHeadersMock(_, _, _, _, _));
+ EXPECT_CALL(*stream_, WriteHeadersMock(false));
stream_->WriteHeaders(SpdyHeaderBlock(), /*fin=*/false, nullptr);
// Write non-zero body data.
- const int kBodySize = 1 * 1024; // 1 MB
- stream_->WriteOrBufferBody(QuicString(kBodySize, 'x'), false, nullptr);
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _)).Times(AtLeast(1));
+ const int kBodySize = 1 * 1024; // 1 kB
+ stream_->WriteOrBufferBody(QuicString(kBodySize, 'x'), false);
EXPECT_EQ(0u, stream_->BufferedDataBytes());
// Headers and body have been fully written, there is no queued data. Writing
// trailers marks the end of this stream, and thus the write side is closed.
- EXPECT_CALL(*session_, WriteHeadersMock(_, _, true, _, _));
+ EXPECT_CALL(*stream_, WriteHeadersMock(true));
stream_->WriteTrailers(SpdyHeaderBlock(), nullptr);
EXPECT_TRUE(stream_->write_side_closed());
}
@@ -1146,35 +1131,30 @@
// while there are still body bytes queued.
testing::InSequence seq;
Initialize(kShouldProcessData);
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
- .Times(AnyNumber())
- .WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
// Write the initial headers.
- EXPECT_CALL(*session_, WriteHeadersMock(_, _, _, _, _));
+ EXPECT_CALL(*stream_, WriteHeadersMock(false));
stream_->WriteHeaders(SpdyHeaderBlock(), /*fin=*/false, nullptr);
// Write non-zero body data, but only consume partially, ensuring queueing.
- const int kBodySize = 1 * 1024; // 1 KB
- if (connection_->transport_version() == QUIC_VERSION_99) {
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
- .WillOnce(Return(QuicConsumedData(3, false)));
+ const int kBodySize = 1 * 1024; // 1 kB
+ if (HasFrameHeader()) {
+ EXPECT_CALL(*session_, WritevData(_, _, 3, _, NO_FIN));
}
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
+ EXPECT_CALL(*session_, WritevData(_, _, kBodySize, _, NO_FIN))
.WillOnce(Return(QuicConsumedData(kBodySize - 1, false)));
- stream_->WriteOrBufferBody(QuicString(kBodySize, 'x'), false, nullptr);
+ stream_->WriteOrBufferBody(QuicString(kBodySize, 'x'), false);
EXPECT_EQ(1u, stream_->BufferedDataBytes());
// Writing trailers will send a FIN, but not close the write side of the
// stream as there are queued bytes.
- EXPECT_CALL(*session_, WriteHeadersMock(_, _, true, _, _));
+ EXPECT_CALL(*stream_, WriteHeadersMock(true));
stream_->WriteTrailers(SpdyHeaderBlock(), nullptr);
EXPECT_TRUE(stream_->fin_sent());
EXPECT_FALSE(stream_->write_side_closed());
// Writing the queued bytes will close the write side of the stream.
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
- .WillOnce(Return(QuicConsumedData(1, false)));
+ EXPECT_CALL(*session_, WritevData(_, _, 1, _, NO_FIN));
stream_->OnCanWrite();
EXPECT_TRUE(stream_->write_side_closed());
}
@@ -1187,12 +1167,9 @@
// Test that it is not possible to write Trailers after a FIN has been sent.
Initialize(kShouldProcessData);
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
- .Times(AnyNumber())
- .WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
// Write the initial headers, with a FIN.
- EXPECT_CALL(*session_, WriteHeadersMock(_, _, _, _, _));
+ EXPECT_CALL(*stream_, WriteHeadersMock(true));
stream_->WriteHeaders(SpdyHeaderBlock(), /*fin=*/true, nullptr);
EXPECT_TRUE(stream_->fin_sent());
@@ -1204,9 +1181,7 @@
TEST_P(QuicSpdyStreamTest, HeaderStreamNotiferCorrespondingSpdyStream) {
Initialize(kShouldProcessData);
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
- .Times(AnyNumber())
- .WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _)).Times(AtLeast(1));
testing::InSequence s;
QuicReferenceCountedPointer<MockAckListener> ack_listener1(
new MockAckListener());
@@ -1217,20 +1192,26 @@
session_->headers_stream()->WriteOrBufferData("Header1", false,
ack_listener1);
- stream_->WriteOrBufferBody("Test1", true, nullptr);
+ stream_->WriteOrBufferBody("Test1", true);
session_->headers_stream()->WriteOrBufferData("Header2", false,
ack_listener2);
- stream2_->WriteOrBufferBody("Test2", false, nullptr);
+ stream2_->WriteOrBufferBody("Test2", false);
QuicStreamFrame frame1(
QuicUtils::GetHeadersStreamId(connection_->transport_version()), false, 0,
"Header1");
- QuicStreamFrame frame2(stream_->id(), true, 0, "Test1");
+ QuicString header = "";
+ if (HasFrameHeader()) {
+ std::unique_ptr<char[]> buffer;
+ QuicByteCount header_length = encoder_.SerializeDataFrameHeader(5, &buffer);
+ header = QuicString(buffer.get(), header_length);
+ }
+ QuicStreamFrame frame2(stream_->id(), true, 0, header + "Test1");
QuicStreamFrame frame3(
QuicUtils::GetHeadersStreamId(connection_->transport_version()), false, 7,
"Header2");
- QuicStreamFrame frame4(stream2_->id(), false, 0, "Test2");
+ QuicStreamFrame frame4(stream2_->id(), false, 0, header + "Test2");
EXPECT_CALL(*ack_listener1, OnPacketRetransmitted(7));
session_->OnStreamFrameRetransmitted(frame1);
@@ -1251,12 +1232,10 @@
TEST_P(QuicSpdyStreamTest, StreamBecomesZombieWithWriteThatCloses) {
Initialize(kShouldProcessData);
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
- .Times(AnyNumber())
- .WillRepeatedly(Invoke(MockQuicSession::ConsumeData));
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _)).Times(AtLeast(1));
QuicStreamPeer::CloseReadSide(stream_);
// This write causes stream to be closed.
- stream_->WriteOrBufferBody("Test1", true, nullptr);
+ stream_->WriteOrBufferBody("Test1", true);
// stream_ has unacked data and should become zombie.
EXPECT_TRUE(QuicContainsKey(QuicSessionPeer::zombie_streams(session_.get()),
stream_->id()));
@@ -1273,26 +1252,24 @@
testing::InSequence seq;
Initialize(kShouldProcessData);
- if (connection_->transport_version() == QUIC_VERSION_99) {
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
- .WillOnce(Return(QuicConsumedData(2, false)));
+ if (HasFrameHeader()) {
+ EXPECT_CALL(*session_, WritevData(_, _, 2, _, NO_FIN));
}
- EXPECT_CALL(*session_, WritevData(_, _, _, _, _))
- .WillOnce(Return(QuicConsumedData(4, true)));
- stream_->WriteOrBufferBody("data", true, nullptr);
+ EXPECT_CALL(*session_, WritevData(_, _, 4, _, FIN));
+ stream_->WriteOrBufferBody("data", true);
stream_->OnPriorityFrame(kV3HighestPriority);
EXPECT_EQ(kV3HighestPriority, stream_->priority());
}
TEST_P(QuicSpdyStreamTest, SetPriorityBeforeUpdateStreamPriority) {
- MockQuicConnection* connection = new testing::StrictMock<MockQuicConnection>(
+ MockQuicConnection* connection = new StrictMock<MockQuicConnection>(
&helper_, &alarm_factory_, Perspective::IS_SERVER,
SupportedVersions(GetParam()));
std::unique_ptr<TestMockUpdateStreamSession> session(
- new testing::StrictMock<TestMockUpdateStreamSession>(connection));
- TestStream* stream = new TestStream(
- QuicSpdySessionPeer::GetNthClientInitiatedBidirectionalStreamId(*session,
- 0),
+ new StrictMock<TestMockUpdateStreamSession>(connection));
+ auto stream = new StrictMock<TestStream>(
+ GetNthClientInitiatedBidirectionalStreamId(
+ session->connection()->transport_version(), 0),
session.get(),
/*should_process_data=*/true);
session->ActivateStream(QuicWrapUnique(stream));
@@ -1309,6 +1286,233 @@
stream->SetPriority(kV3LowestPriority);
}
+TEST_P(QuicSpdyStreamTest, StreamWaitsForAcks) {
+ Initialize(kShouldProcessData);
+ QuicReferenceCountedPointer<MockAckListener> mock_ack_listener(
+ new StrictMock<MockAckListener>);
+ stream_->set_ack_listener(mock_ack_listener);
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _)).Times(AtLeast(1));
+ // Stream is not waiting for acks initially.
+ EXPECT_FALSE(stream_->IsWaitingForAcks());
+ EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
+
+ // Send kData1.
+ stream_->WriteOrBufferData("FooAndBar", false, nullptr);
+ EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size());
+ EXPECT_TRUE(stream_->IsWaitingForAcks());
+ EXPECT_CALL(*mock_ack_listener, OnPacketAcked(9, _));
+ QuicByteCount newly_acked_length = 0;
+ EXPECT_TRUE(stream_->OnStreamFrameAcked(0, 9, false, QuicTime::Delta::Zero(),
+ &newly_acked_length));
+ // Stream is not waiting for acks as all sent data is acked.
+ EXPECT_FALSE(stream_->IsWaitingForAcks());
+ EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
+
+ // Send kData2.
+ stream_->WriteOrBufferData("FooAndBar", false, nullptr);
+ EXPECT_TRUE(stream_->IsWaitingForAcks());
+ EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size());
+ // Send FIN.
+ stream_->WriteOrBufferData("", true, nullptr);
+ // Fin only frame is not stored in send buffer.
+ EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size());
+
+ // kData2 is retransmitted.
+ EXPECT_CALL(*mock_ack_listener, OnPacketRetransmitted(9));
+ stream_->OnStreamFrameRetransmitted(9, 9, false);
+
+ // kData2 is acked.
+ EXPECT_CALL(*mock_ack_listener, OnPacketAcked(9, _));
+ EXPECT_TRUE(stream_->OnStreamFrameAcked(9, 9, false, QuicTime::Delta::Zero(),
+ &newly_acked_length));
+ // Stream is waiting for acks as FIN is not acked.
+ EXPECT_TRUE(stream_->IsWaitingForAcks());
+ EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
+
+ // FIN is acked.
+ EXPECT_CALL(*mock_ack_listener, OnPacketAcked(0, _));
+ EXPECT_TRUE(stream_->OnStreamFrameAcked(18, 0, true, QuicTime::Delta::Zero(),
+ &newly_acked_length));
+ EXPECT_FALSE(stream_->IsWaitingForAcks());
+ EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
+}
+
+TEST_P(QuicSpdyStreamTest, StreamDataGetAckedMultipleTimes) {
+ Initialize(kShouldProcessData);
+ QuicReferenceCountedPointer<MockAckListener> mock_ack_listener(
+ new StrictMock<MockAckListener>);
+ stream_->set_ack_listener(mock_ack_listener);
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _)).Times(AtLeast(1));
+ // Send [0, 27) and fin.
+ stream_->WriteOrBufferData("FooAndBar", false, nullptr);
+ stream_->WriteOrBufferData("FooAndBar", false, nullptr);
+ stream_->WriteOrBufferData("FooAndBar", true, nullptr);
+
+ // Ack [0, 9), [5, 22) and [18, 26)
+ // Verify [0, 9) 9 bytes are acked.
+ QuicByteCount newly_acked_length = 0;
+ EXPECT_CALL(*mock_ack_listener, OnPacketAcked(9, _));
+ EXPECT_TRUE(stream_->OnStreamFrameAcked(0, 9, false, QuicTime::Delta::Zero(),
+ &newly_acked_length));
+ EXPECT_EQ(2u, QuicStreamPeer::SendBuffer(stream_).size());
+ // Verify [9, 22) 13 bytes are acked.
+ EXPECT_CALL(*mock_ack_listener, OnPacketAcked(13, _));
+ EXPECT_TRUE(stream_->OnStreamFrameAcked(5, 17, false, QuicTime::Delta::Zero(),
+ &newly_acked_length));
+ EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size());
+ // Verify [22, 26) 4 bytes are acked.
+ EXPECT_CALL(*mock_ack_listener, OnPacketAcked(4, _));
+ EXPECT_TRUE(stream_->OnStreamFrameAcked(18, 8, false, QuicTime::Delta::Zero(),
+ &newly_acked_length));
+ EXPECT_EQ(1u, QuicStreamPeer::SendBuffer(stream_).size());
+ EXPECT_TRUE(stream_->IsWaitingForAcks());
+
+ // Ack [0, 27).
+ // Verify [26, 27) 1 byte is acked.
+ EXPECT_CALL(*mock_ack_listener, OnPacketAcked(1, _));
+ EXPECT_TRUE(stream_->OnStreamFrameAcked(26, 1, false, QuicTime::Delta::Zero(),
+ &newly_acked_length));
+ EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
+ EXPECT_TRUE(stream_->IsWaitingForAcks());
+
+ // Ack Fin. Verify OnPacketAcked is called.
+ EXPECT_CALL(*mock_ack_listener, OnPacketAcked(0, _));
+ EXPECT_TRUE(stream_->OnStreamFrameAcked(27, 0, true, QuicTime::Delta::Zero(),
+ &newly_acked_length));
+ EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
+ EXPECT_FALSE(stream_->IsWaitingForAcks());
+
+ // Ack [10, 27) and fin.
+ // No new data is acked, verify OnPacketAcked is not called.
+ EXPECT_CALL(*mock_ack_listener, OnPacketAcked(_, _)).Times(0);
+ EXPECT_FALSE(stream_->OnStreamFrameAcked(
+ 10, 17, true, QuicTime::Delta::Zero(), &newly_acked_length));
+ EXPECT_EQ(0u, QuicStreamPeer::SendBuffer(stream_).size());
+ EXPECT_FALSE(stream_->IsWaitingForAcks());
+}
+
+// HTTP/3 only.
+TEST_P(QuicSpdyStreamTest, HeadersAckNotReportedWriteOrBufferBody) {
+ Initialize(kShouldProcessData);
+ if (!HasFrameHeader()) {
+ return;
+ }
+ QuicReferenceCountedPointer<MockAckListener> mock_ack_listener(
+ new StrictMock<MockAckListener>);
+ stream_->set_ack_listener(mock_ack_listener);
+ QuicString body = "Test1";
+ QuicString body2(100, 'x');
+
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _)).Times(AtLeast(1));
+ stream_->WriteOrBufferBody(body, false);
+ stream_->WriteOrBufferBody(body2, true);
+
+ std::unique_ptr<char[]> buffer;
+ QuicByteCount header_length =
+ encoder_.SerializeDataFrameHeader(body.length(), &buffer);
+ QuicString header = QuicString(buffer.get(), header_length);
+
+ header_length = encoder_.SerializeDataFrameHeader(body2.length(), &buffer);
+ QuicString header2 = QuicString(buffer.get(), header_length);
+
+ EXPECT_CALL(*mock_ack_listener, OnPacketAcked(body.length(), _));
+ QuicStreamFrame frame(stream_->id(), false, 0, header + body);
+ EXPECT_TRUE(
+ session_->OnFrameAcked(QuicFrame(frame), QuicTime::Delta::Zero()));
+
+ EXPECT_CALL(*mock_ack_listener, OnPacketAcked(0, _));
+ QuicStreamFrame frame2(stream_->id(), false, (header + body).length(),
+ header2);
+ EXPECT_TRUE(
+ session_->OnFrameAcked(QuicFrame(frame2), QuicTime::Delta::Zero()));
+
+ EXPECT_CALL(*mock_ack_listener, OnPacketAcked(body2.length(), _));
+ QuicStreamFrame frame3(stream_->id(), true,
+ (header + body).length() + header2.length(), body2);
+ EXPECT_TRUE(
+ session_->OnFrameAcked(QuicFrame(frame3), QuicTime::Delta::Zero()));
+
+ EXPECT_TRUE(
+ QuicSpdyStreamPeer::unacked_frame_headers_offsets(stream_).Empty());
+}
+
+// HTTP/3 only.
+TEST_P(QuicSpdyStreamTest, HeadersAckNotReportedWriteBodySlices) {
+ Initialize(kShouldProcessData);
+ if (!HasFrameHeader()) {
+ return;
+ }
+ QuicReferenceCountedPointer<MockAckListener> mock_ack_listener(
+ new StrictMock<MockAckListener>);
+ stream_->set_ack_listener(mock_ack_listener);
+ QuicString body = "Test1";
+ QuicString body2(100, 'x');
+ struct iovec body1_iov = {const_cast<char*>(body.data()), body.length()};
+ struct iovec body2_iov = {const_cast<char*>(body2.data()), body2.length()};
+ QuicMemSliceStorage storage(&body1_iov, 1,
+ helper_.GetStreamSendBufferAllocator(), 1024);
+ QuicMemSliceStorage storage2(&body2_iov, 1,
+ helper_.GetStreamSendBufferAllocator(), 1024);
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _)).Times(AtLeast(1));
+ stream_->WriteBodySlices(storage.ToSpan(), false);
+ stream_->WriteBodySlices(storage2.ToSpan(), true);
+
+ std::unique_ptr<char[]> buffer;
+ QuicByteCount header_length =
+ encoder_.SerializeDataFrameHeader(body.length(), &buffer);
+ QuicString header = QuicString(buffer.get(), header_length);
+
+ header_length = encoder_.SerializeDataFrameHeader(body2.length(), &buffer);
+ QuicString header2 = QuicString(buffer.get(), header_length);
+
+ EXPECT_CALL(*mock_ack_listener,
+ OnPacketAcked(body.length() + body2.length(), _));
+ QuicStreamFrame frame(stream_->id(), true, 0,
+ header + body + header2 + body2);
+ EXPECT_TRUE(
+ session_->OnFrameAcked(QuicFrame(frame), QuicTime::Delta::Zero()));
+
+ EXPECT_TRUE(
+ QuicSpdyStreamPeer::unacked_frame_headers_offsets(stream_).Empty());
+}
+
+// HTTP/3 only.
+TEST_P(QuicSpdyStreamTest, HeaderBytesNotReportedOnRetransmission) {
+ Initialize(kShouldProcessData);
+ if (!HasFrameHeader()) {
+ return;
+ }
+ QuicReferenceCountedPointer<MockAckListener> mock_ack_listener(
+ new StrictMock<MockAckListener>);
+ stream_->set_ack_listener(mock_ack_listener);
+ QuicString body = "Test1";
+ QuicString body2(100, 'x');
+
+ EXPECT_CALL(*session_, WritevData(_, _, _, _, _)).Times(AtLeast(1));
+ stream_->WriteOrBufferBody(body, false);
+ stream_->WriteOrBufferBody(body2, true);
+
+ std::unique_ptr<char[]> buffer;
+ QuicByteCount header_length =
+ encoder_.SerializeDataFrameHeader(body.length(), &buffer);
+ QuicString header = QuicString(buffer.get(), header_length);
+
+ header_length = encoder_.SerializeDataFrameHeader(body2.length(), &buffer);
+ QuicString header2 = QuicString(buffer.get(), header_length);
+
+ EXPECT_CALL(*mock_ack_listener, OnPacketRetransmitted(body.length()));
+ QuicStreamFrame frame(stream_->id(), false, 0, header + body);
+ session_->OnStreamFrameRetransmitted(frame);
+
+ EXPECT_CALL(*mock_ack_listener, OnPacketRetransmitted(body2.length()));
+ QuicStreamFrame frame2(stream_->id(), true, (header + body).length(),
+ header2 + body2);
+ session_->OnStreamFrameRetransmitted(frame2);
+
+ EXPECT_FALSE(
+ QuicSpdyStreamPeer::unacked_frame_headers_offsets(stream_).Empty());
+}
+
} // namespace
} // namespace test
} // namespace quic
diff --git a/quic/core/http/spdy_utils.cc b/quic/core/http/spdy_utils.cc
index d8fc79d..aa6d6e7 100644
--- a/quic/core/http/spdy_utils.cc
+++ b/quic/core/http/spdy_utils.cc
@@ -255,12 +255,12 @@
// Validate the scheme; this is to ensure a scheme of "foo://bar" is not
// parsed as a URL of "foo://bar://baz" when combined with a host of "baz".
std::string canonical_scheme;
- url::StdStringCanonOutput canon_output(&canonical_scheme);
+ url::StdStringCanonOutput canon_scheme_output(&canonical_scheme);
url::Component canon_component;
url::Component scheme_component(0, scheme.size());
- if (!url::CanonicalizeScheme(scheme.data(), scheme_component, &canon_output,
- &canon_component) ||
+ if (!url::CanonicalizeScheme(scheme.data(), scheme_component,
+ &canon_scheme_output, &canon_component) ||
!canon_component.is_nonempty() || canon_component.begin != 0) {
return QuicString();
}
@@ -304,13 +304,13 @@
}
}
- // Validate the host by attempting to canoncalize it. Invalid characters
+ // Validate the host by attempting to canonicalize it. Invalid characters
// will result in a canonicalization failure (e.g. '/')
std::string canon_host;
- canon_output = url::StdStringCanonOutput(&canon_host);
+ url::StdStringCanonOutput canon_host_output(&canon_host);
canon_component.reset();
- if (!url::CanonicalizeHost(authority.data(), host_component, &canon_output,
- &canon_component) ||
+ if (!url::CanonicalizeHost(authority.data(), host_component,
+ &canon_host_output, &canon_component) ||
!canon_component.is_nonempty() || canon_component.begin != 0) {
return QuicString();
}
diff --git a/quic/core/qpack/offline/qpack_offline_decoder_bin.cc b/quic/core/qpack/offline/qpack_offline_decoder_bin.cc
index 499c9fd..9d2be7c 100644
--- a/quic/core/qpack/offline/qpack_offline_decoder_bin.cc
+++ b/quic/core/qpack/offline/qpack_offline_decoder_bin.cc
@@ -12,18 +12,21 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
int main(int argc, char* argv[]) {
- InitGoogle(argv[0], &argc, &argv, false);
+ const char* usage =
+ "Usage: qpack_offline_decoder input_filename expected_headers_filename "
+ "....";
+ std::vector<quic::QuicString> args =
+ quic::QuicParseCommandLineFlags(usage, argc, argv);
- if (argc < 3 || argc % 2 != 1) {
- QUIC_LOG(ERROR) << "Usage: " << argv[0]
- << " input_filename expected_headers_filename ...";
+ if (args.size() < 2 || args.size() % 2 != 0) {
+ quic::QuicPrintCommandLineFlagHelp(usage);
return 1;
}
- int i;
- for (i = 0; 2 * i + 1 < argc; ++i) {
- const quic::QuicStringPiece input_filename(argv[2 * i + 1]);
- const quic::QuicStringPiece expected_headers_filename(argv[2 * i + 2]);
+ size_t i;
+ for (i = 0; 2 * i < args.size(); ++i) {
+ const quic::QuicStringPiece input_filename(args[2 * i]);
+ const quic::QuicStringPiece expected_headers_filename(args[2 * i + 1]);
// Every file represents a different connection,
// therefore every file needs a fresh decoding context.
diff --git a/quic/core/qpack/qpack_decoded_headers_accumulator.cc b/quic/core/qpack/qpack_decoded_headers_accumulator.cc
new file mode 100644
index 0000000..ac60fce
--- /dev/null
+++ b/quic/core/qpack/qpack_decoded_headers_accumulator.cc
@@ -0,0 +1,70 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/core/qpack/qpack_decoded_headers_accumulator.h"
+
+#include "net/third_party/quiche/src/quic/core/qpack/qpack_decoder.h"
+
+namespace quic {
+
+QpackDecodedHeadersAccumulator::QpackDecodedHeadersAccumulator(
+ QuicStreamId id,
+ QpackDecoder* qpack_decoder)
+ : decoder_(qpack_decoder->DecodeHeaderBlock(id, this)),
+ uncompressed_header_bytes_(0),
+ compressed_header_bytes_(0),
+ error_detected_(false) {
+ quic_header_list_.OnHeaderBlockStart();
+}
+
+void QpackDecodedHeadersAccumulator::OnHeaderDecoded(QuicStringPiece name,
+ QuicStringPiece value) {
+ DCHECK(!error_detected_);
+
+ uncompressed_header_bytes_ += name.size() + value.size();
+ quic_header_list_.OnHeader(name, value);
+}
+
+void QpackDecodedHeadersAccumulator::OnDecodingCompleted() {}
+
+void QpackDecodedHeadersAccumulator::OnDecodingErrorDetected(
+ QuicStringPiece error_message) {
+ DCHECK(!error_detected_);
+
+ error_detected_ = true;
+ // Copy error message to ensure it remains valid for the lifetime of |this|.
+ error_message_.assign(error_message.data(), error_message.size());
+}
+
+bool QpackDecodedHeadersAccumulator::Decode(QuicStringPiece data) {
+ DCHECK(!error_detected_);
+
+ compressed_header_bytes_ += data.size();
+ decoder_->Decode(data);
+
+ return !error_detected_;
+}
+
+bool QpackDecodedHeadersAccumulator::EndHeaderBlock() {
+ DCHECK(!error_detected_);
+
+ decoder_->EndHeaderBlock();
+
+ quic_header_list_.OnHeaderBlockEnd(uncompressed_header_bytes_,
+ compressed_header_bytes_);
+
+ return !error_detected_;
+}
+
+const QuicHeaderList& QpackDecodedHeadersAccumulator::quic_header_list() const {
+ DCHECK(!error_detected_);
+ return quic_header_list_;
+}
+
+QuicStringPiece QpackDecodedHeadersAccumulator::error_message() const {
+ DCHECK(error_detected_);
+ return error_message_;
+}
+
+} // namespace quic
diff --git a/quic/core/qpack/qpack_decoded_headers_accumulator.h b/quic/core/qpack/qpack_decoded_headers_accumulator.h
new file mode 100644
index 0000000..47d4f63
--- /dev/null
+++ b/quic/core/qpack/qpack_decoded_headers_accumulator.h
@@ -0,0 +1,64 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_QUIC_CORE_QPACK_QPACK_DECODED_HEADERS_ACCUMULATOR_H_
+#define QUICHE_QUIC_CORE_QPACK_QPACK_DECODED_HEADERS_ACCUMULATOR_H_
+
+#include <cstddef>
+
+#include "net/third_party/quiche/src/quic/core/http/quic_header_list.h"
+#include "net/third_party/quiche/src/quic/core/qpack/qpack_progressive_decoder.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_string.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+
+namespace quic {
+
+class QpackDecoder;
+
+// A class that creates and owns a QpackProgressiveDecoder instance, accumulates
+// decoded headers in a QuicHeaderList, and keeps track of uncompressed and
+// compressed size so that it can be passed to QuicHeaderList::EndHeaderBlock().
+class QUIC_EXPORT_PRIVATE QpackDecodedHeadersAccumulator
+ : public QpackProgressiveDecoder::HeadersHandlerInterface {
+ public:
+ QpackDecodedHeadersAccumulator(QuicStreamId id, QpackDecoder* qpack_decoder);
+ virtual ~QpackDecodedHeadersAccumulator() = default;
+
+ // QpackProgressiveDecoder::HeadersHandlerInterface implementation.
+ // These methods should only be called by |decoder_|.
+ void OnHeaderDecoded(QuicStringPiece name, QuicStringPiece value) override;
+ void OnDecodingCompleted() override;
+ void OnDecodingErrorDetected(QuicStringPiece error_message) override;
+
+ // Decode payload data. Returns true on success, false on error.
+ // Must not be called if an error has been detected.
+ // Must not be called after EndHeaderBlock().
+ bool Decode(QuicStringPiece data);
+
+ // Signal end of HEADERS frame. Returns true on success, false on error.
+ // Must not be called if an error has been detected.
+ // Must not be called more that once.
+ bool EndHeaderBlock();
+
+ // Returns accumulated header list.
+ const QuicHeaderList& quic_header_list() const;
+
+ // Returns error message.
+ // Must not be called unless an error has been detected.
+ QuicStringPiece error_message() const;
+
+ private:
+ std::unique_ptr<QpackProgressiveDecoder> decoder_;
+ QuicHeaderList quic_header_list_;
+ size_t uncompressed_header_bytes_;
+ size_t compressed_header_bytes_;
+ bool error_detected_;
+ QuicString error_message_;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_QPACK_QPACK_DECODED_HEADERS_ACCUMULATOR_H_
diff --git a/quic/core/qpack/qpack_decoded_headers_accumulator_test.cc b/quic/core/qpack/qpack_decoded_headers_accumulator_test.cc
new file mode 100644
index 0000000..0c71b19
--- /dev/null
+++ b/quic/core/qpack/qpack_decoded_headers_accumulator_test.cc
@@ -0,0 +1,100 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/core/qpack/qpack_decoded_headers_accumulator.h"
+
+#include <cstring>
+
+#include "net/third_party/quiche/src/quic/core/qpack/qpack_decoder.h"
+#include "net/third_party/quiche/src/quic/core/qpack/qpack_decoder_test_utils.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+
+using ::testing::Eq;
+using ::testing::StrictMock;
+
+namespace quic {
+namespace test {
+namespace {
+
+QuicStreamId kTestStreamId = 1;
+
+// Header Acknowledgement decoder stream instruction with stream_id = 1.
+const char* const kHeaderAcknowledgement = "\x81";
+
+} // anonymous namespace
+
+class QpackDecodedHeadersAccumulatorTest : public QuicTest {
+ protected:
+ QpackDecodedHeadersAccumulatorTest()
+ : qpack_decoder_(&encoder_stream_error_delegate_,
+ &decoder_stream_sender_delegate_),
+ accumulator_(kTestStreamId, &qpack_decoder_) {}
+
+ NoopEncoderStreamErrorDelegate encoder_stream_error_delegate_;
+ StrictMock<MockDecoderStreamSenderDelegate> decoder_stream_sender_delegate_;
+ QpackDecoder qpack_decoder_;
+ QpackDecodedHeadersAccumulator accumulator_;
+};
+
+// HEADERS frame payload must have a complete Header Block Prefix.
+TEST_F(QpackDecodedHeadersAccumulatorTest, EmptyPayload) {
+ EXPECT_FALSE(accumulator_.EndHeaderBlock());
+ EXPECT_EQ("Incomplete header data prefix.", accumulator_.error_message());
+}
+
+// HEADERS frame payload must have a complete Header Block Prefix.
+TEST_F(QpackDecodedHeadersAccumulatorTest, TruncatedHeaderBlockPrefix) {
+ EXPECT_TRUE(accumulator_.Decode(QuicTextUtils::HexDecode("00")));
+ EXPECT_FALSE(accumulator_.EndHeaderBlock());
+ EXPECT_EQ("Incomplete header data prefix.", accumulator_.error_message());
+}
+
+TEST_F(QpackDecodedHeadersAccumulatorTest, EmptyHeaderList) {
+ EXPECT_CALL(decoder_stream_sender_delegate_,
+ WriteDecoderStreamData(Eq(kHeaderAcknowledgement)));
+
+ EXPECT_TRUE(accumulator_.Decode(QuicTextUtils::HexDecode("0000")));
+ EXPECT_TRUE(accumulator_.EndHeaderBlock());
+
+ EXPECT_TRUE(accumulator_.quic_header_list().empty());
+}
+
+// This payload is the prefix of a valid payload, but EndHeaderBlock() is called
+// before it can be completely decoded.
+TEST_F(QpackDecodedHeadersAccumulatorTest, TruncatedPayload) {
+ EXPECT_TRUE(accumulator_.Decode(QuicTextUtils::HexDecode("00002366")));
+ EXPECT_FALSE(accumulator_.EndHeaderBlock());
+ EXPECT_EQ("Incomplete header block.", accumulator_.error_message());
+}
+
+// This payload is invalid because it refers to a non-existing static entry.
+TEST_F(QpackDecodedHeadersAccumulatorTest, InvalidPayload) {
+ EXPECT_FALSE(accumulator_.Decode(QuicTextUtils::HexDecode("0000ff23ff24")));
+ EXPECT_EQ("Static table entry not found.", accumulator_.error_message());
+}
+
+TEST_F(QpackDecodedHeadersAccumulatorTest, Success) {
+ EXPECT_CALL(decoder_stream_sender_delegate_,
+ WriteDecoderStreamData(Eq(kHeaderAcknowledgement)));
+
+ QuicString encoded_data(QuicTextUtils::HexDecode("000023666f6f03626172"));
+ EXPECT_TRUE(accumulator_.Decode(encoded_data));
+ EXPECT_TRUE(accumulator_.EndHeaderBlock());
+
+ auto header_list = accumulator_.quic_header_list();
+ auto it = header_list.begin();
+ EXPECT_TRUE(it != header_list.end());
+ EXPECT_EQ("foo", it->first);
+ EXPECT_EQ("bar", it->second);
+ ++it;
+ EXPECT_TRUE(it == header_list.end());
+
+ EXPECT_EQ(strlen("foo") + strlen("bar"),
+ header_list.uncompressed_header_bytes());
+ EXPECT_EQ(encoded_data.size(), header_list.compressed_header_bytes());
+}
+
+} // namespace test
+} // namespace quic
diff --git a/quic/core/qpack/qpack_decoder_test.cc b/quic/core/qpack/qpack_decoder_test.cc
index 52f739c..7292c50 100644
--- a/quic/core/qpack/qpack_decoder_test.cc
+++ b/quic/core/qpack/qpack_decoder_test.cc
@@ -62,10 +62,8 @@
const FragmentMode fragment_mode_;
};
-INSTANTIATE_TEST_CASE_P(,
- QpackDecoderTest,
- Values(FragmentMode::kSingleChunk,
- FragmentMode::kOctetByOctet));
+INSTANTIATE_TEST_SUITE_P(, QpackDecoderTest, Values(FragmentMode::kSingleChunk,
+ FragmentMode::kOctetByOctet));
TEST_P(QpackDecoderTest, NoPrefix) {
EXPECT_CALL(handler_,
diff --git a/quic/core/qpack/qpack_decoder_test_utils.h b/quic/core/qpack/qpack_decoder_test_utils.h
index 937ecfc..ca5b608 100644
--- a/quic/core/qpack/qpack_decoder_test_utils.h
+++ b/quic/core/qpack/qpack_decoder_test_utils.h
@@ -96,9 +96,9 @@
public:
~NoOpHeadersHandler() override = default;
- void OnHeaderDecoded(QuicStringPiece name, QuicStringPiece value) override{};
- void OnDecodingCompleted() override{};
- void OnDecodingErrorDetected(QuicStringPiece error_message) override{};
+ void OnHeaderDecoded(QuicStringPiece name, QuicStringPiece value) override {}
+ void OnDecodingCompleted() override {}
+ void OnDecodingErrorDetected(QuicStringPiece error_message) override {}
};
void QpackDecode(
diff --git a/quic/core/qpack/qpack_encoder_test.cc b/quic/core/qpack/qpack_encoder_test.cc
index e3dba00..6dea968 100644
--- a/quic/core/qpack/qpack_encoder_test.cc
+++ b/quic/core/qpack/qpack_encoder_test.cc
@@ -37,10 +37,10 @@
const FragmentMode fragment_mode_;
};
-INSTANTIATE_TEST_CASE_P(,
- QpackEncoderTest,
- Values(FragmentMode::kSingleChunk,
- FragmentMode::kOctetByOctet));
+INSTANTIATE_TEST_SUITE_P(,
+ QpackEncoderTest,
+ Values(FragmentMode::kSingleChunk,
+ FragmentMode::kOctetByOctet));
TEST_P(QpackEncoderTest, Empty) {
spdy::SpdyHeaderBlock header_list;
diff --git a/quic/core/qpack/qpack_instruction_decoder_test.cc b/quic/core/qpack/qpack_instruction_decoder_test.cc
index d1fe9b5..08557ec 100644
--- a/quic/core/qpack/qpack_instruction_decoder_test.cc
+++ b/quic/core/qpack/qpack_instruction_decoder_test.cc
@@ -101,10 +101,10 @@
const FragmentMode fragment_mode_;
};
-INSTANTIATE_TEST_CASE_P(,
- QpackInstructionDecoderTest,
- Values(FragmentMode::kSingleChunk,
- FragmentMode::kOctetByOctet));
+INSTANTIATE_TEST_SUITE_P(,
+ QpackInstructionDecoderTest,
+ Values(FragmentMode::kSingleChunk,
+ FragmentMode::kOctetByOctet));
TEST_P(QpackInstructionDecoderTest, SBitAndVarint2) {
EXPECT_CALL(delegate_, OnInstructionDecoded(TestInstruction1()));
diff --git a/quic/core/qpack/qpack_instruction_encoder_test.cc b/quic/core/qpack/qpack_instruction_encoder_test.cc
index 255520e..006476f 100644
--- a/quic/core/qpack/qpack_instruction_encoder_test.cc
+++ b/quic/core/qpack/qpack_instruction_encoder_test.cc
@@ -43,10 +43,10 @@
const FragmentMode fragment_mode_;
};
-INSTANTIATE_TEST_CASE_P(,
- QpackInstructionEncoderTest,
- Values(FragmentMode::kSingleChunk,
- FragmentMode::kOctetByOctet));
+INSTANTIATE_TEST_SUITE_P(,
+ QpackInstructionEncoderTest,
+ Values(FragmentMode::kSingleChunk,
+ FragmentMode::kOctetByOctet));
TEST_P(QpackInstructionEncoderTest, Varint) {
const QpackInstruction instruction{QpackInstructionOpcode{0x00, 0x80},
diff --git a/quic/core/qpack/qpack_round_trip_test.cc b/quic/core/qpack/qpack_round_trip_test.cc
index b9c6300..700ff85 100644
--- a/quic/core/qpack/qpack_round_trip_test.cc
+++ b/quic/core/qpack/qpack_round_trip_test.cc
@@ -56,7 +56,7 @@
const FragmentMode decoding_fragment_mode_;
};
-INSTANTIATE_TEST_CASE_P(
+INSTANTIATE_TEST_SUITE_P(
,
QpackRoundTripTest,
Combine(Values(FragmentMode::kSingleChunk, FragmentMode::kOctetByOctet),
diff --git a/quic/core/quic_arena_scoped_ptr_test.cc b/quic/core/quic_arena_scoped_ptr_test.cc
index 52a8ae2..109fd37 100644
--- a/quic/core/quic_arena_scoped_ptr_test.cc
+++ b/quic/core/quic_arena_scoped_ptr_test.cc
@@ -42,10 +42,10 @@
QuicOneBlockArena<1024> arena_;
};
-INSTANTIATE_TEST_CASE_P(QuicArenaScopedPtrParamTest,
- QuicArenaScopedPtrParamTest,
- testing::Values(TestParam::kFromHeap,
- TestParam::kFromArena));
+INSTANTIATE_TEST_SUITE_P(QuicArenaScopedPtrParamTest,
+ QuicArenaScopedPtrParamTest,
+ testing::Values(TestParam::kFromHeap,
+ TestParam::kFromArena));
TEST_P(QuicArenaScopedPtrParamTest, NullObjects) {
QuicArenaScopedPtr<TestObject> def;
diff --git a/quic/core/quic_config.cc b/quic/core/quic_config.cc
index ce6f9ea..e53719c 100644
--- a/quic/core/quic_config.cc
+++ b/quic/core/quic_config.cc
@@ -14,6 +14,7 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_macros.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
@@ -492,7 +493,7 @@
}
// TODO(ianswett) Use this for silent close on mobile, or delete.
-ABSL_ATTRIBUTE_UNUSED void QuicConfig::SetSilentClose(bool silent_close) {
+QUIC_UNUSED void QuicConfig::SetSilentClose(bool silent_close) {
silent_close_.set(silent_close ? 1 : 0, silent_close ? 1 : 0);
}
diff --git a/quic/core/quic_connection.cc b/quic/core/quic_connection.cc
index d4c13c4..6346ae0 100644
--- a/quic/core/quic_connection.cc
+++ b/quic/core/quic_connection.cc
@@ -26,6 +26,7 @@
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_error_code_wrappers.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_exported_stats.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
@@ -43,10 +44,6 @@
namespace {
-// Maximum number of acks received before sending an ack in response.
-// TODO(fayang): Remove this constant when deprecating QUIC_VERSION_35.
-const QuicPacketCount kMaxPacketsReceivedBeforeAckSend = 20;
-
// Maximum number of consecutive sent nonretransmittable packets.
const QuicPacketCount kMaxConsecutiveNonRetransmittablePackets = 19;
@@ -63,10 +60,6 @@
// One eighth RTT delay when doing ack decimation.
const float kShortAckDecimationDelay = 0.125;
-// Error code used in WriteResult to indicate that the packet writer rejected
-// the message as being too big.
-const int kMessageTooBigErrorCode = EMSGSIZE;
-
// The minimum release time into future in ms.
const int kMinReleaseTimeIntoFutureMs = 1;
@@ -338,9 +331,7 @@
processing_ack_frame_(false),
supports_release_time_(false),
release_time_into_future_(QuicTime::Delta::Zero()),
- no_version_negotiation_(supported_versions.size() == 1),
- clear_probing_mark_after_packet_processing_(GetQuicReloadableFlag(
- quic_clear_probing_mark_after_packet_processing)) {
+ no_version_negotiation_(supported_versions.size() == 1) {
if (ack_mode_ == ACK_DECIMATION) {
QUIC_RELOADABLE_FLAG_COUNT(quic_enable_ack_decimation);
}
@@ -466,8 +457,7 @@
if (config.HasClientSentConnectionOption(k5RTO, perspective_)) {
close_connection_after_five_rtos_ = true;
}
- if (transport_version() != QUIC_VERSION_35 &&
- config.HasClientSentConnectionOption(kNSTP, perspective_)) {
+ if (config.HasClientSentConnectionOption(kNSTP, perspective_)) {
no_stop_waiting_frames_ = true;
}
if (config.HasReceivedStatelessResetToken()) {
@@ -688,6 +678,7 @@
server_supported_versions_ = packet.versions;
if (GetQuicReloadableFlag(quic_no_client_conn_ver_negotiation)) {
+ QUIC_RELOADABLE_FLAG_COUNT(quic_no_client_conn_ver_negotiation);
CloseConnection(
QUIC_INVALID_VERSION,
QuicStrCat(
@@ -815,6 +806,10 @@
if (level == ENCRYPTION_FORWARD_SECURE &&
perspective_ == Perspective::IS_SERVER) {
sent_packet_manager_.SetHandshakeConfirmed();
+ if (sent_packet_manager_.unacked_packets().use_uber_loss_algorithm()) {
+ // This may have changed the retransmission timer, so re-arm it.
+ SetRetransmissionAlarm();
+ }
}
}
@@ -909,11 +904,11 @@
return false;
}
- QUIC_BUG << ENDPOINT
- << "Received an unencrypted data frame: closing connection"
- << " packet_number:" << last_header_.packet_number
- << " stream_id:" << frame.stream_id
- << " received_packets:" << received_packet_manager_.ack_frame();
+ QUIC_PEER_BUG << ENDPOINT
+ << "Received an unencrypted data frame: closing connection"
+ << " packet_number:" << last_header_.packet_number
+ << " stream_id:" << frame.stream_id << " received_packets:"
+ << received_packet_manager_.ack_frame();
CloseConnection(QUIC_UNENCRYPTED_STREAM_DATA,
"Unencrypted stream data seen.",
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
@@ -926,8 +921,15 @@
}
bool QuicConnection::OnCryptoFrame(const QuicCryptoFrame& frame) {
- // TODO(nharper): Implement.
- return false;
+ DCHECK(connected_);
+
+ // Since a CRYPTO frame was received, this is not a connectivity probe.
+ // A probe only contains a PING and full padding.
+ UpdatePacketContent(NOT_PADDED_PING);
+
+ visitor_->OnCryptoFrame(frame);
+ should_last_packet_instigate_acks_ = true;
+ return connected_;
}
bool QuicConnection::OnAckFrameStart(QuicPacketNumber largest_acked,
@@ -1335,7 +1337,8 @@
if (debug_visitor_ != nullptr) {
debug_visitor_->OnMessageFrame(frame);
}
- visitor_->OnMessageReceived(frame.message_data);
+ visitor_->OnMessageReceived(
+ QuicStringPiece(frame.data, frame.message_length));
should_last_packet_instigate_acks_ = true;
return connected_;
}
@@ -1454,14 +1457,6 @@
void QuicConnection::MaybeQueueAck(bool was_missing) {
++num_packets_received_since_last_ack_sent_;
- // Always send an ack every 20 packets in order to allow the peer to discard
- // information from the SentPacketManager and provide an RTT measurement.
- if (transport_version() == QUIC_VERSION_35 &&
- num_packets_received_since_last_ack_sent_ >=
- kMaxPacketsReceivedBeforeAckSend) {
- ack_queued_ = true;
- }
-
// Determine whether the newly received packet was missing before recording
// the received packet.
if (was_missing) {
@@ -1478,10 +1473,9 @@
if (should_last_packet_instigate_acks_ && !ack_queued_) {
++num_retransmittable_packets_received_since_last_ack_sent_;
if (ack_mode_ != TCP_ACKING &&
- // TODO(fayang): Fix this as this check assumes the first received
- // packet is 1.
- last_header_.packet_number >
- QuicPacketNumber(min_received_before_ack_decimation_)) {
+ last_header_.packet_number >=
+ received_packet_manager_.PeerFirstSendingPacketNumber() +
+ min_received_before_ack_decimation_) {
// Ack up to 10 packets at once unless ack decimation is unlimited.
if (!unlimited_ack_decimation_ &&
num_retransmittable_packets_received_since_last_ack_sent_ >=
@@ -1566,7 +1560,9 @@
sent_packet_manager_.GetLeastUnacked() + max_tracked_packets_) {
CloseConnection(
QUIC_TOO_MANY_OUTSTANDING_SENT_PACKETS,
- QuicStrCat("More than ", max_tracked_packets_, " outstanding."),
+ QuicStrCat("More than ", max_tracked_packets_,
+ " outstanding, least_unacked: ",
+ sent_packet_manager_.GetLeastUnacked().ToUint64()),
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
}
}
@@ -1648,6 +1644,18 @@
pending_version_negotiation_packet_ = false;
}
+size_t QuicConnection::SendCryptoData(EncryptionLevel level,
+ size_t write_length,
+ QuicStreamOffset offset) {
+ if (write_length == 0) {
+ QUIC_BUG << "Attempt to send empty crypto frame";
+ return 0;
+ }
+
+ ScopedPacketFlusher flusher(this, SEND_ACK_IF_PENDING);
+ return packet_generator_.ConsumeCryptoData(level, write_length, offset);
+}
+
QuicConsumedData QuicConnection::SendStreamData(QuicStreamId id,
size_t write_length,
QuicStreamOffset offset,
@@ -1746,6 +1754,10 @@
return stats_;
}
+void QuicConnection::OnCoalescedPacket(const QuicEncryptedPacket& packet) {
+ QueueCoalescedPacket(packet);
+}
+
void QuicConnection::ProcessUdpPacket(const QuicSocketAddress& self_address,
const QuicSocketAddress& peer_address,
const QuicReceivedPacket& packet) {
@@ -1813,13 +1825,9 @@
<< "Unable to process packet. Last packet processed: "
<< last_header_.packet_number;
current_packet_data_ = nullptr;
- if (clear_probing_mark_after_packet_processing_) {
- if (is_current_packet_connectivity_probing_) {
- QUIC_RELOADABLE_FLAG_COUNT_N(
- quic_clear_probing_mark_after_packet_processing, 1, 2);
- }
- is_current_packet_connectivity_probing_ = false;
- }
+ is_current_packet_connectivity_probing_ = false;
+
+ MaybeProcessCoalescedPackets();
return;
}
@@ -1840,17 +1848,12 @@
}
}
+ MaybeProcessCoalescedPackets();
MaybeProcessUndecryptablePackets();
MaybeSendInResponseToPacket();
SetPingAlarm();
current_packet_data_ = nullptr;
- if (clear_probing_mark_after_packet_processing_) {
- if (is_current_packet_connectivity_probing_) {
- QUIC_RELOADABLE_FLAG_COUNT_N(
- quic_clear_probing_mark_after_packet_processing, 2, 2);
- }
- is_current_packet_connectivity_probing_ = false;
- }
+ is_current_packet_connectivity_probing_ = false;
}
void QuicConnection::OnBlockedWriterCanWrite() {
@@ -1965,16 +1968,17 @@
// Count those that would have been accepted if FLAGS..random_ipn
// were true -- to detect/diagnose potential issues prior to
// enabling the flag.
- if ((header.packet_number > QuicPacketNumber(1)) &&
- (header.packet_number <= MaxRandomInitialPacketNumber())) {
+ if (header.packet_number >
+ received_packet_manager_.PeerFirstSendingPacketNumber() &&
+ header.packet_number <= MaxRandomInitialPacketNumber()) {
QUIC_CODE_COUNT_N(had_possibly_random_ipn, 2, 2);
}
bool out_of_bound =
last_header_.packet_number.IsInitialized()
? !Near(header.packet_number, last_header_.packet_number)
- // TODO(fayang): Fix this as this check assume the first received
- // packet is 1.
- : header.packet_number > QuicPacketNumber(kMaxPacketGap);
+ : header.packet_number >=
+ (received_packet_manager_.PeerFirstSendingPacketNumber() +
+ kMaxPacketGap);
if (out_of_bound) {
QUIC_DLOG(INFO) << ENDPOINT << "Packet " << header.packet_number
<< " out of bounds. Discarding";
@@ -2390,8 +2394,7 @@
bool QuicConnection::IsMsgTooBig(const WriteResult& result) {
return (result.status == WRITE_STATUS_MSG_TOO_BIG) ||
- (IsWriteError(result.status) &&
- result.error_code == kMessageTooBigErrorCode);
+ (IsWriteError(result.status) && result.error_code == QUIC_EMSGSIZE);
}
bool QuicConnection::ShouldDiscardPacket(const SerializedPacket& packet) {
@@ -2426,7 +2429,7 @@
"Write failed with error: ", error_code, " (", strerror(error_code), ")");
QUIC_LOG_FIRST_N(ERROR, 2) << ENDPOINT << error_details;
switch (error_code) {
- case kMessageTooBigErrorCode:
+ case QUIC_EMSGSIZE:
CloseConnection(
QUIC_PACKET_WRITE_ERROR, error_details,
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET_WITH_NO_ACK);
@@ -2469,15 +2472,13 @@
return;
}
- if (transport_version() != QUIC_VERSION_35) {
- if (serialized_packet->retransmittable_frames.empty() &&
- !serialized_packet->original_packet_number.IsInitialized()) {
- // Increment consecutive_num_packets_with_no_retransmittable_frames_ if
- // this packet is a new transmission with no retransmittable frames.
- ++consecutive_num_packets_with_no_retransmittable_frames_;
- } else {
- consecutive_num_packets_with_no_retransmittable_frames_ = 0;
- }
+ if (serialized_packet->retransmittable_frames.empty() &&
+ !serialized_packet->original_packet_number.IsInitialized()) {
+ // Increment consecutive_num_packets_with_no_retransmittable_frames_ if
+ // this packet is a new transmission with no retransmittable frames.
+ ++consecutive_num_packets_with_no_retransmittable_frames_;
+ } else {
+ consecutive_num_packets_with_no_retransmittable_frames_ = 0;
}
SendOrQueuePacket(serialized_packet);
}
@@ -2519,6 +2520,10 @@
void QuicConnection::OnHandshakeComplete() {
sent_packet_manager_.SetHandshakeConfirmed();
+ if (sent_packet_manager_.unacked_packets().use_uber_loss_algorithm()) {
+ // This may have changed the retransmission timer, so re-arm it.
+ SetRetransmissionAlarm();
+ }
// The client should immediately ack the SHLO to confirm the handshake is
// complete with the server.
if (perspective_ == Perspective::IS_CLIENT && !ack_queued_ &&
@@ -2712,6 +2717,44 @@
}
}
+void QuicConnection::QueueCoalescedPacket(const QuicEncryptedPacket& packet) {
+ QUIC_DVLOG(1) << ENDPOINT << "Queueing coalesced packet.";
+ coalesced_packets_.push_back(packet.Clone());
+}
+
+void QuicConnection::MaybeProcessCoalescedPackets() {
+ bool processed = false;
+ for (const auto& packet : coalesced_packets_) {
+ if (!connected_) {
+ return;
+ }
+
+ // }
+ // while (connected_ && !coalesced_packets_.empty()) {
+ QUIC_DVLOG(1) << ENDPOINT << "Processing coalesced packet";
+ // QuicEncryptedPacket* packet = coalesced_packets_.front().get();
+ if (framer_.ProcessPacket(*packet)) {
+ processed = true;
+ } else {
+ // If we are unable to decrypt this packet, it might be
+ // because the CHLO or SHLO packet was lost.
+ if (framer_.error() == QUIC_DECRYPTION_FAILURE) {
+ if (encryption_level_ != ENCRYPTION_FORWARD_SECURE &&
+ undecryptable_packets_.size() < max_undecryptable_packets_) {
+ QueueUndecryptablePacket(*packet);
+ } else if (debug_visitor_ != nullptr) {
+ debug_visitor_->OnUndecryptablePacket();
+ }
+ }
+ }
+ // coalesced_packets_.pop_front();
+ }
+ coalesced_packets_.clear();
+ if (processed) {
+ MaybeProcessUndecryptablePackets();
+ }
+}
+
void QuicConnection::CloseConnection(
QuicErrorCode error,
const QuicString& error_details,
@@ -3088,9 +3131,7 @@
return true;
}
if (save_crypto_packets_as_termination_packets_ &&
- frame.type == STREAM_FRAME &&
- frame.stream_frame.stream_id ==
- QuicUtils::GetCryptoStreamId(transport_version())) {
+ QuicUtils::IsHandshakeFrame(frame, transport_version())) {
return true;
}
}
@@ -3535,13 +3576,13 @@
}
MessageStatus QuicConnection::SendMessage(QuicMessageId message_id,
- QuicStringPiece message) {
+ QuicMemSliceSpan message) {
if (transport_version() <= QUIC_VERSION_44) {
QUIC_BUG << "MESSAGE frame is not supported for version "
<< transport_version();
return MESSAGE_STATUS_UNSUPPORTED;
}
- if (message.length() > GetLargestMessagePayload()) {
+ if (message.total_length() > GetLargestMessagePayload()) {
return MESSAGE_STATUS_TOO_LARGE;
}
if (!CanWrite(HAS_RETRANSMITTABLE_DATA)) {
diff --git a/quic/core/quic_connection.h b/quic/core/quic_connection.h
index 221754f..d27d0b7 100644
--- a/quic/core/quic_connection.h
+++ b/quic/core/quic_connection.h
@@ -96,6 +96,9 @@
// A simple visitor interface for dealing with a data frame.
virtual void OnStreamFrame(const QuicStreamFrame& frame) = 0;
+ // Called when a CRYPTO frame containing handshake data is received.
+ virtual void OnCryptoFrame(const QuicCryptoFrame& frame) = 0;
+
// The session should process the WINDOW_UPDATE frame, adjusting both stream
// and connection level flow control windows.
virtual void OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) = 0;
@@ -231,9 +234,6 @@
// Called when a StreamFrame has been parsed.
virtual void OnStreamFrame(const QuicStreamFrame& frame) {}
- // Called when a AckFrame has been parsed.
- virtual void OnAckFrame(const QuicAckFrame& frame) {}
-
// Called when a StopWaitingFrame has been parsed.
virtual void OnStopWaitingFrame(const QuicStopWaitingFrame& frame) {}
@@ -380,6 +380,13 @@
// Sets the number of active streams on the connection for congestion control.
void SetNumOpenStreams(size_t num_streams);
+ // Sends crypto handshake messages of length |write_length| to the peer in as
+ // few packets as possible. Returns the number of bytes consumed from the
+ // data.
+ virtual size_t SendCryptoData(EncryptionLevel level,
+ size_t write_length,
+ QuicStreamOffset offset);
+
// Send the data of length |write_length| to the peer in as few packets as
// possible. Returns the number of bytes consumed from data, and a boolean
// indicating if the fin bit was consumed. This does not indicate the data
@@ -479,6 +486,7 @@
bool OnUnauthenticatedHeader(const QuicPacketHeader& header) override;
void OnDecryptedPacket(EncryptionLevel level) override;
bool OnPacketHeader(const QuicPacketHeader& header) override;
+ void OnCoalescedPacket(const QuicEncryptedPacket& packet) override;
bool OnStreamFrame(const QuicStreamFrame& frame) override;
bool OnCryptoFrame(const QuicCryptoFrame& frame) override;
bool OnAckFrameStart(QuicPacketNumber largest_acked,
@@ -748,7 +756,7 @@
// Tries to send |message| and returns the message status.
virtual MessageStatus SendMessage(QuicMessageId message_id,
- QuicStringPiece message);
+ QuicMemSliceSpan message);
// Returns the largest payload that will fit into a single MESSAGE frame.
QuicPacketLength GetLargestMessagePayload() const;
@@ -847,6 +855,12 @@
// Attempts to process any queued undecryptable packets.
void MaybeProcessUndecryptablePackets();
+ // Queue a coalesced packet.
+ void QueueCoalescedPacket(const QuicEncryptedPacket& packet);
+
+ // Process previously queued coalesced packets.
+ void MaybeProcessCoalescedPackets();
+
enum PacketContent : uint8_t {
NO_FRAMES_RECEIVED,
// TODO(fkastenholz): Change name when we get rid of padded ping/
@@ -1156,6 +1170,10 @@
// sent with the INITIAL encryption and the CHLO message was lost.
QuicDeque<std::unique_ptr<QuicEncryptedPacket>> undecryptable_packets_;
+ // Collection of coalesced packets which were received while processing
+ // the current packet.
+ QuicDeque<std::unique_ptr<QuicEncryptedPacket>> coalesced_packets_;
+
// Maximum number of undecryptable packets the connection will store.
size_t max_undecryptable_packets_;
@@ -1400,9 +1418,6 @@
// provided in constructor.
const bool no_version_negotiation_;
- // Latched value of --quic_clear_probing_mark_after_packet_processing.
- const bool clear_probing_mark_after_packet_processing_;
-
// Payload of most recently transmitted QUIC_VERSION_99 connectivity
// probe packet (the PATH_CHALLENGE payload). This implementation transmits
// only one PATH_CHALLENGE per connectivity probe, so only one
diff --git a/quic/core/quic_connection_id.cc b/quic/core/quic_connection_id.cc
index a86a5dd..25c5b1f 100644
--- a/quic/core/quic_connection_id.cc
+++ b/quic/core/quic_connection_id.cc
@@ -19,18 +19,9 @@
namespace quic {
-QuicConnectionId::QuicConnectionId() {
- if (!QuicConnectionIdUseNetworkByteOrder()) {
- id64_ = 0;
- length_ = sizeof(uint64_t);
- return;
- }
- length_ = 0;
-}
+QuicConnectionId::QuicConnectionId() : length_(0) {}
QuicConnectionId::QuicConnectionId(const char* data, uint8_t length) {
- QUIC_BUG_IF(!QuicConnectionIdUseNetworkByteOrder())
- << "new constructor called when flag disabled";
if (length > kQuicMaxConnectionIdLength) {
QUIC_BUG << "Attempted to create connection ID of length " << length;
length = kQuicMaxConnectionIdLength;
@@ -39,48 +30,15 @@
if (length_ > 0) {
memcpy(data_, data, length_);
}
- QUIC_RESTART_FLAG_COUNT_N(quic_variable_length_connection_ids_server, 2, 3);
-}
-
-QuicConnectionId::QuicConnectionId(uint64_t connection_id64)
- : length_(sizeof(uint64_t)) {
- if (!QuicConnectionIdUseNetworkByteOrder()) {
- id64_ = connection_id64;
- return;
- }
- QUIC_BUG_IF(QuicConnectionIdSupportsVariableLength(Perspective::IS_CLIENT) &&
- QuicConnectionIdSupportsVariableLength(Perspective::IS_SERVER))
- << "old constructor called when flag enabled";
- const uint64_t connection_id64_net = QuicEndian::HostToNet64(connection_id64);
- memcpy(&data_, &connection_id64_net, sizeof(connection_id64_net));
}
QuicConnectionId::~QuicConnectionId() {}
-uint64_t QuicConnectionId::ToUInt64() const {
- if (!QuicConnectionIdUseNetworkByteOrder()) {
- return id64_;
- }
- QUIC_BUG_IF(QuicConnectionIdSupportsVariableLength(Perspective::IS_CLIENT) &&
- QuicConnectionIdSupportsVariableLength(Perspective::IS_SERVER))
- << "ToUInt64 called when flag enabled";
- uint64_t connection_id64_net = 0;
- memcpy(&connection_id64_net, &data_,
- std::min<size_t>(static_cast<size_t>(length_),
- sizeof(connection_id64_net)));
- return QuicEndian::NetToHost64(connection_id64_net);
-}
-
const char* QuicConnectionId::data() const {
- QUIC_BUG_IF(!QuicConnectionIdUseNetworkByteOrder())
- << "data called when flag disabled";
- QUIC_RESTART_FLAG_COUNT_N(quic_variable_length_connection_ids_server, 3, 3);
return data_;
}
char* QuicConnectionId::mutable_data() {
- QUIC_BUG_IF(!QuicConnectionIdUseNetworkByteOrder())
- << "mutable_data called when flag disabled";
return data_;
}
@@ -89,35 +47,24 @@
}
void QuicConnectionId::set_length(uint8_t length) {
- QUIC_BUG_IF(!QuicConnectionIdUseNetworkByteOrder())
- << "set_length called when flag disabled";
length_ = length;
}
bool QuicConnectionId::IsEmpty() const {
- if (!QuicConnectionIdUseNetworkByteOrder()) {
- return id64_ == 0;
- }
return length_ == 0;
}
size_t QuicConnectionId::Hash() const {
- if (!QuicConnectionIdUseNetworkByteOrder()) {
- return id64_;
- }
uint64_t data_bytes[3] = {0, 0, 0};
static_assert(sizeof(data_bytes) >= sizeof(data_), "sizeof(data_) changed");
memcpy(data_bytes, data_, length_);
- // This Hash function is designed to return the same value
- // as ToUInt64() when the connection ID length is 64 bits.
+ // This Hash function is designed to return the same value as the host byte
+ // order representation when the connection ID length is 64 bits.
return QuicEndian::NetToHost64(kQuicDefaultConnectionIdLength ^ length_ ^
data_bytes[0] ^ data_bytes[1] ^ data_bytes[2]);
}
QuicString QuicConnectionId::ToString() const {
- if (!QuicConnectionIdUseNetworkByteOrder()) {
- return QuicTextUtils::Uint64ToString(id64_);
- }
if (IsEmpty()) {
return QuicString("0");
}
@@ -130,9 +77,6 @@
}
bool QuicConnectionId::operator==(const QuicConnectionId& v) const {
- if (!QuicConnectionIdUseNetworkByteOrder()) {
- return id64_ == v.id64_;
- }
return length_ == v.length_ && memcmp(data_, v.data_, length_) == 0;
}
@@ -141,9 +85,6 @@
}
bool QuicConnectionId::operator<(const QuicConnectionId& v) const {
- if (!QuicConnectionIdUseNetworkByteOrder()) {
- return id64_ < v.id64_;
- }
if (length_ < v.length_) {
return true;
}
@@ -157,42 +98,6 @@
return QuicConnectionId();
}
-QuicConnectionId QuicConnectionIdFromUInt64(uint64_t connection_id64) {
- return QuicConnectionId(connection_id64);
-}
-
-uint64_t QuicConnectionIdToUInt64(QuicConnectionId connection_id) {
- return connection_id.ToUInt64();
-}
-
-bool QuicConnectionIdUseNetworkByteOrder() {
- const bool res = GetQuicRestartFlag(quic_connection_ids_network_byte_order);
- if (res) {
- QUIC_RESTART_FLAG_COUNT(quic_connection_ids_network_byte_order);
- }
- return res;
-}
-
-bool QuicConnectionIdSupportsVariableLength(Perspective perspective) {
- if (!QuicConnectionIdUseNetworkByteOrder()) {
- return false;
- }
- bool res;
- if (perspective == Perspective::IS_SERVER) {
- res = GetQuicRestartFlag(quic_variable_length_connection_ids_server);
- if (res) {
- QUIC_RESTART_FLAG_COUNT_N(quic_variable_length_connection_ids_server, 1,
- 3);
- }
- } else {
- res = GetQuicRestartFlag(quic_variable_length_connection_ids_client);
- if (res) {
- QUIC_RESTART_FLAG_COUNT(quic_variable_length_connection_ids_client);
- }
- }
- return res;
-}
-
static_assert(kQuicDefaultConnectionIdLength == sizeof(uint64_t),
"kQuicDefaultConnectionIdLength changed");
static_assert(kQuicDefaultConnectionIdLength == PACKET_8BYTE_CONNECTION_ID,
diff --git a/quic/core/quic_connection_id.h b/quic/core/quic_connection_id.h
index 5df72ec..06fecfb 100644
--- a/quic/core/quic_connection_id.h
+++ b/quic/core/quic_connection_id.h
@@ -25,17 +25,12 @@
class QUIC_EXPORT_PRIVATE QuicConnectionId {
public:
- // Creates a connection ID of length zero, unless the restart flag
- // quic_connection_ids_network_byte_order is false in which case
- // it returns an 8-byte all-zeroes connection ID.
+ // Creates a connection ID of length zero.
QuicConnectionId();
// Creates a connection ID from network order bytes.
QuicConnectionId(const char* data, uint8_t length);
- // Creator from host byte order uint64_t.
- explicit QuicConnectionId(uint64_t connection_id64);
-
~QuicConnectionId();
// Returns the length of the connection ID, in bytes.
@@ -51,14 +46,9 @@
// in network byte order.
char* mutable_data();
- // Returns whether the connection ID has length zero, unless the restart flag
- // quic_connection_ids_network_byte_order is false in which case
- // it checks if it is all zeroes.
+ // Returns whether the connection ID has length zero.
bool IsEmpty() const;
- // Converts to host byte order uint64_t.
- uint64_t ToUInt64() const;
-
// Hash() is required to use connection IDs as keys in hash tables.
size_t Hash() const;
@@ -77,11 +67,10 @@
bool operator<(const QuicConnectionId& v) const;
private:
- // The connection ID is currently represented in host byte order in |id64_|.
- // In the future, it will be saved in the first |length_| bytes of |data_|.
+ // The connection ID is represented in network byte order
+ // in the first |length_| bytes of |data_|.
char data_[kQuicMaxConnectionIdLength];
uint8_t length_;
- uint64_t id64_; // host byte order
};
// Creates a connection ID of length zero, unless the restart flag
@@ -89,16 +78,6 @@
// it returns an 8-byte all-zeroes connection ID.
QUIC_EXPORT_PRIVATE QuicConnectionId EmptyQuicConnectionId();
-// Converts connection ID from host-byte-order uint64_t to QuicConnectionId.
-// This is currently the identity function.
-QUIC_EXPORT_PRIVATE QuicConnectionId
-QuicConnectionIdFromUInt64(uint64_t connection_id64);
-
-// Converts connection ID from QuicConnectionId to host-byte-order uint64_t.
-// This is currently the identity function.
-QUIC_EXPORT_PRIVATE uint64_t
-QuicConnectionIdToUInt64(QuicConnectionId connection_id);
-
// QuicConnectionIdHash can be passed as hash argument to hash tables.
class QuicConnectionIdHash {
public:
@@ -107,16 +86,6 @@
}
};
-// Governs how connection IDs are represented in memory.
-// Checks gfe_restart_flag_quic_connection_ids_network_byte_order.
-QUIC_EXPORT_PRIVATE bool QuicConnectionIdUseNetworkByteOrder();
-
-enum class Perspective : uint8_t;
-// Governs how connection IDs are created.
-// Checks gfe_restart_flag_quic_variable_length_connection_ids_(client|server).
-QUIC_EXPORT_PRIVATE bool QuicConnectionIdSupportsVariableLength(
- Perspective perspective);
-
} // namespace quic
#endif // QUICHE_QUIC_CORE_QUIC_CONNECTION_ID_H_
diff --git a/quic/core/quic_connection_id_test.cc b/quic/core/quic_connection_id_test.cc
index 017e59e..1c7c761 100644
--- a/quic/core/quic_connection_id_test.cc
+++ b/quic/core/quic_connection_id_test.cc
@@ -37,18 +37,10 @@
TEST_F(QuicConnectionIdTest, ZeroIsNotEmpty) {
QuicConnectionId connection_id = test::TestConnectionId(0);
- if (!GetQuicRestartFlag(quic_connection_ids_network_byte_order)) {
- // Zero is empty when connection IDs are represented in host byte order.
- return;
- }
EXPECT_FALSE(connection_id.IsEmpty());
}
TEST_F(QuicConnectionIdTest, Data) {
- if (!GetQuicRestartFlag(quic_connection_ids_network_byte_order)) {
- // These methods are not allowed when the flag is off.
- return;
- }
char connection_id_data[kQuicDefaultConnectionIdLength];
memset(connection_id_data, 0x42, sizeof(connection_id_data));
QuicConnectionId connection_id1 =
diff --git a/quic/core/quic_connection_test.cc b/quic/core/quic_connection_test.cc
index fe851fd..c56d2c1 100644
--- a/quic/core/quic_connection_test.cc
+++ b/quic/core/quic_connection_test.cc
@@ -19,6 +19,7 @@
#include "net/third_party/quiche/src/quic/core/quic_simple_buffer_allocator.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_error_code_wrappers.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
@@ -102,8 +103,7 @@
bool SetIV(QuicStringPiece iv) override { return true; }
- bool EncryptPacket(QuicTransportVersion /*version*/,
- uint64_t packet_number,
+ bool EncryptPacket(uint64_t packet_number,
QuicStringPiece associated_data,
QuicStringPiece plaintext,
char* output,
@@ -167,8 +167,7 @@
return true;
}
- bool DecryptPacket(QuicTransportVersion /*version*/,
- uint64_t packet_number,
+ bool DecryptPacket(uint64_t packet_number,
QuicStringPiece associated_data,
QuicStringPiece ciphertext,
char* output,
@@ -332,10 +331,10 @@
}
if (next_packet_too_large_) {
next_packet_too_large_ = false;
- return WriteResult(WRITE_STATUS_ERROR, EMSGSIZE);
+ return WriteResult(WRITE_STATUS_ERROR, QUIC_EMSGSIZE);
}
if (always_get_packet_too_large_) {
- return WriteResult(WRITE_STATUS_ERROR, EMSGSIZE);
+ return WriteResult(WRITE_STATUS_ERROR, QUIC_EMSGSIZE);
}
if (IsWriteBlocked()) {
return WriteResult(is_write_blocked_data_buffered_
@@ -357,10 +356,6 @@
return WriteResult(WRITE_STATUS_OK, last_packet_size_);
}
- bool IsWriteBlockedDataBuffered() const override {
- return is_write_blocked_data_buffered_;
- }
-
bool ShouldWriteFail() { return write_should_fail_; }
bool IsWriteBlocked() const override { return write_blocked_; }
@@ -433,6 +428,10 @@
return framer_.stream_frames();
}
+ const std::vector<std::unique_ptr<QuicCryptoFrame>>& crypto_frames() const {
+ return framer_.crypto_frames();
+ }
+
const std::vector<QuicPingFrame>& ping_frames() const {
return framer_.ping_frames();
}
@@ -643,8 +642,23 @@
// split needlessly across packet boundaries). As a result, we have separate
// tests for some cases for this stream.
QuicConsumedData SendCryptoStreamData() {
- return SendStreamDataWithString(
- QuicUtils::GetCryptoStreamId(transport_version()), "chlo", 0, NO_FIN);
+ QuicStreamOffset offset = 0;
+ QuicStringPiece data("chlo");
+ if (transport_version() < QUIC_VERSION_47) {
+ return SendStreamDataWithString(
+ QuicUtils::GetCryptoStreamId(transport_version()), data, offset,
+ NO_FIN);
+ }
+ producer_.SaveCryptoData(ENCRYPTION_NONE, offset, data);
+ size_t bytes_written;
+ if (notifier_) {
+ bytes_written =
+ notifier_->WriteCryptoData(ENCRYPTION_NONE, data.length(), offset);
+ } else {
+ bytes_written = QuicConnection::SendCryptoData(ENCRYPTION_NONE,
+ data.length(), offset);
+ }
+ return QuicConsumedData(bytes_written, /*fin_consumed*/ false);
}
void set_version(ParsedQuicVersion version) {
@@ -987,7 +1001,7 @@
QuicPacketCreatorPeer::FillPacketHeader(&peer_creator_, &header);
char encrypted_buffer[kMaxPacketSize];
size_t length = peer_framer_.BuildDataPacket(
- header, frames, encrypted_buffer, kMaxPacketSize);
+ header, frames, encrypted_buffer, kMaxPacketSize, ENCRYPTION_NONE);
DCHECK_GT(length, 0u);
const size_t encrypted_length = peer_framer_.EncryptInPlace(
@@ -1135,7 +1149,7 @@
QuicStopWaitingFrame* frame,
EncryptionLevel level) {
return ProcessFramePacketAtLevel(number, QuicFrame(frame),
- ENCRYPTION_INITIAL);
+ ENCRYPTION_ZERO_RTT);
}
void ProcessGoAwayPacket(QuicGoAwayFrame* frame) {
@@ -1336,9 +1350,9 @@
};
// Run all end to end tests with all supported versions.
-INSTANTIATE_TEST_CASE_P(SupportedVersion,
- QuicConnectionTest,
- ::testing::ValuesIn(GetTestParams()));
+INSTANTIATE_TEST_SUITE_P(SupportedVersion,
+ QuicConnectionTest,
+ ::testing::ValuesIn(GetTestParams()));
TEST_P(QuicConnectionTest, SelfAddressChangeAtClient) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
@@ -1621,9 +1635,6 @@
connection_.GetStats().num_connectivity_probing_received;
ProcessReceivedPacket(kSelfAddress, kPeerAddress, *received);
- if (!GetQuicReloadableFlag(quic_clear_probing_mark_after_packet_processing)) {
- EXPECT_FALSE(connection_.IsCurrentPacketConnectivityProbing());
- }
EXPECT_EQ(num_probing_received,
connection_.GetStats().num_connectivity_probing_received);
EXPECT_EQ(kPeerAddress, connection_.peer_address());
@@ -1723,9 +1734,6 @@
connection_.GetStats().num_connectivity_probing_received;
ProcessReceivedPacket(kSelfAddress, kNewPeerAddress, *received);
- if (!GetQuicReloadableFlag(quic_clear_probing_mark_after_packet_processing)) {
- EXPECT_TRUE(connection_.IsCurrentPacketConnectivityProbing());
- }
EXPECT_EQ(num_probing_received + 1,
connection_.GetStats().num_connectivity_probing_received);
EXPECT_EQ(kPeerAddress, connection_.peer_address());
@@ -1786,9 +1794,6 @@
connection_.GetStats().num_connectivity_probing_received;
ProcessReceivedPacket(kSelfAddress, kNewPeerAddress, *received);
- if (!GetQuicReloadableFlag(quic_clear_probing_mark_after_packet_processing)) {
- EXPECT_TRUE(connection_.IsCurrentPacketConnectivityProbing());
- }
EXPECT_EQ(num_probing_received + 1,
connection_.GetStats().num_connectivity_probing_received);
EXPECT_EQ(kPeerAddress, connection_.peer_address());
@@ -1881,9 +1886,6 @@
connection_.GetStats().num_connectivity_probing_received;
ProcessReceivedPacket(kSelfAddress, kPeerAddress, *received);
- if (!GetQuicReloadableFlag(quic_clear_probing_mark_after_packet_processing)) {
- EXPECT_FALSE(connection_.IsCurrentPacketConnectivityProbing());
- }
EXPECT_EQ(num_probing_received,
connection_.GetStats().num_connectivity_probing_received);
EXPECT_EQ(kPeerAddress, connection_.peer_address());
@@ -1929,9 +1931,6 @@
connection_.GetStats().num_connectivity_probing_received;
ProcessReceivedPacket(kNewSelfAddress, kPeerAddress, *received);
- if (!GetQuicReloadableFlag(quic_clear_probing_mark_after_packet_processing)) {
- EXPECT_TRUE(connection_.IsCurrentPacketConnectivityProbing());
- }
EXPECT_EQ(num_probing_received + 1,
connection_.GetStats().num_connectivity_probing_received);
EXPECT_EQ(kPeerAddress, connection_.peer_address());
@@ -1995,6 +1994,13 @@
header.version_flag = true;
header.packet_number = QuicPacketNumber(1);
+ if (QuicVersionHasLongHeaderLengths(
+ peer_framer_.version().transport_version)) {
+ header.long_packet_type = INITIAL;
+ header.retry_token_length_length = VARIABLE_LENGTH_INTEGER_LENGTH_1;
+ header.length_length = VARIABLE_LENGTH_INTEGER_LENGTH_2;
+ }
+
QuicFrames frames;
QuicPaddingFrame padding;
frames.push_back(QuicFrame(frame1_));
@@ -2028,6 +2034,13 @@
header.version_flag = true;
header.packet_number = QuicPacketNumber(1);
+ if (QuicVersionHasLongHeaderLengths(
+ peer_framer_.version().transport_version)) {
+ header.long_packet_type = INITIAL;
+ header.retry_token_length_length = VARIABLE_LENGTH_INTEGER_LENGTH_1;
+ header.length_length = VARIABLE_LENGTH_INTEGER_LENGTH_2;
+ }
+
QuicFrames frames;
QuicPaddingFrame padding;
frames.push_back(QuicFrame(frame1_));
@@ -2192,20 +2205,38 @@
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
ProcessPacket(3);
- // Should ack immediately since we have missing packets.
- EXPECT_EQ(1u, writer_->packets_write_attempts());
+ if (GetQuicRestartFlag(quic_enable_accept_random_ipn)) {
+ // Should not cause an ack.
+ EXPECT_EQ(0u, writer_->packets_write_attempts());
+ } else {
+ // Should ack immediately since we have missing packets.
+ EXPECT_EQ(1u, writer_->packets_write_attempts());
+ }
ProcessPacket(2);
- // Should ack immediately since we have missing packets.
- EXPECT_EQ(2u, writer_->packets_write_attempts());
+ if (GetQuicRestartFlag(quic_enable_accept_random_ipn)) {
+ // Should ack immediately, since this fills the last hole.
+ EXPECT_EQ(1u, writer_->packets_write_attempts());
+ } else {
+ // Should ack immediately since we have missing packets.
+ EXPECT_EQ(2u, writer_->packets_write_attempts());
+ }
ProcessPacket(1);
// Should ack immediately, since this fills the last hole.
- EXPECT_EQ(3u, writer_->packets_write_attempts());
+ if (GetQuicRestartFlag(quic_enable_accept_random_ipn)) {
+ EXPECT_EQ(2u, writer_->packets_write_attempts());
+ } else {
+ EXPECT_EQ(3u, writer_->packets_write_attempts());
+ }
ProcessPacket(4);
// Should not cause an ack.
- EXPECT_EQ(3u, writer_->packets_write_attempts());
+ if (GetQuicRestartFlag(quic_enable_accept_random_ipn)) {
+ EXPECT_EQ(2u, writer_->packets_write_attempts());
+ } else {
+ EXPECT_EQ(3u, writer_->packets_write_attempts());
+ }
}
TEST_P(QuicConnectionTest, OutOfOrderAckReceiptCausesNoAck) {
@@ -2293,33 +2324,7 @@
ProcessAckPacket(&frame2);
}
-TEST_P(QuicConnectionTest, 20AcksCausesAckSend) {
- if (connection_.version().transport_version != QUIC_VERSION_35) {
- return;
- }
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
-
- SendStreamDataToPeer(1, "foo", 0, NO_FIN, nullptr);
-
- QuicAlarm* ack_alarm = QuicConnectionPeer::GetAckAlarm(&connection_);
- // But an ack with no missing packets will not send an ack.
- QuicAckFrame frame = InitAckFrame(1);
- EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
- for (int i = 0; i < 19; ++i) {
- ProcessAckPacket(&frame);
- EXPECT_FALSE(ack_alarm->IsSet());
- }
- EXPECT_EQ(1u, writer_->packets_write_attempts());
- // The 20th ack packet will cause an ack to be sent.
- ProcessAckPacket(&frame);
- EXPECT_EQ(2u, writer_->packets_write_attempts());
-}
-
TEST_P(QuicConnectionTest, AckSentEveryNthPacket) {
- if (connection_.version().transport_version == QUIC_VERSION_35) {
- return;
- }
-
connection_.set_ack_frequency_before_ack_decimation(3);
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
@@ -2363,10 +2368,6 @@
}
TEST_P(QuicConnectionTest, AckNeedsRetransmittableFrames) {
- if (connection_.version().transport_version == QUIC_VERSION_35) {
- return;
- }
-
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(99);
@@ -2676,10 +2677,14 @@
// Parse the last packet and ensure it's the crypto stream frame.
EXPECT_EQ(2u, writer_->frame_count());
- ASSERT_EQ(1u, writer_->stream_frames().size());
ASSERT_EQ(1u, writer_->padding_frames().size());
- EXPECT_EQ(QuicUtils::GetCryptoStreamId(connection_.transport_version()),
- writer_->stream_frames()[0]->stream_id);
+ if (connection_.transport_version() < QUIC_VERSION_47) {
+ ASSERT_EQ(1u, writer_->stream_frames().size());
+ EXPECT_EQ(QuicUtils::GetCryptoStreamId(connection_.transport_version()),
+ writer_->stream_frames()[0]->stream_id);
+ } else {
+ EXPECT_EQ(1u, writer_->crypto_frames().size());
+ }
}
TEST_P(QuicConnectionTest, FramePackingCryptoThenNonCrypto) {
@@ -3574,9 +3579,9 @@
NO_FIN, nullptr);
EXPECT_EQ(0x01010101u, writer_->final_bytes_of_last_packet());
- connection_.SetEncrypter(ENCRYPTION_INITIAL,
+ connection_.SetEncrypter(ENCRYPTION_ZERO_RTT,
QuicMakeUnique<TaggingEncrypter>(0x02));
- connection_.SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
+ connection_.SetDefaultEncryptionLevel(ENCRYPTION_ZERO_RTT);
SendStreamDataToPeer(3, "foo", 0, NO_FIN, nullptr);
EXPECT_EQ(0x02020202u, writer_->final_bytes_of_last_packet());
@@ -3594,7 +3599,7 @@
// Packet should have been sent with ENCRYPTION_NONE.
EXPECT_EQ(0x01010101u, writer_->final_bytes_of_previous_packet());
- // Packet should have been sent with ENCRYPTION_INITIAL.
+ // Packet should have been sent with ENCRYPTION_ZERO_RTT.
EXPECT_EQ(0x02020202u, writer_->final_bytes_of_last_packet());
}
@@ -3615,9 +3620,9 @@
EXPECT_EQ(1u, connection_.NumQueuedPackets());
// Switch to the new encrypter.
- connection_.SetEncrypter(ENCRYPTION_INITIAL,
+ connection_.SetEncrypter(ENCRYPTION_ZERO_RTT,
QuicMakeUnique<TaggingEncrypter>(0x02));
- connection_.SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
+ connection_.SetDefaultEncryptionLevel(ENCRYPTION_ZERO_RTT);
// Now become writeable and flush the packets.
writer_->SetWritable();
@@ -3635,9 +3640,7 @@
connection_.SetEncrypter(ENCRYPTION_NONE,
QuicMakeUnique<TaggingEncrypter>(0x01));
QuicPacketNumber packet_number;
- SendStreamDataToPeer(
- QuicUtils::GetCryptoStreamId(connection_.transport_version()), "foo", 0,
- NO_FIN, &packet_number);
+ connection_.SendCryptoStreamData();
// Simulate the retransmission alarm firing and the socket blocking.
BlockOnNextWrite();
@@ -3668,9 +3671,9 @@
QuicUtils::GetCryptoStreamId(connection_.transport_version()), "foo", 0,
NO_FIN, nullptr);
- connection_.SetEncrypter(ENCRYPTION_INITIAL,
+ connection_.SetEncrypter(ENCRYPTION_ZERO_RTT,
QuicMakeUnique<TaggingEncrypter>(0x02));
- connection_.SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
+ connection_.SetDefaultEncryptionLevel(ENCRYPTION_ZERO_RTT);
SendStreamDataToPeer(2, "bar", 0, NO_FIN, nullptr);
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
@@ -3687,27 +3690,27 @@
use_tagging_decrypter();
const uint8_t tag = 0x07;
- peer_framer_.SetEncrypter(ENCRYPTION_INITIAL,
+ peer_framer_.SetEncrypter(ENCRYPTION_ZERO_RTT,
QuicMakeUnique<TaggingEncrypter>(tag));
// Process an encrypted packet which can not yet be decrypted which should
// result in the packet being buffered.
- ProcessDataPacketAtLevel(1, !kHasStopWaiting, ENCRYPTION_INITIAL);
+ ProcessDataPacketAtLevel(1, !kHasStopWaiting, ENCRYPTION_ZERO_RTT);
// Transition to the new encryption state and process another encrypted packet
// which should result in the original packet being processed.
- connection_.SetDecrypter(ENCRYPTION_INITIAL,
+ connection_.SetDecrypter(ENCRYPTION_ZERO_RTT,
QuicMakeUnique<StrictTaggingDecrypter>(tag));
- connection_.SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
- connection_.SetEncrypter(ENCRYPTION_INITIAL,
+ connection_.SetDefaultEncryptionLevel(ENCRYPTION_ZERO_RTT);
+ connection_.SetEncrypter(ENCRYPTION_ZERO_RTT,
QuicMakeUnique<TaggingEncrypter>(tag));
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(2);
- ProcessDataPacketAtLevel(2, !kHasStopWaiting, ENCRYPTION_INITIAL);
+ ProcessDataPacketAtLevel(2, !kHasStopWaiting, ENCRYPTION_ZERO_RTT);
// Finally, process a third packet and note that we do not reprocess the
// buffered packet.
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
- ProcessDataPacketAtLevel(3, !kHasStopWaiting, ENCRYPTION_INITIAL);
+ ProcessDataPacketAtLevel(3, !kHasStopWaiting, ENCRYPTION_ZERO_RTT);
}
TEST_P(QuicConnectionTest, TestRetransmitOrder) {
@@ -3752,23 +3755,23 @@
use_tagging_decrypter();
const uint8_t tag = 0x07;
- peer_framer_.SetEncrypter(ENCRYPTION_INITIAL,
+ peer_framer_.SetEncrypter(ENCRYPTION_ZERO_RTT,
QuicMakeUnique<TaggingEncrypter>(tag));
// Process an encrypted packet which can not yet be decrypted which should
// result in the packet being buffered.
for (uint64_t i = 1; i <= 100; ++i) {
- ProcessDataPacketAtLevel(i, !kHasStopWaiting, ENCRYPTION_INITIAL);
+ ProcessDataPacketAtLevel(i, !kHasStopWaiting, ENCRYPTION_ZERO_RTT);
}
// Transition to the new encryption state and process another encrypted packet
// which should result in the original packets being processed.
EXPECT_FALSE(connection_.GetProcessUndecryptablePacketsAlarm()->IsSet());
- connection_.SetDecrypter(ENCRYPTION_INITIAL,
+ connection_.SetDecrypter(ENCRYPTION_ZERO_RTT,
QuicMakeUnique<StrictTaggingDecrypter>(tag));
EXPECT_TRUE(connection_.GetProcessUndecryptablePacketsAlarm()->IsSet());
- connection_.SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
- connection_.SetEncrypter(ENCRYPTION_INITIAL,
+ connection_.SetDefaultEncryptionLevel(ENCRYPTION_ZERO_RTT);
+ connection_.SetEncrypter(ENCRYPTION_ZERO_RTT,
QuicMakeUnique<TaggingEncrypter>(tag));
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(100);
@@ -3777,7 +3780,7 @@
// Finally, process a third packet and note that we do not reprocess the
// buffered packet.
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
- ProcessDataPacketAtLevel(102, !kHasStopWaiting, ENCRYPTION_INITIAL);
+ ProcessDataPacketAtLevel(102, !kHasStopWaiting, ENCRYPTION_ZERO_RTT);
}
TEST_P(QuicConnectionTest, SetRTOAfterWritingToSocket) {
@@ -4932,7 +4935,9 @@
connection_.version().transport_version, kIncludeVersion,
!kIncludeDiversificationNonce, PACKET_8BYTE_CONNECTION_ID,
PACKET_0BYTE_CONNECTION_ID,
- QuicPacketCreatorPeer::GetPacketNumberLength(creator_), &payload_length);
+ QuicPacketCreatorPeer::GetPacketNumberLength(creator_),
+ QuicPacketCreatorPeer::GetRetryTokenLengthLength(creator_),
+ QuicPacketCreatorPeer::GetLengthLength(creator_), &payload_length);
connection_.SetMaxPacketLength(length);
// Queue the first packet.
@@ -4959,7 +4964,9 @@
connection_.version().transport_version, kIncludeVersion,
!kIncludeDiversificationNonce, PACKET_8BYTE_CONNECTION_ID,
PACKET_0BYTE_CONNECTION_ID,
- QuicPacketCreatorPeer::GetPacketNumberLength(creator_), &payload_length);
+ QuicPacketCreatorPeer::GetPacketNumberLength(creator_),
+ QuicPacketCreatorPeer::GetRetryTokenLengthLength(creator_),
+ QuicPacketCreatorPeer::GetLengthLength(creator_), &payload_length);
// GetPacketLengthForOneStream() assumes a stream offset of 0 in determining
// packet length. The size of the offset field in a stream frame is
// 0 for offset 0, and 2 for non-zero offsets up through 16K (for
@@ -5049,17 +5056,17 @@
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
const uint8_t tag = 0x07;
- connection_.SetDecrypter(ENCRYPTION_INITIAL,
+ connection_.SetDecrypter(ENCRYPTION_ZERO_RTT,
QuicMakeUnique<StrictTaggingDecrypter>(tag));
- peer_framer_.SetEncrypter(ENCRYPTION_INITIAL,
+ peer_framer_.SetEncrypter(ENCRYPTION_ZERO_RTT,
QuicMakeUnique<TaggingEncrypter>(tag));
// Process a packet from the non-crypto stream.
frame1_.stream_id = 3;
- // The same as ProcessPacket(1) except that ENCRYPTION_INITIAL is used
+ // The same as ProcessPacket(1) except that ENCRYPTION_ZERO_RTT is used
// instead of ENCRYPTION_NONE.
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
- ProcessDataPacketAtLevel(1, !kHasStopWaiting, ENCRYPTION_INITIAL);
+ ProcessDataPacketAtLevel(1, !kHasStopWaiting, ENCRYPTION_ZERO_RTT);
// Check if delayed ack timer is running for the expected interval.
EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
@@ -5087,17 +5094,17 @@
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
const uint8_t tag = 0x07;
- connection_.SetDecrypter(ENCRYPTION_INITIAL,
+ connection_.SetDecrypter(ENCRYPTION_ZERO_RTT,
QuicMakeUnique<StrictTaggingDecrypter>(tag));
- peer_framer_.SetEncrypter(ENCRYPTION_INITIAL,
+ peer_framer_.SetEncrypter(ENCRYPTION_ZERO_RTT,
QuicMakeUnique<TaggingEncrypter>(tag));
// Process a packet from the non-crypto stream.
frame1_.stream_id = 3;
- // The same as ProcessPacket(1) except that ENCRYPTION_INITIAL is used
+ // The same as ProcessPacket(1) except that ENCRYPTION_ZERO_RTT is used
// instead of ENCRYPTION_NONE.
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
- ProcessDataPacketAtLevel(1, !kHasStopWaiting, ENCRYPTION_INITIAL);
+ ProcessDataPacketAtLevel(1, !kHasStopWaiting, ENCRYPTION_ZERO_RTT);
// Check if delayed ack timer is running for the expected interval.
EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
@@ -5119,7 +5126,7 @@
// ack alarm to be set delayed ack time in the future.
ack_time = clock_.ApproximateNow() + DefaultDelayedAckTime();
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
- ProcessDataPacketAtLevel(2, !kHasStopWaiting, ENCRYPTION_INITIAL);
+ ProcessDataPacketAtLevel(2, !kHasStopWaiting, ENCRYPTION_ZERO_RTT);
// Check if delayed ack timer is running for the expected interval.
EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
@@ -5141,7 +5148,7 @@
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
ack_time = clock_.ApproximateNow() + QuicTime::Delta::FromMilliseconds(1);
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
- ProcessDataPacketAtLevel(3, !kHasStopWaiting, ENCRYPTION_INITIAL);
+ ProcessDataPacketAtLevel(3, !kHasStopWaiting, ENCRYPTION_ZERO_RTT);
// Check if delayed ack timer is running for the expected interval.
EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
@@ -5163,9 +5170,9 @@
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
const uint8_t tag = 0x07;
- connection_.SetDecrypter(ENCRYPTION_INITIAL,
+ connection_.SetDecrypter(ENCRYPTION_ZERO_RTT,
QuicMakeUnique<StrictTaggingDecrypter>(tag));
- peer_framer_.SetEncrypter(ENCRYPTION_INITIAL,
+ peer_framer_.SetEncrypter(ENCRYPTION_ZERO_RTT,
QuicMakeUnique<TaggingEncrypter>(tag));
// Process a packet from the non-crypto stream.
frame1_.stream_id = 3;
@@ -5174,14 +5181,14 @@
uint64_t kFirstDecimatedPacket = 101;
for (unsigned int i = 0; i < kFirstDecimatedPacket - 1; ++i) {
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
- ProcessDataPacketAtLevel(1 + i, !kHasStopWaiting, ENCRYPTION_INITIAL);
+ ProcessDataPacketAtLevel(1 + i, !kHasStopWaiting, ENCRYPTION_ZERO_RTT);
}
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
- // The same as ProcessPacket(1) except that ENCRYPTION_INITIAL is used
+ // The same as ProcessPacket(1) except that ENCRYPTION_ZERO_RTT is used
// instead of ENCRYPTION_NONE.
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
ProcessDataPacketAtLevel(kFirstDecimatedPacket, !kHasStopWaiting,
- ENCRYPTION_INITIAL);
+ ENCRYPTION_ZERO_RTT);
// Check if delayed ack timer is running for the expected interval.
EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
@@ -5192,7 +5199,7 @@
EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
ProcessDataPacketAtLevel(kFirstDecimatedPacket + 1 + i, !kHasStopWaiting,
- ENCRYPTION_INITIAL);
+ ENCRYPTION_ZERO_RTT);
}
// Check that ack is sent and that delayed ack alarm is reset.
if (GetParam().no_stop_waiting) {
@@ -5222,17 +5229,17 @@
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
const uint8_t tag = 0x07;
- connection_.SetDecrypter(ENCRYPTION_INITIAL,
+ connection_.SetDecrypter(ENCRYPTION_ZERO_RTT,
QuicMakeUnique<StrictTaggingDecrypter>(tag));
- peer_framer_.SetEncrypter(ENCRYPTION_INITIAL,
+ peer_framer_.SetEncrypter(ENCRYPTION_ZERO_RTT,
QuicMakeUnique<TaggingEncrypter>(tag));
// Process a packet from the non-crypto stream.
frame1_.stream_id = 3;
- // The same as ProcessPacket(1) except that ENCRYPTION_INITIAL is used
+ // The same as ProcessPacket(1) except that ENCRYPTION_ZERO_RTT is used
// instead of ENCRYPTION_NONE.
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
- ProcessDataPacketAtLevel(1, !kHasStopWaiting, ENCRYPTION_INITIAL);
+ ProcessDataPacketAtLevel(1, !kHasStopWaiting, ENCRYPTION_ZERO_RTT);
// Check if delayed ack timer is running for the expected interval.
EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
@@ -5254,7 +5261,7 @@
// ack alarm to be set delayed ack time in the future.
ack_time = clock_.ApproximateNow() + DefaultDelayedAckTime();
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
- ProcessDataPacketAtLevel(2, !kHasStopWaiting, ENCRYPTION_INITIAL);
+ ProcessDataPacketAtLevel(2, !kHasStopWaiting, ENCRYPTION_ZERO_RTT);
// Check if delayed ack timer is running for the expected interval.
EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
@@ -5276,7 +5283,7 @@
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
ack_time = clock_.ApproximateNow() + QuicTime::Delta::FromMilliseconds(1);
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
- ProcessDataPacketAtLevel(3, !kHasStopWaiting, ENCRYPTION_INITIAL);
+ ProcessDataPacketAtLevel(3, !kHasStopWaiting, ENCRYPTION_ZERO_RTT);
// Check if delayed ack timer is running for the expected interval.
EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
@@ -5290,14 +5297,14 @@
uint64_t kFirstDecimatedPacket = 101;
for (unsigned int i = 0; i < kFirstDecimatedPacket - 4; ++i) {
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
- ProcessDataPacketAtLevel(4 + i, !kHasStopWaiting, ENCRYPTION_INITIAL);
+ ProcessDataPacketAtLevel(4 + i, !kHasStopWaiting, ENCRYPTION_ZERO_RTT);
}
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
- // The same as ProcessPacket(1) except that ENCRYPTION_INITIAL is used
+ // The same as ProcessPacket(1) except that ENCRYPTION_ZERO_RTT is used
// instead of ENCRYPTION_NONE.
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
ProcessDataPacketAtLevel(kFirstDecimatedPacket, !kHasStopWaiting,
- ENCRYPTION_INITIAL);
+ ENCRYPTION_ZERO_RTT);
// Check if delayed ack timer is running for the expected interval.
EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
@@ -5308,7 +5315,7 @@
EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
ProcessDataPacketAtLevel(kFirstDecimatedPacket + 1 + i, !kHasStopWaiting,
- ENCRYPTION_INITIAL);
+ ENCRYPTION_ZERO_RTT);
}
// Check that ack is sent and that delayed ack alarm is reset.
if (GetParam().no_stop_waiting) {
@@ -5326,7 +5333,7 @@
ack_time = clock_.ApproximateNow() + QuicTime::Delta::FromMilliseconds(1);
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
ProcessDataPacketAtLevel(kFirstDecimatedPacket + 10, !kHasStopWaiting,
- ENCRYPTION_INITIAL);
+ ENCRYPTION_ZERO_RTT);
// Check if delayed ack timer is running for the expected interval.
EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
@@ -5355,9 +5362,9 @@
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
const uint8_t tag = 0x07;
- connection_.SetDecrypter(ENCRYPTION_INITIAL,
+ connection_.SetDecrypter(ENCRYPTION_ZERO_RTT,
QuicMakeUnique<StrictTaggingDecrypter>(tag));
- peer_framer_.SetEncrypter(ENCRYPTION_INITIAL,
+ peer_framer_.SetEncrypter(ENCRYPTION_ZERO_RTT,
QuicMakeUnique<TaggingEncrypter>(tag));
// Process a packet from the non-crypto stream.
frame1_.stream_id = 3;
@@ -5366,14 +5373,14 @@
uint64_t kFirstDecimatedPacket = 101;
for (unsigned int i = 0; i < kFirstDecimatedPacket - 1; ++i) {
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
- ProcessDataPacketAtLevel(1 + i, !kHasStopWaiting, ENCRYPTION_INITIAL);
+ ProcessDataPacketAtLevel(1 + i, !kHasStopWaiting, ENCRYPTION_ZERO_RTT);
}
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
- // The same as ProcessPacket(1) except that ENCRYPTION_INITIAL is used
+ // The same as ProcessPacket(1) except that ENCRYPTION_ZERO_RTT is used
// instead of ENCRYPTION_NONE.
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
ProcessDataPacketAtLevel(kFirstDecimatedPacket, !kHasStopWaiting,
- ENCRYPTION_INITIAL);
+ ENCRYPTION_ZERO_RTT);
// Check if delayed ack timer is running for the expected interval.
EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
@@ -5385,7 +5392,7 @@
EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
ProcessDataPacketAtLevel(kFirstDecimatedPacket + 1 + i, !kHasStopWaiting,
- ENCRYPTION_INITIAL);
+ ENCRYPTION_ZERO_RTT);
}
// The delayed ack timer should still be set to the expected deadline.
EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
@@ -5408,9 +5415,9 @@
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
const uint8_t tag = 0x07;
- connection_.SetDecrypter(ENCRYPTION_INITIAL,
+ connection_.SetDecrypter(ENCRYPTION_ZERO_RTT,
QuicMakeUnique<StrictTaggingDecrypter>(tag));
- peer_framer_.SetEncrypter(ENCRYPTION_INITIAL,
+ peer_framer_.SetEncrypter(ENCRYPTION_ZERO_RTT,
QuicMakeUnique<TaggingEncrypter>(tag));
// Process a packet from the non-crypto stream.
frame1_.stream_id = 3;
@@ -5419,14 +5426,14 @@
uint64_t kFirstDecimatedPacket = 101;
for (unsigned int i = 0; i < kFirstDecimatedPacket - 1; ++i) {
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
- ProcessDataPacketAtLevel(1 + i, !kHasStopWaiting, ENCRYPTION_INITIAL);
+ ProcessDataPacketAtLevel(1 + i, !kHasStopWaiting, ENCRYPTION_ZERO_RTT);
}
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
- // The same as ProcessPacket(1) except that ENCRYPTION_INITIAL is used
+ // The same as ProcessPacket(1) except that ENCRYPTION_ZERO_RTT is used
// instead of ENCRYPTION_NONE.
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
ProcessDataPacketAtLevel(kFirstDecimatedPacket, !kHasStopWaiting,
- ENCRYPTION_INITIAL);
+ ENCRYPTION_ZERO_RTT);
// Check if delayed ack timer is running for the expected interval.
EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
@@ -5437,7 +5444,7 @@
EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
ProcessDataPacketAtLevel(kFirstDecimatedPacket + 1 + i, !kHasStopWaiting,
- ENCRYPTION_INITIAL);
+ ENCRYPTION_ZERO_RTT);
}
// Check that ack is sent and that delayed ack alarm is reset.
if (GetParam().no_stop_waiting) {
@@ -5471,9 +5478,9 @@
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
const uint8_t tag = 0x07;
- connection_.SetDecrypter(ENCRYPTION_INITIAL,
+ connection_.SetDecrypter(ENCRYPTION_ZERO_RTT,
QuicMakeUnique<StrictTaggingDecrypter>(tag));
- peer_framer_.SetEncrypter(ENCRYPTION_INITIAL,
+ peer_framer_.SetEncrypter(ENCRYPTION_ZERO_RTT,
QuicMakeUnique<TaggingEncrypter>(tag));
// Process a packet from the non-crypto stream.
frame1_.stream_id = 3;
@@ -5482,7 +5489,7 @@
uint64_t kFirstDecimatedPacket = 101;
for (unsigned int i = 0; i < kFirstDecimatedPacket - 1; ++i) {
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
- ProcessDataPacketAtLevel(1 + i, !kHasStopWaiting, ENCRYPTION_INITIAL);
+ ProcessDataPacketAtLevel(1 + i, !kHasStopWaiting, ENCRYPTION_ZERO_RTT);
}
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
@@ -5492,7 +5499,7 @@
// Process packet 10 first and ensure the alarm is one eighth min_rtt.
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
ProcessDataPacketAtLevel(kFirstDecimatedPacket + 9 + (j * 11),
- !kHasStopWaiting, ENCRYPTION_INITIAL);
+ !kHasStopWaiting, ENCRYPTION_ZERO_RTT);
ack_time = clock_.ApproximateNow() + QuicTime::Delta::FromMilliseconds(5);
EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
EXPECT_EQ(ack_time, connection_.GetAckAlarm()->deadline());
@@ -5505,7 +5512,7 @@
// The ACK shouldn't be sent until the 10th packet is processed.
EXPECT_TRUE(writer_->ack_frames().empty());
ProcessDataPacketAtLevel(kFirstDecimatedPacket + i + (j * 11),
- !kHasStopWaiting, ENCRYPTION_INITIAL);
+ !kHasStopWaiting, ENCRYPTION_ZERO_RTT);
}
// Check that ack is sent and that delayed ack alarm is reset.
if (GetParam().no_stop_waiting) {
@@ -5540,9 +5547,9 @@
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
const uint8_t tag = 0x07;
- connection_.SetDecrypter(ENCRYPTION_INITIAL,
+ connection_.SetDecrypter(ENCRYPTION_ZERO_RTT,
QuicMakeUnique<StrictTaggingDecrypter>(tag));
- peer_framer_.SetEncrypter(ENCRYPTION_INITIAL,
+ peer_framer_.SetEncrypter(ENCRYPTION_ZERO_RTT,
QuicMakeUnique<TaggingEncrypter>(tag));
// Process a packet from the non-crypto stream.
frame1_.stream_id = 3;
@@ -5551,14 +5558,14 @@
uint64_t kFirstDecimatedPacket = 101;
for (unsigned int i = 0; i < kFirstDecimatedPacket - 1; ++i) {
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
- ProcessDataPacketAtLevel(1 + i, !kHasStopWaiting, ENCRYPTION_INITIAL);
+ ProcessDataPacketAtLevel(1 + i, !kHasStopWaiting, ENCRYPTION_ZERO_RTT);
}
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
- // The same as ProcessPacket(1) except that ENCRYPTION_INITIAL is used
+ // The same as ProcessPacket(1) except that ENCRYPTION_ZERO_RTT is used
// instead of ENCRYPTION_NONE.
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
ProcessDataPacketAtLevel(kFirstDecimatedPacket, !kHasStopWaiting,
- ENCRYPTION_INITIAL);
+ ENCRYPTION_ZERO_RTT);
// Check if delayed ack timer is running for the expected interval.
EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
@@ -5567,7 +5574,7 @@
// Process packet 10 first and ensure the alarm is one eighth min_rtt.
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
ProcessDataPacketAtLevel(kFirstDecimatedPacket + 19, !kHasStopWaiting,
- ENCRYPTION_INITIAL);
+ ENCRYPTION_ZERO_RTT);
ack_time = clock_.ApproximateNow() + QuicTime::Delta::FromMilliseconds(5);
EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
EXPECT_EQ(ack_time, connection_.GetAckAlarm()->deadline());
@@ -5577,7 +5584,7 @@
EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
ProcessDataPacketAtLevel(kFirstDecimatedPacket + 1 + i, !kHasStopWaiting,
- ENCRYPTION_INITIAL);
+ ENCRYPTION_ZERO_RTT);
}
// Check that ack is sent and that delayed ack alarm is reset.
if (GetParam().no_stop_waiting) {
@@ -5595,7 +5602,7 @@
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
ProcessDataPacketAtLevel(kFirstDecimatedPacket + 10, !kHasStopWaiting,
- ENCRYPTION_INITIAL);
+ ENCRYPTION_ZERO_RTT);
// Check that ack is sent and that delayed ack alarm is reset.
if (GetParam().no_stop_waiting) {
EXPECT_EQ(1u, writer_->frame_count());
@@ -5629,9 +5636,9 @@
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
const uint8_t tag = 0x07;
- connection_.SetDecrypter(ENCRYPTION_INITIAL,
+ connection_.SetDecrypter(ENCRYPTION_ZERO_RTT,
QuicMakeUnique<StrictTaggingDecrypter>(tag));
- peer_framer_.SetEncrypter(ENCRYPTION_INITIAL,
+ peer_framer_.SetEncrypter(ENCRYPTION_ZERO_RTT,
QuicMakeUnique<TaggingEncrypter>(tag));
// Process a packet from the non-crypto stream.
frame1_.stream_id = 3;
@@ -5640,14 +5647,14 @@
uint64_t kFirstDecimatedPacket = 101;
for (unsigned int i = 0; i < kFirstDecimatedPacket - 1; ++i) {
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
- ProcessDataPacketAtLevel(1 + i, !kHasStopWaiting, ENCRYPTION_INITIAL);
+ ProcessDataPacketAtLevel(1 + i, !kHasStopWaiting, ENCRYPTION_ZERO_RTT);
}
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
- // The same as ProcessPacket(1) except that ENCRYPTION_INITIAL is used
+ // The same as ProcessPacket(1) except that ENCRYPTION_ZERO_RTT is used
// instead of ENCRYPTION_NONE.
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
ProcessDataPacketAtLevel(kFirstDecimatedPacket, !kHasStopWaiting,
- ENCRYPTION_INITIAL);
+ ENCRYPTION_ZERO_RTT);
// Check if delayed ack timer is running for the expected interval.
EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
@@ -5656,7 +5663,7 @@
// Process packet 10 first and ensure the alarm is one eighth min_rtt.
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
ProcessDataPacketAtLevel(kFirstDecimatedPacket + 9, !kHasStopWaiting,
- ENCRYPTION_INITIAL);
+ ENCRYPTION_ZERO_RTT);
ack_time = clock_.ApproximateNow() + QuicTime::Delta::FromMilliseconds(5);
EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
EXPECT_EQ(ack_time, connection_.GetAckAlarm()->deadline());
@@ -5666,7 +5673,7 @@
EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
ProcessDataPacketAtLevel(kFirstDecimatedPacket + 1 + i, !kHasStopWaiting,
- ENCRYPTION_INITIAL);
+ ENCRYPTION_ZERO_RTT);
}
// Check that ack is sent and that delayed ack alarm is reset.
if (GetParam().no_stop_waiting) {
@@ -5702,9 +5709,9 @@
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
const uint8_t tag = 0x07;
- connection_.SetDecrypter(ENCRYPTION_INITIAL,
+ connection_.SetDecrypter(ENCRYPTION_ZERO_RTT,
QuicMakeUnique<StrictTaggingDecrypter>(tag));
- peer_framer_.SetEncrypter(ENCRYPTION_INITIAL,
+ peer_framer_.SetEncrypter(ENCRYPTION_ZERO_RTT,
QuicMakeUnique<TaggingEncrypter>(tag));
// Process a packet from the non-crypto stream.
frame1_.stream_id = 3;
@@ -5713,14 +5720,14 @@
uint64_t kFirstDecimatedPacket = 101;
for (unsigned int i = 0; i < kFirstDecimatedPacket - 1; ++i) {
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
- ProcessDataPacketAtLevel(1 + i, !kHasStopWaiting, ENCRYPTION_INITIAL);
+ ProcessDataPacketAtLevel(1 + i, !kHasStopWaiting, ENCRYPTION_ZERO_RTT);
}
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
- // The same as ProcessPacket(1) except that ENCRYPTION_INITIAL is used
+ // The same as ProcessPacket(1) except that ENCRYPTION_ZERO_RTT is used
// instead of ENCRYPTION_NONE.
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
ProcessDataPacketAtLevel(kFirstDecimatedPacket, !kHasStopWaiting,
- ENCRYPTION_INITIAL);
+ ENCRYPTION_ZERO_RTT);
// Check if delayed ack timer is running for the expected interval.
EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
@@ -5729,7 +5736,7 @@
// Process packet 10 first and ensure the alarm is one eighth min_rtt.
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
ProcessDataPacketAtLevel(kFirstDecimatedPacket + 19, !kHasStopWaiting,
- ENCRYPTION_INITIAL);
+ ENCRYPTION_ZERO_RTT);
ack_time = clock_.ApproximateNow() + QuicTime::Delta::FromMilliseconds(5);
EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
EXPECT_EQ(ack_time, connection_.GetAckAlarm()->deadline());
@@ -5739,7 +5746,7 @@
EXPECT_TRUE(connection_.GetAckAlarm()->IsSet());
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
ProcessDataPacketAtLevel(kFirstDecimatedPacket + 1 + i, !kHasStopWaiting,
- ENCRYPTION_INITIAL);
+ ENCRYPTION_ZERO_RTT);
}
// Check that ack is sent and that delayed ack alarm is reset.
if (GetParam().no_stop_waiting) {
@@ -5757,7 +5764,7 @@
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
ProcessDataPacketAtLevel(kFirstDecimatedPacket + 10, !kHasStopWaiting,
- ENCRYPTION_INITIAL);
+ ENCRYPTION_ZERO_RTT);
// Check that ack is sent and that delayed ack alarm is reset.
if (GetParam().no_stop_waiting) {
EXPECT_EQ(1u, writer_->frame_count());
@@ -5810,23 +5817,46 @@
TEST_P(QuicConnectionTest, NoAckOnOldNacks) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
// Drop one packet, triggering a sequence of acks.
+ if (GetQuicRestartFlag(quic_enable_accept_random_ipn)) {
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
+ } else {
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
+ }
ProcessPacket(2);
size_t frames_per_ack = GetParam().no_stop_waiting ? 1 : 2;
- EXPECT_EQ(frames_per_ack, writer_->frame_count());
- EXPECT_FALSE(writer_->ack_frames().empty());
- writer_->Reset();
+ if (!GetQuicRestartFlag(quic_enable_accept_random_ipn)) {
+ EXPECT_EQ(frames_per_ack, writer_->frame_count());
+ EXPECT_FALSE(writer_->ack_frames().empty());
+ writer_->Reset();
+ }
+
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
ProcessPacket(3);
EXPECT_EQ(frames_per_ack, writer_->frame_count());
EXPECT_FALSE(writer_->ack_frames().empty());
writer_->Reset();
+
+ if (GetQuicRestartFlag(quic_enable_accept_random_ipn)) {
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
+ } else {
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
+ }
ProcessPacket(4);
- EXPECT_EQ(frames_per_ack, writer_->frame_count());
- EXPECT_FALSE(writer_->ack_frames().empty());
- writer_->Reset();
+ if (GetQuicRestartFlag(quic_enable_accept_random_ipn)) {
+ EXPECT_EQ(0u, writer_->frame_count());
+ } else {
+ EXPECT_EQ(frames_per_ack, writer_->frame_count());
+ EXPECT_FALSE(writer_->ack_frames().empty());
+ writer_->Reset();
+ }
+
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
ProcessPacket(5);
EXPECT_EQ(frames_per_ack, writer_->frame_count());
EXPECT_FALSE(writer_->ack_frames().empty());
writer_->Reset();
+
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
// Now only set the timer on the 6th packet, instead of sending another ack.
ProcessPacket(6);
EXPECT_EQ(0u, writer_->frame_count());
@@ -5904,7 +5934,11 @@
EXPECT_EQ(4u, writer_->frame_count());
EXPECT_FALSE(writer_->stop_waiting_frames().empty());
}
- EXPECT_EQ(1u, writer_->stream_frames().size());
+ if (connection_.transport_version() < QUIC_VERSION_47) {
+ EXPECT_EQ(1u, writer_->stream_frames().size());
+ } else {
+ EXPECT_EQ(1u, writer_->crypto_frames().size());
+ }
EXPECT_EQ(1u, writer_->padding_frames().size());
ASSERT_FALSE(writer_->ack_frames().empty());
EXPECT_EQ(QuicPacketNumber(2u), LargestAcked(writer_->ack_frames().front()));
@@ -5933,7 +5967,11 @@
EXPECT_EQ(4u, writer_->frame_count());
EXPECT_FALSE(writer_->stop_waiting_frames().empty());
}
- EXPECT_EQ(1u, writer_->stream_frames().size());
+ if (connection_.transport_version() < QUIC_VERSION_47) {
+ EXPECT_EQ(1u, writer_->stream_frames().size());
+ } else {
+ EXPECT_EQ(1u, writer_->crypto_frames().size());
+ }
EXPECT_EQ(1u, writer_->padding_frames().size());
ASSERT_FALSE(writer_->ack_frames().empty());
EXPECT_EQ(QuicPacketNumber(2u), LargestAcked(writer_->ack_frames().front()));
@@ -6214,6 +6252,13 @@
header.version_flag = true;
header.packet_number = QuicPacketNumber(12);
+ if (QuicVersionHasLongHeaderLengths(
+ peer_framer_.version().transport_version)) {
+ header.long_packet_type = INITIAL;
+ header.retry_token_length_length = VARIABLE_LENGTH_INTEGER_LENGTH_1;
+ header.length_length = VARIABLE_LENGTH_INTEGER_LENGTH_2;
+ }
+
QuicFrames frames;
frames.push_back(QuicFrame(frame1_));
std::unique_ptr<QuicPacket> packet(ConstructPacket(header, frames));
@@ -6259,6 +6304,13 @@
header.version_flag = true;
header.packet_number = QuicPacketNumber(12);
+ if (QuicVersionHasLongHeaderLengths(
+ peer_framer_.version().transport_version)) {
+ header.long_packet_type = INITIAL;
+ header.retry_token_length_length = VARIABLE_LENGTH_INTEGER_LENGTH_1;
+ header.length_length = VARIABLE_LENGTH_INTEGER_LENGTH_2;
+ }
+
QuicFrames frames;
frames.push_back(QuicFrame(frame1_));
std::unique_ptr<QuicPacket> packet(ConstructPacket(header, frames));
@@ -6311,6 +6363,13 @@
header.version_flag = true;
header.packet_number = QuicPacketNumber(12);
+ if (QuicVersionHasLongHeaderLengths(
+ peer_framer_.version().transport_version)) {
+ header.long_packet_type = INITIAL;
+ header.retry_token_length_length = VARIABLE_LENGTH_INTEGER_LENGTH_1;
+ header.length_length = VARIABLE_LENGTH_INTEGER_LENGTH_2;
+ }
+
QuicFrames frames;
frames.push_back(QuicFrame(frame1_));
std::unique_ptr<QuicPacket> packet(ConstructPacket(header, frames));
@@ -7586,6 +7645,7 @@
}
QuicString message(connection_.GetLargestMessagePayload() * 2, 'a');
QuicStringPiece message_data(message);
+ QuicMemSliceStorage storage(nullptr, 0, nullptr, 0);
{
QuicConnection::ScopedPacketFlusher flusher(&connection_,
QuicConnection::SEND_ACK);
@@ -7594,22 +7654,32 @@
// get sent, one contains stream frame, and the other only contains the
// message frame.
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(2);
- EXPECT_EQ(MESSAGE_STATUS_SUCCESS,
- connection_.SendMessage(
- 1, QuicStringPiece(message_data.data(),
- connection_.GetLargestMessagePayload())));
+ EXPECT_EQ(
+ MESSAGE_STATUS_SUCCESS,
+ connection_.SendMessage(
+ 1, MakeSpan(connection_.helper()->GetStreamSendBufferAllocator(),
+ QuicStringPiece(message_data.data(),
+ connection_.GetLargestMessagePayload()),
+ &storage)));
}
// Fail to send a message if connection is congestion control blocked.
EXPECT_CALL(*send_algorithm_, CanSend(_)).WillOnce(Return(false));
- EXPECT_EQ(MESSAGE_STATUS_BLOCKED, connection_.SendMessage(2, "message"));
+ EXPECT_EQ(
+ MESSAGE_STATUS_BLOCKED,
+ connection_.SendMessage(
+ 2, MakeSpan(connection_.helper()->GetStreamSendBufferAllocator(),
+ "message", &storage)));
// Always fail to send a message which cannot fit into one packet.
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
EXPECT_EQ(
MESSAGE_STATUS_TOO_LARGE,
connection_.SendMessage(
- 3, QuicStringPiece(message_data.data(),
- connection_.GetLargestMessagePayload() + 1)));
+ 3,
+ MakeSpan(connection_.helper()->GetStreamSendBufferAllocator(),
+ QuicStringPiece(message_data.data(),
+ connection_.GetLargestMessagePayload() + 1),
+ &storage)));
}
// Test to check that the path challenge/path response logic works
diff --git a/quic/core/quic_control_frame_manager.cc b/quic/core/quic_control_frame_manager.cc
index c2b5192..8d4ba53 100644
--- a/quic/core/quic_control_frame_manager.cc
+++ b/quic/core/quic_control_frame_manager.cc
@@ -88,25 +88,6 @@
new QuicStopSendingFrame(++last_control_frame_id_, stream_id, code)));
}
-void QuicControlFrameManager::WriteOrBufferRstStreamStopSending(
- QuicStreamId stream_id,
- QuicRstStreamErrorCode error_code,
- QuicStreamOffset bytes_written) {
- const bool had_buffered_frames = HasBufferedFrames();
- QUIC_DVLOG(1) << "Queuing RST_STREAM_FRAME";
- control_frames_.emplace_back(QuicFrame(new QuicRstStreamFrame(
- ++last_control_frame_id_, stream_id, error_code, bytes_written)));
- if (session_->connection()->transport_version() == QUIC_VERSION_99) {
- QUIC_DVLOG(1) << "Version 99, Queuing STOP_SENDING";
- control_frames_.emplace_back(QuicFrame(new QuicStopSendingFrame(
- ++last_control_frame_id_, stream_id, error_code)));
- }
- if (had_buffered_frames) {
- return;
- }
- WriteBufferedFrames();
-}
-
void QuicControlFrameManager::WritePing() {
QUIC_DVLOG(1) << "Writing PING_FRAME";
if (HasBufferedFrames()) {
diff --git a/quic/core/quic_control_frame_manager.h b/quic/core/quic_control_frame_manager.h
index ace08c6..618f3f9 100644
--- a/quic/core/quic_control_frame_manager.h
+++ b/quic/core/quic_control_frame_manager.h
@@ -61,13 +61,6 @@
// immediately.
void WriteOrBufferMaxStreamId(QuicStreamId id);
- // Tries to send a packet with both a RST_STREAM and, if version 99, an
- // IETF-QUIC STOP_SENDING frame. The frames are buffered if they can not
- // be sent immediately.
- void WriteOrBufferRstStreamStopSending(QuicControlFrameId stream_id,
- QuicRstStreamErrorCode error_code,
- QuicStreamOffset bytes_written);
-
// Tries to send an IETF-QUIC STOP_SENDING frame. The frame is buffered if it
// can not be sent immediately.
void WriteOrBufferStopSending(uint16_t code, QuicStreamId stream_id);
diff --git a/quic/core/quic_crypto_client_handshaker.cc b/quic/core/quic_crypto_client_handshaker.cc
index 81487df..43948c2 100644
--- a/quic/core/quic_crypto_client_handshaker.cc
+++ b/quic/core/quic_crypto_client_handshaker.cc
@@ -95,7 +95,7 @@
proof_handler_(proof_handler),
verify_ok_(false),
stateless_reject_received_(false),
- proof_verify_start_time_(QuicWallTime::Zero()),
+ proof_verify_start_time_(QuicTime::Zero()),
num_scup_messages_received_(0),
encryption_established_(false),
handshake_confirmed_(false),
@@ -272,7 +272,7 @@
// the proof.
DCHECK(crypto_config_->proof_verifier());
// Track proof verification time when cached server config is used.
- proof_verify_start_time_ = session()->connection()->clock()->WallNow();
+ proof_verify_start_time_ = session()->connection()->clock()->Now();
chlo_hash_ = cached->chlo_hash();
// If the cached state needs to be verified, do it now.
next_state_ = STATE_VERIFY_PROOF;
@@ -381,15 +381,15 @@
SendHandshakeMessage(out);
// Be prepared to decrypt with the new server write key.
session()->connection()->SetAlternativeDecrypter(
- ENCRYPTION_INITIAL,
+ ENCRYPTION_ZERO_RTT,
std::move(crypto_negotiated_params_->initial_crypters.decrypter),
true /* latch once used */);
// Send subsequent packets under encryption on the assumption that the
// server will accept the handshake.
session()->connection()->SetEncrypter(
- ENCRYPTION_INITIAL,
+ ENCRYPTION_ZERO_RTT,
std::move(crypto_negotiated_params_->initial_crypters.encrypter));
- session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
+ session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_ZERO_RTT);
// TODO(ianswett): Merge ENCRYPTION_REESTABLISHED and
// ENCRYPTION_FIRST_ESTABLSIHED
@@ -498,12 +498,10 @@
void QuicCryptoClientHandshaker::DoVerifyProofComplete(
QuicCryptoClientConfig::CachedState* cached) {
- if (!proof_verify_start_time_.IsZero()) {
+ if (proof_verify_start_time_.IsInitialized()) {
QUIC_CLIENT_HISTOGRAM_TIMES(
"QuicSession.VerifyProofTime.CachedServerConfig",
- QuicTime::Delta::FromMicroseconds(
- session()->connection()->clock()->WallNow().ToUNIXMicroseconds() -
- proof_verify_start_time_.ToUNIXMicroseconds()),
+ (session()->connection()->clock()->Now() - proof_verify_start_time_),
QuicTime::Delta::FromMilliseconds(1), QuicTime::Delta::FromSeconds(10),
50, "");
}
diff --git a/quic/core/quic_crypto_client_handshaker.h b/quic/core/quic_crypto_client_handshaker.h
index 14fe0a8..c84c2cd 100644
--- a/quic/core/quic_crypto_client_handshaker.h
+++ b/quic/core/quic_crypto_client_handshaker.h
@@ -222,7 +222,7 @@
// STATE_VERIFY_PROOF*, and subsequent STATE_SEND_CHLO state.
bool stateless_reject_received_;
- QuicWallTime proof_verify_start_time_;
+ QuicTime proof_verify_start_time_;
int num_scup_messages_received_;
diff --git a/quic/core/quic_crypto_handshaker.cc b/quic/core/quic_crypto_handshaker.cc
index dab2741..fa0f78a 100644
--- a/quic/core/quic_crypto_handshaker.cc
+++ b/quic/core/quic_crypto_handshaker.cc
@@ -26,8 +26,8 @@
session()->OnCryptoHandshakeMessageSent(message);
last_sent_handshake_message_tag_ = message.tag();
const QuicData& data = message.GetSerialized();
- stream_->WriteOrBufferData(QuicStringPiece(data.data(), data.length()), false,
- nullptr);
+ stream_->WriteCryptoData(session_->connection()->encryption_level(),
+ data.AsStringPiece());
}
void QuicCryptoHandshaker::OnError(CryptoFramer* framer) {
diff --git a/quic/core/quic_crypto_server_handshaker.cc b/quic/core/quic_crypto_server_handshaker.cc
index e79a60c..08ef18b 100644
--- a/quic/core/quic_crypto_server_handshaker.cc
+++ b/quic/core/quic_crypto_server_handshaker.cc
@@ -225,13 +225,13 @@
//
// NOTE: the SHLO will be encrypted with the new server write key.
session()->connection()->SetEncrypter(
- ENCRYPTION_INITIAL,
+ ENCRYPTION_ZERO_RTT,
std::move(crypto_negotiated_params_->initial_crypters.encrypter));
- session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
+ session()->connection()->SetDefaultEncryptionLevel(ENCRYPTION_ZERO_RTT);
// Set the decrypter immediately so that we no longer accept unencrypted
// packets.
session()->connection()->SetDecrypter(
- ENCRYPTION_INITIAL,
+ ENCRYPTION_ZERO_RTT,
std::move(crypto_negotiated_params_->initial_crypters.decrypter));
session()->connection()->SetDiversificationNonce(*diversification_nonce);
@@ -310,9 +310,13 @@
QUIC_DVLOG(1) << "Server: Sending server config update: "
<< message.DebugString();
- const QuicData& data = message.GetSerialized();
- stream_->WriteOrBufferData(QuicStringPiece(data.data(), data.length()), false,
- nullptr);
+ if (transport_version() < QUIC_VERSION_47) {
+ const QuicData& data = message.GetSerialized();
+ stream_->WriteOrBufferData(QuicStringPiece(data.data(), data.length()),
+ false, nullptr);
+ } else {
+ SendHandshakeMessage(message);
+ }
++num_server_config_update_messages_sent_;
}
@@ -352,6 +356,11 @@
QuicLongHeaderType QuicCryptoServerHandshaker::GetLongHeaderType(
QuicStreamOffset /*offset*/) const {
if (last_sent_handshake_message_tag() == kSREJ) {
+ if (QuicVersionHasLongHeaderLengths(
+ session()->connection()->transport_version())) {
+ return HANDSHAKE;
+ }
+ // TODO(b/123493765): we should probably not be sending RETRY here.
return RETRY;
}
if (last_sent_handshake_message_tag() == kSHLO) {
diff --git a/quic/core/quic_crypto_server_stream_test.cc b/quic/core/quic_crypto_server_stream_test.cc
index 33635d8..c0a3e08 100644
--- a/quic/core/quic_crypto_server_stream_test.cc
+++ b/quic/core/quic_crypto_server_stream_test.cc
@@ -189,7 +189,7 @@
ParsedQuicVersionVector supported_versions_ = AllSupportedVersions();
};
-INSTANTIATE_TEST_CASE_P(Tests, QuicCryptoServerStreamTest, testing::Bool());
+INSTANTIATE_TEST_SUITE_P(Tests, QuicCryptoServerStreamTest, testing::Bool());
TEST_P(QuicCryptoServerStreamTest, NotInitiallyConected) {
Initialize();
@@ -497,9 +497,9 @@
std::unique_ptr<FailingProofSource>(new FailingProofSource)) {}
};
-INSTANTIATE_TEST_CASE_P(MoreTests,
- QuicCryptoServerStreamTestWithFailingProofSource,
- testing::Bool());
+INSTANTIATE_TEST_SUITE_P(MoreTests,
+ QuicCryptoServerStreamTestWithFailingProofSource,
+ testing::Bool());
TEST_P(QuicCryptoServerStreamTestWithFailingProofSource, Test) {
Initialize();
@@ -531,9 +531,9 @@
QuicCryptoServerConfigPeer crypto_config_peer_;
};
-INSTANTIATE_TEST_CASE_P(YetMoreTests,
- QuicCryptoServerStreamTestWithFakeProofSource,
- testing::Bool());
+INSTANTIATE_TEST_SUITE_P(YetMoreTests,
+ QuicCryptoServerStreamTestWithFakeProofSource,
+ testing::Bool());
// Regression test for b/35422225, in which multiple CHLOs arriving on the same
// connection in close succession could cause a crash, especially when the use
diff --git a/quic/core/quic_crypto_stream.cc b/quic/core/quic_crypto_stream.cc
index 8199571..43d1f1a 100644
--- a/quic/core/quic_crypto_stream.cc
+++ b/quic/core/quic_crypto_stream.cc
@@ -27,7 +27,10 @@
session->connection()->transport_version()),
session,
/*is_static=*/true,
- BIDIRECTIONAL) {
+ BIDIRECTIONAL),
+ substreams_{{this, ENCRYPTION_NONE},
+ {this, ENCRYPTION_ZERO_RTT},
+ {this, ENCRYPTION_FORWARD_SECURE}} {
// The crypto stream is exempt from connection level flow control.
DisableConnectionFlowControlForThisStream();
}
@@ -43,56 +46,57 @@
/*include_diversification_nonce=*/true,
version > QUIC_VERSION_43 ? PACKET_4BYTE_PACKET_NUMBER
: PACKET_1BYTE_PACKET_NUMBER,
+ VARIABLE_LENGTH_INTEGER_LENGTH_1, VARIABLE_LENGTH_INTEGER_LENGTH_2,
/*offset=*/0);
}
-void QuicCryptoStream::OnDataAvailable() {
- struct iovec iov;
- // When calling CryptoMessageParser::ProcessInput, an EncryptionLevel needs to
- // be provided. Note that in the general case, the following code may be
- // incorrect. When a stream frame is added to the sequencer, the encryption
- // level provided by the connection will be the encryption level that the
- // frame was received under, but stream frames can be received out of order.
- // If a later stream frame at a higher encryption level is received before an
- // earlier stream frame at a lower encryption level, this code will call
- // CryptoMessageParser::Process input with the data from both frames, but
- // indicate that they both were received at the higher encryption level.
- //
- // For QUIC crypto, this is not a problem, because the CryptoFramer (which
- // implements CryptoMessageParser) ignores the EncryptionLevel passed into
- // ProcessInput.
- //
- // For the TLS handshake, this does not cause an issue for the transition from
- // initial encryption (ClientHello, HelloRetryRequest, and ServerHello) to
- // handshake encryption, as all data from the initial encryption level is
- // needed to derive the handshake encryption keys. For the transition from
- // handshake encryption to 1-RTT application data encryption, all messages at
- // the handshake encryption level *except* the client Finished are needed. The
- // only place this logic would be broken is if a server receives a crypto
- // handshake message that is encrypted under the 1-RTT data keys before
- // receiving the client's Finished message (under handshake encryption keys).
- // Right now, this implementation of TLS in QUIC does not support doing that,
- // but it is possible (although unlikely) that other implementations could.
- // Therefore, this needs to be fixed before the TLS handshake is enabled.
- //
- // TODO(nharper): Use a more robust and correct mechanism to provide the
- // EncryptionLevel to CryptoMessageParser::ProcessInput. This must be done
- // before enabling the TLS handshake.
+void QuicCryptoStream::OnCryptoFrame(const QuicCryptoFrame& frame) {
+ QUIC_BUG_IF(session()->connection()->transport_version() < QUIC_VERSION_47)
+ << "Versions less than 47 shouldn't receive CRYPTO frames";
EncryptionLevel level = session()->connection()->last_decrypted_level();
- while (sequencer()->GetReadableRegion(&iov)) {
+ substreams_[level].sequencer.OnCryptoFrame(frame);
+}
+
+void QuicCryptoStream::OnStreamFrame(const QuicStreamFrame& frame) {
+ if (session()->connection()->transport_version() >= QUIC_VERSION_47) {
+ QUIC_PEER_BUG
+ << "Crypto data received in stream frame instead of crypto frame";
+ CloseConnectionWithDetails(QUIC_INVALID_STREAM_DATA,
+ "Unexpected stream frame");
+ }
+ QuicStream::OnStreamFrame(frame);
+}
+
+void QuicCryptoStream::OnDataAvailable() {
+ EncryptionLevel level = session()->connection()->last_decrypted_level();
+ if (session()->connection()->transport_version() < QUIC_VERSION_47) {
+ // Versions less than 47 only support QUIC crypto, which ignores the
+ // EncryptionLevel passed into CryptoMessageParser::ProcessInput (and
+ // OnDataAvailableInSequencer).
+ OnDataAvailableInSequencer(sequencer(), level);
+ return;
+ }
+ OnDataAvailableInSequencer(&substreams_[level].sequencer, level);
+}
+
+void QuicCryptoStream::OnDataAvailableInSequencer(
+ QuicStreamSequencer* sequencer,
+ EncryptionLevel level) {
+ struct iovec iov;
+ while (sequencer->GetReadableRegion(&iov)) {
QuicStringPiece data(static_cast<char*>(iov.iov_base), iov.iov_len);
if (!crypto_message_parser()->ProcessInput(data, level)) {
CloseConnectionWithDetails(crypto_message_parser()->error(),
crypto_message_parser()->error_detail());
return;
}
- sequencer()->MarkConsumed(iov.iov_len);
+ sequencer->MarkConsumed(iov.iov_len);
if (handshake_confirmed() &&
crypto_message_parser()->InputBytesRemaining() == 0) {
// If the handshake is complete and the current message has been fully
// processed then no more handshake messages are likely to arrive soon
// so release the memory in the stream sequencer.
- sequencer()->ReleaseBufferIfEmpty();
+ sequencer->ReleaseBufferIfEmpty();
}
}
}
@@ -113,33 +117,90 @@
void QuicCryptoStream::WriteCryptoData(EncryptionLevel level,
QuicStringPiece data) {
- // TODO(nharper): This approach to writing data, by setting the encryption
- // level, calling WriteOrBufferData, and then restoring the encryption level,
- // is fragile and assumes that the data gets received by the peer when
- // WriteOrBufferData is called. There is no guarantee that data will get
- // retransmitted at the correct level. This needs to be redone with the
- // cleanup for OnDataAvailable by managing the streams/crypto frames for
- // encryption levels separately.
+ if (session()->connection()->transport_version() < QUIC_VERSION_47) {
+ // The QUIC crypto handshake takes care of setting the appropriate
+ // encryption level before writing data. Since that is the only handshake
+ // supported in versions less than 47, |level| can be ignored here.
+ WriteOrBufferData(data, /* fin */ false, /* ack_listener */ nullptr);
+ return;
+ }
+ if (data.empty()) {
+ QUIC_BUG << "Empty crypto data being written";
+ return;
+ }
+ // Append |data| to the send buffer for this encryption level.
+ struct iovec iov(QuicUtils::MakeIovec(data));
+ QuicStreamSendBuffer* send_buffer = &substreams_[level].send_buffer;
+ QuicStreamOffset offset = send_buffer->stream_offset();
+ send_buffer->SaveStreamData(&iov, /*iov_count=*/1, /*iov_offset=*/0,
+ data.length());
+ if (kMaxStreamLength - offset < data.length()) {
+ QUIC_BUG << "Writing too much crypto handshake data";
+ // TODO(nharper): Switch this to an IETF QUIC error code, possibly
+ // INTERNAL_ERROR?
+ CloseConnectionWithDetails(QUIC_STREAM_LENGTH_OVERFLOW,
+ "Writing too much crypto handshake data");
+ }
+
+ // Set long header type based on the encryption level.
+ if (level != ENCRYPTION_FORWARD_SECURE) {
+ QuicStreamOffset fake_offset = level == ENCRYPTION_NONE ? 0 : 1;
+ // Implementations of GetLongHeaderType either don't care at all about the
+ // offset, or only care whether or not it's 0. However, they do care that it
+ // is an absolute offset from the start of unencrypted crypto data, not the
+ // offset at a particular encryption level.
+ QuicLongHeaderType type = GetLongHeaderType(fake_offset);
+ session()->connection()->SetLongHeaderType(type);
+ }
EncryptionLevel current_level = session()->connection()->encryption_level();
session()->connection()->SetDefaultEncryptionLevel(level);
- WriteOrBufferData(data, /* fin */ false, /* ack_listener */ nullptr);
- if (current_level == ENCRYPTION_FORWARD_SECURE && level != current_level) {
- session()->connection()->SetDefaultEncryptionLevel(current_level);
- }
+ size_t bytes_consumed =
+ session()->connection()->SendCryptoData(level, data.length(), offset);
+ session()->connection()->SetDefaultEncryptionLevel(current_level);
+
+ send_buffer->OnStreamDataConsumed(bytes_consumed);
}
void QuicCryptoStream::OnSuccessfulVersionNegotiation(
const ParsedQuicVersion& version) {}
+bool QuicCryptoStream::OnCryptoFrameAcked(const QuicCryptoFrame& frame,
+ QuicTime::Delta ack_delay_time) {
+ QuicByteCount newly_acked_length = 0;
+ if (!substreams_[frame.level].send_buffer.OnStreamDataAcked(
+ frame.offset, frame.data_length, &newly_acked_length)) {
+ CloseConnectionWithDetails(QUIC_INTERNAL_ERROR,
+ "Trying to ack unsent crypto data.");
+ return false;
+ }
+ return newly_acked_length > 0;
+}
+
void QuicCryptoStream::NeuterUnencryptedStreamData() {
- for (const auto& interval : bytes_consumed_[ENCRYPTION_NONE]) {
+ if (session()->connection()->transport_version() < QUIC_VERSION_47) {
+ for (const auto& interval : bytes_consumed_[ENCRYPTION_NONE]) {
+ QuicByteCount newly_acked_length = 0;
+ send_buffer().OnStreamDataAcked(
+ interval.min(), interval.max() - interval.min(), &newly_acked_length);
+ }
+ return;
+ }
+ QuicStreamSendBuffer* send_buffer = &substreams_[ENCRYPTION_NONE].send_buffer;
+ // TODO(nharper): Consider adding a Clear() method to QuicStreamSendBuffer to
+ // replace the following code.
+ QuicIntervalSet<QuicStreamOffset> to_ack = send_buffer->bytes_acked();
+ to_ack.Complement(0, send_buffer->stream_offset());
+ for (const auto& interval : to_ack) {
QuicByteCount newly_acked_length = 0;
- send_buffer().OnStreamDataAcked(
+ send_buffer->OnStreamDataAcked(
interval.min(), interval.max() - interval.min(), &newly_acked_length);
}
}
void QuicCryptoStream::OnStreamDataConsumed(size_t bytes_consumed) {
+ if (session()->connection()->transport_version() >= QUIC_VERSION_47) {
+ QUIC_BUG << "Stream data consumed when CRYPTO frames should be in use";
+ }
if (bytes_consumed > 0) {
bytes_consumed_[session()->connection()->encryption_level()].Add(
stream_bytes_written(), stream_bytes_written() + bytes_consumed);
@@ -147,6 +208,38 @@
QuicStream::OnStreamDataConsumed(bytes_consumed);
}
+bool QuicCryptoStream::HasPendingCryptoRetransmission() {
+ if (session()->connection()->transport_version() < QUIC_VERSION_47) {
+ return false;
+ }
+ for (EncryptionLevel level :
+ {ENCRYPTION_NONE, ENCRYPTION_ZERO_RTT, ENCRYPTION_FORWARD_SECURE}) {
+ if (substreams_[level].send_buffer.HasPendingRetransmission()) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void QuicCryptoStream::WritePendingCryptoRetransmission() {
+ QUIC_BUG_IF(session()->connection()->transport_version() < QUIC_VERSION_47)
+ << "Versions less than 47 don't write CRYPTO frames";
+ EncryptionLevel current_encryption_level =
+ session()->connection()->encryption_level();
+ for (EncryptionLevel level :
+ {ENCRYPTION_NONE, ENCRYPTION_ZERO_RTT, ENCRYPTION_FORWARD_SECURE}) {
+ QuicStreamSendBuffer* send_buffer = &substreams_[level].send_buffer;
+ session()->connection()->SetDefaultEncryptionLevel(level);
+ while (send_buffer->HasPendingRetransmission()) {
+ auto pending = send_buffer->NextPendingRetransmission();
+ size_t bytes_consumed = session()->connection()->SendCryptoData(
+ level, pending.length, pending.offset);
+ send_buffer->OnStreamDataRetransmitted(pending.offset, bytes_consumed);
+ }
+ }
+ session()->connection()->SetDefaultEncryptionLevel(current_encryption_level);
+}
+
void QuicCryptoStream::WritePendingRetransmission() {
while (HasPendingRetransmission()) {
StreamPendingRetransmission pending =
@@ -236,5 +329,97 @@
return true;
}
+uint64_t QuicCryptoStream::crypto_bytes_read() const {
+ if (session()->connection()->transport_version() < QUIC_VERSION_47) {
+ return stream_bytes_read();
+ }
+ return substreams_[ENCRYPTION_NONE].sequencer.NumBytesConsumed() +
+ substreams_[ENCRYPTION_ZERO_RTT].sequencer.NumBytesConsumed() +
+ substreams_[ENCRYPTION_FORWARD_SECURE].sequencer.NumBytesConsumed();
+}
+
+uint64_t QuicCryptoStream::BytesReadOnLevel(EncryptionLevel level) const {
+ return substreams_[level].sequencer.NumBytesConsumed();
+}
+
+bool QuicCryptoStream::WriteCryptoFrame(EncryptionLevel level,
+ QuicStreamOffset offset,
+ QuicByteCount data_length,
+ QuicDataWriter* writer) {
+ QUIC_BUG_IF(session()->connection()->transport_version() < QUIC_VERSION_47)
+ << "Versions less than 47 don't write CRYPTO frames (2)";
+ return substreams_[level].send_buffer.WriteStreamData(offset, data_length,
+ writer);
+}
+
+void QuicCryptoStream::OnCryptoFrameLost(QuicCryptoFrame* crypto_frame) {
+ QUIC_BUG_IF(session()->connection()->transport_version() < QUIC_VERSION_47)
+ << "Versions less than 47 don't lose CRYPTO frames";
+ substreams_[crypto_frame->level].send_buffer.OnStreamDataLost(
+ crypto_frame->offset, crypto_frame->data_length);
+}
+
+void QuicCryptoStream::RetransmitData(QuicCryptoFrame* crypto_frame) {
+ QUIC_BUG_IF(session()->connection()->transport_version() < QUIC_VERSION_47)
+ << "Versions less than 47 don't retransmit CRYPTO frames";
+ QuicIntervalSet<QuicStreamOffset> retransmission(
+ crypto_frame->offset, crypto_frame->offset + crypto_frame->data_length);
+ QuicStreamSendBuffer* send_buffer =
+ &substreams_[crypto_frame->level].send_buffer;
+ retransmission.Difference(send_buffer->bytes_acked());
+ if (retransmission.Empty()) {
+ return;
+ }
+ EncryptionLevel current_encryption_level =
+ session()->connection()->encryption_level();
+ for (const auto& interval : retransmission) {
+ size_t retransmission_offset = interval.min();
+ size_t retransmission_length = interval.max() - interval.min();
+ session()->connection()->SetDefaultEncryptionLevel(crypto_frame->level);
+ size_t bytes_consumed = session()->connection()->SendCryptoData(
+ crypto_frame->level, retransmission_length, retransmission_offset);
+ send_buffer->OnStreamDataRetransmitted(retransmission_offset,
+ bytes_consumed);
+ }
+ session()->connection()->SetDefaultEncryptionLevel(current_encryption_level);
+}
+
+bool QuicCryptoStream::IsFrameOutstanding(EncryptionLevel level,
+ size_t offset,
+ size_t length) const {
+ if (session()->connection()->transport_version() < QUIC_VERSION_47) {
+ // This only happens if a client was originally configured for a version
+ // greater than 45, but received a version negotiation packet and is
+ // attempting to retransmit for a version less than 47. Outside of tests,
+ // this is a misconfiguration of the client, and this connection will be
+ // doomed. Return false here to avoid trying to retransmit CRYPTO frames on
+ // the wrong transport version.
+ return false;
+ }
+ return substreams_[level].send_buffer.IsStreamDataOutstanding(offset, length);
+}
+
+bool QuicCryptoStream::IsWaitingForAcks() const {
+ if (session()->connection()->transport_version() < QUIC_VERSION_47) {
+ return QuicStream::IsWaitingForAcks();
+ }
+ for (EncryptionLevel level :
+ {ENCRYPTION_NONE, ENCRYPTION_ZERO_RTT, ENCRYPTION_FORWARD_SECURE}) {
+ if (substreams_[level].send_buffer.stream_bytes_outstanding()) {
+ return true;
+ }
+ }
+ return false;
+}
+
+QuicCryptoStream::CryptoSubstream::CryptoSubstream(
+ QuicCryptoStream* crypto_stream,
+ EncryptionLevel)
+ : sequencer(crypto_stream),
+ send_buffer(crypto_stream->session()
+ ->connection()
+ ->helper()
+ ->GetStreamSendBufferAllocator()) {}
+
#undef ENDPOINT // undef for jumbo builds
} // namespace quic
diff --git a/quic/core/quic_crypto_stream.h b/quic/core/quic_crypto_stream.h
index 0593f44..cfd81c7 100644
--- a/quic/core/quic_crypto_stream.h
+++ b/quic/core/quic_crypto_stream.h
@@ -45,8 +45,16 @@
QuicTransportVersion version);
// QuicStream implementation
+ void OnStreamFrame(const QuicStreamFrame& frame) override;
void OnDataAvailable() override;
+ // Called when a CRYPTO frame is received.
+ void OnCryptoFrame(const QuicCryptoFrame& frame);
+
+ // Called when a CRYPTO frame is ACKed.
+ bool OnCryptoFrameAcked(const QuicCryptoFrame& frame,
+ QuicTime::Delta ack_delay_time);
+
// Performs key extraction to derive a new secret of |result_len| bytes
// dependent on |label|, |context|, and the stream's negotiated subkey secret.
// Returns false if the handshake has not been confirmed or the parameters are
@@ -86,6 +94,13 @@
// Override to record the encryption level of consumed data.
void OnStreamDataConsumed(size_t bytes_consumed) override;
+ // Returns whether there are any bytes pending retransmission in CRYPTO
+ // frames.
+ virtual bool HasPendingCryptoRetransmission();
+
+ // Writes any pending CRYPTO frame retransmissions.
+ void WritePendingCryptoRetransmission();
+
// Override to retransmit lost crypto data with the appropriate encryption
// level.
void WritePendingRetransmission() override;
@@ -95,11 +110,66 @@
QuicByteCount data_length,
bool fin) override;
+ // Returns the number of bytes of handshake data that have been received from
+ // the peer in either CRYPTO or STREAM frames.
+ uint64_t crypto_bytes_read() const;
+
+ // Returns the number of bytes of handshake data that have been received from
+ // the peer in CRYPTO frames at a particular encryption level.
+ QuicByteCount BytesReadOnLevel(EncryptionLevel level) const;
+
+ // Writes |data_length| of data of a crypto frame to |writer|. The data
+ // written is from the send buffer for encryption level |level| and starts at
+ // |offset|.
+ bool WriteCryptoFrame(EncryptionLevel level,
+ QuicStreamOffset offset,
+ QuicByteCount data_length,
+ QuicDataWriter* writer);
+
+ // Called when data from a CRYPTO frame is considered lost. The lost data is
+ // identified by the encryption level, offset, and length in |crypto_frame|.
+ void OnCryptoFrameLost(QuicCryptoFrame* crypto_frame);
+
+ // Called to retransmit any outstanding data in the range indicated by the
+ // encryption level, offset, and length in |crypto_frame|.
+ void RetransmitData(QuicCryptoFrame* crypto_frame);
+
+ // Returns true if any portion of the data at encryption level |level|
+ // starting at |offset| for |length| bytes is outstanding.
+ bool IsFrameOutstanding(EncryptionLevel level,
+ size_t offset,
+ size_t length) const;
+
+ // Returns true if the crypto handshake is still waiting for acks of sent
+ // data, and false if all data has been acked.
+ bool IsWaitingForAcks() const;
+
private:
+ // Data sent and received in CRYPTO frames is sent at multiple encryption
+ // levels. Some of the state for the single logical crypto stream is split
+ // across encryption levels, and a CryptoSubstream is used to manage that
+ // state for a particular encryption level.
+ struct CryptoSubstream {
+ CryptoSubstream(QuicCryptoStream* crypto_stream, EncryptionLevel);
+
+ QuicStreamSequencer sequencer;
+ QuicStreamSendBuffer send_buffer;
+ };
+
+ // Helper method for OnDataAvailable. Calls CryptoMessageParser::ProcessInput
+ // with the data available in |sequencer| and |level|, and marks the data
+ // passed to ProcessInput as consumed.
+ void OnDataAvailableInSequencer(QuicStreamSequencer* sequencer,
+ EncryptionLevel level);
+
// Consumed data according to encryption levels.
// TODO(fayang): This is not needed once switching from QUIC crypto to
// TLS 1.3, which never encrypts crypto data.
QuicIntervalSet<QuicStreamOffset> bytes_consumed_[NUM_ENCRYPTION_LEVELS];
+
+ // Keeps state for data sent/received in CRYPTO frames at each encryption
+ // level.
+ CryptoSubstream substreams_[NUM_ENCRYPTION_LEVELS];
};
} // namespace quic
diff --git a/quic/core/quic_crypto_stream_test.cc b/quic/core/quic_crypto_stream_test.cc
index 6ce0b41..eb1a672 100644
--- a/quic/core/quic_crypto_stream_test.cc
+++ b/quic/core/quic_crypto_stream_test.cc
@@ -11,6 +11,7 @@
#include "base/macros.h"
#include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake.h"
#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
+#include "net/third_party/quiche/src/quic/core/crypto/null_encrypter.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string.h"
@@ -104,10 +105,15 @@
}
TEST_F(QuicCryptoStreamTest, ProcessRawData) {
- stream_->OnStreamFrame(QuicStreamFrame(
- QuicUtils::GetCryptoStreamId(connection_->transport_version()),
- /*fin=*/false,
- /*offset=*/0, message_data_->AsStringPiece()));
+ if (connection_->transport_version() < QUIC_VERSION_47) {
+ stream_->OnStreamFrame(QuicStreamFrame(
+ QuicUtils::GetCryptoStreamId(connection_->transport_version()),
+ /*fin=*/false,
+ /*offset=*/0, message_data_->AsStringPiece()));
+ } else {
+ stream_->OnCryptoFrame(QuicCryptoFrame(ENCRYPTION_NONE, /*offset*/ 0,
+ message_data_->AsStringPiece()));
+ }
ASSERT_EQ(1u, stream_->messages()->size());
const CryptoHandshakeMessage& message = (*stream_->messages())[0];
EXPECT_EQ(kSHLO, message.tag());
@@ -126,9 +132,13 @@
EXPECT_CALL(*connection_, CloseConnection(QUIC_CRYPTO_TAGS_OUT_OF_ORDER,
testing::_, testing::_));
- stream_->OnStreamFrame(QuicStreamFrame(
- QuicUtils::GetCryptoStreamId(connection_->transport_version()),
- /*fin=*/false, /*offset=*/0, bad));
+ if (connection_->transport_version() < QUIC_VERSION_47) {
+ stream_->OnStreamFrame(QuicStreamFrame(
+ QuicUtils::GetCryptoStreamId(connection_->transport_version()),
+ /*fin=*/false, /*offset=*/0, bad));
+ } else {
+ stream_->OnCryptoFrame(QuicCryptoFrame(ENCRYPTION_NONE, /*offset*/ 0, bad));
+ }
}
TEST_F(QuicCryptoStreamTest, NoConnectionLevelFlowControl) {
@@ -137,6 +147,9 @@
}
TEST_F(QuicCryptoStreamTest, RetransmitCryptoData) {
+ if (connection_->transport_version() >= QUIC_VERSION_47) {
+ return;
+ }
InSequence s;
// Send [0, 1350) in ENCRYPTION_NONE.
EXPECT_EQ(ENCRYPTION_NONE, connection_->encryption_level());
@@ -148,9 +161,9 @@
1350, 0, _))
.WillOnce(Invoke(MockQuicSession::ConsumeData));
stream_->WriteOrBufferData(data, false, nullptr);
- // Send [1350, 2700) in ENCRYPTION_INITIAL.
- connection_->SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
- EXPECT_EQ(ENCRYPTION_INITIAL, connection_->encryption_level());
+ // Send [1350, 2700) in ENCRYPTION_ZERO_RTT.
+ connection_->SetDefaultEncryptionLevel(ENCRYPTION_ZERO_RTT);
+ EXPECT_EQ(ENCRYPTION_ZERO_RTT, connection_->encryption_level());
EXPECT_CALL(
session_,
WritevData(_,
@@ -192,7 +205,62 @@
EXPECT_EQ(ENCRYPTION_FORWARD_SECURE, connection_->encryption_level());
}
+TEST_F(QuicCryptoStreamTest, RetransmitCryptoDataInCryptoFrames) {
+ if (connection_->transport_version() < QUIC_VERSION_47) {
+ return;
+ }
+ EXPECT_CALL(*connection_, SendCryptoData(_, _, _)).Times(0);
+ InSequence s;
+ // Send [0, 1350) in ENCRYPTION_NONE.
+ EXPECT_EQ(ENCRYPTION_NONE, connection_->encryption_level());
+ QuicString data(1350, 'a');
+ EXPECT_CALL(*connection_, SendCryptoData(ENCRYPTION_NONE, 1350, 0))
+ .WillOnce(Invoke(connection_,
+ &MockQuicConnection::QuicConnection_SendCryptoData));
+ stream_->WriteCryptoData(ENCRYPTION_NONE, data);
+ // Send [1350, 2700) in ENCRYPTION_ZERO_RTT.
+ connection_->SetDefaultEncryptionLevel(ENCRYPTION_ZERO_RTT);
+ std::unique_ptr<NullEncrypter> encrypter =
+ QuicMakeUnique<NullEncrypter>(Perspective::IS_CLIENT);
+ connection_->SetEncrypter(ENCRYPTION_ZERO_RTT, std::move(encrypter));
+ EXPECT_EQ(ENCRYPTION_ZERO_RTT, connection_->encryption_level());
+ EXPECT_CALL(*connection_, SendCryptoData(ENCRYPTION_ZERO_RTT, 1350, 0))
+ .WillOnce(Invoke(connection_,
+ &MockQuicConnection::QuicConnection_SendCryptoData));
+ stream_->WriteCryptoData(ENCRYPTION_ZERO_RTT, data);
+ connection_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
+ EXPECT_EQ(ENCRYPTION_FORWARD_SECURE, connection_->encryption_level());
+
+ // Lost [0, 1000).
+ QuicCryptoFrame lost_frame(ENCRYPTION_NONE, 0, 1000);
+ stream_->OnCryptoFrameLost(&lost_frame);
+ EXPECT_TRUE(stream_->HasPendingCryptoRetransmission());
+ // Lost [1200, 2000).
+ lost_frame = QuicCryptoFrame(ENCRYPTION_NONE, 1200, 150);
+ stream_->OnCryptoFrameLost(&lost_frame);
+ lost_frame = QuicCryptoFrame(ENCRYPTION_ZERO_RTT, 0, 650);
+ stream_->OnCryptoFrameLost(&lost_frame);
+ EXPECT_CALL(*connection_, SendCryptoData(ENCRYPTION_NONE, 1000, 0))
+ .WillOnce(Invoke(connection_,
+ &MockQuicConnection::QuicConnection_SendCryptoData));
+ // Verify [1200, 2000) are sent in [1200, 1350) and [1350, 2000) because of
+ // they are in different encryption levels.
+ EXPECT_CALL(*connection_, SendCryptoData(ENCRYPTION_NONE, 150, 1200))
+ .WillOnce(Invoke(connection_,
+ &MockQuicConnection::QuicConnection_SendCryptoData));
+ EXPECT_CALL(*connection_, SendCryptoData(ENCRYPTION_ZERO_RTT, 650, 0))
+ .WillOnce(Invoke(connection_,
+ &MockQuicConnection::QuicConnection_SendCryptoData));
+ stream_->WritePendingCryptoRetransmission();
+ EXPECT_FALSE(stream_->HasPendingCryptoRetransmission());
+ // Verify connection's encryption level has restored.
+ EXPECT_EQ(ENCRYPTION_FORWARD_SECURE, connection_->encryption_level());
+}
+
TEST_F(QuicCryptoStreamTest, NeuterUnencryptedStreamData) {
+ if (connection_->transport_version() >= QUIC_VERSION_47) {
+ return;
+ }
// Send [0, 1350) in ENCRYPTION_NONE.
EXPECT_EQ(ENCRYPTION_NONE, connection_->encryption_level());
QuicString data(1350, 'a');
@@ -203,9 +271,9 @@
1350, 0, _))
.WillOnce(Invoke(MockQuicSession::ConsumeData));
stream_->WriteOrBufferData(data, false, nullptr);
- // Send [1350, 2700) in ENCRYPTION_INITIAL.
- connection_->SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
- EXPECT_EQ(ENCRYPTION_INITIAL, connection_->encryption_level());
+ // Send [1350, 2700) in ENCRYPTION_ZERO_RTT.
+ connection_->SetDefaultEncryptionLevel(ENCRYPTION_ZERO_RTT);
+ EXPECT_EQ(ENCRYPTION_ZERO_RTT, connection_->encryption_level());
EXPECT_CALL(
session_,
WritevData(_,
@@ -231,7 +299,53 @@
EXPECT_TRUE(stream_->HasPendingRetransmission());
}
+TEST_F(QuicCryptoStreamTest, NeuterUnencryptedCryptoData) {
+ if (connection_->transport_version() < QUIC_VERSION_47) {
+ return;
+ }
+ // Send [0, 1350) in ENCRYPTION_NONE.
+ EXPECT_EQ(ENCRYPTION_NONE, connection_->encryption_level());
+ QuicString data(1350, 'a');
+ EXPECT_CALL(*connection_, SendCryptoData(ENCRYPTION_NONE, 1350, 0))
+ .WillOnce(Invoke(connection_,
+ &MockQuicConnection::QuicConnection_SendCryptoData));
+ stream_->WriteCryptoData(ENCRYPTION_NONE, data);
+ // Send [1350, 2700) in ENCRYPTION_ZERO_RTT.
+ connection_->SetDefaultEncryptionLevel(ENCRYPTION_ZERO_RTT);
+ std::unique_ptr<NullEncrypter> encrypter =
+ QuicMakeUnique<NullEncrypter>(Perspective::IS_CLIENT);
+ connection_->SetEncrypter(ENCRYPTION_ZERO_RTT, std::move(encrypter));
+ EXPECT_EQ(ENCRYPTION_ZERO_RTT, connection_->encryption_level());
+ EXPECT_CALL(*connection_, SendCryptoData(_, _, _)).Times(0);
+ EXPECT_CALL(*connection_, SendCryptoData(ENCRYPTION_ZERO_RTT, 1350, 0))
+ .WillOnce(Invoke(connection_,
+ &MockQuicConnection::QuicConnection_SendCryptoData));
+ stream_->WriteCryptoData(ENCRYPTION_ZERO_RTT, data);
+
+ // Lost [0, 1350).
+ QuicCryptoFrame lost_frame(ENCRYPTION_NONE, 0, 1350);
+ stream_->OnCryptoFrameLost(&lost_frame);
+ EXPECT_TRUE(stream_->HasPendingCryptoRetransmission());
+ // Neuters [0, 1350).
+ stream_->NeuterUnencryptedStreamData();
+ EXPECT_FALSE(stream_->HasPendingCryptoRetransmission());
+ // Lost [0, 1350) again.
+ stream_->OnCryptoFrameLost(&lost_frame);
+ EXPECT_FALSE(stream_->HasPendingCryptoRetransmission());
+
+ // Lost [1350, 2000), which starts at offset 0 at the ENCRYPTION_ZERO_RTT
+ // level.
+ lost_frame = QuicCryptoFrame(ENCRYPTION_ZERO_RTT, 0, 650);
+ stream_->OnCryptoFrameLost(&lost_frame);
+ EXPECT_TRUE(stream_->HasPendingCryptoRetransmission());
+ stream_->NeuterUnencryptedStreamData();
+ EXPECT_TRUE(stream_->HasPendingCryptoRetransmission());
+}
+
TEST_F(QuicCryptoStreamTest, RetransmitStreamData) {
+ if (connection_->transport_version() >= QUIC_VERSION_47) {
+ return;
+ }
InSequence s;
// Send [0, 1350) in ENCRYPTION_NONE.
EXPECT_EQ(ENCRYPTION_NONE, connection_->encryption_level());
@@ -243,9 +357,9 @@
1350, 0, _))
.WillOnce(Invoke(MockQuicSession::ConsumeData));
stream_->WriteOrBufferData(data, false, nullptr);
- // Send [1350, 2700) in ENCRYPTION_INITIAL.
- connection_->SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
- EXPECT_EQ(ENCRYPTION_INITIAL, connection_->encryption_level());
+ // Send [1350, 2700) in ENCRYPTION_ZERO_RTT.
+ connection_->SetDefaultEncryptionLevel(ENCRYPTION_ZERO_RTT);
+ EXPECT_EQ(ENCRYPTION_ZERO_RTT, connection_->encryption_level());
EXPECT_CALL(
session_,
WritevData(_,
@@ -257,7 +371,10 @@
EXPECT_EQ(ENCRYPTION_FORWARD_SECURE, connection_->encryption_level());
// Ack [2000, 2500).
- stream_->OnStreamFrameAcked(2000, 500, false, QuicTime::Delta::Zero());
+ QuicByteCount newly_acked_length = 0;
+ stream_->OnStreamFrameAcked(2000, 500, false, QuicTime::Delta::Zero(),
+ &newly_acked_length);
+ EXPECT_EQ(500u, newly_acked_length);
// Force crypto stream to send [1350, 2700) and only [1350, 1500) is consumed.
EXPECT_CALL(
@@ -298,8 +415,69 @@
EXPECT_TRUE(stream_->RetransmitStreamData(0, 0, false));
}
+TEST_F(QuicCryptoStreamTest, RetransmitStreamDataWithCryptoFrames) {
+ if (connection_->transport_version() < QUIC_VERSION_47) {
+ return;
+ }
+ InSequence s;
+ // Send [0, 1350) in ENCRYPTION_NONE.
+ EXPECT_EQ(ENCRYPTION_NONE, connection_->encryption_level());
+ QuicString data(1350, 'a');
+ EXPECT_CALL(*connection_, SendCryptoData(ENCRYPTION_NONE, 1350, 0))
+ .WillOnce(Invoke(connection_,
+ &MockQuicConnection::QuicConnection_SendCryptoData));
+ stream_->WriteCryptoData(ENCRYPTION_NONE, data);
+ // Send [1350, 2700) in ENCRYPTION_ZERO_RTT.
+ connection_->SetDefaultEncryptionLevel(ENCRYPTION_ZERO_RTT);
+ std::unique_ptr<NullEncrypter> encrypter =
+ QuicMakeUnique<NullEncrypter>(Perspective::IS_CLIENT);
+ connection_->SetEncrypter(ENCRYPTION_ZERO_RTT, std::move(encrypter));
+ EXPECT_EQ(ENCRYPTION_ZERO_RTT, connection_->encryption_level());
+ EXPECT_CALL(*connection_, SendCryptoData(ENCRYPTION_ZERO_RTT, 1350, 0))
+ .WillOnce(Invoke(connection_,
+ &MockQuicConnection::QuicConnection_SendCryptoData));
+ stream_->WriteCryptoData(ENCRYPTION_ZERO_RTT, data);
+ connection_->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
+ EXPECT_EQ(ENCRYPTION_FORWARD_SECURE, connection_->encryption_level());
+
+ // Ack [2000, 2500).
+ QuicCryptoFrame acked_frame(ENCRYPTION_ZERO_RTT, 650, 500);
+ EXPECT_TRUE(
+ stream_->OnCryptoFrameAcked(acked_frame, QuicTime::Delta::Zero()));
+
+ // Retransmit only [1350, 1500).
+ EXPECT_CALL(*connection_, SendCryptoData(ENCRYPTION_ZERO_RTT, 150, 0))
+ .WillOnce(Invoke(connection_,
+ &MockQuicConnection::QuicConnection_SendCryptoData));
+ QuicCryptoFrame frame_to_retransmit(ENCRYPTION_ZERO_RTT, 0, 150);
+ stream_->RetransmitData(&frame_to_retransmit);
+
+ // Verify connection's encryption level has restored.
+ EXPECT_EQ(ENCRYPTION_FORWARD_SECURE, connection_->encryption_level());
+
+ // Retransmit [1350, 2700) again and all data is sent.
+ EXPECT_CALL(*connection_, SendCryptoData(ENCRYPTION_ZERO_RTT, 650, 0))
+ .WillOnce(Invoke(connection_,
+ &MockQuicConnection::QuicConnection_SendCryptoData));
+ EXPECT_CALL(*connection_, SendCryptoData(ENCRYPTION_ZERO_RTT, 200, 1150))
+ .WillOnce(Invoke(connection_,
+ &MockQuicConnection::QuicConnection_SendCryptoData));
+ frame_to_retransmit = QuicCryptoFrame(ENCRYPTION_ZERO_RTT, 0, 1350);
+ stream_->RetransmitData(&frame_to_retransmit);
+ // Verify connection's encryption level has restored.
+ EXPECT_EQ(ENCRYPTION_FORWARD_SECURE, connection_->encryption_level());
+
+ EXPECT_CALL(*connection_, SendCryptoData(_, _, _)).Times(0);
+ // Force to send an empty frame.
+ QuicCryptoFrame empty_frame(ENCRYPTION_FORWARD_SECURE, 0, 0);
+ stream_->RetransmitData(&empty_frame);
+}
+
// Regression test for b/115926584.
TEST_F(QuicCryptoStreamTest, HasUnackedCryptoData) {
+ if (connection_->transport_version() >= QUIC_VERSION_47) {
+ return;
+ }
QuicString data(1350, 'a');
EXPECT_CALL(
session_,
@@ -325,6 +503,21 @@
EXPECT_TRUE(session_.HasUnackedCryptoData());
}
+TEST_F(QuicCryptoStreamTest, HasUnackedCryptoDataWithCryptoFrames) {
+ if (connection_->transport_version() < QUIC_VERSION_47) {
+ return;
+ }
+ // Send [0, 1350) in ENCRYPTION_NONE.
+ EXPECT_EQ(ENCRYPTION_NONE, connection_->encryption_level());
+ QuicString data(1350, 'a');
+ EXPECT_CALL(*connection_, SendCryptoData(ENCRYPTION_NONE, 1350, 0))
+ .WillOnce(Invoke(connection_,
+ &MockQuicConnection::QuicConnection_SendCryptoData));
+ stream_->WriteCryptoData(ENCRYPTION_NONE, data);
+ EXPECT_TRUE(stream_->IsWaitingForAcks());
+ EXPECT_TRUE(session_.HasUnackedCryptoData());
+}
+
} // namespace
} // namespace test
} // namespace quic
diff --git a/quic/core/quic_data_reader.cc b/quic/core/quic_data_reader.cc
index 13a4c5a..191c755 100644
--- a/quic/core/quic_data_reader.cc
+++ b/quic/core/quic_data_reader.cc
@@ -12,6 +12,9 @@
namespace quic {
+QuicDataReader::QuicDataReader(const char* data, const size_t len)
+ : QuicDataReader(data, len, NETWORK_BYTE_ORDER) {}
+
QuicDataReader::QuicDataReader(const char* data,
const size_t len,
Endianness endianness)
@@ -129,17 +132,7 @@
}
bool QuicDataReader::ReadConnectionId(QuicConnectionId* connection_id,
- uint8_t length,
- Perspective perspective) {
- if (!QuicConnectionIdSupportsVariableLength(perspective)) {
- uint64_t connection_id64 = 0;
- if (!ReadBytes(&connection_id64, sizeof(connection_id64))) {
- return false;
- }
- *connection_id =
- QuicConnectionIdFromUInt64(QuicEndian::NetToHost64(connection_id64));
- return true;
- }
+ uint8_t length) {
DCHECK_LE(length, kQuicMaxConnectionIdLength);
const bool ok = ReadBytes(connection_id->mutable_data(), length);
@@ -159,7 +152,7 @@
return payload;
}
-QuicStringPiece QuicDataReader::PeekRemainingPayload() {
+QuicStringPiece QuicDataReader::PeekRemainingPayload() const {
return QuicStringPiece(data_ + pos_, len_ - pos_);
}
@@ -183,20 +176,29 @@
return len_ == pos_;
}
-int QuicDataReader::PeekVarInt62Length() {
+QuicVariableLengthIntegerLength QuicDataReader::PeekVarInt62Length() {
DCHECK_EQ(endianness_, NETWORK_BYTE_ORDER);
const unsigned char* next =
reinterpret_cast<const unsigned char*>(data_ + pos_);
if (BytesRemaining() == 0) {
- return 0;
+ return VARIABLE_LENGTH_INTEGER_LENGTH_0;
}
- return 1 << ((*next & 0b11000000) >> 6);
+ return static_cast<QuicVariableLengthIntegerLength>(
+ 1 << ((*next & 0b11000000) >> 6));
}
size_t QuicDataReader::BytesRemaining() const {
return len_ - pos_;
}
+bool QuicDataReader::TruncateRemaining(size_t truncation_length) {
+ if (truncation_length > BytesRemaining()) {
+ return false;
+ }
+ len_ = pos_ + truncation_length;
+ return true;
+}
+
bool QuicDataReader::CanRead(size_t bytes) const {
return bytes <= (len_ - pos_);
}
diff --git a/quic/core/quic_data_reader.h b/quic/core/quic_data_reader.h
index ca9f323..fff0ffd 100644
--- a/quic/core/quic_data_reader.h
+++ b/quic/core/quic_data_reader.h
@@ -32,6 +32,10 @@
// called after failure, as they will also fail immediately.
class QUIC_EXPORT_PRIVATE QuicDataReader {
public:
+ // Constructs a reader using NETWORK_BYTE_ORDER endianness.
+ // Caller must provide an underlying buffer to work on.
+ QuicDataReader(const char* data, const size_t len);
+ // Constructs a reader using the specified endianness.
// Caller must provide an underlying buffer to work on.
QuicDataReader(const char* data, const size_t len, Endianness endianness);
QuicDataReader(const QuicDataReader&) = delete;
@@ -75,11 +79,7 @@
// Reads connection ID into the given output parameter.
// Forwards the internal iterator on success.
// Returns true on success, false otherwise.
- // TODO(dschinazi) b/120240679 - remove perspective once these flags are
- // deprecated: quic_variable_length_connection_ids_(client|server).
- bool ReadConnectionId(QuicConnectionId* connection_id,
- uint8_t length,
- Perspective perspective);
+ bool ReadConnectionId(QuicConnectionId* connection_id, uint8_t length);
// Reads tag represented as 32-bit unsigned integer into given output
// parameter. Tags are in big endian on the wire (e.g., CHLO is
@@ -101,7 +101,7 @@
// This should be kept in mind when handling memory management!
//
// DOES NOT forward the internal iterator.
- QuicStringPiece PeekRemainingPayload();
+ QuicStringPiece PeekRemainingPayload() const;
// Reads a given number of bytes into the given buffer. The buffer
// must be of adequate size.
@@ -115,11 +115,17 @@
// Returns the length in bytes of a variable length integer based on the next
// two bits available. Returns 1, 2, 4, or 8 on success, and 0 on failure.
- int PeekVarInt62Length();
+ QuicVariableLengthIntegerLength PeekVarInt62Length();
// Returns the number of bytes remaining to be read.
size_t BytesRemaining() const;
+ // Truncates the reader down by reducing its internal length.
+ // If called immediately after calling this, BytesRemaining will
+ // return |truncation_length|. If truncation_length is less than the
+ // current value of BytesRemaining, this does nothing and returns false.
+ bool TruncateRemaining(size_t truncation_length);
+
// Returns the next byte that to be read. Must not be called when there are no
// bytes to be read.
//
@@ -158,7 +164,7 @@
const char* data_;
// The length of the data buffer that we're reading from.
- const size_t len_;
+ size_t len_;
// The location of the next read from our data buffer.
size_t pos_;
diff --git a/quic/core/quic_data_writer.cc b/quic/core/quic_data_writer.cc
index 865b262..c7bedb5 100644
--- a/quic/core/quic_data_writer.cc
+++ b/quic/core/quic_data_writer.cc
@@ -15,6 +15,9 @@
namespace quic {
+QuicDataWriter::QuicDataWriter(size_t size, char* buffer)
+ : QuicDataWriter(size, buffer, NETWORK_BYTE_ORDER) {}
+
QuicDataWriter::QuicDataWriter(size_t size, char* buffer, Endianness endianness)
: buffer_(buffer), capacity_(size), length_(0), endianness_(endianness) {}
@@ -171,14 +174,7 @@
return WriteRepeatedByte(0x00, count);
}
-bool QuicDataWriter::WriteConnectionId(QuicConnectionId connection_id,
- Perspective perspective) {
- if (!QuicConnectionIdSupportsVariableLength(perspective)) {
- uint64_t connection_id64 =
- QuicEndian::HostToNet64(QuicConnectionIdToUInt64(connection_id));
-
- return WriteBytes(&connection_id64, sizeof(connection_id64));
- }
+bool QuicDataWriter::WriteConnectionId(QuicConnectionId connection_id) {
return WriteBytes(connection_id.data(), connection_id.length());
}
@@ -283,23 +279,58 @@
return false;
}
+bool QuicDataWriter::WriteVarInt62(
+ uint64_t value,
+ QuicVariableLengthIntegerLength write_length) {
+ DCHECK_EQ(endianness_, NETWORK_BYTE_ORDER);
+
+ size_t remaining = capacity_ - length_;
+ if (remaining < write_length) {
+ return false;
+ }
+
+ const QuicVariableLengthIntegerLength min_length = GetVarInt62Len(value);
+ if (write_length < min_length) {
+ QUIC_BUG << "Cannot write value " << value << " with write_length "
+ << write_length;
+ return false;
+ }
+ if (write_length == min_length) {
+ return WriteVarInt62(value);
+ }
+
+ if (write_length == VARIABLE_LENGTH_INTEGER_LENGTH_2) {
+ return WriteUInt8(0b01000000) && WriteUInt8(value);
+ }
+ if (write_length == VARIABLE_LENGTH_INTEGER_LENGTH_4) {
+ return WriteUInt8(0b10000000) && WriteUInt8(0) && WriteUInt16(value);
+ }
+ if (write_length == VARIABLE_LENGTH_INTEGER_LENGTH_8) {
+ return WriteUInt8(0b11000000) && WriteUInt8(0) && WriteUInt16(0) &&
+ WriteUInt32(value);
+ }
+
+ QUIC_BUG << "Invalid write_length " << static_cast<int>(write_length);
+ return false;
+}
+
// static
-int QuicDataWriter::GetVarInt62Len(uint64_t value) {
+QuicVariableLengthIntegerLength QuicDataWriter::GetVarInt62Len(uint64_t value) {
if ((value & kVarInt62ErrorMask) != 0) {
QUIC_BUG << "Attempted to encode a value, " << value
<< ", that is too big for VarInt62";
- return 0;
+ return VARIABLE_LENGTH_INTEGER_LENGTH_0;
}
if ((value & kVarInt62Mask8Bytes) != 0) {
- return 8;
+ return VARIABLE_LENGTH_INTEGER_LENGTH_8;
}
if ((value & kVarInt62Mask4Bytes) != 0) {
- return 4;
+ return VARIABLE_LENGTH_INTEGER_LENGTH_4;
}
if ((value & kVarInt62Mask2Bytes) != 0) {
- return 2;
+ return VARIABLE_LENGTH_INTEGER_LENGTH_2;
}
- return 1;
+ return VARIABLE_LENGTH_INTEGER_LENGTH_1;
}
bool QuicDataWriter::WriteStringPieceVarInt62(
diff --git a/quic/core/quic_data_writer.h b/quic/core/quic_data_writer.h
index 9423553..e107fcb 100644
--- a/quic/core/quic_data_writer.h
+++ b/quic/core/quic_data_writer.h
@@ -38,7 +38,11 @@
// of the QuicDataWriter.
class QUIC_EXPORT_PRIVATE QuicDataWriter {
public:
- // Creates a QuicDataWriter where |buffer| is not owned.
+ // Creates a QuicDataWriter where |buffer| is not owned
+ // using NETWORK_BYTE_ORDER endianness.
+ QuicDataWriter(size_t size, char* buffer);
+ // Creates a QuicDataWriter where |buffer| is not owned
+ // using the specified endianness.
QuicDataWriter(size_t size, char* buffer, Endianness endianness);
QuicDataWriter(const QuicDataWriter&) = delete;
QuicDataWriter& operator=(const QuicDataWriter&) = delete;
@@ -68,6 +72,13 @@
// buffer.
bool WriteVarInt62(uint64_t value);
+ // Same as WriteVarInt62(uint64_t), but forces an encoding size to write to.
+ // This is not as optimized as WriteVarInt62(uint64_t).
+ // Returns false if the value does not fit in the specified write_length or if
+ // there is no room in the buffer.
+ bool WriteVarInt62(uint64_t value,
+ QuicVariableLengthIntegerLength write_length);
+
// Writes a string piece as a consecutive length/content pair. The
// length is VarInt62 encoded.
bool WriteStringPieceVarInt62(const QuicStringPiece& string_piece);
@@ -76,7 +87,7 @@
// the given value using IETF VarInt62 encoding. Returns the number
// of bytes required to encode the given integer or 0 if the value
// is too large to encode.
- static int GetVarInt62Len(uint64_t value);
+ static QuicVariableLengthIntegerLength GetVarInt62Len(uint64_t value);
// Writes least significant |num_bytes| of a 64-bit unsigned integer in the
// correct byte order.
@@ -96,10 +107,7 @@
bool WritePaddingBytes(size_t count);
// Write connection ID to the payload.
- // TODO(dschinazi) b/120240679 - remove perspective once these flags are
- // deprecated: quic_variable_length_connection_ids_(client|server).
- bool WriteConnectionId(QuicConnectionId connection_id,
- Perspective perspective);
+ bool WriteConnectionId(QuicConnectionId connection_id);
// Write tag as a 32-bit unsigned integer to the payload. As tags are already
// converted to big endian (e.g., CHLO is 'C','H','L','O') in memory by TAG or
diff --git a/quic/core/quic_data_writer_test.cc b/quic/core/quic_data_writer_test.cc
index 9fe05e6..978143e 100644
--- a/quic/core/quic_data_writer_test.cc
+++ b/quic/core/quic_data_writer_test.cc
@@ -37,9 +37,8 @@
class QuicDataWriterTest : public QuicTestWithParam<TestParams> {};
-INSTANTIATE_TEST_CASE_P(QuicDataWriterTests,
- QuicDataWriterTest,
- ::testing::ValuesIn(GetTestParams()));
+INSTANTIATE_TEST_SUITE_P(QuicDataWriterTests, QuicDataWriterTest,
+ ::testing::ValuesIn(GetTestParams()));
TEST_P(QuicDataWriterTest, SanityCheckUFloat16Consts) {
// Check the arithmetic on the constants - otherwise the values below make
@@ -256,99 +255,16 @@
ASSERT_LE(connection_id.length(), kQuicMaxConnectionIdLength);
char buffer[kQuicMaxConnectionIdLength];
QuicDataWriter writer(connection_id.length(), buffer, GetParam().endianness);
- EXPECT_TRUE(writer.WriteConnectionId(connection_id, Perspective::IS_CLIENT));
+ EXPECT_TRUE(writer.WriteConnectionId(connection_id));
test::CompareCharArraysWithHexError("connection_id", buffer,
connection_id.length(), big_endian,
connection_id.length());
QuicConnectionId read_connection_id;
QuicDataReader reader(buffer, connection_id.length(), GetParam().endianness);
- EXPECT_TRUE(reader.ReadConnectionId(
- &read_connection_id, QUIC_ARRAYSIZE(big_endian), Perspective::IS_CLIENT));
+ EXPECT_TRUE(
+ reader.ReadConnectionId(&read_connection_id, QUIC_ARRAYSIZE(big_endian)));
EXPECT_EQ(connection_id, read_connection_id);
-
- // TODO(dschinazi) b/120240679 - remove this second read once these flags are
- // deprecated: quic_variable_length_connection_ids_(client|server).
- QuicConnectionId read_connection_id2;
- QuicDataReader reader2(buffer, connection_id.length(), GetParam().endianness);
- EXPECT_TRUE(reader2.ReadConnectionId(&read_connection_id2,
- QUIC_ARRAYSIZE(big_endian),
- Perspective::IS_SERVER));
- EXPECT_EQ(connection_id, read_connection_id2);
-}
-
-// TODO(dschinazi) b/120240679 - remove this test once these flags are
-// deprecated: quic_variable_length_connection_ids_(client|server).
-TEST_P(QuicDataWriterTest, WriteConnectionIdServerAllowingVariableLength) {
- if (!GetQuicRestartFlag(quic_connection_ids_network_byte_order)) {
- // This test is pointless if the flag is off.
- return;
- }
- SetQuicRestartFlag(quic_variable_length_connection_ids_client, false);
- SetQuicRestartFlag(quic_variable_length_connection_ids_server, true);
- QuicConnectionId connection_id =
- TestConnectionId(UINT64_C(0x0011223344556677));
- char big_endian[] = {
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
- };
- EXPECT_EQ(connection_id.length(), QUIC_ARRAYSIZE(big_endian));
- ASSERT_LE(connection_id.length(), kQuicMaxConnectionIdLength);
- char buffer[kQuicMaxConnectionIdLength];
- QuicDataWriter writer(connection_id.length(), buffer, GetParam().endianness);
- EXPECT_TRUE(writer.WriteConnectionId(connection_id, Perspective::IS_SERVER));
- test::CompareCharArraysWithHexError("connection_id", buffer,
- connection_id.length(), big_endian,
- connection_id.length());
-
- QuicConnectionId read_connection_id;
- QuicDataReader reader(buffer, connection_id.length(), GetParam().endianness);
- EXPECT_TRUE(reader.ReadConnectionId(
- &read_connection_id, QUIC_ARRAYSIZE(big_endian), Perspective::IS_CLIENT));
- EXPECT_EQ(connection_id, read_connection_id);
-
- QuicConnectionId read_connection_id2;
- QuicDataReader reader2(buffer, connection_id.length(), GetParam().endianness);
- EXPECT_TRUE(reader2.ReadConnectionId(&read_connection_id2,
- QUIC_ARRAYSIZE(big_endian),
- Perspective::IS_SERVER));
- EXPECT_EQ(connection_id, read_connection_id2);
-}
-
-// TODO(dschinazi) b/120240679 - remove this test once these flags are
-// deprecated: quic_variable_length_connection_ids_(client|server).
-TEST_P(QuicDataWriterTest, WriteConnectionIdClientAllowingVariableLength) {
- if (!GetQuicRestartFlag(quic_connection_ids_network_byte_order)) {
- // This test is pointless if the flag is off.
- return;
- }
- SetQuicRestartFlag(quic_variable_length_connection_ids_client, true);
- SetQuicRestartFlag(quic_variable_length_connection_ids_server, false);
- QuicConnectionId connection_id =
- TestConnectionId(UINT64_C(0x0011223344556677));
- char big_endian[] = {
- 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
- };
- EXPECT_EQ(connection_id.length(), QUIC_ARRAYSIZE(big_endian));
- ASSERT_LE(connection_id.length(), kQuicMaxConnectionIdLength);
- char buffer[kQuicMaxConnectionIdLength];
- QuicDataWriter writer(connection_id.length(), buffer, GetParam().endianness);
- EXPECT_TRUE(writer.WriteConnectionId(connection_id, Perspective::IS_SERVER));
- test::CompareCharArraysWithHexError("connection_id", buffer,
- connection_id.length(), big_endian,
- connection_id.length());
-
- QuicConnectionId read_connection_id;
- QuicDataReader reader(buffer, connection_id.length(), GetParam().endianness);
- EXPECT_TRUE(reader.ReadConnectionId(
- &read_connection_id, QUIC_ARRAYSIZE(big_endian), Perspective::IS_CLIENT));
- EXPECT_EQ(connection_id, read_connection_id);
-
- QuicConnectionId read_connection_id2;
- QuicDataReader reader2(buffer, connection_id.length(), GetParam().endianness);
- EXPECT_TRUE(reader2.ReadConnectionId(&read_connection_id2,
- QUIC_ARRAYSIZE(big_endian),
- Perspective::IS_SERVER));
- EXPECT_EQ(connection_id, read_connection_id2);
}
TEST_P(QuicDataWriterTest, WriteTag) {
@@ -991,6 +907,76 @@
EXPECT_FALSE(reader.ReadVarInt62(&test_val));
}
+// Test writing varints with a forced length.
+TEST_P(QuicDataWriterTest, VarIntFixedLength) {
+ char buffer[90];
+ memset(buffer, 0, sizeof(buffer));
+ QuicDataWriter writer(sizeof(buffer), static_cast<char*>(buffer),
+ Endianness::NETWORK_BYTE_ORDER);
+
+ writer.WriteVarInt62(1, VARIABLE_LENGTH_INTEGER_LENGTH_1);
+ writer.WriteVarInt62(1, VARIABLE_LENGTH_INTEGER_LENGTH_2);
+ writer.WriteVarInt62(1, VARIABLE_LENGTH_INTEGER_LENGTH_4);
+ writer.WriteVarInt62(1, VARIABLE_LENGTH_INTEGER_LENGTH_8);
+
+ writer.WriteVarInt62(63, VARIABLE_LENGTH_INTEGER_LENGTH_1);
+ writer.WriteVarInt62(63, VARIABLE_LENGTH_INTEGER_LENGTH_2);
+ writer.WriteVarInt62(63, VARIABLE_LENGTH_INTEGER_LENGTH_4);
+ writer.WriteVarInt62(63, VARIABLE_LENGTH_INTEGER_LENGTH_8);
+
+ writer.WriteVarInt62(64, VARIABLE_LENGTH_INTEGER_LENGTH_2);
+ writer.WriteVarInt62(64, VARIABLE_LENGTH_INTEGER_LENGTH_4);
+ writer.WriteVarInt62(64, VARIABLE_LENGTH_INTEGER_LENGTH_8);
+
+ writer.WriteVarInt62(16383, VARIABLE_LENGTH_INTEGER_LENGTH_2);
+ writer.WriteVarInt62(16383, VARIABLE_LENGTH_INTEGER_LENGTH_4);
+ writer.WriteVarInt62(16383, VARIABLE_LENGTH_INTEGER_LENGTH_8);
+
+ writer.WriteVarInt62(16384, VARIABLE_LENGTH_INTEGER_LENGTH_4);
+ writer.WriteVarInt62(16384, VARIABLE_LENGTH_INTEGER_LENGTH_8);
+
+ writer.WriteVarInt62(1073741823, VARIABLE_LENGTH_INTEGER_LENGTH_4);
+ writer.WriteVarInt62(1073741823, VARIABLE_LENGTH_INTEGER_LENGTH_8);
+
+ writer.WriteVarInt62(1073741824, VARIABLE_LENGTH_INTEGER_LENGTH_8);
+
+ QuicDataReader reader(buffer, sizeof(buffer), Endianness::NETWORK_BYTE_ORDER);
+
+ uint64_t test_val = 0;
+ for (int i = 0; i < 4; ++i) {
+ EXPECT_TRUE(reader.ReadVarInt62(&test_val));
+ EXPECT_EQ(test_val, 1);
+ }
+ for (int i = 0; i < 4; ++i) {
+ EXPECT_TRUE(reader.ReadVarInt62(&test_val));
+ EXPECT_EQ(test_val, 63);
+ }
+
+ for (int i = 0; i < 3; ++i) {
+ EXPECT_TRUE(reader.ReadVarInt62(&test_val));
+ EXPECT_EQ(test_val, 64);
+ }
+ for (int i = 0; i < 3; ++i) {
+ EXPECT_TRUE(reader.ReadVarInt62(&test_val));
+ EXPECT_EQ(test_val, 16383);
+ }
+
+ for (int i = 0; i < 2; ++i) {
+ EXPECT_TRUE(reader.ReadVarInt62(&test_val));
+ EXPECT_EQ(test_val, 16384);
+ }
+ for (int i = 0; i < 2; ++i) {
+ EXPECT_TRUE(reader.ReadVarInt62(&test_val));
+ EXPECT_EQ(test_val, 1073741823);
+ }
+
+ EXPECT_TRUE(reader.ReadVarInt62(&test_val));
+ EXPECT_EQ(test_val, 1073741824);
+
+ // We are at the end of the buffer so this should fail.
+ EXPECT_FALSE(reader.ReadVarInt62(&test_val));
+}
+
// Test encoding/decoding stream-id values.
void EncodeDecodeStreamId(uint64_t value_in, bool expected_decode_result) {
char buffer[1 * kMultiVarCount];
diff --git a/quic/core/quic_default_packet_writer.cc b/quic/core/quic_default_packet_writer.cc
index 2c162e0..3b16a74 100644
--- a/quic/core/quic_default_packet_writer.cc
+++ b/quic/core/quic_default_packet_writer.cc
@@ -30,10 +30,6 @@
return result;
}
-bool QuicDefaultPacketWriter::IsWriteBlockedDataBuffered() const {
- return false;
-}
-
bool QuicDefaultPacketWriter::IsWriteBlocked() const {
return write_blocked_;
}
diff --git a/quic/core/quic_default_packet_writer.h b/quic/core/quic_default_packet_writer.h
index 93917da..b5473eb 100644
--- a/quic/core/quic_default_packet_writer.h
+++ b/quic/core/quic_default_packet_writer.h
@@ -30,7 +30,6 @@
const QuicIpAddress& self_address,
const QuicSocketAddress& peer_address,
PerPacketOptions* options) override;
- bool IsWriteBlockedDataBuffered() const override;
bool IsWriteBlocked() const override;
void SetWritable() override;
QuicByteCount GetMaxPacketSize(
diff --git a/quic/core/quic_dispatcher.cc b/quic/core/quic_dispatcher.cc
index 0cb03aa..f17bdf2 100644
--- a/quic/core/quic_dispatcher.cc
+++ b/quic/core/quic_dispatcher.cc
@@ -96,8 +96,7 @@
QuicStreamOffset offset,
QuicByteCount data_length,
QuicDataWriter* writer) override {
- QUIC_BUG << "PacketCollector::WriteCryptoData is unimplemented.";
- return false;
+ return send_buffer_.WriteStreamData(offset, data_length, writer);
}
std::vector<std::unique_ptr<QuicEncryptedPacket>>* packets() {
@@ -143,7 +142,12 @@
frame->error_details = error_details;
// TODO(fayang): Use the right long header type for conneciton close sent by
// dispatcher.
- creator_.SetLongHeaderType(RETRY);
+ if (QuicVersionHasLongHeaderLengths(framer_->transport_version())) {
+ creator_.SetLongHeaderType(HANDSHAKE);
+ } else {
+ // TODO(b/123493765): we should probably not be sending RETRY here.
+ creator_.SetLongHeaderType(RETRY);
+ }
if (!creator_.AddSavedFrame(QuicFrame(frame), NOT_RETRANSMISSION)) {
QUIC_BUG << "Unable to add frame to an empty packet";
delete frame;
@@ -165,16 +169,31 @@
collector_.SaveStatelessRejectFrameData(reject);
while (offset < reject.length()) {
QuicFrame frame;
- creator_.SetLongHeaderType(RETRY);
- if (!creator_.ConsumeData(
- QuicUtils::GetCryptoStreamId(framer_->transport_version()),
- reject.length(), offset, offset,
- /*fin=*/false,
- /*needs_full_padding=*/true, NOT_RETRANSMISSION, &frame)) {
- QUIC_BUG << "Unable to consume data into an empty packet.";
- return;
+ if (QuicVersionHasLongHeaderLengths(framer_->transport_version())) {
+ creator_.SetLongHeaderType(HANDSHAKE);
+ } else {
+ // TODO(b/123493765): we should probably not be sending RETRY here.
+ creator_.SetLongHeaderType(RETRY);
}
- offset += frame.stream_frame.data_length;
+ if (framer_->transport_version() < QUIC_VERSION_47) {
+ if (!creator_.ConsumeData(
+ QuicUtils::GetCryptoStreamId(framer_->transport_version()),
+ reject.length(), offset, offset,
+ /*fin=*/false,
+ /*needs_full_padding=*/true, NOT_RETRANSMISSION, &frame)) {
+ QUIC_BUG << "Unable to consume data into an empty packet.";
+ return;
+ }
+ offset += frame.stream_frame.data_length;
+ } else {
+ if (!creator_.ConsumeCryptoData(ENCRYPTION_NONE,
+ reject.length() - offset, offset,
+ NOT_RETRANSMISSION, &frame)) {
+ QUIC_BUG << "Unable to consume crypto data into an empty packet.";
+ return;
+ }
+ offset += frame.crypto_frame->data_length;
+ }
if (offset < reject.length()) {
DCHECK(!creator_.HasRoomForStreamFrame(
QuicUtils::GetCryptoStreamId(framer_->transport_version()), offset,
@@ -267,7 +286,7 @@
} // namespace
QuicDispatcher::QuicDispatcher(
- const QuicConfig& config,
+ const QuicConfig* config,
const QuicCryptoServerConfig* crypto_config,
QuicVersionManager* version_manager,
std::unique_ptr<QuicConnectionHelperInterface> helper,
@@ -404,16 +423,13 @@
if (ShouldCreateSessionForUnknownVersion(framer_.last_version_label())) {
return true;
}
- if (!GetQuicReloadableFlag(quic_limit_version_negotiation) ||
- current_packet_->length() >= kMinPacketSizeForVersionNegotiation) {
+ if (current_packet_->length() >= kMinPacketSizeForVersionNegotiation) {
// Since the version is not supported, send a version negotiation
// packet and stop processing the current packet.
time_wait_list_manager()->SendVersionNegotiationPacket(
connection_id, header.form != GOOGLE_QUIC_PACKET,
GetSupportedVersions(), current_self_address_,
current_peer_address_, GetPerPacketContext());
- } else {
- QUIC_RELOADABLE_FLAG_COUNT(quic_limit_version_negotiation);
}
return false;
}
@@ -845,6 +861,10 @@
return false;
}
+void QuicDispatcher::OnCoalescedPacket(const QuicEncryptedPacket& /*packet*/) {
+ DCHECK(false);
+}
+
bool QuicDispatcher::OnStreamFrame(const QuicStreamFrame& /*frame*/) {
DCHECK(false);
return false;
@@ -1202,7 +1222,7 @@
ChloAlpnExtractor alpn_extractor;
if (FLAGS_quic_allow_chlo_buffering &&
!ChloExtractor::Extract(*current_packet_, GetSupportedVersions(),
- config_.create_session_tag_indicators(),
+ config_->create_session_tag_indicators(),
&alpn_extractor)) {
// Buffer non-CHLO packets.
ProcessUnauthenticatedHeaderFate(kFateBuffer, connection_id, form,
@@ -1224,7 +1244,7 @@
current_peer_address_, current_self_address_,
rejector.get());
if (!ChloExtractor::Extract(*current_packet_, GetSupportedVersions(),
- config_.create_session_tag_indicators(),
+ config_->create_session_tag_indicators(),
&validator)) {
ProcessUnauthenticatedHeaderFate(kFateBuffer, connection_id, form, version);
return;
@@ -1281,12 +1301,6 @@
current_packet_ = current_packet.get();
current_connection_id_ = rejector->connection_id();
framer_.set_version(first_version);
- if (GetQuicReloadableFlag(quic_fix_last_packet_is_ietf_quic)) {
- if (GetLastPacketFormat() != current_packet_format) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_fix_last_packet_is_ietf_quic);
- }
- framer_.set_last_packet_form(current_packet_format);
- }
// Stop buffering packets on this connection
const auto num_erased =
@@ -1385,8 +1399,4 @@
framer_.set_validate_flags(false);
}
-PacketHeaderFormat QuicDispatcher::GetLastPacketFormat() const {
- return framer_.GetLastPacketFormat();
-}
-
} // namespace quic
diff --git a/quic/core/quic_dispatcher.h b/quic/core/quic_dispatcher.h
index d6eb35b..b0c2509 100644
--- a/quic/core/quic_dispatcher.h
+++ b/quic/core/quic_dispatcher.h
@@ -44,7 +44,7 @@
// Ideally we'd have a linked_hash_set: the boolean is unused.
typedef QuicLinkedHashMap<QuicBlockedWriterInterface*, bool> WriteBlockedList;
- QuicDispatcher(const QuicConfig& config,
+ QuicDispatcher(const QuicConfig* config,
const QuicCryptoServerConfig* crypto_config,
QuicVersionManager* version_manager,
std::unique_ptr<QuicConnectionHelperInterface> helper,
@@ -143,6 +143,7 @@
const QuicVersionNegotiationPacket& packet) override;
void OnDecryptedPacket(EncryptionLevel level) override;
bool OnPacketHeader(const QuicPacketHeader& header) override;
+ void OnCoalescedPacket(const QuicEncryptedPacket& packet) override;
bool OnStreamFrame(const QuicStreamFrame& frame) override;
bool OnCryptoFrame(const QuicCryptoFrame& frame) override;
bool OnAckFrameStart(QuicPacketNumber largest_acked,
@@ -271,7 +272,7 @@
}
const QuicReceivedPacket& current_packet() const { return *current_packet_; }
- const QuicConfig& config() const { return config_; }
+ const QuicConfig& config() const { return *config_; }
const QuicCryptoServerConfig* crypto_config() const { return crypto_config_; }
@@ -351,11 +352,6 @@
// Skip validating that the public flags are set to legal values.
void DisableFlagValidation();
- // Please do not use this method.
- // TODO(fayang): Remove this method when deprecating
- // quic_fix_last_packet_is_ietf_quic flag.
- PacketHeaderFormat GetLastPacketFormat() const;
-
private:
friend class test::QuicDispatcherPeer;
friend class StatelessRejectorProcessDoneCallback;
@@ -410,7 +406,7 @@
new_sessions_allowed_per_event_loop_ = new_sessions_allowed_per_event_loop;
}
- const QuicConfig& config_;
+ const QuicConfig* config_;
const QuicCryptoServerConfig* crypto_config_;
diff --git a/quic/core/quic_dispatcher_test.cc b/quic/core/quic_dispatcher_test.cc
index 0381cf5..7fc1263 100644
--- a/quic/core/quic_dispatcher_test.cc
+++ b/quic/core/quic_dispatcher_test.cc
@@ -72,7 +72,7 @@
TestQuicSpdyServerSession& operator=(const TestQuicSpdyServerSession&) =
delete;
- ~TestQuicSpdyServerSession() override { delete connection(); };
+ ~TestQuicSpdyServerSession() override { delete connection(); }
MOCK_METHOD3(OnConnectionClosed,
void(QuicErrorCode error,
@@ -114,7 +114,7 @@
class TestDispatcher : public QuicDispatcher {
public:
- TestDispatcher(const QuicConfig& config,
+ TestDispatcher(const QuicConfig* config,
const QuicCryptoServerConfig* crypto_config,
QuicVersionManager* version_manager)
: QuicDispatcher(config,
@@ -157,7 +157,6 @@
using QuicDispatcher::current_client_address;
using QuicDispatcher::current_peer_address;
using QuicDispatcher::current_self_address;
- using QuicDispatcher::GetLastPacketFormat;
using QuicDispatcher::writer;
};
@@ -207,7 +206,8 @@
std::move(proof_source),
KeyExchangeSource::Default(),
TlsServerHandshaker::CreateSslCtx()),
- dispatcher_(new NiceMock<TestDispatcher>(config_,
+ server_address_(QuicIpAddress::Any4(), 5),
+ dispatcher_(new NiceMock<TestDispatcher>(&config_,
&crypto_config_,
&version_manager_)),
time_wait_list_manager_(nullptr),
@@ -370,9 +370,12 @@
};
TEST_F(QuicDispatcherTest, TlsClientHelloCreatesSession) {
+ if (CurrentSupportedVersions().front().transport_version < QUIC_VERSION_47) {
+ // TLS is only supported in versions 47 and greater.
+ return;
+ }
FLAGS_quic_supports_tls_handshake = true;
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
- server_address_ = QuicSocketAddress(QuicIpAddress::Any4(), 5);
EXPECT_CALL(*dispatcher_,
CreateQuicSession(TestConnectionId(1), client_address,
@@ -400,7 +403,6 @@
TEST_F(QuicDispatcherTest, ProcessPackets) {
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
- server_address_ = QuicSocketAddress(QuicIpAddress::Any4(), 5);
EXPECT_CALL(*dispatcher_,
CreateQuicSession(TestConnectionId(1), client_address,
@@ -448,7 +450,6 @@
// Regression test of b/93325907.
TEST_F(QuicDispatcherTest, DispatcherDoesNotRejectPacketNumberZero) {
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
- server_address_ = QuicSocketAddress(QuicIpAddress::Any4(), 5);
EXPECT_CALL(*dispatcher_,
CreateQuicSession(TestConnectionId(1), client_address,
@@ -486,9 +487,7 @@
TEST_F(QuicDispatcherTest, StatelessVersionNegotiation) {
CreateTimeWaitListManager();
- SetQuicReloadableFlag(quic_limit_version_negotiation, false);
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
- server_address_ = QuicSocketAddress(QuicIpAddress::Any4(), 5);
EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
EXPECT_CALL(*time_wait_list_manager_,
@@ -497,16 +496,17 @@
QuicTransportVersion version =
static_cast<QuicTransportVersion>(QuicTransportVersionMin() - 1);
ParsedQuicVersion parsed_version(PROTOCOL_QUIC_CRYPTO, version);
- ProcessPacket(client_address, TestConnectionId(1), true, parsed_version,
- SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID,
- PACKET_4BYTE_PACKET_NUMBER, 1);
+ // Pad the CHLO message with enough data to make the packet large enough
+ // to trigger version negotiation.
+ QuicString chlo = SerializeCHLO() + QuicString(1200, 'a');
+ DCHECK_LE(1200u, chlo.length());
+ ProcessPacket(client_address, TestConnectionId(1), true, parsed_version, chlo,
+ PACKET_8BYTE_CONNECTION_ID, PACKET_4BYTE_PACKET_NUMBER, 1);
}
TEST_F(QuicDispatcherTest, NoVersionNegotiationWithSmallPacket) {
CreateTimeWaitListManager();
- SetQuicReloadableFlag(quic_limit_version_negotiation, true);
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
- server_address_ = QuicSocketAddress(QuicIpAddress::Any4(), 5);
EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _)).Times(0);
EXPECT_CALL(*time_wait_list_manager_,
@@ -515,10 +515,12 @@
QuicTransportVersion version =
static_cast<QuicTransportVersion>(QuicTransportVersionMin() - 1);
ParsedQuicVersion parsed_version(PROTOCOL_QUIC_CRYPTO, version);
- QuicString chlo = SerializeCHLO();
+ QuicString chlo = SerializeCHLO() + QuicString(1200, 'a');
// Truncate to 1100 bytes of payload which results in a packet just
// under 1200 bytes after framing, packet, and encryption overhead.
+ DCHECK_LE(1200u, chlo.length());
QuicString truncated_chlo = chlo.substr(0, 1100);
+ DCHECK_EQ(1100u, truncated_chlo.length());
ProcessPacket(client_address, TestConnectionId(1), true, parsed_version,
truncated_chlo, PACKET_8BYTE_CONNECTION_ID,
PACKET_4BYTE_PACKET_NUMBER, 1);
@@ -607,7 +609,6 @@
CreateTimeWaitListManager();
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 0);
- server_address_ = QuicSocketAddress(QuicIpAddress::Any4(), 5);
// dispatcher_ should drop this packet.
EXPECT_CALL(*dispatcher_,
@@ -623,7 +624,6 @@
TEST_F(QuicDispatcherTest, OKSeqNoPacketProcessed) {
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
QuicConnectionId connection_id = TestConnectionId(1);
- server_address_ = QuicSocketAddress(QuicIpAddress::Any4(), 5);
EXPECT_CALL(*dispatcher_,
CreateQuicSession(TestConnectionId(1), client_address,
@@ -681,17 +681,15 @@
}
TEST_F(QuicDispatcherTest, SupportedTransportVersionsChangeInFlight) {
- static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 8u,
+ static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 6u,
"Supported versions out of sync");
- SetQuicReloadableFlag(quic_disable_version_35, false);
+ SetQuicReloadableFlag(quic_disable_version_39, false);
SetQuicReloadableFlag(quic_enable_version_43, true);
SetQuicReloadableFlag(quic_enable_version_44, true);
- SetQuicReloadableFlag(quic_enable_version_45, true);
SetQuicReloadableFlag(quic_enable_version_46, true);
SetQuicReloadableFlag(quic_enable_version_47, true);
SetQuicReloadableFlag(quic_enable_version_99, true);
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
- server_address_ = QuicSocketAddress(QuicIpAddress::Any4(), 5);
uint64_t conn_id = 1;
QuicConnectionId connection_id = TestConnectionId(conn_id);
@@ -808,39 +806,6 @@
SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID,
PACKET_4BYTE_PACKET_NUMBER, 1);
- // Turn off version 45.
- SetQuicReloadableFlag(quic_enable_version_45, false);
- connection_id = TestConnectionId(++conn_id);
- EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address,
- QuicStringPiece("hq"), _))
- .Times(0);
- ProcessPacket(client_address, connection_id, true,
- ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_45),
- SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID,
- PACKET_4BYTE_PACKET_NUMBER, 1);
-
- // Turn on version 45.
- SetQuicReloadableFlag(quic_enable_version_45, true);
- connection_id = TestConnectionId(++conn_id);
- EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address,
- QuicStringPiece("hq"), _))
- .WillOnce(testing::Return(CreateSession(
- dispatcher_.get(), config_, connection_id, client_address,
- &mock_helper_, &mock_alarm_factory_, &crypto_config_,
- QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
- EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
- ProcessUdpPacket(_, _, _))
- .WillOnce(WithArg<2>(
- Invoke([this, connection_id](const QuicEncryptedPacket& packet) {
- ValidatePacket(connection_id, packet);
- })));
- EXPECT_CALL(*dispatcher_,
- ShouldCreateOrBufferPacketForConnection(connection_id, _));
- ProcessPacket(client_address, connection_id, true,
- ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_45),
- SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID,
- PACKET_4BYTE_PACKET_NUMBER, 1);
-
// Turn off version 44.
SetQuicReloadableFlag(quic_enable_version_44, false);
connection_id = TestConnectionId(++conn_id);
@@ -907,19 +872,19 @@
SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID,
PACKET_4BYTE_PACKET_NUMBER, 1);
- // Turn off version 35.
- SetQuicReloadableFlag(quic_disable_version_35, true);
+ // Turn off version 39.
+ SetQuicReloadableFlag(quic_disable_version_39, true);
connection_id = TestConnectionId(++conn_id);
EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address,
QuicStringPiece("hq"), _))
.Times(0);
ProcessPacket(client_address, connection_id, true,
- ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_35),
+ ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_39),
SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID,
PACKET_4BYTE_PACKET_NUMBER, 1);
- // Turn on version 35.
- SetQuicReloadableFlag(quic_disable_version_35, false);
+ // Turn on version 39.
+ SetQuicReloadableFlag(quic_disable_version_39, false);
connection_id = TestConnectionId(++conn_id);
EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address,
QuicStringPiece("hq"), _))
@@ -936,7 +901,7 @@
EXPECT_CALL(*dispatcher_,
ShouldCreateOrBufferPacketForConnection(connection_id, _));
ProcessPacket(client_address, connection_id, true,
- ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_35),
+ ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_39),
SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID,
PACKET_4BYTE_PACKET_NUMBER, 1);
}
@@ -1067,9 +1032,9 @@
// Parameterized test for stateless rejects. Should test all
// combinations of enabling/disabling, reject/no-reject for stateless
// rejects.
-INSTANTIATE_TEST_CASE_P(QuicDispatcherStatelessRejectTests,
- QuicDispatcherStatelessRejectTest,
- ::testing::ValuesIn(GetStatelessRejectTestParams()));
+INSTANTIATE_TEST_SUITE_P(QuicDispatcherStatelessRejectTests,
+ QuicDispatcherStatelessRejectTest,
+ ::testing::ValuesIn(GetStatelessRejectTestParams()));
TEST_P(QuicDispatcherStatelessRejectTest, ParameterizedBasicTest) {
CreateTimeWaitListManager();
@@ -1624,6 +1589,7 @@
public:
BufferedPacketStoreTest()
: QuicDispatcherTest(),
+ server_addr_(QuicSocketAddress(QuicIpAddress::Any4(), 5)),
client_addr_(QuicIpAddress::Loopback4(), 1234),
signed_config_(new QuicSignedServerConfig) {
SetQuicReloadableFlag(quic_use_cheap_stateless_rejects,
@@ -1660,7 +1626,7 @@
CryptoHandshakeMessage full_chlo_;
};
-INSTANTIATE_TEST_CASE_P(
+INSTANTIATE_TEST_SUITE_P(
BufferedPacketStoreTests,
BufferedPacketStoreTest,
::testing::ValuesIn(GetBufferedPacketStoreTestParams()));
@@ -1668,7 +1634,6 @@
TEST_P(BufferedPacketStoreTest, ProcessNonChloPacketsUptoLimitAndProcessChlo) {
InSequence s;
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
- server_address_ = QuicSocketAddress(QuicIpAddress::Any4(), 5);
QuicConnectionId conn_id = TestConnectionId(1);
// A bunch of non-CHLO should be buffered upon arrival, and the first one
// should trigger ShouldCreateOrBufferPacketForConnection().
@@ -1708,7 +1673,6 @@
TEST_P(BufferedPacketStoreTest,
ProcessNonChloPacketsForDifferentConnectionsUptoLimit) {
InSequence s;
- server_address_ = QuicSocketAddress(QuicIpAddress::Any4(), 5);
// A bunch of non-CHLO should be buffered upon arrival.
size_t kNumConnections = kMaxConnectionsWithoutCHLO + 1;
for (size_t i = 1; i <= kNumConnections; ++i) {
@@ -1781,7 +1745,6 @@
TEST_P(BufferedPacketStoreTest, ReceiveRetransmittedCHLO) {
InSequence s;
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
- server_address_ = QuicSocketAddress(QuicIpAddress::Any4(), 5);
QuicConnectionId conn_id = TestConnectionId(1);
ProcessPacket(client_address, conn_id, true, QuicStrCat("data packet ", 2),
PACKET_8BYTE_CONNECTION_ID, PACKET_4BYTE_PACKET_NUMBER,
@@ -1817,7 +1780,6 @@
QuicBufferedPacketStorePeer::set_clock(store, mock_helper_.GetClock());
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
- server_address_ = QuicSocketAddress(QuicIpAddress::Any4(), 5);
QuicConnectionId conn_id = TestConnectionId(1);
ProcessPacket(client_address, conn_id, true, QuicStrCat("data packet ", 2),
PACKET_8BYTE_CONNECTION_ID, PACKET_4BYTE_PACKET_NUMBER,
@@ -2125,6 +2087,7 @@
client_addr_(QuicIpAddress::Loopback4(), 1234),
client_addr_2_(QuicIpAddress::Loopback4(), 1357),
crypto_config_peer_(&crypto_config_),
+ server_addr_(QuicIpAddress::Any4(), 5),
signed_config_(new QuicSignedServerConfig) {
SetQuicReloadableFlag(enable_quic_stateless_reject_support, true);
SetQuicReloadableFlag(quic_use_cheap_stateless_rejects, true);
@@ -2722,16 +2685,17 @@
// different endianness which causes the client to close the connection
// because of QUIC_INVALID_STREAM_DATA.
- SetQuicReloadableFlag(quic_disable_version_35, false);
- ParsedQuicVersion chlo_version(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_39);
+ SetQuicReloadableFlag(quic_disable_version_39, false);
+ SetQuicReloadableFlag(quic_enable_version_43, true);
+ ParsedQuicVersion chlo_version(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_43);
chlo_.SetVersion(kVER, chlo_version);
- // Send a CHLO with v39. Dispatcher framer's version is set to v39.
+ // Send a CHLO with v43. Dispatcher framer's version is set to v43.
ProcessPacket(client_addr_, TestConnectionId(1), true, chlo_version,
SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID,
PACKET_4BYTE_PACKET_NUMBER, 1);
- // Send another CHLO with v35. Dispatcher framer's version is set to v35.
- chlo_version.transport_version = QUIC_VERSION_35;
+ // Send another CHLO with v39. Dispatcher framer's version is set to v39.
+ chlo_version.transport_version = QUIC_VERSION_39;
chlo_.SetVersion(kVER, chlo_version);
// Invalidate the cached serialized form.
chlo_.MarkDirty();
@@ -2740,7 +2704,7 @@
PACKET_4BYTE_PACKET_NUMBER, 1);
ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 2);
- // Complete the ProofSource::GetProof call for v39. This would cause the
+ // Complete the ProofSource::GetProof call for v43. This would cause the
// version mismatch between the CHLO packet and the dispatcher.
GetFakeProofSource()->InvokePendingCallback(0);
ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1);
@@ -2748,15 +2712,12 @@
// Regression test for b/116200989.
TEST_F(AsyncGetProofTest, DispatcherHasWrongLastPacketIsIetfQuic) {
- SetQuicReloadableFlag(quic_fix_last_packet_is_ietf_quic, true);
-
// Process a packet of v44.
ParsedQuicVersion chlo_version(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_44);
chlo_.SetVersion(kVER, chlo_version);
ProcessPacket(client_addr_, TestConnectionId(1), true, chlo_version,
SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID,
PACKET_4BYTE_PACKET_NUMBER, 1);
- EXPECT_NE(GOOGLE_QUIC_PACKET, dispatcher_->GetLastPacketFormat());
// Process another packet of v43.
chlo_version.transport_version = QUIC_VERSION_43;
@@ -2766,18 +2727,14 @@
ProcessPacket(client_addr_, TestConnectionId(2), true, chlo_version,
SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID,
PACKET_4BYTE_PACKET_NUMBER, 1);
- EXPECT_EQ(GOOGLE_QUIC_PACKET, dispatcher_->GetLastPacketFormat());
ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 2);
// Complete the ProofSource::GetProof call for v44.
GetFakeProofSource()->InvokePendingCallback(0);
- // Verify the last_packet_is_ietf_quic gets reset properly.
- EXPECT_NE(GOOGLE_QUIC_PACKET, dispatcher_->GetLastPacketFormat());
ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 1);
// Complete the ProofSource::GetProof call for v43.
GetFakeProofSource()->InvokePendingCallback(0);
- EXPECT_EQ(GOOGLE_QUIC_PACKET, dispatcher_->GetLastPacketFormat());
ASSERT_EQ(GetFakeProofSource()->NumPendingCallbacks(), 0);
}
diff --git a/quic/core/quic_epoll_alarm_factory.cc b/quic/core/quic_epoll_alarm_factory.cc
index 2ec2f6f..2d6efdf 100644
--- a/quic/core/quic_epoll_alarm_factory.cc
+++ b/quic/core/quic_epoll_alarm_factory.cc
@@ -69,7 +69,7 @@
QuicEpollAlarmFactory::QuicEpollAlarmFactory(QuicEpollServer* epoll_server)
: epoll_server_(epoll_server) {}
-QuicEpollAlarmFactory::~QuicEpollAlarmFactory() {}
+QuicEpollAlarmFactory::~QuicEpollAlarmFactory() = default;
QuicAlarm* QuicEpollAlarmFactory::CreateAlarm(QuicAlarm::Delegate* delegate) {
return new QuicEpollAlarm(epoll_server_,
diff --git a/quic/core/quic_epoll_alarm_factory_test.cc b/quic/core/quic_epoll_alarm_factory_test.cc
index b8d4caf..08a7cfe 100644
--- a/quic/core/quic_epoll_alarm_factory_test.cc
+++ b/quic/core/quic_epoll_alarm_factory_test.cc
@@ -40,9 +40,8 @@
QuicConnectionArena arena_;
};
-INSTANTIATE_TEST_CASE_P(UseArena,
- QuicEpollAlarmFactoryTest,
- ::testing::ValuesIn({true, false}));
+INSTANTIATE_TEST_SUITE_P(UseArena, QuicEpollAlarmFactoryTest,
+ ::testing::ValuesIn({true, false}));
TEST_P(QuicEpollAlarmFactoryTest, CreateAlarm) {
QuicArenaScopedPtr<TestDelegate> delegate =
diff --git a/quic/core/quic_epoll_connection_helper.cc b/quic/core/quic_epoll_connection_helper.cc
index 49002f6..e05139f 100644
--- a/quic/core/quic_epoll_connection_helper.cc
+++ b/quic/core/quic_epoll_connection_helper.cc
@@ -22,7 +22,7 @@
random_generator_(QuicRandom::GetInstance()),
allocator_type_(type) {}
-QuicEpollConnectionHelper::~QuicEpollConnectionHelper() {}
+QuicEpollConnectionHelper::~QuicEpollConnectionHelper() = default;
const QuicClock* QuicEpollConnectionHelper::GetClock() const {
return &clock_;
diff --git a/quic/core/quic_epoll_connection_helper.h b/quic/core/quic_epoll_connection_helper.h
index 62e030c..8b2a469 100644
--- a/quic/core/quic_epoll_connection_helper.h
+++ b/quic/core/quic_epoll_connection_helper.h
@@ -56,8 +56,6 @@
QuicBufferAllocator* GetStreamSendBufferAllocator() override;
private:
- friend class QuicEpollConnectionHelperPeer;
-
const QuicEpollClock clock_;
QuicRandom* random_generator_;
// Set up allocators. They take up minimal memory before use.
diff --git a/quic/core/quic_error_codes.cc b/quic/core/quic_error_codes.cc
index a6259e9..215f527 100644
--- a/quic/core/quic_error_codes.cc
+++ b/quic/core/quic_error_codes.cc
@@ -155,6 +155,7 @@
RETURN_STRING_LITERAL(QUIC_STREAM_ID_BLOCKED_ERROR);
RETURN_STRING_LITERAL(QUIC_MAX_STREAM_ID_ERROR);
RETURN_STRING_LITERAL(QUIC_HTTP_DECODER_ERROR);
+ RETURN_STRING_LITERAL(QUIC_STALE_CONNECTION_CANCELLED);
RETURN_STRING_LITERAL(QUIC_LAST_ERROR);
// Intentionally have no default case, so we'll break the build
diff --git a/quic/core/quic_error_codes.h b/quic/core/quic_error_codes.h
index ebf15f5..d3446a8 100644
--- a/quic/core/quic_error_codes.h
+++ b/quic/core/quic_error_codes.h
@@ -325,9 +325,11 @@
QUIC_MAX_STREAM_ID_ERROR = 119,
// Error in Http decoder
QUIC_HTTP_DECODER_ERROR = 120,
+ // Connection from stale host needs to be cancelled.
+ QUIC_STALE_CONNECTION_CANCELLED = 121,
// No error. Used as bound while iterating.
- QUIC_LAST_ERROR = 121,
+ QUIC_LAST_ERROR = 122,
};
// QuicErrorCodes is encoded as a single octet on-the-wire.
static_assert(static_cast<int>(QUIC_LAST_ERROR) <=
diff --git a/quic/core/quic_framer.cc b/quic/core/quic_framer.cc
index 1b93074..854b8c7 100644
--- a/quic/core/quic_framer.cc
+++ b/quic/core/quic_framer.cc
@@ -4,6 +4,7 @@
#include "net/third_party/quiche/src/quic/core/quic_framer.h"
+#include <cstddef>
#include <cstdint>
#include <memory>
@@ -23,12 +24,14 @@
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_aligned.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_endian.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_fallthrough.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_map_util.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_stack_trace.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
@@ -186,7 +189,7 @@
uint8_t PacketNumberLengthToOnWireValue(
QuicTransportVersion version,
QuicPacketNumberLength packet_number_length) {
- if (version > QUIC_VERSION_46) {
+ if (version > QUIC_VERSION_44) {
return packet_number_length - 1;
}
switch (packet_number_length) {
@@ -209,7 +212,7 @@
QuicPacketNumberLength* packet_number_length) {
DCHECK(!(type & FLAGS_LONG_HEADER));
const bool two_bits_packet_number_length =
- infer_packet_header_type_from_version ? version > QUIC_VERSION_46
+ infer_packet_header_type_from_version ? version > QUIC_VERSION_44
: (type & FLAGS_FIXED_BIT);
if (two_bits_packet_number_length) {
*packet_number_length =
@@ -237,13 +240,13 @@
QuicLongHeaderType type) {
switch (type) {
case INITIAL:
- return version > QUIC_VERSION_46 ? 0 : 0x7F;
+ return version > QUIC_VERSION_44 ? 0 : 0x7F;
case ZERO_RTT_PROTECTED:
- return version > QUIC_VERSION_46 ? 1 << 4 : 0x7C;
+ return version > QUIC_VERSION_44 ? 1 << 4 : 0x7C;
case HANDSHAKE:
- return version > QUIC_VERSION_46 ? 2 << 4 : 0x7D;
+ return version > QUIC_VERSION_44 ? 2 << 4 : 0x7D;
case RETRY:
- return version > QUIC_VERSION_46 ? 3 << 4 : 0x7E;
+ return version > QUIC_VERSION_44 ? 3 << 4 : 0x7E;
case VERSION_NEGOTIATION:
return 0xF0; // Value does not matter
default:
@@ -256,7 +259,7 @@
uint8_t type,
QuicLongHeaderType* long_header_type) {
DCHECK((type & FLAGS_LONG_HEADER) && version != QUIC_VERSION_UNSUPPORTED);
- if (version > QUIC_VERSION_46) {
+ if (version > QUIC_VERSION_44) {
switch ((type & 0x30) >> 4) {
case 0:
*long_header_type = INITIAL;
@@ -303,7 +306,7 @@
QuicPacketNumberLength GetLongHeaderPacketNumberLength(
QuicTransportVersion version,
uint8_t type) {
- if (version > QUIC_VERSION_46) {
+ if (version > QUIC_VERSION_44) {
return static_cast<QuicPacketNumberLength>((type & 0x03) + 1);
}
return PACKET_4BYTE_PACKET_NUMBER;
@@ -343,6 +346,63 @@
version == QUIC_VERSION_99);
}
+// Convert a stream ID to a count of streams, for IETF QUIC/Version 99 only.
+// There is no need to take into account whether the ID is for uni- or
+// bi-directional streams, or whether it's server- or client- initiated. It
+// always returns a valid count.
+QuicStreamId StreamIdToCount(QuicTransportVersion version,
+ QuicStreamId stream_id) {
+ DCHECK_EQ(QUIC_VERSION_99, version);
+ if ((stream_id & 0x3) == 0) {
+ return (stream_id / QuicUtils::StreamIdDelta(version));
+ }
+ return (stream_id / QuicUtils::StreamIdDelta(version)) + 1;
+}
+
+// Returns the maximum value that a stream count may have, taking into account
+// the fact that bidirectional, client initiated, streams have one fewer stream
+// available than the others. This is because the old crypto streams, with ID ==
+// 0 are not included in the count.
+// The version is not included in the call, nor does the method take the version
+// into account, because this is called only from code used for IETF QUIC.
+// TODO(fkastenholz): Remove this method and replace calls to it with direct
+// references to kMaxQuicStreamIdCount when streamid 0 becomes a normal stream
+// id.
+QuicStreamId GetMaxStreamCount(bool unidirectional, Perspective perspective) {
+ if (!unidirectional && perspective == Perspective::IS_CLIENT) {
+ return kMaxQuicStreamId >> 2;
+ }
+ return (kMaxQuicStreamId >> 2) + 1;
+}
+
+// Convert a stream count to the maximum stream ID for that count.
+// Needs to know whether the resulting stream ID should be uni-directional,
+// bi-directional, server-initiated, or client-initiated.
+// Returns true if it works, false if not. The only error condition is that
+// the stream_count is too big and it would generate a stream id that is larger
+// than the implementation's maximum stream id value.
+bool StreamCountToId(QuicStreamId stream_count,
+ bool unidirectional,
+ Perspective perspective,
+ QuicTransportVersion version,
+ QuicStreamId* generated_stream_id) {
+ DCHECK_EQ(QUIC_VERSION_99, version);
+ // TODO(fkastenholz): when the MAX_STREAMS and STREAMS_BLOCKED frames
+ // are connected all the way up to the stream_id_manager, handle count==0
+ // properly (interpret it as "can open 0 streams") and the count being too
+ // large (close the connection).
+ if ((stream_count == 0) ||
+ (stream_count > GetMaxStreamCount(unidirectional, perspective))) {
+ return false;
+ }
+ *generated_stream_id =
+ ((unidirectional)
+ ? QuicUtils::GetFirstUnidirectionalStreamId(version, perspective)
+ : QuicUtils::GetFirstBidirectionalStreamId(version, perspective)) +
+ ((stream_count - 1) * QuicUtils::StreamIdDelta(version));
+ return true;
+}
+
} // namespace
QuicFramer::QuicFramer(const ParsedQuicVersionVector& supported_versions,
@@ -352,7 +412,6 @@
error_(QUIC_NO_ERROR),
last_serialized_connection_id_(EmptyQuicConnectionId()),
last_version_label_(0),
- last_header_form_(GOOGLE_QUIC_PACKET),
version_(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED),
supported_versions_(supported_versions),
decrypter_level_(ENCRYPTION_NONE),
@@ -485,7 +544,7 @@
if (version != QUIC_VERSION_99) {
return kQuicFrameTypeSize + kQuicMaxStreamIdSize + kQuicMaxStreamOffsetSize;
}
- if (frame.stream_id == 0) {
+ if (frame.stream_id == QuicUtils::GetInvalidStreamId(version)) {
// Frame would be a MAX DATA frame, which has only a Maximum Data field.
return kQuicFrameTypeSize +
QuicDataWriter::GetVarInt62Len(frame.byte_offset);
@@ -498,24 +557,32 @@
}
// static
-size_t QuicFramer::GetMaxStreamIdFrameSize(QuicTransportVersion version,
- const QuicMaxStreamIdFrame& frame) {
+size_t QuicFramer::GetMaxStreamsFrameSize(QuicTransportVersion version,
+ const QuicMaxStreamIdFrame& frame) {
if (version != QUIC_VERSION_99) {
QUIC_BUG << "In version " << version
<< " - not 99 - and tried to serialize MaxStreamId Frame.";
}
- return kQuicFrameTypeSize +
- QuicDataWriter::GetVarInt62Len(frame.max_stream_id);
+
+ // Convert from the stream id on which the connection is blocked to a count
+ QuicStreamId stream_count = StreamIdToCount(version, frame.max_stream_id);
+
+ return kQuicFrameTypeSize + QuicDataWriter::GetVarInt62Len(stream_count);
}
+
// static
-size_t QuicFramer::GetStreamIdBlockedFrameSize(
+size_t QuicFramer::GetStreamsBlockedFrameSize(
QuicTransportVersion version,
const QuicStreamIdBlockedFrame& frame) {
if (version != QUIC_VERSION_99) {
QUIC_BUG << "In version " << version
<< " - not 99 - and tried to serialize StreamIdBlocked Frame.";
}
- return kQuicFrameTypeSize + QuicDataWriter::GetVarInt62Len(frame.stream_id);
+
+ // Convert from the stream id on which the connection is blocked to a count
+ QuicStreamId stream_count = StreamIdToCount(version, frame.stream_id);
+
+ return kQuicFrameTypeSize + QuicDataWriter::GetVarInt62Len(stream_count);
}
// static
@@ -524,10 +591,7 @@
if (version != QUIC_VERSION_99) {
return kQuicFrameTypeSize + kQuicMaxStreamIdSize;
}
- // TODO(fkastenholz): This should be converted to use
- // QuicUtils::GetInvalidStreamId to get the correct invalid stream id value
- // and not rely on 0.
- if (frame.stream_id == 0) {
+ if (frame.stream_id == QuicUtils::GetInvalidStreamId(version)) {
// return size of IETF QUIC Blocked frame
return kQuicFrameTypeSize + QuicDataWriter::GetVarInt62Len(frame.offset);
}
@@ -591,10 +655,9 @@
case NEW_TOKEN_FRAME:
return GetNewTokenFrameSize(*frame.new_token_frame);
case MAX_STREAM_ID_FRAME:
- return GetMaxStreamIdFrameSize(version, frame.max_stream_id_frame);
+ return GetMaxStreamsFrameSize(version, frame.max_stream_id_frame);
case STREAM_ID_BLOCKED_FRAME:
- return GetStreamIdBlockedFrameSize(version,
- frame.stream_id_blocked_frame);
+ return GetStreamsBlockedFrameSize(version, frame.stream_id_blocked_frame);
case PATH_RESPONSE_FRAME:
return GetPathResponseFrameSize(*frame.path_response_frame);
case PATH_CHALLENGE_FRAME:
@@ -761,19 +824,63 @@
QuicFramer::AckFrameInfo::~AckFrameInfo() {}
+bool QuicFramer::WriteIetfLongHeaderLength(const QuicPacketHeader& header,
+ QuicDataWriter* writer,
+ size_t length_field_offset,
+ EncryptionLevel level) {
+ if (!QuicVersionHasLongHeaderLengths(transport_version()) ||
+ !header.version_flag || length_field_offset == 0) {
+ return true;
+ }
+ if (writer->length() < length_field_offset ||
+ writer->length() - length_field_offset <
+ kQuicDefaultLongHeaderLengthLength) {
+ set_detailed_error("Invalid length_field_offset.");
+ QUIC_BUG << "Invalid length_field_offset.";
+ return false;
+ }
+ size_t length_to_write = writer->length() - length_field_offset -
+ kQuicDefaultLongHeaderLengthLength;
+ // Add length of auth tag.
+ length_to_write = GetCiphertextSize(level, length_to_write);
+
+ QuicDataWriter length_writer(writer->length() - length_field_offset,
+ writer->data() + length_field_offset);
+ if (!length_writer.WriteVarInt62(length_to_write,
+ kQuicDefaultLongHeaderLengthLength)) {
+ set_detailed_error("Failed to overwrite long header length.");
+ QUIC_BUG << "Failed to overwrite long header length.";
+ return false;
+ }
+ return true;
+}
+
size_t QuicFramer::BuildDataPacket(const QuicPacketHeader& header,
const QuicFrames& frames,
char* buffer,
- size_t packet_length) {
- if (version_.transport_version == QUIC_VERSION_99) {
- return BuildIetfDataPacket(header, frames, buffer, packet_length);
- }
- QuicDataWriter writer(packet_length, buffer, endianness());
- if (!AppendPacketHeader(header, &writer)) {
+ size_t packet_length,
+ EncryptionLevel level) {
+ QuicDataWriter writer(packet_length, buffer);
+ size_t length_field_offset = 0;
+ if (!AppendPacketHeader(header, &writer, &length_field_offset)) {
QUIC_BUG << "AppendPacketHeader failed";
return 0;
}
+ if (transport_version() == QUIC_VERSION_99) {
+ if (AppendIetfFrames(frames, &writer) == 0) {
+ return 0;
+ }
+ if (!WriteIetfLongHeaderLength(header, &writer, length_field_offset,
+ level)) {
+ return 0;
+ }
+ return writer.length();
+ }
+ // TODO(dschinazi) if we enable long header lengths before v99, we need to
+ // add support for fixing up lengths in QuicFramer::BuildDataPacket.
+ DCHECK(!QuicVersionHasLongHeaderLengths(transport_version()));
+
size_t i = 0;
for (const QuicFrame& frame : frames) {
// Determine if we should write stream frame length in header.
@@ -893,173 +1000,11 @@
}
break;
case CRYPTO_FRAME:
- set_detailed_error(
- "Attempt to append CRYPTO frame and not in version 99.");
- return RaiseError(QUIC_INTERNAL_ERROR);
- default:
- RaiseError(QUIC_INVALID_FRAME_DATA);
- QUIC_BUG << "QUIC_INVALID_FRAME_DATA";
- return 0;
- }
- ++i;
- }
-
- return writer.length();
-}
-
-size_t QuicFramer::BuildIetfDataPacket(const QuicPacketHeader& header,
- const QuicFrames& frames,
- char* buffer,
- size_t packet_length) {
- QuicDataWriter writer(packet_length, buffer, endianness());
- if (!AppendIetfPacketHeader(header, &writer)) {
- QUIC_BUG << "AppendPacketHeader failed";
- return 0;
- }
-
- size_t i = 0;
- for (const QuicFrame& frame : frames) {
- // Determine if we should write stream frame length in header.
- const bool last_frame_in_packet = i == frames.size() - 1;
- if (!AppendIetfTypeByte(frame, last_frame_in_packet, &writer)) {
- QUIC_BUG << "AppendIetfTypeByte failed";
- return 0;
- }
-
- switch (frame.type) {
- case PADDING_FRAME:
- if (!AppendPaddingFrame(frame.padding_frame, &writer)) {
- QUIC_BUG << "AppendPaddingFrame of "
- << frame.padding_frame.num_padding_bytes << " failed";
- return 0;
+ if (version_.transport_version < QUIC_VERSION_47) {
+ set_detailed_error(
+ "Attempt to append CRYPTO frame in version prior to 47.");
+ return RaiseError(QUIC_INTERNAL_ERROR);
}
- break;
- case STREAM_FRAME:
- if (!AppendStreamFrame(frame.stream_frame, last_frame_in_packet,
- &writer)) {
- QUIC_BUG << "AppendStreamFrame failed";
- return 0;
- }
- break;
- case ACK_FRAME:
- if (!AppendIetfAckFrameAndTypeByte(*frame.ack_frame, &writer)) {
- QUIC_BUG << "AppendAckFrameAndTypeByte failed";
- return 0;
- }
- break;
- case STOP_WAITING_FRAME:
- set_detailed_error(
- "Attempt to append STOP WAITING frame in version 99.");
- return RaiseError(QUIC_INTERNAL_ERROR);
- case MTU_DISCOVERY_FRAME:
- // MTU discovery frames are serialized as ping frames.
- QUIC_FALLTHROUGH_INTENDED;
- case PING_FRAME:
- // Ping has no payload.
- break;
- case RST_STREAM_FRAME:
- if (!AppendRstStreamFrame(*frame.rst_stream_frame, &writer)) {
- QUIC_BUG << "AppendRstStreamFrame failed";
- return 0;
- }
- break;
- case CONNECTION_CLOSE_FRAME:
- if (!AppendConnectionCloseFrame(*frame.connection_close_frame,
- &writer)) {
- QUIC_BUG << "AppendConnectionCloseFrame failed";
- return 0;
- }
- break;
- case GOAWAY_FRAME:
- set_detailed_error("Attempt to append GOAWAY frame in version 99.");
- return RaiseError(QUIC_INTERNAL_ERROR);
- case WINDOW_UPDATE_FRAME:
- // Depending on whether there is a stream ID or not, will be either a
- // MAX STREAM DATA frame or a MAX DATA frame.
- if (frame.window_update_frame->stream_id == 0) {
- if (!AppendMaxDataFrame(*frame.window_update_frame, &writer)) {
- QUIC_BUG << "AppendMaxDataFrame failed";
- return 0;
- }
- } else {
- if (!AppendMaxStreamDataFrame(*frame.window_update_frame, &writer)) {
- QUIC_BUG << "AppendMaxStreamDataFrame failed";
- return 0;
- }
- }
- break;
- case BLOCKED_FRAME:
- if (!AppendBlockedFrame(*frame.blocked_frame, &writer)) {
- QUIC_BUG << "AppendBlockedFrame failed";
- return 0;
- }
- break;
- case APPLICATION_CLOSE_FRAME:
- if (!AppendApplicationCloseFrame(*frame.application_close_frame,
- &writer)) {
- QUIC_BUG << "AppendApplicationCloseFrame failed";
- return 0;
- }
- break;
- case MAX_STREAM_ID_FRAME:
- if (!AppendMaxStreamIdFrame(frame.max_stream_id_frame, &writer)) {
- QUIC_BUG << "AppendMaxStreamIdFrame failed";
- return 0;
- }
- break;
- case STREAM_ID_BLOCKED_FRAME:
- if (!AppendStreamIdBlockedFrame(frame.stream_id_blocked_frame,
- &writer)) {
- QUIC_BUG << "AppendMaxStreamIdFrame failed";
- return 0;
- }
- break;
- case NEW_CONNECTION_ID_FRAME:
- if (!AppendNewConnectionIdFrame(*frame.new_connection_id_frame,
- &writer)) {
- QUIC_BUG << "AppendNewConnectionIdFrame failed";
- return 0;
- }
- break;
- case RETIRE_CONNECTION_ID_FRAME:
- if (!AppendRetireConnectionIdFrame(*frame.retire_connection_id_frame,
- &writer)) {
- QUIC_BUG << "AppendRetireConnectionIdFrame failed";
- return 0;
- }
- break;
- case NEW_TOKEN_FRAME:
- if (!AppendNewTokenFrame(*frame.new_token_frame, &writer)) {
- QUIC_BUG << "AppendNewTokenFrame failed";
- return 0;
- }
- break;
- case STOP_SENDING_FRAME:
- if (!AppendStopSendingFrame(*frame.stop_sending_frame, &writer)) {
- QUIC_BUG << "AppendStopSendingFrame failed";
- return 0;
- }
- break;
- case PATH_CHALLENGE_FRAME:
- if (!AppendPathChallengeFrame(*frame.path_challenge_frame, &writer)) {
- QUIC_BUG << "AppendPathChallengeFrame failed";
- return 0;
- }
- break;
- case PATH_RESPONSE_FRAME:
- if (!AppendPathResponseFrame(*frame.path_response_frame, &writer)) {
- QUIC_BUG << "AppendPathResponseFrame failed";
- return 0;
- }
- break;
- case MESSAGE_FRAME:
- if (!AppendMessageFrameAndTypeByte(*frame.message_frame,
- last_frame_in_packet, &writer)) {
- QUIC_BUG << "AppendMessageFrame failed";
- return 0;
- }
- break;
- case CRYPTO_FRAME:
if (!AppendCryptoFrame(*frame.crypto_frame, &writer)) {
QUIC_BUG << "AppendCryptoFrame failed";
return 0;
@@ -1076,10 +1021,176 @@
return writer.length();
}
-size_t QuicFramer::BuildIetfConnectivityProbingPacket(
+size_t QuicFramer::AppendIetfFrames(const QuicFrames& frames,
+ QuicDataWriter* writer) {
+ size_t i = 0;
+ for (const QuicFrame& frame : frames) {
+ // Determine if we should write stream frame length in header.
+ const bool last_frame_in_packet = i == frames.size() - 1;
+ if (!AppendIetfTypeByte(frame, last_frame_in_packet, writer)) {
+ QUIC_BUG << "AppendIetfTypeByte failed: " << detailed_error();
+ return 0;
+ }
+
+ switch (frame.type) {
+ case PADDING_FRAME:
+ if (!AppendPaddingFrame(frame.padding_frame, writer)) {
+ QUIC_BUG << "AppendPaddingFrame of "
+ << frame.padding_frame.num_padding_bytes
+ << " failed: " << detailed_error();
+ return 0;
+ }
+ break;
+ case STREAM_FRAME:
+ if (!AppendStreamFrame(frame.stream_frame, last_frame_in_packet,
+ writer)) {
+ QUIC_BUG << "AppendStreamFrame failed: " << detailed_error();
+ return 0;
+ }
+ break;
+ case ACK_FRAME:
+ if (!AppendIetfAckFrameAndTypeByte(*frame.ack_frame, writer)) {
+ QUIC_BUG << "AppendAckFrameAndTypeByte failed: " << detailed_error();
+ return 0;
+ }
+ break;
+ case STOP_WAITING_FRAME:
+ set_detailed_error(
+ "Attempt to append STOP WAITING frame in version 99.");
+ return RaiseError(QUIC_INTERNAL_ERROR);
+ case MTU_DISCOVERY_FRAME:
+ // MTU discovery frames are serialized as ping frames.
+ QUIC_FALLTHROUGH_INTENDED;
+ case PING_FRAME:
+ // Ping has no payload.
+ break;
+ case RST_STREAM_FRAME:
+ if (!AppendRstStreamFrame(*frame.rst_stream_frame, writer)) {
+ QUIC_BUG << "AppendRstStreamFrame failed: " << detailed_error();
+ return 0;
+ }
+ break;
+ case CONNECTION_CLOSE_FRAME:
+ if (!AppendConnectionCloseFrame(*frame.connection_close_frame,
+ writer)) {
+ QUIC_BUG << "AppendConnectionCloseFrame failed: " << detailed_error();
+ return 0;
+ }
+ break;
+ case GOAWAY_FRAME:
+ set_detailed_error("Attempt to append GOAWAY frame in version 99.");
+ return RaiseError(QUIC_INTERNAL_ERROR);
+ case WINDOW_UPDATE_FRAME:
+ // Depending on whether there is a stream ID or not, will be either a
+ // MAX STREAM DATA frame or a MAX DATA frame.
+ if (frame.window_update_frame->stream_id ==
+ QuicUtils::GetInvalidStreamId(transport_version())) {
+ if (!AppendMaxDataFrame(*frame.window_update_frame, writer)) {
+ QUIC_BUG << "AppendMaxDataFrame failed: " << detailed_error();
+ return 0;
+ }
+ } else {
+ if (!AppendMaxStreamDataFrame(*frame.window_update_frame, writer)) {
+ QUIC_BUG << "AppendMaxStreamDataFrame failed: " << detailed_error();
+ return 0;
+ }
+ }
+ break;
+ case BLOCKED_FRAME:
+ if (!AppendBlockedFrame(*frame.blocked_frame, writer)) {
+ QUIC_BUG << "AppendBlockedFrame failed: " << detailed_error();
+ return 0;
+ }
+ break;
+ case APPLICATION_CLOSE_FRAME:
+ if (!AppendApplicationCloseFrame(*frame.application_close_frame,
+ writer)) {
+ QUIC_BUG << "AppendApplicationCloseFrame failed: "
+ << detailed_error();
+ return 0;
+ }
+ break;
+ case MAX_STREAM_ID_FRAME:
+ if (!AppendMaxStreamsFrame(frame.max_stream_id_frame, writer)) {
+ QUIC_BUG << "AppendMaxStreamsFrame failed" << detailed_error();
+ return 0;
+ }
+ break;
+ case STREAM_ID_BLOCKED_FRAME:
+ if (!AppendStreamsBlockedFrame(frame.stream_id_blocked_frame, writer)) {
+ QUIC_BUG << "AppendStreamsBlockedFrame failed" << detailed_error();
+ return 0;
+ }
+ break;
+ case NEW_CONNECTION_ID_FRAME:
+ if (!AppendNewConnectionIdFrame(*frame.new_connection_id_frame,
+ writer)) {
+ QUIC_BUG << "AppendNewConnectionIdFrame failed: " << detailed_error();
+ return 0;
+ }
+ break;
+ case RETIRE_CONNECTION_ID_FRAME:
+ if (!AppendRetireConnectionIdFrame(*frame.retire_connection_id_frame,
+ writer)) {
+ QUIC_BUG << "AppendRetireConnectionIdFrame failed: "
+ << detailed_error();
+ return 0;
+ }
+ break;
+ case NEW_TOKEN_FRAME:
+ if (!AppendNewTokenFrame(*frame.new_token_frame, writer)) {
+ QUIC_BUG << "AppendNewTokenFrame failed: " << detailed_error();
+ return 0;
+ }
+ break;
+ case STOP_SENDING_FRAME:
+ if (!AppendStopSendingFrame(*frame.stop_sending_frame, writer)) {
+ QUIC_BUG << "AppendStopSendingFrame failed: " << detailed_error();
+ return 0;
+ }
+ break;
+ case PATH_CHALLENGE_FRAME:
+ if (!AppendPathChallengeFrame(*frame.path_challenge_frame, writer)) {
+ QUIC_BUG << "AppendPathChallengeFrame failed: " << detailed_error();
+ return 0;
+ }
+ break;
+ case PATH_RESPONSE_FRAME:
+ if (!AppendPathResponseFrame(*frame.path_response_frame, writer)) {
+ QUIC_BUG << "AppendPathResponseFrame failed: " << detailed_error();
+ return 0;
+ }
+ break;
+ case MESSAGE_FRAME:
+ if (!AppendMessageFrameAndTypeByte(*frame.message_frame,
+ last_frame_in_packet, writer)) {
+ QUIC_BUG << "AppendMessageFrame failed: " << detailed_error();
+ return 0;
+ }
+ break;
+ case CRYPTO_FRAME:
+ if (!AppendCryptoFrame(*frame.crypto_frame, writer)) {
+ QUIC_BUG << "AppendCryptoFrame failed: " << detailed_error();
+ return 0;
+ }
+ break;
+ default:
+ RaiseError(QUIC_INVALID_FRAME_DATA);
+ set_detailed_error("Tried to append unknown frame type.");
+ QUIC_BUG << "QUIC_INVALID_FRAME_DATA";
+ return 0;
+ }
+ ++i;
+ }
+
+ return writer->length();
+}
+
+size_t QuicFramer::BuildConnectivityProbingPacketNew(
const QuicPacketHeader& header,
char* buffer,
- size_t packet_length) {
+ size_t packet_length,
+ EncryptionLevel level) {
QuicFrames frames;
// Write a PING frame, which has no data payload.
@@ -1090,19 +1201,26 @@
QuicPaddingFrame padding_frame;
frames.push_back(QuicFrame(padding_frame));
- return BuildIetfDataPacket(header, frames, buffer, packet_length);
+ return BuildDataPacket(header, frames, buffer, packet_length, level);
}
size_t QuicFramer::BuildConnectivityProbingPacket(
const QuicPacketHeader& header,
char* buffer,
- size_t packet_length) {
- if (version_.transport_version == QUIC_VERSION_99) {
- return BuildIetfConnectivityProbingPacket(header, buffer, packet_length);
+ size_t packet_length,
+ EncryptionLevel level) {
+ if (transport_version() == QUIC_VERSION_99 ||
+ QuicVersionHasLongHeaderLengths(transport_version()) ||
+ GetQuicReloadableFlag(quic_simplify_build_connectivity_probing_packet)) {
+ QUIC_RELOADABLE_FLAG_COUNT(quic_simplify_build_connectivity_probing_packet);
+ // TODO(rch): Remove this method when the flag is deprecated.
+ return BuildConnectivityProbingPacketNew(header, buffer, packet_length,
+ level);
}
- QuicDataWriter writer(packet_length, buffer, endianness());
- if (!AppendPacketHeader(header, &writer)) {
+ QuicDataWriter writer(packet_length, buffer);
+
+ if (!AppendPacketHeader(header, &writer, nullptr)) {
QUIC_BUG << "AppendPacketHeader failed";
return 0;
}
@@ -1133,7 +1251,8 @@
char* buffer,
size_t packet_length,
QuicPathFrameBuffer* payload,
- QuicRandom* randomizer) {
+ QuicRandom* randomizer,
+ EncryptionLevel level) {
if (version_.transport_version != QUIC_VERSION_99) {
QUIC_BUG << "Attempt to build a PATH_CHALLENGE Connectivity Probing "
"packet and not doing IETF QUIC";
@@ -1152,7 +1271,7 @@
QuicPaddingFrame padding_frame;
frames.push_back(QuicFrame(padding_frame));
- return BuildIetfDataPacket(header, frames, buffer, packet_length);
+ return BuildDataPacket(header, frames, buffer, packet_length, level);
}
size_t QuicFramer::BuildPathResponsePacket(
@@ -1160,7 +1279,8 @@
char* buffer,
size_t packet_length,
const QuicDeque<QuicPathFrameBuffer>& payloads,
- const bool is_padded) {
+ const bool is_padded,
+ EncryptionLevel level) {
if (payloads.empty()) {
QUIC_BUG
<< "Attempt to generate connectivity response with no request payloads";
@@ -1192,7 +1312,7 @@
frames.push_back(QuicFrame(padding_frame));
}
- return BuildIetfDataPacket(header, frames, buffer, packet_length);
+ return BuildDataPacket(header, frames, buffer, packet_length, level);
}
// static
@@ -1221,7 +1341,7 @@
std::unique_ptr<char[]> buffer(new char[len]);
// Endianness is not a concern here, as writer is not going to write integers
// or floating numbers.
- QuicDataWriter writer(len, buffer.get(), NETWORK_BYTE_ORDER);
+ QuicDataWriter writer(len, buffer.get());
uint8_t flags = static_cast<uint8_t>(PACKET_PUBLIC_FLAGS_RST |
PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID);
@@ -1231,7 +1351,7 @@
return nullptr;
}
- if (!writer.WriteConnectionId(packet.connection_id, Perspective::IS_SERVER)) {
+ if (!writer.WriteConnectionId(packet.connection_id)) {
return nullptr;
}
@@ -1255,7 +1375,7 @@
size_t len = kPacketHeaderTypeSize + random_bytes_length +
sizeof(stateless_reset_token);
std::unique_ptr<char[]> buffer(new char[len]);
- QuicDataWriter writer(len, buffer.get(), NETWORK_BYTE_ORDER);
+ QuicDataWriter writer(len, buffer.get());
uint8_t type = 0;
type |= FLAGS_FIXED_BIT;
@@ -1306,7 +1426,7 @@
std::unique_ptr<char[]> buffer(new char[len]);
// Endianness is not a concern here, version negotiation packet does not have
// integers or floating numbers.
- QuicDataWriter writer(len, buffer.get(), NETWORK_BYTE_ORDER);
+ QuicDataWriter writer(len, buffer.get());
uint8_t flags = static_cast<uint8_t>(
PACKET_PUBLIC_FLAGS_VERSION | PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID |
@@ -1316,7 +1436,7 @@
return nullptr;
}
- if (!writer.WriteConnectionId(connection_id, Perspective::IS_SERVER)) {
+ if (!writer.WriteConnectionId(connection_id)) {
return nullptr;
}
@@ -1342,7 +1462,7 @@
PACKET_8BYTE_CONNECTION_ID +
(versions.size() + 1) * kQuicVersionSize;
std::unique_ptr<char[]> buffer(new char[len]);
- QuicDataWriter writer(len, buffer.get(), NETWORK_BYTE_ORDER);
+ QuicDataWriter writer(len, buffer.get());
// TODO(fayang): Randomly select a value for the type.
uint8_t type = static_cast<uint8_t>(FLAGS_LONG_HEADER | VERSION_NEGOTIATION);
@@ -1356,8 +1476,7 @@
if (!AppendIetfConnectionId(true, EmptyQuicConnectionId(),
PACKET_0BYTE_CONNECTION_ID, connection_id,
- PACKET_8BYTE_CONNECTION_ID, &writer,
- Perspective::IS_SERVER)) {
+ PACKET_8BYTE_CONNECTION_ID, &writer)) {
return nullptr;
}
@@ -1373,7 +1492,7 @@
}
bool QuicFramer::ProcessPacket(const QuicEncryptedPacket& packet) {
- QuicDataReader reader(packet.data(), packet.length(), endianness());
+ QuicDataReader reader(packet.data(), packet.length());
bool last_packet_is_ietf_quic = false;
if (infer_packet_header_type_from_version_) {
@@ -1384,7 +1503,6 @@
}
if (last_packet_is_ietf_quic) {
QUIC_DVLOG(1) << ENDPOINT << "Processing IETF QUIC packet.";
- reader.set_endianness(NETWORK_BYTE_ORDER);
}
visitor_->OnPacket();
@@ -1397,7 +1515,6 @@
DCHECK_NE("", detailed_error_);
return RaiseError(QUIC_INVALID_PACKET_HEADER);
}
- last_header_form_ = header.form;
if (!visitor_->OnUnauthenticatedPublicHeader(header)) {
// The visitor suppresses further processing of the packet.
@@ -1411,9 +1528,6 @@
}
}
- // framer's version may change, reset reader's endianness.
- reader.set_endianness(endianness());
-
bool rv;
if (IsVersionNegotiation(header, last_packet_is_ietf_quic)) {
QUIC_DVLOG(1) << ENDPOINT << "Received version negotiation packet";
@@ -1467,6 +1581,119 @@
return true;
}
+bool QuicFramer::MaybeProcessIetfInitialRetryToken(
+ QuicDataReader* encrypted_reader,
+ QuicPacketHeader* header) {
+ if (!QuicVersionHasLongHeaderLengths(header->version.transport_version) ||
+ header->form != IETF_QUIC_LONG_HEADER_PACKET ||
+ header->long_packet_type != INITIAL) {
+ return true;
+ }
+ uint64_t retry_token_length = 0;
+ header->retry_token_length_length = encrypted_reader->PeekVarInt62Length();
+ if (!encrypted_reader->ReadVarInt62(&retry_token_length)) {
+ set_detailed_error("Unable to read INITIAL retry token length.");
+ return RaiseError(QUIC_INVALID_PACKET_HEADER);
+ }
+ header->retry_token = encrypted_reader->PeekRemainingPayload();
+ // Safety check to avoid spending ressources if malformed.
+ // At this point header->retry_token contains the rest of the packet
+ // so its length() is the amount of data remaining in the packet.
+ if (retry_token_length > header->retry_token.length()) {
+ set_detailed_error("INITIAL token length longer than packet.");
+ return RaiseError(QUIC_INVALID_PACKET_HEADER);
+ }
+ // Resize retry_token to make it only contain the retry token.
+ header->retry_token.remove_suffix(header->retry_token.length() -
+ retry_token_length);
+ // Advance encrypted_reader by retry_token_length.
+ uint8_t wasted_byte;
+ for (uint64_t i = 0; i < retry_token_length; ++i) {
+ if (!encrypted_reader->ReadUInt8(&wasted_byte)) {
+ set_detailed_error("Unable to read INITIAL retry token.");
+ return RaiseError(QUIC_INVALID_PACKET_HEADER);
+ }
+ }
+ return true;
+}
+
+// Seeks the current packet to check for a coalesced packet at the end.
+// If the IETF length field only spans part of the outer packet,
+// then there is a coalesced packet after this one.
+void QuicFramer::MaybeProcessCoalescedPacket(
+ const QuicDataReader& encrypted_reader,
+ uint64_t remaining_bytes_length,
+ const QuicPacketHeader& header) {
+ if (header.remaining_packet_length >= remaining_bytes_length) {
+ // There is no coalesced packet.
+ return;
+ }
+
+ QuicStringPiece remaining_data = encrypted_reader.PeekRemainingPayload();
+ DCHECK_EQ(remaining_data.length(), remaining_bytes_length);
+
+ const char* coalesced_data =
+ remaining_data.data() + header.remaining_packet_length;
+ uint64_t coalesced_data_length =
+ remaining_bytes_length - header.remaining_packet_length;
+ QuicDataReader coalesced_reader(coalesced_data, coalesced_data_length);
+
+ QuicPacketHeader coalesced_header;
+ if (!ProcessIetfPacketHeader(&coalesced_reader, &coalesced_header)) {
+ QUIC_PEER_BUG << ENDPOINT
+ << "Failed to parse received coalesced header of length "
+ << coalesced_data_length << ": "
+ << QuicTextUtils::HexEncode(coalesced_data,
+ coalesced_data_length)
+ << " previous header was " << header;
+ return;
+ }
+
+ if (coalesced_header.destination_connection_id !=
+ header.destination_connection_id ||
+ (coalesced_header.form != IETF_QUIC_SHORT_HEADER_PACKET &&
+ coalesced_header.version != header.version)) {
+ QUIC_PEER_BUG << ENDPOINT << "Received mismatched coalesced header "
+ << coalesced_header << " previous header was " << header;
+ return;
+ }
+
+ QuicEncryptedPacket coalesced_packet(coalesced_data, coalesced_data_length,
+ /*owns_buffer=*/false);
+ visitor_->OnCoalescedPacket(coalesced_packet);
+}
+
+bool QuicFramer::MaybeProcessIetfLength(QuicDataReader* encrypted_reader,
+ QuicPacketHeader* header) {
+ if (!QuicVersionHasLongHeaderLengths(header->version.transport_version) ||
+ header->form != IETF_QUIC_LONG_HEADER_PACKET ||
+ (header->long_packet_type != INITIAL &&
+ header->long_packet_type != HANDSHAKE &&
+ header->long_packet_type != ZERO_RTT_PROTECTED)) {
+ return true;
+ }
+ header->length_length = encrypted_reader->PeekVarInt62Length();
+ if (!encrypted_reader->ReadVarInt62(&header->remaining_packet_length)) {
+ set_detailed_error("Unable to read long header payload length.");
+ return RaiseError(QUIC_INVALID_PACKET_HEADER);
+ }
+ uint64_t remaining_bytes_length = encrypted_reader->BytesRemaining();
+ if (header->remaining_packet_length > remaining_bytes_length) {
+ set_detailed_error("Long header payload length longer than packet.");
+ return RaiseError(QUIC_INVALID_PACKET_HEADER);
+ }
+
+ MaybeProcessCoalescedPacket(*encrypted_reader, remaining_bytes_length,
+ *header);
+
+ if (!encrypted_reader->TruncateRemaining(header->remaining_packet_length)) {
+ set_detailed_error("Length TruncateRemaining failed.");
+ QUIC_BUG << "Length TruncateRemaining failed.";
+ return RaiseError(QUIC_INVALID_PACKET_HEADER);
+ }
+ return true;
+}
+
bool QuicFramer::ProcessIetfDataPacket(QuicDataReader* encrypted_reader,
QuicPacketHeader* header,
const QuicEncryptedPacket& packet,
@@ -1474,6 +1701,10 @@
size_t buffer_length) {
DCHECK_NE(GOOGLE_QUIC_PACKET, header->form);
DCHECK(!header->has_possible_stateless_reset_token);
+ header->retry_token_length_length = VARIABLE_LENGTH_INTEGER_LENGTH_0;
+ header->retry_token = QuicStringPiece();
+ header->length_length = VARIABLE_LENGTH_INTEGER_LENGTH_0;
+ header->remaining_packet_length = 0;
if (header->form == IETF_QUIC_SHORT_HEADER_PACKET &&
perspective_ == Perspective::IS_CLIENT) {
// Peek possible stateless reset token. Will only be used on decryption
@@ -1488,6 +1719,14 @@
}
}
+ if (!MaybeProcessIetfInitialRetryToken(encrypted_reader, header)) {
+ return false;
+ }
+
+ if (!MaybeProcessIetfLength(encrypted_reader, header)) {
+ return false;
+ }
+
if (header->form == IETF_QUIC_SHORT_HEADER_PACKET ||
header->long_packet_type != VERSION_NEGOTIATION) {
// Process packet number.
@@ -1518,7 +1757,8 @@
// using QUIC crypto.
if (header->form == IETF_QUIC_LONG_HEADER_PACKET &&
header->long_packet_type == ZERO_RTT_PROTECTED &&
- perspective_ == Perspective::IS_CLIENT) {
+ perspective_ == Perspective::IS_CLIENT &&
+ version_.handshake_protocol == PROTOCOL_QUIC_CRYPTO) {
if (!encrypted_reader->ReadBytes(
reinterpret_cast<uint8_t*>(last_nonce_.data()),
last_nonce_.size())) {
@@ -1537,8 +1777,17 @@
return false;
}
+ QuicStringPiece encrypted = encrypted_reader->ReadRemainingPayload();
+ QuicStringPiece associated_data = GetAssociatedDataFromEncryptedPacket(
+ version_.transport_version, packet,
+ header->destination_connection_id_length,
+ header->source_connection_id_length, header->version_flag,
+ header->nonce != nullptr, header->packet_number_length,
+ header->retry_token_length_length, header->retry_token.length(),
+ header->length_length);
+
size_t decrypted_length = 0;
- if (!DecryptPayload(encrypted_reader, *header, packet, decrypted_buffer,
+ if (!DecryptPayload(encrypted, associated_data, *header, decrypted_buffer,
buffer_length, &decrypted_length)) {
if (IsIetfStatelessResetPacket(*header)) {
// This is a stateless reset packet.
@@ -1550,7 +1799,7 @@
set_detailed_error("Unable to decrypt payload.");
return RaiseError(QUIC_DECRYPTION_FAILURE);
}
- QuicDataReader reader(decrypted_buffer, decrypted_length, endianness());
+ QuicDataReader reader(decrypted_buffer, decrypted_length);
// Update the largest packet number after we have decrypted the packet
// so we are confident is not attacker controlled.
@@ -1609,14 +1858,23 @@
return false;
}
+ QuicStringPiece encrypted = encrypted_reader->ReadRemainingPayload();
+ QuicStringPiece associated_data = GetAssociatedDataFromEncryptedPacket(
+ version_.transport_version, packet,
+ header->destination_connection_id_length,
+ header->source_connection_id_length, header->version_flag,
+ header->nonce != nullptr, header->packet_number_length,
+ header->retry_token_length_length, header->retry_token.length(),
+ header->length_length);
+
size_t decrypted_length = 0;
- if (!DecryptPayload(encrypted_reader, *header, packet, decrypted_buffer,
+ if (!DecryptPayload(encrypted, associated_data, *header, decrypted_buffer,
buffer_length, &decrypted_length)) {
set_detailed_error("Unable to decrypt payload.");
return RaiseError(QUIC_DECRYPTION_FAILURE);
}
- QuicDataReader reader(decrypted_buffer, decrypted_length, endianness());
+ QuicDataReader reader(decrypted_buffer, decrypted_length);
// Update the largest packet number after we have decrypted the packet
// so we are confident is not attacker controlled.
@@ -1704,9 +1962,10 @@
}
bool QuicFramer::AppendPacketHeader(const QuicPacketHeader& header,
- QuicDataWriter* writer) {
+ QuicDataWriter* writer,
+ size_t* length_field_offset) {
if (transport_version() > QUIC_VERSION_43) {
- return AppendIetfPacketHeader(header, writer);
+ return AppendIetfPacketHeader(header, writer, length_field_offset);
}
QUIC_DVLOG(1) << ENDPOINT << "Appending header: " << header;
uint8_t public_flags = 0;
@@ -1745,8 +2004,7 @@
public_flags |= PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID_OLD;
}
if (!writer->WriteUInt8(public_flags) ||
- !writer->WriteConnectionId(header.destination_connection_id,
- perspective_)) {
+ !writer->WriteConnectionId(header.destination_connection_id)) {
return false;
}
break;
@@ -1781,7 +2039,7 @@
bool QuicFramer::AppendIetfHeaderTypeByte(const QuicPacketHeader& header,
QuicDataWriter* writer) {
uint8_t type = 0;
- if (transport_version() > QUIC_VERSION_46) {
+ if (transport_version() > QUIC_VERSION_44) {
if (header.version_flag) {
type = static_cast<uint8_t>(
FLAGS_LONG_HEADER | FLAGS_FIXED_BIT |
@@ -1814,7 +2072,8 @@
}
bool QuicFramer::AppendIetfPacketHeader(const QuicPacketHeader& header,
- QuicDataWriter* writer) {
+ QuicDataWriter* writer,
+ size_t* length_field_offset) {
QUIC_DVLOG(1) << ENDPOINT << "Appending IETF header: " << header;
QUIC_BUG_IF(!QuicUtils::IsConnectionIdValidForVersion(
header.destination_connection_id, transport_version()))
@@ -1838,11 +2097,34 @@
if (!AppendIetfConnectionId(
header.version_flag, header.destination_connection_id,
header.destination_connection_id_length, header.source_connection_id,
- header.source_connection_id_length, writer, perspective_)) {
+ header.source_connection_id_length, writer)) {
return false;
}
last_serialized_connection_id_ = header.destination_connection_id;
+ if (QuicVersionHasLongHeaderLengths(transport_version()) &&
+ header.version_flag) {
+ if (header.long_packet_type == INITIAL) {
+ // Write retry token length.
+ if (!writer->WriteVarInt62(header.retry_token.length(),
+ header.retry_token_length_length)) {
+ return false;
+ }
+ // Write retry token.
+ if (!header.retry_token.empty() &&
+ !writer->WriteStringPiece(header.retry_token)) {
+ return false;
+ }
+ }
+ if (length_field_offset != nullptr) {
+ *length_field_offset = writer->length();
+ }
+ // Add fake length to reserve two bytes to add length in later.
+ writer->WriteVarInt62(256);
+ } else if (length_field_offset != nullptr) {
+ *length_field_offset = 0;
+ }
+
// Append packet number.
if (!AppendPacketNumber(header.packet_number_length, header.packet_number,
writer)) {
@@ -1943,8 +2225,7 @@
switch (public_flags & PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID) {
case PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID:
if (!reader->ReadConnectionId(&header->destination_connection_id,
- kQuicDefaultConnectionIdLength,
- perspective_)) {
+ kQuicDefaultConnectionIdLength)) {
set_detailed_error("Unable to read ConnectionId.");
return false;
}
@@ -2133,7 +2414,7 @@
} else {
header->version = ParseQuicVersionLabel(version_label);
if (header->version.transport_version != QUIC_VERSION_UNSUPPORTED) {
- if (header->version.transport_version > QUIC_VERSION_46 &&
+ if (header->version.transport_version > QUIC_VERSION_44 &&
!(type & FLAGS_FIXED_BIT)) {
set_detailed_error("Fixed bit is 0 in long header.");
return false;
@@ -2170,7 +2451,7 @@
header->destination_connection_id = last_serialized_connection_id_;
}
if (infer_packet_header_type_from_version_ &&
- transport_version() > QUIC_VERSION_46 && !(type & FLAGS_FIXED_BIT)) {
+ transport_version() > QUIC_VERSION_44 && !(type & FLAGS_FIXED_BIT)) {
set_detailed_error("Fixed bit is 0 in short header.");
return false;
}
@@ -2218,14 +2499,14 @@
// Read connection ID.
if (header->destination_connection_id_length == PACKET_8BYTE_CONNECTION_ID &&
!reader->ReadConnectionId(&header->destination_connection_id,
- kQuicDefaultConnectionIdLength, perspective_)) {
+ kQuicDefaultConnectionIdLength)) {
set_detailed_error("Unable to read Destination ConnectionId.");
return false;
}
if (header->source_connection_id_length == PACKET_8BYTE_CONNECTION_ID &&
!reader->ReadConnectionId(&header->source_connection_id,
- kQuicDefaultConnectionIdLength, perspective_)) {
+ kQuicDefaultConnectionIdLength)) {
set_detailed_error("Unable to read Source ConnectionId.");
return false;
}
@@ -2428,6 +2709,22 @@
}
break;
}
+ case CRYPTO_FRAME: {
+ if (version_.transport_version < QUIC_VERSION_47) {
+ set_detailed_error("Illegal frame type.");
+ return RaiseError(QUIC_INVALID_FRAME_DATA);
+ }
+ QuicCryptoFrame frame;
+ if (!ProcessCryptoFrame(reader, &frame)) {
+ return RaiseError(QUIC_INVALID_FRAME_DATA);
+ }
+ if (!visitor_->OnCryptoFrame(frame)) {
+ QUIC_DVLOG(1) << "Visitor asked to stop further processing.";
+ // Returning true since there was no parsing error.
+ return true;
+ }
+ break;
+ }
default:
set_detailed_error("Illegal frame type.");
@@ -2556,9 +2853,10 @@
}
break;
}
- case IETF_MAX_STREAM_ID: {
+ case IETF_MAX_STREAMS_BIDIRECTIONAL:
+ case IETF_MAX_STREAMS_UNIDIRECTIONAL: {
QuicMaxStreamIdFrame frame;
- if (!ProcessMaxStreamIdFrame(reader, &frame)) {
+ if (!ProcessMaxStreamsFrame(reader, &frame, frame_type)) {
return RaiseError(QUIC_MAX_STREAM_ID_DATA);
}
QUIC_CODE_COUNT_N(max_stream_id_received, 1, 2);
@@ -2603,9 +2901,10 @@
}
break;
}
- case IETF_STREAM_ID_BLOCKED: {
+ case IETF_STREAMS_BLOCKED_UNIDIRECTIONAL:
+ case IETF_STREAMS_BLOCKED_BIDIRECTIONAL: {
QuicStreamIdBlockedFrame frame;
- if (!ProcessStreamIdBlockedFrame(reader, &frame)) {
+ if (!ProcessStreamsBlockedFrame(reader, &frame, frame_type)) {
return RaiseError(QUIC_STREAM_ID_BLOCKED_DATA);
}
QUIC_CODE_COUNT_N(stream_id_blocked_received, 1, 2);
@@ -2927,9 +3226,7 @@
return false;
}
- if (GetQuicReloadableFlag(quic_disallow_peer_ack_0) &&
- largest_acked < first_sending_packet_number_.ToUint64()) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_disallow_peer_ack_0, 1, 3);
+ if (largest_acked < first_sending_packet_number_.ToUint64()) {
// Connection always sends packet starting from kFirstSendingPacketNumber >
// 0, peer has observed an unsent packet.
set_detailed_error("Largest acked is 0.");
@@ -2966,25 +3263,12 @@
}
if (first_block_length == 0) {
- // For non-empty ACKs, the first block length must be non-zero.
- // TODO(fayang): remove this if and return false directly when deprecating
- // gfe2_reloadable_flag_quic_disallow_peer_ack_0.
- if (largest_acked != 0 || num_ack_blocks != 0) {
- set_detailed_error(
- QuicStrCat("First block length is zero but ACK is "
- "not empty. largest acked is ",
- largest_acked, ", num ack blocks is ",
- QuicTextUtils::Uint64ToString(num_ack_blocks), ".")
- .c_str());
- return false;
- }
- DCHECK(!GetQuicReloadableFlag(quic_disallow_peer_ack_0));
+ set_detailed_error("First block length is zero.");
+ return false;
}
bool first_ack_block_underflow = first_block_length > largest_acked + 1;
- if (GetQuicReloadableFlag(quic_disallow_peer_ack_0) &&
- first_block_length + first_sending_packet_number_.ToUint64() >
- largest_acked + 1) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_disallow_peer_ack_0, 2, 3);
+ if (first_block_length + first_sending_packet_number_.ToUint64() >
+ largest_acked + 1) {
first_ack_block_underflow = true;
}
if (first_ack_block_underflow) {
@@ -3018,10 +3302,8 @@
return false;
}
bool ack_block_underflow = first_received < gap + current_block_length;
- if (GetQuicReloadableFlag(quic_disallow_peer_ack_0) &&
- first_received < gap + current_block_length +
+ if (first_received < gap + current_block_length +
first_sending_packet_number_.ToUint64()) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_disallow_peer_ack_0, 3, 3);
ack_block_underflow = true;
}
if (ack_block_underflow) {
@@ -3074,6 +3356,14 @@
return false;
}
+ if (largest_acked.ToUint64() <= delta_from_largest_observed) {
+ set_detailed_error(QuicStrCat("delta_from_largest_observed too high: ",
+ delta_from_largest_observed,
+ ", largest_acked: ", largest_acked.ToUint64())
+ .c_str());
+ return false;
+ }
+
// Time delta from the framer creation.
uint32_t time_delta_us;
if (!reader->ReadUInt32(&time_delta_us)) {
@@ -3093,6 +3383,14 @@
set_detailed_error("Unable to read sequence delta in received packets.");
return false;
}
+ if (largest_acked.ToUint64() <= delta_from_largest_observed) {
+ set_detailed_error(
+ QuicStrCat("delta_from_largest_observed too high: ",
+ delta_from_largest_observed,
+ ", largest_acked: ", largest_acked.ToUint64())
+ .c_str());
+ return false;
+ }
seq_num = largest_acked - delta_from_largest_observed;
// Time delta from the previous timestamp.
@@ -3410,11 +3708,6 @@
void QuicFramer::ProcessPaddingFrame(QuicDataReader* reader,
QuicPaddingFrame* frame) {
- if (version_.transport_version == QUIC_VERSION_35) {
- frame->num_padding_bytes = reader->BytesRemaining() + 1;
- reader->ReadRemainingPayload();
- return;
- }
// Type byte has been read.
frame->num_padding_bytes = 1;
uint8_t next_byte;
@@ -3429,7 +3722,9 @@
bool no_message_length,
QuicMessageFrame* frame) {
if (no_message_length) {
- frame->message_data = QuicString(reader->ReadRemainingPayload());
+ QuicStringPiece remaining(reader->ReadRemainingPayload());
+ frame->data = remaining.data();
+ frame->message_length = remaining.length();
return true;
}
@@ -3445,7 +3740,8 @@
return false;
}
- frame->message_data = QuicString(message_piece);
+ frame->data = message_piece.data();
+ frame->message_length = message_length;
return true;
}
@@ -3458,14 +3754,18 @@
QuicConnectionIdLength source_connection_id_length,
bool includes_version,
bool includes_diversification_nonce,
- QuicPacketNumberLength packet_number_length) {
+ QuicPacketNumberLength packet_number_length,
+ QuicVariableLengthIntegerLength retry_token_length_length,
+ uint64_t retry_token_length,
+ QuicVariableLengthIntegerLength length_length) {
// TODO(ianswett): This is identical to QuicData::AssociatedData.
return QuicStringPiece(
encrypted.data(),
GetStartOfEncryptedData(version, destination_connection_id_length,
source_connection_id_length, includes_version,
includes_diversification_nonce,
- packet_number_length));
+ packet_number_length, retry_token_length_length,
+ retry_token_length, length_length));
}
void QuicFramer::SetDecrypter(EncryptionLevel level,
@@ -3509,7 +3809,7 @@
DCHECK(packet_number.IsInitialized());
size_t output_length = 0;
if (!encrypter_[level]->EncryptPacket(
- version_.transport_version, packet_number.ToUint64(),
+ packet_number.ToUint64(),
QuicStringPiece(buffer, ad_len), // Associated data
QuicStringPiece(buffer + ad_len, total_len - ad_len), // Plaintext
buffer + ad_len, // Destination buffer
@@ -3538,7 +3838,7 @@
// Encrypt the plaintext into the buffer.
size_t output_length = 0;
if (!encrypter_[level]->EncryptPacket(
- version_.transport_version, packet_number.ToUint64(), associated_data,
+ packet_number.ToUint64(), associated_data,
packet.Plaintext(version_.transport_version), buffer + ad_len,
&output_length, buffer_len - ad_len)) {
RaiseError(QUIC_ENCRYPTION_FAILURE);
@@ -3548,6 +3848,11 @@
return ad_len + output_length;
}
+size_t QuicFramer::GetCiphertextSize(EncryptionLevel level,
+ size_t plaintext_size) const {
+ return encrypter_[level]->GetCiphertextSize(plaintext_size);
+}
+
size_t QuicFramer::GetMaxPlaintextSize(size_t ciphertext_size) {
// In order to keep the code simple, we don't have the current encryption
// level to hand. Both the NullEncrypter and AES-GCM have a tag length of 12.
@@ -3565,24 +3870,17 @@
return min_plaintext_size;
}
-bool QuicFramer::DecryptPayload(QuicDataReader* encrypted_reader,
+bool QuicFramer::DecryptPayload(QuicStringPiece encrypted,
+ QuicStringPiece associated_data,
const QuicPacketHeader& header,
- const QuicEncryptedPacket& packet,
char* decrypted_buffer,
size_t buffer_length,
size_t* decrypted_length) {
- QuicStringPiece encrypted = encrypted_reader->ReadRemainingPayload();
DCHECK(decrypter_ != nullptr);
- QuicStringPiece associated_data = GetAssociatedDataFromEncryptedPacket(
- version_.transport_version, packet,
- header.destination_connection_id_length,
- header.source_connection_id_length, header.version_flag,
- header.nonce != nullptr, header.packet_number_length);
bool success = decrypter_->DecryptPacket(
- version_.transport_version, header.packet_number.ToUint64(),
- associated_data, encrypted, decrypted_buffer, decrypted_length,
- buffer_length);
+ header.packet_number.ToUint64(), associated_data, encrypted,
+ decrypted_buffer, decrypted_length, buffer_length);
if (success) {
visitor_->OnDecryptedPacket(decrypter_level_);
} else if (alternative_decrypter_ != nullptr) {
@@ -3591,7 +3889,7 @@
alternative_decrypter_->SetDiversificationNonce(*header.nonce);
}
bool try_alternative_decryption = true;
- if (alternative_decrypter_level_ == ENCRYPTION_INITIAL) {
+ if (alternative_decrypter_level_ == ENCRYPTION_ZERO_RTT) {
if (perspective_ == Perspective::IS_CLIENT) {
if (header.nonce == nullptr) {
// Can not use INITIAL decryption without a diversification nonce.
@@ -3604,9 +3902,8 @@
if (try_alternative_decryption) {
success = alternative_decrypter_->DecryptPacket(
- version_.transport_version, header.packet_number.ToUint64(),
- associated_data, encrypted, decrypted_buffer, decrypted_length,
- buffer_length);
+ header.packet_number.ToUint64(), associated_data, encrypted,
+ decrypted_buffer, decrypted_length, buffer_length);
}
if (success) {
visitor_->OnDecryptedPacket(alternative_decrypter_level_);
@@ -3793,7 +4090,7 @@
case MESSAGE_FRAME:
return GetMessageFrameSize(version_.transport_version,
last_frame_in_packet,
- frame.message_frame->message_data.length());
+ frame.message_frame->message_length);
case PADDING_FRAME:
DCHECK(false);
return 0;
@@ -3890,14 +4187,16 @@
case WINDOW_UPDATE_FRAME:
// Depending on whether there is a stream ID or not, will be either a
// MAX_STREAM_DATA frame or a MAX_DATA frame.
- if (frame.window_update_frame->stream_id == 0) {
+ if (frame.window_update_frame->stream_id ==
+ QuicUtils::GetInvalidStreamId(transport_version())) {
type_byte = IETF_MAX_DATA;
} else {
type_byte = IETF_MAX_STREAM_DATA;
}
break;
case BLOCKED_FRAME:
- if (frame.blocked_frame->stream_id == 0) {
+ if (frame.blocked_frame->stream_id ==
+ QuicUtils::GetInvalidStreamId(transport_version())) {
type_byte = IETF_BLOCKED;
} else {
type_byte = IETF_STREAM_BLOCKED;
@@ -3935,10 +4234,20 @@
type_byte = IETF_NEW_TOKEN;
break;
case MAX_STREAM_ID_FRAME:
- type_byte = IETF_MAX_STREAM_ID;
+ if (QuicUtils::IsBidirectionalStreamId(
+ frame.max_stream_id_frame.max_stream_id)) {
+ type_byte = IETF_MAX_STREAMS_BIDIRECTIONAL;
+ } else {
+ type_byte = IETF_MAX_STREAMS_UNIDIRECTIONAL;
+ }
break;
case STREAM_ID_BLOCKED_FRAME:
- type_byte = IETF_STREAM_ID_BLOCKED;
+ if (QuicUtils::IsBidirectionalStreamId(
+ frame.max_stream_id_frame.max_stream_id)) {
+ type_byte = IETF_STREAMS_BLOCKED_BIDIRECTIONAL;
+ } else {
+ type_byte = IETF_STREAMS_BLOCKED_UNIDIRECTIONAL;
+ }
break;
case PATH_RESPONSE_FRAME:
type_byte = IETF_PATH_RESPONSE;
@@ -4061,8 +4370,6 @@
return true;
}
-// TODO(dschinazi) b/120240679 - remove perspective once these flags are
-// deprecated: quic_variable_length_connection_ids_(client|server).
// static
bool QuicFramer::AppendIetfConnectionId(
bool version_flag,
@@ -4070,8 +4377,7 @@
QuicConnectionIdLength destination_connection_id_length,
QuicConnectionId source_connection_id,
QuicConnectionIdLength source_connection_id_length,
- QuicDataWriter* writer,
- Perspective perspective) {
+ QuicDataWriter* writer) {
if (version_flag) {
// Append connection ID length byte.
uint8_t dcil = GetConnectionIdLengthValue(destination_connection_id_length);
@@ -4082,11 +4388,11 @@
}
}
if (destination_connection_id_length == PACKET_8BYTE_CONNECTION_ID &&
- !writer->WriteConnectionId(destination_connection_id, perspective)) {
+ !writer->WriteConnectionId(destination_connection_id)) {
return false;
}
if (source_connection_id_length == PACKET_8BYTE_CONNECTION_ID &&
- !writer->WriteConnectionId(source_connection_id, perspective)) {
+ !writer->WriteConnectionId(source_connection_id)) {
return false;
}
return true;
@@ -4688,10 +4994,7 @@
bool QuicFramer::AppendBlockedFrame(const QuicBlockedFrame& frame,
QuicDataWriter* writer) {
if (version_.transport_version == QUIC_VERSION_99) {
- // TODO(fkastenholz): This should be converted to use
- // QuicUtils::GetInvalidStreamId to get the correct invalid stream id value
- // and not rely on 0.
- if (frame.stream_id == 0) {
+ if (frame.stream_id == QuicUtils::GetInvalidStreamId(transport_version())) {
return AppendIetfBlockedFrame(frame, writer);
}
return AppendStreamBlockedFrame(frame, writer);
@@ -4705,11 +5008,6 @@
bool QuicFramer::AppendPaddingFrame(const QuicPaddingFrame& frame,
QuicDataWriter* writer) {
- if (version_.transport_version == QUIC_VERSION_35) {
- writer->WritePadding();
- return true;
- }
-
if (frame.num_padding_bytes == 0) {
return false;
}
@@ -4730,12 +5028,15 @@
if (!writer->WriteUInt8(type_byte)) {
return false;
}
- if (!last_frame_in_packet &&
- !writer->WriteVarInt62(frame.message_data.length())) {
+ if (!last_frame_in_packet && !writer->WriteVarInt62(frame.message_length)) {
return false;
}
- return writer->WriteBytes(frame.message_data.data(),
- frame.message_data.length());
+ for (const auto& slice : frame.message_data) {
+ if (!writer->WriteBytes(slice.data(), slice.length())) {
+ return false;
+ }
+ }
+ return true;
}
bool QuicFramer::RaiseError(QuicErrorCode error) {
@@ -4760,11 +5061,6 @@
return header.long_packet_type == VERSION_NEGOTIATION;
}
-Endianness QuicFramer::endianness() const {
- return version_.transport_version != QUIC_VERSION_35 ? NETWORK_BYTE_ORDER
- : HOST_BYTE_ORDER;
-}
-
bool QuicFramer::StartsWithChlo(QuicStreamId id,
QuicStreamOffset offset) const {
if (data_producer_ == nullptr) {
@@ -4772,7 +5068,7 @@
return false;
}
char buf[sizeof(kCHLO)];
- QuicDataWriter writer(sizeof(kCHLO), buf, endianness());
+ QuicDataWriter writer(sizeof(kCHLO), buf);
if (data_producer_->WriteStreamData(id, offset, sizeof(kCHLO), &writer) !=
WRITE_SUCCESS) {
QUIC_BUG << "Failed to write data for stream " << id << " with offset "
@@ -4784,10 +5080,6 @@
0;
}
-PacketHeaderFormat QuicFramer::GetLastPacketFormat() const {
- return last_header_form_;
-}
-
bool QuicFramer::AppendIetfConnectionCloseFrame(
const QuicConnectionCloseFrame& frame,
QuicDataWriter* writer) {
@@ -5003,7 +5295,7 @@
bool QuicFramer::ProcessMaxDataFrame(QuicDataReader* reader,
QuicWindowUpdateFrame* frame) {
- frame->stream_id = 0;
+ frame->stream_id = QuicUtils::GetInvalidStreamId(transport_version());
if (!reader->ReadVarInt62(&frame->byte_offset)) {
set_detailed_error("Can not read MAX_DATA byte-offset");
return false;
@@ -5038,22 +5330,47 @@
return true;
}
-bool QuicFramer::AppendMaxStreamIdFrame(const QuicMaxStreamIdFrame& frame,
- QuicDataWriter* writer) {
- if (!writer->WriteVarInt62(frame.max_stream_id)) {
- set_detailed_error("Can not write MAX_STREAM_ID stream id");
+bool QuicFramer::AppendMaxStreamsFrame(const QuicMaxStreamIdFrame& frame,
+ QuicDataWriter* writer) {
+ // Convert from the stream id on which the connection is blocked to a count
+ QuicStreamId stream_count =
+ StreamIdToCount(version_.transport_version, frame.max_stream_id);
+
+ if (!writer->WriteVarInt62(stream_count)) {
+ set_detailed_error("Can not write MAX_STREAMS stream count");
return false;
}
return true;
}
-bool QuicFramer::ProcessMaxStreamIdFrame(QuicDataReader* reader,
- QuicMaxStreamIdFrame* frame) {
- if (!reader->ReadVarIntStreamId(&frame->max_stream_id)) {
- set_detailed_error("Can not read MAX_STREAM_ID stream id.");
+bool QuicFramer::ProcessMaxStreamsFrame(QuicDataReader* reader,
+ QuicMaxStreamIdFrame* frame,
+ uint64_t frame_type) {
+ QuicStreamId received_stream_count;
+ if (!reader->ReadVarIntStreamId(&received_stream_count)) {
+ set_detailed_error("Can not read MAX_STREAMS stream count.");
return false;
}
- return true;
+ // TODO(fkastenholz): handle properly when the STREAMS_BLOCKED
+ // frame is implemented and passed up to the stream ID manager.
+ if (received_stream_count == 0) {
+ set_detailed_error("MAX_STREAMS stream count of 0 not supported.");
+ return false;
+ }
+ // Note that this code assumes that the only possible error that
+ // StreamCountToId can detect is that the stream count is too big or is 0.
+ // Too big is prevented by passing in the minimum of the received count
+ // and the maximum supported count, ensuring that the stream ID is
+ // pegged at the maximum allowed ID.
+ // count==0 is handled above, so that detailed_error_ may be set
+ // properly.
+ return StreamCountToId(
+ std::min(
+ received_stream_count,
+ GetMaxStreamCount((frame_type == IETF_MAX_STREAMS_UNIDIRECTIONAL),
+ perspective_)),
+ /*unidirectional=*/(frame_type == IETF_MAX_STREAMS_UNIDIRECTIONAL),
+ perspective_, version_.transport_version, &frame->max_stream_id);
}
bool QuicFramer::AppendIetfBlockedFrame(const QuicBlockedFrame& frame,
@@ -5068,10 +5385,7 @@
bool QuicFramer::ProcessIetfBlockedFrame(QuicDataReader* reader,
QuicBlockedFrame* frame) {
// Indicates that it is a BLOCKED frame (as opposed to STREAM_BLOCKED).
- // TODO(fkastenholz): This should be converted to use
- // QuicUtils::GetInvalidStreamId to get the correct invalid stream id value
- // and not rely on 0.
- frame->stream_id = 0;
+ frame->stream_id = QuicUtils::GetInvalidStreamId(transport_version());
if (!reader->ReadVarInt62(&frame->offset)) {
set_detailed_error("Can not read blocked offset.");
return false;
@@ -5105,23 +5419,58 @@
return true;
}
-bool QuicFramer::AppendStreamIdBlockedFrame(
+bool QuicFramer::AppendStreamsBlockedFrame(
const QuicStreamIdBlockedFrame& frame,
QuicDataWriter* writer) {
- if (!writer->WriteVarInt62(frame.stream_id)) {
- set_detailed_error("Can not write STREAM_ID_BLOCKED stream id");
+ // Convert from the stream id on which the connection is blocked to a count
+ QuicStreamId stream_count =
+ StreamIdToCount(version_.transport_version, frame.stream_id);
+
+ if (!writer->WriteVarInt62(stream_count)) {
+ set_detailed_error("Can not write STREAMS_BLOCKED stream count");
return false;
}
return true;
}
-bool QuicFramer::ProcessStreamIdBlockedFrame(QuicDataReader* reader,
- QuicStreamIdBlockedFrame* frame) {
- if (!reader->ReadVarIntStreamId(&frame->stream_id)) {
- set_detailed_error("Can not read STREAM_ID_BLOCKED stream id.");
+bool QuicFramer::ProcessStreamsBlockedFrame(QuicDataReader* reader,
+ QuicStreamIdBlockedFrame* frame,
+ uint64_t frame_type) {
+ QuicStreamId received_stream_count;
+ if (!reader->ReadVarIntStreamId(&received_stream_count)) {
+ set_detailed_error("Can not read STREAMS_BLOCKED stream id.");
return false;
}
- return true;
+ // TODO(fkastenholz): handle properly when the STREAMS_BLOCKED
+ // frame is implemented and passed up to the stream ID manager.
+ if (received_stream_count == 0) {
+ set_detailed_error("STREAMS_BLOCKED stream count 0 not supported.");
+ return false;
+ }
+ // TODO(fkastenholz): handle properly when the STREAMS_BLOCKED
+ // frame is implemented and passed up to the stream ID manager.
+ if (received_stream_count >
+ GetMaxStreamCount((frame_type == IETF_MAX_STREAMS_UNIDIRECTIONAL),
+ ((perspective_ == Perspective::IS_CLIENT)
+ ? Perspective::IS_SERVER
+ : Perspective::IS_CLIENT))) {
+ // If stream count is such that the resulting stream ID would exceed our
+ // implementation limit, generate an error.
+ set_detailed_error(
+ "STREAMS_BLOCKED stream count exceeds implementation limit.");
+ return false;
+ }
+ // Convert the stream count to an ID that can be used.
+ // The STREAMS_BLOCKED frame is a request for more streams
+ // that the peer will initiate. If this node is a client, it
+ // means that the peer is a server, and wants server-initiated
+ // stream IDs.
+ return StreamCountToId(
+ received_stream_count,
+ /*unidirectional=*/(frame_type == IETF_STREAMS_BLOCKED_UNIDIRECTIONAL),
+ (perspective_ == Perspective::IS_CLIENT) ? Perspective::IS_SERVER
+ : Perspective::IS_CLIENT,
+ version_.transport_version, &frame->stream_id);
}
bool QuicFramer::AppendNewConnectionIdFrame(
@@ -5136,7 +5485,7 @@
"Can not write New Connection ID frame connection ID Length");
return false;
}
- if (!writer->WriteConnectionId(frame.connection_id, perspective_)) {
+ if (!writer->WriteConnectionId(frame.connection_id)) {
set_detailed_error("Can not write New Connection ID frame connection ID");
return false;
}
@@ -5171,8 +5520,7 @@
return false;
}
- if (!reader->ReadConnectionId(&frame->connection_id, connection_id_length,
- perspective_)) {
+ if (!reader->ReadConnectionId(&frame->connection_id, connection_id_length)) {
set_detailed_error("Unable to read new connection ID frame connection id.");
return false;
}
diff --git a/quic/core/quic_framer.h b/quic/core/quic_framer.h
index 46280c5..76d86b8 100644
--- a/quic/core/quic_framer.h
+++ b/quic/core/quic_framer.h
@@ -112,6 +112,16 @@
// If OnPacketHeader returns false, framing for this packet will cease.
virtual bool OnPacketHeader(const QuicPacketHeader& header) = 0;
+ // Called when the packet being processed contains multiple IETF QUIC packets,
+ // which is due to there being more data after what is covered by the length
+ // field. |packet| contains the remaining data which can be processed.
+ // Note that this is called when the framer parses the length field, before
+ // it attempts to decrypt the first payload. It is the visitor's
+ // responsibility to buffer the packet and call ProcessPacket on it
+ // after the framer is done parsing the current payload. |packet| does not
+ // own its internal buffer, the visitor should make a copy of it.
+ virtual void OnCoalescedPacket(const QuicEncryptedPacket& packet) = 0;
+
// Called when a StreamFrame has been parsed.
virtual bool OnStreamFrame(const QuicStreamFrame& frame) = 0;
@@ -304,11 +314,11 @@
// be generated and calculates the appropriate size.
static size_t GetWindowUpdateFrameSize(QuicTransportVersion version,
const QuicWindowUpdateFrame& frame);
- // Size in bytes of all MaxStreamId frame fields.
- static size_t GetMaxStreamIdFrameSize(QuicTransportVersion version,
- const QuicMaxStreamIdFrame& frame);
- // Size in bytes of all StreamIdBlocked frame fields.
- static size_t GetStreamIdBlockedFrameSize(
+ // Size in bytes of all MaxStreams frame fields.
+ static size_t GetMaxStreamsFrameSize(QuicTransportVersion version,
+ const QuicMaxStreamIdFrame& frame);
+ // Size in bytes of all StreamsBlocked frame fields.
+ static size_t GetStreamsBlockedFrameSize(
QuicTransportVersion version,
const QuicStreamIdBlockedFrame& frame);
// Size in bytes of all Blocked frame fields.
@@ -362,7 +372,10 @@
QuicConnectionIdLength source_connection_id_length,
bool includes_version,
bool includes_diversification_nonce,
- QuicPacketNumberLength packet_number_length);
+ QuicPacketNumberLength packet_number_length,
+ QuicVariableLengthIntegerLength retry_token_length_length,
+ uint64_t retry_token_length,
+ QuicVariableLengthIntegerLength length_length);
// Serializes a packet containing |frames| into |buffer|.
// Returns the length of the packet, which must not be longer than
@@ -370,19 +383,22 @@
size_t BuildDataPacket(const QuicPacketHeader& header,
const QuicFrames& frames,
char* buffer,
- size_t packet_length);
+ size_t packet_length,
+ EncryptionLevel level);
// Serializes a probing packet, which is a padded PING packet. Returns the
// length of the packet. Returns 0 if it fails to serialize.
size_t BuildConnectivityProbingPacket(const QuicPacketHeader& header,
char* buffer,
- size_t packet_length);
+ size_t packet_length,
+ EncryptionLevel level);
- // Serializes an IETF probing packet, which is a padded PING packet.
- // Returns the length of the packet. Returns 0 if it fails to serialize.
- size_t BuildIetfConnectivityProbingPacket(const QuicPacketHeader& header,
- char* buffer,
- size_t packet_length);
+ // Serializes a probing packet, which is a padded PING packet. Returns the
+ // length of the packet. Returns 0 if it fails to serialize.
+ size_t BuildConnectivityProbingPacketNew(const QuicPacketHeader& header,
+ char* buffer,
+ size_t packet_length,
+ EncryptionLevel level);
// Serialize a probing packet that uses IETF QUIC's PATH CHALLENGE frame. Also
// fills the packet with padding.
@@ -390,7 +406,8 @@
char* buffer,
size_t packet_length,
QuicPathFrameBuffer* payload,
- QuicRandom* randomizer);
+ QuicRandom* randomizer,
+ EncryptionLevel level);
// Serialize a probing response packet that uses IETF QUIC's PATH RESPONSE
// frame. Also fills the packet with padding if |is_padded| is
@@ -400,7 +417,8 @@
char* buffer,
size_t packet_length,
const QuicDeque<QuicPathFrameBuffer>& payloads,
- const bool is_padded);
+ const bool is_padded,
+ EncryptionLevel level);
// Returns a new public reset packet.
static std::unique_ptr<QuicEncryptedPacket> BuildPublicResetPacket(
@@ -426,17 +444,24 @@
// packet will be set -- but it will be set from version_ not
// header.versions.
bool AppendPacketHeader(const QuicPacketHeader& header,
- QuicDataWriter* writer);
+ QuicDataWriter* writer,
+ size_t* length_field_offset);
bool AppendIetfHeaderTypeByte(const QuicPacketHeader& header,
QuicDataWriter* writer);
bool AppendIetfPacketHeader(const QuicPacketHeader& header,
- QuicDataWriter* writer);
+ QuicDataWriter* writer,
+ size_t* length_field_offset);
+ bool WriteIetfLongHeaderLength(const QuicPacketHeader& header,
+ QuicDataWriter* writer,
+ size_t length_field_offset,
+ EncryptionLevel level);
bool AppendTypeByte(const QuicFrame& frame,
bool last_frame_in_packet,
QuicDataWriter* writer);
bool AppendIetfTypeByte(const QuicFrame& frame,
bool last_frame_in_packet,
QuicDataWriter* writer);
+ size_t AppendIetfFrames(const QuicFrames& frames, QuicDataWriter* writer);
bool AppendStreamFrame(const QuicStreamFrame& frame,
bool last_frame_in_packet,
QuicDataWriter* writer);
@@ -485,6 +510,10 @@
char* buffer,
size_t buffer_len);
+ // Returns the length of the ciphertext that would be generated by encrypting
+ // to plaintext of size |plaintext_size| at the given level.
+ size_t GetCiphertextSize(EncryptionLevel level, size_t plaintext_size) const;
+
// Returns the maximum length of plaintext that can be encrypted
// to ciphertext no larger than |ciphertext_size|.
size_t GetMaxPlaintextSize(size_t ciphertext_size);
@@ -507,28 +536,15 @@
// Returns true if data with |offset| of stream |id| starts with 'CHLO'.
bool StartsWithChlo(QuicStreamId id, QuicStreamOffset offset) const;
- // Returns byte order to read/write integers and floating numbers.
- Endianness endianness() const;
-
// Returns true if |header| is considered as an stateless reset packet.
bool IsIetfStatelessResetPacket(const QuicPacketHeader& header) const;
- // Returns header wire format of last received packet.
- // Please do not use this method.
- // TODO(fayang): Remove last_header_form_ when deprecating
- // quic_fix_last_packet_is_ietf_quic flag.
- PacketHeaderFormat GetLastPacketFormat() const;
-
void set_validate_flags(bool value) { validate_flags_ = value; }
Perspective perspective() const { return perspective_; }
QuicVersionLabel last_version_label() const { return last_version_label_; }
- void set_last_packet_form(PacketHeaderFormat form) {
- last_header_form_ = form;
- }
-
void set_data_producer(QuicStreamFrameDataProducer* data_producer) {
data_producer_ = data_producer;
}
@@ -566,12 +582,6 @@
size_t num_ack_blocks;
};
- // The same as BuildDataPacket, but it only builds IETF-format packets.
- size_t BuildIetfDataPacket(const QuicPacketHeader& header,
- const QuicFrames& frames,
- char* buffer,
- size_t packet_length);
-
bool ProcessDataPacket(QuicDataReader* reader,
QuicPacketHeader* header,
const QuicEncryptedPacket& packet,
@@ -590,6 +600,16 @@
bool ProcessVersionNegotiationPacket(QuicDataReader* reader,
const QuicPacketHeader& header);
+ bool MaybeProcessIetfInitialRetryToken(QuicDataReader* encrypted_reader,
+ QuicPacketHeader* header);
+
+ void MaybeProcessCoalescedPacket(const QuicDataReader& encrypted_reader,
+ uint64_t remaining_bytes_length,
+ const QuicPacketHeader& header);
+
+ bool MaybeProcessIetfLength(QuicDataReader* encrypted_reader,
+ QuicPacketHeader* header);
+
bool ProcessPublicHeader(QuicDataReader* reader,
bool last_packet_is_ietf_quic,
QuicPacketHeader* header);
@@ -640,9 +660,9 @@
bool no_message_length,
QuicMessageFrame* frame);
- bool DecryptPayload(QuicDataReader* encrypted_reader,
+ bool DecryptPayload(QuicStringPiece encrypted,
+ QuicStringPiece associated_data,
const QuicPacketHeader& header,
- const QuicEncryptedPacket& packet,
char* decrypted_buffer,
size_t buffer_length,
size_t* decrypted_length);
@@ -703,8 +723,7 @@
QuicConnectionIdLength destination_connection_id_length,
QuicConnectionId source_connection_id,
QuicConnectionIdLength source_connection_id_length,
- QuicDataWriter* writer,
- Perspective perspective);
+ QuicDataWriter* writer);
// The Append* methods attempt to write the provided header or frame using the
// |writer|, and return true if successful.
@@ -789,10 +808,11 @@
bool ProcessMaxStreamDataFrame(QuicDataReader* reader,
QuicWindowUpdateFrame* frame);
- bool AppendMaxStreamIdFrame(const QuicMaxStreamIdFrame& frame,
- QuicDataWriter* writer);
- bool ProcessMaxStreamIdFrame(QuicDataReader* reader,
- QuicMaxStreamIdFrame* frame);
+ bool AppendMaxStreamsFrame(const QuicMaxStreamIdFrame& frame,
+ QuicDataWriter* writer);
+ bool ProcessMaxStreamsFrame(QuicDataReader* reader,
+ QuicMaxStreamIdFrame* frame,
+ uint64_t frame_type);
bool AppendIetfBlockedFrame(const QuicBlockedFrame& frame,
QuicDataWriter* writer);
@@ -803,10 +823,12 @@
bool ProcessStreamBlockedFrame(QuicDataReader* reader,
QuicBlockedFrame* frame);
- bool AppendStreamIdBlockedFrame(const QuicStreamIdBlockedFrame& frame,
- QuicDataWriter* writer);
- bool ProcessStreamIdBlockedFrame(QuicDataReader* reader,
- QuicStreamIdBlockedFrame* frame);
+ bool AppendStreamsBlockedFrame(const QuicStreamIdBlockedFrame& frame,
+ QuicDataWriter* writer);
+ bool ProcessStreamsBlockedFrame(QuicDataReader* reader,
+ QuicStreamIdBlockedFrame* frame,
+ uint64_t frame_type);
+
bool AppendNewConnectionIdFrame(const QuicNewConnectionIdFrame& frame,
QuicDataWriter* writer);
bool ProcessNewConnectionIdFrame(QuicDataReader* reader,
@@ -845,9 +867,6 @@
QuicConnectionId last_serialized_connection_id_;
// The last QUIC version label received.
QuicVersionLabel last_version_label_;
- // Format of last received packet header, whether it is Google QUIC, IETF long
- // header packet or IETF short header packet.
- PacketHeaderFormat last_header_form_;
// Version of the protocol being used.
ParsedQuicVersion version_;
// This vector contains QUIC versions which we currently support.
diff --git a/quic/core/quic_framer_test.cc b/quic/core/quic_framer_test.cc
index 888c87e..c674896 100644
--- a/quic/core/quic_framer_test.cc
+++ b/quic/core/quic_framer_test.cc
@@ -24,6 +24,7 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_framer_peer.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/simple_data_producer.h"
@@ -83,14 +84,12 @@
bool SetKey(QuicStringPiece key) override { return true; }
bool SetNoncePrefix(QuicStringPiece nonce_prefix) override { return true; }
bool SetIV(QuicStringPiece iv) override { return true; }
- bool EncryptPacket(QuicTransportVersion version,
- uint64_t packet_number,
+ bool EncryptPacket(uint64_t packet_number,
QuicStringPiece associated_data,
QuicStringPiece plaintext,
char* output,
size_t* output_length,
size_t max_output_length) override {
- version_ = version;
packet_number_ = QuicPacketNumber(packet_number);
associated_data_ = QuicString(associated_data);
plaintext_ = QuicString(plaintext);
@@ -110,7 +109,6 @@
QuicStringPiece GetKey() const override { return QuicStringPiece(); }
QuicStringPiece GetNoncePrefix() const override { return QuicStringPiece(); }
- QuicTransportVersion version_;
QuicPacketNumber packet_number_;
QuicString associated_data_;
QuicString plaintext_;
@@ -129,14 +127,12 @@
bool SetDiversificationNonce(const DiversificationNonce& key) override {
return true;
}
- bool DecryptPacket(QuicTransportVersion version,
- uint64_t packet_number,
+ bool DecryptPacket(uint64_t packet_number,
QuicStringPiece associated_data,
QuicStringPiece ciphertext,
char* output,
size_t* output_length,
size_t max_output_length) override {
- version_ = version;
packet_number_ = QuicPacketNumber(packet_number);
associated_data_ = QuicString(associated_data);
ciphertext_ = QuicString(ciphertext);
@@ -150,7 +146,6 @@
QuicStringPiece GetNoncePrefix() const override { return QuicStringPiece(); }
// Use a distinct value starting with 0xFFFFFF, which is never used by TLS.
uint32_t cipher_id() const override { return 0xFFFFFFF2; }
- QuicTransportVersion version_;
QuicPacketNumber packet_number_;
QuicString associated_data_;
QuicString ciphertext_;
@@ -212,6 +207,15 @@
return accept_packet_;
}
+ void OnCoalescedPacket(const QuicEncryptedPacket& packet) override {
+ size_t coalesced_data_length = packet.length();
+ char* coalesced_data = new char[coalesced_data_length];
+ memcpy(coalesced_data, packet.data(), coalesced_data_length);
+ coalesced_packets_.push_back(QuicMakeUnique<QuicEncryptedPacket>(
+ coalesced_data, coalesced_data_length,
+ /*owns_buffer=*/true));
+ }
+
bool OnStreamFrame(const QuicStreamFrame& frame) override {
++frame_count_;
// Save a copy of the data so it is valid after the packet is processed.
@@ -278,7 +282,8 @@
bool OnMessageFrame(const QuicMessageFrame& frame) override {
++frame_count_;
- message_frames_.push_back(QuicMakeUnique<QuicMessageFrame>(frame));
+ message_frames_.push_back(
+ QuicMakeUnique<QuicMessageFrame>(frame.data, frame.message_length));
return true;
}
@@ -386,6 +391,7 @@
std::vector<std::unique_ptr<QuicPaddingFrame>> padding_frames_;
std::vector<std::unique_ptr<QuicPingFrame>> ping_frames_;
std::vector<std::unique_ptr<QuicMessageFrame>> message_frames_;
+ std::vector<std::unique_ptr<QuicEncryptedPacket>> coalesced_packets_;
QuicRstStreamFrame rst_stream_frame_;
QuicConnectionCloseFrame connection_close_frame_;
QuicApplicationCloseFrame application_close_frame_;
@@ -459,7 +465,6 @@
}
bool CheckEncryption(QuicPacketNumber packet_number, QuicPacket* packet) {
- EXPECT_EQ(version_.transport_version, encrypter_->version_);
if (packet_number != encrypter_->packet_number_) {
QUIC_LOG(ERROR) << "Encrypted incorrect packet number. expected "
<< packet_number
@@ -488,36 +493,53 @@
bool includes_diversification_nonce,
QuicConnectionIdLength destination_connection_id_length,
QuicConnectionIdLength source_connection_id_length) {
- EXPECT_EQ(version_.transport_version, decrypter_->version_);
+ return CheckDecryption(
+ encrypted, includes_version, includes_diversification_nonce,
+ destination_connection_id_length, source_connection_id_length,
+ VARIABLE_LENGTH_INTEGER_LENGTH_0, 0, VARIABLE_LENGTH_INTEGER_LENGTH_0);
+ }
+
+ bool CheckDecryption(
+ const QuicEncryptedPacket& encrypted,
+ bool includes_version,
+ bool includes_diversification_nonce,
+ QuicConnectionIdLength destination_connection_id_length,
+ QuicConnectionIdLength source_connection_id_length,
+ QuicVariableLengthIntegerLength retry_token_length_length,
+ size_t retry_token_length,
+ QuicVariableLengthIntegerLength length_length) {
if (visitor_.header_->packet_number != decrypter_->packet_number_) {
QUIC_LOG(ERROR) << "Decrypted incorrect packet number. expected "
<< visitor_.header_->packet_number
<< " actual: " << decrypter_->packet_number_;
return false;
}
- if (QuicFramer::GetAssociatedDataFromEncryptedPacket(
+ QuicStringPiece associated_data =
+ QuicFramer::GetAssociatedDataFromEncryptedPacket(
framer_.transport_version(), encrypted,
destination_connection_id_length, source_connection_id_length,
includes_version, includes_diversification_nonce,
- PACKET_4BYTE_PACKET_NUMBER) != decrypter_->associated_data_) {
+ PACKET_4BYTE_PACKET_NUMBER, retry_token_length_length,
+ retry_token_length, length_length);
+ if (associated_data != decrypter_->associated_data_) {
QUIC_LOG(ERROR) << "Decrypted incorrect associated data. expected "
- << QuicFramer::GetAssociatedDataFromEncryptedPacket(
- framer_.transport_version(), encrypted,
- destination_connection_id_length,
- source_connection_id_length, includes_version,
- includes_diversification_nonce,
- PACKET_4BYTE_PACKET_NUMBER)
- << " actual: " << decrypter_->associated_data_;
+ << QuicTextUtils::HexEncode(associated_data)
+ << " actual: "
+ << QuicTextUtils::HexEncode(decrypter_->associated_data_);
return false;
}
QuicStringPiece ciphertext(
encrypted.AsStringPiece().substr(GetStartOfEncryptedData(
framer_.transport_version(), destination_connection_id_length,
source_connection_id_length, includes_version,
- includes_diversification_nonce, PACKET_4BYTE_PACKET_NUMBER)));
+ includes_diversification_nonce, PACKET_4BYTE_PACKET_NUMBER,
+ retry_token_length_length, retry_token_length, length_length)));
if (ciphertext != decrypter_->ciphertext_) {
QUIC_LOG(ERROR) << "Decrypted incorrect ciphertext data. expected "
- << ciphertext << " actual: " << decrypter_->ciphertext_;
+ << QuicTextUtils::HexEncode(ciphertext) << " actual: "
+ << QuicTextUtils::HexEncode(decrypter_->ciphertext_)
+ << " associated data: "
+ << QuicTextUtils::HexEncode(associated_data);
return false;
}
return true;
@@ -609,12 +631,29 @@
return BuildUnsizedDataPacket(&framer_, header, frames, packet_size);
}
+ // N starts at 1.
+ QuicStreamId GetNthStreamid(QuicTransportVersion transport_version,
+ Perspective perspective,
+ bool bidirectional,
+ int n) {
+ if (bidirectional) {
+ return QuicUtils::GetFirstBidirectionalStreamId(transport_version,
+ perspective) +
+ ((n - 1) * QuicUtils::StreamIdDelta(transport_version));
+ }
+ // Unidirectional
+ return QuicUtils::GetFirstUnidirectionalStreamId(transport_version,
+ perspective) +
+ ((n - 1) * QuicUtils::StreamIdDelta(transport_version));
+ }
+
test::TestEncrypter* encrypter_;
test::TestDecrypter* decrypter_;
ParsedQuicVersion version_;
QuicTime start_;
QuicFramer framer_;
test::TestQuicVisitor visitor_;
+ SimpleBufferAllocator allocator_;
};
// Multiple test cases of QuicFramerTest use byte arrays to define packets for
@@ -626,7 +665,7 @@
GetQuicVersionDigitOnes()
// Run all framer tests with all supported versions of QUIC.
-INSTANTIATE_TEST_CASE_P(
+INSTANTIATE_TEST_SUITE_P(
QuicFramerTests,
QuicFramerTest,
::testing::ValuesIn(AllSupportedVersionsIncludingTls()));
@@ -764,7 +803,7 @@
// packet number
0x78, 0x56, 0x34, 0x12,
};
- unsigned char packet47[kMaxPacketSize + 1] = {
+ unsigned char packet46[kMaxPacketSize + 1] = {
// type (short header 4 byte packet number)
0x43,
// connection_id
@@ -775,9 +814,9 @@
// clang-format on
unsigned char* p = packet;
size_t p_size = QUIC_ARRAYSIZE(packet);
- if (framer_.transport_version() > QUIC_VERSION_46) {
- p = packet47;
- p_size = QUIC_ARRAYSIZE(packet47);
+ if (framer_.transport_version() > QUIC_VERSION_44) {
+ p = packet46;
+ p_size = QUIC_ARRAYSIZE(packet46);
} else if (framer_.transport_version() > QUIC_VERSION_43) {
p = packet44;
p_size = QUIC_ARRAYSIZE(packet44);
@@ -786,7 +825,8 @@
const size_t header_size = GetPacketHeaderSize(
framer_.transport_version(), PACKET_8BYTE_CONNECTION_ID,
PACKET_0BYTE_CONNECTION_ID, !kIncludeVersion,
- !kIncludeDiversificationNonce, PACKET_4BYTE_PACKET_NUMBER);
+ !kIncludeDiversificationNonce, PACKET_4BYTE_PACKET_NUMBER,
+ VARIABLE_LENGTH_INTEGER_LENGTH_0, 0, VARIABLE_LENGTH_INTEGER_LENGTH_0);
memset(p + header_size, 0, kMaxPacketSize - header_size);
@@ -802,20 +842,12 @@
}
TEST_P(QuicFramerTest, PacketHeader) {
- // clang-format off
- PacketFragments packet38 = {
- // public flags (8 byte connection_id)
- {"Unable to read public flags.",
- {0x28}},
- // connection_id
- {"Unable to read ConnectionId.",
- {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
- // packet number
- {"Unable to read packet number.",
- {0x78, 0x56, 0x34, 0x12}},
- };
+ if (framer_.transport_version() > QUIC_VERSION_43) {
+ return;
+ }
- PacketFragments packet39 = {
+ // clang-format off
+ PacketFragments packet = {
// public flags (8 byte connection_id)
{"Unable to read public flags.",
{0x28}},
@@ -828,12 +860,7 @@
};
// clang-format on
- if (framer_.transport_version() > QUIC_VERSION_43) {
- return;
- }
-
- PacketFragments& fragments =
- framer_.transport_version() == QUIC_VERSION_35 ? packet38 : packet39;
+ PacketFragments& fragments = packet;
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
@@ -869,7 +896,7 @@
{"Unable to read packet number.",
{0x12, 0x34, 0x56, 0x78}},
};
- PacketFragments packet47 = {
+ PacketFragments packet46 = {
// type (long header with packet type INITIAL)
{"Unable to read type.",
{0xC3}},
@@ -888,12 +915,13 @@
};
// clang-format on
- if (framer_.transport_version() <= QUIC_VERSION_43) {
+ if (framer_.transport_version() <= QUIC_VERSION_43 ||
+ QuicVersionHasLongHeaderLengths(framer_.transport_version())) {
return;
}
PacketFragments& fragments =
- framer_.transport_version() > QUIC_VERSION_46 ? packet47 : packet44;
+ framer_.transport_version() > QUIC_VERSION_44 ? packet46 : packet44;
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
@@ -907,7 +935,7 @@
EXPECT_EQ(kPacketNumber, visitor_.header_->packet_number);
CheckFramingBoundaries(
- framer_.transport_version() > QUIC_VERSION_46 ? packet47 : packet44,
+ framer_.transport_version() > QUIC_VERSION_44 ? packet46 : packet44,
QUIC_INVALID_PACKET_HEADER);
}
@@ -924,16 +952,6 @@
// connection_id
// packet number
{"Unable to read packet number.",
- {0x78, 0x56, 0x34, 0x12}}
- };
-
- PacketFragments packet39 = {
- // public flags (0 byte connection_id)
- {"Unable to read public flags.",
- {0x20}},
- // connection_id
- // packet number
- {"Unable to read packet number.",
{0x12, 0x34, 0x56, 0x78}},
};
@@ -947,7 +965,7 @@
{0x12, 0x34, 0x56, 0x78}},
};
- PacketFragments packet47 = {
+ PacketFragments packet46 = {
// type (short header, 4 byte packet number)
{"Unable to read type.",
{0x43}},
@@ -959,12 +977,9 @@
// clang-format on
PacketFragments& fragments =
- framer_.transport_version() > QUIC_VERSION_46
- ? packet47
- : (framer_.transport_version() > QUIC_VERSION_43
- ? packet44
- : (framer_.transport_version() == QUIC_VERSION_35 ? packet
- : packet39));
+ framer_.transport_version() > QUIC_VERSION_44
+ ? packet46
+ : (framer_.transport_version() > QUIC_VERSION_43 ? packet44 : packet);
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
@@ -993,21 +1008,6 @@
{QUIC_VERSION_BYTES}},
// packet number
{"Unable to read packet number.",
- {0x78, 0x56, 0x34, 0x12}},
- };
-
- PacketFragments packet39 = {
- // public flags (0 byte connection_id)
- {"Unable to read public flags.",
- {0x29}},
- // connection_id
- {"Unable to read ConnectionId.",
- {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
- // version tag
- {"Unable to read protocol version.",
- {QUIC_VERSION_BYTES}},
- // packet number
- {"Unable to read packet number.",
{0x12, 0x34, 0x56, 0x78}},
};
@@ -1029,7 +1029,7 @@
{0x12, 0x34, 0x56, 0x78}},
};
- PacketFragments packet47 = {
+ PacketFragments packet46 = {
// type (long header with packet type ZERO_RTT_PROTECTED and 4 bytes
// packet number)
{"Unable to read type.",
@@ -1047,15 +1047,37 @@
{"Unable to read packet number.",
{0x12, 0x34, 0x56, 0x78}},
};
+
+ PacketFragments packet99 = {
+ // type (long header with packet type ZERO_RTT_PROTECTED and 4 bytes
+ // packet number)
+ {"Unable to read type.",
+ {0xD3}},
+ // version tag
+ {"Unable to read protocol version.",
+ {QUIC_VERSION_BYTES}},
+ // connection_id length
+ {"Unable to read ConnectionId length.",
+ {0x50}},
+ // connection_id
+ {"Unable to read Destination ConnectionId.",
+ {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
+ // long header packet length
+ {"Unable to read long header payload length.",
+ {0x04}},
+ // packet number
+ {"Long header payload length longer than packet.",
+ {0x12, 0x34, 0x56, 0x78}},
+ };
// clang-format on
PacketFragments& fragments =
- framer_.transport_version() > QUIC_VERSION_46
- ? packet47
- : (framer_.transport_version() > QUIC_VERSION_43
- ? packet44
- : (framer_.transport_version() == QUIC_VERSION_35 ? packet
- : packet39));
+ framer_.transport_version() == QUIC_VERSION_99
+ ? packet99
+ : framer_.transport_version() > QUIC_VERSION_44
+ ? packet46
+ : (framer_.transport_version() > QUIC_VERSION_43 ? packet44
+ : packet);
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
@@ -1084,18 +1106,6 @@
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"Unable to read packet number.",
- {0x78, 0x56, 0x34, 0x12}},
- };
-
- PacketFragments packet39 = {
- // public flags (8 byte connection_id and 4 byte packet number)
- {"Unable to read public flags.",
- {0x28}},
- // connection_id
- {"Unable to read ConnectionId.",
- {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
- // packet number
- {"Unable to read packet number.",
{0x12, 0x34, 0x56, 0x78}},
};
@@ -1111,7 +1121,7 @@
{0x12, 0x34, 0x56, 0x78}},
};
- PacketFragments packet47 = {
+ PacketFragments packet46 = {
// type (short header, 4 byte packet number)
{"Unable to read type.",
{0x43}},
@@ -1125,12 +1135,9 @@
// clang-format on
PacketFragments& fragments =
- framer_.transport_version() > QUIC_VERSION_46
- ? packet47
- : (framer_.transport_version() > QUIC_VERSION_43
- ? packet44
- : (framer_.transport_version() == QUIC_VERSION_35 ? packet
- : packet39));
+ framer_.transport_version() > QUIC_VERSION_44
+ ? packet46
+ : (framer_.transport_version() > QUIC_VERSION_43 ? packet44 : packet);
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
@@ -1158,18 +1165,6 @@
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"Unable to read packet number.",
- {0x78, 0x56}},
- };
-
- PacketFragments packet39 = {
- // public flags (8 byte connection_id and 2 byte packet number)
- {"Unable to read public flags.",
- {0x18}},
- // connection_id
- {"Unable to read ConnectionId.",
- {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
- // packet number
- {"Unable to read packet number.",
{0x56, 0x78}},
};
@@ -1185,7 +1180,7 @@
{0x56, 0x78}},
};
- PacketFragments packet47 = {
+ PacketFragments packet46 = {
// type (short header, 2 byte packet number)
{"Unable to read type.",
{0x41}},
@@ -1199,12 +1194,9 @@
// clang-format on
PacketFragments& fragments =
- framer_.transport_version() > QUIC_VERSION_46
- ? packet47
- : (framer_.transport_version() > QUIC_VERSION_43
- ? packet44
- : (framer_.transport_version() == QUIC_VERSION_35 ? packet
- : packet39));
+ framer_.transport_version() > QUIC_VERSION_44
+ ? packet46
+ : (framer_.transport_version() > QUIC_VERSION_43 ? packet44 : packet);
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
@@ -1248,7 +1240,7 @@
{0x78}},
};
- PacketFragments packet47 = {
+ PacketFragments packet46 = {
// type (8 byte connection_id and 1 byte packet number)
{"Unable to read type.",
{0x40}},
@@ -1263,8 +1255,8 @@
// clang-format on
PacketFragments& fragments =
- framer_.transport_version() > QUIC_VERSION_46
- ? packet47
+ framer_.transport_version() > QUIC_VERSION_44
+ ? packet46
: (framer_.transport_version() > QUIC_VERSION_43 ? packet44 : packet);
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
@@ -1360,24 +1352,6 @@
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
// packet number
- 0x78, 0x56, 0x34, 0x12,
-
- // frame type (padding)
- 0x00,
- 0x00, 0x00, 0x00, 0x00
- };
-
- unsigned char packet39[] = {
- // public flags: includes nonce flag
- 0x2C,
- // connection_id
- 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
- // nonce
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
- 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
- // packet number
0x12, 0x34, 0x56, 0x78,
// frame type (padding)
@@ -1407,7 +1381,7 @@
0x00, 0x00, 0x00, 0x00
};
- unsigned char packet47[] = {
+ unsigned char packet46[] = {
// type: Long header with packet type ZERO_RTT_PROTECTED and 1 byte packet
// number.
0xD0,
@@ -1429,18 +1403,48 @@
0x00,
0x00, 0x00, 0x00, 0x00
};
+
+ unsigned char packet99[] = {
+ // type: Long header with packet type ZERO_RTT_PROTECTED and 1 byte packet
+ // number.
+ 0xD0,
+ // version tag
+ QUIC_VERSION_BYTES,
+ // connection_id length
+ 0x05,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // long header packet length
+ 0x26,
+ // packet number
+ 0x78,
+ // nonce
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+
+ // frame type (padding)
+ 0x00,
+ 0x00, 0x00, 0x00, 0x00
+ };
// clang-format on
+ if (framer_.version().handshake_protocol != PROTOCOL_QUIC_CRYPTO) {
+ return;
+ }
+
unsigned char* p = packet;
size_t p_size = QUIC_ARRAYSIZE(packet);
- if (framer_.transport_version() > QUIC_VERSION_46) {
- p = packet47;
- p_size = QUIC_ARRAYSIZE(packet47);
+ if (framer_.transport_version() == QUIC_VERSION_99) {
+ p = packet99;
+ p_size = QUIC_ARRAYSIZE(packet99);
+ } else if (framer_.transport_version() > QUIC_VERSION_44) {
+ p = packet46;
+ p_size = QUIC_ARRAYSIZE(packet46);
} else if (framer_.transport_version() > QUIC_VERSION_43) {
p = packet44;
p_size = QUIC_ARRAYSIZE(packet44);
- } else if (framer_.transport_version() != QUIC_VERSION_35) {
- p = packet39;
}
QuicEncryptedPacket encrypted(AsChars(p), p_size, false);
@@ -1452,7 +1456,7 @@
}
EXPECT_EQ(1u, visitor_.padding_frames_.size());
EXPECT_EQ(5, visitor_.padding_frames_[0]->num_padding_bytes);
-};
+}
TEST_P(QuicFramerTest, LargePublicFlagWithMismatchedVersions) {
// clang-format off
@@ -1464,21 +1468,6 @@
// version tag
'Q', '0', '0', '0',
// packet number
- 0x78, 0x56, 0x34, 0x12,
-
- // frame type (padding frame)
- 0x00,
- 0x00, 0x00, 0x00, 0x00
- };
-
- unsigned char packet39[] = {
- // public flags (8 byte connection_id, version flag and an unknown flag)
- 0x29,
- // connection_id
- 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
- // version tag
- 'Q', '0', '0', '0',
- // packet number
0x12, 0x34, 0x56, 0x78,
// frame type (padding frame)
@@ -1505,11 +1494,8 @@
// clang-format on
QuicEncryptedPacket encrypted(
- AsChars(framer_.transport_version() > QUIC_VERSION_43
- ? packet44
- : (framer_.transport_version() == QUIC_VERSION_35
- ? packet
- : packet39)),
+ AsChars(framer_.transport_version() > QUIC_VERSION_43 ? packet44
+ : packet),
framer_.transport_version() > QUIC_VERSION_43 ? QUIC_ARRAYSIZE(packet44)
: QUIC_ARRAYSIZE(packet),
false);
@@ -1520,7 +1506,7 @@
EXPECT_EQ(1, visitor_.version_mismatch_);
EXPECT_EQ(1u, visitor_.padding_frames_.size());
EXPECT_EQ(5, visitor_.padding_frames_[0]->num_padding_bytes);
-};
+}
TEST_P(QuicFramerTest, PaddingFrame) {
// clang-format off
@@ -1530,88 +1516,6 @@
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
- 0x78, 0x56, 0x34, 0x12,
-
- // frame type (padding frame)
- 0x00,
- // Ignored data (which in this case is a stream frame)
- // frame type (stream frame with fin)
- 0xFF,
- // stream id
- 0x04, 0x03, 0x02, 0x01,
- // offset
- 0x54, 0x76, 0x10, 0x32,
- 0xDC, 0xFE, 0x98, 0x3A,
- // data length
- 0x0c, 0x00,
- // data
- 'h', 'e', 'l', 'l',
- 'o', ' ', 'w', 'o',
- 'r', 'l', 'd', '!',
- };
- // clang-format on
-
- if (framer_.transport_version() != QUIC_VERSION_35) {
- return;
- }
-
- QuicEncryptedPacket encrypted(AsChars(packet), QUIC_ARRAYSIZE(packet), false);
- EXPECT_TRUE(framer_.ProcessPacket(encrypted));
- EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
- ASSERT_TRUE(visitor_.header_.get());
- EXPECT_TRUE(CheckDecryption(
- encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
- PACKET_8BYTE_CONNECTION_ID, PACKET_0BYTE_CONNECTION_ID));
-
- ASSERT_EQ(0u, visitor_.stream_frames_.size());
- EXPECT_EQ(0u, visitor_.ack_frames_.size());
- EXPECT_EQ(1u, visitor_.padding_frames_.size());
- EXPECT_EQ(28, visitor_.padding_frames_[0]->num_padding_bytes);
- // A packet with no frames is not acceptable.
- CheckProcessingFails(
- packet,
- GetPacketHeaderSize(
- framer_.transport_version(), PACKET_8BYTE_CONNECTION_ID,
- PACKET_0BYTE_CONNECTION_ID, !kIncludeVersion,
- !kIncludeDiversificationNonce, PACKET_4BYTE_PACKET_NUMBER),
- "Packet has no frames.", QUIC_MISSING_PAYLOAD);
-}
-
-TEST_P(QuicFramerTest, NewPaddingFrame) {
- // clang-format off
- unsigned char packet[] = {
- // public flags (8 byte connection_id)
- 0x28,
- // connection_id
- 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
- // packet number
- 0x78, 0x56, 0x34, 0x12,
-
- // paddings
- 0x00, 0x00,
- // frame type (stream frame with fin)
- 0xFF,
- // stream id
- 0x04, 0x03, 0x02, 0x01,
- // offset
- 0x54, 0x76, 0x10, 0x32,
- 0xDC, 0xFE, 0x98, 0x3A,
- // data length
- 0x0c, 0x00,
- // data
- 'h', 'e', 'l', 'l',
- 'o', ' ', 'w', 'o',
- 'r', 'l', 'd', '!',
- // paddings
- 0x00, 0x00,
- };
-
- unsigned char packet39[] = {
- // public flags (8 byte connection_id)
- 0x28,
- // connection_id
- 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
- // packet number
0x12, 0x34, 0x56, 0x78,
// paddings
@@ -1660,7 +1564,7 @@
0x00, 0x00,
};
- unsigned char packet47[] = {
+ unsigned char packet46[] = {
// type (short header, 4 byte packet number)
0x43,
// connection_id
@@ -1716,22 +1620,17 @@
};
// clang-format on
- if (framer_.transport_version() == QUIC_VERSION_35) {
- return;
- }
unsigned char* p = packet;
size_t p_size = QUIC_ARRAYSIZE(packet);
if (framer_.transport_version() == QUIC_VERSION_99) {
p = packet99;
p_size = QUIC_ARRAYSIZE(packet99);
- } else if (framer_.transport_version() > QUIC_VERSION_46) {
- p = packet47;
- p_size = QUIC_ARRAYSIZE(packet47);
+ } else if (framer_.transport_version() > QUIC_VERSION_44) {
+ p = packet46;
+ p_size = QUIC_ARRAYSIZE(packet46);
} else if (framer_.transport_version() > QUIC_VERSION_43) {
p = packet44;
p_size = QUIC_ARRAYSIZE(packet44);
- } else if (framer_.transport_version() != QUIC_VERSION_35) {
- p = packet39;
}
QuicEncryptedPacket encrypted(AsChars(p), p_size, false);
@@ -1764,36 +1663,6 @@
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
- {0x78, 0x56, 0x34, 0x12}},
- // frame type (stream frame with fin)
- {"",
- {0xFF}},
- // stream id
- {"Unable to read stream_id.",
- {0x04, 0x03, 0x02, 0x01}},
- // offset
- {"Unable to read offset.",
- {0x54, 0x76, 0x10, 0x32,
- 0xDC, 0xFE, 0x98, 0x3A}},
- {"Unable to read frame data.",
- {
- // data length
- 0x0c, 0x00,
- // data
- 'h', 'e', 'l', 'l',
- 'o', ' ', 'w', 'o',
- 'r', 'l', 'd', '!'}},
- };
-
- PacketFragments packet39 = {
- // public flags (8 byte connection_id)
- {"",
- {0x28}},
- // connection_id
- {"",
- {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
- // packet number
- {"",
{0x12, 0x34, 0x56, 0x78}},
// frame type (stream frame with fin)
{"",
@@ -1845,7 +1714,7 @@
'r', 'l', 'd', '!'}},
};
- PacketFragments packet47 = {
+ PacketFragments packet46 = {
// type (short header, 4 byte packet number)
{"",
{0x43}},
@@ -1909,13 +1778,10 @@
PacketFragments& fragments =
framer_.transport_version() == QUIC_VERSION_99
? packet99
- : (framer_.transport_version() > QUIC_VERSION_46
- ? packet47
- : (framer_.transport_version() > QUIC_VERSION_43
- ? packet44
- : (framer_.transport_version() != QUIC_VERSION_35
- ? packet39
- : packet)));
+ : (framer_.transport_version() > QUIC_VERSION_44
+ ? packet46
+ : (framer_.transport_version() > QUIC_VERSION_43 ? packet44
+ : packet));
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
@@ -1996,33 +1862,10 @@
QuicMakeUnique<NullDecrypter>(Perspective::IS_CLIENT));
decrypter_ = new test::TestDecrypter();
framer_.SetAlternativeDecrypter(
- ENCRYPTION_INITIAL, std::unique_ptr<QuicDecrypter>(decrypter_), false);
+ ENCRYPTION_ZERO_RTT, std::unique_ptr<QuicDecrypter>(decrypter_), false);
// clang-format off
unsigned char packet[] = {
- // public flags (8 byte connection_id)
- 0x28,
- // connection_id
- 0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
- // packet number
- 0x78, 0x56, 0x34, 0x12,
-
- // frame type (stream frame with fin)
- 0xFF,
- // stream id
- 0x04, 0x03, 0x02, 0x01,
- // offset
- 0x54, 0x76, 0x10, 0x32,
- 0xDC, 0xFE, 0x98, 0x3A,
- // data length
- 0x0c, 0x00,
- // data
- 'h', 'e', 'l', 'l',
- 'o', ' ', 'w', 'o',
- 'r', 'l', 'd', '!',
- };
-
- unsigned char packet39[] = {
// public flags (8 byte connection_id)
0x28,
// connection_id
@@ -2076,8 +1919,6 @@
unsigned char* p = packet;
if (framer_.transport_version() > QUIC_VERSION_43) {
p = packet44;
- } else if (framer_.transport_version() != QUIC_VERSION_35) {
- p = packet39;
}
QuicEncryptedPacket encrypted(AsChars(p),
framer_.transport_version() > QUIC_VERSION_43
@@ -2108,36 +1949,6 @@
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
- {0x78, 0x56, 0x34, 0x12}},
- // frame type (stream frame with fin)
- {"",
- {0xFE}},
- // stream id
- {"Unable to read stream_id.",
- {0x04, 0x03, 0x02}},
- // offset
- {"Unable to read offset.",
- {0x54, 0x76, 0x10, 0x32,
- 0xDC, 0xFE, 0x98, 0x3A}},
- {"Unable to read frame data.",
- {
- // data length
- 0x0c, 0x00,
- // data
- 'h', 'e', 'l', 'l',
- 'o', ' ', 'w', 'o',
- 'r', 'l', 'd', '!'}},
- };
-
- PacketFragments packet39 = {
- // public flags (8 byte connection_id)
- {"",
- {0x28}},
- // connection_id
- {"",
- {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
- // packet number
- {"",
{0x12, 0x34, 0x56, 0x78}},
// frame type (stream frame with fin)
{"",
@@ -2160,8 +1971,7 @@
};
// clang-format on
- PacketFragments& fragments =
- framer_.transport_version() != QUIC_VERSION_35 ? packet39 : packet;
+ PacketFragments& fragments = packet;
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
@@ -2194,36 +2004,6 @@
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
- {0x78, 0x56, 0x34, 0x12}},
- // frame type (stream frame with fin)
- {"",
- {0xFD}},
- // stream id
- {"Unable to read stream_id.",
- {0x04, 0x03}},
- // offset
- {"Unable to read offset.",
- {0x54, 0x76, 0x10, 0x32,
- 0xDC, 0xFE, 0x98, 0x3A}},
- {"Unable to read frame data.",
- {
- // data length
- 0x0c, 0x00,
- // data
- 'h', 'e', 'l', 'l',
- 'o', ' ', 'w', 'o',
- 'r', 'l', 'd', '!'}},
- };
-
- PacketFragments packet39 = {
- // public flags (8 byte connection_id)
- {"",
- {0x28}},
- // connection_id
- {"",
- {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
- // packet number
- {"",
{0x12, 0x34, 0x56, 0x78}},
// frame type (stream frame with fin)
{"",
@@ -2275,7 +2055,7 @@
'r', 'l', 'd', '!'}},
};
- PacketFragments packet47 = {
+ PacketFragments packet46 = {
// type (short header, 4 byte packet number)
{"",
{0x43}},
@@ -2339,13 +2119,10 @@
PacketFragments& fragments =
framer_.transport_version() == QUIC_VERSION_99
? packet99
- : (framer_.transport_version() > QUIC_VERSION_46
- ? packet47
- : (framer_.transport_version() > QUIC_VERSION_43
- ? packet44
- : (framer_.transport_version() != QUIC_VERSION_35
- ? packet39
- : packet)));
+ : (framer_.transport_version() > QUIC_VERSION_44
+ ? packet46
+ : (framer_.transport_version() > QUIC_VERSION_43 ? packet44
+ : packet));
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
@@ -2378,36 +2155,6 @@
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
- {0x78, 0x56, 0x34, 0x12}},
- // frame type (stream frame with fin)
- {"",
- {0xFC}},
- // stream id
- {"Unable to read stream_id.",
- {0x04}},
- // offset
- {"Unable to read offset.",
- {0x54, 0x76, 0x10, 0x32,
- 0xDC, 0xFE, 0x98, 0x3A}},
- {"Unable to read frame data.",
- {
- // data length
- 0x0c, 0x00,
- // data
- 'h', 'e', 'l', 'l',
- 'o', ' ', 'w', 'o',
- 'r', 'l', 'd', '!'}},
- };
-
- PacketFragments packet39 = {
- // public flags (8 byte connection_id)
- {"",
- {0x28}},
- // connection_id
- {"",
- {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
- // packet number
- {"",
{0x12, 0x34, 0x56, 0x78}},
// frame type (stream frame with fin)
{"",
@@ -2459,7 +2206,7 @@
'r', 'l', 'd', '!'}},
};
- PacketFragments packet47 = {
+ PacketFragments packet46 = {
// type (short header, 4 byte packet number)
{"",
{0x43}},
@@ -2523,13 +2270,10 @@
PacketFragments& fragments =
framer_.transport_version() == QUIC_VERSION_99
? packet99
- : (framer_.transport_version() > QUIC_VERSION_46
- ? packet47
- : (framer_.transport_version() > QUIC_VERSION_43
- ? packet44
- : (framer_.transport_version() != QUIC_VERSION_35
- ? packet39
- : packet)));
+ : (framer_.transport_version() > QUIC_VERSION_44
+ ? packet46
+ : (framer_.transport_version() > QUIC_VERSION_43 ? packet44
+ : packet));
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
@@ -2565,39 +2309,6 @@
{QUIC_VERSION_BYTES}},
// packet number
{"",
- {0x78, 0x56, 0x34, 0x12}},
- // frame type (stream frame with fin)
- {"",
- {0xFE}},
- // stream id
- {"Unable to read stream_id.",
- {0x04, 0x03, 0x02}},
- // offset
- {"Unable to read offset.",
- {0x54, 0x76, 0x10, 0x32,
- 0xDC, 0xFE, 0x98, 0x3A}},
- {"Unable to read frame data.",
- {
- // data length
- 0x0c, 0x00,
- // data
- 'h', 'e', 'l', 'l',
- 'o', ' ', 'w', 'o',
- 'r', 'l', 'd', '!'}},
- };
-
- PacketFragments packet39 = {
- // public flags (version, 8 byte connection_id)
- {"",
- {0x29}},
- // connection_id
- {"",
- {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
- // version tag
- {"",
- {QUIC_VERSION_BYTES}},
- // packet number
- {"",
{0x12, 0x34, 0x56, 0x78}},
// frame type (stream frame with fin)
{"",
@@ -2655,7 +2366,7 @@
'r', 'l', 'd', '!'}},
};
- PacketFragments packet47 = {
+ PacketFragments packet46 = {
// public flags (long header with packet type ZERO_RTT_PROTECTED and
// 4-byte packet number)
{"",
@@ -2706,6 +2417,9 @@
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
+ // long header packet length
+ {"",
+ {0x1E}},
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
@@ -2713,33 +2427,38 @@
{"",
{0x08 | 0x01 | 0x02 | 0x04}},
// stream id
- {"Unable to read stream_id.",
+ {"Long header payload length longer than packet.",
{kVarInt62FourBytes + 0x00, 0x02, 0x03, 0x04}},
// offset
- {"Unable to read stream data offset.",
+ {"Long header payload length longer than packet.",
{kVarInt62EightBytes + 0x3A, 0x98, 0xFE, 0xDC,
0x32, 0x10, 0x76, 0x54}},
// data length
- {"Unable to read stream data length.",
+ {"Long header payload length longer than packet.",
{kVarInt62OneByte + 0x0c}},
// data
- {"Unable to read frame data.",
+ {"Long header payload length longer than packet.",
{ 'h', 'e', 'l', 'l',
'o', ' ', 'w', 'o',
'r', 'l', 'd', '!'}},
};
// clang-format on
+ QuicVariableLengthIntegerLength retry_token_length_length =
+ VARIABLE_LENGTH_INTEGER_LENGTH_0;
+ size_t retry_token_length = 0;
+ QuicVariableLengthIntegerLength length_length =
+ QuicVersionHasLongHeaderLengths(framer_.transport_version())
+ ? VARIABLE_LENGTH_INTEGER_LENGTH_1
+ : VARIABLE_LENGTH_INTEGER_LENGTH_0;
+
PacketFragments& fragments =
framer_.transport_version() == QUIC_VERSION_99
? packet99
- : (framer_.transport_version() > QUIC_VERSION_46
- ? packet47
- : (framer_.transport_version() > QUIC_VERSION_43
- ? packet44
- : (framer_.transport_version() != QUIC_VERSION_35
- ? packet39
- : packet)));
+ : (framer_.transport_version() > QUIC_VERSION_44
+ ? packet46
+ : (framer_.transport_version() > QUIC_VERSION_43 ? packet44
+ : packet));
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
@@ -2748,7 +2467,8 @@
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, kIncludeVersion, !kIncludeDiversificationNonce,
- PACKET_8BYTE_CONNECTION_ID, PACKET_0BYTE_CONNECTION_ID));
+ PACKET_8BYTE_CONNECTION_ID, PACKET_0BYTE_CONNECTION_ID,
+ retry_token_length_length, retry_token_length, length_length));
ASSERT_EQ(1u, visitor_.stream_frames_.size());
EXPECT_EQ(0u, visitor_.ack_frames_.size());
@@ -2758,7 +2478,10 @@
EXPECT_EQ(kStreamOffset, visitor_.stream_frames_[0]->offset);
CheckStreamFrameData("hello world!", visitor_.stream_frames_[0].get());
- CheckFramingBoundaries(fragments, QUIC_INVALID_STREAM_DATA);
+ CheckFramingBoundaries(fragments,
+ framer_.transport_version() == QUIC_VERSION_99
+ ? QUIC_INVALID_PACKET_HEADER
+ : QUIC_INVALID_STREAM_DATA);
}
TEST_P(QuicFramerTest, RejectPacket) {
@@ -2771,29 +2494,6 @@
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
- 0x78, 0x56, 0x34, 0x12,
-
- // frame type (stream frame with fin)
- 0xFF,
- // stream id
- 0x04, 0x03, 0x02, 0x01,
- // offset
- 0x54, 0x76, 0x10, 0x32,
- 0xDC, 0xFE, 0x98, 0x3A,
- // data length
- 0x0c, 0x00,
- // data
- 'h', 'e', 'l', 'l',
- 'o', ' ', 'w', 'o',
- 'r', 'l', 'd', '!',
- };
-
- unsigned char packet39[] = {
- // public flags (8 byte connection_id)
- 0x28,
- // connection_id
- 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
- // packet number
0x12, 0x34, 0x56, 0x78,
// frame type (stream frame with fin)
@@ -2834,7 +2534,7 @@
'r', 'l', 'd', '!',
};
- unsigned char packet47[] = {
+ unsigned char packet46[] = {
// type (short header, 4 byte packet number)
0x43,
// connection_id
@@ -2859,12 +2559,10 @@
// clang-format on
unsigned char* p = packet;
- if (framer_.transport_version() > QUIC_VERSION_46) {
- p = packet47;
+ if (framer_.transport_version() > QUIC_VERSION_44) {
+ p = packet46;
} else if (framer_.transport_version() > QUIC_VERSION_43) {
p = packet44;
- } else if (framer_.transport_version() != QUIC_VERSION_35) {
- p = packet39;
}
QuicEncryptedPacket encrypted(AsChars(p),
framer_.transport_version() > QUIC_VERSION_43
@@ -2903,7 +2601,7 @@
0x01,
};
- unsigned char packet47[] = {
+ unsigned char packet46[] = {
// type (short header, 1 byte packet number)
0x40,
// connection_id
@@ -2914,12 +2612,12 @@
// clang-format on
QuicEncryptedPacket encrypted(
- framer_.transport_version() > QUIC_VERSION_46
- ? AsChars(packet47)
+ framer_.transport_version() > QUIC_VERSION_44
+ ? AsChars(packet46)
: (framer_.transport_version() > QUIC_VERSION_43 ? AsChars(packet44)
: AsChars(packet)),
- framer_.transport_version() > QUIC_VERSION_46
- ? QUIC_ARRAYSIZE(packet47)
+ framer_.transport_version() > QUIC_VERSION_44
+ ? QUIC_ARRAYSIZE(packet46)
: (framer_.transport_version() > QUIC_VERSION_43
? QUIC_ARRAYSIZE(packet44)
: QUIC_ARRAYSIZE(packet)),
@@ -2942,34 +2640,6 @@
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
- {0x78, 0x56, 0x34, 0x12}},
- // frame type (ack frame)
- // (one ack block, 2 byte largest observed, 2 byte block length)
- {"",
- {0x45}},
- // largest acked
- {"Unable to read largest acked.",
- {0x34, 0x12}},
- // Zero delta time.
- {"Unable to read ack delay time.",
- {0x00, 0x00}},
- // first ack block length.
- {"Unable to read first ack block length.",
- {0x34, 0x12}},
- // num timestamps.
- {"Unable to read num received packets.",
- {0x00}}
- };
-
- PacketFragments packet39 = {
- // public flags (8 byte connection_id)
- {"",
- {0x2C}},
- // connection_id
- {"",
- {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
- // packet number
- {"",
{0x12, 0x34, 0x56, 0x78}},
// frame type (ack frame)
// (one ack block, 2 byte largest observed, 2 byte block length)
@@ -3017,7 +2687,7 @@
{0x00}}
};
- PacketFragments packet47 = {
+ PacketFragments packet46 = {
// type (short packet, 4 byte packet number)
{"",
{0x43}},
@@ -3084,13 +2754,10 @@
PacketFragments& fragments =
framer_.transport_version() == QUIC_VERSION_99
? packet99
- : (framer_.transport_version() > QUIC_VERSION_46
- ? packet47
- : (framer_.transport_version() > QUIC_VERSION_43
- ? packet44
- : (framer_.transport_version() != QUIC_VERSION_35
- ? packet39
- : packet)));
+ : (framer_.transport_version() > QUIC_VERSION_44
+ ? packet46
+ : (framer_.transport_version() > QUIC_VERSION_43 ? packet44
+ : packet));
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
@@ -3124,34 +2791,6 @@
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
- {0x78, 0x56, 0x34, 0x12}},
- // frame type (ack frame)
- // (one ack block, 2 byte largest observed, 2 byte block length)
- {"",
- {0x45}},
- // largest acked
- {"Unable to read largest acked.",
- {0x34, 0x12}},
- // Zero delta time.
- {"Unable to read ack delay time.",
- {0x00, 0x00}},
- // first ack block length.
- {"Unable to read first ack block length.",
- {0x88, 0x88}},
- // num timestamps.
- {"Underflow with first ack block length 34952 largest acked is 4660.",
- {0x00}}
- };
-
- PacketFragments packet39 = {
- // public flags (8 byte connection_id)
- {"",
- {0x2C}},
- // connection_id
- {"",
- {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
- // packet number
- {"",
{0x12, 0x34, 0x56, 0x78}},
// frame type (ack frame)
// (one ack block, 2 byte largest observed, 2 byte block length)
@@ -3199,7 +2838,7 @@
{0x00}}
};
- PacketFragments packet47 = {
+ PacketFragments packet46 = {
// type (short header, 4 byte packet number)
{"",
{0x43}},
@@ -3258,13 +2897,10 @@
PacketFragments& fragments =
framer_.transport_version() == QUIC_VERSION_99
? packet99
- : (framer_.transport_version() > QUIC_VERSION_46
- ? packet47
- : (framer_.transport_version() > QUIC_VERSION_43
- ? packet44
- : (framer_.transport_version() != QUIC_VERSION_35
- ? packet39
- : packet)));
+ : (framer_.transport_version() > QUIC_VERSION_44
+ ? packet46
+ : (framer_.transport_version() > QUIC_VERSION_43 ? packet44
+ : packet));
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
@@ -3557,47 +3193,6 @@
{ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 }},
// packet number
{"",
- { 0x78, 0x56, 0x34, 0x12 }},
-
- // frame type (ack frame)
- // (more than one ack block, 2 byte largest observed, 2 byte block length)
- {"",
- { 0x65 }},
- // largest acked
- {"Unable to read largest acked.",
- { 0x34, 0x12 }},
- // Zero delta time.
- {"Unable to read ack delay time.",
- { 0x00, 0x00 }},
- // num ack blocks ranges.
- {"Unable to read num of ack blocks.",
- { 0x01 }},
- // first ack block length.
- {"Unable to read first ack block length.",
- { 0x00, 0x00 }},
- // gap to next block.
- { "First block length is zero but ACK is not empty. "
- "largest acked is 4660, num ack blocks is 1.",
- { 0x01 }},
- // ack block length.
- { "First block length is zero but ACK is not empty. "
- "largest acked is 4660, num ack blocks is 1.",
- { 0xaf, 0x0e }},
- // Number of timestamps.
- { "First block length is zero but ACK is not empty. "
- "largest acked is 4660, num ack blocks is 1.",
- { 0x00 }},
- };
-
- PacketFragments packet39 = {
- // public flags (8 byte connection_id)
- {"",
- { 0x2C }},
- // connection_id
- {"",
- { 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 }},
- // packet number
- {"",
{ 0x12, 0x34, 0x56, 0x78 }},
// frame type (ack frame)
@@ -3617,16 +3212,13 @@
{"Unable to read first ack block length.",
{ 0x00, 0x00 }},
// gap to next block.
- { "First block length is zero but ACK is not empty. "
- "largest acked is 4660, num ack blocks is 1.",
+ { "First block length is zero.",
{ 0x01 }},
// ack block length.
- { "First block length is zero but ACK is not empty. "
- "largest acked is 4660, num ack blocks is 1.",
+ { "First block length is zero.",
{ 0x0e, 0xaf }},
// Number of timestamps.
- { "First block length is zero but ACK is not empty. "
- "largest acked is 4660, num ack blocks is 1.",
+ { "First block length is zero.",
{ 0x00 }},
};
@@ -3658,20 +3250,17 @@
{"Unable to read first ack block length.",
{ 0x00, 0x00 }},
// gap to next block.
- { "First block length is zero but ACK is not empty. "
- "largest acked is 4660, num ack blocks is 1.",
+ { "First block length is zero.",
{ 0x01 }},
// ack block length.
- { "First block length is zero but ACK is not empty. "
- "largest acked is 4660, num ack blocks is 1.",
+ { "First block length is zero.",
{ 0x0e, 0xaf }},
// Number of timestamps.
- { "First block length is zero but ACK is not empty. "
- "largest acked is 4660, num ack blocks is 1.",
+ { "First block length is zero.",
{ 0x00 }},
};
- PacketFragments packet47 = {
+ PacketFragments packet46 = {
// type (short header, 4 byte packet number)
{"",
{ 0x43 }},
@@ -3699,27 +3288,21 @@
{"Unable to read first ack block length.",
{ 0x00, 0x00 }},
// gap to next block.
- { "First block length is zero but ACK is not empty. "
- "largest acked is 4660, num ack blocks is 1.",
+ { "First block length is zero.",
{ 0x01 }},
// ack block length.
- { "First block length is zero but ACK is not empty. "
- "largest acked is 4660, num ack blocks is 1.",
+ { "First block length is zero.",
{ 0x0e, 0xaf }},
// Number of timestamps.
- { "First block length is zero but ACK is not empty. "
- "largest acked is 4660, num ack blocks is 1.",
+ { "First block length is zero.",
{ 0x00 }},
};
// clang-format on
PacketFragments& fragments =
- framer_.transport_version() > QUIC_VERSION_46
- ? packet47
- : (framer_.transport_version() > QUIC_VERSION_43
- ? packet44
- : (framer_.transport_version() != QUIC_VERSION_35 ? packet39
- : packet));
+ framer_.transport_version() > QUIC_VERSION_44
+ ? packet46
+ : (framer_.transport_version() > QUIC_VERSION_43 ? packet44 : packet);
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
@@ -3749,34 +3332,6 @@
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
- {0x78, 0x56, 0x34, 0x12}},
- // frame type (ack frame)
- // (one ack block, 4 byte largest observed, 2 byte block length)
- {"",
- {0x49}},
- // largest acked
- {"Unable to read largest acked.",
- {0x78, 0x56, 0x34, 0x12}},
- // Zero delta time.
- {"Unable to read ack delay time.",
- {0x00, 0x00}},
- // first ack block length.
- {"Unable to read first ack block length.",
- {0x34, 0x12}},
- // num timestamps.
- {"Unable to read num received packets.",
- {0x00}}
- };
-
- PacketFragments packet39 = {
- // public flags (8 byte connection_id)
- {"",
- {0x2C}},
- // connection_id
- {"",
- {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
- // packet number
- {"",
{0x12, 0x34, 0x56, 0x78}},
// frame type (ack frame)
// (one ack block, 4 byte largest observed, 2 byte block length)
@@ -3824,7 +3379,7 @@
{0x00}}
};
- PacketFragments packet47 = {
+ PacketFragments packet46 = {
// type (short header, 4 byte packet number)
{"",
{0x43}},
@@ -3883,13 +3438,10 @@
PacketFragments& fragments =
framer_.transport_version() == QUIC_VERSION_99
? packet99
- : (framer_.transport_version() > QUIC_VERSION_46
- ? packet47
- : (framer_.transport_version() > QUIC_VERSION_43
- ? packet44
- : (framer_.transport_version() != QUIC_VERSION_35
- ? packet39
- : packet)));
+ : (framer_.transport_version() > QUIC_VERSION_44
+ ? packet46
+ : (framer_.transport_version() > QUIC_VERSION_43 ? packet44
+ : packet));
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
@@ -3922,74 +3474,6 @@
{ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 }},
// packet number
{"",
- { 0x78, 0x56, 0x34, 0x12 }},
-
- // frame type (ack frame)
- // (more than one ack block, 2 byte largest observed, 2 byte block length)
- {"",
- { 0x65 }},
- // largest acked
- {"Unable to read largest acked.",
- { 0x34, 0x12 }},
- // Zero delta time.
- {"Unable to read ack delay time.",
- { 0x00, 0x00 }},
- // num ack blocks ranges.
- {"Unable to read num of ack blocks.",
- { 0x04 }},
- // first ack block length.
- {"Unable to read first ack block length.",
- { 0x01, 0x00 }},
- // gap to next block.
- { "Unable to read gap to next ack block.",
- { 0x01 }},
- // ack block length.
- { "Unable to ack block length.",
- { 0xaf, 0x0e }},
- // gap to next block.
- { "Unable to read gap to next ack block.",
- { 0xff }},
- // ack block length.
- { "Unable to ack block length.",
- { 0x00, 0x00 }},