Project import generated by Copybara. PiperOrigin-RevId: 231652158 Change-Id: I80001699b542a5c823722d90d24fcdd014ef99e7
diff --git a/http2/hpack/decoder/hpack_entry_decoder.cc b/http2/hpack/decoder/hpack_entry_decoder.cc index b227b18..96b9f06 100644 --- a/http2/hpack/decoder/hpack_entry_decoder.cc +++ b/http2/hpack/decoder/hpack_entry_decoder.cc
@@ -192,7 +192,7 @@ bool HpackEntryDecoder::DispatchOnType(HpackEntryDecoderListener* listener) { const HpackEntryType entry_type = entry_type_decoder_.entry_type(); - const uint64_t varint = entry_type_decoder_.varint(); + const uint32_t varint = static_cast<uint32_t>(entry_type_decoder_.varint()); switch (entry_type) { case HpackEntryType::kIndexedHeader: // The entry consists solely of the entry type and varint. See:
diff --git a/http2/hpack/decoder/hpack_string_decoder.h b/http2/hpack/decoder/hpack_string_decoder.h index 5e0d220..2128728 100644 --- a/http2/hpack/decoder/hpack_string_decoder.h +++ b/http2/hpack/decoder/hpack_string_decoder.h
@@ -13,7 +13,6 @@ #include <algorithm> #include <cstdint> -#include <limits> #include "base/logging.h" #include "base/macros.h" @@ -169,16 +168,8 @@ // false otherwise, in which case status set. template <class Listener> void OnStringStart(Listener* cb, DecodeStatus* status) { - // HpackVarintDecoder::value() returns uint64_t. - const uint64_t value = length_decoder_.value(); - // |remaining_| is size_t. Check for truncation on 32-bit platforms. - // numeric_limits::max() is constexpr. On platforms where size_t is at - // least 64 bit wide, the compiler should optimize away this branch. - if (value > std::numeric_limits<size_t>::max()) { - *status = DecodeStatus::kDecodeError; - return; - } - remaining_ = static_cast<size_t>(value); + // TODO(vasilvv): fail explicitly in case of truncation. + remaining_ = static_cast<size_t>(length_decoder_.value()); // Make callback so consumer knows what is coming. cb->OnStringStart(huffman_encoded_, remaining_); }
diff --git a/http2/hpack/varint/hpack_varint_decoder.cc b/http2/hpack/varint/hpack_varint_decoder.cc index dd64025..ac85247 100644 --- a/http2/hpack/varint/hpack_varint_decoder.cc +++ b/http2/hpack/varint/hpack_varint_decoder.cc
@@ -4,7 +4,6 @@ #include "net/third_party/quiche/src/http2/hpack/varint/hpack_varint_decoder.h" -#include "net/third_party/quiche/src/http2/platform/api/http2_flag_utils.h" #include "net/third_party/quiche/src/http2/platform/api/http2_string_utils.h" namespace http2 { @@ -43,96 +42,67 @@ } DecodeStatus HpackVarintDecoder::Resume(DecodeBuffer* db) { - if (decode_64_bits_) { - HTTP2_RELOADABLE_FLAG_COUNT(http2_varint_decode_64_bits); - // There can be at most 10 continuation bytes. Offset is zero for the - // first one and increases by 7 for each subsequent one. - const uint8_t kMaxOffset = 63; - CheckNotDone(); - - // Process most extension bytes without the need for overflow checking. - while (offset_ < kMaxOffset) { - if (db->Empty()) { - return DecodeStatus::kDecodeInProgress; - } - - uint8_t byte = db->DecodeUInt8(); - uint64_t summand = byte & 0x7f; - - // Shifting a 7 bit value to the left by at most 56 places can never - // overflow on uint64_t. - DCHECK_LE(offset_, 56); - DCHECK_LE(summand, std::numeric_limits<uint64_t>::max() >> offset_); - - summand <<= offset_; - - // At this point, - // |value_| is at most (2^prefix_length - 1) + (2^49 - 1), and - // |summand| is at most 255 << 56 (which is smaller than 2^63), - // so adding them can never overflow on uint64_t. - DCHECK_LE(value_, std::numeric_limits<uint64_t>::max() - summand); - - value_ += summand; - - // Decoding ends if continuation flag is not set. - if ((byte & 0x80) == 0) { - MarkDone(); - return DecodeStatus::kDecodeDone; - } - - offset_ += 7; - } - - if (db->Empty()) { - return DecodeStatus::kDecodeInProgress; - } - - DCHECK_EQ(kMaxOffset, offset_); - - uint8_t byte = db->DecodeUInt8(); - // No more extension bytes are allowed after this. - if ((byte & 0x80) == 0) { - uint64_t summand = byte & 0x7f; - // Check for overflow in left shift. - if (summand <= std::numeric_limits<uint64_t>::max() >> offset_) { - summand <<= offset_; - // Check for overflow in addition. - if (value_ <= std::numeric_limits<uint64_t>::max() - summand) { - value_ += summand; - MarkDone(); - return DecodeStatus::kDecodeDone; - } - } - } - - // Signal error if value is too large or there are too many extension bytes. - DLOG(WARNING) << "Variable length int encoding is too large or too long. " - << DebugString(); - MarkDone(); - return DecodeStatus::kDecodeError; - } - - // Old code path. TODO(bnc): remove. - DCHECK(!decode_64_bits_); - const uint8_t kMaxOffset = 28; + // There can be at most 10 continuation bytes. Offset is zero for the + // first one and increases by 7 for each subsequent one. + const uint8_t kMaxOffset = 63; CheckNotDone(); - do { + + // Process most extension bytes without the need for overflow checking. + while (offset_ < kMaxOffset) { if (db->Empty()) { return DecodeStatus::kDecodeInProgress; } + uint8_t byte = db->DecodeUInt8(); - if (offset_ == kMaxOffset && byte != 0) - break; - DCHECK(offset_ <= kMaxOffset - 7 || byte == 0); - // Shifting a 7 bit value to the left by at most 21 places can never - // overflow on uint32_t. Shifting 0 to the left cannot overflow either. - value_ += (byte & 0x7f) << offset_; + uint64_t summand = byte & 0x7f; + + // Shifting a 7 bit value to the left by at most 56 places can never + // overflow on uint64_t. + DCHECK_LE(offset_, 56); + DCHECK_LE(summand, std::numeric_limits<uint64_t>::max() >> offset_); + + summand <<= offset_; + + // At this point, + // |value_| is at most (2^prefix_length - 1) + (2^49 - 1), and + // |summand| is at most 255 << 56 (which is smaller than 2^63), + // so adding them can never overflow on uint64_t. + DCHECK_LE(value_, std::numeric_limits<uint64_t>::max() - summand); + + value_ += summand; + + // Decoding ends if continuation flag is not set. if ((byte & 0x80) == 0) { MarkDone(); return DecodeStatus::kDecodeDone; } + offset_ += 7; - } while (offset_ <= kMaxOffset); + } + + if (db->Empty()) { + return DecodeStatus::kDecodeInProgress; + } + + DCHECK_EQ(kMaxOffset, offset_); + + uint8_t byte = db->DecodeUInt8(); + // No more extension bytes are allowed after this. + if ((byte & 0x80) == 0) { + uint64_t summand = byte & 0x7f; + // Check for overflow in left shift. + if (summand <= std::numeric_limits<uint64_t>::max() >> offset_) { + summand <<= offset_; + // Check for overflow in addition. + if (value_ <= std::numeric_limits<uint64_t>::max() - summand) { + value_ += summand; + MarkDone(); + return DecodeStatus::kDecodeDone; + } + } + } + + // Signal error if value is too large or there are too many extension bytes. DLOG(WARNING) << "Variable length int encoding is too large or too long. " << DebugString(); MarkDone();
diff --git a/http2/hpack/varint/hpack_varint_decoder.h b/http2/hpack/varint/hpack_varint_decoder.h index c793500..5c99b5c 100644 --- a/http2/hpack/varint/hpack_varint_decoder.h +++ b/http2/hpack/varint/hpack_varint_decoder.h
@@ -13,23 +13,16 @@ // For details of the encoding, see: // http://httpwg.org/specs/rfc7541.html#integer.representation // -// If GetHttp2ReloadableFlag(http2_varint_decode_64_bits) is true, then this -// decoder supports decoding any integer that can be represented on uint64_t, -// thereby exceeding the requirements for QPACK: "QPACK implementations MUST be -// able to decode integers up to 62 bits long." See +// HpackVarintDecoder supports decoding any integer that can be represented on +// uint64_t, thereby exceeding the requirements for QPACK: "QPACK +// implementations MUST be able to decode integers up to 62 bits long." See // https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#rfc.section.5.1.1 // -// If GetHttp2ReloadableFlag(http2_varint_decode_64_bits) is false, then this -// decoder supports decoding integers up to 2^28 + 2^prefix_length - 2. -// // This decoder supports at most 10 extension bytes (bytes following the prefix, -// also called continuation bytes) if -// GetHttp2ReloadableFlag(http2_varint_decode_64_bits) is true, and at most 5 -// extension bytes if GetHttp2ReloadableFlag(http2_varint_decode_64_bits) is -// false. An encoder is allowed to zero pad the encoded integer on the left, -// thereby increasing the number of extension bytes. If an encoder uses so much -// padding that the number of extension bytes exceeds the limit, then this -// decoder signals an error. +// also called continuation bytes). An encoder is allowed to zero pad the +// encoded integer on the left, thereby increasing the number of extension +// bytes. If an encoder uses so much padding that the number of extension bytes +// exceeds the limit, then this decoder signals an error. #ifndef QUICHE_HTTP2_HPACK_VARINT_HPACK_VARINT_DECODER_H_ #define QUICHE_HTTP2_HPACK_VARINT_HPACK_VARINT_DECODER_H_ @@ -41,7 +34,6 @@ #include "net/third_party/quiche/src/http2/decoder/decode_buffer.h" #include "net/third_party/quiche/src/http2/decoder/decode_status.h" #include "net/third_party/quiche/src/http2/platform/api/http2_export.h" -#include "net/third_party/quiche/src/http2/platform/api/http2_flags.h" #include "net/third_party/quiche/src/http2/platform/api/http2_string.h" namespace http2 { @@ -119,12 +111,6 @@ #endif } - // If true, decode integers up to 2^64 - 1, and accept at most 10 extension - // bytes (some of which might be padding). - // If false, decode integers up to 2^28 + 2^prefix_length - 2, and accept at - // most 5 extension bytes (some of which might be padding). - bool decode_64_bits_ = GetHttp2ReloadableFlag(http2_varint_decode_64_bits); - // These fields are initialized just to keep ASAN happy about reading // them from DebugString().
diff --git a/http2/hpack/varint/hpack_varint_decoder_test.cc b/http2/hpack/varint/hpack_varint_decoder_test.cc index e36ad07..32a4a30 100644 --- a/http2/hpack/varint/hpack_varint_decoder_test.cc +++ b/http2/hpack/varint/hpack_varint_decoder_test.cc
@@ -22,32 +22,13 @@ namespace test { namespace { -// Save previous value of flag and restore on destruction. -class FlagSaver { - public: - FlagSaver() = delete; - explicit FlagSaver(bool decode_64_bits) - : saved_value_(GetHttp2ReloadableFlag(http2_varint_decode_64_bits)) { - SetHttp2ReloadableFlag(http2_varint_decode_64_bits, decode_64_bits); - } - ~FlagSaver() { - SetHttp2ReloadableFlag(http2_varint_decode_64_bits, saved_value_); - } - - private: - const bool saved_value_; -}; - -class HpackVarintDecoderTest - : public RandomDecoderTest, - public ::testing::WithParamInterface< - ::testing::tuple<bool, uint8_t, const char*>> { +class HpackVarintDecoderTest : public RandomDecoderTest, + public ::testing::WithParamInterface< + ::testing::tuple<uint8_t, const char*>> { protected: HpackVarintDecoderTest() - : decode_64_bits_(::testing::get<0>(GetParam())), - high_bits_(::testing::get<1>(GetParam())), - suffix_(Http2HexDecode(::testing::get<2>(GetParam()))), - flag_saver_(decode_64_bits_), + : high_bits_(::testing::get<0>(GetParam())), + suffix_(Http2HexDecode(::testing::get<1>(GetParam()))), prefix_length_(0) {} void DecodeExpectSuccess(Http2StringPiece data, @@ -81,8 +62,6 @@ EXPECT_TRUE(Decode(data, prefix_length, validator)); } - bool decode_64_bits() const { return decode_64_bits_; } - private: AssertionResult Decode(Http2StringPiece data, uint32_t prefix_length, @@ -119,16 +98,11 @@ return decoder_.Resume(b); } - // Test new or old behavior. - const bool decode_64_bits_; // Bits of the first byte not part of the prefix. const uint8_t high_bits_; // Extra bytes appended to the input. const Http2String suffix_; - // |flag_saver_| must preceed |decoder_| so that the flag is already set when - // |decoder_| is constructed. - FlagSaver flag_saver_; HpackVarintDecoder decoder_; uint8_t prefix_length_; }; @@ -137,15 +111,11 @@ HpackVarintDecoderTest, HpackVarintDecoderTest, ::testing::Combine( - // Test both the new version (supporting 64 bit integers) and the old - // one (only supporting up to 2^28 + 2^prefix_length - 2. - ::testing::Bool(), // Bits of the first byte not part of the prefix should be ignored. ::testing::Values(0b00000000, 0b11111111, 0b10101010), // Extra bytes appended to the input should be ignored. ::testing::Values("", "00", "666f6f"))); -// Test data used when decode_64_bits() == true. struct { const char* data; uint32_t prefix_length; @@ -289,124 +259,14 @@ {"1f9a0a", 5, 1337}, }; -// Test data used when decode_64_bits() == false. -struct { - const char* data; - uint32_t prefix_length; - uint64_t expected_value; -} kSuccessTestDataOld[] = { - // Zero value with different prefix lengths. - {"00", 3, 0}, - {"00", 4, 0}, - {"00", 5, 0}, - {"00", 6, 0}, - {"00", 7, 0}, - // Small values that fit in the prefix. - {"06", 3, 6}, - {"0d", 4, 13}, - {"10", 5, 16}, - {"29", 6, 41}, - {"56", 7, 86}, - // Values of 2^n-1, which have an all-zero extension byte. - {"0700", 3, 7}, - {"0f00", 4, 15}, - {"1f00", 5, 31}, - {"3f00", 6, 63}, - {"7f00", 7, 127}, - // Values of 2^n-1, plus one extra byte of padding. - {"078000", 3, 7}, - {"0f8000", 4, 15}, - {"1f8000", 5, 31}, - {"3f8000", 6, 63}, - {"7f8000", 7, 127}, - // Values requiring one extension byte. - {"0760", 3, 103}, - {"0f2a", 4, 57}, - {"1f7f", 5, 158}, - {"3f02", 6, 65}, - {"7f49", 7, 200}, - // Values requiring one extension byte, plus one byte of padding. - {"07e000", 3, 103}, - {"0faa00", 4, 57}, - {"1fff00", 5, 158}, - {"3f8200", 6, 65}, - {"7fc900", 7, 200}, - // Values requiring one extension byte, plus two bytes of padding. - {"07e08000", 3, 103}, - {"0faa8000", 4, 57}, - {"1fff8000", 5, 158}, - {"3f828000", 6, 65}, - {"7fc98000", 7, 200}, - // Values requiring one extension byte, plus the maximum amount of padding. - {"07e080808000", 3, 103}, - {"0faa80808000", 4, 57}, - {"1fff80808000", 5, 158}, - {"3f8280808000", 6, 65}, - {"7fc980808000", 7, 200}, - // Values requiring two extension bytes. - {"07b260", 3, 12345}, - {"0f8a2a", 4, 5401}, - {"1fa87f", 5, 16327}, - {"3fd002", 6, 399}, - {"7fff49", 7, 9598}, - // Values requiring two extension bytes, plus one byte of padding. - {"07b2e000", 3, 12345}, - {"0f8aaa00", 4, 5401}, - {"1fa8ff00", 5, 16327}, - {"3fd08200", 6, 399}, - {"7fffc900", 7, 9598}, - // Values requiring two extension bytes, plus the maximum amount of padding. - {"07b2e0808000", 3, 12345}, - {"0f8aaa808000", 4, 5401}, - {"1fa8ff808000", 5, 16327}, - {"3fd082808000", 6, 399}, - {"7fffc9808000", 7, 9598}, - // Values requiring three extension bytes. - {"078ab260", 3, 1579281}, - {"0fc18a2a", 4, 689488}, - {"1fada87f", 5, 2085964}, - {"3fa0d002", 6, 43103}, - {"7ffeff49", 7, 1212541}, - // Values requiring three extension bytes, plus one byte of padding. - {"078ab2e000", 3, 1579281}, - {"0fc18aaa00", 4, 689488}, - {"1fada8ff00", 5, 2085964}, - {"3fa0d08200", 6, 43103}, - {"7ffeffc900", 7, 1212541}, - // Values requiring four extension bytes. - {"079f8ab260", 3, 202147110}, - {"0fa2c18a2a", 4, 88252593}, - {"1fd0ada87f", 5, 266999535}, - {"3ff9a0d002", 6, 5509304}, - {"7f9efeff49", 7, 155189149}, - // Values requiring four extension bytes, plus one byte of padding. - {"079f8ab2e000", 3, 202147110}, - {"0fa2c18aaa00", 4, 88252593}, - {"1fd0ada8ff00", 5, 266999535}, - {"3ff9a0d08200", 6, 5509304}, - {"7f9efeffc900", 7, 155189149}, - // Examples from RFC7541 C.1. - {"0a", 5, 10}, - {"1f9a0a", 5, 1337}, -}; - TEST_P(HpackVarintDecoderTest, Success) { - if (decode_64_bits()) { for (size_t i = 0; i < HTTP2_ARRAYSIZE(kSuccessTestData); ++i) { DecodeExpectSuccess(Http2HexDecode(kSuccessTestData[i].data), kSuccessTestData[i].prefix_length, kSuccessTestData[i].expected_value); } - } else { - for (size_t i = 0; i < HTTP2_ARRAYSIZE(kSuccessTestDataOld); ++i) { - DecodeExpectSuccess(Http2HexDecode(kSuccessTestDataOld[i].data), - kSuccessTestDataOld[i].prefix_length, - kSuccessTestDataOld[i].expected_value); - } - } } -// Test data used when decode_64_bits() == true. struct { const char* data; uint32_t prefix_length; @@ -440,45 +300,11 @@ {"7f80ffffffffffffffff8100", 7}, {"ff80feffffffffffffff8100", 8}}; -// Test data used when decode_64_bits() == false. -// In this mode, HpackVarintDecoder allows at most five extension bytes, -// and fifth extension byte must be zero. -struct { - const char* data; - uint32_t prefix_length; -} kErrorTestDataOld[] = { - // Maximum number of extension bytes but last byte is non-zero. - {"078080808001", 3}, - {"0f8080808001", 4}, - {"1f8080808001", 5}, - {"3f8080808001", 6}, - {"7f8080808001", 7}, - // Too many extension bytes, all 0s (except for extension bit in each byte). - {"078080808080", 3}, - {"0f8080808080", 4}, - {"1f8080808080", 5}, - {"3f8080808080", 6}, - {"7f8080808080", 7}, - // Too many extension bytes, all 1s. - {"07ffffffffff", 3}, - {"0fffffffffff", 4}, - {"1fffffffffff", 5}, - {"3fffffffffff", 6}, - {"7fffffffffff", 7}, -}; - TEST_P(HpackVarintDecoderTest, Error) { - if (decode_64_bits()) { for (size_t i = 0; i < HTTP2_ARRAYSIZE(kErrorTestData); ++i) { DecodeExpectError(Http2HexDecode(kErrorTestData[i].data), kErrorTestData[i].prefix_length); } - } else { - for (size_t i = 0; i < HTTP2_ARRAYSIZE(kErrorTestDataOld); ++i) { - DecodeExpectError(Http2HexDecode(kErrorTestDataOld[i].data), - kErrorTestDataOld[i].prefix_length); - } - } } } // namespace
diff --git a/http2/hpack/varint/hpack_varint_round_trip_test.cc b/http2/hpack/varint/hpack_varint_round_trip_test.cc index 3299d5e..cd26553 100644 --- a/http2/hpack/varint/hpack_varint_round_trip_test.cc +++ b/http2/hpack/varint/hpack_varint_round_trip_test.cc
@@ -22,29 +22,11 @@ using ::testing::AssertionFailure; using ::testing::AssertionSuccess; -using ::testing::Bool; -using ::testing::WithParamInterface; namespace http2 { namespace test { namespace { -// Save previous value of flag and restore on destruction. -class FlagSaver { - public: - FlagSaver() = delete; - explicit FlagSaver(bool decode_64_bits) - : saved_value_(GetHttp2ReloadableFlag(http2_varint_decode_64_bits)) { - SetHttp2ReloadableFlag(http2_varint_decode_64_bits, decode_64_bits); - } - ~FlagSaver() { - SetHttp2ReloadableFlag(http2_varint_decode_64_bits, saved_value_); - } - - private: - const bool saved_value_; -}; - // Returns the highest value with the specified number of extension bytes // and the specified prefix length (bits). uint64_t HiValueOfExtensionBytes(uint32_t extension_bytes, @@ -53,13 +35,9 @@ (extension_bytes == 0 ? 0 : (1LLU << (extension_bytes * 7))); } -class HpackVarintRoundTripTest : public RandomDecoderTest, - public WithParamInterface<bool> { +class HpackVarintRoundTripTest : public RandomDecoderTest { protected: - HpackVarintRoundTripTest() - : decode_64_bits_(GetParam()), - flag_saver_(decode_64_bits_), - prefix_length_(0) {} + HpackVarintRoundTripTest() : prefix_length_(0) {} DecodeStatus StartDecoding(DecodeBuffer* b) override { CHECK_LT(0u, b->Remaining()); @@ -260,22 +238,14 @@ EncodeAndDecodeValues(values, prefix_length, expected_bytes); } - // |flag_saver_| must preceed |decoder_| so that the flag is already set when - // |decoder_| is constructed. - const bool decode_64_bits_; - FlagSaver flag_saver_; HpackVarintDecoder decoder_; Http2String buffer_; uint8_t prefix_length_; }; -INSTANTIATE_TEST_CASE_P(HpackVarintRoundTripTest, - HpackVarintRoundTripTest, - Bool()); - // To help me and future debuggers of varint encodings, this LOGs out the // transition points where a new extension byte is added. -TEST_P(HpackVarintRoundTripTest, Encode) { +TEST_F(HpackVarintRoundTripTest, Encode) { for (int prefix_length = 3; prefix_length <= 8; ++prefix_length) { const uint64_t a = HiValueOfExtensionBytes(0, prefix_length); const uint64_t b = HiValueOfExtensionBytes(1, prefix_length); @@ -300,19 +270,13 @@ b - 1, b, b + 1, b + 2, b + 3, // Force line break. c - 1, c, c + 1, c + 2, c + 3, // Force line break. d - 1, d, d + 1, d + 2, d + 3, // Force line break. - e - 1, e, e + 1, e + 2, e + 3 // Force line break. + e - 1, e, e + 1, e + 2, e + 3, // Force line break. + f - 1, f, f + 1, f + 2, f + 3, // Force line break. + g - 1, g, g + 1, g + 2, g + 3, // Force line break. + h - 1, h, h + 1, h + 2, h + 3, // Force line break. + i - 1, i, i + 1, i + 2, i + 3, // Force line break. + j - 1, j, j + 1, j + 2, j + 3, // Force line break. }; - if (decode_64_bits_) { - for (auto value : { - f - 1, f, f + 1, f + 2, f + 3, // Force line break. - g - 1, g, g + 1, g + 2, g + 3, // Force line break. - h - 1, h, h + 1, h + 2, h + 3, // Force line break. - i - 1, i, i + 1, i + 2, i + 3, // Force line break. - j - 1, j, j + 1, j + 2, j + 3, // Force line break. - }) { - values.push_back(value); - } - } for (uint64_t value : values) { EncodeNoRandom(value, prefix_length); @@ -323,7 +287,7 @@ } } -TEST_P(HpackVarintRoundTripTest, FromSpec1337) { +TEST_F(HpackVarintRoundTripTest, FromSpec1337) { DecodeBuffer b(Http2StringPiece("\x1f\x9a\x0a")); uint32_t prefix_length = 5; uint8_t p = b.DecodeUInt8(); @@ -340,7 +304,7 @@ } // Test all the values that fit into the prefix (one less than the mask). -TEST_P(HpackVarintRoundTripTest, ValidatePrefixOnly) { +TEST_F(HpackVarintRoundTripTest, ValidatePrefixOnly) { for (int prefix_length = 3; prefix_length <= 8; ++prefix_length) { const uint8_t prefix_mask = (1 << prefix_length) - 1; EncodeAndDecodeValuesInRange(0, prefix_mask, prefix_length, 1); @@ -348,7 +312,7 @@ } // Test all values that require exactly 1 extension byte. -TEST_P(HpackVarintRoundTripTest, ValidateOneExtensionByte) { +TEST_F(HpackVarintRoundTripTest, ValidateOneExtensionByte) { for (int prefix_length = 3; prefix_length <= 8; ++prefix_length) { const uint64_t start = HiValueOfExtensionBytes(0, prefix_length) + 1; EncodeAndDecodeValuesInRange(start, 128, prefix_length, 2); @@ -356,7 +320,7 @@ } // Test *some* values that require exactly 2 extension bytes. -TEST_P(HpackVarintRoundTripTest, ValidateTwoExtensionBytes) { +TEST_F(HpackVarintRoundTripTest, ValidateTwoExtensionBytes) { for (int prefix_length = 3; prefix_length <= 8; ++prefix_length) { const uint64_t start = HiValueOfExtensionBytes(1, prefix_length) + 1; const uint64_t range = 127 << 7; @@ -366,7 +330,7 @@ } // Test *some* values that require 3 extension bytes. -TEST_P(HpackVarintRoundTripTest, ValidateThreeExtensionBytes) { +TEST_F(HpackVarintRoundTripTest, ValidateThreeExtensionBytes) { for (int prefix_length = 3; prefix_length <= 8; ++prefix_length) { const uint64_t start = HiValueOfExtensionBytes(2, prefix_length) + 1; const uint64_t range = 127 << 14; @@ -376,7 +340,7 @@ } // Test *some* values that require 4 extension bytes. -TEST_P(HpackVarintRoundTripTest, ValidateFourExtensionBytes) { +TEST_F(HpackVarintRoundTripTest, ValidateFourExtensionBytes) { for (int prefix_length = 3; prefix_length <= 8; ++prefix_length) { const uint64_t start = HiValueOfExtensionBytes(3, prefix_length) + 1; const uint64_t range = 127 << 21; @@ -386,11 +350,7 @@ } // Test *some* values that require 5 extension bytes. -TEST_P(HpackVarintRoundTripTest, ValidateFiveExtensionBytes) { - if (!decode_64_bits_) { - return; - } - +TEST_F(HpackVarintRoundTripTest, ValidateFiveExtensionBytes) { for (int prefix_length = 3; prefix_length <= 8; ++prefix_length) { const uint64_t start = HiValueOfExtensionBytes(4, prefix_length) + 1; const uint64_t range = 127llu << 28; @@ -400,11 +360,7 @@ } // Test *some* values that require 6 extension bytes. -TEST_P(HpackVarintRoundTripTest, ValidateSixExtensionBytes) { - if (!decode_64_bits_) { - return; - } - +TEST_F(HpackVarintRoundTripTest, ValidateSixExtensionBytes) { for (int prefix_length = 3; prefix_length <= 8; ++prefix_length) { const uint64_t start = HiValueOfExtensionBytes(5, prefix_length) + 1; const uint64_t range = 127llu << 35; @@ -414,11 +370,7 @@ } // Test *some* values that require 7 extension bytes. -TEST_P(HpackVarintRoundTripTest, ValidateSevenExtensionBytes) { - if (!decode_64_bits_) { - return; - } - +TEST_F(HpackVarintRoundTripTest, ValidateSevenExtensionBytes) { for (int prefix_length = 3; prefix_length <= 8; ++prefix_length) { const uint64_t start = HiValueOfExtensionBytes(6, prefix_length) + 1; const uint64_t range = 127llu << 42; @@ -428,11 +380,7 @@ } // Test *some* values that require 8 extension bytes. -TEST_P(HpackVarintRoundTripTest, ValidateEightExtensionBytes) { - if (!decode_64_bits_) { - return; - } - +TEST_F(HpackVarintRoundTripTest, ValidateEightExtensionBytes) { for (int prefix_length = 3; prefix_length <= 8; ++prefix_length) { const uint64_t start = HiValueOfExtensionBytes(7, prefix_length) + 1; const uint64_t range = 127llu << 49; @@ -442,11 +390,7 @@ } // Test *some* values that require 9 extension bytes. -TEST_P(HpackVarintRoundTripTest, ValidateNineExtensionBytes) { - if (!decode_64_bits_) { - return; - } - +TEST_F(HpackVarintRoundTripTest, ValidateNineExtensionBytes) { for (int prefix_length = 3; prefix_length <= 8; ++prefix_length) { const uint64_t start = HiValueOfExtensionBytes(8, prefix_length) + 1; const uint64_t range = 127llu << 56; @@ -456,11 +400,7 @@ } // Test *some* values that require 10 extension bytes. -TEST_P(HpackVarintRoundTripTest, ValidateTenExtensionBytes) { - if (!decode_64_bits_) { - return; - } - +TEST_F(HpackVarintRoundTripTest, ValidateTenExtensionBytes) { for (int prefix_length = 3; prefix_length <= 8; ++prefix_length) { const uint64_t start = HiValueOfExtensionBytes(9, prefix_length) + 1; const uint64_t range = std::numeric_limits<uint64_t>::max() - start; @@ -469,45 +409,6 @@ } } -// Test the value one larger than the largest that can be decoded. -TEST_P(HpackVarintRoundTripTest, ValueTooLarge) { - // New implementation can decode any integer that HpackVarintEncoder can - // encode. - if (decode_64_bits_) { - return; - } - - for (prefix_length_ = 3; prefix_length_ <= 8; ++prefix_length_) { - const uint64_t too_large = (1 << 28) + (1 << prefix_length_) - 1; - const uint32_t expected_offset = 6; - HpackBlockBuilder bb; - bb.AppendHighBitsAndVarint(0, prefix_length_, too_large); - buffer_ = bb.buffer(); - - // The validator is called after each of the several times that the input - // DecodeBuffer is decoded, each with a different segmentation of the input. - // Validate that decoder_.value() matches the expected value. - bool validated = false; - Validator validator = [&validated, expected_offset]( - const DecodeBuffer& db, - DecodeStatus status) -> AssertionResult { - validated = true; - VERIFY_EQ(DecodeStatus::kDecodeError, status); - VERIFY_EQ(expected_offset, db.Offset()); - return AssertionSuccess(); - }; - - // StartDecoding, above, requires the DecodeBuffer be non-empty so that it - // can call Start with the prefix byte. - bool return_non_zero_on_first = true; - DecodeBuffer b(buffer_); - EXPECT_TRUE( - DecodeAndValidateSeveralWays(&b, return_non_zero_on_first, validator)); - EXPECT_EQ(expected_offset, b.Offset()); - EXPECT_TRUE(validated); - } -} - } // namespace } // namespace test } // namespace http2
diff --git a/quic/core/chlo_extractor_test.cc b/quic/core/chlo_extractor_test.cc index b1c470c..d16050b 100644 --- a/quic/core/chlo_extractor_test.cc +++ b/quic/core/chlo_extractor_test.cc
@@ -52,7 +52,7 @@ header_.version = AllSupportedVersions().front(); header_.reset_flag = false; header_.packet_number_length = PACKET_4BYTE_PACKET_NUMBER; - header_.packet_number = 1; + header_.packet_number = QuicPacketNumber(1); } void MakePacket(const QuicStreamFrame& stream_frame) {
diff --git a/quic/core/congestion_control/bandwidth_sampler.cc b/quic/core/congestion_control/bandwidth_sampler.cc index 47d55d6..c60eaa2 100644 --- a/quic/core/congestion_control/bandwidth_sampler.cc +++ b/quic/core/congestion_control/bandwidth_sampler.cc
@@ -18,9 +18,7 @@ total_bytes_sent_at_last_acked_packet_(0), last_acked_packet_sent_time_(QuicTime::Zero()), last_acked_packet_ack_time_(QuicTime::Zero()), - last_sent_packet_(0), is_app_limited_(false), - end_of_app_limited_phase_(0), connection_state_map_() {} BandwidthSampler::~BandwidthSampler() {}
diff --git a/quic/core/congestion_control/bandwidth_sampler_test.cc b/quic/core/congestion_control/bandwidth_sampler_test.cc index 4203686..e9b74c7 100644 --- a/quic/core/congestion_control/bandwidth_sampler_test.cc +++ b/quic/core/congestion_control/bandwidth_sampler_test.cc
@@ -40,54 +40,55 @@ BandwidthSampler sampler_; QuicByteCount bytes_in_flight_; - void SendPacketInner(QuicPacketNumber packet_number, + void SendPacketInner(uint64_t packet_number, QuicByteCount bytes, HasRetransmittableData has_retransmittable_data) { - sampler_.OnPacketSent(clock_.Now(), packet_number, bytes, bytes_in_flight_, - has_retransmittable_data); + sampler_.OnPacketSent(clock_.Now(), QuicPacketNumber(packet_number), bytes, + bytes_in_flight_, has_retransmittable_data); if (has_retransmittable_data == HAS_RETRANSMITTABLE_DATA) { bytes_in_flight_ += bytes; } } - void SendPacket(QuicPacketNumber packet_number) { + void SendPacket(uint64_t packet_number) { SendPacketInner(packet_number, kRegularPacketSize, HAS_RETRANSMITTABLE_DATA); } - BandwidthSample AckPacketInner(QuicPacketNumber packet_number) { - QuicByteCount size = - BandwidthSamplerPeer::GetPacketSize(sampler_, packet_number); + BandwidthSample AckPacketInner(uint64_t packet_number) { + QuicByteCount size = BandwidthSamplerPeer::GetPacketSize( + sampler_, QuicPacketNumber(packet_number)); bytes_in_flight_ -= size; - return sampler_.OnPacketAcknowledged(clock_.Now(), packet_number); + return sampler_.OnPacketAcknowledged(clock_.Now(), + QuicPacketNumber(packet_number)); } // Acknowledge receipt of a packet and expect it to be not app-limited. - QuicBandwidth AckPacket(QuicPacketNumber packet_number) { + QuicBandwidth AckPacket(uint64_t packet_number) { BandwidthSample sample = AckPacketInner(packet_number); EXPECT_FALSE(sample.is_app_limited); return sample.bandwidth; } - void LosePacket(QuicPacketNumber packet_number) { - QuicByteCount size = - BandwidthSamplerPeer::GetPacketSize(sampler_, packet_number); + void LosePacket(uint64_t packet_number) { + QuicByteCount size = BandwidthSamplerPeer::GetPacketSize( + sampler_, QuicPacketNumber(packet_number)); bytes_in_flight_ -= size; - sampler_.OnPacketLost(packet_number); + sampler_.OnPacketLost(QuicPacketNumber(packet_number)); } // Sends one packet and acks it. Then, send 20 packets. Finally, send // another 20 packets while acknowledging previous 20. void Send40PacketsAndAckFirst20(QuicTime::Delta time_between_packets) { // Send 20 packets at a constant inter-packet time. - for (QuicPacketNumber i = 1; i <= 20; i++) { + for (int i = 1; i <= 20; i++) { SendPacket(i); clock_.AdvanceTime(time_between_packets); } // Ack packets 1 to 20, while sending new packets at the same rate as // before. - for (QuicPacketNumber i = 1; i <= 20; i++) { + for (int i = 1; i <= 20; i++) { AckPacket(i); SendPacket(i + 20); clock_.AdvanceTime(time_between_packets); @@ -102,7 +103,7 @@ QuicBandwidth::FromBytesPerSecond(kRegularPacketSize * 100); // Send packets at the constant bandwidth. - for (QuicPacketNumber i = 1; i < 20; i++) { + for (int i = 1; i < 20; i++) { SendPacket(i); clock_.AdvanceTime(time_between_packets); QuicBandwidth current_sample = AckPacket(i); @@ -110,7 +111,7 @@ } // Send packets at the exponentially decreasing bandwidth. - for (QuicPacketNumber i = 20; i < 25; i++) { + for (int i = 20; i < 25; i++) { time_between_packets = time_between_packets * 2; expected_bandwidth = expected_bandwidth * 0.5; @@ -135,7 +136,7 @@ // Ack the packets 21 to 40, arriving at the correct bandwidth. QuicBandwidth last_bandwidth = QuicBandwidth::Zero(); - for (QuicPacketNumber i = 21; i <= 40; i++) { + for (int i = 21; i <= 40; i++) { last_bandwidth = AckPacket(i); EXPECT_EQ(expected_bandwidth, last_bandwidth); clock_.AdvanceTime(time_between_packets); @@ -152,14 +153,14 @@ QuicBandwidth::FromKBytesPerSecond(kRegularPacketSize) * 0.5; // Send 20 packets, each 1 ms apart. - for (QuicPacketNumber i = 1; i <= 20; i++) { + for (int i = 1; i <= 20; i++) { SendPacket(i); clock_.AdvanceTime(time_between_packets); } // Ack packets 1 to 20, losing every even-numbered packet, while sending new // packets at the same rate as before. - for (QuicPacketNumber i = 1; i <= 20; i++) { + for (int i = 1; i <= 20; i++) { if (i % 2 == 0) { AckPacket(i); } else { @@ -171,7 +172,7 @@ // Ack the packets 21 to 40 with the same loss pattern. QuicBandwidth last_bandwidth = QuicBandwidth::Zero(); - for (QuicPacketNumber i = 21; i <= 40; i++) { + for (int i = 21; i <= 40; i++) { if (i % 2 == 0) { last_bandwidth = AckPacket(i); EXPECT_EQ(expected_bandwidth, last_bandwidth); @@ -196,7 +197,7 @@ // Send 20 packets, each 1 ms apart. Every even packet is not congestion // controlled. - for (QuicPacketNumber i = 1; i <= 20; i++) { + for (int i = 1; i <= 20; i++) { SendPacketInner( i, kRegularPacketSize, i % 2 == 0 ? HAS_RETRANSMITTABLE_DATA : NO_RETRANSMITTABLE_DATA); @@ -208,7 +209,7 @@ // Ack packets 2 to 21, ignoring every even-numbered packet, while sending new // packets at the same rate as before. - for (QuicPacketNumber i = 1; i <= 20; i++) { + for (int i = 1; i <= 20; i++) { if (i % 2 == 0) { AckPacket(i); } @@ -220,7 +221,7 @@ // Ack the packets 22 to 41 with the same congestion controlled pattern. QuicBandwidth last_bandwidth = QuicBandwidth::Zero(); - for (QuicPacketNumber i = 21; i <= 40; i++) { + for (int i = 21; i <= 40; i++) { if (i % 2 == 0) { last_bandwidth = AckPacket(i); EXPECT_EQ(expected_bandwidth, last_bandwidth); @@ -251,7 +252,7 @@ QuicBandwidth last_bandwidth = QuicBandwidth::Zero(); QuicTime::Delta ridiculously_small_time_delta = QuicTime::Delta::FromMicroseconds(20); - for (QuicPacketNumber i = 21; i <= 40; i++) { + for (int i = 21; i <= 40; i++) { last_bandwidth = AckPacket(i); clock_.AdvanceTime(ridiculously_small_time_delta); } @@ -272,7 +273,7 @@ // Ack the packets 21 to 40 in the reverse order, while sending packets 41 to // 60. QuicBandwidth last_bandwidth = QuicBandwidth::Zero(); - for (QuicPacketNumber i = 0; i < 20; i++) { + for (int i = 0; i < 20; i++) { last_bandwidth = AckPacket(40 - i); EXPECT_EQ(expected_bandwidth, last_bandwidth); SendPacket(41 + i); @@ -280,7 +281,7 @@ } // Ack the packets 41 to 60, now in the regular order. - for (QuicPacketNumber i = 41; i <= 60; i++) { + for (int i = 41; i <= 60; i++) { last_bandwidth = AckPacket(i); EXPECT_EQ(expected_bandwidth, last_bandwidth); clock_.AdvanceTime(time_between_packets); @@ -301,7 +302,7 @@ // We are now app-limited. Ack 21 to 40 as usual, but do not send anything for // now. sampler_.OnAppLimited(); - for (QuicPacketNumber i = 21; i <= 40; i++) { + for (int i = 21; i <= 40; i++) { QuicBandwidth current_sample = AckPacket(i); EXPECT_EQ(expected_bandwidth, current_sample); clock_.AdvanceTime(time_between_packets); @@ -311,14 +312,14 @@ clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1)); // Send packets 41 to 60, all of which would be marked as app-limited. - for (QuicPacketNumber i = 41; i <= 60; i++) { + for (int i = 41; i <= 60; i++) { SendPacket(i); clock_.AdvanceTime(time_between_packets); } // Ack packets 41 to 60, while sending packets 61 to 80. 41 to 60 should be // app-limited and underestimate the bandwidth due to that. - for (QuicPacketNumber i = 41; i <= 60; i++) { + for (int i = 41; i <= 60; i++) { BandwidthSample sample = AckPacketInner(i); EXPECT_TRUE(sample.is_app_limited); EXPECT_LT(sample.bandwidth, 0.7f * expected_bandwidth); @@ -329,7 +330,7 @@ // Run out of packets, and then ack packet 61 to 80, all of which should have // correct non-app-limited samples. - for (QuicPacketNumber i = 61; i <= 80; i++) { + for (int i = 61; i <= 80; i++) { QuicBandwidth last_bandwidth = AckPacket(i); EXPECT_EQ(expected_bandwidth, last_bandwidth); clock_.AdvanceTime(time_between_packets); @@ -349,7 +350,7 @@ const QuicBandwidth real_bandwidth = QuicBandwidth::FromBytesAndTimeDelta(num_bytes, rtt); - for (QuicPacketNumber i = 1; i <= 10; i++) { + for (int i = 1; i <= 10; i++) { SendPacket(i); clock_.AdvanceTime(time_between_packets); } @@ -357,7 +358,7 @@ clock_.AdvanceTime(rtt - num_packets * time_between_packets); QuicBandwidth last_sample = QuicBandwidth::Zero(); - for (QuicPacketNumber i = 1; i <= 10; i++) { + for (int i = 1; i <= 10; i++) { QuicBandwidth sample = AckPacket(i); EXPECT_GT(sample, last_sample); last_sample = sample; @@ -385,9 +386,9 @@ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(100)); EXPECT_EQ(5u, BandwidthSamplerPeer::GetNumberOfTrackedPackets(sampler_)); - sampler_.RemoveObsoletePackets(4); + sampler_.RemoveObsoletePackets(QuicPacketNumber(4)); EXPECT_EQ(2u, BandwidthSamplerPeer::GetNumberOfTrackedPackets(sampler_)); - sampler_.OnPacketLost(4); + sampler_.OnPacketLost(QuicPacketNumber(4)); EXPECT_EQ(1u, BandwidthSamplerPeer::GetNumberOfTrackedPackets(sampler_)); AckPacket(5); EXPECT_EQ(0u, BandwidthSamplerPeer::GetNumberOfTrackedPackets(sampler_));
diff --git a/quic/core/congestion_control/bbr_sender.cc b/quic/core/congestion_control/bbr_sender.cc index 81931a1..6a7fe2b 100644 --- a/quic/core/congestion_control/bbr_sender.cc +++ b/quic/core/congestion_control/bbr_sender.cc
@@ -87,8 +87,6 @@ random_(random), mode_(STARTUP), round_trip_count_(0), - last_sent_packet_(0), - current_round_trip_end_(0), max_bandwidth_(kBandwidthWindowSize, QuicBandwidth::Zero(), 0), max_ack_height_(kBandwidthWindowSize, 0, 0), aggregation_epoch_start_time_(QuicTime::Zero()), @@ -122,14 +120,12 @@ has_non_app_limited_sample_(false), flexible_app_limited_(false), recovery_state_(NOT_IN_RECOVERY), - end_recovery_at_(0), recovery_window_(max_congestion_window_), is_app_limited_recovery_(false), slower_startup_(false), rate_based_startup_(false), startup_rate_reduction_multiplier_(0), startup_bytes_lost_(0), - initial_conservation_in_startup_(CONSERVATION), enable_ack_aggregation_during_startup_(false), expire_ack_aggregation_in_startup_(false), drain_to_target_(false), @@ -263,12 +259,6 @@ if (config.HasClientRequestedIndependentOption(kBBS1, perspective)) { rate_based_startup_ = true; } - if (config.HasClientRequestedIndependentOption(kBBS2, perspective)) { - initial_conservation_in_startup_ = MEDIUM_GROWTH; - } - if (config.HasClientRequestedIndependentOption(kBBS3, perspective)) { - initial_conservation_in_startup_ = GROWTH; - } if (GetQuicReloadableFlag(quic_bbr_startup_rate_reduction) && config.HasClientRequestedIndependentOption(kBBS4, perspective)) { rate_based_startup_ = true; @@ -467,7 +457,8 @@ } bool BbrSender::UpdateRoundTripCounter(QuicPacketNumber last_acked_packet) { - if (last_acked_packet > current_round_trip_end_) { + if (!current_round_trip_end_.IsInitialized() || + last_acked_packet > current_round_trip_end_) { round_trip_count_++; current_round_trip_end_ = last_sent_packet_; return true; @@ -677,9 +668,6 @@ // Enter conservation on the first loss. if (has_losses) { recovery_state_ = CONSERVATION; - if (mode_ == STARTUP) { - recovery_state_ = initial_conservation_in_startup_; - } // This will cause the |recovery_window_| to be set to the correct // value in CalculateRecoveryWindow(). recovery_window_ = 0; @@ -695,7 +683,6 @@ break; case CONSERVATION: - case MEDIUM_GROWTH: if (is_round_start) { recovery_state_ = GROWTH; } @@ -759,7 +746,7 @@ return; } // Slow the pacing rate in STARTUP once loss has ever been detected. - const bool has_ever_detected_loss = end_recovery_at_ > 0; + const bool has_ever_detected_loss = end_recovery_at_.IsInitialized(); if (slower_startup_ && has_ever_detected_loss && has_non_app_limited_sample_) { pacing_rate_ = kStartupAfterLossGain * BandwidthEstimate(); @@ -848,11 +835,8 @@ // In CONSERVATION mode, just subtracting losses is sufficient. In GROWTH, // release additional |bytes_acked| to achieve a slow-start-like behavior. - // In MEDIUM_GROWTH, release |bytes_acked| / 2 to split the difference. if (recovery_state_ == GROWTH) { recovery_window_ += bytes_acked; - } else if (recovery_state_ == MEDIUM_GROWTH) { - recovery_window_ += bytes_acked / 2; } // Sanity checks. Ensure that we always allow to send at least an MSS or
diff --git a/quic/core/congestion_control/bbr_sender.h b/quic/core/congestion_control/bbr_sender.h index 0ee730c..37e2695 100644 --- a/quic/core/congestion_control/bbr_sender.h +++ b/quic/core/congestion_control/bbr_sender.h
@@ -58,8 +58,6 @@ NOT_IN_RECOVERY, // Allow an extra outstanding byte for each byte acknowledged. CONSERVATION, - // Allow 1.5 extra outstanding bytes for each byte acknowledged. - MEDIUM_GROWTH, // Allow two extra outstanding bytes for each byte acknowledged (slow // start). GROWTH @@ -265,7 +263,7 @@ QuicPacketNumber last_sent_packet_; // Acknowledgement of any packet after |current_round_trip_end_| will cause // the round trip counter to advance. - QuicPacketCount current_round_trip_end_; + QuicPacketNumber current_round_trip_end_; // The filter that tracks the maximum bandwidth over the multiple recent // round-trips. @@ -375,8 +373,6 @@ // Sum of bytes lost in STARTUP. QuicByteCount startup_bytes_lost_; - // Used as the initial packet conservation mode when first entering recovery. - RecoveryState initial_conservation_in_startup_; // When true, add the most recent ack aggregation measurement during STARTUP. bool enable_ack_aggregation_during_startup_; // When true, expire the windowed ack aggregation values in STARTUP when
diff --git a/quic/core/congestion_control/bbr_sender_test.cc b/quic/core/congestion_control/bbr_sender_test.cc index bc7fc76..e0d5867 100644 --- a/quic/core/congestion_control/bbr_sender_test.cc +++ b/quic/core/congestion_control/bbr_sender_test.cc
@@ -515,97 +515,6 @@ ASSERT_TRUE(simulator_result); } -// Ensures the code transitions loss recovery states correctly when in STARTUP -// and the BBS2 connection option is used. -// (NOT_IN_RECOVERY -> CONSERVATION -> GROWTH -> NOT_IN_RECOVERY). -TEST_F(BbrSenderTest, StartupMediumRecoveryStates) { - // Set seed to the position where the gain cycling causes the sender go - // into conservation upon entering PROBE_BW. - // - // TODO(vasilvv): there should be a better way to test this. - random_.set_seed(UINT64_C(14719894707049085006)); - - const QuicTime::Delta timeout = QuicTime::Delta::FromSeconds(10); - bool simulator_result; - CreateSmallBufferSetup(); - SetConnectionOption(kBBS2); - - bbr_sender_.AddBytesToTransfer(100 * 1024 * 1024); - ASSERT_EQ(BbrSender::NOT_IN_RECOVERY, - sender_->ExportDebugState().recovery_state); - - simulator_result = simulator_.RunUntilOrTimeout( - [this]() { - return sender_->ExportDebugState().recovery_state != - BbrSender::NOT_IN_RECOVERY; - }, - timeout); - ASSERT_TRUE(simulator_result); - ASSERT_EQ(BbrSender::MEDIUM_GROWTH, - sender_->ExportDebugState().recovery_state); - - simulator_result = simulator_.RunUntilOrTimeout( - [this]() { - return sender_->ExportDebugState().recovery_state != - BbrSender::MEDIUM_GROWTH; - }, - timeout); - ASSERT_TRUE(simulator_result); - ASSERT_EQ(BbrSender::GROWTH, sender_->ExportDebugState().recovery_state); - - simulator_result = simulator_.RunUntilOrTimeout( - [this]() { - return sender_->ExportDebugState().recovery_state != BbrSender::GROWTH; - }, - timeout); - - ASSERT_EQ(BbrSender::PROBE_BW, sender_->ExportDebugState().mode); - ASSERT_EQ(BbrSender::NOT_IN_RECOVERY, - sender_->ExportDebugState().recovery_state); - ASSERT_TRUE(simulator_result); -} - -// Ensures the code transitions loss recovery states correctly when in STARTUP -// and the BBS3 connection option is used. -// (NOT_IN_RECOVERY -> GROWTH -> NOT_IN_RECOVERY). -TEST_F(BbrSenderTest, StartupGrowthRecoveryStates) { - // Set seed to the position where the gain cycling causes the sender go - // into conservation upon entering PROBE_BW. - // - // TODO(vasilvv): there should be a better way to test this. - random_.set_seed(UINT64_C(14719894707049085006)); - - const QuicTime::Delta timeout = QuicTime::Delta::FromSeconds(10); - bool simulator_result; - CreateSmallBufferSetup(); - SetConnectionOption(kBBS3); - - bbr_sender_.AddBytesToTransfer(100 * 1024 * 1024); - ASSERT_EQ(BbrSender::NOT_IN_RECOVERY, - sender_->ExportDebugState().recovery_state); - - simulator_result = simulator_.RunUntilOrTimeout( - [this]() { - return sender_->ExportDebugState().recovery_state != - BbrSender::NOT_IN_RECOVERY; - }, - timeout); - ASSERT_TRUE(simulator_result); - ASSERT_EQ(BbrSender::GROWTH, sender_->ExportDebugState().recovery_state); - - simulator_result = simulator_.RunUntilOrTimeout( - [this]() { - return sender_->ExportDebugState().recovery_state != BbrSender::GROWTH; - }, - timeout); - ASSERT_TRUE(simulator_result); - - ASSERT_EQ(BbrSender::PROBE_BW, sender_->ExportDebugState().mode); - ASSERT_EQ(BbrSender::NOT_IN_RECOVERY, - sender_->ExportDebugState().recovery_state); - ASSERT_TRUE(simulator_result); -} - // Verify the behavior of the algorithm in the case when the connection sends // small bursts of data after sending continuously for a while. TEST_F(BbrSenderTest, ApplicationLimitedBursts) { @@ -1185,7 +1094,7 @@ QuicBandwidth pacing_rate = original_pacing_rate; const QuicByteCount original_cwnd = sender_->GetCongestionWindow(); LostPacketVector lost_packets; - lost_packets.push_back(LostPacket(0, kMaxPacketSize)); + lost_packets.push_back(LostPacket(QuicPacketNumber(), kMaxPacketSize)); QuicPacketNumber largest_sent = bbr_sender_.connection()->sent_packet_manager().GetLargestSentPacket(); for (QuicPacketNumber packet_number = @@ -1235,7 +1144,7 @@ QuicBandwidth pacing_rate = original_pacing_rate; const QuicByteCount original_cwnd = sender_->GetCongestionWindow(); LostPacketVector lost_packets; - lost_packets.push_back(LostPacket(0, kMaxPacketSize)); + lost_packets.push_back(LostPacket(QuicPacketNumber(), kMaxPacketSize)); QuicPacketNumber largest_sent = bbr_sender_.connection()->sent_packet_manager().GetLargestSentPacket(); for (QuicPacketNumber packet_number =
diff --git a/quic/core/congestion_control/general_loss_algorithm.cc b/quic/core/congestion_control/general_loss_algorithm.cc index 7250940..27a3ab8 100644 --- a/quic/core/congestion_control/general_loss_algorithm.cc +++ b/quic/core/congestion_control/general_loss_algorithm.cc
@@ -31,7 +31,6 @@ GeneralLossAlgorithm::GeneralLossAlgorithm(LossDetectionType loss_type) : loss_detection_timeout_(QuicTime::Zero()), - largest_lost_(0), least_in_flight_(1), faster_detect_loss_(GetQuicReloadableFlag(quic_faster_detect_loss)) { SetLossDetectionType(loss_type); @@ -39,7 +38,7 @@ void GeneralLossAlgorithm::SetLossDetectionType(LossDetectionType loss_type) { loss_detection_timeout_ = QuicTime::Zero(); - largest_sent_on_spurious_retransmit_ = kInvalidPacketNumber; + largest_sent_on_spurious_retransmit_.Clear(); loss_type_ = loss_type; reordering_shift_ = loss_type == kAdaptiveTime ? kDefaultAdaptiveLossDelayShift @@ -49,7 +48,7 @@ QUIC_RELOADABLE_FLAG_COUNT(quic_eighth_rtt_loss_detection); reordering_shift_ = 3; } - largest_previously_acked_ = kInvalidPacketNumber; + largest_previously_acked_.Clear(); } LossDetectionType GeneralLossAlgorithm::GetLossDetectionType() const { @@ -91,7 +90,7 @@ QuicPacketNumber packet_number = unacked_packets.GetLeastUnacked(); auto it = unacked_packets.begin(); if (faster_detect_loss_) { - if (least_in_flight_ >= packet_number) { + 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: " @@ -103,9 +102,9 @@ } } // Clear least_in_flight_. - least_in_flight_ = kInvalidPacketNumber; + least_in_flight_.Clear(); } else { - if (largest_lost_ >= packet_number) { + 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: " @@ -132,7 +131,8 @@ } else if (loss_type_ == kLazyFack) { // Require two in order acks to invoke FACK, which avoids spuriously // retransmitting packets when one packet is reordered by a large amount. - if (largest_newly_acked > largest_previously_acked_ && + if (largest_previously_acked_.IsInitialized() && + largest_newly_acked > largest_previously_acked_ && largest_previously_acked_ > packet_number && largest_previously_acked_ - packet_number >= (kNumberOfNacksBeforeRetransmission - 1)) { @@ -150,7 +150,7 @@ QuicTime when_lost = it->sent_time + loss_delay; if (time < when_lost) { loss_detection_timeout_ = when_lost; - if (least_in_flight_ == kInvalidPacketNumber) { + if (!least_in_flight_.IsInitialized()) { // At this point, packet_number is in flight and not detected as lost. least_in_flight_ = packet_number; } @@ -166,18 +166,19 @@ packets_lost->push_back(LostPacket(packet_number, it->bytes_sent)); continue; } - if (least_in_flight_ == kInvalidPacketNumber) { + if (!least_in_flight_.IsInitialized()) { // At this point, packet_number is in flight and not detected as lost. least_in_flight_ = packet_number; } } - if (least_in_flight_ == kInvalidPacketNumber) { + if (!least_in_flight_.IsInitialized()) { // There is no in flight packet. least_in_flight_ = largest_newly_acked + 1; } largest_previously_acked_ = largest_newly_acked; if (!packets_lost->empty()) { - DCHECK_LT(largest_lost_, packets_lost->back().packet_number); + DCHECK(!largest_lost_.IsInitialized() || + largest_lost_ < packets_lost->back().packet_number); largest_lost_ = packets_lost->back().packet_number; } } @@ -212,7 +213,8 @@ return; } - if (spurious_retransmission <= largest_sent_on_spurious_retransmit_) { + if (largest_sent_on_spurious_retransmit_.IsInitialized() && + spurious_retransmission <= largest_sent_on_spurious_retransmit_) { return; } largest_sent_on_spurious_retransmit_ = unacked_packets.largest_sent_packet();
diff --git a/quic/core/congestion_control/general_loss_algorithm_test.cc b/quic/core/congestion_control/general_loss_algorithm_test.cc index 7a8ec67..2cd19a7 100644 --- a/quic/core/congestion_control/general_loss_algorithm_test.cc +++ b/quic/core/congestion_control/general_loss_algorithm_test.cc
@@ -31,37 +31,43 @@ ~GeneralLossAlgorithmTest() override {} - void SendDataPacket(QuicPacketNumber packet_number) { + void SendDataPacket(uint64_t packet_number) { QuicStreamFrame frame; frame.stream_id = QuicUtils::GetHeadersStreamId( CurrentSupportedVersions()[0].transport_version); - SerializedPacket packet(packet_number, PACKET_1BYTE_PACKET_NUMBER, nullptr, - kDefaultLength, false, false); + SerializedPacket packet(QuicPacketNumber(packet_number), + PACKET_1BYTE_PACKET_NUMBER, nullptr, kDefaultLength, + false, false); packet.retransmittable_frames.push_back(QuicFrame(frame)); - unacked_packets_.AddSentPacket(&packet, 0, NOT_RETRANSMISSION, clock_.Now(), - true); + unacked_packets_.AddSentPacket(&packet, QuicPacketNumber(), + NOT_RETRANSMISSION, clock_.Now(), true); } - void SendAckPacket(QuicPacketNumber packet_number) { - SerializedPacket packet(packet_number, PACKET_1BYTE_PACKET_NUMBER, nullptr, - kDefaultLength, true, false); - unacked_packets_.AddSentPacket(&packet, 0, NOT_RETRANSMISSION, clock_.Now(), - false); + void SendAckPacket(uint64_t packet_number) { + SerializedPacket packet(QuicPacketNumber(packet_number), + PACKET_1BYTE_PACKET_NUMBER, nullptr, kDefaultLength, + true, false); + unacked_packets_.AddSentPacket(&packet, QuicPacketNumber(), + NOT_RETRANSMISSION, clock_.Now(), false); } - void VerifyLosses(QuicPacketNumber largest_newly_acked, + void VerifyLosses(uint64_t largest_newly_acked, const AckedPacketVector& packets_acked, - const std::vector<QuicPacketNumber>& losses_expected) { - if (largest_newly_acked > unacked_packets_.largest_acked()) { - unacked_packets_.IncreaseLargestAcked(largest_newly_acked); + const std::vector<uint64_t>& losses_expected) { + if (!unacked_packets_.largest_acked().IsInitialized() || + QuicPacketNumber(largest_newly_acked) > + unacked_packets_.largest_acked()) { + unacked_packets_.IncreaseLargestAcked( + QuicPacketNumber(largest_newly_acked)); } LostPacketVector lost_packets; loss_algorithm_.DetectLosses(unacked_packets_, clock_.Now(), rtt_stats_, - largest_newly_acked, packets_acked, - &lost_packets); + 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, losses_expected[i]); + EXPECT_EQ(lost_packets[i].packet_number, + QuicPacketNumber(losses_expected[i])); } } @@ -79,18 +85,21 @@ } AckedPacketVector packets_acked; // No loss on one ack. - unacked_packets_.RemoveFromInFlight(2); - packets_acked.push_back(AckedPacket(2, kMaxPacketSize, QuicTime::Zero())); - VerifyLosses(2, packets_acked, std::vector<QuicPacketNumber>{}); + unacked_packets_.RemoveFromInFlight(QuicPacketNumber(2)); + packets_acked.push_back( + AckedPacket(QuicPacketNumber(2), kMaxPacketSize, QuicTime::Zero())); + VerifyLosses(2, packets_acked, std::vector<uint64_t>{}); packets_acked.clear(); // No loss on two acks. - unacked_packets_.RemoveFromInFlight(3); - packets_acked.push_back(AckedPacket(3, kMaxPacketSize, QuicTime::Zero())); - VerifyLosses(3, packets_acked, std::vector<QuicPacketNumber>{}); + unacked_packets_.RemoveFromInFlight(QuicPacketNumber(3)); + packets_acked.push_back( + AckedPacket(QuicPacketNumber(3), kMaxPacketSize, QuicTime::Zero())); + VerifyLosses(3, packets_acked, std::vector<uint64_t>{}); packets_acked.clear(); // Loss on three acks. - unacked_packets_.RemoveFromInFlight(4); - packets_acked.push_back(AckedPacket(4, kMaxPacketSize, QuicTime::Zero())); + unacked_packets_.RemoveFromInFlight(QuicPacketNumber(4)); + packets_acked.push_back( + AckedPacket(QuicPacketNumber(4), kMaxPacketSize, QuicTime::Zero())); VerifyLosses(4, packets_acked, {1}); EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); } @@ -105,12 +114,15 @@ } AckedPacketVector packets_acked; // Nack the first packet 3 times in a single StretchAck. - unacked_packets_.RemoveFromInFlight(2); - packets_acked.push_back(AckedPacket(2, kMaxPacketSize, QuicTime::Zero())); - unacked_packets_.RemoveFromInFlight(3); - packets_acked.push_back(AckedPacket(3, kMaxPacketSize, QuicTime::Zero())); - unacked_packets_.RemoveFromInFlight(4); - packets_acked.push_back(AckedPacket(4, kMaxPacketSize, QuicTime::Zero())); + unacked_packets_.RemoveFromInFlight(QuicPacketNumber(2)); + packets_acked.push_back( + AckedPacket(QuicPacketNumber(2), kMaxPacketSize, QuicTime::Zero())); + unacked_packets_.RemoveFromInFlight(QuicPacketNumber(3)); + packets_acked.push_back( + AckedPacket(QuicPacketNumber(3), kMaxPacketSize, QuicTime::Zero())); + unacked_packets_.RemoveFromInFlight(QuicPacketNumber(4)); + packets_acked.push_back( + AckedPacket(QuicPacketNumber(4), kMaxPacketSize, QuicTime::Zero())); VerifyLosses(4, packets_acked, {1}); EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); } @@ -124,8 +136,9 @@ } AckedPacketVector packets_acked; // Nack the first packet 3 times in an AckFrame with three missing packets. - unacked_packets_.RemoveFromInFlight(4); - packets_acked.push_back(AckedPacket(4, kMaxPacketSize, QuicTime::Zero())); + unacked_packets_.RemoveFromInFlight(QuicPacketNumber(4)); + packets_acked.push_back( + AckedPacket(QuicPacketNumber(4), kMaxPacketSize, QuicTime::Zero())); VerifyLosses(4, packets_acked, {1}); EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); } @@ -138,9 +151,10 @@ } AckedPacketVector packets_acked; // Early retransmit when the final packet gets acked and the first is nacked. - unacked_packets_.RemoveFromInFlight(2); - packets_acked.push_back(AckedPacket(2, kMaxPacketSize, QuicTime::Zero())); - VerifyLosses(2, packets_acked, std::vector<QuicPacketNumber>{}); + unacked_packets_.RemoveFromInFlight(QuicPacketNumber(2)); + packets_acked.push_back( + AckedPacket(QuicPacketNumber(2), kMaxPacketSize, QuicTime::Zero())); + VerifyLosses(2, packets_acked, std::vector<uint64_t>{}); packets_acked.clear(); EXPECT_EQ(clock_.Now() + 1.25 * rtt_stats_.smoothed_rtt(), loss_algorithm_.GetLossTimeout()); @@ -162,9 +176,9 @@ AckedPacketVector packets_acked; // Early retransmit when the final packet gets acked and 1.25 RTTs have // elapsed since the packets were sent. - unacked_packets_.RemoveFromInFlight(kNumSentPackets); - packets_acked.push_back( - AckedPacket(kNumSentPackets, kMaxPacketSize, QuicTime::Zero())); + unacked_packets_.RemoveFromInFlight(QuicPacketNumber(kNumSentPackets)); + packets_acked.push_back(AckedPacket(QuicPacketNumber(kNumSentPackets), + kMaxPacketSize, QuicTime::Zero())); // This simulates a single ack following multiple missing packets with FACK. VerifyLosses(kNumSentPackets, packets_acked, {1, 2}); packets_acked.clear(); @@ -190,14 +204,15 @@ } AckedPacketVector packets_acked; // Neuter packet 1. - unacked_packets_.RemoveRetransmittability(1); + unacked_packets_.RemoveRetransmittability(QuicPacketNumber(1)); clock_.AdvanceTime(rtt_stats_.smoothed_rtt()); // Early retransmit when the final packet gets acked and the first is nacked. - unacked_packets_.IncreaseLargestAcked(2); - unacked_packets_.RemoveFromInFlight(2); - packets_acked.push_back(AckedPacket(2, kMaxPacketSize, QuicTime::Zero())); - VerifyLosses(2, packets_acked, std::vector<QuicPacketNumber>{}); + unacked_packets_.IncreaseLargestAcked(QuicPacketNumber(2)); + unacked_packets_.RemoveFromInFlight(QuicPacketNumber(2)); + packets_acked.push_back( + AckedPacket(QuicPacketNumber(2), kMaxPacketSize, QuicTime::Zero())); + VerifyLosses(2, packets_acked, std::vector<uint64_t>{}); EXPECT_EQ(clock_.Now() + 0.25 * rtt_stats_.smoothed_rtt(), loss_algorithm_.GetLossTimeout()); } @@ -211,10 +226,11 @@ clock_.AdvanceTime(rtt_stats_.smoothed_rtt()); // Early retransmit when the final packet gets acked and the first is nacked. - unacked_packets_.IncreaseLargestAcked(2); - unacked_packets_.RemoveFromInFlight(2); - packets_acked.push_back(AckedPacket(2, kMaxPacketSize, QuicTime::Zero())); - VerifyLosses(2, packets_acked, std::vector<QuicPacketNumber>{}); + unacked_packets_.IncreaseLargestAcked(QuicPacketNumber(2)); + unacked_packets_.RemoveFromInFlight(QuicPacketNumber(2)); + packets_acked.push_back( + AckedPacket(QuicPacketNumber(2), kMaxPacketSize, QuicTime::Zero())); + VerifyLosses(2, packets_acked, std::vector<uint64_t>{}); packets_acked.clear(); EXPECT_EQ(clock_.Now() + 0.25 * rtt_stats_.smoothed_rtt(), loss_algorithm_.GetLossTimeout()); @@ -237,9 +253,10 @@ AckedPacketVector packets_acked; // Wait another RTT and ack 2. clock_.AdvanceTime(rtt_stats_.smoothed_rtt()); - unacked_packets_.IncreaseLargestAcked(2); - unacked_packets_.RemoveFromInFlight(2); - packets_acked.push_back(AckedPacket(2, kMaxPacketSize, QuicTime::Zero())); + unacked_packets_.IncreaseLargestAcked(QuicPacketNumber(2)); + unacked_packets_.RemoveFromInFlight(QuicPacketNumber(2)); + packets_acked.push_back( + AckedPacket(QuicPacketNumber(2), kMaxPacketSize, QuicTime::Zero())); VerifyLosses(2, packets_acked, {1}); } @@ -253,18 +270,21 @@ } AckedPacketVector packets_acked; // No loss on one ack. - unacked_packets_.RemoveFromInFlight(2); - packets_acked.push_back(AckedPacket(2, kMaxPacketSize, QuicTime::Zero())); - VerifyLosses(2, packets_acked, std::vector<QuicPacketNumber>{}); + unacked_packets_.RemoveFromInFlight(QuicPacketNumber(2)); + packets_acked.push_back( + AckedPacket(QuicPacketNumber(2), kMaxPacketSize, QuicTime::Zero())); + VerifyLosses(2, packets_acked, std::vector<uint64_t>{}); packets_acked.clear(); // No loss on two acks. - unacked_packets_.RemoveFromInFlight(3); - packets_acked.push_back(AckedPacket(3, kMaxPacketSize, QuicTime::Zero())); - VerifyLosses(3, packets_acked, std::vector<QuicPacketNumber>{}); + unacked_packets_.RemoveFromInFlight(QuicPacketNumber(3)); + packets_acked.push_back( + AckedPacket(QuicPacketNumber(3), kMaxPacketSize, QuicTime::Zero())); + VerifyLosses(3, packets_acked, std::vector<uint64_t>{}); packets_acked.clear(); // Loss on three acks. - unacked_packets_.RemoveFromInFlight(4); - packets_acked.push_back(AckedPacket(4, kMaxPacketSize, QuicTime::Zero())); + unacked_packets_.RemoveFromInFlight(QuicPacketNumber(4)); + packets_acked.push_back( + AckedPacket(QuicPacketNumber(4), kMaxPacketSize, QuicTime::Zero())); VerifyLosses(4, packets_acked, {1}); EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); } @@ -281,19 +301,23 @@ } AckedPacketVector packets_acked; // Nack the first packet 3 times in a single StretchAck. - unacked_packets_.RemoveFromInFlight(2); - packets_acked.push_back(AckedPacket(2, kMaxPacketSize, QuicTime::Zero())); - unacked_packets_.RemoveFromInFlight(3); - packets_acked.push_back(AckedPacket(3, kMaxPacketSize, QuicTime::Zero())); - unacked_packets_.RemoveFromInFlight(4); - packets_acked.push_back(AckedPacket(4, kMaxPacketSize, QuicTime::Zero())); - VerifyLosses(4, packets_acked, std::vector<QuicPacketNumber>{}); + unacked_packets_.RemoveFromInFlight(QuicPacketNumber(2)); + packets_acked.push_back( + AckedPacket(QuicPacketNumber(2), kMaxPacketSize, QuicTime::Zero())); + unacked_packets_.RemoveFromInFlight(QuicPacketNumber(3)); + packets_acked.push_back( + AckedPacket(QuicPacketNumber(3), kMaxPacketSize, QuicTime::Zero())); + unacked_packets_.RemoveFromInFlight(QuicPacketNumber(4)); + packets_acked.push_back( + AckedPacket(QuicPacketNumber(4), kMaxPacketSize, QuicTime::Zero())); + VerifyLosses(4, packets_acked, std::vector<uint64_t>{}); packets_acked.clear(); // The timer isn't set because we expect more acks. EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); // Process another ack and then packet 1 will be lost. - unacked_packets_.RemoveFromInFlight(5); - packets_acked.push_back(AckedPacket(5, kMaxPacketSize, QuicTime::Zero())); + unacked_packets_.RemoveFromInFlight(QuicPacketNumber(5)); + packets_acked.push_back( + AckedPacket(QuicPacketNumber(5), kMaxPacketSize, QuicTime::Zero())); VerifyLosses(5, packets_acked, {1}); EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); } @@ -308,15 +332,17 @@ } AckedPacketVector packets_acked; // Nack the first packet 3 times in an AckFrame with three missing packets. - unacked_packets_.RemoveFromInFlight(4); - packets_acked.push_back(AckedPacket(4, kMaxPacketSize, QuicTime::Zero())); - VerifyLosses(4, packets_acked, std::vector<QuicPacketNumber>{}); + unacked_packets_.RemoveFromInFlight(QuicPacketNumber(4)); + packets_acked.push_back( + AckedPacket(QuicPacketNumber(4), kMaxPacketSize, QuicTime::Zero())); + VerifyLosses(4, packets_acked, std::vector<uint64_t>{}); packets_acked.clear(); // The timer isn't set because we expect more acks. EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); // Process another ack and then packet 1 and 2 will be lost. - unacked_packets_.RemoveFromInFlight(5); - packets_acked.push_back(AckedPacket(5, kMaxPacketSize, QuicTime::Zero())); + unacked_packets_.RemoveFromInFlight(QuicPacketNumber(5)); + packets_acked.push_back( + AckedPacket(QuicPacketNumber(5), kMaxPacketSize, QuicTime::Zero())); VerifyLosses(5, packets_acked, {1, 2}); EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); } @@ -330,10 +356,11 @@ SendDataPacket(i); } AckedPacketVector packets_acked; - unacked_packets_.RemoveFromInFlight(2); - packets_acked.push_back(AckedPacket(2, kMaxPacketSize, QuicTime::Zero())); + unacked_packets_.RemoveFromInFlight(QuicPacketNumber(2)); + packets_acked.push_back( + AckedPacket(QuicPacketNumber(2), kMaxPacketSize, QuicTime::Zero())); for (size_t i = 1; i < 500; ++i) { - VerifyLosses(2, packets_acked, std::vector<QuicPacketNumber>{}); + VerifyLosses(2, packets_acked, std::vector<uint64_t>{}); packets_acked.clear(); } if (GetQuicReloadableFlag(quic_eighth_rtt_loss_detection)) { @@ -357,9 +384,10 @@ // Expect the timer to not be set. EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); // The packet should not be lost until 1.25 RTTs pass. - unacked_packets_.RemoveFromInFlight(2); - packets_acked.push_back(AckedPacket(2, kMaxPacketSize, QuicTime::Zero())); - VerifyLosses(2, packets_acked, std::vector<QuicPacketNumber>{}); + unacked_packets_.RemoveFromInFlight(QuicPacketNumber(2)); + packets_acked.push_back( + AckedPacket(QuicPacketNumber(2), kMaxPacketSize, QuicTime::Zero())); + VerifyLosses(2, packets_acked, std::vector<uint64_t>{}); packets_acked.clear(); if (GetQuicReloadableFlag(quic_eighth_rtt_loss_detection)) { // Expect the timer to be set to 0.25 RTT's in the future. @@ -370,7 +398,7 @@ EXPECT_EQ(0.25 * rtt_stats_.smoothed_rtt(), loss_algorithm_.GetLossTimeout() - clock_.Now()); } - VerifyLosses(2, packets_acked, std::vector<QuicPacketNumber>{}); + VerifyLosses(2, packets_acked, std::vector<uint64_t>{}); clock_.AdvanceTime(0.25 * rtt_stats_.smoothed_rtt()); VerifyLosses(2, packets_acked, {1}); EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); @@ -388,16 +416,17 @@ // Expect the timer to not be set. EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); // The packet should not be lost without a nack. - unacked_packets_.RemoveFromInFlight(1); - packets_acked.push_back(AckedPacket(1, kMaxPacketSize, QuicTime::Zero())); - VerifyLosses(1, packets_acked, std::vector<QuicPacketNumber>{}); + unacked_packets_.RemoveFromInFlight(QuicPacketNumber(1)); + packets_acked.push_back( + AckedPacket(QuicPacketNumber(1), kMaxPacketSize, QuicTime::Zero())); + VerifyLosses(1, packets_acked, std::vector<uint64_t>{}); packets_acked.clear(); // The timer should still not be set. EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); clock_.AdvanceTime(0.25 * rtt_stats_.smoothed_rtt()); - VerifyLosses(1, packets_acked, std::vector<QuicPacketNumber>{}); + VerifyLosses(1, packets_acked, std::vector<uint64_t>{}); clock_.AdvanceTime(rtt_stats_.smoothed_rtt()); - VerifyLosses(1, packets_acked, std::vector<QuicPacketNumber>{}); + VerifyLosses(1, packets_acked, std::vector<uint64_t>{}); EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); } @@ -414,9 +443,10 @@ // Expect the timer to not be set. EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); // The packet should not be lost until 1.25 RTTs pass. - unacked_packets_.RemoveFromInFlight(10); - packets_acked.push_back(AckedPacket(10, kMaxPacketSize, QuicTime::Zero())); - VerifyLosses(10, packets_acked, std::vector<QuicPacketNumber>{}); + unacked_packets_.RemoveFromInFlight(QuicPacketNumber(10)); + packets_acked.push_back( + AckedPacket(QuicPacketNumber(10), kMaxPacketSize, QuicTime::Zero())); + VerifyLosses(10, packets_acked, std::vector<uint64_t>{}); packets_acked.clear(); if (GetQuicReloadableFlag(quic_eighth_rtt_loss_detection)) { // Expect the timer to be set to 0.25 RTT's in the future. @@ -445,9 +475,10 @@ EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); // The packet should not be lost until 1.25 RTTs pass. - unacked_packets_.RemoveFromInFlight(10); - packets_acked.push_back(AckedPacket(10, kMaxPacketSize, QuicTime::Zero())); - VerifyLosses(10, packets_acked, std::vector<QuicPacketNumber>{}); + unacked_packets_.RemoveFromInFlight(QuicPacketNumber(10)); + packets_acked.push_back( + AckedPacket(QuicPacketNumber(10), kMaxPacketSize, QuicTime::Zero())); + VerifyLosses(10, packets_acked, std::vector<uint64_t>{}); packets_acked.clear(); if (GetQuicReloadableFlag(quic_eighth_rtt_loss_detection)) { // Expect the timer to be set to 0.25 RTT's in the future. @@ -461,10 +492,11 @@ clock_.AdvanceTime(0.25 * rtt_stats_.smoothed_rtt()); // Now ack packets 1 to 9 and ensure the timer is no longer set and no packets // are lost. - for (QuicPacketNumber i = 1; i <= 9; ++i) { - unacked_packets_.RemoveFromInFlight(i); - packets_acked.push_back(AckedPacket(i, kMaxPacketSize, QuicTime::Zero())); - VerifyLosses(i, packets_acked, std::vector<QuicPacketNumber>{}); + for (uint64_t i = 1; i <= 9; ++i) { + unacked_packets_.RemoveFromInFlight(QuicPacketNumber(i)); + packets_acked.push_back( + AckedPacket(QuicPacketNumber(i), kMaxPacketSize, QuicTime::Zero())); + VerifyLosses(i, packets_acked, std::vector<uint64_t>{}); packets_acked.clear(); EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); } @@ -484,14 +516,15 @@ // Expect the timer to not be set. EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); // Packet 1 should not be lost until 1/16 RTTs pass. - unacked_packets_.RemoveFromInFlight(2); - packets_acked.push_back(AckedPacket(2, kMaxPacketSize, QuicTime::Zero())); - VerifyLosses(2, packets_acked, std::vector<QuicPacketNumber>{}); + unacked_packets_.RemoveFromInFlight(QuicPacketNumber(2)); + packets_acked.push_back( + AckedPacket(QuicPacketNumber(2), kMaxPacketSize, QuicTime::Zero())); + VerifyLosses(2, packets_acked, std::vector<uint64_t>{}); packets_acked.clear(); // Expect the timer to be set to 1/16 RTT's in the future. EXPECT_EQ(rtt_stats_.smoothed_rtt() * (1.0f / 16), loss_algorithm_.GetLossTimeout() - clock_.Now()); - VerifyLosses(2, packets_acked, std::vector<QuicPacketNumber>{}); + VerifyLosses(2, packets_acked, std::vector<uint64_t>{}); clock_.AdvanceTime(rtt_stats_.smoothed_rtt() * (1.0f / 16)); VerifyLosses(2, packets_acked, {1}); EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout()); @@ -508,13 +541,13 @@ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(1)); } loss_algorithm_.SpuriousRetransmitDetected(unacked_packets_, clock_.Now(), - rtt_stats_, 11); + rtt_stats_, QuicPacketNumber(11)); EXPECT_EQ(1, loss_algorithm_.reordering_shift()); // Detect another spurious retransmit and ensure the threshold doesn't // increase again. loss_algorithm_.SpuriousRetransmitDetected(unacked_packets_, clock_.Now(), - rtt_stats_, 12); + rtt_stats_, QuicPacketNumber(12)); EXPECT_EQ(1, loss_algorithm_.reordering_shift()); }
diff --git a/quic/core/congestion_control/hybrid_slow_start.cc b/quic/core/congestion_control/hybrid_slow_start.cc index 11a14e6..28963b1 100644 --- a/quic/core/congestion_control/hybrid_slow_start.cc +++ b/quic/core/congestion_control/hybrid_slow_start.cc
@@ -24,8 +24,6 @@ HybridSlowStart::HybridSlowStart() : started_(false), hystart_found_(NOT_FOUND), - last_sent_packet_number_(0), - end_packet_number_(0), rtt_sample_count_(0), current_min_rtt_(QuicTime::Delta::Zero()) {} @@ -56,7 +54,7 @@ } bool HybridSlowStart::IsEndOfRound(QuicPacketNumber ack) const { - return end_packet_number_ <= ack; + return !end_packet_number_.IsInitialized() || end_packet_number_ <= ack; } bool HybridSlowStart::ShouldExitSlowStart(QuicTime::Delta latest_rtt,
diff --git a/quic/core/congestion_control/hybrid_slow_start_test.cc b/quic/core/congestion_control/hybrid_slow_start_test.cc index c97c616..aa2f849 100644 --- a/quic/core/congestion_control/hybrid_slow_start_test.cc +++ b/quic/core/congestion_control/hybrid_slow_start_test.cc
@@ -24,8 +24,8 @@ }; TEST_F(HybridSlowStartTest, Simple) { - QuicPacketNumber packet_number = 1; - QuicPacketNumber end_packet_number = 3; + QuicPacketNumber packet_number(1); + QuicPacketNumber end_packet_number(3); slow_start_->StartReceiveRound(end_packet_number); EXPECT_FALSE(slow_start_->IsEndOfRound(packet_number++)); @@ -39,7 +39,7 @@ // Test without a new registered end_packet_number; EXPECT_TRUE(slow_start_->IsEndOfRound(packet_number++)); - end_packet_number = 20; + end_packet_number = QuicPacketNumber(20); slow_start_->StartReceiveRound(end_packet_number); while (packet_number < end_packet_number) { EXPECT_FALSE(slow_start_->IsEndOfRound(packet_number++)); @@ -52,7 +52,7 @@ // RTT of 60ms the detection will happen at 67.5 ms. const int kHybridStartMinSamples = 8; // Number of acks required to trigger. - QuicPacketNumber end_packet_number = 1; + QuicPacketNumber end_packet_number(1); slow_start_->StartReceiveRound(end_packet_number++); // Will not trigger since our lowest RTT in our burst is the same as the long
diff --git a/quic/core/congestion_control/pacing_sender_test.cc b/quic/core/congestion_control/pacing_sender_test.cc index 904fb8d..0bb9258 100644 --- a/quic/core/congestion_control/pacing_sender_test.cc +++ b/quic/core/congestion_control/pacing_sender_test.cc
@@ -50,7 +50,7 @@ if (burst_size == 0) { EXPECT_CALL(*mock_sender_, OnCongestionEvent(_, _, _, _, _)); LostPacketVector lost_packets; - lost_packets.push_back(LostPacket(1, kMaxPacketSize)); + lost_packets.push_back(LostPacket(QuicPacketNumber(1), kMaxPacketSize)); AckedPacketVector empty; pacing_sender_->OnCongestionEvent(true, 1234, clock_.Now(), empty, lost_packets); @@ -320,7 +320,7 @@ // Losing a packet will set clear burst tokens. LostPacketVector lost_packets; - lost_packets.push_back(LostPacket(1, kMaxPacketSize)); + lost_packets.push_back(LostPacket(QuicPacketNumber(1), kMaxPacketSize)); AckedPacketVector empty_acked; EXPECT_CALL(*mock_sender_, OnCongestionEvent(true, kMaxPacketSize, _, IsEmpty(), _));
diff --git a/quic/core/congestion_control/rtt_stats_test.cc b/quic/core/congestion_control/rtt_stats_test.cc index 4d154a6..83cb155 100644 --- a/quic/core/congestion_control/rtt_stats_test.cc +++ b/quic/core/congestion_control/rtt_stats_test.cc
@@ -192,9 +192,9 @@ for (QuicTime::Delta bad_send_delta : bad_send_deltas) { SCOPED_TRACE(Message() << "bad_send_delta = " << bad_send_delta.ToMicroseconds()); -#if QUIC_LOG_WARNING_IS_ON - EXPECT_QUIC_LOG_CALL_CONTAINS(log, WARNING, "Ignoring"); -#endif + if (QUIC_LOG_WARNING_IS_ON()) { + EXPECT_QUIC_LOG_CALL_CONTAINS(log, WARNING, "Ignoring"); + } rtt_stats_.UpdateRtt(bad_send_delta, QuicTime::Delta::Zero(), QuicTime::Zero()); EXPECT_EQ(initial_rtt, rtt_stats_.min_rtt());
diff --git a/quic/core/congestion_control/tcp_cubic_sender_bytes.cc b/quic/core/congestion_control/tcp_cubic_sender_bytes.cc index 1d903ea..5b843eb 100644 --- a/quic/core/congestion_control/tcp_cubic_sender_bytes.cc +++ b/quic/core/congestion_control/tcp_cubic_sender_bytes.cc
@@ -38,9 +38,6 @@ stats_(stats), reno_(reno), num_connections_(kDefaultNumConnections), - largest_sent_packet_number_(kInvalidPacketNumber), - largest_acked_packet_number_(kInvalidPacketNumber), - largest_sent_at_last_cutback_(kInvalidPacketNumber), min4_mode_(false), last_cutback_exited_slowstart_(false), slow_start_large_reduction_(false), @@ -151,8 +148,12 @@ QuicByteCount acked_bytes, QuicByteCount prior_in_flight, QuicTime event_time) { - largest_acked_packet_number_ = - std::max(acked_packet_number, largest_acked_packet_number_); + if (largest_acked_packet_number_.IsInitialized()) { + largest_acked_packet_number_ = + std::max(acked_packet_number, largest_acked_packet_number_); + } else { + largest_acked_packet_number_ = acked_packet_number; + } if (InRecovery()) { if (!no_prr_) { // PRR is used when in recovery. @@ -184,7 +185,8 @@ // PRR is used when in recovery. prr_.OnPacketSent(bytes); } - DCHECK_LT(largest_sent_packet_number_, packet_number); + DCHECK(!largest_sent_packet_number_.IsInitialized() || + largest_sent_packet_number_ < packet_number); largest_sent_packet_number_ = packet_number; hybrid_slow_start_.OnPacketSent(packet_number); } @@ -240,8 +242,9 @@ } bool TcpCubicSenderBytes::InRecovery() const { - return largest_acked_packet_number_ <= largest_sent_at_last_cutback_ && - largest_acked_packet_number_ != kInvalidPacketNumber; + return largest_acked_packet_number_.IsInitialized() && + largest_sent_at_last_cutback_.IsInitialized() && + largest_acked_packet_number_ <= largest_sent_at_last_cutback_; } bool TcpCubicSenderBytes::ShouldSendProbingPacket() const { @@ -249,7 +252,7 @@ } void TcpCubicSenderBytes::OnRetransmissionTimeout(bool packets_retransmitted) { - largest_sent_at_last_cutback_ = kInvalidPacketNumber; + largest_sent_at_last_cutback_.Clear(); if (!packets_retransmitted) { return; } @@ -298,7 +301,8 @@ QuicByteCount prior_in_flight) { // TCP NewReno (RFC6582) says that once a loss occurs, any losses in packets // already sent should be treated as a single loss event, since it's expected. - if (packet_number <= largest_sent_at_last_cutback_) { + if (largest_sent_at_last_cutback_.IsInitialized() && + packet_number <= largest_sent_at_last_cutback_) { if (last_cutback_exited_slowstart_) { ++stats_->slowstart_packets_lost; stats_->slowstart_bytes_lost += lost_bytes; @@ -414,9 +418,9 @@ void TcpCubicSenderBytes::OnConnectionMigration() { hybrid_slow_start_.Restart(); prr_ = PrrSender(); - largest_sent_packet_number_ = kInvalidPacketNumber; - largest_acked_packet_number_ = kInvalidPacketNumber; - largest_sent_at_last_cutback_ = kInvalidPacketNumber; + largest_sent_packet_number_.Clear(); + largest_acked_packet_number_.Clear(); + largest_sent_at_last_cutback_.Clear(); last_cutback_exited_slowstart_ = false; cubic_.ResetCubicState(); num_acked_packets_ = 0;
diff --git a/quic/core/congestion_control/tcp_cubic_sender_bytes_test.cc b/quic/core/congestion_control/tcp_cubic_sender_bytes_test.cc index b7234bc..5eb6226 100644 --- a/quic/core/congestion_control/tcp_cubic_sender_bytes_test.cc +++ b/quic/core/congestion_control/tcp_cubic_sender_bytes_test.cc
@@ -69,8 +69,9 @@ int packets_sent = 0; bool can_send = sender_->CanSend(bytes_in_flight_); while (can_send) { - sender_->OnPacketSent(clock_.Now(), bytes_in_flight_, packet_number_++, - kDefaultTCPMSS, HAS_RETRANSMITTABLE_DATA); + sender_->OnPacketSent(clock_.Now(), bytes_in_flight_, + QuicPacketNumber(packet_number_++), kDefaultTCPMSS, + HAS_RETRANSMITTABLE_DATA); ++packets_sent; bytes_in_flight_ += kDefaultTCPMSS; can_send = sender_->CanSend(bytes_in_flight_); @@ -87,7 +88,8 @@ for (int i = 0; i < n; ++i) { ++acked_packet_number_; acked_packets.push_back( - AckedPacket(acked_packet_number_, kDefaultTCPMSS, QuicTime::Zero())); + AckedPacket(QuicPacketNumber(acked_packet_number_), kDefaultTCPMSS, + QuicTime::Zero())); } sender_->OnCongestionEvent(true, bytes_in_flight_, clock_.Now(), acked_packets, lost_packets); @@ -102,7 +104,8 @@ LostPacketVector lost_packets; for (int i = 0; i < n; ++i) { ++acked_packet_number_; - lost_packets.push_back(LostPacket(acked_packet_number_, packet_length)); + lost_packets.push_back( + LostPacket(QuicPacketNumber(acked_packet_number_), packet_length)); } sender_->OnCongestionEvent(false, bytes_in_flight_, clock_.Now(), acked_packets, lost_packets); @@ -110,10 +113,11 @@ } // Does not increment acked_packet_number_. - void LosePacket(QuicPacketNumber packet_number) { + void LosePacket(uint64_t packet_number) { AckedPacketVector acked_packets; LostPacketVector lost_packets; - lost_packets.push_back(LostPacket(packet_number, kDefaultTCPMSS)); + lost_packets.push_back( + LostPacket(QuicPacketNumber(packet_number), kDefaultTCPMSS)); sender_->OnCongestionEvent(false, bytes_in_flight_, clock_.Now(), acked_packets, lost_packets); bytes_in_flight_ -= kDefaultTCPMSS; @@ -122,8 +126,8 @@ const QuicTime::Delta one_ms_; MockClock clock_; std::unique_ptr<TcpCubicSenderBytesPeer> sender_; - QuicPacketNumber packet_number_; - QuicPacketNumber acked_packet_number_; + uint64_t packet_number_; + uint64_t acked_packet_number_; QuicByteCount bytes_in_flight_; }; @@ -779,7 +783,8 @@ LostPacketVector missing_packets; for (uint64_t i = 1; i < kDefaultMaxCongestionWindowPackets; ++i) { acked_packets.clear(); - acked_packets.push_back(AckedPacket(i, 1350, QuicTime::Zero())); + acked_packets.push_back( + AckedPacket(QuicPacketNumber(i), 1350, QuicTime::Zero())); sender->OnCongestionEvent(true, sender->GetCongestionWindow(), clock_.Now(), acked_packets, missing_packets); }
diff --git a/quic/core/crypto/aead_base_decrypter.cc b/quic/core/crypto/aead_base_decrypter.cc index f5ec25c..51cfa26 100644 --- a/quic/core/crypto/aead_base_decrypter.cc +++ b/quic/core/crypto/aead_base_decrypter.cc
@@ -142,7 +142,7 @@ } bool AeadBaseDecrypter::DecryptPacket(QuicTransportVersion /*version*/, - QuicPacketNumber packet_number, + 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 494d6c2..b4906b8 100644 --- a/quic/core/crypto/aead_base_decrypter.h +++ b/quic/core/crypto/aead_base_decrypter.h
@@ -36,7 +36,7 @@ bool SetPreliminaryKey(QuicStringPiece key) override; bool SetDiversificationNonce(const DiversificationNonce& nonce) override; bool DecryptPacket(QuicTransportVersion version, - QuicPacketNumber packet_number, + 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 cbe07e3..199851e 100644 --- a/quic/core/crypto/aead_base_encrypter.cc +++ b/quic/core/crypto/aead_base_encrypter.cc
@@ -124,7 +124,7 @@ } bool AeadBaseEncrypter::EncryptPacket(QuicTransportVersion /*version*/, - QuicPacketNumber packet_number, + 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 d3ee016..255bd87 100644 --- a/quic/core/crypto/aead_base_encrypter.h +++ b/quic/core/crypto/aead_base_encrypter.h
@@ -34,7 +34,7 @@ bool SetNoncePrefix(QuicStringPiece nonce_prefix) override; bool SetIV(QuicStringPiece iv) override; bool EncryptPacket(QuicTransportVersion version, - QuicPacketNumber packet_number, + 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 7ffbf6e..eb2fa5e 100644 --- a/quic/core/crypto/aes_128_gcm_12_decrypter_test.cc +++ b/quic/core/crypto/aes_128_gcm_12_decrypter_test.cc
@@ -203,7 +203,7 @@ QuicStringPiece nonce, QuicStringPiece associated_data, QuicStringPiece ciphertext) { - QuicPacketNumber packet_number; + uint64_t packet_number; QuicStringPiece nonce_prefix(nonce.data(), nonce.size() - sizeof(packet_number)); decrypter->SetNoncePrefix(nonce_prefix);
diff --git a/quic/core/crypto/aes_128_gcm_encrypter_test.cc b/quic/core/crypto/aes_128_gcm_encrypter_test.cc index 68f56d0..79276ca 100644 --- a/quic/core/crypto/aes_128_gcm_encrypter_test.cc +++ b/quic/core/crypto/aes_128_gcm_encrypter_test.cc
@@ -220,7 +220,7 @@ TEST_F(Aes128GcmEncrypterTest, EncryptPacket) { QuicString key = QuicTextUtils::HexDecode("d95a145250826c25a77b6a84fd4d34fc"); QuicString iv = QuicTextUtils::HexDecode("50c4431ebb18283448e276e2"); - QuicPacketNumber packet_num = 0x13278f44; + uint64_t packet_num = 0x13278f44; QuicString aad = QuicTextUtils::HexDecode("875d49f64a70c9cbe713278f44ff000005"); QuicString pt = QuicTextUtils::HexDecode("aa0003a250bd000000000001");
diff --git a/quic/core/crypto/chacha20_poly1305_decrypter_test.cc b/quic/core/crypto/chacha20_poly1305_decrypter_test.cc index ba72027..a0c3cbe 100644 --- a/quic/core/crypto/chacha20_poly1305_decrypter_test.cc +++ b/quic/core/crypto/chacha20_poly1305_decrypter_test.cc
@@ -116,7 +116,7 @@ QuicStringPiece nonce, QuicStringPiece associated_data, QuicStringPiece ciphertext) { - QuicPacketNumber packet_number; + uint64_t packet_number; QuicStringPiece nonce_prefix(nonce.data(), nonce.size() - sizeof(packet_number)); decrypter->SetNoncePrefix(nonce_prefix);
diff --git a/quic/core/crypto/chacha20_poly1305_encrypter_test.cc b/quic/core/crypto/chacha20_poly1305_encrypter_test.cc index b5b43fb..8d9a900 100644 --- a/quic/core/crypto/chacha20_poly1305_encrypter_test.cc +++ b/quic/core/crypto/chacha20_poly1305_encrypter_test.cc
@@ -96,7 +96,7 @@ ASSERT_TRUE(encrypter.SetNoncePrefix("abcd")); ASSERT_TRUE(decrypter.SetNoncePrefix("abcd")); - QuicPacketNumber packet_number = UINT64_C(0x123456789ABC); + uint64_t packet_number = UINT64_C(0x123456789ABC); QuicString associated_data = "associated_data"; QuicString plaintext = "plaintext"; char encrypted[1024];
diff --git a/quic/core/crypto/chacha20_poly1305_tls_encrypter_test.cc b/quic/core/crypto/chacha20_poly1305_tls_encrypter_test.cc index 4a9ecf8..bc7c6c4 100644 --- a/quic/core/crypto/chacha20_poly1305_tls_encrypter_test.cc +++ b/quic/core/crypto/chacha20_poly1305_tls_encrypter_test.cc
@@ -95,7 +95,7 @@ ASSERT_TRUE(encrypter.SetIV("abcdefghijkl")); ASSERT_TRUE(decrypter.SetIV("abcdefghijkl")); - QuicPacketNumber packet_number = UINT64_C(0x123456789ABC); + uint64_t packet_number = UINT64_C(0x123456789ABC); QuicString associated_data = "associated_data"; QuicString plaintext = "plaintext"; char encrypted[1024];
diff --git a/quic/core/crypto/crypto_server_test.cc b/quic/core/crypto/crypto_server_test.cc index a97b829..c2c4041 100644 --- a/quic/core/crypto/crypto_server_test.cc +++ b/quic/core/crypto/crypto_server_test.cc
@@ -107,7 +107,7 @@ CryptoServerTest() : rand_(QuicRandom::GetInstance()), client_address_(QuicIpAddress::Loopback4(), 1234), - client_version_(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED), + client_version_(UnsupportedQuicVersion()), config_(QuicCryptoServerConfig::TESTING, rand_, crypto_test_utils::ProofSourceForTesting(), @@ -723,6 +723,26 @@ CheckRejectReasons(kRejectReasons, QUIC_ARRAYSIZE(kRejectReasons)); } +TEST_P(CryptoServerTest, CorruptSourceAddressTokenIsStillAccepted) { + // This tests corrupted source address token. + CryptoHandshakeMessage msg = crypto_test_utils::CreateCHLO( + {{"PDMD", "X509"}, + {"AEAD", "AESG"}, + {"KEXS", "C255"}, + {"SCID", scid_hex_}, + {"#004b5453", (QuicString(1, 'X') + srct_hex_)}, + {"PUBS", pub_hex_}, + {"NONC", nonce_hex_}, + {"XLCT", XlctHexString()}, + {"VER\0", client_version_string_}}, + kClientHelloMinimumSize); + + config_.set_validate_source_address_token(false); + + ShouldSucceed(msg); + EXPECT_EQ(kSHLO, out_.tag()); +} + TEST_P(CryptoServerTest, CorruptClientNonceAndSourceAddressToken) { // This test corrupts client nonce and source address token. CryptoHandshakeMessage msg = crypto_test_utils::CreateCHLO(
diff --git a/quic/core/crypto/crypto_utils.cc b/quic/core/crypto/crypto_utils.cc index 72fbdd9..46d172f 100644 --- a/quic/core/crypto/crypto_utils.cc +++ b/quic/core/crypto/crypto_utils.cc
@@ -95,11 +95,13 @@ // static void CryptoUtils::CreateTlsInitialCrypters(Perspective perspective, + QuicTransportVersion version, QuicConnectionId connection_id, CrypterPair* crypters) { - QUIC_BUG_IF(connection_id.length() != kQuicDefaultConnectionIdLength) - << "CreateTlsInitialCrypters called with connection ID " << connection_id - << " of unsupported length " << connection_id.length(); + QUIC_BUG_IF(!QuicUtils::IsConnectionIdValidForVersion(connection_id, version)) + << "CreateTlsInitialCrypters: attempted to use connection ID " + << connection_id << " which is invalid with version " + << QuicVersionToString(version); const EVP_MD* hash = EVP_sha256(); std::vector<uint8_t> handshake_secret;
diff --git a/quic/core/crypto/crypto_utils.h b/quic/core/crypto/crypto_utils.h index 713822a..511bae9 100644 --- a/quic/core/crypto/crypto_utils.h +++ b/quic/core/crypto/crypto_utils.h
@@ -90,6 +90,7 @@ // decrypter (put in |*crypters|) to use for this packet protection, as well // as setting the key and IV on those crypters. static void CreateTlsInitialCrypters(Perspective perspective, + QuicTransportVersion version, QuicConnectionId connection_id, CrypterPair* crypters);
diff --git a/quic/core/crypto/ephemeral_key_source.h b/quic/core/crypto/ephemeral_key_source.h deleted file mode 100644 index e494310..0000000 --- a/quic/core/crypto/ephemeral_key_source.h +++ /dev/null
@@ -1,41 +0,0 @@ -// Copyright (c) 2013 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_CRYPTO_EPHEMERAL_KEY_SOURCE_H_ -#define QUICHE_QUIC_CORE_CRYPTO_EPHEMERAL_KEY_SOURCE_H_ - -#include "net/third_party/quiche/src/quic/core/crypto/key_exchange.h" -#include "net/third_party/quiche/src/quic/core/quic_time.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 QuicRandom; - -// EphemeralKeySource manages and rotates ephemeral keys as they can be reused -// for several connections in a short space of time. Since the implementation -// of this may involve locking or thread-local data, this interface abstracts -// that away. -class QUIC_EXPORT_PRIVATE EphemeralKeySource { - public: - virtual ~EphemeralKeySource() {} - - // CalculateForwardSecureKey generates an ephemeral public/private key pair - // using the algorithm represented by |key_exchange_factory|, sets - // |*public_value| to the public key and returns the shared key between - // |peer_public_value| and the private key. |*public_value| will be sent to - // the peer to be used with the peer's private key. - virtual QuicString CalculateForwardSecureKey( - const KeyExchange::Factory& key_exchange_factory, - QuicRandom* rand, - QuicTime now, - QuicStringPiece peer_public_value, - QuicString* public_value) = 0; -}; - -} // namespace quic - -#endif // QUICHE_QUIC_CORE_CRYPTO_EPHEMERAL_KEY_SOURCE_H_
diff --git a/quic/core/crypto/null_decrypter.cc b/quic/core/crypto/null_decrypter.cc index ba470f5..0c108b6 100644 --- a/quic/core/crypto/null_decrypter.cc +++ b/quic/core/crypto/null_decrypter.cc
@@ -39,7 +39,7 @@ } bool NullDecrypter::DecryptPacket(QuicTransportVersion version, - QuicPacketNumber /*packet_number*/, + uint64_t /*packet_number*/, QuicStringPiece associated_data, QuicStringPiece ciphertext, char* output,
diff --git a/quic/core/crypto/null_decrypter.h b/quic/core/crypto/null_decrypter.h index 275228c..3996eb7 100644 --- a/quic/core/crypto/null_decrypter.h +++ b/quic/core/crypto/null_decrypter.h
@@ -36,7 +36,7 @@ bool SetPreliminaryKey(QuicStringPiece key) override; bool SetDiversificationNonce(const DiversificationNonce& nonce) override; bool DecryptPacket(QuicTransportVersion version, - QuicPacketNumber packet_number, + uint64_t packet_number, QuicStringPiece associated_data, QuicStringPiece ciphertext, char* output,
diff --git a/quic/core/crypto/null_encrypter.cc b/quic/core/crypto/null_encrypter.cc index 524caef..e4a165f 100644 --- a/quic/core/crypto/null_encrypter.cc +++ b/quic/core/crypto/null_encrypter.cc
@@ -27,7 +27,7 @@ } bool NullEncrypter::EncryptPacket(QuicTransportVersion version, - QuicPacketNumber /*packet_number*/, + uint64_t /*packet_number*/, QuicStringPiece associated_data, QuicStringPiece plaintext, char* output,
diff --git a/quic/core/crypto/null_encrypter.h b/quic/core/crypto/null_encrypter.h index d826202..01ecd45 100644 --- a/quic/core/crypto/null_encrypter.h +++ b/quic/core/crypto/null_encrypter.h
@@ -30,7 +30,7 @@ bool SetNoncePrefix(QuicStringPiece nonce_prefix) override; bool SetIV(QuicStringPiece iv) override; bool EncryptPacket(QuicTransportVersion version, - QuicPacketNumber packet_number, + uint64_t packet_number, QuicStringPiece associated_data, QuicStringPiece plaintext, char* output,
diff --git a/quic/core/crypto/quic_crypto_client_config.cc b/quic/core/crypto/quic_crypto_client_config.cc index 0a37be8..56447bb 100644 --- a/quic/core/crypto/quic_crypto_client_config.cc +++ b/quic/core/crypto/quic_crypto_client_config.cc
@@ -13,6 +13,7 @@ #include "net/third_party/quiche/src/quic/core/crypto/channel_id.h" #include "net/third_party/quiche/src/quic/core/crypto/common_cert_set.h" #include "net/third_party/quiche/src/quic/core/crypto/crypto_framer.h" +#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h" #include "net/third_party/quiche/src/quic/core/crypto/crypto_utils.h" #include "net/third_party/quiche/src/quic/core/crypto/curve25519_key_exchange.h" #include "net/third_party/quiche/src/quic/core/crypto/key_exchange.h" @@ -88,8 +89,8 @@ const CryptoHandshakeMessage* scfg = GetServerConfig(); if (!scfg) { - RecordInchoateClientHelloReason(SERVER_CONFIG_CORRUPTED); // Should be impossible short of cache corruption. + RecordInchoateClientHelloReason(SERVER_CONFIG_CORRUPTED); DCHECK(false); return false; } @@ -441,7 +442,11 @@ CryptoHandshakeMessage* out) const { out->set_tag(kCHLO); // TODO(rch): Remove this when we remove quic_use_chlo_packet_size flag. - out->set_minimum_size(kClientHelloMinimumSize); + if (pad_inchoate_hello_) { + out->set_minimum_size(kClientHelloMinimumSize); + } else { + out->set_minimum_size(1); + } // Server name indication. We only send SNI if it's a valid domain name, as // per the spec. @@ -517,13 +522,21 @@ CryptoHandshakeMessage* out, QuicString* error_details) const { DCHECK(error_details != nullptr); - QUIC_BUG_IF(connection_id.length() != kQuicDefaultConnectionIdLength) - << "FillClientHello called with connection ID " << connection_id - << " of unsupported length " << connection_id.length(); + QUIC_BUG_IF(!QuicUtils::IsConnectionIdValidForVersion( + connection_id, preferred_version.transport_version)) + << "FillClientHello: attempted to use connection ID " << connection_id + << " which is invalid with version " + << QuicVersionToString(preferred_version.transport_version); FillInchoateClientHello(server_id, preferred_version, cached, rand, /* demand_x509_proof= */ true, out_params, out); + if (pad_full_hello_) { + out->set_minimum_size(kClientHelloMinimumSize); + } else { + out->set_minimum_size(1); + } + const CryptoHandshakeMessage* scfg = cached->GetServerConfig(); if (!scfg) { // This should never happen as our caller should have checked @@ -860,10 +873,9 @@ } connection_id = QuicConnectionId(connection_id_bytes.data(), connection_id_bytes.length()); - if (connection_id.length() != kQuicDefaultConnectionIdLength) { + if (!QuicUtils::IsConnectionIdValidForVersion(connection_id, version)) { QUIC_PEER_BUG << "Received server-designated connection ID " - << connection_id << " of bad length " - << connection_id.length() << " with version " + << connection_id << " which is invalid with version " << QuicVersionToString(version); *error_details = "Bad kRCID length"; return QUIC_CRYPTO_INTERNAL_ERROR;
diff --git a/quic/core/crypto/quic_crypto_client_config.h b/quic/core/crypto/quic_crypto_client_config.h index c7e46a9..32df726 100644 --- a/quic/core/crypto/quic_crypto_client_config.h +++ b/quic/core/crypto/quic_crypto_client_config.h
@@ -13,6 +13,7 @@ #include "base/macros.h" #include "third_party/boringssl/src/include/openssl/base.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/quic_packets.h" #include "net/third_party/quiche/src/quic/core/quic_server_id.h" #include "net/third_party/quiche/src/quic/platform/api/quic_export.h" @@ -351,6 +352,14 @@ pre_shared_key_ = QuicString(psk); } + bool pad_inchoate_hello() const { return pad_inchoate_hello_; } + void set_pad_inchoate_hello(bool new_value) { + pad_inchoate_hello_ = new_value; + } + + bool pad_full_hello() const { return pad_full_hello_; } + void set_pad_full_hello(bool new_value) { pad_full_hello_ = new_value; } + private: // Sets the members to reasonable, default values. void SetDefaults(); @@ -402,6 +411,20 @@ // If non-empty, the client will operate in the pre-shared key mode by // incorporating |pre_shared_key_| into the key schedule. QuicString pre_shared_key_; + + // In QUIC, technically, client hello should be fully padded. + // However, fully padding on slow network connection (e.g. 50kbps) can add + // 150ms latency to one roundtrip. Therefore, you can disable padding of + // individual messages. It is recommend to leave at least one message in + // each direction fully padded (e.g. full CHLO and SHLO), but if you know + // the lower-bound MTU, you don't need to pad all of them (keep in mind that + // it's not OK to do it according to the standard). + // + // Also, if you disable padding, you must disable (change) the + // anti-amplification protection. You should only do so if you have some + // other means of verifying the client. + bool pad_inchoate_hello_ = true; + bool pad_full_hello_ = true; }; } // namespace quic
diff --git a/quic/core/crypto/quic_crypto_client_config_test.cc b/quic/core/crypto/quic_crypto_client_config_test.cc index 8cc0420..5e0ca6e 100644 --- a/quic/core/crypto/quic_crypto_client_config_test.cc +++ b/quic/core/crypto/quic_crypto_client_config_test.cc
@@ -113,9 +113,11 @@ TEST_F(QuicCryptoClientConfigTest, CachedState_ServerIdConsumedBeforeSet) { QuicCryptoClientConfig::CachedState state; EXPECT_FALSE(state.has_server_designated_connection_id()); +#if GTEST_HAS_DEATH_TEST && !defined(NDEBUG) EXPECT_DEBUG_DEATH(state.GetNextServerDesignatedConnectionId(), "Attempting to consume a connection id " "that was never designated."); +#endif // GTEST_HAS_DEATH_TEST && !defined(NDEBUG) } TEST_F(QuicCryptoClientConfigTest, CachedState_ServerNonce) { @@ -152,9 +154,11 @@ TEST_F(QuicCryptoClientConfigTest, CachedState_ServerNonceConsumedBeforeSet) { QuicCryptoClientConfig::CachedState state; EXPECT_FALSE(state.has_server_nonce()); +#if GTEST_HAS_DEATH_TEST && !defined(NDEBUG) EXPECT_DEBUG_DEATH(state.GetNextServerNonce(), "Attempting to consume a server nonce " "that was never designated."); +#endif // GTEST_HAS_DEATH_TEST && !defined(NDEBUG) } TEST_F(QuicCryptoClientConfigTest, CachedState_InitializeFrom) { @@ -197,6 +201,26 @@ QuicStringPiece alpn; EXPECT_TRUE(msg.GetStringPiece(kALPN, &alpn)); EXPECT_EQ("hq", alpn); + + EXPECT_EQ(msg.minimum_size(), 1024u); +} + +TEST_F(QuicCryptoClientConfigTest, InchoateChloIsNotPadded) { + QuicCryptoClientConfig::CachedState state; + QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting(), + TlsClientHandshaker::CreateSslCtx()); + config.set_pad_inchoate_hello(false); + config.set_user_agent_id("quic-tester"); + config.set_alpn("hq"); + QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params( + new QuicCryptoNegotiatedParameters); + CryptoHandshakeMessage msg; + QuicServerId server_id("www.google.com", 443, false); + MockRandom rand; + config.FillInchoateClientHello(server_id, QuicVersionMax(), &state, &rand, + /* demand_x509_proof= */ true, params, &msg); + + EXPECT_EQ(msg.minimum_size(), 1u); } // Make sure AES-GCM is the preferred encryption algorithm if it has hardware @@ -307,6 +331,30 @@ EXPECT_EQ(CreateQuicVersionLabel(QuicVersionMax()), cver); } +TEST_F(QuicCryptoClientConfigTest, FillClientHelloNoPadding) { + QuicCryptoClientConfig::CachedState state; + QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting(), + TlsClientHandshaker::CreateSslCtx()); + config.set_pad_full_hello(false); + QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params( + new QuicCryptoNegotiatedParameters); + QuicConnectionId kConnectionId = TestConnectionId(1234); + QuicString error_details; + MockRandom rand; + CryptoHandshakeMessage chlo; + QuicServerId server_id("www.google.com", 443, false); + config.FillClientHello(server_id, kConnectionId, QuicVersionMax(), &state, + QuicWallTime::Zero(), &rand, + nullptr, // channel_id_key + params, &chlo, &error_details); + + // Verify that the version label has been set correctly in the CHLO. + QuicVersionLabel cver; + EXPECT_EQ(QUIC_NO_ERROR, chlo.GetVersionLabel(kVER, &cver)); + EXPECT_EQ(CreateQuicVersionLabel(QuicVersionMax()), cver); + EXPECT_EQ(chlo.minimum_size(), 1u); +} + TEST_F(QuicCryptoClientConfigTest, ProcessServerDowngradeAttack) { ParsedQuicVersionVector supported_versions = AllSupportedVersions(); if (supported_versions.size() == 1) {
diff --git a/quic/core/crypto/quic_crypto_server_config.cc b/quic/core/crypto/quic_crypto_server_config.cc index 1004236..851f8e3 100644 --- a/quic/core/crypto/quic_crypto_server_config.cc +++ b/quic/core/crypto/quic_crypto_server_config.cc
@@ -20,7 +20,6 @@ #include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message.h" #include "net/third_party/quiche/src/quic/core/crypto/crypto_utils.h" #include "net/third_party/quiche/src/quic/core/crypto/curve25519_key_exchange.h" -#include "net/third_party/quiche/src/quic/core/crypto/ephemeral_key_source.h" #include "net/third_party/quiche/src/quic/core/crypto/key_exchange.h" #include "net/third_party/quiche/src/quic/core/crypto/p256_key_exchange.h" #include "net/third_party/quiche/src/quic/core/crypto/proof_source.h" @@ -35,6 +34,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_cert_utils.h" #include "net/third_party/quiche/src/quic/platform/api/quic_clock.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" @@ -220,7 +220,11 @@ source_address_token_future_secs_(3600), source_address_token_lifetime_secs_(86400), enable_serving_sct_(false), - rejection_observer_(nullptr) { + rejection_observer_(nullptr), + pad_rej_(true), + pad_shlo_(true), + validate_chlo_size_(true), + validate_source_address_token_(true) { DCHECK(proof_source_.get()); source_address_token_boxer_.SetKeys( {DeriveSourceAddressTokenKey(source_address_token_secret)}); @@ -507,13 +511,11 @@ QuicReferenceCountedPointer<Config> primary_config; { QuicReaderMutexLock locked(&configs_lock_); - if (!primary_config_.get()) { result->error_code = QUIC_CRYPTO_INTERNAL_ERROR; result->error_details = "No configurations loaded"; } else { - if (!next_config_promotion_time_.IsZero() && - next_config_promotion_time_.IsAfter(now)) { + if (IsNextConfigReady(now)) { configs_lock_.ReaderUnlock(); configs_lock_.WriterLock(); SelectNewPrimaryConfig(now); @@ -678,6 +680,7 @@ validate_chlo_result, QuicConnectionId connection_id, const QuicSocketAddress& client_address, + ParsedQuicVersion version, const ParsedQuicVersionVector& supported_versions, const QuicClock* clock, QuicRandom* rand, @@ -694,6 +697,7 @@ validate_chlo_result_(std::move(validate_chlo_result)), connection_id_(connection_id), client_address_(client_address), + version_(version), supported_versions_(supported_versions), clock_(clock), rand_(rand), @@ -707,7 +711,7 @@ config_->ProcessClientHelloAfterCalculateSharedKeys( !ok, std::move(proof_source_details_), key_exchange_factory_, std::move(out_), public_value_, *validate_chlo_result_, connection_id_, - client_address_, supported_versions_, clock_, rand_, params_, + client_address_, version_, supported_versions_, clock_, rand_, params_, signed_config_, requested_config_, primary_config_, std::move(done_cb_)); } @@ -722,6 +726,7 @@ validate_chlo_result_; QuicConnectionId connection_id_; const QuicSocketAddress client_address_; + ParsedQuicVersion version_; const ParsedQuicVersionVector supported_versions_; const QuicClock* clock_; QuicRandom* rand_; @@ -780,8 +785,7 @@ if (!primary_config_) { no_primary_config = true; } else { - if (!next_config_promotion_time_.IsZero() && - next_config_promotion_time_.IsAfter(now)) { + if (IsNextConfigReady(now)) { configs_lock_.ReaderUnlock(); configs_lock_.WriterLock(); SelectNewPrimaryConfig(now); @@ -867,11 +871,11 @@ const QuicReferenceCountedPointer<Config>& requested_config, const QuicReferenceCountedPointer<Config>& primary_config, std::unique_ptr<ProcessClientHelloResultCallback> done_cb) const { - if (connection_id.length() != kQuicDefaultConnectionIdLength) { - QUIC_BUG << "ProcessClientHelloAfterGetProof called with connection ID " - << connection_id << " of unsupported length " - << connection_id.length(); - } + QUIC_BUG_IF(!QuicUtils::IsConnectionIdValidForVersion( + connection_id, version.transport_version)) + << "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))); @@ -965,25 +969,13 @@ // TODO(rch): Would it be better to implement a move operator and just // std::move(helper) instead of done_cb? helper.DetachCallback(); - if (GetQuicRestartFlag(quic_use_async_key_exchange)) { - QUIC_RESTART_FLAG_COUNT(quic_use_async_key_exchange); - auto cb = QuicMakeUnique<ProcessClientHelloAfterGetProofCallback>( - this, std::move(proof_source_details), key_exchange->GetFactory(), - std::move(out), public_value, validate_chlo_result, connection_id, - client_address, supported_versions, clock, rand, params, signed_config, - requested_config, primary_config, std::move(done_cb)); - key_exchange->CalculateSharedKey( - public_value, ¶ms->initial_premaster_secret, std::move(cb)); - } else { - found_error = !key_exchange->CalculateSharedKey( - public_value, ¶ms->initial_premaster_secret); - ProcessClientHelloAfterCalculateSharedKeys( - found_error, std::move(proof_source_details), - key_exchange->GetFactory(), std::move(out), public_value, - *validate_chlo_result, connection_id, client_address, - supported_versions, clock, rand, params, signed_config, - requested_config, primary_config, std::move(done_cb)); - } + auto cb = QuicMakeUnique<ProcessClientHelloAfterGetProofCallback>( + this, std::move(proof_source_details), key_exchange->GetFactory(), + std::move(out), public_value, validate_chlo_result, connection_id, + client_address, version, supported_versions, clock, rand, params, + signed_config, requested_config, primary_config, std::move(done_cb)); + key_exchange->CalculateSharedKey( + public_value, ¶ms->initial_premaster_secret, std::move(cb)); } void QuicCryptoServerConfig::ProcessClientHelloAfterCalculateSharedKeys( @@ -995,6 +987,7 @@ const ValidateClientHelloResultCallback::Result& validate_chlo_result, QuicConnectionId connection_id, const QuicSocketAddress& client_address, + ParsedQuicVersion version, const ParsedQuicVersionVector& supported_versions, const QuicClock* clock, QuicRandom* rand, @@ -1003,12 +996,12 @@ const QuicReferenceCountedPointer<Config>& requested_config, const QuicReferenceCountedPointer<Config>& primary_config, std::unique_ptr<ProcessClientHelloResultCallback> done_cb) const { - if (connection_id.length() != kQuicDefaultConnectionIdLength) { - QUIC_BUG << "ProcessClientHelloAfterCalculateSharedKeys called with " - "connection ID " - << connection_id << " of unsupported length " - << connection_id.length(); - } + QUIC_BUG_IF(!QuicUtils::IsConnectionIdValidForVersion( + connection_id, version.transport_version)) + << "ProcessClientHelloAfterCalculateSharedKeys:" + " attempted to use connection ID " + << connection_id << " which is invalid with version " + << QuicVersionToString(version.transport_version); ProcessClientHelloHelper helper(&done_cb); if (found_error) { @@ -1140,30 +1133,14 @@ } QuicString forward_secure_public_value; - if (GetQuicRestartFlag(quic_no_ephemeral_key_source)) { - if (ephemeral_key_source_) { - QUIC_BUG << "quic_no_ephemeral_key_source flag is on, but " - "ephemeral_key_source is present"; - } else { - QUIC_RESTART_FLAG_COUNT(quic_no_ephemeral_key_source); - } - } - if (ephemeral_key_source_) { - params->forward_secure_premaster_secret = - ephemeral_key_source_->CalculateForwardSecureKey( - key_exchange_factory, rand, clock->ApproximateNow(), public_value, - &forward_secure_public_value); - } else { - std::unique_ptr<KeyExchange> forward_secure_key_exchange = - key_exchange_factory.Create(rand); - forward_secure_public_value = - QuicString(forward_secure_key_exchange->public_value()); - if (!forward_secure_key_exchange->CalculateSharedKey( - public_value, ¶ms->forward_secure_premaster_secret)) { - helper.Fail(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER, - "Invalid public value"); - return; - } + std::unique_ptr<KeyExchange> forward_secure_key_exchange = + key_exchange_factory.Create(rand); + forward_secure_public_value = + QuicString(forward_secure_key_exchange->public_value()); + if (!forward_secure_key_exchange->CalculateSharedKey( + public_value, ¶ms->forward_secure_premaster_secret)) { + helper.Fail(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER, "Invalid public value"); + return; } QuicString forward_secure_hkdf_input; @@ -1332,7 +1309,6 @@ requested_config, QuicReferenceCountedPointer<QuicCryptoServerConfig::Config> primary_config, - bool use_get_cert_chain, QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config, QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result> client_hello_state, @@ -1342,7 +1318,6 @@ version_(version), requested_config_(std::move(requested_config)), primary_config_(std::move(primary_config)), - use_get_cert_chain_(use_get_cert_chain), signed_config_(signed_config), client_hello_state_(std::move(client_hello_state)), done_cb_(std::move(done_cb)) {} @@ -1357,8 +1332,8 @@ } config_.EvaluateClientHelloAfterGetProof( server_ip_, version_, requested_config_, primary_config_, - signed_config_, std::move(details), use_get_cert_chain_, !ok, - client_hello_state_, std::move(done_cb_)); + signed_config_, std::move(details), !ok, client_hello_state_, + std::move(done_cb_)); } private: @@ -1369,7 +1344,6 @@ requested_config_; const QuicReferenceCountedPointer<QuicCryptoServerConfig::Config> primary_config_; - const bool use_get_cert_chain_; QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config_; QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result> client_hello_state_; @@ -1392,7 +1366,7 @@ const CryptoHandshakeMessage& client_hello = client_hello_state->client_hello; ClientHelloInfo* info = &(client_hello_state->info); - if (client_hello.size() < kClientHelloMinimumSize) { + if (validate_chlo_size_ && client_hello.size() < kClientHelloMinimumSize) { helper.ValidationComplete(QUIC_CRYPTO_INVALID_VALUE_LENGTH, "Client hello too small", nullptr); return; @@ -1408,22 +1382,27 @@ client_hello.GetStringPiece(kUAID, &info->user_agent_id); HandshakeFailureReason source_address_token_error = MAX_FAILURE_REASON; - QuicStringPiece srct; - if (client_hello.GetStringPiece(kSourceAddressTokenTag, &srct)) { - Config& config = - requested_config != nullptr ? *requested_config : *primary_config; - source_address_token_error = - ParseSourceAddressToken(config, srct, &info->source_address_tokens); + if (validate_source_address_token_) { + QuicStringPiece srct; + if (client_hello.GetStringPiece(kSourceAddressTokenTag, &srct)) { + Config& config = + requested_config != nullptr ? *requested_config : *primary_config; + source_address_token_error = + ParseSourceAddressToken(config, srct, &info->source_address_tokens); - if (source_address_token_error == HANDSHAKE_OK) { - source_address_token_error = ValidateSourceAddressTokens( - info->source_address_tokens, info->client_ip, info->now, - &client_hello_state->cached_network_params); + if (source_address_token_error == HANDSHAKE_OK) { + source_address_token_error = ValidateSourceAddressTokens( + info->source_address_tokens, info->client_ip, info->now, + &client_hello_state->cached_network_params); + } + info->valid_source_address_token = + (source_address_token_error == HANDSHAKE_OK); + } else { + source_address_token_error = SOURCE_ADDRESS_TOKEN_INVALID_FAILURE; } - info->valid_source_address_token = - (source_address_token_error == HANDSHAKE_OK); } else { - source_address_token_error = SOURCE_ADDRESS_TOKEN_INVALID_FAILURE; + source_address_token_error = HANDSHAKE_OK; + info->valid_source_address_token = true; } if (!requested_config.get()) { @@ -1450,28 +1429,6 @@ // No valid source address token. } - const bool use_get_cert_chain = - GetQuicReloadableFlag(quic_use_get_cert_chain); - if (!use_get_cert_chain) { - QUIC_RELOADABLE_FLAG_COUNT_N(quic_use_get_cert_chain, 1, 2); - QuicString serialized_config = primary_config->serialized; - QuicString chlo_hash; - CryptoUtils::HashHandshakeMessage(client_hello, &chlo_hash, - Perspective::IS_SERVER); - // Make an async call to GetProof and setup the callback to trampoline - // back into EvaluateClientHelloAfterGetProof - auto cb = QuicMakeUnique<EvaluateClientHelloCallback>( - *this, server_address.host(), version, requested_config, primary_config, - use_get_cert_chain, signed_config, client_hello_state, - std::move(done_cb)); - proof_source_->GetProof(server_address, QuicString(info->sni), - serialized_config, version, chlo_hash, - std::move(cb)); - helper.DetachCallback(); - return; - } - - QUIC_RELOADABLE_FLAG_COUNT_N(quic_use_get_cert_chain, 2, 2); QuicReferenceCountedPointer<ProofSource::Chain> chain = proof_source_->GetCertChain(server_address, QuicString(info->sni)); if (!chain) { @@ -1481,7 +1438,7 @@ } EvaluateClientHelloAfterGetProof( server_address.host(), version, requested_config, primary_config, - signed_config, /*proof_source_details=*/nullptr, use_get_cert_chain, + signed_config, /*proof_source_details=*/nullptr, /*get_proof_failed=*/false, client_hello_state, std::move(done_cb)); helper.DetachCallback(); } @@ -1493,7 +1450,6 @@ QuicReferenceCountedPointer<Config> primary_config, QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config, std::unique_ptr<ProofSource::Details> proof_source_details, - bool use_get_cert_chain, bool get_proof_failed, QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result> client_hello_state, @@ -1502,18 +1458,6 @@ const CryptoHandshakeMessage& client_hello = client_hello_state->client_hello; ClientHelloInfo* info = &(client_hello_state->info); - if (!use_get_cert_chain) { - if (get_proof_failed) { - info->reject_reasons.push_back(SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE); - } - - if (signed_config->chain != nullptr && - !ValidateExpectedLeafCertificate(client_hello, - signed_config->chain->certs)) { - info->reject_reasons.push_back(INVALID_EXPECTED_LEAF_CERTIFICATE); - } - } - if (info->client_nonce.size() != kNonceSize) { info->reject_reasons.push_back(CLIENT_NONCE_INVALID_FAILURE); // Invalid client nonce. @@ -1673,12 +1617,11 @@ out->SetValue(kRCID, QuicEndian::HostToNet64(QuicConnectionIdToUInt64( server_designated_connection_id))); } else { - if (server_designated_connection_id.length() != - kQuicDefaultConnectionIdLength && - version < QUIC_VERSION_99) { - QUIC_BUG << "Tried to send connection ID " - << server_designated_connection_id << " of bad length " - << server_designated_connection_id.length() << " with version " + if (!QuicUtils::IsConnectionIdValidForVersion( + server_designated_connection_id, version)) { + QUIC_BUG << "Tried to send server designated connection ID " + << server_designated_connection_id + << " which is invalid with version " << QuicVersionToString(version); return; } @@ -1754,8 +1697,22 @@ out->SetStringPiece(kPROF, signed_config.proof.signature); if (should_return_sct) { if (cert_sct.empty()) { - QUIC_LOG_EVERY_N_SEC(WARNING, 60) - << "SCT is expected but it is empty. sni :" << params->sni; + if (!GetQuicReloadableFlag(quic_log_cert_name_for_empty_sct)) { + QUIC_LOG_EVERY_N_SEC(WARNING, 60) + << "SCT is expected but it is empty. sni :" << params->sni; + } else { + // Log SNI and subject name for the leaf cert if its SCT is empty. + // This is for debugging b/28342827. + const std::vector<quic::QuicString>& certs = + signed_config.chain->certs; + QuicStringPiece ca_subject; + if (!certs.empty()) { + QuicCertUtils::ExtractSubjectNameFromDERCert(certs[0], &ca_subject); + } + QUIC_LOG_EVERY_N_SEC(WARNING, 60) + << "SCT is expected but it is empty. sni: '" << params->sni + << "' cert subject: '" << ca_subject << "'"; + } } else { out->SetStringPiece(kCertificateSCTTag, cert_sct); } @@ -1855,7 +1812,7 @@ static_assert(sizeof(config->orbit) == kOrbitSize, "incorrect orbit size"); memcpy(config->orbit, orbit.data(), sizeof(config->orbit)); - if (kexs_tags.size() != protobuf->key_size()) { + if (kexs_tags.size() != static_cast<size_t>(protobuf->key_size())) { QUIC_LOG(WARNING) << "Server config has " << kexs_tags.size() << " key exchange methods configured, but " << protobuf->key_size() << " private keys"; @@ -1878,7 +1835,7 @@ config->kexs.push_back(tag); - for (size_t j = 0; j < protobuf->key_size(); j++) { + for (int j = 0; j < protobuf->key_size(); j++) { const QuicServerConfigProtobuf::PrivateKey& key = protobuf->key(i); if (key.tag() == tag) { private_key = key.private_key(); @@ -1911,11 +1868,6 @@ return config; } -void QuicCryptoServerConfig::SetEphemeralKeySource( - std::unique_ptr<EphemeralKeySource> ephemeral_key_source) { - ephemeral_key_source_ = std::move(ephemeral_key_source); -} - void QuicCryptoServerConfig::set_replay_protection(bool on) { replay_protection_ = on; } @@ -2124,6 +2076,15 @@ return false; } +bool QuicCryptoServerConfig::IsNextConfigReady(QuicWallTime now) const { + if (GetQuicReloadableFlag(quic_fix_config_rotation)) { + return !next_config_promotion_time_.IsZero() && + !next_config_promotion_time_.IsAfter(now); + } + return !next_config_promotion_time_.IsZero() && + next_config_promotion_time_.IsAfter(now); +} + QuicCryptoServerConfig::Config::Config() : channel_id_enabled(false), is_primary(false),
diff --git a/quic/core/crypto/quic_crypto_server_config.h b/quic/core/crypto/quic_crypto_server_config.h index b10786d..3561844 100644 --- a/quic/core/crypto/quic_crypto_server_config.h +++ b/quic/core/crypto/quic_crypto_server_config.h
@@ -34,7 +34,6 @@ namespace quic { class CryptoHandshakeMessage; -class EphemeralKeySource; class ProofSource; class QuicClock; class QuicRandom; @@ -370,12 +369,6 @@ const CachedNetworkParameters* cached_network_params, std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb) const; - // SetEphemeralKeySource installs an object that can cache ephemeral keys for - // a short period of time. If not set, ephemeral keys will be generated - // per-connection. - void SetEphemeralKeySource( - std::unique_ptr<EphemeralKeySource> ephemeral_key_source); - // set_replay_protection controls whether replay protection is enabled. If // replay protection is disabled then no strike registers are needed and // frontends can share an orbit value without a shared strike-register. @@ -388,6 +381,19 @@ // valid source-address token. void set_chlo_multiplier(size_t multiplier); + // When sender is allowed to not pad client hello (not standards compliant), + // we need to disable the client hello check. + void set_validate_chlo_size(bool new_value) { + validate_chlo_size_ = new_value; + } + + // When QUIC is tunneled through some other mechanism, source token validation + // may be disabled. Do not disable it if you are not providing other + // protection. (|true| protects against UDP amplification attack.). + void set_validate_source_address_token(bool new_value) { + validate_source_address_token_ = new_value; + } + // set_source_address_token_future_secs sets the number of seconds into the // future that source-address tokens will be accepted from. Since // source-address tokens are authenticated, this should only happen if @@ -423,6 +429,12 @@ pre_shared_key_ = QuicString(psk); } + bool pad_rej() const { return pad_rej_; } + void set_pad_rej(bool new_value) { pad_rej_ = new_value; } + + bool pad_shlo() const { return pad_shlo_; } + void set_pad_shlo(bool new_value) { pad_shlo_ = new_value; } + private: friend class test::QuicCryptoServerConfigPeer; friend struct QuicSignedServerConfig; @@ -539,7 +551,6 @@ QuicReferenceCountedPointer<Config> primary_config, QuicReferenceCountedPointer<QuicSignedServerConfig> crypto_proof, std::unique_ptr<ProofSource::Details> proof_source_details, - bool use_get_cert_chain, bool get_proof_failed, QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result> client_hello_state, @@ -589,6 +600,7 @@ const ValidateClientHelloResultCallback::Result& validate_chlo_result, QuicConnectionId connection_id, const QuicSocketAddress& client_address, + ParsedQuicVersion version, const ParsedQuicVersionVector& supported_versions, const QuicClock* clock, QuicRandom* rand, @@ -754,6 +766,10 @@ CryptoHandshakeMessage message, std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb) const; + // Returns true if the next config promotion should happen now. + bool IsNextConfigReady(QuicWallTime now) const + SHARED_LOCKS_REQUIRED(configs_lock_); + // replay_protection_ controls whether the server enforces that handshakes // aren't replays. bool replay_protection_; @@ -805,10 +821,6 @@ // ssl_ctx_ contains the server configuration for doing TLS handshakes. bssl::UniquePtr<SSL_CTX> ssl_ctx_; - // ephemeral_key_source_ contains an object that caches ephemeral keys for a - // short period of time. - std::unique_ptr<EphemeralKeySource> ephemeral_key_source_; - // These fields store configuration values. See the comments for their // respective setter functions. uint32_t source_address_token_future_secs_; @@ -823,6 +835,23 @@ // If non-empty, the server will operate in the pre-shared key mode by // incorporating |pre_shared_key_| into the key schedule. QuicString pre_shared_key_; + + // Whether REJ message should be padded to max packet size. + bool pad_rej_; + + // Whether SHLO message should be padded to max packet size. + bool pad_shlo_; + + // If client is allowed to send a small client hello (by disabling padding), + // server MUST not check for the client hello size. + // DO NOT disable this unless you have some other way of validating client. + // (e.g. in realtime scenarios, where quic is tunneled through ICE, ICE will + // do its own peer validation using STUN pings with ufrag/upass). + bool validate_chlo_size_; + + // When source address is validated by some other means (e.g. when using ICE), + // source address token validation may be disabled. + bool validate_source_address_token_; }; struct QUIC_EXPORT_PRIVATE QuicSignedServerConfig
diff --git a/quic/core/crypto/quic_crypto_server_config_test.cc b/quic/core/crypto/quic_crypto_server_config_test.cc index 15de28b..81e6951 100644 --- a/quic/core/crypto/quic_crypto_server_config_test.cc +++ b/quic/core/crypto/quic_crypto_server_config_test.cc
@@ -258,12 +258,12 @@ NewSourceAddressToken(kPrimary, ip4_, &cached_network_params_input); CachedNetworkParameters cached_network_params_output; - EXPECT_NE(cached_network_params_output.DebugString(), - cached_network_params_input.DebugString()); + EXPECT_NE(cached_network_params_output.SerializeAsString(), + cached_network_params_input.SerializeAsString()); ValidateSourceAddressTokens(kPrimary, token4_with_cached_network_params, ip4_, &cached_network_params_output); - EXPECT_EQ(cached_network_params_output.DebugString(), - cached_network_params_input.DebugString()); + EXPECT_EQ(cached_network_params_output.SerializeAsString(), + cached_network_params_input.SerializeAsString()); } // Test the ability for a source address token to be valid for multiple @@ -457,6 +457,33 @@ test_peer_.CheckConfigs({{"a", false}, {"b", true}}); } +class ValidateCallback : public ValidateClientHelloResultCallback { + public: + void Run(QuicReferenceCountedPointer<Result> result, + std::unique_ptr<ProofSource::Details> /* details */) override {} +}; + +TEST_F(CryptoServerConfigsTest, AdvancePrimaryViaValidate) { + SetQuicReloadableFlag(quic_fix_config_rotation, true); + // Check that a new primary config is enabled at the right time. + SetConfigs({{"a", 900, 1}, {"b", 1100, 1}}); + test_peer_.SelectNewPrimaryConfig(1000); + test_peer_.CheckConfigs({{"a", true}, {"b", false}}); + CryptoHandshakeMessage client_hello; + QuicIpAddress client_ip; + QuicSocketAddress server_address; + QuicTransportVersion version = QUIC_VERSION_99; + MockClock clock; + QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config( + new QuicSignedServerConfig); + std::unique_ptr<ValidateClientHelloResultCallback> done_cb( + new ValidateCallback); + clock.AdvanceTime(QuicTime::Delta::FromSeconds(1100)); + config_.ValidateClientHello(client_hello, client_ip, server_address, version, + &clock, signed_config, std::move(done_cb)); + test_peer_.CheckConfigs({{"a", false}, {"b", true}}); +} + TEST_F(CryptoServerConfigsTest, InvalidConfigs) { // Ensure that invalid configs don't change anything. SetConfigs({{"a", 800, 1}, {"b", 900, 1}, {"c", 1100, 1}});
diff --git a/quic/core/crypto/quic_decrypter.h b/quic/core/crypto/quic_decrypter.h index f61f621..892504c 100644 --- a/quic/core/crypto/quic_decrypter.h +++ b/quic/core/crypto/quic_decrypter.h
@@ -54,7 +54,7 @@ // 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, - QuicPacketNumber packet_number, + 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 ea1cee8..591021e 100644 --- a/quic/core/crypto/quic_encrypter.h +++ b/quic/core/crypto/quic_encrypter.h
@@ -35,7 +35,7 @@ // |associated_data|. If |output| overlaps with |plaintext| then // |plaintext| must be <= |output|. virtual bool EncryptPacket(QuicTransportVersion version, - QuicPacketNumber packet_number, + 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 3493f97..5f47b3f 100644 --- a/quic/core/frames/quic_ack_frame.cc +++ b/quic/core/frames/quic_ack_frame.cc
@@ -12,19 +12,29 @@ namespace quic { namespace { -const QuicPacketNumber kMaxPrintRange = 128; + +const QuicPacketCount kMaxPrintRange = 128; + +uint64_t PacketNumberIntervalLength( + const QuicInterval<QuicPacketNumber>& interval) { + if (interval.Empty()) { + return 0u; + } + return interval.max() - interval.min(); +} } // namespace bool IsAwaitingPacket(const QuicAckFrame& ack_frame, QuicPacketNumber packet_number, QuicPacketNumber peer_least_packet_awaiting_ack) { - return packet_number >= peer_least_packet_awaiting_ack && + DCHECK(packet_number.IsInitialized()); + return (!peer_least_packet_awaiting_ack.IsInitialized() || + packet_number >= peer_least_packet_awaiting_ack) && !ack_frame.packets.Contains(packet_number); } QuicAckFrame::QuicAckFrame() - : largest_acked(kInvalidPacketNumber), - ack_delay_time(QuicTime::Delta::Infinite()), + : ack_delay_time(QuicTime::Delta::Infinite()), ecn_counters_populated(false), ect_0_count(0), ect_1_count(0), @@ -56,7 +66,7 @@ } void QuicAckFrame::Clear() { - largest_acked = kInvalidPacketNumber; + largest_acked.Clear(); ack_delay_time = QuicTime::Delta::Infinite(); received_packet_times.clear(); packets.Clear(); @@ -73,6 +83,9 @@ default; void PacketNumberQueue::Add(QuicPacketNumber packet_number) { + if (!packet_number.IsInitialized()) { + return; + } // Check if the deque is empty if (packet_number_deque_.empty()) { packet_number_deque_.push_front( @@ -148,7 +161,7 @@ void PacketNumberQueue::AddRange(QuicPacketNumber lower, QuicPacketNumber higher) { - if (lower >= higher) { + if (!lower.IsInitialized() || !higher.IsInitialized() || lower >= higher) { return; } if (packet_number_deque_.empty()) { @@ -187,7 +200,7 @@ } bool PacketNumberQueue::RemoveUpTo(QuicPacketNumber higher) { - if (Empty()) { + if (!higher.IsInitialized() || Empty()) { return false; } const QuicPacketNumber old_min = Min(); @@ -221,7 +234,7 @@ } bool PacketNumberQueue::Contains(QuicPacketNumber packet_number) const { - if (packet_number_deque_.empty()) { + if (!packet_number.IsInitialized() || packet_number_deque_.empty()) { return false; } if (packet_number_deque_.front().min() > packet_number || @@ -253,7 +266,7 @@ QuicPacketCount PacketNumberQueue::NumPacketsSlow() const { QuicPacketCount n_packets = 0; for (QuicInterval<QuicPacketNumber> interval : packet_number_deque_) { - n_packets += interval.Length(); + n_packets += PacketNumberIntervalLength(interval); } return n_packets; } @@ -278,9 +291,9 @@ return packet_number_deque_.rend(); } -QuicPacketNumber PacketNumberQueue::LastIntervalLength() const { +QuicPacketCount PacketNumberQueue::LastIntervalLength() const { DCHECK(!Empty()); - return packet_number_deque_.back().Length(); + return PacketNumberIntervalLength(packet_number_deque_.back()); } // Largest min...max range for packet numbers where we print the numbers
diff --git a/quic/core/frames/quic_ack_frame.h b/quic/core/frames/quic_ack_frame.h index 29d511e..4dcfc3d 100644 --- a/quic/core/frames/quic_ack_frame.h +++ b/quic/core/frames/quic_ack_frame.h
@@ -73,7 +73,7 @@ size_t NumIntervals() const; // Returns the length of last interval. - QuicPacketNumber LastIntervalLength() const; + QuicPacketCount LastIntervalLength() const; // Returns iterators over the packet number intervals. const_iterator begin() const;
diff --git a/quic/core/frames/quic_blocked_frame.h b/quic/core/frames/quic_blocked_frame.h index 3203c67..a4be664 100644 --- a/quic/core/frames/quic_blocked_frame.h +++ b/quic/core/frames/quic_blocked_frame.h
@@ -37,6 +37,9 @@ // BLOCKED or STREAM_BLOCKED frame is generated. // If stream_id is 0 then a BLOCKED frame is generated and transmitted, // if non-0, a 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. QuicStreamId stream_id; // For Google QUIC, the offset is ignored.
diff --git a/quic/core/frames/quic_crypto_frame.cc b/quic/core/frames/quic_crypto_frame.cc index c7f500a..9d602bc 100644 --- a/quic/core/frames/quic_crypto_frame.cc +++ b/quic/core/frames/quic_crypto_frame.cc
@@ -8,15 +8,27 @@ namespace quic { -QuicCryptoFrame::QuicCryptoFrame() : QuicCryptoFrame(0, nullptr, 0) {} +QuicCryptoFrame::QuicCryptoFrame() + : QuicCryptoFrame(ENCRYPTION_NONE, 0, nullptr, 0) {} -QuicCryptoFrame::QuicCryptoFrame(QuicStreamOffset offset, QuicStringPiece data) - : QuicCryptoFrame(offset, data.data(), data.length()) {} +QuicCryptoFrame::QuicCryptoFrame(EncryptionLevel level, + QuicStreamOffset offset, + QuicPacketLength data_length) + : QuicCryptoFrame(level, offset, nullptr, data_length) {} -QuicCryptoFrame::QuicCryptoFrame(QuicStreamOffset offset, +QuicCryptoFrame::QuicCryptoFrame(EncryptionLevel level, + QuicStreamOffset offset, + QuicStringPiece data) + : QuicCryptoFrame(level, offset, data.data(), data.length()) {} + +QuicCryptoFrame::QuicCryptoFrame(EncryptionLevel level, + QuicStreamOffset offset, const char* data_buffer, QuicPacketLength data_length) - : data_length(data_length), data_buffer(data_buffer), offset(offset) {} + : level(level), + data_length(data_length), + data_buffer(data_buffer), + offset(offset) {} QuicCryptoFrame::~QuicCryptoFrame() {}
diff --git a/quic/core/frames/quic_crypto_frame.h b/quic/core/frames/quic_crypto_frame.h index bbf8ea0..a3968fe 100644 --- a/quic/core/frames/quic_crypto_frame.h +++ b/quic/core/frames/quic_crypto_frame.h
@@ -17,20 +17,29 @@ struct QUIC_EXPORT_PRIVATE QuicCryptoFrame { QuicCryptoFrame(); - QuicCryptoFrame(QuicStreamOffset offset, QuicStringPiece data); + QuicCryptoFrame(EncryptionLevel level, + QuicStreamOffset offset, + QuicPacketLength data_length); + QuicCryptoFrame(EncryptionLevel level, + QuicStreamOffset offset, + QuicStringPiece data); ~QuicCryptoFrame(); friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, const QuicCryptoFrame& s); + // When writing a crypto frame to a packet, the packet must be encrypted at + // |level|. When a crypto frame is read, the encryption level of the packet it + // was received in is put in |level|. + EncryptionLevel level; QuicPacketLength data_length; // When reading, |data_buffer| points to the data that was received in the - // frame. When writing, |data_buffer| must be a valid pointer for the lifetime - // of the frame, which may get serialized some time after creation. + // frame. |data_buffer| is not used when writing. const char* data_buffer; QuicStreamOffset offset; // Location of this data in the stream. - QuicCryptoFrame(QuicStreamOffset offset, + QuicCryptoFrame(EncryptionLevel level, + QuicStreamOffset offset, const char* data_buffer, QuicPacketLength data_length); };
diff --git a/quic/core/frames/quic_frame.cc b/quic/core/frames/quic_frame.cc index a951ce6..2e6a303 100644 --- a/quic/core/frames/quic_frame.cc +++ b/quic/core/frames/quic_frame.cc
@@ -246,15 +246,15 @@ case PING_FRAME: copy = QuicFrame(QuicPingFrame(frame.ping_frame.control_frame_id)); break; + case STOP_SENDING_FRAME: + copy = QuicFrame(new QuicStopSendingFrame(*frame.stop_sending_frame)); + break; case STREAM_ID_BLOCKED_FRAME: copy = QuicFrame(QuicStreamIdBlockedFrame(frame.stream_id_blocked_frame)); break; case MAX_STREAM_ID_FRAME: copy = QuicFrame(QuicMaxStreamIdFrame(frame.max_stream_id_frame)); break; - case STOP_SENDING_FRAME: - copy = QuicFrame(new QuicStopSendingFrame(*frame.stop_sending_frame)); - break; default: QUIC_BUG << "Try to copy a non-retransmittable control frame: " << frame; copy = QuicFrame(QuicPingFrame(kInvalidControlFrameId));
diff --git a/quic/core/frames/quic_frames_test.cc b/quic/core/frames/quic_frames_test.cc index 725ce83..af9c40b 100644 --- a/quic/core/frames/quic_frames_test.cc +++ b/quic/core/frames/quic_frames_test.cc
@@ -27,12 +27,13 @@ TEST_F(QuicFramesTest, AckFrameToString) { QuicAckFrame frame; - frame.largest_acked = 5; + frame.largest_acked = QuicPacketNumber(5); frame.ack_delay_time = QuicTime::Delta::FromMicroseconds(3); - frame.packets.Add(4); - frame.packets.Add(5); + frame.packets.Add(QuicPacketNumber(4)); + frame.packets.Add(QuicPacketNumber(5)); frame.received_packet_times = { - {6, QuicTime::Zero() + QuicTime::Delta::FromMicroseconds(7)}}; + {QuicPacketNumber(6), + QuicTime::Zero() + QuicTime::Delta::FromMicroseconds(7)}}; std::ostringstream stream; stream << frame; EXPECT_EQ( @@ -45,11 +46,12 @@ TEST_F(QuicFramesTest, BigAckFrameToString) { QuicAckFrame frame; - frame.largest_acked = 500; + frame.largest_acked = QuicPacketNumber(500); frame.ack_delay_time = QuicTime::Delta::FromMicroseconds(3); - frame.packets.AddRange(4, 501); + frame.packets.AddRange(QuicPacketNumber(4), QuicPacketNumber(501)); frame.received_packet_times = { - {500, QuicTime::Zero() + QuicTime::Delta::FromMicroseconds(7)}}; + {QuicPacketNumber(500), + QuicTime::Zero() + QuicTime::Delta::FromMicroseconds(7)}}; std::ostringstream stream; stream << frame; EXPECT_EQ( @@ -213,7 +215,7 @@ TEST_F(QuicFramesTest, StopWaitingFrameToString) { QuicStopWaitingFrame frame; - frame.least_unacked = 2; + frame.least_unacked = QuicPacketNumber(2); std::ostringstream stream; stream << frame; EXPECT_EQ("{ least_unacked: 2 }\n", stream.str()); @@ -223,69 +225,84 @@ TEST_F(QuicFramesTest, IsAwaitingPacket) { QuicAckFrame ack_frame1; - ack_frame1.largest_acked = 10u; - ack_frame1.packets.AddRange(1, 11); - EXPECT_TRUE(IsAwaitingPacket(ack_frame1, 11u, 0u)); - EXPECT_FALSE(IsAwaitingPacket(ack_frame1, 1u, 0u)); + ack_frame1.largest_acked = QuicPacketNumber(10u); + ack_frame1.packets.AddRange(QuicPacketNumber(1), QuicPacketNumber(11)); + EXPECT_TRUE( + IsAwaitingPacket(ack_frame1, QuicPacketNumber(11u), QuicPacketNumber())); + EXPECT_FALSE( + IsAwaitingPacket(ack_frame1, QuicPacketNumber(1u), QuicPacketNumber())); - ack_frame1.packets.Add(12); - EXPECT_TRUE(IsAwaitingPacket(ack_frame1, 11u, 0u)); + ack_frame1.packets.Add(QuicPacketNumber(12)); + EXPECT_TRUE( + IsAwaitingPacket(ack_frame1, QuicPacketNumber(11u), QuicPacketNumber())); QuicAckFrame ack_frame2; - ack_frame2.largest_acked = 100u; - ack_frame2.packets.AddRange(21, 100); - EXPECT_FALSE(IsAwaitingPacket(ack_frame2, 11u, 20u)); - EXPECT_FALSE(IsAwaitingPacket(ack_frame2, 80u, 20u)); - EXPECT_TRUE(IsAwaitingPacket(ack_frame2, 101u, 20u)); + ack_frame2.largest_acked = QuicPacketNumber(100u); + ack_frame2.packets.AddRange(QuicPacketNumber(21), QuicPacketNumber(100)); + EXPECT_FALSE(IsAwaitingPacket(ack_frame2, QuicPacketNumber(11u), + QuicPacketNumber(20u))); + EXPECT_FALSE(IsAwaitingPacket(ack_frame2, QuicPacketNumber(80u), + QuicPacketNumber(20u))); + EXPECT_TRUE(IsAwaitingPacket(ack_frame2, QuicPacketNumber(101u), + QuicPacketNumber(20u))); - ack_frame2.packets.AddRange(102, 200); - EXPECT_TRUE(IsAwaitingPacket(ack_frame2, 101u, 20u)); + ack_frame2.packets.AddRange(QuicPacketNumber(102), QuicPacketNumber(200)); + EXPECT_TRUE(IsAwaitingPacket(ack_frame2, QuicPacketNumber(101u), + QuicPacketNumber(20u))); } TEST_F(QuicFramesTest, AddPacket) { QuicAckFrame ack_frame1; - ack_frame1.packets.Add(1); - ack_frame1.packets.Add(99); + ack_frame1.packets.Add(QuicPacketNumber(1)); + ack_frame1.packets.Add(QuicPacketNumber(99)); EXPECT_EQ(2u, ack_frame1.packets.NumIntervals()); - EXPECT_EQ(1u, ack_frame1.packets.Min()); - EXPECT_EQ(99u, ack_frame1.packets.Max()); + EXPECT_EQ(QuicPacketNumber(1u), ack_frame1.packets.Min()); + EXPECT_EQ(QuicPacketNumber(99u), ack_frame1.packets.Max()); std::vector<QuicInterval<QuicPacketNumber>> expected_intervals; - expected_intervals.emplace_back(QuicInterval<QuicPacketNumber>(1, 2)); - expected_intervals.emplace_back(QuicInterval<QuicPacketNumber>(99, 100)); + expected_intervals.emplace_back( + QuicInterval<QuicPacketNumber>(QuicPacketNumber(1), QuicPacketNumber(2))); + expected_intervals.emplace_back(QuicInterval<QuicPacketNumber>( + QuicPacketNumber(99), QuicPacketNumber(100))); const std::vector<QuicInterval<QuicPacketNumber>> actual_intervals( ack_frame1.packets.begin(), ack_frame1.packets.end()); EXPECT_EQ(expected_intervals, actual_intervals); - ack_frame1.packets.Add(20); + ack_frame1.packets.Add(QuicPacketNumber(20)); const std::vector<QuicInterval<QuicPacketNumber>> actual_intervals2( ack_frame1.packets.begin(), ack_frame1.packets.end()); std::vector<QuicInterval<QuicPacketNumber>> expected_intervals2; - expected_intervals2.emplace_back(QuicInterval<QuicPacketNumber>(1, 2)); - expected_intervals2.emplace_back(QuicInterval<QuicPacketNumber>(20, 21)); - expected_intervals2.emplace_back(QuicInterval<QuicPacketNumber>(99, 100)); + expected_intervals2.emplace_back( + QuicInterval<QuicPacketNumber>(QuicPacketNumber(1), QuicPacketNumber(2))); + expected_intervals2.emplace_back(QuicInterval<QuicPacketNumber>( + QuicPacketNumber(20), QuicPacketNumber(21))); + expected_intervals2.emplace_back(QuicInterval<QuicPacketNumber>( + QuicPacketNumber(99), QuicPacketNumber(100))); EXPECT_EQ(3u, ack_frame1.packets.NumIntervals()); EXPECT_EQ(expected_intervals2, actual_intervals2); - ack_frame1.packets.Add(19); - ack_frame1.packets.Add(21); + ack_frame1.packets.Add(QuicPacketNumber(19)); + ack_frame1.packets.Add(QuicPacketNumber(21)); const std::vector<QuicInterval<QuicPacketNumber>> actual_intervals3( ack_frame1.packets.begin(), ack_frame1.packets.end()); std::vector<QuicInterval<QuicPacketNumber>> expected_intervals3; - expected_intervals3.emplace_back(QuicInterval<QuicPacketNumber>(1, 2)); - expected_intervals3.emplace_back(QuicInterval<QuicPacketNumber>(19, 22)); - expected_intervals3.emplace_back(QuicInterval<QuicPacketNumber>(99, 100)); + expected_intervals3.emplace_back( + QuicInterval<QuicPacketNumber>(QuicPacketNumber(1), QuicPacketNumber(2))); + expected_intervals3.emplace_back(QuicInterval<QuicPacketNumber>( + QuicPacketNumber(19), QuicPacketNumber(22))); + expected_intervals3.emplace_back(QuicInterval<QuicPacketNumber>( + QuicPacketNumber(99), QuicPacketNumber(100))); EXPECT_EQ(expected_intervals3, actual_intervals3); - ack_frame1.packets.Add(20); + ack_frame1.packets.Add(QuicPacketNumber(20)); const std::vector<QuicInterval<QuicPacketNumber>> actual_intervals4( ack_frame1.packets.begin(), ack_frame1.packets.end()); @@ -293,37 +310,44 @@ EXPECT_EQ(expected_intervals3, actual_intervals4); QuicAckFrame ack_frame2; - ack_frame2.packets.Add(20); - ack_frame2.packets.Add(40); - ack_frame2.packets.Add(60); - ack_frame2.packets.Add(10); - ack_frame2.packets.Add(80); + ack_frame2.packets.Add(QuicPacketNumber(20)); + ack_frame2.packets.Add(QuicPacketNumber(40)); + ack_frame2.packets.Add(QuicPacketNumber(60)); + ack_frame2.packets.Add(QuicPacketNumber(10)); + ack_frame2.packets.Add(QuicPacketNumber(80)); const std::vector<QuicInterval<QuicPacketNumber>> actual_intervals5( ack_frame2.packets.begin(), ack_frame2.packets.end()); std::vector<QuicInterval<QuicPacketNumber>> expected_intervals5; - expected_intervals5.emplace_back(QuicInterval<QuicPacketNumber>(10, 11)); - expected_intervals5.emplace_back(QuicInterval<QuicPacketNumber>(20, 21)); - expected_intervals5.emplace_back(QuicInterval<QuicPacketNumber>(40, 41)); - expected_intervals5.emplace_back(QuicInterval<QuicPacketNumber>(60, 61)); - expected_intervals5.emplace_back(QuicInterval<QuicPacketNumber>(80, 81)); + expected_intervals5.emplace_back(QuicInterval<QuicPacketNumber>( + QuicPacketNumber(10), QuicPacketNumber(11))); + expected_intervals5.emplace_back(QuicInterval<QuicPacketNumber>( + QuicPacketNumber(20), QuicPacketNumber(21))); + expected_intervals5.emplace_back(QuicInterval<QuicPacketNumber>( + QuicPacketNumber(40), QuicPacketNumber(41))); + expected_intervals5.emplace_back(QuicInterval<QuicPacketNumber>( + QuicPacketNumber(60), QuicPacketNumber(61))); + expected_intervals5.emplace_back(QuicInterval<QuicPacketNumber>( + QuicPacketNumber(80), QuicPacketNumber(81))); EXPECT_EQ(expected_intervals5, actual_intervals5); } TEST_F(QuicFramesTest, AddInterval) { QuicAckFrame ack_frame1; - ack_frame1.packets.AddRange(1, 10); - ack_frame1.packets.AddRange(50, 100); + ack_frame1.packets.AddRange(QuicPacketNumber(1), QuicPacketNumber(10)); + ack_frame1.packets.AddRange(QuicPacketNumber(50), QuicPacketNumber(100)); EXPECT_EQ(2u, ack_frame1.packets.NumIntervals()); - EXPECT_EQ(1u, ack_frame1.packets.Min()); - EXPECT_EQ(99u, ack_frame1.packets.Max()); + EXPECT_EQ(QuicPacketNumber(1u), ack_frame1.packets.Min()); + EXPECT_EQ(QuicPacketNumber(99u), ack_frame1.packets.Max()); std::vector<QuicInterval<QuicPacketNumber>> expected_intervals; - expected_intervals.emplace_back(QuicInterval<QuicPacketNumber>(1, 10)); - expected_intervals.emplace_back(QuicInterval<QuicPacketNumber>(50, 100)); + expected_intervals.emplace_back(QuicInterval<QuicPacketNumber>( + QuicPacketNumber(1), QuicPacketNumber(10))); + expected_intervals.emplace_back(QuicInterval<QuicPacketNumber>( + QuicPacketNumber(50), QuicPacketNumber(100))); const std::vector<QuicInterval<QuicPacketNumber>> actual_intervals( ack_frame1.packets.begin(), ack_frame1.packets.end()); @@ -331,48 +355,58 @@ EXPECT_EQ(expected_intervals, actual_intervals); // Ensure adding a range within the existing ranges fails. - EXPECT_QUIC_BUG(ack_frame1.packets.AddRange(20, 30), ""); + EXPECT_QUIC_BUG( + ack_frame1.packets.AddRange(QuicPacketNumber(20), QuicPacketNumber(30)), + ""); const std::vector<QuicInterval<QuicPacketNumber>> actual_intervals2( ack_frame1.packets.begin(), ack_frame1.packets.end()); std::vector<QuicInterval<QuicPacketNumber>> expected_intervals2; - expected_intervals2.emplace_back(QuicInterval<QuicPacketNumber>(1, 10)); - expected_intervals2.emplace_back(QuicInterval<QuicPacketNumber>(50, 100)); + expected_intervals2.emplace_back(QuicInterval<QuicPacketNumber>( + QuicPacketNumber(1), QuicPacketNumber(10))); + expected_intervals2.emplace_back(QuicInterval<QuicPacketNumber>( + QuicPacketNumber(50), QuicPacketNumber(100))); EXPECT_EQ(expected_intervals2.size(), ack_frame1.packets.NumIntervals()); EXPECT_EQ(expected_intervals2, actual_intervals2); // Add ranges at both ends. QuicAckFrame ack_frame2; - ack_frame2.packets.AddRange(20, 25); - ack_frame2.packets.AddRange(40, 45); - ack_frame2.packets.AddRange(60, 65); - ack_frame2.packets.AddRange(10, 15); - ack_frame2.packets.AddRange(80, 85); + ack_frame2.packets.AddRange(QuicPacketNumber(20), QuicPacketNumber(25)); + ack_frame2.packets.AddRange(QuicPacketNumber(40), QuicPacketNumber(45)); + ack_frame2.packets.AddRange(QuicPacketNumber(60), QuicPacketNumber(65)); + ack_frame2.packets.AddRange(QuicPacketNumber(10), QuicPacketNumber(15)); + ack_frame2.packets.AddRange(QuicPacketNumber(80), QuicPacketNumber(85)); const std::vector<QuicInterval<QuicPacketNumber>> actual_intervals8( ack_frame2.packets.begin(), ack_frame2.packets.end()); std::vector<QuicInterval<QuicPacketNumber>> expected_intervals8; - expected_intervals8.emplace_back(QuicInterval<QuicPacketNumber>(10, 15)); - expected_intervals8.emplace_back(QuicInterval<QuicPacketNumber>(20, 25)); - expected_intervals8.emplace_back(QuicInterval<QuicPacketNumber>(40, 45)); - expected_intervals8.emplace_back(QuicInterval<QuicPacketNumber>(60, 65)); - expected_intervals8.emplace_back(QuicInterval<QuicPacketNumber>(80, 85)); + expected_intervals8.emplace_back(QuicInterval<QuicPacketNumber>( + QuicPacketNumber(10), QuicPacketNumber(15))); + expected_intervals8.emplace_back(QuicInterval<QuicPacketNumber>( + QuicPacketNumber(20), QuicPacketNumber(25))); + expected_intervals8.emplace_back(QuicInterval<QuicPacketNumber>( + QuicPacketNumber(40), QuicPacketNumber(45))); + expected_intervals8.emplace_back(QuicInterval<QuicPacketNumber>( + QuicPacketNumber(60), QuicPacketNumber(65))); + expected_intervals8.emplace_back(QuicInterval<QuicPacketNumber>( + QuicPacketNumber(80), QuicPacketNumber(85))); EXPECT_EQ(expected_intervals8, actual_intervals8); } TEST_F(QuicFramesTest, AddAdjacentForward) { QuicAckFrame ack_frame1; - ack_frame1.packets.Add(49); - ack_frame1.packets.AddRange(50, 60); - ack_frame1.packets.AddRange(60, 70); - ack_frame1.packets.AddRange(70, 100); + ack_frame1.packets.Add(QuicPacketNumber(49)); + ack_frame1.packets.AddRange(QuicPacketNumber(50), QuicPacketNumber(60)); + ack_frame1.packets.AddRange(QuicPacketNumber(60), QuicPacketNumber(70)); + ack_frame1.packets.AddRange(QuicPacketNumber(70), QuicPacketNumber(100)); std::vector<QuicInterval<QuicPacketNumber>> expected_intervals; - expected_intervals.emplace_back(QuicInterval<QuicPacketNumber>(49, 100)); + expected_intervals.emplace_back(QuicInterval<QuicPacketNumber>( + QuicPacketNumber(49), QuicPacketNumber(100))); const std::vector<QuicInterval<QuicPacketNumber>> actual_intervals( ack_frame1.packets.begin(), ack_frame1.packets.end()); @@ -382,13 +416,14 @@ TEST_F(QuicFramesTest, AddAdjacentReverse) { QuicAckFrame ack_frame1; - ack_frame1.packets.AddRange(70, 100); - ack_frame1.packets.AddRange(60, 70); - ack_frame1.packets.AddRange(50, 60); - ack_frame1.packets.Add(49); + ack_frame1.packets.AddRange(QuicPacketNumber(70), QuicPacketNumber(100)); + ack_frame1.packets.AddRange(QuicPacketNumber(60), QuicPacketNumber(70)); + ack_frame1.packets.AddRange(QuicPacketNumber(50), QuicPacketNumber(60)); + ack_frame1.packets.Add(QuicPacketNumber(49)); std::vector<QuicInterval<QuicPacketNumber>> expected_intervals; - expected_intervals.emplace_back(QuicInterval<QuicPacketNumber>(49, 100)); + expected_intervals.emplace_back(QuicInterval<QuicPacketNumber>( + QuicPacketNumber(49), QuicPacketNumber(100))); const std::vector<QuicInterval<QuicPacketNumber>> actual_intervals( ack_frame1.packets.begin(), ack_frame1.packets.end()); @@ -398,19 +433,19 @@ TEST_F(QuicFramesTest, RemoveSmallestInterval) { QuicAckFrame ack_frame1; - ack_frame1.largest_acked = 100u; - ack_frame1.packets.AddRange(51, 60); - ack_frame1.packets.AddRange(71, 80); - ack_frame1.packets.AddRange(91, 100); + ack_frame1.largest_acked = QuicPacketNumber(100u); + ack_frame1.packets.AddRange(QuicPacketNumber(51), QuicPacketNumber(60)); + ack_frame1.packets.AddRange(QuicPacketNumber(71), QuicPacketNumber(80)); + ack_frame1.packets.AddRange(QuicPacketNumber(91), QuicPacketNumber(100)); ack_frame1.packets.RemoveSmallestInterval(); EXPECT_EQ(2u, ack_frame1.packets.NumIntervals()); - EXPECT_EQ(71u, ack_frame1.packets.Min()); - EXPECT_EQ(99u, ack_frame1.packets.Max()); + EXPECT_EQ(QuicPacketNumber(71u), ack_frame1.packets.Min()); + EXPECT_EQ(QuicPacketNumber(99u), ack_frame1.packets.Max()); ack_frame1.packets.RemoveSmallestInterval(); EXPECT_EQ(1u, ack_frame1.packets.NumIntervals()); - EXPECT_EQ(91u, ack_frame1.packets.Min()); - EXPECT_EQ(99u, ack_frame1.packets.Max()); + EXPECT_EQ(QuicPacketNumber(91u), ack_frame1.packets.Min()); + EXPECT_EQ(QuicPacketNumber(99u), ack_frame1.packets.Max()); } class PacketNumberQueueTest : public QuicTest {}; @@ -418,85 +453,85 @@ // Tests that a queue contains the expected data after calls to Add(). TEST_F(PacketNumberQueueTest, AddRange) { PacketNumberQueue queue; - queue.AddRange(1, 51); - queue.Add(53); + queue.AddRange(QuicPacketNumber(1), QuicPacketNumber(51)); + queue.Add(QuicPacketNumber(53)); - EXPECT_FALSE(queue.Contains(0)); + EXPECT_FALSE(queue.Contains(QuicPacketNumber())); for (int i = 1; i < 51; ++i) { - EXPECT_TRUE(queue.Contains(i)); + EXPECT_TRUE(queue.Contains(QuicPacketNumber(i))); } - EXPECT_FALSE(queue.Contains(51)); - EXPECT_FALSE(queue.Contains(52)); - EXPECT_TRUE(queue.Contains(53)); - EXPECT_FALSE(queue.Contains(54)); + EXPECT_FALSE(queue.Contains(QuicPacketNumber(51))); + EXPECT_FALSE(queue.Contains(QuicPacketNumber(52))); + EXPECT_TRUE(queue.Contains(QuicPacketNumber(53))); + EXPECT_FALSE(queue.Contains(QuicPacketNumber(54))); EXPECT_EQ(51u, queue.NumPacketsSlow()); - EXPECT_EQ(1u, queue.Min()); - EXPECT_EQ(53u, queue.Max()); + EXPECT_EQ(QuicPacketNumber(1u), queue.Min()); + EXPECT_EQ(QuicPacketNumber(53u), queue.Max()); - queue.Add(70); - EXPECT_EQ(70u, queue.Max()); + queue.Add(QuicPacketNumber(70)); + EXPECT_EQ(QuicPacketNumber(70u), queue.Max()); } // Tests Contains function TEST_F(PacketNumberQueueTest, Contains) { PacketNumberQueue queue; - EXPECT_FALSE(queue.Contains(0)); - queue.AddRange(5, 10); - queue.Add(20); + EXPECT_FALSE(queue.Contains(QuicPacketNumber())); + queue.AddRange(QuicPacketNumber(5), QuicPacketNumber(10)); + queue.Add(QuicPacketNumber(20)); for (int i = 1; i < 5; ++i) { - EXPECT_FALSE(queue.Contains(i)); + EXPECT_FALSE(queue.Contains(QuicPacketNumber(i))); } for (int i = 5; i < 10; ++i) { - EXPECT_TRUE(queue.Contains(i)); + EXPECT_TRUE(queue.Contains(QuicPacketNumber(i))); } for (int i = 10; i < 20; ++i) { - EXPECT_FALSE(queue.Contains(i)); + EXPECT_FALSE(queue.Contains(QuicPacketNumber(i))); } - EXPECT_TRUE(queue.Contains(20)); - EXPECT_FALSE(queue.Contains(21)); + EXPECT_TRUE(queue.Contains(QuicPacketNumber(20))); + EXPECT_FALSE(queue.Contains(QuicPacketNumber(21))); PacketNumberQueue queue2; - EXPECT_FALSE(queue2.Contains(1)); + EXPECT_FALSE(queue2.Contains(QuicPacketNumber(1))); for (int i = 1; i < 51; ++i) { - queue2.Add(2 * i); + queue2.Add(QuicPacketNumber(2 * i)); } - EXPECT_FALSE(queue2.Contains(0)); + EXPECT_FALSE(queue2.Contains(QuicPacketNumber())); for (int i = 1; i < 51; ++i) { if (i % 2 == 0) { - EXPECT_TRUE(queue2.Contains(i)); + EXPECT_TRUE(queue2.Contains(QuicPacketNumber(i))); } else { - EXPECT_FALSE(queue2.Contains(i)); + EXPECT_FALSE(queue2.Contains(QuicPacketNumber(i))); } } - EXPECT_FALSE(queue2.Contains(101)); + EXPECT_FALSE(queue2.Contains(QuicPacketNumber(101))); } // Tests that a queue contains the expected data after calls to RemoveUpTo(). TEST_F(PacketNumberQueueTest, Removal) { PacketNumberQueue queue; - EXPECT_FALSE(queue.Contains(51)); - queue.AddRange(0, 100); + EXPECT_FALSE(queue.Contains(QuicPacketNumber(51))); + queue.AddRange(QuicPacketNumber(1), QuicPacketNumber(100)); - EXPECT_TRUE(queue.RemoveUpTo(51)); - EXPECT_FALSE(queue.RemoveUpTo(51)); + EXPECT_TRUE(queue.RemoveUpTo(QuicPacketNumber(51))); + EXPECT_FALSE(queue.RemoveUpTo(QuicPacketNumber(51))); - EXPECT_FALSE(queue.Contains(0)); + EXPECT_FALSE(queue.Contains(QuicPacketNumber())); for (int i = 1; i < 51; ++i) { - EXPECT_FALSE(queue.Contains(i)); + EXPECT_FALSE(queue.Contains(QuicPacketNumber(i))); } for (int i = 51; i < 100; ++i) { - EXPECT_TRUE(queue.Contains(i)); + EXPECT_TRUE(queue.Contains(QuicPacketNumber(i))); } EXPECT_EQ(49u, queue.NumPacketsSlow()); - EXPECT_EQ(51u, queue.Min()); - EXPECT_EQ(99u, queue.Max()); + EXPECT_EQ(QuicPacketNumber(51u), queue.Min()); + EXPECT_EQ(QuicPacketNumber(99u), queue.Max()); PacketNumberQueue queue2; - queue2.AddRange(0, 5); - EXPECT_TRUE(queue2.RemoveUpTo(3)); - EXPECT_TRUE(queue2.RemoveUpTo(50)); + queue2.AddRange(QuicPacketNumber(1), QuicPacketNumber(5)); + EXPECT_TRUE(queue2.RemoveUpTo(QuicPacketNumber(3))); + EXPECT_TRUE(queue2.RemoveUpTo(QuicPacketNumber(50))); EXPECT_TRUE(queue2.Empty()); } @@ -506,8 +541,8 @@ EXPECT_TRUE(queue.Empty()); EXPECT_EQ(0u, queue.NumPacketsSlow()); - queue.AddRange(1, 100); - EXPECT_TRUE(queue.RemoveUpTo(100)); + queue.AddRange(QuicPacketNumber(1), QuicPacketNumber(100)); + EXPECT_TRUE(queue.RemoveUpTo(QuicPacketNumber(100))); EXPECT_TRUE(queue.Empty()); EXPECT_EQ(0u, queue.NumPacketsSlow()); } @@ -518,29 +553,30 @@ PacketNumberQueue queue; oss << queue; - queue.Add(1); - queue.AddRange(50, 100); + queue.Add(QuicPacketNumber(1)); + queue.AddRange(QuicPacketNumber(50), QuicPacketNumber(100)); oss << queue; } // Tests that the iterators returned from a packet queue iterate over the queue. TEST_F(PacketNumberQueueTest, Iterators) { PacketNumberQueue queue; - queue.AddRange(1, 100); + queue.AddRange(QuicPacketNumber(1), QuicPacketNumber(100)); const std::vector<QuicInterval<QuicPacketNumber>> actual_intervals( queue.begin(), queue.end()); PacketNumberQueue queue2; for (int i = 1; i < 100; i++) { - queue2.AddRange(i, i + 1); + queue2.AddRange(QuicPacketNumber(i), QuicPacketNumber(i + 1)); } const std::vector<QuicInterval<QuicPacketNumber>> actual_intervals2( queue2.begin(), queue2.end()); std::vector<QuicInterval<QuicPacketNumber>> expected_intervals; - expected_intervals.emplace_back(QuicInterval<QuicPacketNumber>(1, 100)); + expected_intervals.emplace_back(QuicInterval<QuicPacketNumber>( + QuicPacketNumber(1), QuicPacketNumber(100))); EXPECT_EQ(expected_intervals, actual_intervals); EXPECT_EQ(expected_intervals, actual_intervals2); EXPECT_EQ(actual_intervals, actual_intervals2); @@ -548,10 +584,10 @@ TEST_F(PacketNumberQueueTest, ReversedIterators) { PacketNumberQueue queue; - queue.AddRange(1, 100); + queue.AddRange(QuicPacketNumber(1), QuicPacketNumber(100)); PacketNumberQueue queue2; for (int i = 1; i < 100; i++) { - queue2.AddRange(i, i + 1); + queue2.AddRange(QuicPacketNumber(i), QuicPacketNumber(i + 1)); } const std::vector<QuicInterval<QuicPacketNumber>> actual_intervals( queue.rbegin(), queue.rend()); @@ -559,7 +595,8 @@ queue2.rbegin(), queue2.rend()); std::vector<QuicInterval<QuicPacketNumber>> expected_intervals; - expected_intervals.emplace_back(QuicInterval<QuicPacketNumber>(1, 100)); + expected_intervals.emplace_back(QuicInterval<QuicPacketNumber>( + QuicPacketNumber(1), QuicPacketNumber(100))); EXPECT_EQ(expected_intervals, actual_intervals); EXPECT_EQ(expected_intervals, actual_intervals2); @@ -567,7 +604,7 @@ PacketNumberQueue queue3; for (int i = 1; i < 20; i++) { - queue3.Add(2 * i); + queue3.Add(QuicPacketNumber(2 * i)); } auto begin = queue3.begin(); @@ -583,17 +620,17 @@ TEST_F(PacketNumberQueueTest, IntervalLengthAndRemoveInterval) { PacketNumberQueue queue; - queue.AddRange(1, 10); - queue.AddRange(20, 30); - queue.AddRange(40, 50); + queue.AddRange(QuicPacketNumber(1), QuicPacketNumber(10)); + queue.AddRange(QuicPacketNumber(20), QuicPacketNumber(30)); + queue.AddRange(QuicPacketNumber(40), QuicPacketNumber(50)); EXPECT_EQ(3u, queue.NumIntervals()); EXPECT_EQ(10u, queue.LastIntervalLength()); - EXPECT_TRUE(queue.RemoveUpTo(25)); + EXPECT_TRUE(queue.RemoveUpTo(QuicPacketNumber(25))); EXPECT_EQ(2u, queue.NumIntervals()); EXPECT_EQ(10u, queue.LastIntervalLength()); - EXPECT_EQ(25u, queue.Min()); - EXPECT_EQ(49u, queue.Max()); + EXPECT_EQ(QuicPacketNumber(25u), queue.Min()); + EXPECT_EQ(QuicPacketNumber(49u), queue.Max()); } } // namespace
diff --git a/quic/core/frames/quic_stop_waiting_frame.cc b/quic/core/frames/quic_stop_waiting_frame.cc index 696bed4..0674e8f 100644 --- a/quic/core/frames/quic_stop_waiting_frame.cc +++ b/quic/core/frames/quic_stop_waiting_frame.cc
@@ -8,7 +8,7 @@ namespace quic { -QuicStopWaitingFrame::QuicStopWaitingFrame() : least_unacked(0) {} +QuicStopWaitingFrame::QuicStopWaitingFrame() {} QuicStopWaitingFrame::~QuicStopWaitingFrame() {}
diff --git a/quic/core/http/end_to_end_test.cc b/quic/core/http/end_to_end_test.cc index 55c72ff..132da8e 100644 --- a/quic/core/http/end_to_end_test.cc +++ b/quic/core/http/end_to_end_test.cc
@@ -22,6 +22,7 @@ #include "net/third_party/quiche/src/quic/core/quic_packets.h" #include "net/third_party/quiche/src/quic/core/quic_session.h" #include "net/third_party/quiche/src/quic/core/quic_utils.h" +#include "net/third_party/quiche/src/quic/platform/api/quic_epoll.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" @@ -62,8 +63,6 @@ #include "net/third_party/quiche/src/quic/tools/quic_simple_client_stream.h" #include "net/third_party/quiche/src/quic/tools/quic_simple_server_stream.h" -using gfe2::EpollEvent; -using gfe2::EpollServer; using spdy::kV3LowestPriority; using spdy::SETTINGS_MAX_HEADER_LIST_SIZE; using spdy::SpdyFramer; @@ -260,7 +259,7 @@ explicit ClientDelegate(QuicClient* client) : client_(client) {} ~ClientDelegate() override = default; void OnCanWrite() override { - EpollEvent event(EPOLLOUT); + QuicEpollEvent event(EPOLLOUT); client_->epoll_network_helper()->OnEvent(client_->GetLatestFD(), &event); } @@ -278,10 +277,11 @@ server_hostname_("test.example.com"), client_writer_(nullptr), server_writer_(nullptr), - negotiated_version_(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED), + negotiated_version_(UnsupportedQuicVersion()), chlo_multiplier_(0), stream_factory_(nullptr), - support_server_push_(false) { + support_server_push_(false), + override_connection_id_(nullptr) { FLAGS_quic_supports_tls_handshake = true; SetQuicRestartFlag(quic_no_server_conn_ver_negotiation2, true); SetQuicReloadableFlag(quic_no_client_conn_ver_negotiation, true); @@ -330,6 +330,9 @@ if (!pre_shared_key_client_.empty()) { client->client()->SetPreSharedKey(pre_shared_key_client_); } + if (override_connection_id_ != nullptr) { + client->UseConnectionId(*override_connection_id_); + } client->Connect(); return client; } @@ -419,14 +422,14 @@ } CreateClientWithWriter(); - static EpollEvent event(EPOLLOUT); + static QuicEpollEvent event(EPOLLOUT); if (client_writer_ != nullptr) { client_writer_->Initialize( QuicConnectionPeer::GetHelper( client_->client()->client_session()->connection()), QuicConnectionPeer::GetAlarmFactory( client_->client()->client_session()->connection()), - absl::make_unique<ClientDelegate>(client_->client())); + QuicMakeUnique<ClientDelegate>(client_->client())); } initialized_ = true; return client_->client()->connected(); @@ -470,7 +473,7 @@ server_writer_->Initialize(QuicDispatcherPeer::GetHelper(dispatcher), QuicDispatcherPeer::GetAlarmFactory(dispatcher), - absl::make_unique<ServerDelegate>(dispatcher)); + QuicMakeUnique<ServerDelegate>(dispatcher)); if (stream_factory_ != nullptr) { down_cast<QuicTestServer*>(server_thread_->server()) ->SetSpdyStreamFactory(stream_factory_); @@ -632,6 +635,7 @@ bool support_server_push_; QuicString pre_shared_key_client_; QuicString pre_shared_key_server_; + QuicConnectionId* override_connection_id_; }; // Run all end to end tests with all supported versions. @@ -724,6 +728,28 @@ client_->client()->GetNumSentClientHellos()); } +TEST_P(EndToEndTest, SimpleRequestResponseZeroConnectionID) { + QuicConnectionId connection_id = QuicUtils::CreateZeroConnectionId( + GetParam().negotiated_version.transport_version); + override_connection_id_ = &connection_id; + 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()); + EXPECT_EQ(client_->client()->client_session()->connection()->connection_id(), + QuicUtils::CreateZeroConnectionId( + 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); @@ -1870,7 +1896,7 @@ // Register the new FD for epoll events. int new_fd = client_->client()->GetLatestFD(); - EpollServer* eps = client_->epoll_server(); + QuicEpollServer* eps = client_->epoll_server(); eps->RegisterFD(new_fd, client_->client()->epoll_network_helper(), EPOLLIN | EPOLLOUT | EPOLLET); @@ -3132,13 +3158,13 @@ client->UseWriter(client_writer_); client->Connect(); client_.reset(client); - static EpollEvent event(EPOLLOUT); + static QuicEpollEvent event(EPOLLOUT); client_writer_->Initialize( QuicConnectionPeer::GetHelper( client_->client()->client_session()->connection()), QuicConnectionPeer::GetAlarmFactory( client_->client()->client_session()->connection()), - absl::make_unique<ClientDelegate>(client_->client())); + QuicMakeUnique<ClientDelegate>(client_->client())); initialized_ = true; ASSERT_TRUE(client_->client()->connected()); @@ -3695,6 +3721,32 @@ EXPECT_EQ(kStopSendingTestCode, client_stream->last_stop_sending_code()); } +TEST_P(EndToEndTest, SimpleStopSendingRstStreamTest) { + ASSERT_TRUE(Initialize()); + + // Send a request without a fin, to keep the stream open + SpdyHeaderBlock headers; + headers[":method"] = "POST"; + headers[":path"] = "/foo"; + headers[":scheme"] = "https"; + headers[":authority"] = server_hostname_; + client_->SendMessage(headers, "", /*fin=*/false); + // Stream should be open + ASSERT_NE(nullptr, client_->latest_created_stream()); + EXPECT_FALSE( + QuicStreamPeer::write_side_closed(client_->latest_created_stream())); + EXPECT_FALSE( + QuicStreamPeer::read_side_closed(client_->latest_created_stream())); + + // Send a RST_STREAM+STOP_SENDING on the stream + // Code is not important. + client_->latest_created_stream()->Reset(QUIC_BAD_APPLICATION_PAYLOAD); + client_->WaitForResponse(); + + // Stream should be gone. + ASSERT_EQ(nullptr, client_->latest_created_stream()); +} + } // namespace } // namespace test } // namespace quic
diff --git a/quic/core/http/http_decoder.cc b/quic/core/http/http_decoder.cc index f1d6de0..345f2cb 100644 --- a/quic/core/http/http_decoder.cc +++ b/quic/core/http/http_decoder.cc
@@ -262,6 +262,24 @@ } return; } + + case 0xE: { // DUPLICATE_PUSH + BufferFramePayload(reader); + if (remaining_frame_length_ != 0) { + return; + } + QuicDataReader reader(buffer_.data(), current_frame_length_, + NETWORK_BYTE_ORDER); + DuplicatePushFrame frame; + if (!reader.ReadVarInt62(&frame.push_id)) { + RaiseError(QUIC_INTERNAL_ERROR, "Unable to read push_id"); + return; + } + visitor_->OnDuplicatePushFrame(frame); + state_ = STATE_READING_FRAME_LENGTH; + current_length_field_size_ = 0; + return; + } // Reserved frame types. // TODO(rch): Since these are actually the same behavior as the // default, we probably don't need to special case them here?
diff --git a/quic/core/http/http_decoder.h b/quic/core/http/http_decoder.h index 730bbe3..a5f41b5 100644 --- a/quic/core/http/http_decoder.h +++ b/quic/core/http/http_decoder.h
@@ -58,7 +58,10 @@ // Called when a SETTINGS frame has been successfully parsed. virtual void OnSettingsFrame(const SettingsFrame& frame) = 0; - // Called when a DATA frame has been recevied, |frame_lengths| will be + // Called when a DUPLICATE_PUSH frame has been successfully parsed. + virtual void OnDuplicatePushFrame(const DuplicatePushFrame& frame) = 0; + + // Called when a DATA frame has been received, |frame_lengths| will be // passed to inform header length and payload length of the frame. virtual void OnDataFrameStart(Http3FrameLengths frame_length) = 0; // Called when the payload of a DATA frame has read. May be called
diff --git a/quic/core/http/http_decoder_test.cc b/quic/core/http/http_decoder_test.cc index 5261d65..c2b303c 100644 --- a/quic/core/http/http_decoder_test.cc +++ b/quic/core/http/http_decoder_test.cc
@@ -23,6 +23,7 @@ MOCK_METHOD1(OnMaxPushIdFrame, void(const MaxPushIdFrame& frame)); MOCK_METHOD1(OnGoAwayFrame, void(const GoAwayFrame& frame)); MOCK_METHOD1(OnSettingsFrame, void(const SettingsFrame& frame)); + MOCK_METHOD1(OnDuplicatePushFrame, void(const DuplicatePushFrame& frame)); MOCK_METHOD1(OnDataFrameStart, void(Http3FrameLengths frame_lengths)); MOCK_METHOD1(OnDataFramePayload, void(QuicStringPiece payload)); @@ -134,7 +135,7 @@ // Process the full frame. InSequence s; EXPECT_CALL(visitor_, OnPushPromiseFrameStart(1)); - EXPECT_CALL(visitor_, OnPushPromiseFramePayload("Headers")); + EXPECT_CALL(visitor_, OnPushPromiseFramePayload(QuicStringPiece("Headers"))); EXPECT_CALL(visitor_, OnPushPromiseFrameEnd()); EXPECT_EQ(QUIC_ARRAYSIZE(input), decoder_.ProcessInput(input, QUIC_ARRAYSIZE(input))); @@ -143,13 +144,13 @@ // Process the frame incremently. EXPECT_CALL(visitor_, OnPushPromiseFrameStart(1)); - EXPECT_CALL(visitor_, OnPushPromiseFramePayload("H")); - EXPECT_CALL(visitor_, OnPushPromiseFramePayload("e")); - EXPECT_CALL(visitor_, OnPushPromiseFramePayload("a")); - EXPECT_CALL(visitor_, OnPushPromiseFramePayload("d")); - EXPECT_CALL(visitor_, OnPushPromiseFramePayload("e")); - EXPECT_CALL(visitor_, OnPushPromiseFramePayload("r")); - EXPECT_CALL(visitor_, OnPushPromiseFramePayload("s")); + EXPECT_CALL(visitor_, OnPushPromiseFramePayload(QuicStringPiece("H"))); + EXPECT_CALL(visitor_, OnPushPromiseFramePayload(QuicStringPiece("e"))); + EXPECT_CALL(visitor_, OnPushPromiseFramePayload(QuicStringPiece("a"))); + EXPECT_CALL(visitor_, OnPushPromiseFramePayload(QuicStringPiece("d"))); + EXPECT_CALL(visitor_, OnPushPromiseFramePayload(QuicStringPiece("e"))); + EXPECT_CALL(visitor_, OnPushPromiseFramePayload(QuicStringPiece("r"))); + EXPECT_CALL(visitor_, OnPushPromiseFramePayload(QuicStringPiece("s"))); EXPECT_CALL(visitor_, OnPushPromiseFrameEnd()); for (char c : input) { EXPECT_EQ(1u, decoder_.ProcessInput(&c, 1)); @@ -182,6 +183,29 @@ EXPECT_EQ("", decoder_.error_detail()); } +TEST_F(HttpDecoderTest, DuplicatePush) { + char input[] = {// length + 0x1, + // type (DUPLICATE_PUSH) + 0x0E, + // Push Id + 0x01}; + // Process the full frame. + EXPECT_CALL(visitor_, OnDuplicatePushFrame(DuplicatePushFrame({1}))); + EXPECT_EQ(QUIC_ARRAYSIZE(input), + decoder_.ProcessInput(input, QUIC_ARRAYSIZE(input))); + EXPECT_EQ(QUIC_NO_ERROR, decoder_.error()); + EXPECT_EQ("", decoder_.error_detail()); + + // Process the frame incremently. + EXPECT_CALL(visitor_, OnDuplicatePushFrame(DuplicatePushFrame({1}))); + for (char c : input) { + EXPECT_EQ(1u, decoder_.ProcessInput(&c, 1)); + } + EXPECT_EQ(QUIC_NO_ERROR, decoder_.error()); + EXPECT_EQ("", decoder_.error_detail()); +} + TEST_F(HttpDecoderTest, PriorityFrame) { char input[] = {// length 0x4, @@ -273,7 +297,7 @@ // Process the full frame. InSequence s; EXPECT_CALL(visitor_, OnDataFrameStart(Http3FrameLengths(2, 5))); - EXPECT_CALL(visitor_, OnDataFramePayload("Data!")); + EXPECT_CALL(visitor_, OnDataFramePayload(QuicStringPiece("Data!"))); EXPECT_CALL(visitor_, OnDataFrameEnd()); EXPECT_EQ(QUIC_ARRAYSIZE(input), decoder_.ProcessInput(input, QUIC_ARRAYSIZE(input))); @@ -282,11 +306,11 @@ // Process the frame incremently. EXPECT_CALL(visitor_, OnDataFrameStart(Http3FrameLengths(2, 5))); - EXPECT_CALL(visitor_, OnDataFramePayload("D")); - EXPECT_CALL(visitor_, OnDataFramePayload("a")); - EXPECT_CALL(visitor_, OnDataFramePayload("t")); - EXPECT_CALL(visitor_, OnDataFramePayload("a")); - EXPECT_CALL(visitor_, OnDataFramePayload("!")); + EXPECT_CALL(visitor_, OnDataFramePayload(QuicStringPiece("D"))); + EXPECT_CALL(visitor_, OnDataFramePayload(QuicStringPiece("a"))); + EXPECT_CALL(visitor_, OnDataFramePayload(QuicStringPiece("t"))); + EXPECT_CALL(visitor_, OnDataFramePayload(QuicStringPiece("a"))); + EXPECT_CALL(visitor_, OnDataFramePayload(QuicStringPiece("!"))); EXPECT_CALL(visitor_, OnDataFrameEnd()); for (char c : input) { EXPECT_EQ(1u, decoder_.ProcessInput(&c, 1)); @@ -358,7 +382,7 @@ // Process the full frame. InSequence s; EXPECT_CALL(visitor_, OnHeadersFrameStart()); - EXPECT_CALL(visitor_, OnHeadersFramePayload("Headers")); + EXPECT_CALL(visitor_, OnHeadersFramePayload(QuicStringPiece("Headers"))); EXPECT_CALL(visitor_, OnHeadersFrameEnd()); EXPECT_EQ(QUIC_ARRAYSIZE(input), decoder_.ProcessInput(input, QUIC_ARRAYSIZE(input))); @@ -367,13 +391,13 @@ // Process the frame incremently. EXPECT_CALL(visitor_, OnHeadersFrameStart()); - EXPECT_CALL(visitor_, OnHeadersFramePayload("H")); - EXPECT_CALL(visitor_, OnHeadersFramePayload("e")); - EXPECT_CALL(visitor_, OnHeadersFramePayload("a")); - EXPECT_CALL(visitor_, OnHeadersFramePayload("d")); - EXPECT_CALL(visitor_, OnHeadersFramePayload("e")); - EXPECT_CALL(visitor_, OnHeadersFramePayload("r")); - EXPECT_CALL(visitor_, OnHeadersFramePayload("s")); + EXPECT_CALL(visitor_, OnHeadersFramePayload(QuicStringPiece("H"))); + EXPECT_CALL(visitor_, OnHeadersFramePayload(QuicStringPiece("e"))); + EXPECT_CALL(visitor_, OnHeadersFramePayload(QuicStringPiece("a"))); + EXPECT_CALL(visitor_, OnHeadersFramePayload(QuicStringPiece("d"))); + EXPECT_CALL(visitor_, OnHeadersFramePayload(QuicStringPiece("e"))); + EXPECT_CALL(visitor_, OnHeadersFramePayload(QuicStringPiece("r"))); + EXPECT_CALL(visitor_, OnHeadersFramePayload(QuicStringPiece("s"))); EXPECT_CALL(visitor_, OnHeadersFrameEnd()); 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 6e2487b..7c07838 100644 --- a/quic/core/http/http_encoder.cc +++ b/quic/core/http/http_encoder.cc
@@ -59,33 +59,32 @@ HttpEncoder::~HttpEncoder() {} QuicByteCount HttpEncoder::SerializeDataFrameHeader( - QuicByteCount length, + QuicByteCount payload_length, std::unique_ptr<char[]>* output) { - DCHECK_NE(0u, length); + DCHECK_NE(0u, payload_length); QuicByteCount header_length = - QuicDataWriter::GetVarInt62Len(length) + kFrameTypeLength; + QuicDataWriter::GetVarInt62Len(payload_length) + kFrameTypeLength; output->reset(new char[header_length]); QuicDataWriter writer(header_length, output->get(), NETWORK_BYTE_ORDER); - if (WriteFrameHeader(length, HttpFrameType::DATA, &writer)) { + if (WriteFrameHeader(payload_length, HttpFrameType::DATA, &writer)) { return header_length; } return 0; } QuicByteCount HttpEncoder::SerializeHeadersFrameHeader( - const HeadersFrame& headers, + QuicByteCount payload_length, std::unique_ptr<char[]>* output) { + DCHECK_NE(0u, payload_length); QuicByteCount header_length = - QuicDataWriter::GetVarInt62Len(headers.headers.length()) + - kFrameTypeLength; + QuicDataWriter::GetVarInt62Len(payload_length) + kFrameTypeLength; output->reset(new char[header_length]); QuicDataWriter writer(header_length, output->get(), NETWORK_BYTE_ORDER); - if (WriteFrameHeader(headers.headers.length(), HttpFrameType::HEADERS, - &writer)) { + if (WriteFrameHeader(payload_length, HttpFrameType::HEADERS, &writer)) { return header_length; } return 0; @@ -225,6 +224,24 @@ return 0; } +QuicByteCount HttpEncoder::SerializeDuplicatePushFrame( + const DuplicatePushFrame& duplicate_push, + std::unique_ptr<char[]>* output) { + QuicByteCount payload_length = + QuicDataWriter::GetVarInt62Len(duplicate_push.push_id); + QuicByteCount total_length = GetTotalLength(payload_length); + + output->reset(new char[total_length]); + QuicDataWriter writer(total_length, output->get(), NETWORK_BYTE_ORDER); + + if (WriteFrameHeader(payload_length, HttpFrameType::DUPLICATE_PUSH, + &writer) && + writer.WriteVarInt62(duplicate_push.push_id)) { + return total_length; + } + return 0; +} + bool HttpEncoder::WriteFrameHeader(QuicByteCount length, HttpFrameType type, QuicDataWriter* writer) {
diff --git a/quic/core/http/http_encoder.h b/quic/core/http/http_encoder.h index 79b76e9..f04e6e4 100644 --- a/quic/core/http/http_encoder.h +++ b/quic/core/http/http_encoder.h
@@ -24,14 +24,14 @@ ~HttpEncoder(); - // Serializes the header of a DATA frame into a new buffer stored in |output|. + // Serializes a DATA frame header into a new buffer stored in |output|. // Returns the length of the buffer on success, or 0 otherwise. - QuicByteCount SerializeDataFrameHeader(QuicByteCount length, + QuicByteCount SerializeDataFrameHeader(QuicByteCount payload_length, std::unique_ptr<char[]>* output); - // Serializes the header of a HEADERS frame into a new buffer stored in - // |output|. Returns the length of the buffer on success, or 0 otherwise. - QuicByteCount SerializeHeadersFrameHeader(const HeadersFrame& headers, + // Serializes a HEADERS frame header into a new buffer stored in |output|. + // Returns the length of the buffer on success, or 0 otherwise. + QuicByteCount SerializeHeadersFrameHeader(QuicByteCount payload_length, std::unique_ptr<char[]>* output); // Serializes a PRIORITY frame into a new buffer stored in |output|. @@ -66,6 +66,12 @@ QuicByteCount SerializeMaxPushIdFrame(const MaxPushIdFrame& max_push_id, std::unique_ptr<char[]>* output); + // Serialize a DUPLICATE_PUSH frame into a new buffer stored in |output|. + // Returns the length of the buffer on success, or 0 otherwise. + QuicByteCount SerializeDuplicatePushFrame( + const DuplicatePushFrame& duplicate_push, + std::unique_ptr<char[]>* output); + private: bool WriteFrameHeader(QuicByteCount length, HttpFrameType type,
diff --git a/quic/core/http/http_encoder_test.cc b/quic/core/http/http_encoder_test.cc index 70cfd6a..a484aed 100644 --- a/quic/core/http/http_encoder_test.cc +++ b/quic/core/http/http_encoder_test.cc
@@ -18,11 +18,9 @@ }; TEST_F(HttpEncoderTest, SerializeDataFrameHeader) { - DataFrame data; - data.data = "Data!"; std::unique_ptr<char[]> buffer; uint64_t length = - encoder_.SerializeDataFrameHeader(data.data.length(), &buffer); + encoder_.SerializeDataFrameHeader(/* payload_length = */ 5, &buffer); char output[] = {// length 0x05, // type (DATA) @@ -33,10 +31,9 @@ } TEST_F(HttpEncoderTest, SerializeHeadersFrameHeader) { - HeadersFrame headers; - headers.headers = "Headers"; std::unique_ptr<char[]> buffer; - uint64_t length = encoder_.SerializeHeadersFrameHeader(headers, &buffer); + uint64_t length = + encoder_.SerializeHeadersFrameHeader(/* payload_length = */ 7, &buffer); char output[] = {// length 0x07, // type (HEADERS) @@ -167,5 +164,22 @@ QUIC_ARRAYSIZE(output)); } +TEST_F(HttpEncoderTest, SerializeDuplicatePushFrame) { + DuplicatePushFrame duplicate_push; + duplicate_push.push_id = 0x1; + char output[] = {// length + 0x1, + // type (DUPLICATE_PUSH) + 0x0E, + // Push Id + 0x01}; + std::unique_ptr<char[]> buffer; + uint64_t length = + encoder_.SerializeDuplicatePushFrame(duplicate_push, &buffer); + EXPECT_EQ(QUIC_ARRAYSIZE(output), length); + CompareCharArraysWithHexError("DUPLICATE_PUSH", buffer.get(), length, output, + QUIC_ARRAYSIZE(output)); +} + } // namespace test } // namespace quic
diff --git a/quic/core/http/http_frames.h b/quic/core/http/http_frames.h index 6b6aa41..ea11557 100644 --- a/quic/core/http/http_frames.h +++ b/quic/core/http/http_frames.h
@@ -21,10 +21,11 @@ SETTINGS = 0x4, PUSH_PROMISE = 0x5, GOAWAY = 0x7, - MAX_PUSH_ID = 0xD + MAX_PUSH_ID = 0xD, + DUPLICATE_PUSH = 0xE }; -// 4.2.2. DATA +// 4.2.1. DATA // // DATA frames (type=0x0) convey arbitrary, variable-length sequences of // octets associated with an HTTP request or response payload. @@ -32,7 +33,7 @@ QuicStringPiece data; }; -// 4.2.3. HEADERS +// 4.2.2. HEADERS // // The HEADERS frame (type=0x1) is used to carry a header block, // compressed using QPACK. @@ -40,7 +41,7 @@ QuicStringPiece headers; }; -// 4.2.4. PRIORITY +// 4.2.3. PRIORITY // // The PRIORITY (type=0x02) frame specifies the sender-advised priority // of a stream @@ -69,7 +70,7 @@ } }; -// 4.2.5. CANCEL_PUSH +// 4.2.4. CANCEL_PUSH // // The CANCEL_PUSH frame (type=0x3) is used to request cancellation of // server push prior to the push stream being created. @@ -83,7 +84,7 @@ } }; -// 4.2.6. SETTINGS +// 4.2.5. SETTINGS // // The SETTINGS frame (type=0x4) conveys configuration parameters that // affect how endpoints communicate, such as preferences and constraints @@ -100,7 +101,7 @@ } }; -// 4.2.7. PUSH_PROMISE +// 4.2.6. PUSH_PROMISE // // The PUSH_PROMISE frame (type=0x05) is used to carry a request header // set from server to client, as in HTTP/2. @@ -113,7 +114,7 @@ } }; -// 4.2.8. GOAWAY +// 4.2.7. GOAWAY // // The GOAWAY frame (type=0x7) is used to initiate graceful shutdown of // a connection by a server. @@ -125,7 +126,7 @@ } }; -// 4.2.9. MAX_PUSH_ID +// 4.2.8. MAX_PUSH_ID // // The MAX_PUSH_ID frame (type=0xD) is used by clients to control the // number of server pushes that the server can initiate. @@ -137,6 +138,19 @@ } }; +// 4.2.9. DUPLICATE_PUSH +// +// The DUPLICATE_PUSH frame (type=0xE) is used by servers to indicate +// that an existing pushed resource is related to multiple client +// requests. +struct DuplicatePushFrame { + PushId push_id; + + bool operator==(const DuplicatePushFrame& rhs) const { + return push_id == rhs.push_id; + } +}; + } // namespace quic #endif // QUICHE_QUIC_CORE_HTTP_HTTP_FRAMES_H_
diff --git a/quic/core/http/quic_server_session_base.cc b/quic/core/http/quic_server_session_base.cc index 47e3a27..40b43dc 100644 --- a/quic/core/http/quic_server_session_base.cc +++ b/quic/core/http/quic_server_session_base.cc
@@ -30,8 +30,7 @@ helper_(helper), bandwidth_resumption_enabled_(false), bandwidth_estimate_sent_to_client_(QuicBandwidth::Zero()), - last_scup_time_(QuicTime::Zero()), - last_scup_packet_number_(0) {} + last_scup_time_(QuicTime::Zero()) {} QuicServerSessionBase::~QuicServerSessionBase() {} @@ -112,9 +111,15 @@ int64_t srtt_ms = sent_packet_manager.GetRttStats()->smoothed_rtt().ToMilliseconds(); int64_t now_ms = (now - last_scup_time_).ToMilliseconds(); - int64_t packets_since_last_scup = - connection()->sent_packet_manager().GetLargestSentPacket() - - last_scup_packet_number_; + int64_t packets_since_last_scup = 0; + const QuicPacketNumber largest_sent_packet = + connection()->sent_packet_manager().GetLargestSentPacket(); + if (largest_sent_packet.IsInitialized()) { + packets_since_last_scup = + last_scup_packet_number_.IsInitialized() + ? largest_sent_packet - last_scup_packet_number_ + : largest_sent_packet.ToUint64(); + } if (now_ms < (kMinIntervalBetweenServerConfigUpdatesRTTs * srtt_ms) || now_ms < kMinIntervalBetweenServerConfigUpdatesMs || packets_since_last_scup < kMinPacketsBetweenServerConfigUpdates) {
diff --git a/quic/core/http/quic_server_session_base.h b/quic/core/http/quic_server_session_base.h index 7495253..55a8d60 100644 --- a/quic/core/http/quic_server_session_base.h +++ b/quic/core/http/quic_server_session_base.h
@@ -126,7 +126,7 @@ QuicTime last_scup_time_; // Number of packets sent to the peer, at the time we last sent a SCUP. - int64_t last_scup_packet_number_; + QuicPacketNumber last_scup_packet_number_; // Converts QuicBandwidth to an int32 bytes/second that can be // stored in CachedNetworkParameters. TODO(jokulik): This function
diff --git a/quic/core/http/quic_server_session_base_test.cc b/quic/core/http/quic_server_session_base_test.cc index 6a8fb37..9f36e37 100644 --- a/quic/core/http/quic_server_session_base_test.cc +++ b/quic/core/http/quic_server_session_base_test.cc
@@ -170,6 +170,28 @@ return connection_->transport_version(); } + // 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. This method can be used to inject a STOP_SENDING, which + // would cause a close in the opposite direction. This allows tests to do the + // extra work to get a two-way (full) close where desired. Also sets up + // expects needed to ensure that the STOP_SENDING worked as expected. + void InjectStopSendingFrame(QuicStreamId stream_id, + QuicRstStreamErrorCode rst_stream_code) { + if (transport_version() != QUIC_VERSION_99) { + // Only needed for version 99/IETF QUIC. Noop otherwise. + return; + } + QuicStopSendingFrame stop_sending( + kInvalidControlFrameId, stream_id, + static_cast<QuicApplicationErrorCode>(rst_stream_code)); + EXPECT_CALL(owner_, OnStopSendingReceived(_)).Times(1); + // Expect the RESET_STREAM that is generated in response to receiving a + // STOP_SENDING. + EXPECT_CALL(*connection_, OnStreamReset(stream_id, rst_stream_code)); + session_->OnStopSendingFrame(stop_sending); + } + StrictMock<MockQuicSessionVisitor> owner_; StrictMock<MockQuicCryptoServerStreamHelper> stream_helper_; MockQuicConnectionHelper helper_; @@ -221,6 +243,12 @@ OnStreamReset(GetNthClientInitiatedBidirectionalId(0), QUIC_RST_ACKNOWLEDGEMENT)); visitor_->OnRstStream(rst1); + + // For version-99 will create and receive a stop-sending, completing + // the full-close expected by this test. + InjectStopSendingFrame(GetNthClientInitiatedBidirectionalId(0), + QUIC_ERROR_PROCESSING_STREAM); + EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams()); // Send the same two bytes of payload in a new packet. @@ -242,6 +270,12 @@ OnStreamReset(GetNthClientInitiatedBidirectionalId(0), QUIC_RST_ACKNOWLEDGEMENT)); visitor_->OnRstStream(rst1); + + // For version-99 will create and receive a stop-sending, completing + // the full-close expected by this test. + InjectStopSendingFrame(GetNthClientInitiatedBidirectionalId(0), + QUIC_ERROR_PROCESSING_STREAM); + EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams()); // Send two bytes of payload. @@ -275,6 +309,11 @@ QUIC_RST_ACKNOWLEDGEMENT)); visitor_->OnRstStream(rst); + // For version-99 will create and receive a stop-sending, completing + // the full-close expected by this test. + InjectStopSendingFrame(GetNthClientInitiatedBidirectionalId(0), + QUIC_ERROR_PROCESSING_STREAM); + // If we were tracking, we'd probably want to reject this because it's data // past the reset point of stream 3. As it's a closed stream we just drop the // data on the floor, but accept the packet because it has data for stream 5. @@ -499,10 +538,11 @@ // Bandwidth estimate has now changed sufficiently, enough time has passed, // and enough packets have been sent. - SerializedPacket packet(1 + kMinPacketsBetweenServerConfigUpdates, - PACKET_4BYTE_PACKET_NUMBER, nullptr, 1000, false, - false); - sent_packet_manager->OnPacketSent(&packet, 0, now, NOT_RETRANSMISSION, + SerializedPacket packet( + QuicPacketNumber(1) + kMinPacketsBetweenServerConfigUpdates, + PACKET_4BYTE_PACKET_NUMBER, nullptr, 1000, false, false); + sent_packet_manager->OnPacketSent(&packet, QuicPacketNumber(), now, + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA); // Verify that the proto has exactly the values we expect. @@ -655,7 +695,7 @@ EXPECT_CALL(stream_helper_, CanAcceptClientHello(_, _, _, _, _)) .WillOnce(testing::Return(true)); - EXPECT_CALL(stream_helper_, GenerateConnectionIdForReject(_)) + EXPECT_CALL(stream_helper_, GenerateConnectionIdForReject(_, _)) .WillOnce(testing::Return(TestConnectionId(12345))); // Set the current packet
diff --git a/quic/core/http/quic_spdy_client_session_test.cc b/quic/core/http/quic_spdy_client_session_test.cc index 579870a..a9d6c62 100644 --- a/quic/core/http/quic_spdy_client_session_test.cc +++ b/quic/core/http/quic_spdy_client_session_test.cc
@@ -454,7 +454,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_99) { + if (connection_->transport_version() > QUIC_VERSION_46) { // Illegal fixed bit value. EXPECT_CALL(*connection_, OnError(_)).Times(1); }
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 ab13943..51abf0c 100644 --- a/quic/core/http/quic_spdy_server_stream_base_test.cc +++ b/quic/core/http/quic_spdy_server_stream_base_test.cc
@@ -62,6 +62,14 @@ QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream_->id(), QUIC_STREAM_CANCELLED, 1234); stream_->OnStreamReset(rst_frame); + if (session_.connection()->transport_version() == QUIC_VERSION_99) { + // Create and inject a STOP SENDING frame to complete the close + // of the stream. This is only needed for version 99/IETF QUIC. + QuicStopSendingFrame stop_sending( + kInvalidControlFrameId, stream_->id(), + static_cast<QuicApplicationErrorCode>(QUIC_STREAM_CANCELLED)); + session_.OnStopSendingFrame(stop_sending); + } EXPECT_TRUE(stream_->reading_stopped()); EXPECT_TRUE(stream_->write_side_closed());
diff --git a/quic/core/http/quic_spdy_session_test.cc b/quic/core/http/quic_spdy_session_test.cc index 00fb10f..affa07a 100644 --- a/quic/core/http/quic_spdy_session_test.cc +++ b/quic/core/http/quic_spdy_session_test.cc
@@ -1001,6 +1001,23 @@ GetNthClientInitiatedBidirectionalId(0), QUIC_ERROR_PROCESSING_STREAM, 0); session_.OnRstStream(rst1); + + // 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) { + // Only needed for version 99/IETF QUIC. + QuicStopSendingFrame stop_sending( + kInvalidControlFrameId, GetNthClientInitiatedBidirectionalId(0), + static_cast<QuicApplicationErrorCode>(QUIC_ERROR_PROCESSING_STREAM)); + // Expect the RESET_STREAM that is generated in response to receiving a + // STOP_SENDING. + EXPECT_CALL(*connection_, + OnStreamReset(GetNthClientInitiatedBidirectionalId(0), + QUIC_ERROR_PROCESSING_STREAM)); + session_.OnStopSendingFrame(stop_sending); + } + EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams()); // Connection should remain alive. EXPECT_TRUE(connection_->connected()); @@ -1219,15 +1236,31 @@ .Times(2) .WillRepeatedly(Invoke(&session_, &TestSession::ClearControlFrame)); } else { - // V99 has an additional, STOP_SENDING, frame. + // V99 has an additional, STOP_SENDING, frame and an additional RST_STREAM + // (the response to the STOP_SENDING) frame. EXPECT_CALL(*connection_, SendControlFrame(_)) - .Times(3) + .Times(4) .WillRepeatedly(Invoke(&session_, &TestSession::ClearControlFrame)); } 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) { + // Only needed for version 99/IETF QUIC. + QuicStopSendingFrame stop_sending( + kInvalidControlFrameId, stream->id(), + static_cast<QuicApplicationErrorCode>(QUIC_STREAM_CANCELLED)); + // Expect the RESET_STREAM that is generated in response to receiving a + // STOP_SENDING. + EXPECT_CALL(*connection_, + OnStreamReset(stream->id(), QUIC_STREAM_CANCELLED)); + session_.OnStopSendingFrame(stop_sending); + } + EXPECT_EQ(kByteOffset, session_.flow_controller()->bytes_consumed()); }
diff --git a/quic/core/http/quic_spdy_stream.cc b/quic/core/http/quic_spdy_stream.cc index 9a5d024..eb8135a 100644 --- a/quic/core/http/quic_spdy_stream.cc +++ b/quic/core/http/quic_spdy_stream.cc
@@ -59,6 +59,10 @@ CloseConnectionOnWrongFrame("Settings"); } + void OnDuplicatePushFrame(const DuplicatePushFrame& frame) override { + CloseConnectionOnWrongFrame("Duplicate Push"); + } + void OnDataFrameStart(Http3FrameLengths frame_lengths) override { stream_->OnDataFrameStart(frame_lengths); } @@ -176,19 +180,23 @@ QuicStringPiece data, bool fin, QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) { - if (spdy_session_->connection()->transport_version() == QUIC_VERSION_99 && - data.length() > 0) { - std::unique_ptr<char[]> buffer; - QuicByteCount header_length = - encoder_.SerializeDataFrameHeader(data.length(), &buffer); - WriteOrBufferData(QuicStringPiece(buffer.get(), header_length), false, - nullptr); - QUIC_DLOG(INFO) << "Stream " << id() << " is writing header of length " - << header_length; - total_header_bytes_written_ += header_length; + if (spdy_session_->connection()->transport_version() != QUIC_VERSION_99 || + data.length() == 0) { + WriteOrBufferData(data, fin, std::move(ack_listener)); + return; } + QuicConnection::ScopedPacketFlusher flusher( + spdy_session_->connection(), QuicConnection::SEND_ACK_IF_PENDING); + std::unique_ptr<char[]> buffer; + QuicByteCount header_length = + encoder_.SerializeDataFrameHeader(data.length(), &buffer); + WriteOrBufferData(QuicStringPiece(buffer.get(), header_length), false, + nullptr); + 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)); - QUIC_DLOG(INFO) << "Stream" << id() << " is writing body of length " + QUIC_DLOG(INFO) << "Stream " << id() << " is writing body of length " << data.length(); } @@ -254,6 +262,8 @@ return {0, false}; } + QuicConnection::ScopedPacketFlusher flusher( + spdy_session_->connection(), QuicConnection::SEND_ACK_IF_PENDING); struct iovec header_iov = {static_cast<void*>(buffer.get()), header_length}; QuicMemSliceStorage storage( &header_iov, 1,
diff --git a/quic/core/http/quic_spdy_stream_body_buffer.h b/quic/core/http/quic_spdy_stream_body_buffer.h index acd4985..2485aac 100644 --- a/quic/core/http/quic_spdy_stream_body_buffer.h +++ b/quic/core/http/quic_spdy_stream_body_buffer.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef QUICHE_QUIC_CORE_HTTP_QUIC_SPDY_STREAM_BODY_BUFFER_H -#define QUICHE_QUIC_CORE_HTTP_QUIC_SPDY_STREAM_BODY_BUFFER_H +#ifndef QUICHE_QUIC_CORE_HTTP_QUIC_SPDY_STREAM_BODY_BUFFER_H_ +#define QUICHE_QUIC_CORE_HTTP_QUIC_SPDY_STREAM_BODY_BUFFER_H_ #include "net/third_party/quiche/src/quic/core/http/http_decoder.h" #include "net/third_party/quiche/src/quic/core/quic_stream_sequencer.h" @@ -72,4 +72,4 @@ } // namespace quic -#endif // QUICHE_QUIC_CORE_HTTP_QUIC_SPDY_STREAM_BODY_BUFFER_H +#endif // QUICHE_QUIC_CORE_HTTP_QUIC_SPDY_STREAM_BODY_BUFFER_H_
diff --git a/quic/core/http/spdy_utils_test.cc b/quic/core/http/spdy_utils_test.cc index b8edf49..6cd2f1d 100644 --- a/quic/core/http/spdy_utils_test.cc +++ b/quic/core/http/spdy_utils_test.cc
@@ -327,6 +327,24 @@ EXPECT_EQ(SpdyUtils::GetPromisedUrlFromHeaders(headers), ""); } +TEST_F(GetPromisedUrlFromHeaders, InvalidUserinfo) { + SpdyHeaderBlock headers; + headers[":method"] = "GET"; + headers[":authority"] = "user@www.google.com"; + headers[":scheme"] = "https"; + headers[":path"] = "/"; + EXPECT_EQ(SpdyUtils::GetPromisedUrlFromHeaders(headers), ""); +} + +TEST_F(GetPromisedUrlFromHeaders, InvalidPath) { + SpdyHeaderBlock headers; + headers[":method"] = "GET"; + headers[":authority"] = "www.google.com"; + headers[":scheme"] = "https"; + headers[":path"] = ""; + EXPECT_EQ(SpdyUtils::GetPromisedUrlFromHeaders(headers), ""); +} + using GetPromisedHostNameFromHeaders = QuicTest; TEST_F(GetPromisedHostNameFromHeaders, NormalUsage) {
diff --git a/quic/core/legacy_quic_stream_id_manager.cc b/quic/core/legacy_quic_stream_id_manager.cc index 000d0cb..6fb662a 100644 --- a/quic/core/legacy_quic_stream_id_manager.cc +++ b/quic/core/legacy_quic_stream_id_manager.cc
@@ -1,3 +1,6 @@ +// Copyright (c) 2018 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/legacy_quic_stream_id_manager.h" #include "net/third_party/quiche/src/quic/core/quic_session.h"
diff --git a/quic/core/legacy_quic_stream_id_manager.h b/quic/core/legacy_quic_stream_id_manager.h index 79a4d47..78d4545 100644 --- a/quic/core/legacy_quic_stream_id_manager.h +++ b/quic/core/legacy_quic_stream_id_manager.h
@@ -1,3 +1,6 @@ +// Copyright (c) 2018 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_LEGACY_QUIC_STREAM_ID_MANAGER_H_ #define QUICHE_QUIC_CORE_LEGACY_QUIC_STREAM_ID_MANAGER_H_
diff --git a/quic/core/legacy_quic_stream_id_manager_test.cc b/quic/core/legacy_quic_stream_id_manager_test.cc index 643ff5b..823cdc0 100644 --- a/quic/core/legacy_quic_stream_id_manager_test.cc +++ b/quic/core/legacy_quic_stream_id_manager_test.cc
@@ -1,3 +1,6 @@ +// Copyright (c) 2018 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/legacy_quic_stream_id_manager.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"
diff --git a/quic/core/packet_number_indexed_queue.h b/quic/core/packet_number_indexed_queue.h index 97d93de..ab2e20b 100644 --- a/quic/core/packet_number_indexed_queue.h +++ b/quic/core/packet_number_indexed_queue.h
@@ -5,8 +5,9 @@ #ifndef QUICHE_QUIC_CORE_PACKET_NUMBER_INDEXED_QUEUE_H_ #define QUICHE_QUIC_CORE_PACKET_NUMBER_INDEXED_QUEUE_H_ -#include "base/logging.h" +#include "net/third_party/quiche/src/quic/core/quic_constants.h" #include "net/third_party/quiche/src/quic/core/quic_types.h" +#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h" #include "net/third_party/quiche/src/quic/platform/api/quic_containers.h" namespace quic { @@ -35,8 +36,7 @@ template <typename T> class PacketNumberIndexedQueue { public: - PacketNumberIndexedQueue() - : number_of_present_entries_(0), first_packet_(0) {} + PacketNumberIndexedQueue() : number_of_present_entries_(0) {} // Retrieve the entry associated with the packet number. Returns the pointer // to the entry in case of success, or nullptr if the entry does not exist. @@ -65,15 +65,15 @@ // proportional to the memory usage of the queue. size_t entry_slots_used() const { return entries_.size(); } - // Packet number of the first entry in the queue. Zero if the queue is empty. - size_t first_packet() const { return first_packet_; } + // Packet number of the first entry in the queue. + QuicPacketNumber first_packet() const { return first_packet_; } // Packet number of the last entry ever inserted in the queue. Note that the // entry in question may have already been removed. Zero if the queue is // empty. - size_t last_packet() const { + QuicPacketNumber last_packet() const { if (IsEmpty()) { - return 0; + return QuicPacketNumber(); } return first_packet_ + entries_.size() - 1; } @@ -127,9 +127,14 @@ template <typename... Args> bool PacketNumberIndexedQueue<T>::Emplace(QuicPacketNumber packet_number, Args&&... args) { + if (!packet_number.IsInitialized()) { + QUIC_BUG << "Try to insert an uninitialized packet number"; + return false; + } + if (IsEmpty()) { DCHECK(entries_.empty()); - DCHECK_EQ(0u, first_packet_); + DCHECK(!first_packet_.IsInitialized()); entries_.emplace_back(std::forward<Args>(args)...); number_of_present_entries_ = 1; @@ -176,18 +181,19 @@ first_packet_++; } if (entries_.empty()) { - first_packet_ = 0; + first_packet_.Clear(); } } template <typename T> -auto PacketNumberIndexedQueue<T>::GetEntryWrapper(QuicPacketNumber offset) const - -> const EntryWrapper* { - if (offset < first_packet_) { +auto PacketNumberIndexedQueue<T>::GetEntryWrapper( + QuicPacketNumber packet_number) const -> const EntryWrapper* { + if (!packet_number.IsInitialized() || IsEmpty() || + packet_number < first_packet_) { return nullptr; } - offset -= first_packet_; + uint64_t offset = packet_number - first_packet_; if (offset >= entries_.size()) { return nullptr; }
diff --git a/quic/core/packet_number_indexed_queue_test.cc b/quic/core/packet_number_indexed_queue_test.cc index 0190df2..294d2a4 100644 --- a/quic/core/packet_number_indexed_queue_test.cc +++ b/quic/core/packet_number_indexed_queue_test.cc
@@ -23,156 +23,156 @@ TEST_F(PacketNumberIndexedQueueTest, InitialState) { EXPECT_TRUE(queue_.IsEmpty()); - EXPECT_EQ(0u, queue_.first_packet()); - EXPECT_EQ(0u, queue_.last_packet()); + EXPECT_FALSE(queue_.first_packet().IsInitialized()); + EXPECT_FALSE(queue_.last_packet().IsInitialized()); EXPECT_EQ(0u, queue_.number_of_present_entries()); EXPECT_EQ(0u, queue_.entry_slots_used()); } TEST_F(PacketNumberIndexedQueueTest, InsertingContinuousElements) { - ASSERT_TRUE(queue_.Emplace(1001, "one")); - EXPECT_EQ("one", *queue_.GetEntry(1001)); + ASSERT_TRUE(queue_.Emplace(QuicPacketNumber(1001), "one")); + EXPECT_EQ("one", *queue_.GetEntry(QuicPacketNumber(1001))); - ASSERT_TRUE(queue_.Emplace(1002, "two")); - EXPECT_EQ("two", *queue_.GetEntry(1002)); + ASSERT_TRUE(queue_.Emplace(QuicPacketNumber(1002), "two")); + EXPECT_EQ("two", *queue_.GetEntry(QuicPacketNumber(1002))); EXPECT_FALSE(queue_.IsEmpty()); - EXPECT_EQ(1001u, queue_.first_packet()); - EXPECT_EQ(1002u, queue_.last_packet()); + EXPECT_EQ(QuicPacketNumber(1001u), queue_.first_packet()); + EXPECT_EQ(QuicPacketNumber(1002u), queue_.last_packet()); EXPECT_EQ(2u, queue_.number_of_present_entries()); EXPECT_EQ(2u, queue_.entry_slots_used()); } TEST_F(PacketNumberIndexedQueueTest, InsertingOutOfOrder) { - queue_.Emplace(1001, "one"); + queue_.Emplace(QuicPacketNumber(1001), "one"); - ASSERT_TRUE(queue_.Emplace(1003, "three")); - EXPECT_EQ(nullptr, queue_.GetEntry(1002)); - EXPECT_EQ("three", *queue_.GetEntry(1003)); + ASSERT_TRUE(queue_.Emplace(QuicPacketNumber(1003), "three")); + EXPECT_EQ(nullptr, queue_.GetEntry(QuicPacketNumber(1002))); + EXPECT_EQ("three", *queue_.GetEntry(QuicPacketNumber(1003))); - EXPECT_EQ(1001u, queue_.first_packet()); - EXPECT_EQ(1003u, queue_.last_packet()); + EXPECT_EQ(QuicPacketNumber(1001u), queue_.first_packet()); + EXPECT_EQ(QuicPacketNumber(1003u), queue_.last_packet()); EXPECT_EQ(2u, queue_.number_of_present_entries()); EXPECT_EQ(3u, queue_.entry_slots_used()); - ASSERT_FALSE(queue_.Emplace(1002, "two")); + ASSERT_FALSE(queue_.Emplace(QuicPacketNumber(1002), "two")); } TEST_F(PacketNumberIndexedQueueTest, InsertingIntoPast) { - queue_.Emplace(1001, "one"); - EXPECT_FALSE(queue_.Emplace(1000, "zero")); + queue_.Emplace(QuicPacketNumber(1001), "one"); + EXPECT_FALSE(queue_.Emplace(QuicPacketNumber(1000), "zero")); } TEST_F(PacketNumberIndexedQueueTest, InsertingDuplicate) { - queue_.Emplace(1001, "one"); - EXPECT_FALSE(queue_.Emplace(1001, "one")); + queue_.Emplace(QuicPacketNumber(1001), "one"); + EXPECT_FALSE(queue_.Emplace(QuicPacketNumber(1001), "one")); } TEST_F(PacketNumberIndexedQueueTest, RemoveInTheMiddle) { - queue_.Emplace(1001, "one"); - queue_.Emplace(1002, "two"); - queue_.Emplace(1003, "three"); + queue_.Emplace(QuicPacketNumber(1001), "one"); + queue_.Emplace(QuicPacketNumber(1002), "two"); + queue_.Emplace(QuicPacketNumber(1003), "three"); - ASSERT_TRUE(queue_.Remove(1002)); - EXPECT_EQ(nullptr, queue_.GetEntry(1002)); + ASSERT_TRUE(queue_.Remove(QuicPacketNumber(1002))); + EXPECT_EQ(nullptr, queue_.GetEntry(QuicPacketNumber(1002))); - EXPECT_EQ(1001u, queue_.first_packet()); - EXPECT_EQ(1003u, queue_.last_packet()); + EXPECT_EQ(QuicPacketNumber(1001u), queue_.first_packet()); + EXPECT_EQ(QuicPacketNumber(1003u), queue_.last_packet()); EXPECT_EQ(2u, queue_.number_of_present_entries()); EXPECT_EQ(3u, queue_.entry_slots_used()); - EXPECT_FALSE(queue_.Emplace(1002, "two")); - EXPECT_TRUE(queue_.Emplace(1004, "four")); + EXPECT_FALSE(queue_.Emplace(QuicPacketNumber(1002), "two")); + EXPECT_TRUE(queue_.Emplace(QuicPacketNumber(1004), "four")); } TEST_F(PacketNumberIndexedQueueTest, RemoveAtImmediateEdges) { - queue_.Emplace(1001, "one"); - queue_.Emplace(1002, "two"); - queue_.Emplace(1003, "three"); - ASSERT_TRUE(queue_.Remove(1001)); - EXPECT_EQ(nullptr, queue_.GetEntry(1001)); - ASSERT_TRUE(queue_.Remove(1003)); - EXPECT_EQ(nullptr, queue_.GetEntry(1003)); + queue_.Emplace(QuicPacketNumber(1001), "one"); + queue_.Emplace(QuicPacketNumber(1002), "two"); + queue_.Emplace(QuicPacketNumber(1003), "three"); + ASSERT_TRUE(queue_.Remove(QuicPacketNumber(1001))); + EXPECT_EQ(nullptr, queue_.GetEntry(QuicPacketNumber(1001))); + ASSERT_TRUE(queue_.Remove(QuicPacketNumber(1003))); + EXPECT_EQ(nullptr, queue_.GetEntry(QuicPacketNumber(1003))); - EXPECT_EQ(1002u, queue_.first_packet()); - EXPECT_EQ(1003u, queue_.last_packet()); + EXPECT_EQ(QuicPacketNumber(1002u), queue_.first_packet()); + EXPECT_EQ(QuicPacketNumber(1003u), queue_.last_packet()); EXPECT_EQ(1u, queue_.number_of_present_entries()); EXPECT_EQ(2u, queue_.entry_slots_used()); - EXPECT_TRUE(queue_.Emplace(1004, "four")); + EXPECT_TRUE(queue_.Emplace(QuicPacketNumber(1004), "four")); } TEST_F(PacketNumberIndexedQueueTest, RemoveAtDistantFront) { - queue_.Emplace(1001, "one"); - queue_.Emplace(1002, "one (kinda)"); - queue_.Emplace(2001, "two"); + queue_.Emplace(QuicPacketNumber(1001), "one"); + queue_.Emplace(QuicPacketNumber(1002), "one (kinda)"); + queue_.Emplace(QuicPacketNumber(2001), "two"); - EXPECT_EQ(1001u, queue_.first_packet()); - EXPECT_EQ(2001u, queue_.last_packet()); + EXPECT_EQ(QuicPacketNumber(1001u), queue_.first_packet()); + EXPECT_EQ(QuicPacketNumber(2001u), queue_.last_packet()); EXPECT_EQ(3u, queue_.number_of_present_entries()); EXPECT_EQ(1001u, queue_.entry_slots_used()); - ASSERT_TRUE(queue_.Remove(1002)); - EXPECT_EQ(1001u, queue_.first_packet()); - EXPECT_EQ(2001u, queue_.last_packet()); + ASSERT_TRUE(queue_.Remove(QuicPacketNumber(1002))); + EXPECT_EQ(QuicPacketNumber(1001u), queue_.first_packet()); + EXPECT_EQ(QuicPacketNumber(2001u), queue_.last_packet()); EXPECT_EQ(2u, queue_.number_of_present_entries()); EXPECT_EQ(1001u, queue_.entry_slots_used()); - ASSERT_TRUE(queue_.Remove(1001)); - EXPECT_EQ(2001u, queue_.first_packet()); - EXPECT_EQ(2001u, queue_.last_packet()); + ASSERT_TRUE(queue_.Remove(QuicPacketNumber(1001))); + EXPECT_EQ(QuicPacketNumber(2001u), queue_.first_packet()); + EXPECT_EQ(QuicPacketNumber(2001u), queue_.last_packet()); EXPECT_EQ(1u, queue_.number_of_present_entries()); EXPECT_EQ(1u, queue_.entry_slots_used()); } TEST_F(PacketNumberIndexedQueueTest, RemoveAtDistantBack) { - queue_.Emplace(1001, "one"); - queue_.Emplace(2001, "two"); + queue_.Emplace(QuicPacketNumber(1001), "one"); + queue_.Emplace(QuicPacketNumber(2001), "two"); - EXPECT_EQ(1001u, queue_.first_packet()); - EXPECT_EQ(2001u, queue_.last_packet()); + EXPECT_EQ(QuicPacketNumber(1001u), queue_.first_packet()); + EXPECT_EQ(QuicPacketNumber(2001u), queue_.last_packet()); - ASSERT_TRUE(queue_.Remove(2001)); - EXPECT_EQ(1001u, queue_.first_packet()); - EXPECT_EQ(2001u, queue_.last_packet()); + ASSERT_TRUE(queue_.Remove(QuicPacketNumber(2001))); + EXPECT_EQ(QuicPacketNumber(1001u), queue_.first_packet()); + EXPECT_EQ(QuicPacketNumber(2001u), queue_.last_packet()); } TEST_F(PacketNumberIndexedQueueTest, ClearAndRepopulate) { - queue_.Emplace(1001, "one"); - queue_.Emplace(2001, "two"); + queue_.Emplace(QuicPacketNumber(1001), "one"); + queue_.Emplace(QuicPacketNumber(2001), "two"); - ASSERT_TRUE(queue_.Remove(1001)); - ASSERT_TRUE(queue_.Remove(2001)); + ASSERT_TRUE(queue_.Remove(QuicPacketNumber(1001))); + ASSERT_TRUE(queue_.Remove(QuicPacketNumber(2001))); EXPECT_TRUE(queue_.IsEmpty()); - EXPECT_EQ(0u, queue_.first_packet()); - EXPECT_EQ(0u, queue_.last_packet()); + EXPECT_FALSE(queue_.first_packet().IsInitialized()); + EXPECT_FALSE(queue_.last_packet().IsInitialized()); - EXPECT_TRUE(queue_.Emplace(101, "one")); - EXPECT_TRUE(queue_.Emplace(201, "two")); - EXPECT_EQ(101u, queue_.first_packet()); - EXPECT_EQ(201u, queue_.last_packet()); + EXPECT_TRUE(queue_.Emplace(QuicPacketNumber(101), "one")); + EXPECT_TRUE(queue_.Emplace(QuicPacketNumber(201), "two")); + EXPECT_EQ(QuicPacketNumber(101u), queue_.first_packet()); + EXPECT_EQ(QuicPacketNumber(201u), queue_.last_packet()); } TEST_F(PacketNumberIndexedQueueTest, FailToRemoveElementsThatNeverExisted) { - ASSERT_FALSE(queue_.Remove(1000)); - queue_.Emplace(1001, "one"); - ASSERT_FALSE(queue_.Remove(1000)); - ASSERT_FALSE(queue_.Remove(1002)); + ASSERT_FALSE(queue_.Remove(QuicPacketNumber(1000))); + queue_.Emplace(QuicPacketNumber(1001), "one"); + ASSERT_FALSE(queue_.Remove(QuicPacketNumber(1000))); + ASSERT_FALSE(queue_.Remove(QuicPacketNumber(1002))); } TEST_F(PacketNumberIndexedQueueTest, FailToRemoveElementsTwice) { - queue_.Emplace(1001, "one"); - ASSERT_TRUE(queue_.Remove(1001)); - ASSERT_FALSE(queue_.Remove(1001)); - ASSERT_FALSE(queue_.Remove(1001)); + queue_.Emplace(QuicPacketNumber(1001), "one"); + ASSERT_TRUE(queue_.Remove(QuicPacketNumber(1001))); + ASSERT_FALSE(queue_.Remove(QuicPacketNumber(1001))); + ASSERT_FALSE(queue_.Remove(QuicPacketNumber(1001))); } TEST_F(PacketNumberIndexedQueueTest, ConstGetter) { - queue_.Emplace(1001, "one"); + queue_.Emplace(QuicPacketNumber(1001), "one"); const auto& const_queue = queue_; - EXPECT_EQ("one", *const_queue.GetEntry(1001)); - EXPECT_EQ(nullptr, const_queue.GetEntry(1002)); + EXPECT_EQ("one", *const_queue.GetEntry(QuicPacketNumber(1001))); + EXPECT_EQ(nullptr, const_queue.GetEntry(QuicPacketNumber(1002))); } } // namespace
diff --git a/quic/core/qpack/fuzzer/qpack_encoder_stream_receiver_fuzzer.cc b/quic/core/qpack/fuzzer/qpack_encoder_stream_receiver_fuzzer.cc index e61c973..980889d 100644 --- a/quic/core/qpack/fuzzer/qpack_encoder_stream_receiver_fuzzer.cc +++ b/quic/core/qpack/fuzzer/qpack_encoder_stream_receiver_fuzzer.cc
@@ -28,7 +28,7 @@ void OnInsertWithoutNameReference(QuicStringPiece name, QuicStringPiece value) override {} void OnDuplicate(uint64_t index) override {} - void OnDynamicTableSizeUpdate(uint64_t max_size) override {} + void OnSetDynamicTableCapacity(uint64_t capacity) override {} void OnErrorDetected(QuicStringPiece error_message) override { error_detected_ = true; }
diff --git a/quic/core/qpack/fuzzer/qpack_encoder_stream_sender_fuzzer.cc b/quic/core/qpack/fuzzer/qpack_encoder_stream_sender_fuzzer.cc index f404a76..501a69f 100644 --- a/quic/core/qpack/fuzzer/qpack_encoder_stream_sender_fuzzer.cc +++ b/quic/core/qpack/fuzzer/qpack_encoder_stream_sender_fuzzer.cc
@@ -8,6 +8,7 @@ #include <cstdint> #include <limits> +#include "net/third_party/quiche/src/quic/core/qpack/qpack_encoder_test_utils.h" #include "net/third_party/quiche/src/quic/platform/api/quic_fuzzed_data_provider.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" @@ -15,22 +16,12 @@ namespace quic { namespace test { -// A QpackEncoderStreamSender::Delegate implementation that ignores encoded -// data. -class NoOpDelegate : public QpackEncoderStreamSender::Delegate { - public: - NoOpDelegate() = default; - ~NoOpDelegate() override = default; - - void Write(QuicStringPiece data) override {} -}; - // This fuzzer exercises QpackEncoderStreamSender. // TODO(bnc): Encoded data could be fed into QpackEncoderStreamReceiver and // decoded instructions directly compared to input. Figure out how to get gMock // enabled for cc_fuzz_target target types. extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - NoOpDelegate delegate; + NoopEncoderStreamSenderDelegate delegate; QpackEncoderStreamSender sender(&delegate); QuicFuzzedDataProvider provider(data, size); @@ -65,8 +56,8 @@ break; } case 3: { - uint64_t max_size = provider.ConsumeIntegral<uint64_t>(); - sender.SendDynamicTableSizeUpdate(max_size); + uint64_t capacity = provider.ConsumeIntegral<uint64_t>(); + sender.SendSetDynamicTableCapacity(capacity); break; } }
diff --git a/quic/core/qpack/offline/qpack_offline_decoder.cc b/quic/core/qpack/offline/qpack_offline_decoder.cc index c3ad1f9..2b02edd 100644 --- a/quic/core/qpack/offline/qpack_offline_decoder.cc +++ b/quic/core/qpack/offline/qpack_offline_decoder.cc
@@ -44,7 +44,7 @@ return true; } -void QpackOfflineDecoder::OnError(QuicStringPiece error_message) { +void QpackOfflineDecoder::OnEncoderStreamError(QuicStringPiece error_message) { QUIC_LOG(ERROR) << "Encoder stream error: " << error_message; encoder_stream_error_detected_ = true; }
diff --git a/quic/core/qpack/offline/qpack_offline_decoder.h b/quic/core/qpack/offline/qpack_offline_decoder.h index faa64bc..922fd64 100644 --- a/quic/core/qpack/offline/qpack_offline_decoder.h +++ b/quic/core/qpack/offline/qpack_offline_decoder.h
@@ -5,6 +5,8 @@ #ifndef QUICHE_QUIC_CORE_QPACK_OFFLINE_QPACK_OFFLINE_DECODER_H_ #define QUICHE_QUIC_CORE_QPACK_OFFLINE_QPACK_OFFLINE_DECODER_H_ +#include <list> + #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_string_piece.h" @@ -30,7 +32,7 @@ QuicStringPiece expected_headers_filename); // QpackDecoder::EncoderStreamErrorDelegate implementation: - void OnError(QuicStringPiece error_message) override; + void OnEncoderStreamError(QuicStringPiece error_message) override; private: // Parse decoder parameters from |input_filename| and set up |decoder_|
diff --git a/quic/core/qpack/offline/qpack_offline_decoder_bin.cc b/quic/core/qpack/offline/qpack_offline_decoder_bin.cc index 2068f52..499c9fd 100644 --- a/quic/core/qpack/offline/qpack_offline_decoder_bin.cc +++ b/quic/core/qpack/offline/qpack_offline_decoder_bin.cc
@@ -20,7 +20,7 @@ return 1; } - size_t i; + 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]);
diff --git a/quic/core/qpack/qpack_constants.cc b/quic/core/qpack/qpack_constants.cc index eda1ef4..b9144e0 100644 --- a/quic/core/qpack/qpack_constants.cc +++ b/quic/core/qpack/qpack_constants.cc
@@ -4,7 +4,6 @@ #include "net/third_party/quiche/src/quic/core/qpack/qpack_constants.h" -#include <cstddef> #include <limits> #include "base/logging.h" @@ -17,8 +16,9 @@ // * in each instruction, the bits of |value| that are zero in |mask| are zero; // * every byte matches exactly one opcode. void ValidateLangague(const QpackLanguage* language) { +#ifndef NDEBUG for (const auto* instruction : *language) { - DCHECK_EQ(0u, instruction->opcode.value & ~instruction->opcode.mask); + DCHECK_EQ(0, instruction->opcode.value & ~instruction->opcode.mask); } for (uint8_t byte = 0; byte < std::numeric_limits<uint8_t>::max(); ++byte) { @@ -30,6 +30,7 @@ } DCHECK_EQ(1u, match_count) << static_cast<int>(byte); } +#endif } } // namespace @@ -68,7 +69,7 @@ return instruction; } -const QpackInstruction* DynamicTableSizeUpdateInstruction() { +const QpackInstruction* SetDynamicTableCapacityInstruction() { static const QpackInstructionOpcode* const opcode = new QpackInstructionOpcode{0b00100000, 0b11100000}; static const QpackInstruction* const instruction = @@ -80,14 +81,12 @@ static const QpackLanguage* const language = new QpackLanguage{ InsertWithNameReferenceInstruction(), InsertWithoutNameReferenceInstruction(), DuplicateInstruction(), - DynamicTableSizeUpdateInstruction()}; -#ifndef NDEBUG + SetDynamicTableCapacityInstruction()}; ValidateLangague(language); -#endif return language; } -const QpackInstruction* TableStateSynchronizeInstruction() { +const QpackInstruction* InsertCountIncrementInstruction() { static const QpackInstructionOpcode* const opcode = new QpackInstructionOpcode{0b00000000, 0b11000000}; static const QpackInstruction* const instruction = @@ -113,11 +112,9 @@ const QpackLanguage* QpackDecoderStreamLanguage() { static const QpackLanguage* const language = new QpackLanguage{ - TableStateSynchronizeInstruction(), HeaderAcknowledgementInstruction(), + InsertCountIncrementInstruction(), HeaderAcknowledgementInstruction(), StreamCancellationInstruction()}; -#ifndef NDEBUG ValidateLangague(language); -#endif return language; } @@ -136,9 +133,7 @@ const QpackLanguage* QpackPrefixLanguage() { static const QpackLanguage* const language = new QpackLanguage{QpackPrefixInstruction()}; -#ifndef NDEBUG ValidateLangague(language); -#endif return language; } @@ -198,9 +193,7 @@ QpackLiteralHeaderFieldNameReferenceInstruction(), QpackLiteralHeaderFieldPostBaseInstruction(), QpackLiteralHeaderFieldInstruction()}; -#ifndef NDEBUG ValidateLangague(language); -#endif return language; }
diff --git a/quic/core/qpack/qpack_constants.h b/quic/core/qpack/qpack_constants.h index 4fce3dd..7b7eb47 100644 --- a/quic/core/qpack/qpack_constants.h +++ b/quic/core/qpack/qpack_constants.h
@@ -30,14 +30,14 @@ // literal consumes all bytes containing the field value. enum class QpackInstructionFieldType { // A single bit indicating whether the index refers to the static table, or - // indicating the sign of Delta Base Index. Called "S" bit because both - // "static" and "sign" start with the letter "S". + // indicating the sign of Delta Base. Called "S" bit because both "static" + // and "sign" start with the letter "S". kSbit, // An integer encoded with variable length encoding. This could be an index, - // stream ID, maximum size, or Largest Reference. + // stream ID, maximum size, or Encoded Required Insert Count. kVarint, // A second integer encoded with variable length encoding. This could be - // Delta Base Index. + // Delta Base. kVarint2, // A header name or header value encoded as: // a bit indicating whether it is Huffman encoded; @@ -97,15 +97,15 @@ const QpackInstruction* DuplicateInstruction(); // 5.2.4 Dynamic Table Size Update -const QpackInstruction* DynamicTableSizeUpdateInstruction(); +const QpackInstruction* SetDynamicTableCapacityInstruction(); // Encoder stream language. const QpackLanguage* QpackEncoderStreamLanguage(); // 5.3 Decoder stream instructions -// 5.3.1 Table State Synchronize -const QpackInstruction* TableStateSynchronizeInstruction(); +// 5.3.1 Insert Count Increment +const QpackInstruction* InsertCountIncrementInstruction(); // 5.3.2 Header Acknowledgement const QpackInstruction* HeaderAcknowledgementInstruction();
diff --git a/quic/core/qpack/qpack_decoder.cc b/quic/core/qpack/qpack_decoder.cc index 9ae883f..fd0867a 100644 --- a/quic/core/qpack/qpack_decoder.cc +++ b/quic/core/qpack/qpack_decoder.cc
@@ -4,6 +4,8 @@ #include "net/third_party/quiche/src/quic/core/qpack/qpack_decoder.h" +#include <limits> + #include "base/logging.h" #include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h" @@ -40,33 +42,36 @@ if (is_static) { auto entry = header_table_.LookupEntry(/* is_static = */ true, name_index); if (!entry) { - encoder_stream_error_delegate_->OnError("Invalid static table entry."); + encoder_stream_error_delegate_->OnEncoderStreamError( + "Invalid static table entry."); return; } entry = header_table_.InsertEntry(entry->name(), value); if (!entry) { - encoder_stream_error_delegate_->OnError( + encoder_stream_error_delegate_->OnEncoderStreamError( "Error inserting entry with name reference."); } return; } - uint64_t real_index; - if (!EncoderStreamRelativeIndexToRealIndex(name_index, &real_index)) { - encoder_stream_error_delegate_->OnError("Invalid relative index."); + uint64_t absolute_index; + if (!EncoderStreamRelativeIndexToAbsoluteIndex(name_index, &absolute_index)) { + encoder_stream_error_delegate_->OnEncoderStreamError( + "Invalid relative index."); return; } const QpackEntry* entry = - header_table_.LookupEntry(/* is_static = */ false, real_index); + header_table_.LookupEntry(/* is_static = */ false, absolute_index); if (!entry) { - encoder_stream_error_delegate_->OnError("Dynamic table entry not found."); + encoder_stream_error_delegate_->OnEncoderStreamError( + "Dynamic table entry not found."); return; } entry = header_table_.InsertEntry(entry->name(), value); if (!entry) { - encoder_stream_error_delegate_->OnError( + encoder_stream_error_delegate_->OnEncoderStreamError( "Error inserting entry with name reference."); } } @@ -75,50 +80,54 @@ QuicStringPiece value) { const QpackEntry* entry = header_table_.InsertEntry(name, value); if (!entry) { - encoder_stream_error_delegate_->OnError("Error inserting literal entry."); + encoder_stream_error_delegate_->OnEncoderStreamError( + "Error inserting literal entry."); } } void QpackDecoder::OnDuplicate(uint64_t index) { - uint64_t real_index; - if (!EncoderStreamRelativeIndexToRealIndex(index, &real_index)) { - encoder_stream_error_delegate_->OnError("Invalid relative index."); + uint64_t absolute_index; + if (!EncoderStreamRelativeIndexToAbsoluteIndex(index, &absolute_index)) { + encoder_stream_error_delegate_->OnEncoderStreamError( + "Invalid relative index."); return; } const QpackEntry* entry = - header_table_.LookupEntry(/* is_static = */ false, real_index); + header_table_.LookupEntry(/* is_static = */ false, absolute_index); if (!entry) { - encoder_stream_error_delegate_->OnError("Dynamic table entry not found."); + encoder_stream_error_delegate_->OnEncoderStreamError( + "Dynamic table entry not found."); return; } entry = header_table_.InsertEntry(entry->name(), entry->value()); if (!entry) { - encoder_stream_error_delegate_->OnError("Error inserting duplicate entry."); + encoder_stream_error_delegate_->OnEncoderStreamError( + "Error inserting duplicate entry."); } } -void QpackDecoder::OnDynamicTableSizeUpdate(uint64_t max_size) { - if (!header_table_.UpdateTableSize(max_size)) { - encoder_stream_error_delegate_->OnError( - "Error updating dynamic table size."); +void QpackDecoder::OnSetDynamicTableCapacity(uint64_t capacity) { + if (!header_table_.SetDynamicTableCapacity(capacity)) { + encoder_stream_error_delegate_->OnEncoderStreamError( + "Error updating dynamic table capacity."); } } void QpackDecoder::OnErrorDetected(QuicStringPiece error_message) { - encoder_stream_error_delegate_->OnError(error_message); + encoder_stream_error_delegate_->OnEncoderStreamError(error_message); } -bool QpackDecoder::EncoderStreamRelativeIndexToRealIndex( +bool QpackDecoder::EncoderStreamRelativeIndexToAbsoluteIndex( uint64_t relative_index, - uint64_t* real_index) const { + uint64_t* absolute_index) const { if (relative_index == std::numeric_limits<uint64_t>::max() || relative_index + 1 > std::numeric_limits<uint64_t>::max() - header_table_.inserted_entry_count()) { return false; } - *real_index = header_table_.inserted_entry_count() - relative_index - 1; + *absolute_index = header_table_.inserted_entry_count() - relative_index - 1; return true; }
diff --git a/quic/core/qpack/qpack_decoder.h b/quic/core/qpack/qpack_decoder.h index ffb2e88..c3b28a3 100644 --- a/quic/core/qpack/qpack_decoder.h +++ b/quic/core/qpack/qpack_decoder.h
@@ -31,7 +31,7 @@ public: virtual ~EncoderStreamErrorDelegate() {} - virtual void OnError(QuicStringPiece error_message) = 0; + virtual void OnEncoderStreamError(QuicStringPiece error_message) = 0; }; QpackDecoder( @@ -79,18 +79,17 @@ void OnInsertWithoutNameReference(QuicStringPiece name, QuicStringPiece value) override; void OnDuplicate(uint64_t index) override; - void OnDynamicTableSizeUpdate(uint64_t max_size) override; + void OnSetDynamicTableCapacity(uint64_t capacity) override; void OnErrorDetected(QuicStringPiece error_message) override; private: // The encoder stream uses relative index (but different from the kind of - // relative index used on a request stream). - // The spec describes how to convert these into absolute index (one based). - // QpackHeaderTable uses real index (zero based, one less than the absolute - // index). This method converts relative index to real index. It returns - // true on success, or false if conversion fails due to overflow/underflow. - bool EncoderStreamRelativeIndexToRealIndex(uint64_t relative_index, - uint64_t* real_index) const; + // relative index used on a request stream). This method converts relative + // index to absolute index (zero based). It returns true on success, or false + // if conversion fails due to overflow/underflow. + bool EncoderStreamRelativeIndexToAbsoluteIndex( + uint64_t relative_index, + uint64_t* absolute_index) const; EncoderStreamErrorDelegate* const encoder_stream_error_delegate_; QpackEncoderStreamReceiver encoder_stream_receiver_;
diff --git a/quic/core/qpack/qpack_decoder_stream_receiver.cc b/quic/core/qpack/qpack_decoder_stream_receiver.cc index b38aedf..559ce43 100644 --- a/quic/core/qpack/qpack_decoder_stream_receiver.cc +++ b/quic/core/qpack/qpack_decoder_stream_receiver.cc
@@ -27,8 +27,8 @@ bool QpackDecoderStreamReceiver::OnInstructionDecoded( const QpackInstruction* instruction) { - if (instruction == TableStateSynchronizeInstruction()) { - delegate_->OnTableStateSynchronize(instruction_decoder_.varint()); + if (instruction == InsertCountIncrementInstruction()) { + delegate_->OnInsertCountIncrement(instruction_decoder_.varint()); return true; }
diff --git a/quic/core/qpack/qpack_decoder_stream_receiver.h b/quic/core/qpack/qpack_decoder_stream_receiver.h index 003be12..61c2773 100644 --- a/quic/core/qpack/qpack_decoder_stream_receiver.h +++ b/quic/core/qpack/qpack_decoder_stream_receiver.h
@@ -25,8 +25,8 @@ public: virtual ~Delegate() = default; - // 5.3.1 Table State Synchronize - virtual void OnTableStateSynchronize(uint64_t insert_count) = 0; + // 5.3.1 Insert Count Increment + virtual void OnInsertCountIncrement(uint64_t increment) = 0; // 5.3.2 Header Acknowledgement virtual void OnHeaderAcknowledgement(QuicStreamId stream_id) = 0; // 5.3.3 Stream Cancellation
diff --git a/quic/core/qpack/qpack_decoder_stream_receiver_test.cc b/quic/core/qpack/qpack_decoder_stream_receiver_test.cc index e9b3124..fc7225f 100644 --- a/quic/core/qpack/qpack_decoder_stream_receiver_test.cc +++ b/quic/core/qpack/qpack_decoder_stream_receiver_test.cc
@@ -9,6 +9,7 @@ #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 { @@ -19,7 +20,7 @@ public: ~MockDelegate() override = default; - MOCK_METHOD1(OnTableStateSynchronize, void(uint64_t insert_count)); + MOCK_METHOD1(OnInsertCountIncrement, void(uint64_t increment)); MOCK_METHOD1(OnHeaderAcknowledgement, void(QuicStreamId stream_id)); MOCK_METHOD1(OnStreamCancellation, void(QuicStreamId stream_id)); MOCK_METHOD1(OnErrorDetected, void(QuicStringPiece error_message)); @@ -34,20 +35,20 @@ StrictMock<MockDelegate> delegate_; }; -TEST_F(QpackDecoderStreamReceiverTest, TableStateSynchronize) { - EXPECT_CALL(delegate_, OnTableStateSynchronize(0)); +TEST_F(QpackDecoderStreamReceiverTest, InsertCountIncrement) { + EXPECT_CALL(delegate_, OnInsertCountIncrement(0)); stream_.Decode(QuicTextUtils::HexDecode("00")); - EXPECT_CALL(delegate_, OnTableStateSynchronize(10)); + EXPECT_CALL(delegate_, OnInsertCountIncrement(10)); stream_.Decode(QuicTextUtils::HexDecode("0a")); - EXPECT_CALL(delegate_, OnTableStateSynchronize(63)); + EXPECT_CALL(delegate_, OnInsertCountIncrement(63)); stream_.Decode(QuicTextUtils::HexDecode("3f00")); - EXPECT_CALL(delegate_, OnTableStateSynchronize(200)); + EXPECT_CALL(delegate_, OnInsertCountIncrement(200)); stream_.Decode(QuicTextUtils::HexDecode("3f8901")); - EXPECT_CALL(delegate_, OnErrorDetected("Encoded integer too large.")); + EXPECT_CALL(delegate_, OnErrorDetected(Eq("Encoded integer too large."))); stream_.Decode(QuicTextUtils::HexDecode("3fffffffffffffffffffff")); } @@ -64,7 +65,7 @@ EXPECT_CALL(delegate_, OnHeaderAcknowledgement(503)); stream_.Decode(QuicTextUtils::HexDecode("fff802")); - EXPECT_CALL(delegate_, OnErrorDetected("Encoded integer too large.")); + EXPECT_CALL(delegate_, OnErrorDetected(Eq("Encoded integer too large."))); stream_.Decode(QuicTextUtils::HexDecode("ffffffffffffffffffffff")); } @@ -81,7 +82,7 @@ EXPECT_CALL(delegate_, OnStreamCancellation(110)); stream_.Decode(QuicTextUtils::HexDecode("7f2f")); - EXPECT_CALL(delegate_, OnErrorDetected("Encoded integer too large.")); + EXPECT_CALL(delegate_, OnErrorDetected(Eq("Encoded integer too large."))); stream_.Decode(QuicTextUtils::HexDecode("7fffffffffffffffffffff")); }
diff --git a/quic/core/qpack/qpack_decoder_stream_sender.cc b/quic/core/qpack/qpack_decoder_stream_sender.cc index 48d0e0e..141b64a 100644 --- a/quic/core/qpack/qpack_decoder_stream_sender.cc +++ b/quic/core/qpack/qpack_decoder_stream_sender.cc
@@ -18,18 +18,17 @@ DCHECK(delegate_); } -void QpackDecoderStreamSender::SendTableStateSynchronize( - uint64_t insert_count) { - instruction_encoder_.set_varint(insert_count); +void QpackDecoderStreamSender::SendInsertCountIncrement(uint64_t increment) { + instruction_encoder_.set_varint(increment); - instruction_encoder_.Encode(TableStateSynchronizeInstruction()); + instruction_encoder_.Encode(InsertCountIncrementInstruction()); QuicString output; instruction_encoder_.Next(std::numeric_limits<size_t>::max(), &output); DCHECK(!instruction_encoder_.HasNext()); - delegate_->Write(output); + delegate_->WriteDecoderStreamData(output); } void QpackDecoderStreamSender::SendHeaderAcknowledgement( @@ -43,7 +42,7 @@ instruction_encoder_.Next(std::numeric_limits<size_t>::max(), &output); DCHECK(!instruction_encoder_.HasNext()); - delegate_->Write(output); + delegate_->WriteDecoderStreamData(output); } void QpackDecoderStreamSender::SendStreamCancellation(QuicStreamId stream_id) { @@ -56,7 +55,7 @@ instruction_encoder_.Next(std::numeric_limits<size_t>::max(), &output); DCHECK(!instruction_encoder_.HasNext()); - delegate_->Write(output); + delegate_->WriteDecoderStreamData(output); } } // namespace quic
diff --git a/quic/core/qpack/qpack_decoder_stream_sender.h b/quic/core/qpack/qpack_decoder_stream_sender.h index 0522042..a791173 100644 --- a/quic/core/qpack/qpack_decoder_stream_sender.h +++ b/quic/core/qpack/qpack_decoder_stream_sender.h
@@ -24,9 +24,10 @@ virtual ~Delegate() = default; // Encoded |data| is ready to be written on the decoder stream. - // Write() is called exactly once for each instruction, |data| contains the - // entire encoded instruction and it is guaranteed to be not empty. - virtual void Write(QuicStringPiece data) = 0; + // WriteDecoderStreamData() is called exactly once for each instruction. + // |data| contains the entire encoded instruction and it is guaranteed to be + // not empty. + virtual void WriteDecoderStreamData(QuicStringPiece data) = 0; }; explicit QpackDecoderStreamSender(Delegate* delegate); @@ -37,8 +38,8 @@ // Methods for sending instructions, see // https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#rfc.section.5.3 - // 5.3.1 Table State Synchronize - void SendTableStateSynchronize(uint64_t insert_count); + // 5.3.1 Insert Count Increment + void SendInsertCountIncrement(uint64_t increment); // 5.3.2 Header Acknowledgement void SendHeaderAcknowledgement(QuicStreamId stream_id); // 5.3.3 Stream Cancellation
diff --git a/quic/core/qpack/qpack_decoder_stream_sender_test.cc b/quic/core/qpack/qpack_decoder_stream_sender_test.cc index ab65c8c..cc95759 100644 --- a/quic/core/qpack/qpack_decoder_stream_sender_test.cc +++ b/quic/core/qpack/qpack_decoder_stream_sender_test.cc
@@ -9,6 +9,7 @@ #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 { @@ -19,7 +20,7 @@ public: ~MockSenderDelegate() override = default; - MOCK_METHOD1(Write, void(QuicStringPiece data)); + MOCK_METHOD1(WriteDecoderStreamData, void(QuicStringPiece data)); }; class QpackDecoderStreamSenderTest : public QuicTest { @@ -31,45 +32,57 @@ QpackDecoderStreamSender stream_; }; -TEST_F(QpackDecoderStreamSenderTest, TableStateSynchronize) { - EXPECT_CALL(delegate_, Write(QuicTextUtils::HexDecode("00"))); - stream_.SendTableStateSynchronize(0); +TEST_F(QpackDecoderStreamSenderTest, InsertCountIncrement) { + EXPECT_CALL(delegate_, + WriteDecoderStreamData(Eq(QuicTextUtils::HexDecode("00")))); + stream_.SendInsertCountIncrement(0); - EXPECT_CALL(delegate_, Write(QuicTextUtils::HexDecode("0a"))); - stream_.SendTableStateSynchronize(10); + EXPECT_CALL(delegate_, + WriteDecoderStreamData(Eq(QuicTextUtils::HexDecode("0a")))); + stream_.SendInsertCountIncrement(10); - EXPECT_CALL(delegate_, Write(QuicTextUtils::HexDecode("3f00"))); - stream_.SendTableStateSynchronize(63); + EXPECT_CALL(delegate_, + WriteDecoderStreamData(Eq(QuicTextUtils::HexDecode("3f00")))); + stream_.SendInsertCountIncrement(63); - EXPECT_CALL(delegate_, Write(QuicTextUtils::HexDecode("3f8901"))); - stream_.SendTableStateSynchronize(200); + EXPECT_CALL(delegate_, + WriteDecoderStreamData(Eq(QuicTextUtils::HexDecode("3f8901")))); + stream_.SendInsertCountIncrement(200); } TEST_F(QpackDecoderStreamSenderTest, HeaderAcknowledgement) { - EXPECT_CALL(delegate_, Write(QuicTextUtils::HexDecode("80"))); + EXPECT_CALL(delegate_, + WriteDecoderStreamData(Eq(QuicTextUtils::HexDecode("80")))); stream_.SendHeaderAcknowledgement(0); - EXPECT_CALL(delegate_, Write(QuicTextUtils::HexDecode("a5"))); + EXPECT_CALL(delegate_, + WriteDecoderStreamData(Eq(QuicTextUtils::HexDecode("a5")))); stream_.SendHeaderAcknowledgement(37); - EXPECT_CALL(delegate_, Write(QuicTextUtils::HexDecode("ff00"))); + EXPECT_CALL(delegate_, + WriteDecoderStreamData(Eq(QuicTextUtils::HexDecode("ff00")))); stream_.SendHeaderAcknowledgement(127); - EXPECT_CALL(delegate_, Write(QuicTextUtils::HexDecode("fff802"))); + EXPECT_CALL(delegate_, + WriteDecoderStreamData(Eq(QuicTextUtils::HexDecode("fff802")))); stream_.SendHeaderAcknowledgement(503); } TEST_F(QpackDecoderStreamSenderTest, StreamCancellation) { - EXPECT_CALL(delegate_, Write(QuicTextUtils::HexDecode("40"))); + EXPECT_CALL(delegate_, + WriteDecoderStreamData(Eq(QuicTextUtils::HexDecode("40")))); stream_.SendStreamCancellation(0); - EXPECT_CALL(delegate_, Write(QuicTextUtils::HexDecode("53"))); + EXPECT_CALL(delegate_, + WriteDecoderStreamData(Eq(QuicTextUtils::HexDecode("53")))); stream_.SendStreamCancellation(19); - EXPECT_CALL(delegate_, Write(QuicTextUtils::HexDecode("7f00"))); + EXPECT_CALL(delegate_, + WriteDecoderStreamData(Eq(QuicTextUtils::HexDecode("7f00")))); stream_.SendStreamCancellation(63); - EXPECT_CALL(delegate_, Write(QuicTextUtils::HexDecode("7f2f"))); + EXPECT_CALL(delegate_, + WriteDecoderStreamData(Eq(QuicTextUtils::HexDecode("7f2f")))); stream_.SendStreamCancellation(110); }
diff --git a/quic/core/qpack/qpack_decoder_test.cc b/quic/core/qpack/qpack_decoder_test.cc index 5f68213..52f739c 100644 --- a/quic/core/qpack/qpack_decoder_test.cc +++ b/quic/core/qpack/qpack_decoder_test.cc
@@ -4,6 +4,8 @@ #include "net/third_party/quiche/src/quic/core/qpack/qpack_decoder.h" +#include <algorithm> + #include "base/logging.h" #include "net/third_party/quiche/src/quic/core/qpack/qpack_decoder_test_utils.h" #include "net/third_party/quiche/src/quic/core/qpack/qpack_test_utils.h" @@ -66,8 +68,8 @@ FragmentMode::kOctetByOctet)); TEST_P(QpackDecoderTest, NoPrefix) { - EXPECT_CALL(handler_, OnDecodingErrorDetected( - QuicStringPiece("Incomplete header data prefix."))); + EXPECT_CALL(handler_, + OnDecodingErrorDetected(Eq("Incomplete header data prefix."))); // Header Data Prefix is at least two bytes long. DecodeHeaderBlock(QuicTextUtils::HexDecode("00")); @@ -76,60 +78,54 @@ TEST_P(QpackDecoderTest, EmptyHeaderBlock) { EXPECT_CALL(handler_, OnDecodingCompleted()); EXPECT_CALL(decoder_stream_sender_delegate_, - Write(Eq(kHeaderAcknowledgement))); + WriteDecoderStreamData(Eq(kHeaderAcknowledgement))); DecodeHeaderBlock(QuicTextUtils::HexDecode("0000")); } TEST_P(QpackDecoderTest, LiteralEntryEmptyName) { - EXPECT_CALL(handler_, - OnHeaderDecoded(QuicStringPiece(""), QuicStringPiece("foo"))); + EXPECT_CALL(handler_, OnHeaderDecoded(Eq(""), Eq("foo"))); EXPECT_CALL(handler_, OnDecodingCompleted()); EXPECT_CALL(decoder_stream_sender_delegate_, - Write(Eq(kHeaderAcknowledgement))); + WriteDecoderStreamData(Eq(kHeaderAcknowledgement))); DecodeHeaderBlock(QuicTextUtils::HexDecode("00002003666f6f")); } TEST_P(QpackDecoderTest, LiteralEntryEmptyValue) { - EXPECT_CALL(handler_, - OnHeaderDecoded(QuicStringPiece("foo"), QuicStringPiece(""))); + EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq(""))); EXPECT_CALL(handler_, OnDecodingCompleted()); EXPECT_CALL(decoder_stream_sender_delegate_, - Write(Eq(kHeaderAcknowledgement))); + WriteDecoderStreamData(Eq(kHeaderAcknowledgement))); DecodeHeaderBlock(QuicTextUtils::HexDecode("000023666f6f00")); } TEST_P(QpackDecoderTest, LiteralEntryEmptyNameAndValue) { - EXPECT_CALL(handler_, - OnHeaderDecoded(QuicStringPiece(""), QuicStringPiece(""))); + EXPECT_CALL(handler_, OnHeaderDecoded(Eq(""), Eq(""))); EXPECT_CALL(handler_, OnDecodingCompleted()); EXPECT_CALL(decoder_stream_sender_delegate_, - Write(Eq(kHeaderAcknowledgement))); + WriteDecoderStreamData(Eq(kHeaderAcknowledgement))); DecodeHeaderBlock(QuicTextUtils::HexDecode("00002000")); } TEST_P(QpackDecoderTest, SimpleLiteralEntry) { - EXPECT_CALL(handler_, - OnHeaderDecoded(QuicStringPiece("foo"), QuicStringPiece("bar"))); + EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("bar"))); EXPECT_CALL(handler_, OnDecodingCompleted()); EXPECT_CALL(decoder_stream_sender_delegate_, - Write(Eq(kHeaderAcknowledgement))); + WriteDecoderStreamData(Eq(kHeaderAcknowledgement))); DecodeHeaderBlock(QuicTextUtils::HexDecode("000023666f6f03626172")); } TEST_P(QpackDecoderTest, MultipleLiteralEntries) { - EXPECT_CALL(handler_, - OnHeaderDecoded(QuicStringPiece("foo"), QuicStringPiece("bar"))); + EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("bar"))); QuicString str(127, 'a'); - EXPECT_CALL(handler_, OnHeaderDecoded(QuicStringPiece("foobaar"), - QuicStringPiece(str))); + EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foobaar"), QuicStringPiece(str))); EXPECT_CALL(handler_, OnDecodingCompleted()); EXPECT_CALL(decoder_stream_sender_delegate_, - Write(Eq(kHeaderAcknowledgement))); + WriteDecoderStreamData(Eq(kHeaderAcknowledgement))); DecodeHeaderBlock(QuicTextUtils::HexDecode( "0000" // prefix @@ -146,24 +142,24 @@ // Name Length value is too large for varint decoder to decode. TEST_P(QpackDecoderTest, NameLenTooLargeForVarintDecoder) { - EXPECT_CALL(handler_, OnDecodingErrorDetected( - QuicStringPiece("Encoded integer too large."))); + EXPECT_CALL(handler_, + OnDecodingErrorDetected(Eq("Encoded integer too large."))); DecodeHeaderBlock(QuicTextUtils::HexDecode("000027ffffffffffffffffffff")); } // Name Length value can be decoded by varint decoder but exceeds 1 MB limit. TEST_P(QpackDecoderTest, NameLenExceedsLimit) { - EXPECT_CALL(handler_, OnDecodingErrorDetected( - QuicStringPiece("String literal too long."))); + EXPECT_CALL(handler_, + OnDecodingErrorDetected(Eq("String literal too long."))); DecodeHeaderBlock(QuicTextUtils::HexDecode("000027ffff7f")); } // Value Length value is too large for varint decoder to decode. TEST_P(QpackDecoderTest, ValueLenTooLargeForVarintDecoder) { - EXPECT_CALL(handler_, OnDecodingErrorDetected( - QuicStringPiece("Encoded integer too large."))); + EXPECT_CALL(handler_, + OnDecodingErrorDetected(Eq("Encoded integer too large."))); DecodeHeaderBlock( QuicTextUtils::HexDecode("000023666f6f7fffffffffffffffffffff")); @@ -171,37 +167,35 @@ // Value Length value can be decoded by varint decoder but exceeds 1 MB limit. TEST_P(QpackDecoderTest, ValueLenExceedsLimit) { - EXPECT_CALL(handler_, OnDecodingErrorDetected( - QuicStringPiece("String literal too long."))); + EXPECT_CALL(handler_, + OnDecodingErrorDetected(Eq("String literal too long."))); DecodeHeaderBlock(QuicTextUtils::HexDecode("000023666f6f7fffff7f")); } TEST_P(QpackDecoderTest, IncompleteHeaderBlock) { - EXPECT_CALL(handler_, OnDecodingErrorDetected( - QuicStringPiece("Incomplete header block."))); + EXPECT_CALL(handler_, + OnDecodingErrorDetected(Eq("Incomplete header block."))); DecodeHeaderBlock(QuicTextUtils::HexDecode("00002366")); } TEST_P(QpackDecoderTest, HuffmanSimple) { - EXPECT_CALL(handler_, OnHeaderDecoded(QuicStringPiece("custom-key"), - QuicStringPiece("custom-value"))); + EXPECT_CALL(handler_, OnHeaderDecoded(Eq("custom-key"), Eq("custom-value"))); EXPECT_CALL(handler_, OnDecodingCompleted()); EXPECT_CALL(decoder_stream_sender_delegate_, - Write(Eq(kHeaderAcknowledgement))); + WriteDecoderStreamData(Eq(kHeaderAcknowledgement))); - DecodeHeaderBlock(QuicTextUtils::HexDecode( - QuicStringPiece("00002f0125a849e95ba97d7f8925a849e95bb8e8b4bf"))); + DecodeHeaderBlock( + QuicTextUtils::HexDecode("00002f0125a849e95ba97d7f8925a849e95bb8e8b4bf")); } TEST_P(QpackDecoderTest, AlternatingHuffmanNonHuffman) { - EXPECT_CALL(handler_, OnHeaderDecoded(QuicStringPiece("custom-key"), - QuicStringPiece("custom-value"))) + EXPECT_CALL(handler_, OnHeaderDecoded(Eq("custom-key"), Eq("custom-value"))) .Times(4); EXPECT_CALL(handler_, OnDecodingCompleted()); EXPECT_CALL(decoder_stream_sender_delegate_, - Write(Eq(kHeaderAcknowledgement))); + WriteDecoderStreamData(Eq(kHeaderAcknowledgement))); DecodeHeaderBlock(QuicTextUtils::HexDecode( "0000" // Prefix. @@ -212,8 +206,7 @@ "2f0125a849e95ba97d7f" // Huffman-encoded name. "0c637573746f6d2d76616c7565" // Non-Huffman encoded value. "2703637573746f6d2d6b6579" // Non-Huffman encoded name. - "8925a849e95bb8e8b4bf" // Huffman-encoded value. - )); + "8925a849e95bb8e8b4bf")); // Huffman-encoded value. } TEST_P(QpackDecoderTest, HuffmanNameDoesNotHaveEOSPrefix) { @@ -260,30 +253,23 @@ TEST_P(QpackDecoderTest, StaticTable) { // A header name that has multiple entries with different values. - EXPECT_CALL(handler_, OnHeaderDecoded(QuicStringPiece(":method"), - QuicStringPiece("GET"))); - EXPECT_CALL(handler_, OnHeaderDecoded(QuicStringPiece(":method"), - QuicStringPiece("POST"))); - EXPECT_CALL(handler_, OnHeaderDecoded(QuicStringPiece(":method"), - QuicStringPiece("TRACE"))); + EXPECT_CALL(handler_, OnHeaderDecoded(Eq(":method"), Eq("GET"))); + EXPECT_CALL(handler_, OnHeaderDecoded(Eq(":method"), Eq("POST"))); + EXPECT_CALL(handler_, OnHeaderDecoded(Eq(":method"), Eq("TRACE"))); // A header name that has a single entry with non-empty value. - EXPECT_CALL(handler_, OnHeaderDecoded(QuicStringPiece("accept-encoding"), - QuicStringPiece("gzip, deflate, br"))); - EXPECT_CALL(handler_, OnHeaderDecoded(QuicStringPiece("accept-encoding"), - QuicStringPiece("compress"))); - EXPECT_CALL(handler_, OnHeaderDecoded(QuicStringPiece("accept-encoding"), - QuicStringPiece(""))); + EXPECT_CALL(handler_, + OnHeaderDecoded(Eq("accept-encoding"), Eq("gzip, deflate, br"))); + EXPECT_CALL(handler_, OnHeaderDecoded(Eq("accept-encoding"), Eq("compress"))); + EXPECT_CALL(handler_, OnHeaderDecoded(Eq("accept-encoding"), Eq(""))); // A header name that has a single entry with empty value. - EXPECT_CALL(handler_, OnHeaderDecoded(QuicStringPiece("location"), - QuicStringPiece(""))); - EXPECT_CALL(handler_, OnHeaderDecoded(QuicStringPiece("location"), - QuicStringPiece("foo"))); + EXPECT_CALL(handler_, OnHeaderDecoded(Eq("location"), Eq(""))); + EXPECT_CALL(handler_, OnHeaderDecoded(Eq("location"), Eq("foo"))); EXPECT_CALL(handler_, OnDecodingCompleted()); EXPECT_CALL(decoder_stream_sender_delegate_, - Write(Eq(kHeaderAcknowledgement))); + WriteDecoderStreamData(Eq(kHeaderAcknowledgement))); DecodeHeaderBlock(QuicTextUtils::HexDecode( "0000d1dfccd45f108621e9aec2a11f5c8294e75f000554524143455f1000")); @@ -291,12 +277,12 @@ TEST_P(QpackDecoderTest, TooHighStaticTableIndex) { // This is the last entry in the static table with index 98. - EXPECT_CALL(handler_, OnHeaderDecoded(QuicStringPiece("x-frame-options"), - QuicStringPiece("sameorigin"))); + EXPECT_CALL(handler_, + OnHeaderDecoded(Eq("x-frame-options"), Eq("sameorigin"))); // Addressing entry 99 should trigger an error. - EXPECT_CALL(handler_, OnDecodingErrorDetected( - QuicStringPiece("Static table entry not found."))); + EXPECT_CALL(handler_, + OnDecodingErrorDetected(Eq("Static table entry not found."))); DecodeHeaderBlock(QuicTextUtils::HexDecode("0000ff23ff24")); } @@ -311,11 +297,10 @@ "01")); // Duplicate entry with relative index 1. // Now there are four entries in the dynamic table. - // Note that absolute indices start with 1. - // Entry 1: "foo", "bar" - // Entry 2: "foo", "ZZZ" - // Entry 3: ":method", "foo" - // Entry 4: "foo", "ZZZ" + // Entry 0: "foo", "bar" + // Entry 1: "foo", "ZZZ" + // Entry 2: ":method", "foo" + // Entry 3: "foo", "ZZZ" // Use a Sequence to test that mock methods are called in order. Sequence s; @@ -327,17 +312,17 @@ EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("ZZZ"))).InSequence(s); EXPECT_CALL(handler_, OnHeaderDecoded(Eq(":method"), Eq("ZZ"))).InSequence(s); EXPECT_CALL(decoder_stream_sender_delegate_, - Write(Eq(kHeaderAcknowledgement))) + WriteDecoderStreamData(Eq(kHeaderAcknowledgement))) .InSequence(s); EXPECT_CALL(handler_, OnDecodingCompleted()).InSequence(s); DecodeHeaderBlock(QuicTextUtils::HexDecode( - "0500" // Largest Reference 4 and Delta Base Index 0. - // Base Index is 4 + 0 = 4. - "83" // Dynamic table entry with relative index 3, absolute index 1. - "82" // Dynamic table entry with relative index 2, absolute index 2. - "81" // Dynamic table entry with relative index 1, absolute index 3. - "80" // Dynamic table entry with relative index 0, absolute index 4. + "0500" // Required Insert Count 4 and Delta Base 0. + // Base is 4 + 0 = 4. + "83" // Dynamic table entry with relative index 3, absolute index 0. + "82" // Dynamic table entry with relative index 2, absolute index 1. + "81" // Dynamic table entry with relative index 1, absolute index 2. + "80" // Dynamic table entry with relative index 0, absolute index 3. "41025a5a")); // Name of entry 1 (relative index) from dynamic table, // with value "ZZ". @@ -348,17 +333,17 @@ EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("ZZZ"))).InSequence(s); EXPECT_CALL(handler_, OnHeaderDecoded(Eq(":method"), Eq("ZZ"))).InSequence(s); EXPECT_CALL(decoder_stream_sender_delegate_, - Write(Eq(kHeaderAcknowledgement))) + WriteDecoderStreamData(Eq(kHeaderAcknowledgement))) .InSequence(s); EXPECT_CALL(handler_, OnDecodingCompleted()).InSequence(s); DecodeHeaderBlock(QuicTextUtils::HexDecode( - "0502" // Largest Reference 4 and Delta Base Index 2. - // Base Index is 4 + 2 = 6. - "85" // Dynamic table entry with relative index 5, absolute index 1. - "84" // Dynamic table entry with relative index 4, absolute index 2. - "83" // Dynamic table entry with relative index 3, absolute index 3. - "82" // Dynamic table entry with relative index 2, absolute index 4. + "0502" // Required Insert Count 4 and Delta Base 2. + // Base is 4 + 2 = 6. + "85" // Dynamic table entry with relative index 5, absolute index 0. + "84" // Dynamic table entry with relative index 4, absolute index 1. + "83" // Dynamic table entry with relative index 3, absolute index 2. + "82" // Dynamic table entry with relative index 2, absolute index 3. "43025a5a")); // Name of entry 3 (relative index) from dynamic table, // with value "ZZ". @@ -369,17 +354,17 @@ EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("ZZZ"))).InSequence(s); EXPECT_CALL(handler_, OnHeaderDecoded(Eq(":method"), Eq("ZZ"))).InSequence(s); EXPECT_CALL(decoder_stream_sender_delegate_, - Write(Eq(kHeaderAcknowledgement))) + WriteDecoderStreamData(Eq(kHeaderAcknowledgement))) .InSequence(s); EXPECT_CALL(handler_, OnDecodingCompleted()).InSequence(s); DecodeHeaderBlock(QuicTextUtils::HexDecode( - "0582" // Largest Reference 4 and Delta Base Index 2 with sign bit set. - // Base Index is 4 - 2 - 1 = 1. - "80" // Dynamic table entry with relative index 0, absolute index 1. - "10" // Dynamic table entry with post-base index 0, absolute index 2. - "11" // Dynamic table entry with post-base index 1, absolute index 3. - "12" // Dynamic table entry with post-base index 2, absolute index 4. + "0582" // Required Insert Count 4 and Delta Base 2 with sign bit set. + // Base is 4 - 2 - 1 = 1. + "80" // Dynamic table entry with relative index 0, absolute index 0. + "10" // Dynamic table entry with post-base index 0, absolute index 1. + "11" // Dynamic table entry with post-base index 1, absolute index 2. + "12" // Dynamic table entry with post-base index 2, absolute index 3. "01025a5a")); // Name of entry 1 (post-base index) from dynamic table, // with value "ZZ". } @@ -391,12 +376,12 @@ EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("bar"))); EXPECT_CALL(handler_, OnDecodingCompleted()); EXPECT_CALL(decoder_stream_sender_delegate_, - Write(Eq(kHeaderAcknowledgement))); + WriteDecoderStreamData(Eq(kHeaderAcknowledgement))); DecodeHeaderBlock(QuicTextUtils::HexDecode( - "0200" // Largest Reference 1 and Delta Base Index 0. - // Base Index is 1 + 0 = 1. - "80")); // Dynamic table entry with relative index 0, absolute index 1. + "0200" // Required Insert Count 1 and Delta Base 0. + // Base is 1 + 0 = 1. + "80")); // Dynamic table entry with relative index 0, absolute index 0. // Change dynamic table capacity to 32 bytes, smaller than the entry. // This must cause the entry to be evicted. @@ -406,14 +391,14 @@ OnDecodingErrorDetected(Eq("Dynamic table entry not found."))); DecodeHeaderBlock(QuicTextUtils::HexDecode( - "0200" // Largest Reference 1 and Delta Base Index 0. - // Base Index is 1 + 0 = 1. - "80")); // Dynamic table entry with relative index 0, absolute index 1. + "0200" // Required Insert Count 1 and Delta Base 0. + // Base is 1 + 0 = 1. + "80")); // Dynamic table entry with relative index 0, absolute index 0. } TEST_P(QpackDecoderTest, EncoderStreamErrorEntryTooLarge) { EXPECT_CALL(encoder_stream_error_delegate_, - OnError(Eq("Error inserting literal entry."))); + OnEncoderStreamError(Eq("Error inserting literal entry."))); // Set dynamic table capacity to 34. DecodeEncoderStreamData(QuicTextUtils::HexDecode("3f03")); @@ -423,7 +408,7 @@ TEST_P(QpackDecoderTest, EncoderStreamErrorInvalidStaticTableEntry) { EXPECT_CALL(encoder_stream_error_delegate_, - OnError(Eq("Invalid static table entry."))); + OnEncoderStreamError(Eq("Invalid static table entry."))); // Address invalid static table entry index 99. DecodeEncoderStreamData(QuicTextUtils::HexDecode("ff2400")); @@ -431,7 +416,7 @@ TEST_P(QpackDecoderTest, EncoderStreamErrorInvalidDynamicTableEntry) { EXPECT_CALL(encoder_stream_error_delegate_, - OnError(Eq("Dynamic table entry not found."))); + OnEncoderStreamError(Eq("Dynamic table entry not found."))); DecodeEncoderStreamData(QuicTextUtils::HexDecode( "6294e703626172" // Add literal entry with name "foo" and value "bar". @@ -442,7 +427,7 @@ TEST_P(QpackDecoderTest, EncoderStreamErrorDuplicateInvalidEntry) { EXPECT_CALL(encoder_stream_error_delegate_, - OnError(Eq("Dynamic table entry not found."))); + OnEncoderStreamError(Eq("Dynamic table entry not found."))); DecodeEncoderStreamData(QuicTextUtils::HexDecode( "6294e703626172" // Add literal entry with name "foo" and value "bar". @@ -453,27 +438,25 @@ TEST_P(QpackDecoderTest, EncoderStreamErrorTooLargeInteger) { EXPECT_CALL(encoder_stream_error_delegate_, - OnError(Eq("Encoded integer too large."))); + OnEncoderStreamError(Eq("Encoded integer too large."))); DecodeEncoderStreamData(QuicTextUtils::HexDecode("3fffffffffffffffffffff")); } -TEST_P(QpackDecoderTest, InvalidDynamicEntryWhenBaseIndexIsZero) { +TEST_P(QpackDecoderTest, InvalidDynamicEntryWhenBaseIsZero) { EXPECT_CALL(handler_, OnDecodingErrorDetected(Eq("Invalid relative index."))); DecodeHeaderBlock(QuicTextUtils::HexDecode( - "0280" // Largest Reference is 1. Base Index 1 - 1 - 0 = 0 is explicitly - // permitted by the spec. + "0280" // Required Insert Count is 1. Base 1 - 1 - 0 = 0 is explicitly + // permitted by the spec. "80")); // However, addressing entry with relative index 0 would point to - // absolute index 0, which is invalid (absolute index is one - // based). + // absolute index -1, which is invalid. } -TEST_P(QpackDecoderTest, InvalidNegativeBaseIndex) { - EXPECT_CALL(handler_, - OnDecodingErrorDetected(Eq("Error calculating Base Index."))); +TEST_P(QpackDecoderTest, InvalidNegativeBase) { + EXPECT_CALL(handler_, OnDecodingErrorDetected(Eq("Error calculating Base."))); - // Largest reference 1, Delta Base Index 1 with sign bit set, Base Index would + // Required Insert Count 1, Delta Base 1 with sign bit set, Base would // be 1 - 1 - 1 = -1, but it is not allowed to be negative. DecodeHeaderBlock(QuicTextUtils::HexDecode("0281")); } @@ -486,38 +469,37 @@ OnDecodingErrorDetected(Eq("Dynamic table entry not found."))); DecodeHeaderBlock(QuicTextUtils::HexDecode( - "0500" // Largest Reference 4 and Delta Base Index 0. - // Base Index is 4 + 0 = 4. + "0500" // Required Insert Count 4 and Delta Base 0. + // Base is 4 + 0 = 4. "82")); // Indexed Header Field instruction addressing relative index 2. - // This is absolute index 2. Such entry does not exist. + // This is absolute index 1. Such entry does not exist. EXPECT_CALL(handler_, OnDecodingErrorDetected(Eq("Invalid relative index."))); DecodeHeaderBlock(QuicTextUtils::HexDecode( - "0500" // Largest Reference 4 and Delta Base Index 0. - // Base Index is 4 + 0 = 4. + "0500" // Required Insert Count 4 and Delta Base 0. + // Base is 4 + 0 = 4. "84")); // Indexed Header Field instruction addressing relative index 4. - // This is absolute index 0, which is invalid, because absolute - // indexing starts from 1. + // This is absolute index -1, which is invalid. EXPECT_CALL(handler_, OnDecodingErrorDetected(Eq("Dynamic table entry not found."))); DecodeHeaderBlock(QuicTextUtils::HexDecode( - "0500" // Largest Reference 4 and Delta Base Index 0. - // Base Index is 4 + 0 = 4. + "0500" // Required Insert Count 4 and Delta Base 0. + // Base is 4 + 0 = 4. "4200")); // Literal Header Field with Name Reference instruction - // addressing relative index 2. This is absolute index 2. Such + // addressing relative index 2. This is absolute index 1. Such // entry does not exist. EXPECT_CALL(handler_, OnDecodingErrorDetected(Eq("Invalid relative index."))); DecodeHeaderBlock(QuicTextUtils::HexDecode( - "0500" // Largest Reference 4 and Delta Base Index 0. - // Base Index is 4 + 0 = 4. + "0500" // Required Insert Count 4 and Delta Base 0. + // Base is 4 + 0 = 4. "4400")); // Literal Header Field with Name Reference instruction - // addressing relative index 4. This is absolute index 0, - // which is invalid, because absolute indexing starts from 1. + // addressing relative index 4. This is absolute index -1, + // which is invalid. } TEST_P(QpackDecoderTest, InvalidDynamicEntryByPostBaseIndex) { @@ -528,26 +510,27 @@ OnDecodingErrorDetected(Eq("Dynamic table entry not found."))); DecodeHeaderBlock(QuicTextUtils::HexDecode( - "0380" // Largest Reference 2 and Delta Base Index 0 with sign bit set. - // Base Index is 2 - 0 - 1 = 1 + "0380" // Required Insert Count 2 and Delta Base 0 with sign bit set. + // Base is 2 - 0 - 1 = 1 "10")); // Indexed Header Field instruction addressing dynamic table - // entry with post-base index 0, absolute index 2. Such entry + // entry with post-base index 0, absolute index 1. Such entry // does not exist. EXPECT_CALL(handler_, OnDecodingErrorDetected(Eq("Dynamic table entry not found."))); DecodeHeaderBlock(QuicTextUtils::HexDecode( - "0380" // Largest Reference 2 and Delta Base Index 0 with sign bit set. - // Base Index is 2 - 0 - 1 = 1 + "0380" // Required Insert Count 2 and Delta Base 0 with sign bit set. + // Base is 2 - 0 - 1 = 1 "0000")); // Literal Header Field With Name Reference instruction // addressing dynamic table entry with post-base index 0, - // absolute index 2. Such entry does not exist. + // absolute index 1. Such entry does not exist. } TEST_P(QpackDecoderTest, TableCapacityMustNotExceedMaximum) { - EXPECT_CALL(encoder_stream_error_delegate_, - OnError(Eq("Error updating dynamic table size."))); + EXPECT_CALL( + encoder_stream_error_delegate_, + OnEncoderStreamError(Eq("Error updating dynamic table capacity."))); // Try to update dynamic table capacity to 2048, which exceeds the maximum. DecodeEncoderStreamData(QuicTextUtils::HexDecode("3fe10f")); @@ -558,17 +541,17 @@ DecodeEncoderStreamData(QuicTextUtils::HexDecode("3f61")); } -TEST_P(QpackDecoderTest, LargestReferenceOutOfRange) { +TEST_P(QpackDecoderTest, InvalidEncodedRequiredInsertCount) { // Maximum dynamic table capacity is 1024. // MaxEntries is 1024 / 32 = 32. - // Largest Reference is decoded modulo 2 * MaxEntries, that is, modulo 64. + // Required Insert Count is decoded modulo 2 * MaxEntries, that is, modulo 64. // A value of 1 cannot be encoded as 65 even though it has the same remainder. - EXPECT_CALL(handler_, - OnDecodingErrorDetected(Eq("Error decoding Largest Reference."))); + EXPECT_CALL(handler_, OnDecodingErrorDetected( + Eq("Error decoding Required Insert Count."))); DecodeHeaderBlock(QuicTextUtils::HexDecode("4100")); } -TEST_P(QpackDecoderTest, WrappedLargestReference) { +TEST_P(QpackDecoderTest, WrappedRequiredInsertCount) { // Maximum dynamic table capacity is 1024. // MaxEntries is 1024 / 32 = 32. @@ -583,131 +566,136 @@ // Duplicate most recent entry 200 times. DecodeEncoderStreamData(QuicString(200, '\x00')); - // Now there is only one entry in the dynamic table, with absolute index 201. + // Now there is only one entry in the dynamic table, with absolute index 200. EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq(header_value))); EXPECT_CALL(handler_, OnDecodingCompleted()); EXPECT_CALL(decoder_stream_sender_delegate_, - Write(Eq(kHeaderAcknowledgement))); + WriteDecoderStreamData(Eq(kHeaderAcknowledgement))); - // Send header block with Largest Reference = 201. + // Send header block with Required Insert Count = 201. DecodeHeaderBlock(QuicTextUtils::HexDecode( - "0a00" // Wire Largest Reference 10, Largest Reference 201, - // Delta Base Index 0, Base Index 201. + "0a00" // Encoded Required Insert Count 10, Required Insert Count 201, + // Delta Base 0, Base 201. "80")); // Emit dynamic table entry with relative index 0. } -TEST_P(QpackDecoderTest, NonZeroLargestReferenceButNoDynamicEntries) { - EXPECT_CALL(handler_, OnHeaderDecoded(QuicStringPiece(":method"), - QuicStringPiece("GET"))); +TEST_P(QpackDecoderTest, NonZeroRequiredInsertCountButNoDynamicEntries) { + EXPECT_CALL(handler_, OnHeaderDecoded(Eq(":method"), Eq("GET"))); EXPECT_CALL(handler_, - OnDecodingErrorDetected(Eq("Largest Reference too large."))); + OnDecodingErrorDetected(Eq("Required Insert Count too large."))); DecodeHeaderBlock(QuicTextUtils::HexDecode( - "0200" // Largest Reference is 1. + "0200" // Required Insert Count is 1. "d1")); // But the only instruction references the static table. } -TEST_P(QpackDecoderTest, AddressEntryBeyondLargestReference) { - EXPECT_CALL(handler_, OnDecodingErrorDetected( - Eq("Index larger than Largest Reference."))); +TEST_P(QpackDecoderTest, AddressEntryNotAllowedByRequiredInsertCount) { + EXPECT_CALL( + handler_, + OnDecodingErrorDetected( + Eq("Absolute Index must be smaller than Required Insert Count."))); DecodeHeaderBlock(QuicTextUtils::HexDecode( - "0201" // Largest Reference 1 and Delta Base Index 1. - // Base Index is 1 + 1 = 2. + "0201" // Required Insert Count 1 and Delta Base 1. + // Base is 1 + 1 = 2. "80")); // Indexed Header Field instruction addressing dynamic table - // entry with relative index 0, absolute index 2. This is beyond - // Largest Reference. + // entry with relative index 0, absolute index 1. This is not + // allowed by Required Insert Count. - EXPECT_CALL(handler_, OnDecodingErrorDetected( - Eq("Index larger than Largest Reference."))); + EXPECT_CALL( + handler_, + OnDecodingErrorDetected( + Eq("Absolute Index must be smaller than Required Insert Count."))); DecodeHeaderBlock(QuicTextUtils::HexDecode( - "0201" // Largest Reference 1 and Delta Base Index 1. - // Base Index is 1 + 1 = 2. + "0201" // Required Insert Count 1 and Delta Base 1. + // Base is 1 + 1 = 2. "4000")); // Literal Header Field with Name Reference instruction // addressing dynamic table entry with relative index 0, - // absolute index 2. This is beyond Largest Reference. + // absolute index 1. This is not allowed by Required Index + // Count. - EXPECT_CALL(handler_, OnDecodingErrorDetected( - Eq("Index larger than Largest Reference."))); + EXPECT_CALL( + handler_, + OnDecodingErrorDetected( + Eq("Absolute Index must be smaller than Required Insert Count."))); DecodeHeaderBlock(QuicTextUtils::HexDecode( - "0200" // Largest Reference 1 and Delta Base Index 0. - // Base Index is 1 + 0 = 1. + "0200" // Required Insert Count 1 and Delta Base 0. + // Base is 1 + 0 = 1. "10")); // Indexed Header Field with Post-Base Index instruction // addressing dynamic table entry with post-base index 0, - // absolute index 2. This is beyond Largest Reference. + // absolute index 1. This is not allowed by Required Insert + // Count. - EXPECT_CALL(handler_, OnDecodingErrorDetected( - Eq("Index larger than Largest Reference."))); + EXPECT_CALL( + handler_, + OnDecodingErrorDetected( + Eq("Absolute Index must be smaller than Required Insert Count."))); DecodeHeaderBlock(QuicTextUtils::HexDecode( - "0200" // Largest Reference 1 and Delta Base Index 0. - // Base Index is 1 + 0 = 1. + "0200" // Required Insert Count 1 and Delta Base 0. + // Base is 1 + 0 = 1. "0000")); // Literal Header Field with Post-Base Name Reference // instruction addressing dynamic table entry with post-base - // index 0, absolute index 2. This is beyond Largest - // Reference. + // index 0, absolute index 1. This is not allowed by Required + // Index Count. } -TEST_P(QpackDecoderTest, PromisedLargestReferenceLargerThanLargestActualIndex) { +TEST_P(QpackDecoderTest, PromisedRequiredInsertCountLargerThanActual) { // Add literal entry with name "foo" and value "bar". DecodeEncoderStreamData(QuicTextUtils::HexDecode("6294e703626172")); // Duplicate entry. DecodeEncoderStreamData(QuicTextUtils::HexDecode("00")); + EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("bar"))); EXPECT_CALL(handler_, - OnHeaderDecoded(QuicStringPiece("foo"), QuicStringPiece("bar"))); - EXPECT_CALL(handler_, - OnDecodingErrorDetected(Eq("Largest Reference too large."))); + OnDecodingErrorDetected(Eq("Required Insert Count too large."))); DecodeHeaderBlock(QuicTextUtils::HexDecode( - "0300" // Largest Reference 2 and Delta Base Index 0. - // Base Index is 2 + 0 = 2. + "0300" // Required Insert Count 2 and Delta Base 0. + // Base is 2 + 0 = 2. "81")); // Indexed Header Field instruction addressing dynamic table - // entry with relative index 1, absolute index 1. This is the - // largest reference in this header block, even though Largest - // Reference is 2. + // entry with relative index 1, absolute index 0. Header block + // requires insert count of 1, even though Required Insert Count + // is 2. + EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq(""))); EXPECT_CALL(handler_, - OnHeaderDecoded(QuicStringPiece("foo"), QuicStringPiece(""))); - EXPECT_CALL(handler_, - OnDecodingErrorDetected(Eq("Largest Reference too large."))); + OnDecodingErrorDetected(Eq("Required Insert Count too large."))); DecodeHeaderBlock(QuicTextUtils::HexDecode( - "0300" // Largest Reference 2 and Delta Base Index 0. - // Base Index is 2 + 0 = 2. + "0300" // Required Insert Count 2 and Delta Base 0. + // Base is 2 + 0 = 2. "4100")); // Literal Header Field with Name Reference instruction // addressing dynamic table entry with relative index 1, - // absolute index 1. This is the largest reference in this - // header block, even though Largest Reference is 2. + // absolute index 0. Header block requires insert count of 1, + // even though Required Insert Count is 2. + EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("bar"))); EXPECT_CALL(handler_, - OnHeaderDecoded(QuicStringPiece("foo"), QuicStringPiece("bar"))); - EXPECT_CALL(handler_, - OnDecodingErrorDetected(Eq("Largest Reference too large."))); + OnDecodingErrorDetected(Eq("Required Insert Count too large."))); DecodeHeaderBlock(QuicTextUtils::HexDecode( - "0481" // Largest Reference 3 and Delta Base Index 1 with sign bit set. - // Base Index is 3 - 1 - 1 = 1. + "0481" // Required Insert Count 3 and Delta Base 1 with sign bit set. + // Base is 3 - 1 - 1 = 1. "10")); // Indexed Header Field with Post-Base Index instruction // addressing dynamic table entry with post-base index 0, - // absolute index 2. This is the largest reference in this - // header block, even though Largest Reference is 3. + // absolute index 1. Header block requires insert count of 2, + // even though Required Insert Count is 3. + EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq(""))); EXPECT_CALL(handler_, - OnHeaderDecoded(QuicStringPiece("foo"), QuicStringPiece(""))); - EXPECT_CALL(handler_, - OnDecodingErrorDetected(Eq("Largest Reference too large."))); + OnDecodingErrorDetected(Eq("Required Insert Count too large."))); DecodeHeaderBlock(QuicTextUtils::HexDecode( - "0481" // Largest Reference 3 and Delta Base Index 1 with sign bit set. - // Base Index is 3 - 1 - 1 = 1. + "0481" // Required Insert Count 3 and Delta Base 1 with sign bit set. + // Base is 3 - 1 - 1 = 1. "0000")); // Literal Header Field with Post-Base Name Reference // instruction addressing dynamic table entry with post-base - // index 0, absolute index 2. This is the largest reference in - // this header block, even though Largest Reference is 3. + // index 0, absolute index 1. Header block requires insert + // count of 2, even though Required Insert Count is 3. } } // namespace
diff --git a/quic/core/qpack/qpack_decoder_test_utils.cc b/quic/core/qpack/qpack_decoder_test_utils.cc index 21a4606..e8bbd17 100644 --- a/quic/core/qpack/qpack_decoder_test_utils.cc +++ b/quic/core/qpack/qpack_decoder_test_utils.cc
@@ -4,16 +4,20 @@ #include "net/third_party/quiche/src/quic/core/qpack/qpack_decoder_test_utils.h" +#include <algorithm> #include <cstddef> +#include <utility> #include "testing/gmock/include/gmock/gmock.h" namespace quic { namespace test { -void NoopEncoderStreamErrorDelegate::OnError(QuicStringPiece error_message) {} +void NoopEncoderStreamErrorDelegate::OnEncoderStreamError( + QuicStringPiece error_message) {} -void NoopDecoderStreamSenderDelegate::Write(QuicStringPiece data) {} +void NoopDecoderStreamSenderDelegate::WriteDecoderStreamData( + QuicStringPiece data) {} TestHeadersHandler::TestHeadersHandler() : decoding_completed_(false), decoding_error_detected_(false) {}
diff --git a/quic/core/qpack/qpack_decoder_test_utils.h b/quic/core/qpack/qpack_decoder_test_utils.h index 4896ce0..937ecfc 100644 --- a/quic/core/qpack/qpack_decoder_test_utils.h +++ b/quic/core/qpack/qpack_decoder_test_utils.h
@@ -21,7 +21,7 @@ public: ~NoopEncoderStreamErrorDelegate() override = default; - void OnError(QuicStringPiece error_message) override; + void OnEncoderStreamError(QuicStringPiece error_message) override; }; // Mock QpackDecoder::EncoderStreamErrorDelegate implementation. @@ -30,7 +30,7 @@ public: ~MockEncoderStreamErrorDelegate() override = default; - MOCK_METHOD1(OnError, void(QuicStringPiece error_message)); + MOCK_METHOD1(OnEncoderStreamError, void(QuicStringPiece error_message)); }; // QpackDecoderStreamSender::Delegate implementation that does nothing. @@ -39,7 +39,7 @@ public: ~NoopDecoderStreamSenderDelegate() override = default; - void Write(QuicStringPiece data) override; + void WriteDecoderStreamData(QuicStringPiece data) override; }; // Mock QpackDecoderStreamSender::Delegate implementation. @@ -48,7 +48,7 @@ public: ~MockDecoderStreamSenderDelegate() override = default; - MOCK_METHOD1(Write, void(QuicStringPiece data)); + MOCK_METHOD1(WriteDecoderStreamData, void(QuicStringPiece data)); }; // HeadersHandlerInterface implementation that collects decoded headers
diff --git a/quic/core/qpack/qpack_encoder.cc b/quic/core/qpack/qpack_encoder.cc index 86f1785..6019229 100644 --- a/quic/core/qpack/qpack_encoder.cc +++ b/quic/core/qpack/qpack_encoder.cc
@@ -35,7 +35,7 @@ decoder_stream_receiver_.Decode(data); } -void QpackEncoder::OnTableStateSynchronize(uint64_t insert_count) { +void QpackEncoder::OnInsertCountIncrement(uint64_t increment) { // TODO(bnc): Implement dynamic table management for encoding. } @@ -48,7 +48,7 @@ } void QpackEncoder::OnErrorDetected(QuicStringPiece error_message) { - decoder_stream_error_delegate_->OnError(error_message); + decoder_stream_error_delegate_->OnDecoderStreamError(error_message); } } // namespace quic
diff --git a/quic/core/qpack/qpack_encoder.h b/quic/core/qpack/qpack_encoder.h index b7d7f20..4e65532 100644 --- a/quic/core/qpack/qpack_encoder.h +++ b/quic/core/qpack/qpack_encoder.h
@@ -36,7 +36,7 @@ public: virtual ~DecoderStreamErrorDelegate() {} - virtual void OnError(QuicStringPiece error_message) = 0; + virtual void OnDecoderStreamError(QuicStringPiece error_message) = 0; }; QpackEncoder( @@ -55,7 +55,7 @@ void DecodeDecoderStreamData(QuicStringPiece data); // QpackDecoderStreamReceiver::Delegate implementation - void OnTableStateSynchronize(uint64_t insert_count) override; + void OnInsertCountIncrement(uint64_t increment) override; void OnHeaderAcknowledgement(QuicStreamId stream_id) override; void OnStreamCancellation(QuicStreamId stream_id) override; void OnErrorDetected(QuicStringPiece error_message) override;
diff --git a/quic/core/qpack/qpack_encoder_stream_receiver.cc b/quic/core/qpack/qpack_encoder_stream_receiver.cc index 008e357..3f8ef08 100644 --- a/quic/core/qpack/qpack_encoder_stream_receiver.cc +++ b/quic/core/qpack/qpack_encoder_stream_receiver.cc
@@ -45,8 +45,8 @@ return true; } - DCHECK_EQ(instruction, DynamicTableSizeUpdateInstruction()); - delegate_->OnDynamicTableSizeUpdate(instruction_decoder_.varint()); + DCHECK_EQ(instruction, SetDynamicTableCapacityInstruction()); + delegate_->OnSetDynamicTableCapacity(instruction_decoder_.varint()); return true; }
diff --git a/quic/core/qpack/qpack_encoder_stream_receiver.h b/quic/core/qpack/qpack_encoder_stream_receiver.h index 7ce4f15..66a2985 100644 --- a/quic/core/qpack/qpack_encoder_stream_receiver.h +++ b/quic/core/qpack/qpack_encoder_stream_receiver.h
@@ -33,8 +33,8 @@ QuicStringPiece value) = 0; // 5.2.3. Duplicate virtual void OnDuplicate(uint64_t index) = 0; - // 5.2.4. Dynamic Table Size Update - virtual void OnDynamicTableSizeUpdate(uint64_t max_size) = 0; + // 5.2.4. Set Dynamic Table Capacity + virtual void OnSetDynamicTableCapacity(uint64_t capacity) = 0; // Decoding error virtual void OnErrorDetected(QuicStringPiece error_message) = 0; };
diff --git a/quic/core/qpack/qpack_encoder_stream_receiver_test.cc b/quic/core/qpack/qpack_encoder_stream_receiver_test.cc index f9fce00..5685981 100644 --- a/quic/core/qpack/qpack_encoder_stream_receiver_test.cc +++ b/quic/core/qpack/qpack_encoder_stream_receiver_test.cc
@@ -9,6 +9,7 @@ #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 { @@ -26,7 +27,7 @@ MOCK_METHOD2(OnInsertWithoutNameReference, void(QuicStringPiece name, QuicStringPiece value)); MOCK_METHOD1(OnDuplicate, void(uint64_t index)); - MOCK_METHOD1(OnDynamicTableSizeUpdate, void(uint64_t max_size)); + MOCK_METHOD1(OnSetDynamicTableCapacity, void(uint64_t capacity)); MOCK_METHOD1(OnErrorDetected, void(QuicStringPiece error_message)); }; @@ -45,15 +46,15 @@ TEST_F(QpackEncoderStreamReceiverTest, InsertWithNameReference) { // Static, index fits in prefix, empty value. - EXPECT_CALL(*delegate(), OnInsertWithNameReference(true, 5, "")); + EXPECT_CALL(*delegate(), OnInsertWithNameReference(true, 5, Eq(""))); // Static, index fits in prefix, Huffman encoded value. - EXPECT_CALL(*delegate(), OnInsertWithNameReference(true, 2, "foo")); + EXPECT_CALL(*delegate(), OnInsertWithNameReference(true, 2, Eq("foo"))); // Not static, index does not fit in prefix, not Huffman encoded value. - EXPECT_CALL(*delegate(), OnInsertWithNameReference(false, 137, "bar")); + EXPECT_CALL(*delegate(), OnInsertWithNameReference(false, 137, Eq("bar"))); // Value length does not fit in prefix. // 'Z' would be Huffman encoded to 8 bits, so no Huffman encoding is used. EXPECT_CALL(*delegate(), - OnInsertWithNameReference(false, 42, QuicString(127, 'Z'))); + OnInsertWithNameReference(false, 42, Eq(QuicString(127, 'Z')))); Decode(QuicTextUtils::HexDecode( "c500" @@ -66,29 +67,29 @@ } TEST_F(QpackEncoderStreamReceiverTest, InsertWithNameReferenceIndexTooLarge) { - EXPECT_CALL(*delegate(), OnErrorDetected("Encoded integer too large.")); + EXPECT_CALL(*delegate(), OnErrorDetected(Eq("Encoded integer too large."))); Decode(QuicTextUtils::HexDecode("bfffffffffffffffffffffff")); } TEST_F(QpackEncoderStreamReceiverTest, InsertWithNameReferenceValueTooLong) { - EXPECT_CALL(*delegate(), - OnErrorDetected(QuicStringPiece("Encoded integer too large."))); + EXPECT_CALL(*delegate(), OnErrorDetected(Eq("Encoded integer too large."))); Decode(QuicTextUtils::HexDecode("c57fffffffffffffffffffff")); } TEST_F(QpackEncoderStreamReceiverTest, InsertWithoutNameReference) { // Empty name and value. - EXPECT_CALL(*delegate(), OnInsertWithoutNameReference("", "")); + EXPECT_CALL(*delegate(), OnInsertWithoutNameReference(Eq(""), Eq(""))); // Huffman encoded short strings. - EXPECT_CALL(*delegate(), OnInsertWithoutNameReference("bar", "bar")); + EXPECT_CALL(*delegate(), OnInsertWithoutNameReference(Eq("bar"), Eq("bar"))); // Not Huffman encoded short strings. - EXPECT_CALL(*delegate(), OnInsertWithoutNameReference("foo", "foo")); + EXPECT_CALL(*delegate(), OnInsertWithoutNameReference(Eq("foo"), Eq("foo"))); // Not Huffman encoded long strings; length does not fit on prefix. // 'Z' would be Huffman encoded to 8 bits, so no Huffman encoding is used. - EXPECT_CALL(*delegate(), OnInsertWithoutNameReference(QuicString(31, 'Z'), - QuicString(127, 'Z'))); + EXPECT_CALL(*delegate(), + OnInsertWithoutNameReference(Eq(QuicString(31, 'Z')), + Eq(QuicString(127, 'Z')))); Decode(QuicTextUtils::HexDecode( "4000" @@ -104,7 +105,7 @@ // Name Length value is too large for varint decoder to decode. TEST_F(QpackEncoderStreamReceiverTest, InsertWithoutNameReferenceNameTooLongForVarintDecoder) { - EXPECT_CALL(*delegate(), OnErrorDetected("Encoded integer too large.")); + EXPECT_CALL(*delegate(), OnErrorDetected(Eq("Encoded integer too large."))); Decode(QuicTextUtils::HexDecode("5fffffffffffffffffffff")); } @@ -112,8 +113,7 @@ // Name Length value can be decoded by varint decoder but exceeds 1 MB limit. TEST_F(QpackEncoderStreamReceiverTest, InsertWithoutNameReferenceNameExceedsLimit) { - EXPECT_CALL(*delegate(), - OnErrorDetected(QuicStringPiece("String literal too long."))); + EXPECT_CALL(*delegate(), OnErrorDetected(Eq("String literal too long."))); Decode(QuicTextUtils::HexDecode("5fffff7f")); } @@ -121,7 +121,7 @@ // Value Length value is too large for varint decoder to decode. TEST_F(QpackEncoderStreamReceiverTest, InsertWithoutNameReferenceValueTooLongForVarintDecoder) { - EXPECT_CALL(*delegate(), OnErrorDetected("Encoded integer too large.")); + EXPECT_CALL(*delegate(), OnErrorDetected(Eq("Encoded integer too large."))); Decode(QuicTextUtils::HexDecode("436261727fffffffffffffffffffff")); } @@ -129,7 +129,7 @@ // Value Length value can be decoded by varint decoder but exceeds 1 MB limit. TEST_F(QpackEncoderStreamReceiverTest, InsertWithoutNameReferenceValueExceedsLimit) { - EXPECT_CALL(*delegate(), OnErrorDetected("String literal too long.")); + EXPECT_CALL(*delegate(), OnErrorDetected(Eq("String literal too long."))); Decode(QuicTextUtils::HexDecode("436261727fffff7f")); } @@ -144,22 +144,22 @@ } TEST_F(QpackEncoderStreamReceiverTest, DuplicateIndexTooLarge) { - EXPECT_CALL(*delegate(), OnErrorDetected("Encoded integer too large.")); + EXPECT_CALL(*delegate(), OnErrorDetected(Eq("Encoded integer too large."))); Decode(QuicTextUtils::HexDecode("1fffffffffffffffffffff")); } -TEST_F(QpackEncoderStreamReceiverTest, DynamicTableSizeUpdate) { - // Small max size fits in prefix. - EXPECT_CALL(*delegate(), OnDynamicTableSizeUpdate(17)); - // Large max size requires two extension bytes. - EXPECT_CALL(*delegate(), OnDynamicTableSizeUpdate(500)); +TEST_F(QpackEncoderStreamReceiverTest, SetDynamicTableCapacity) { + // Small capacity fits in prefix. + EXPECT_CALL(*delegate(), OnSetDynamicTableCapacity(17)); + // Large capacity requires two extension bytes. + EXPECT_CALL(*delegate(), OnSetDynamicTableCapacity(500)); Decode(QuicTextUtils::HexDecode("313fd503")); } -TEST_F(QpackEncoderStreamReceiverTest, DynamicTableSizeUpdateMaxSizeTooLarge) { - EXPECT_CALL(*delegate(), OnErrorDetected("Encoded integer too large.")); +TEST_F(QpackEncoderStreamReceiverTest, SetDynamicTableCapacityTooLarge) { + EXPECT_CALL(*delegate(), OnErrorDetected(Eq("Encoded integer too large."))); Decode(QuicTextUtils::HexDecode("3fffffffffffffffffffff")); }
diff --git a/quic/core/qpack/qpack_encoder_stream_sender.cc b/quic/core/qpack/qpack_encoder_stream_sender.cc index c7ee503..fb43046 100644 --- a/quic/core/qpack/qpack_encoder_stream_sender.cc +++ b/quic/core/qpack/qpack_encoder_stream_sender.cc
@@ -33,7 +33,7 @@ instruction_encoder_.Next(std::numeric_limits<size_t>::max(), &output); DCHECK(!instruction_encoder_.HasNext()); - delegate_->Write(output); + delegate_->WriteEncoderStreamData(output); } void QpackEncoderStreamSender::SendInsertWithoutNameReference( @@ -49,7 +49,7 @@ instruction_encoder_.Next(std::numeric_limits<size_t>::max(), &output); DCHECK(!instruction_encoder_.HasNext()); - delegate_->Write(output); + delegate_->WriteEncoderStreamData(output); } void QpackEncoderStreamSender::SendDuplicate(uint64_t index) { @@ -62,20 +62,20 @@ instruction_encoder_.Next(std::numeric_limits<size_t>::max(), &output); DCHECK(!instruction_encoder_.HasNext()); - delegate_->Write(output); + delegate_->WriteEncoderStreamData(output); } -void QpackEncoderStreamSender::SendDynamicTableSizeUpdate(uint64_t max_size) { - instruction_encoder_.set_varint(max_size); +void QpackEncoderStreamSender::SendSetDynamicTableCapacity(uint64_t capacity) { + instruction_encoder_.set_varint(capacity); - instruction_encoder_.Encode(DynamicTableSizeUpdateInstruction()); + instruction_encoder_.Encode(SetDynamicTableCapacityInstruction()); QuicString output; instruction_encoder_.Next(std::numeric_limits<size_t>::max(), &output); DCHECK(!instruction_encoder_.HasNext()); - delegate_->Write(output); + delegate_->WriteEncoderStreamData(output); } } // namespace quic
diff --git a/quic/core/qpack/qpack_encoder_stream_sender.h b/quic/core/qpack/qpack_encoder_stream_sender.h index 0c8d4dd..ad34568 100644 --- a/quic/core/qpack/qpack_encoder_stream_sender.h +++ b/quic/core/qpack/qpack_encoder_stream_sender.h
@@ -22,9 +22,10 @@ virtual ~Delegate() = default; // Encoded |data| is ready to be written on the encoder stream. - // Write() is called exactly once for each instruction, |data| contains the - // entire encoded instruction and it is guaranteed to be not empty. - virtual void Write(QuicStringPiece data) = 0; + // WriteEncoderStreamData() is called exactly once for each instruction. + // |data| contains the entire encoded instruction and it is guaranteed to be + // not empty. + virtual void WriteEncoderStreamData(QuicStringPiece data) = 0; }; explicit QpackEncoderStreamSender(Delegate* delegate); @@ -44,8 +45,8 @@ QuicStringPiece value); // 5.2.3. Duplicate void SendDuplicate(uint64_t index); - // 5.2.4. Dynamic Table Size Update - void SendDynamicTableSizeUpdate(uint64_t max_size); + // 5.2.4. Set Dynamic Table Capacity + void SendSetDynamicTableCapacity(uint64_t capacity); private: Delegate* const delegate_;
diff --git a/quic/core/qpack/qpack_encoder_stream_sender_test.cc b/quic/core/qpack/qpack_encoder_stream_sender_test.cc index 46e5c46..a850f18 100644 --- a/quic/core/qpack/qpack_encoder_stream_sender_test.cc +++ b/quic/core/qpack/qpack_encoder_stream_sender_test.cc
@@ -6,6 +6,7 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "net/third_party/quiche/src/quic/core/qpack/qpack_encoder_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" @@ -16,40 +17,36 @@ namespace test { namespace { -class MockSenderDelegate : public QpackEncoderStreamSender::Delegate { - public: - ~MockSenderDelegate() override = default; - - MOCK_METHOD1(Write, void(QuicStringPiece data)); -}; - class QpackEncoderStreamSenderTest : public QuicTest { protected: QpackEncoderStreamSenderTest() : stream_(&delegate_) {} ~QpackEncoderStreamSenderTest() override = default; - StrictMock<MockSenderDelegate> delegate_; + StrictMock<MockEncoderStreamSenderDelegate> delegate_; QpackEncoderStreamSender stream_; }; TEST_F(QpackEncoderStreamSenderTest, InsertWithNameReference) { // Static, index fits in prefix, empty value. - EXPECT_CALL(delegate_, Write(Eq(QuicTextUtils::HexDecode("c500")))); + EXPECT_CALL(delegate_, + WriteEncoderStreamData(Eq(QuicTextUtils::HexDecode("c500")))); stream_.SendInsertWithNameReference(true, 5, ""); // Static, index fits in prefix, Huffman encoded value. - EXPECT_CALL(delegate_, Write(Eq(QuicTextUtils::HexDecode("c28294e7")))); + EXPECT_CALL(delegate_, + WriteEncoderStreamData(Eq(QuicTextUtils::HexDecode("c28294e7")))); stream_.SendInsertWithNameReference(true, 2, "foo"); // Not static, index does not fit in prefix, not Huffman encoded value. - EXPECT_CALL(delegate_, Write(Eq(QuicTextUtils::HexDecode("bf4a03626172")))); + EXPECT_CALL(delegate_, WriteEncoderStreamData( + Eq(QuicTextUtils::HexDecode("bf4a03626172")))); stream_.SendInsertWithNameReference(false, 137, "bar"); // Value length does not fit in prefix. // 'Z' would be Huffman encoded to 8 bits, so no Huffman encoding is used. EXPECT_CALL( delegate_, - Write(Eq(QuicTextUtils::HexDecode( + WriteEncoderStreamData(Eq(QuicTextUtils::HexDecode( "aa7f005a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a" "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a" "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a" @@ -59,23 +56,25 @@ TEST_F(QpackEncoderStreamSenderTest, InsertWithoutNameReference) { // Empty name and value. - EXPECT_CALL(delegate_, Write(Eq(QuicTextUtils::HexDecode("4000")))); + EXPECT_CALL(delegate_, + WriteEncoderStreamData(Eq(QuicTextUtils::HexDecode("4000")))); stream_.SendInsertWithoutNameReference("", ""); // Huffman encoded short strings. - EXPECT_CALL(delegate_, - Write(Eq(QuicTextUtils::HexDecode("4362617203626172")))); + EXPECT_CALL(delegate_, WriteEncoderStreamData( + Eq(QuicTextUtils::HexDecode("4362617203626172")))); stream_.SendInsertWithoutNameReference("bar", "bar"); // Not Huffman encoded short strings. - EXPECT_CALL(delegate_, Write(Eq(QuicTextUtils::HexDecode("6294e78294e7")))); + EXPECT_CALL(delegate_, WriteEncoderStreamData( + Eq(QuicTextUtils::HexDecode("6294e78294e7")))); stream_.SendInsertWithoutNameReference("foo", "foo"); // Not Huffman encoded long strings; length does not fit on prefix. // 'Z' would be Huffman encoded to 8 bits, so no Huffman encoding is used. EXPECT_CALL( delegate_, - Write(Eq(QuicTextUtils::HexDecode( + WriteEncoderStreamData(Eq(QuicTextUtils::HexDecode( "5f005a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a7f" "005a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a" "5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a" @@ -87,22 +86,26 @@ TEST_F(QpackEncoderStreamSenderTest, Duplicate) { // Small index fits in prefix. - EXPECT_CALL(delegate_, Write(Eq(QuicTextUtils::HexDecode("11")))); + EXPECT_CALL(delegate_, + WriteEncoderStreamData(Eq(QuicTextUtils::HexDecode("11")))); stream_.SendDuplicate(17); // Large index requires two extension bytes. - EXPECT_CALL(delegate_, Write(Eq(QuicTextUtils::HexDecode("1fd503")))); + EXPECT_CALL(delegate_, + WriteEncoderStreamData(Eq(QuicTextUtils::HexDecode("1fd503")))); stream_.SendDuplicate(500); } -TEST_F(QpackEncoderStreamSenderTest, DynamicTableSizeUpdate) { - // Small max size fits in prefix. - EXPECT_CALL(delegate_, Write(Eq(QuicTextUtils::HexDecode("31")))); - stream_.SendDynamicTableSizeUpdate(17); +TEST_F(QpackEncoderStreamSenderTest, SetDynamicTableCapacity) { + // Small capacity fits in prefix. + EXPECT_CALL(delegate_, + WriteEncoderStreamData(Eq(QuicTextUtils::HexDecode("31")))); + stream_.SendSetDynamicTableCapacity(17); - // Large max size requires two extension bytes. - EXPECT_CALL(delegate_, Write(Eq(QuicTextUtils::HexDecode("3fd503")))); - stream_.SendDynamicTableSizeUpdate(500); + // Large capacity requires two extension bytes. + EXPECT_CALL(delegate_, + WriteEncoderStreamData(Eq(QuicTextUtils::HexDecode("3fd503")))); + stream_.SendSetDynamicTableCapacity(500); } } // namespace
diff --git a/quic/core/qpack/qpack_encoder_test.cc b/quic/core/qpack/qpack_encoder_test.cc index 04e4dd6..e3dba00 100644 --- a/quic/core/qpack/qpack_encoder_test.cc +++ b/quic/core/qpack/qpack_encoder_test.cc
@@ -11,6 +11,7 @@ #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; using ::testing::Values; @@ -153,7 +154,7 @@ TEST_P(QpackEncoderTest, DecoderStreamError) { EXPECT_CALL(decoder_stream_error_delegate_, - OnError("Encoded integer too large.")); + OnDecoderStreamError(Eq("Encoded integer too large."))); QpackEncoder encoder(&decoder_stream_error_delegate_, &encoder_stream_sender_delegate_);
diff --git a/quic/core/qpack/qpack_encoder_test_utils.cc b/quic/core/qpack/qpack_encoder_test_utils.cc index 606db4e..b9a3263 100644 --- a/quic/core/qpack/qpack_encoder_test_utils.cc +++ b/quic/core/qpack/qpack_encoder_test_utils.cc
@@ -9,9 +9,11 @@ namespace quic { namespace test { -void NoopDecoderStreamErrorDelegate::OnError(QuicStringPiece error_message) {} +void NoopDecoderStreamErrorDelegate::OnDecoderStreamError( + QuicStringPiece error_message) {} -void NoopEncoderStreamSenderDelegate::Write(QuicStringPiece data) {} +void NoopEncoderStreamSenderDelegate::WriteEncoderStreamData( + QuicStringPiece data) {} QuicString QpackEncode( QpackEncoder::DecoderStreamErrorDelegate* decoder_stream_error_delegate,
diff --git a/quic/core/qpack/qpack_encoder_test_utils.h b/quic/core/qpack/qpack_encoder_test_utils.h index b000868..03d05cb 100644 --- a/quic/core/qpack/qpack_encoder_test_utils.h +++ b/quic/core/qpack/qpack_encoder_test_utils.h
@@ -21,7 +21,7 @@ public: ~NoopDecoderStreamErrorDelegate() override = default; - void OnError(QuicStringPiece error_message) override; + void OnDecoderStreamError(QuicStringPiece error_message) override; }; // Mock QpackEncoder::DecoderStreamErrorDelegate implementation. @@ -30,7 +30,7 @@ public: ~MockDecoderStreamErrorDelegate() override = default; - MOCK_METHOD1(OnError, void(QuicStringPiece error_message)); + MOCK_METHOD1(OnDecoderStreamError, void(QuicStringPiece error_message)); }; // QpackEncoderStreamSender::Delegate implementation that does nothing. @@ -39,7 +39,16 @@ public: ~NoopEncoderStreamSenderDelegate() override = default; - void Write(QuicStringPiece data) override; + void WriteEncoderStreamData(QuicStringPiece data) override; +}; + +// Mock QpackEncoderStreamSender::Delegate implementation. +class MockEncoderStreamSenderDelegate + : public QpackEncoderStreamSender::Delegate { + public: + ~MockEncoderStreamSenderDelegate() override = default; + + MOCK_METHOD1(WriteEncoderStreamData, void(QuicStringPiece data)); }; QuicString QpackEncode(
diff --git a/quic/core/qpack/qpack_header_table.cc b/quic/core/qpack/qpack_header_table.cc index 4a4c9fa..4ba3ee3 100644 --- a/quic/core/qpack/qpack_header_table.cc +++ b/quic/core/qpack/qpack_header_table.cc
@@ -143,12 +143,12 @@ return new_entry; } -bool QpackHeaderTable::UpdateTableSize(uint64_t max_size) { - if (max_size > maximum_dynamic_table_capacity_) { +bool QpackHeaderTable::SetDynamicTableCapacity(uint64_t capacity) { + if (capacity > maximum_dynamic_table_capacity_) { return false; } - dynamic_table_capacity_ = max_size; + dynamic_table_capacity_ = capacity; EvictDownToCurrentCapacity(); DCHECK_LE(dynamic_table_size_, dynamic_table_capacity_);
diff --git a/quic/core/qpack/qpack_header_table.h b/quic/core/qpack/qpack_header_table.h index b98e7eb..eda7ab5 100644 --- a/quic/core/qpack/qpack_header_table.h +++ b/quic/core/qpack/qpack_header_table.h
@@ -56,9 +56,9 @@ // is larger than the capacity of the dynamic table. const QpackEntry* InsertEntry(QuicStringPiece name, QuicStringPiece value); - // Change dynamic table capacity to |max_size|. Returns true on success. - // Returns false is |max_size| exceeds maximum dynamic table capacity. - bool UpdateTableSize(uint64_t max_size); + // Change dynamic table capacity to |capacity|. Returns true on success. + // Returns false is |capacity| exceeds maximum dynamic table capacity. + bool SetDynamicTableCapacity(uint64_t capacity); // Set |maximum_dynamic_table_capacity_|. The initial value is zero. The // final value is determined by the decoder and is sent to the encoder as @@ -68,7 +68,7 @@ // This method must only be called at most once. void SetMaximumDynamicTableCapacity(uint64_t maximum_dynamic_table_capacity); - // Used by request streams to decode Largest Reference. + // Used on request streams to encode and decode Required Insert Count. uint64_t max_entries() const { return max_entries_; } // The number of entries inserted to the dynamic table (including ones that
diff --git a/quic/core/qpack/qpack_header_table_test.cc b/quic/core/qpack/qpack_header_table_test.cc index 95df41d..f3ac5b5 100644 --- a/quic/core/qpack/qpack_header_table_test.cc +++ b/quic/core/qpack/qpack_header_table_test.cc
@@ -6,7 +6,6 @@ #include "testing/gtest/include/gtest/gtest.h" #include "net/third_party/quiche/src/quic/core/qpack/qpack_static_table.h" -#include "net/third_party/quiche/src/quic/core/qpack/qpack_test_utils.h" #include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h" #include "net/third_party/quiche/src/quic/platform/api/quic_test.h" #include "net/third_party/quiche/src/spdy/core/hpack/hpack_entry.h" @@ -76,8 +75,8 @@ EXPECT_FALSE(table_.InsertEntry(name, value)); } - bool UpdateTableSize(uint64_t max_size) { - return table_.UpdateTableSize(max_size); + bool SetDynamicTableCapacity(uint64_t capacity) { + return table_.SetDynamicTableCapacity(capacity); } uint64_t max_entries() const { return table_.max_entries(); } @@ -237,20 +236,21 @@ EXPECT_EQ(15u, table2.max_entries()); } -TEST_F(QpackHeaderTableTest, UpdateTableSize) { +TEST_F(QpackHeaderTableTest, SetDynamicTableCapacity) { // Dynamic table capacity does not affect MaxEntries. - EXPECT_TRUE(UpdateTableSize(1024)); + EXPECT_TRUE(SetDynamicTableCapacity(1024)); EXPECT_EQ(32u * 1024, max_entries()); - EXPECT_TRUE(UpdateTableSize(500)); + EXPECT_TRUE(SetDynamicTableCapacity(500)); EXPECT_EQ(32u * 1024, max_entries()); // Dynamic table capacity cannot exceed maximum dynamic table capacity. - EXPECT_FALSE(UpdateTableSize(2 * kMaximumDynamicTableCapacityForTesting)); + EXPECT_FALSE( + SetDynamicTableCapacity(2 * kMaximumDynamicTableCapacityForTesting)); } TEST_F(QpackHeaderTableTest, EvictByInsertion) { - EXPECT_TRUE(UpdateTableSize(40)); + EXPECT_TRUE(SetDynamicTableCapacity(40)); // Entry size is 3 + 3 + 32 = 38. InsertEntry("foo", "bar"); @@ -285,7 +285,7 @@ ExpectMatch("baz", "qux", QpackHeaderTable::MatchType::kNameAndValue, /* expected_is_static = */ false, 1u); - EXPECT_TRUE(UpdateTableSize(40)); + EXPECT_TRUE(SetDynamicTableCapacity(40)); EXPECT_EQ(2u, inserted_entry_count()); EXPECT_EQ(1u, dropped_entry_count()); @@ -293,7 +293,7 @@ ExpectMatch("baz", "qux", QpackHeaderTable::MatchType::kNameAndValue, /* expected_is_static = */ false, 1u); - EXPECT_TRUE(UpdateTableSize(20)); + EXPECT_TRUE(SetDynamicTableCapacity(20)); EXPECT_EQ(2u, inserted_entry_count()); EXPECT_EQ(2u, dropped_entry_count()); @@ -302,7 +302,7 @@ } TEST_F(QpackHeaderTableTest, EvictOldestOfIdentical) { - EXPECT_TRUE(UpdateTableSize(80)); + EXPECT_TRUE(SetDynamicTableCapacity(80)); // Entry size is 3 + 3 + 32 = 38. // Insert same entry twice. @@ -327,7 +327,7 @@ } TEST_F(QpackHeaderTableTest, EvictOldestOfSameName) { - EXPECT_TRUE(UpdateTableSize(80)); + EXPECT_TRUE(SetDynamicTableCapacity(80)); // Entry size is 3 + 3 + 32 = 38. // Insert two entries with same name but different values.
diff --git a/quic/core/qpack/qpack_instruction_decoder.cc b/quic/core/qpack/qpack_instruction_decoder.cc index 9623dfb..dbb2076 100644 --- a/quic/core/qpack/qpack_instruction_decoder.cc +++ b/quic/core/qpack/qpack_instruction_decoder.cc
@@ -4,6 +4,9 @@ #include "net/third_party/quiche/src/quic/core/qpack/qpack_instruction_decoder.h" +#include <algorithm> +#include <utility> + #include "base/logging.h" namespace quic {
diff --git a/quic/core/qpack/qpack_instruction_decoder_test.cc b/quic/core/qpack/qpack_instruction_decoder_test.cc index 99be5a0..d1fe9b5 100644 --- a/quic/core/qpack/qpack_instruction_decoder_test.cc +++ b/quic/core/qpack/qpack_instruction_decoder_test.cc
@@ -4,6 +4,8 @@ #include "net/third_party/quiche/src/quic/core/qpack/qpack_instruction_decoder.h" +#include <algorithm> + #include "base/logging.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -13,6 +15,7 @@ #include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h" using ::testing::_; +using ::testing::Eq; using ::testing::Expectation; using ::testing::Return; using ::testing::StrictMock; @@ -140,14 +143,12 @@ } TEST_P(QpackInstructionDecoderTest, InvalidHuffmanEncoding) { - EXPECT_CALL(delegate_, - OnError(QuicStringPiece("Error in Huffman-encoded string."))); + EXPECT_CALL(delegate_, OnError(Eq("Error in Huffman-encoded string."))); decoder_.Decode(QuicTextUtils::HexDecode("c1ff")); } TEST_P(QpackInstructionDecoderTest, InvalidVarintEncoding) { - EXPECT_CALL(delegate_, - OnError(QuicStringPiece("Encoded integer too large."))); + EXPECT_CALL(delegate_, OnError(Eq("Encoded integer too large."))); decoder_.Decode(QuicTextUtils::HexDecode("ffffffffffffffffffffff")); }
diff --git a/quic/core/qpack/qpack_progressive_decoder.cc b/quic/core/qpack/qpack_progressive_decoder.cc index 409c910..430e707 100644 --- a/quic/core/qpack/qpack_progressive_decoder.cc +++ b/quic/core/qpack/qpack_progressive_decoder.cc
@@ -4,6 +4,9 @@ #include "net/third_party/quiche/src/quic/core/qpack/qpack_progressive_decoder.h" +#include <algorithm> +#include <limits> + #include "base/logging.h" #include "net/third_party/quiche/src/quic/core/qpack/qpack_constants.h" #include "net/third_party/quiche/src/quic/core/qpack/qpack_header_table.h" @@ -23,21 +26,21 @@ header_table_(header_table), decoder_stream_sender_(decoder_stream_sender), handler_(handler), - largest_reference_(0), - base_index_(0), - largest_reference_seen_(0), + required_insert_count_(0), + base_(0), + required_insert_count_so_far_(0), prefix_decoded_(false), decoding_(true), error_detected_(false) {} // static -bool QpackProgressiveDecoder::DecodeLargestReference( - uint64_t wire_largest_reference, +bool QpackProgressiveDecoder::DecodeRequiredInsertCount( + uint64_t encoded_required_insert_count, uint64_t max_entries, uint64_t total_number_of_inserts, - uint64_t* largest_reference) { - if (wire_largest_reference == 0) { - *largest_reference = 0; + uint64_t* required_insert_count) { + if (encoded_required_insert_count == 0) { + *required_insert_count = 0; return true; } @@ -45,37 +48,37 @@ // precluding all calculations in this method from overflowing. DCHECK_LE(max_entries, std::numeric_limits<uint64_t>::max() / 32); - if (wire_largest_reference > 2 * max_entries) { + if (encoded_required_insert_count > 2 * max_entries) { return false; } - *largest_reference = wire_largest_reference - 1; - DCHECK_LT(*largest_reference, std::numeric_limits<uint64_t>::max() / 16); + *required_insert_count = encoded_required_insert_count - 1; + DCHECK_LT(*required_insert_count, std::numeric_limits<uint64_t>::max() / 16); uint64_t current_wrapped = total_number_of_inserts % (2 * max_entries); DCHECK_LT(current_wrapped, std::numeric_limits<uint64_t>::max() / 16); - if (current_wrapped >= *largest_reference + max_entries) { - // Largest Reference wrapped around 1 extra time. - *largest_reference += 2 * max_entries; - } else if (current_wrapped + max_entries < *largest_reference) { + if (current_wrapped >= *required_insert_count + max_entries) { + // Required Insert Count wrapped around 1 extra time. + *required_insert_count += 2 * max_entries; + } else if (current_wrapped + max_entries < *required_insert_count) { // Decoder wrapped around 1 extra time. current_wrapped += 2 * max_entries; } - if (*largest_reference > + if (*required_insert_count > std::numeric_limits<uint64_t>::max() - total_number_of_inserts) { return false; } - *largest_reference += total_number_of_inserts; + *required_insert_count += total_number_of_inserts; - // Prevent underflow, but also disallow invalid value 0 for Largest Reference. - if (current_wrapped >= *largest_reference) { + // Prevent underflow, also disallow invalid value 0 for Required Insert Count. + if (current_wrapped >= *required_insert_count) { return false; } - *largest_reference -= current_wrapped; + *required_insert_count -= current_wrapped; return true; } @@ -118,8 +121,8 @@ return; } - if (largest_reference_ != largest_reference_seen_) { - OnError("Largest Reference too large."); + if (required_insert_count_ != required_insert_count_so_far_) { + OnError("Required Insert Count too large."); return; } @@ -164,17 +167,17 @@ return false; } - if (absolute_index > largest_reference_) { - OnError("Index larger than Largest Reference."); + if (absolute_index >= required_insert_count_) { + OnError("Absolute Index must be smaller than Required Insert Count."); return false; } - largest_reference_seen_ = std::max(largest_reference_seen_, absolute_index); + DCHECK_LT(absolute_index, std::numeric_limits<uint64_t>::max()); + required_insert_count_so_far_ = + std::max(required_insert_count_so_far_, absolute_index + 1); - DCHECK_NE(0u, absolute_index); - const uint64_t real_index = absolute_index - 1; auto entry = - header_table_->LookupEntry(/* is_static = */ false, real_index); + header_table_->LookupEntry(/* is_static = */ false, absolute_index); if (!entry) { OnError("Dynamic table entry not found."); return false; @@ -203,16 +206,17 @@ return false; } - if (absolute_index > largest_reference_) { - OnError("Index larger than Largest Reference."); + if (absolute_index >= required_insert_count_) { + OnError("Absolute Index must be smaller than Required Insert Count."); return false; } - largest_reference_seen_ = std::max(largest_reference_seen_, absolute_index); + DCHECK_LT(absolute_index, std::numeric_limits<uint64_t>::max()); + required_insert_count_so_far_ = + std::max(required_insert_count_so_far_, absolute_index + 1); - DCHECK_NE(0u, absolute_index); - const uint64_t real_index = absolute_index - 1; - auto entry = header_table_->LookupEntry(/* is_static = */ false, real_index); + auto entry = + header_table_->LookupEntry(/* is_static = */ false, absolute_index); if (!entry) { OnError("Dynamic table entry not found."); return false; @@ -231,17 +235,17 @@ return false; } - if (absolute_index > largest_reference_) { - OnError("Index larger than Largest Reference."); + if (absolute_index >= required_insert_count_) { + OnError("Absolute Index must be smaller than Required Insert Count."); return false; } - largest_reference_seen_ = std::max(largest_reference_seen_, absolute_index); + DCHECK_LT(absolute_index, std::numeric_limits<uint64_t>::max()); + required_insert_count_so_far_ = + std::max(required_insert_count_so_far_, absolute_index + 1); - DCHECK_NE(0u, absolute_index); - const uint64_t real_index = absolute_index - 1; auto entry = - header_table_->LookupEntry(/* is_static = */ false, real_index); + header_table_->LookupEntry(/* is_static = */ false, absolute_index); if (!entry) { OnError("Dynamic table entry not found."); return false; @@ -270,16 +274,17 @@ return false; } - if (absolute_index > largest_reference_) { - OnError("Index larger than Largest Reference."); + if (absolute_index >= required_insert_count_) { + OnError("Absolute Index must be smaller than Required Insert Count."); return false; } - largest_reference_seen_ = std::max(largest_reference_seen_, absolute_index); + DCHECK_LT(absolute_index, std::numeric_limits<uint64_t>::max()); + required_insert_count_so_far_ = + std::max(required_insert_count_so_far_, absolute_index + 1); - DCHECK_NE(0u, absolute_index); - const uint64_t real_index = absolute_index - 1; - auto entry = header_table_->LookupEntry(/* is_static = */ false, real_index); + auto entry = + header_table_->LookupEntry(/* is_static = */ false, absolute_index); if (!entry) { OnError("Dynamic table entry not found."); return false; @@ -299,17 +304,17 @@ bool QpackProgressiveDecoder::DoPrefixInstruction() { DCHECK(!prefix_decoded_); - if (!DecodeLargestReference( + if (!DecodeRequiredInsertCount( prefix_decoder_->varint(), header_table_->max_entries(), - header_table_->inserted_entry_count(), &largest_reference_)) { - OnError("Error decoding Largest Reference."); + header_table_->inserted_entry_count(), &required_insert_count_)) { + OnError("Error decoding Required Insert Count."); return false; } const bool sign = prefix_decoder_->s_bit(); - const uint64_t delta_base_index = prefix_decoder_->varint2(); - if (!DeltaBaseIndexToBaseIndex(sign, delta_base_index, &base_index_)) { - OnError("Error calculating Base Index."); + const uint64_t delta_base = prefix_decoder_->varint2(); + if (!DeltaBaseToBase(sign, delta_base, &base_)) { + OnError("Error calculating Base."); return false; } @@ -318,24 +323,23 @@ return true; } -bool QpackProgressiveDecoder::DeltaBaseIndexToBaseIndex( - bool sign, - uint64_t delta_base_index, - uint64_t* base_index) { +bool QpackProgressiveDecoder::DeltaBaseToBase(bool sign, + uint64_t delta_base, + uint64_t* base) { if (sign) { - if (delta_base_index == std::numeric_limits<uint64_t>::max() || - largest_reference_ < delta_base_index + 1) { + if (delta_base == std::numeric_limits<uint64_t>::max() || + required_insert_count_ < delta_base + 1) { return false; } - *base_index = largest_reference_ - delta_base_index - 1; + *base = required_insert_count_ - delta_base - 1; return true; } - if (delta_base_index > - std::numeric_limits<uint64_t>::max() - largest_reference_) { + if (delta_base > + std::numeric_limits<uint64_t>::max() - required_insert_count_) { return false; } - *base_index = largest_reference_ + delta_base_index; + *base = required_insert_count_ + delta_base; return true; } @@ -343,22 +347,22 @@ uint64_t relative_index, uint64_t* absolute_index) const { if (relative_index == std::numeric_limits<uint64_t>::max() || - relative_index + 1 > base_index_) { + relative_index + 1 > base_) { return false; } - *absolute_index = base_index_ - relative_index; + *absolute_index = base_ - 1 - relative_index; return true; } bool QpackProgressiveDecoder::PostBaseIndexToAbsoluteIndex( uint64_t post_base_index, uint64_t* absolute_index) const { - if (post_base_index >= std::numeric_limits<uint64_t>::max() - base_index_) { + if (post_base_index >= std::numeric_limits<uint64_t>::max() - base_) { return false; } - *absolute_index = base_index_ + post_base_index + 1; + *absolute_index = base_ + post_base_index; return true; }
diff --git a/quic/core/qpack/qpack_progressive_decoder.h b/quic/core/qpack/qpack_progressive_decoder.h index 7524411..7988861 100644 --- a/quic/core/qpack/qpack_progressive_decoder.h +++ b/quic/core/qpack/qpack_progressive_decoder.h
@@ -56,14 +56,14 @@ QpackProgressiveDecoder& operator=(const QpackProgressiveDecoder&) = delete; ~QpackProgressiveDecoder() override = default; - // Calculate actual Largest Reference from largest reference value sent on - // wire, MaxEntries, and total number of dynamic table insertions according to - // https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#largest-reference + // Calculate Required Insert Count from Encoded Required Insert Count, + // MaxEntries, and total number of dynamic table insertions according to + // https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#ric. // Returns true on success, false on invalid input or overflow/underflow. - static bool DecodeLargestReference(uint64_t wire_largest_reference, - uint64_t max_entries, - uint64_t total_number_of_inserts, - uint64_t* largest_reference); + static bool DecodeRequiredInsertCount(uint64_t encoded_required_insert_count, + uint64_t max_entries, + uint64_t total_number_of_inserts, + uint64_t* required_insert_count); // Provide a data fragment to decode. void Decode(QuicStringPiece data); @@ -84,19 +84,18 @@ bool DoLiteralHeaderFieldInstruction(); bool DoPrefixInstruction(); - // Calculates Base Index from |largest_reference_|, which must be set before - // calling this method, and sign bit and Delta Base Index in the Header Data - // Prefix, which are passed in as arguments. Returns true on success, false - // on failure due to overflow/underflow. - bool DeltaBaseIndexToBaseIndex(bool sign, - uint64_t delta_base_index, - uint64_t* base_index); + // Calculates Base from |required_insert_count_|, which must be set before + // calling this method, and sign bit and Delta Base in the Header Data Prefix, + // which are passed in as arguments. Returns true on success, false on + // failure due to overflow/underflow. + bool DeltaBaseToBase(bool sign, uint64_t delta_base, uint64_t* base); // The request stream can use relative index (but different from the kind of // relative index used on the encoder stream), and post-base index. // These methods convert relative index and post-base index to absolute index // (one based). They return true on success, or false if conversion fails due - // to overflow/underflow. + // to overflow/underflow. On success, |*absolute_index| is guaranteed to be + // strictly less than std::numeric_limits<uint64_t>::max(). bool RequestStreamRelativeIndexToAbsoluteIndex( uint64_t relative_index, uint64_t* absolute_index) const; @@ -115,14 +114,16 @@ QpackDecoderStreamSender* const decoder_stream_sender_; HeadersHandlerInterface* const handler_; - // Largest Reference and Base Index are parsed from the Header Data Prefix. - // They are both absolute indices, that is, one based. - uint64_t largest_reference_; - uint64_t base_index_; + // Required Insert Count and Base are decoded from the Header Data Prefix. + uint64_t required_insert_count_; + uint64_t base_; - // Keep track of largest reference seen in this header block. - // After decoding is completed, this can be compared to |largest_reference_|. - uint64_t largest_reference_seen_; + // Required Insert Count is one larger than the largest absolute index of all + // referenced dynamic table entries, or zero if no dynamic table entries are + // referenced. |required_insert_count_so_far_| starts out as zero and keeps + // track of the Required Insert Count based on entries decoded so far. + // After decoding is completed, it is compared to |required_insert_count_|. + uint64_t required_insert_count_so_far_; // False until prefix is fully read and decoded. bool prefix_decoded_;
diff --git a/quic/core/qpack/qpack_progressive_decoder_test.cc b/quic/core/qpack/qpack_progressive_decoder_test.cc index c1722e5..b306702 100644 --- a/quic/core/qpack/qpack_progressive_decoder_test.cc +++ b/quic/core/qpack/qpack_progressive_decoder_test.cc
@@ -11,12 +11,12 @@ namespace test { namespace { -// For testing valid decodings, the encoded (wire) largest reference value is -// calculated for actual Largest Reference values, so that there is an expected -// value to comparte the decoded value against, and so that intricate -// inequalities can be documented. +// For testing valid decodings, the Encoded Required Insert Count is calculated +// from Required Insert Count, so that there is an expected value to compare +// the decoded value against, and so that intricate inequalities can be +// documented. struct { - uint64_t largest_reference; + uint64_t required_insert_count; uint64_t max_entries; uint64_t total_number_of_inserts; } kTestData[] = { @@ -25,70 +25,72 @@ // No dynamic entries in header. {0, 100, 0}, {0, 100, 500}, - // Largest Reference has not wrapped around yet, no entries evicted. + // Required Insert Count has not wrapped around yet, no entries evicted. {15, 100, 25}, {20, 100, 10}, - // Largest Reference has not wrapped around yet, some entries evicted. + // Required Insert Count has not wrapped around yet, some entries evicted. {90, 100, 110}, - // Largest Reference has wrapped around. + // Required Insert Count has wrapped around. {234, 100, 180}, - // Largest Reference has wrapped around many times. + // Required Insert Count has wrapped around many times. {5678, 100, 5701}, - // Lowest and highest possible Largest Reference values + // Lowest and highest possible Required Insert Count values // for given MaxEntries and total number of insertions. {401, 100, 500}, {600, 100, 500}}; -uint64_t EncodeLargestReference(uint64_t largest_reference, - uint64_t max_entries) { - if (largest_reference == 0) { +uint64_t EncodeRequiredInsertCount(uint64_t required_insert_count, + uint64_t max_entries) { + if (required_insert_count == 0) { return 0; } - return largest_reference % (2 * max_entries) + 1; + return required_insert_count % (2 * max_entries) + 1; } -TEST(QpackProgressiveDecoderTest, DecodeLargestReference) { +TEST(QpackProgressiveDecoderTest, DecodeRequiredInsertCount) { for (size_t i = 0; i < QUIC_ARRAYSIZE(kTestData); ++i) { - const uint64_t largest_reference = kTestData[i].largest_reference; + const uint64_t required_insert_count = kTestData[i].required_insert_count; const uint64_t max_entries = kTestData[i].max_entries; const uint64_t total_number_of_inserts = kTestData[i].total_number_of_inserts; - if (largest_reference != 0) { + if (required_insert_count != 0) { // Dynamic entries cannot be referenced if dynamic table capacity is zero. ASSERT_LT(0u, max_entries) << i; - // Entry |total_number_of_inserts - max_entries| and earlier entries are - // evicted. Entry |largest_reference| is referenced. No evicted entry - // can be referenced. - ASSERT_LT(total_number_of_inserts, largest_reference + max_entries) << i; - // Entry |largest_reference - max_entries| and earlier entries are - // evicted, entry |total_number_of_inserts| is the last acknowledged + // Entry |total_number_of_inserts - 1 - max_entries| and earlier entries + // are evicted. Entry |required_insert_count - 1| is referenced. No + // evicted entry can be referenced. + ASSERT_LT(total_number_of_inserts, required_insert_count + max_entries) + << i; + // Entry |required_insert_count - 1 - max_entries| and earlier entries are + // evicted, entry |total_number_of_inserts - 1| is the last acknowledged // entry. Every evicted entry must be acknowledged. - ASSERT_LE(largest_reference, total_number_of_inserts + max_entries) << i; + ASSERT_LE(required_insert_count, total_number_of_inserts + max_entries) + << i; } - uint64_t wire_largest_reference = - EncodeLargestReference(largest_reference, max_entries); + uint64_t encoded_required_insert_count = + EncodeRequiredInsertCount(required_insert_count, max_entries); // Initialize to a value different from the expected output to confirm that - // DecodeLargestReference() modifies the value of - // |decoded_largest_reference|. - uint64_t decoded_largest_reference = largest_reference + 1; - EXPECT_TRUE(QpackProgressiveDecoder::DecodeLargestReference( - wire_largest_reference, max_entries, total_number_of_inserts, - &decoded_largest_reference)) + // DecodeRequiredInsertCount() modifies the value of + // |decoded_required_insert_count|. + uint64_t decoded_required_insert_count = required_insert_count + 1; + EXPECT_TRUE(QpackProgressiveDecoder::DecodeRequiredInsertCount( + encoded_required_insert_count, max_entries, total_number_of_inserts, + &decoded_required_insert_count)) << i; - EXPECT_EQ(decoded_largest_reference, largest_reference) << i; + EXPECT_EQ(decoded_required_insert_count, required_insert_count) << i; } } -// Failures are tested with hardcoded values for the on-the-wire largest -// reference field, to provide test coverage for values that would never be -// produced by a well behaved encoding function. +// Failures are tested with hardcoded values for encoded required insert count, +// to provide test coverage for values that would never be produced by a well +// behaved encoding function. struct { - uint64_t wire_largest_reference; + uint64_t encoded_required_insert_count; uint64_t max_entries; uint64_t total_number_of_inserts; } kInvalidTestData[] = { @@ -100,19 +102,19 @@ // https://github.com/quicwg/base-drafts/issues/2112#issue-389626872. {1, 10, 2}, {18, 10, 2}, - // Largest Reference value too small or too large + // Encoded Required Insert Count value too small or too large // for given MaxEntries and total number of insertions. {400, 100, 500}, {601, 100, 500}}; -TEST(QpackProgressiveDecoderTest, DecodeLargestReferenceError) { +TEST(QpackProgressiveDecoderTest, DecodeRequiredInsertCountError) { for (size_t i = 0; i < QUIC_ARRAYSIZE(kInvalidTestData); ++i) { - uint64_t decoded_largest_reference = 0; - EXPECT_FALSE(QpackProgressiveDecoder::DecodeLargestReference( - kInvalidTestData[i].wire_largest_reference, + uint64_t decoded_required_insert_count = 0; + EXPECT_FALSE(QpackProgressiveDecoder::DecodeRequiredInsertCount( + kInvalidTestData[i].encoded_required_insert_count, kInvalidTestData[i].max_entries, kInvalidTestData[i].total_number_of_inserts, - &decoded_largest_reference)) + &decoded_required_insert_count)) << i; } }
diff --git a/quic/core/qpack/qpack_progressive_encoder.cc b/quic/core/qpack/qpack_progressive_encoder.cc index 4d2a3cf..41433ff 100644 --- a/quic/core/qpack/qpack_progressive_encoder.cc +++ b/quic/core/qpack/qpack_progressive_encoder.cc
@@ -48,8 +48,8 @@ DCHECK_LT(output->size(), max_length); if (!prefix_encoded_ && !instruction_encoder_.HasNext()) { - // TODO(bnc): Implement dynamic entries and set Largest Reference and - // Delta Base Index accordingly. + // TODO(bnc): Implement dynamic entries and set Required Insert Count and + // Delta Base accordingly. instruction_encoder_.set_varint(0); instruction_encoder_.set_varint2(0); instruction_encoder_.set_s_bit(false);
diff --git a/quic/core/quic_buffered_packet_store_test.cc b/quic/core/quic_buffered_packet_store_test.cc index 027a26c..e214ff1 100644 --- a/quic/core/quic_buffered_packet_store_test.cc +++ b/quic/core/quic_buffered_packet_store_test.cc
@@ -6,6 +6,7 @@ #include <list> +#include "net/third_party/quiche/src/quic/core/quic_versions.h" #include "net/third_party/quiche/src/quic/platform/api/quic_flags.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" @@ -53,7 +54,7 @@ packet_content_("some encrypted content"), packet_time_(QuicTime::Zero() + QuicTime::Delta::FromMicroseconds(42)), packet_(packet_content_.data(), packet_content_.size(), packet_time_), - invalid_version_(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED), + invalid_version_(UnsupportedQuicVersion()), valid_version_(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_44) {} protected:
diff --git a/quic/core/quic_connection.cc b/quic/core/quic_connection.cc index f3a6767..d4c13c4 100644 --- a/quic/core/quic_connection.cc +++ b/quic/core/quic_connection.cc
@@ -23,6 +23,7 @@ #include "net/third_party/quiche/src/quic/core/quic_config.h" #include "net/third_party/quiche/src/quic/core/quic_packet_generator.h" #include "net/third_party/quiche/src/quic/core/quic_pending_retransmission.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_bug_tracker.h" #include "net/third_party/quiche/src/quic/platform/api/quic_exported_stats.h" @@ -42,10 +43,6 @@ namespace { -// The largest gap in packets we'll accept without closing the connection. -// This will likely have to be tuned. -const QuicPacketNumber kMaxPacketGap = 5000; - // 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; @@ -74,7 +71,7 @@ const int kMinReleaseTimeIntoFutureMs = 1; bool Near(QuicPacketNumber a, QuicPacketNumber b) { - QuicPacketNumber delta = (a > b) ? a - b : b - a; + QuicPacketCount delta = (a > b) ? a - b : b - a; return delta <= kMaxPacketGap; } @@ -244,15 +241,12 @@ peer_address_(initial_peer_address), direct_peer_address_(initial_peer_address), active_effective_peer_migration_type_(NO_CHANGE), - highest_packet_sent_before_effective_peer_migration_(0), last_packet_decrypted_(false), last_size_(0), current_packet_data_(nullptr), last_decrypted_packet_level_(ENCRYPTION_NONE), should_last_packet_instigate_acks_(false), was_last_packet_missing_(false), - largest_seen_packet_with_ack_(0), - largest_seen_packet_with_stop_waiting_(0), max_undecryptable_packets_(0), max_tracked_packets_(kMaxTrackedPackets), pending_version_negotiation_packet_(false), @@ -344,10 +338,9 @@ processing_ack_frame_(false), supports_release_time_(false), release_time_into_future_(QuicTime::Delta::Zero()), - donot_retransmit_old_window_updates_(false), no_version_negotiation_(supported_versions.size() == 1), - decrypt_packets_on_key_change_( - GetQuicReloadableFlag(quic_decrypt_packets_on_key_change)) { + clear_probing_mark_after_packet_processing_(GetQuicReloadableFlag( + quic_clear_probing_mark_after_packet_processing)) { if (ack_mode_ == ACK_DECIMATION) { QUIC_RELOADABLE_FLAG_COUNT(quic_enable_ack_decimation); } @@ -359,10 +352,12 @@ << "Created connection with connection_id: " << connection_id << " and version: " << QuicVersionToString(transport_version()); - QUIC_BUG_IF(connection_id.length() != sizeof(uint64_t) && - transport_version() < QUIC_VERSION_99) - << "Cannot use connection ID of length " << connection_id.length() - << " with version " << QuicVersionToString(transport_version()); + + QUIC_BUG_IF(!QuicUtils::IsConnectionIdValidForVersion(connection_id, + transport_version())) + << "QuicConnection: attempted to use connection ID " << connection_id + << " which is invalid with version " + << QuicVersionToString(transport_version()); framer_.set_visitor(this); stats_.connection_creation_time = clock_->ApproximateNow(); @@ -441,16 +436,24 @@ if (config.HasClientSentConnectionOption(kACKD, perspective_)) { ack_mode_ = ACK_DECIMATION; } - if (!GetQuicReloadableFlag(quic_enable_ack_decimation) && + if ((!GetQuicReloadableFlag(quic_enable_ack_decimation) || + GetQuicReloadableFlag(quic_keep_ack_decimation_reordering)) && config.HasClientSentConnectionOption(kAKD2, perspective_)) { + if (GetQuicReloadableFlag(quic_keep_ack_decimation_reordering)) { + QUIC_RELOADABLE_FLAG_COUNT_N(quic_keep_ack_decimation_reordering, 1, 2); + } ack_mode_ = ACK_DECIMATION_WITH_REORDERING; } if (config.HasClientSentConnectionOption(kAKD3, perspective_)) { ack_mode_ = ACK_DECIMATION; ack_decimation_delay_ = kShortAckDecimationDelay; } - if (!GetQuicReloadableFlag(quic_enable_ack_decimation) && + if ((!GetQuicReloadableFlag(quic_enable_ack_decimation) || + GetQuicReloadableFlag(quic_keep_ack_decimation_reordering)) && config.HasClientSentConnectionOption(kAKD4, perspective_)) { + if (GetQuicReloadableFlag(quic_keep_ack_decimation_reordering)) { + QUIC_RELOADABLE_FLAG_COUNT_N(quic_keep_ack_decimation_reordering, 2, 2); + } ack_mode_ = ACK_DECIMATION_WITH_REORDERING; ack_decimation_delay_ = kShortAckDecimationDelay; } @@ -782,7 +785,7 @@ // Packets should have the version flag till version negotiation is // done. QuicString error_details = - QuicStrCat(ENDPOINT, "Packet ", header.packet_number, + QuicStrCat(ENDPOINT, "Packet ", header.packet_number.ToUint64(), " without version flag before version negotiated."); QUIC_DLOG(WARNING) << error_details; CloseConnection(QUIC_INVALID_VERSION, error_details, @@ -840,7 +843,8 @@ current_effective_peer_migration_type_ = NO_CHANGE; if (perspective_ == Perspective::IS_CLIENT) { - if (header.packet_number > received_packet_manager_.GetLargestObserved()) { + if (!received_packet_manager_.GetLargestObserved().IsInitialized() || + header.packet_number > received_packet_manager_.GetLargestObserved()) { // Update peer_address_ and effective_peer_address_ immediately for // client connections. direct_peer_address_ = last_packet_source_address_; @@ -944,22 +948,25 @@ QUIC_DVLOG(1) << ENDPOINT << "OnAckFrameStart, largest_acked: " << largest_acked; - if (last_header_.packet_number <= largest_seen_packet_with_ack_) { + if (largest_seen_packet_with_ack_.IsInitialized() && + last_header_.packet_number <= largest_seen_packet_with_ack_) { QUIC_DLOG(INFO) << ENDPOINT << "Received an old ack frame: ignoring"; return true; } - if (largest_acked > sent_packet_manager_.GetLargestSentPacket()) { + if (!sent_packet_manager_.GetLargestSentPacket().IsInitialized() || + largest_acked > sent_packet_manager_.GetLargestSentPacket()) { QUIC_DLOG(WARNING) << ENDPOINT << "Peer's observed unsent packet:" << largest_acked << " vs " << sent_packet_manager_.GetLargestSentPacket(); - // We got an error for data we have not sent. + // We got an ack for data we have not sent. CloseConnection(QUIC_INVALID_ACK_DATA, "Largest observed too high.", ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); return false; } - if (largest_acked > sent_packet_manager_.GetLargestObserved()) { + if (!sent_packet_manager_.GetLargestObserved().IsInitialized() || + largest_acked > sent_packet_manager_.GetLargestObserved()) { visitor_->OnForwardProgressConfirmed(); } else if (largest_acked < sent_packet_manager_.GetLargestObserved()) { QUIC_LOG(INFO) << ENDPOINT << "Peer's largest_observed packet decreased:" @@ -984,7 +991,8 @@ DCHECK(connected_); QUIC_DVLOG(1) << ENDPOINT << "OnAckRange: [" << start << ", " << end << ")"; - if (last_header_.packet_number <= largest_seen_packet_with_ack_) { + if (largest_seen_packet_with_ack_.IsInitialized() && + last_header_.packet_number <= largest_seen_packet_with_ack_) { QUIC_DLOG(INFO) << ENDPOINT << "Received an old ack frame: ignoring"; return true; } @@ -999,7 +1007,8 @@ QUIC_DVLOG(1) << ENDPOINT << "OnAckTimestamp: [" << packet_number << ", " << timestamp.ToDebuggingValue() << ")"; - if (last_header_.packet_number <= largest_seen_packet_with_ack_) { + if (largest_seen_packet_with_ack_.IsInitialized() && + last_header_.packet_number <= largest_seen_packet_with_ack_) { QUIC_DLOG(INFO) << ENDPOINT << "Received an old ack frame: ignoring"; return true; } @@ -1012,7 +1021,8 @@ DCHECK(connected_); QUIC_DVLOG(1) << ENDPOINT << "OnAckFrameEnd, start: " << start; - if (last_header_.packet_number <= largest_seen_packet_with_ack_) { + if (largest_seen_packet_with_ack_.IsInitialized() && + last_header_.packet_number <= largest_seen_packet_with_ack_) { QUIC_DLOG(INFO) << ENDPOINT << "Received an old ack frame: ignoring"; return true; } @@ -1051,7 +1061,8 @@ if (no_stop_waiting_frames_) { return true; } - if (last_header_.packet_number <= largest_seen_packet_with_stop_waiting_) { + if (largest_seen_packet_with_stop_waiting_.IsInitialized() && + last_header_.packet_number <= largest_seen_packet_with_stop_waiting_) { QUIC_DLOG(INFO) << ENDPOINT << "Received an old stop waiting frame: ignoring"; return true; @@ -1129,8 +1140,10 @@ const char* QuicConnection::ValidateStopWaitingFrame( const QuicStopWaitingFrame& stop_waiting) { - if (stop_waiting.least_unacked < - received_packet_manager_.peer_least_packet_awaiting_ack()) { + if (received_packet_manager_.peer_least_packet_awaiting_ack() + .IsInitialized() && + stop_waiting.least_unacked < + received_packet_manager_.peer_least_packet_awaiting_ack()) { QUIC_DLOG(ERROR) << ENDPOINT << "Peer's sent low least_unacked: " << stop_waiting.least_unacked @@ -1179,7 +1192,22 @@ } bool QuicConnection::OnStopSendingFrame(const QuicStopSendingFrame& frame) { - return visitor_->OnStopSendingFrame(frame); + DCHECK(connected_); + + // Since a reset stream frame was received, this is not a connectivity probe. + // A probe only contains a PING and full padding. + UpdatePacketContent(NOT_PADDED_PING); + + if (debug_visitor_ != nullptr) { + debug_visitor_->OnStopSendingFrame(frame); + } + + QUIC_DLOG(INFO) << ENDPOINT << "STOP_SENDING frame received for stream: " + << frame.stream_id + << " with error: " << frame.application_error_code; + + visitor_->OnStopSendingFrame(frame); + return connected_; } bool QuicConnection::OnPathChallengeFrame(const QuicPathChallengeFrame& frame) { @@ -1439,8 +1467,10 @@ if (was_missing) { // Only ack immediately if an ACK frame was sent with a larger // largest acked than the newly received packet number. - if (last_header_.packet_number < - sent_packet_manager_.unacked_packets().largest_sent_largest_acked()) { + const QuicPacketNumber largest_sent_largest_acked = + sent_packet_manager_.unacked_packets().largest_sent_largest_acked(); + if (largest_sent_largest_acked.IsInitialized() && + last_header_.packet_number < largest_sent_largest_acked) { ack_queued_ = true; } } @@ -1448,7 +1478,10 @@ if (should_last_packet_instigate_acks_ && !ack_queued_) { ++num_retransmittable_packets_received_since_last_ack_sent_; if (ack_mode_ != TCP_ACKING && - last_header_.packet_number > min_received_before_ack_decimation_) { + // TODO(fayang): Fix this as this check assumes the first received + // packet is 1. + last_header_.packet_number > + QuicPacketNumber(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_ >= @@ -1497,7 +1530,8 @@ // If there are new missing packets to report, send an ack immediately. if (received_packet_manager_.HasNewMissingPackets()) { if (ack_mode_ == ACK_DECIMATION_WITH_REORDERING) { - DCHECK(!GetQuicReloadableFlag(quic_enable_ack_decimation)); + DCHECK(!GetQuicReloadableFlag(quic_enable_ack_decimation) || + GetQuicReloadableFlag(quic_keep_ack_decimation_reordering)); // Wait the minimum of an eighth min_rtt and the existing ack time. QuicTime ack_time = clock_->ApproximateNow() + @@ -1527,8 +1561,9 @@ void QuicConnection::CloseIfTooManyOutstandingSentPackets() { // This occurs if we don't discard old packets we've seen fast enough. It's // possible largest observed is less than leaset unacked. - if (sent_packet_manager_.GetLargestObserved() > - sent_packet_manager_.GetLeastUnacked() + max_tracked_packets_) { + if (sent_packet_manager_.GetLargestObserved().IsInitialized() && + sent_packet_manager_.GetLargestObserved() > + sent_packet_manager_.GetLeastUnacked() + max_tracked_packets_) { CloseConnection( QUIC_TOO_MANY_OUTSTANDING_SENT_PACKETS, QuicStrCat("More than ", max_tracked_packets_, " outstanding."), @@ -1602,9 +1637,9 @@ OnWriteError(result.error_code); return; } - if (result.status == WRITE_STATUS_BLOCKED) { + if (IsWriteBlockedStatus(result.status)) { visitor_->OnWriteBlocked(); - if (writer_->IsWriteBlockedDataBuffered()) { + if (result.status == WRITE_STATUS_BLOCKED_DATA_BUFFERED) { pending_version_negotiation_packet_ = false; } return; @@ -1676,6 +1711,8 @@ ++packet_iterator; continue; } + // NOTE THAT RemoveFramesForStream removes only STREAM frames + // for the specified stream. RemoveFramesForStream(retransmittable_frames, id); if (!retransmittable_frames->empty()) { ++packet_iterator; @@ -1776,6 +1813,13 @@ << "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; + } return; } @@ -1787,8 +1831,10 @@ << ", highest_packet_sent_before_effective_peer_migration_ = " << highest_packet_sent_before_effective_peer_migration_; if (active_effective_peer_migration_type_ != NO_CHANGE && - sent_packet_manager_.GetLargestObserved() > - highest_packet_sent_before_effective_peer_migration_) { + sent_packet_manager_.GetLargestObserved().IsInitialized() && + (!highest_packet_sent_before_effective_peer_migration_.IsInitialized() || + sent_packet_manager_.GetLargestObserved() > + highest_packet_sent_before_effective_peer_migration_)) { if (perspective_ == Perspective::IS_SERVER) { OnEffectivePeerMigrationValidated(); } @@ -1798,6 +1844,13 @@ 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; + } } void QuicConnection::OnBlockedWriterCanWrite() { @@ -1883,7 +1936,7 @@ QUIC_RESTART_FLAG_COUNT_N(quic_enable_accept_random_ipn, 2, 2); // Configured to accept any packet number in range 1...0x7fffffff // as initial packet number. - if (last_header_.packet_number != kInvalidPacketNumber) { + if (last_header_.packet_number.IsInitialized()) { // The last packet's number is not 0. Ensure that this packet // is reasonably close to where it should be. if (!Near(header.packet_number, last_header_.packet_number)) { @@ -1896,10 +1949,9 @@ } } else { // The "last packet's number" is 0, meaning that this packet is the first - // one received. Ensure it is in range 1..kMaxRandomInitialPacketNumber, + // one received. Ensure it is in range 1..MaxRandomInitialPacketNumber(), // inclusive. - if ((header.packet_number == kInvalidPacketNumber) || - (header.packet_number > kMaxRandomInitialPacketNumber)) { + if ((header.packet_number > MaxRandomInitialPacketNumber())) { // packet number is bad. QUIC_DLOG(INFO) << ENDPOINT << "Initial packet " << header.packet_number << " out of bounds. Discarding"; @@ -1913,21 +1965,29 @@ // 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 > 1) && - (header.packet_number <= kMaxRandomInitialPacketNumber)) { + if ((header.packet_number > QuicPacketNumber(1)) && + (header.packet_number <= MaxRandomInitialPacketNumber())) { QUIC_CODE_COUNT_N(had_possibly_random_ipn, 2, 2); } - - if (!Near(header.packet_number, last_header_.packet_number)) { + 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); + if (out_of_bound) { QUIC_DLOG(INFO) << ENDPOINT << "Packet " << header.packet_number << " out of bounds. Discarding"; QuicStringPiece packet_data = GetCurrentPacket(); const size_t kMaxPacketLengthInErrorDetails = 64; CloseConnection( QUIC_INVALID_PACKET_HEADER, - QuicStrCat("Packet number out of bounds. last_pkn=", - last_header_.packet_number, - ", current_pkn=", header.packet_number, + QuicStrCat("Packet number out of bounds. ", + last_header_.packet_number.IsInitialized() + ? QuicStrCat("last_pkn=", + last_header_.packet_number.ToUint64()) + : "first received packet", + ", current_pkn=", header.packet_number.ToUint64(), ", current_pkt_len=", packet_data.length(), ", current_hdr=", QuicTextUtils::HexEncode( @@ -2127,7 +2187,8 @@ ++stats_.packets_discarded; return true; } - if (packet->packet_number < sent_packet_manager_.GetLargestSentPacket()) { + if (sent_packet_manager_.GetLargestSentPacket().IsInitialized() && + packet->packet_number < sent_packet_manager_.GetLargestSentPacket()) { QUIC_BUG << "Attempt to write packet:" << packet->packet_number << " after:" << sent_packet_manager_.GetLargestSentPacket(); CloseConnection(QUIC_INTERNAL_ERROR, "Packet written out of order.", @@ -2198,7 +2259,7 @@ WRITE_STATUS_NUM_VALUES, "Status code returned by writer_->WritePacket() in QuicConnection."); - if (result.status == WRITE_STATUS_BLOCKED) { + if (IsWriteBlockedStatus(result.status)) { // Ensure the writer is still write blocked, otherwise QUIC may continue // trying to write when it will not be able to. DCHECK(writer_->IsWriteBlocked()); @@ -2207,7 +2268,7 @@ // be queued and sent again, which would result in an unnecessary // duplicate packet being sent. The helper must call OnCanWrite // when the write completes, and OnWriteError if an error occurs. - if (!writer_->IsWriteBlockedDataBuffered()) { + if (result.status != WRITE_STATUS_BLOCKED_DATA_BUFFERED) { return false; } } @@ -2314,6 +2375,14 @@ } WriteResult result = writer_->Flush(); + + if (HandleWriteBlocked()) { + DCHECK_EQ(WRITE_STATUS_BLOCKED, result.status) + << "Unexpected flush result:" << result; + QUIC_DLOG(INFO) << ENDPOINT << "Write blocked in FlushPackets."; + return; + } + if (IsWriteError(result.status)) { OnWriteError(result.error_code); } @@ -2402,7 +2471,7 @@ if (transport_version() != QUIC_VERSION_35) { if (serialized_packet->retransmittable_frames.empty() && - serialized_packet->original_packet_number == kInvalidPacketNumber) { + !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_; @@ -2496,8 +2565,7 @@ } consecutive_num_packets_with_no_retransmittable_frames_ = 0; if (packet_generator_.HasRetransmittableFrames() || - (donot_retransmit_old_window_updates_ && - visitor_->WillingAndAbleToWrite())) { + visitor_->WillingAndAbleToWrite()) { // There are pending retransmittable frames. return; } @@ -2569,11 +2637,7 @@ void QuicConnection::SetDecrypter(EncryptionLevel level, std::unique_ptr<QuicDecrypter> decrypter) { framer_.SetDecrypter(level, std::move(decrypter)); - if (!decrypt_packets_on_key_change_) { - return; - } - QUIC_RELOADABLE_FLAG_COUNT_N(quic_decrypt_packets_on_key_change, 1, 3); if (!undecryptable_packets_.empty() && !process_undecryptable_packets_alarm_->IsSet()) { process_undecryptable_packets_alarm_->Set(clock_->ApproximateNow()); @@ -2585,11 +2649,7 @@ std::unique_ptr<QuicDecrypter> decrypter, bool latch_once_used) { framer_.SetAlternativeDecrypter(level, std::move(decrypter), latch_once_used); - if (!decrypt_packets_on_key_change_) { - return; - } - QUIC_RELOADABLE_FLAG_COUNT_N(quic_decrypt_packets_on_key_change, 2, 3); if (!undecryptable_packets_.empty() && !process_undecryptable_packets_alarm_->IsSet()) { process_undecryptable_packets_alarm_->Set(clock_->ApproximateNow()); @@ -2611,10 +2671,7 @@ } void QuicConnection::MaybeProcessUndecryptablePackets() { - if (decrypt_packets_on_key_change_) { - QUIC_RELOADABLE_FLAG_COUNT_N(quic_decrypt_packets_on_key_change, 3, 3); - process_undecryptable_packets_alarm_->Cancel(); - } + process_undecryptable_packets_alarm_->Cancel(); if (undecryptable_packets_.empty() || encryption_level_ == ENCRYPTION_NONE) { return; @@ -3071,6 +3128,9 @@ packet_generator_.GenerateMtuDiscoveryPacket(target_mtu); } +// TODO(zhongyi): change this method to generate a connectivity probing packet +// and let the caller to call writer to write the packet and handle write +// status. bool QuicConnection::SendConnectivityProbingPacket( QuicPacketWriter* probing_writer, const QuicSocketAddress& peer_address) { @@ -3186,13 +3246,13 @@ packet_send_time, probing_packet->transmission_type, NO_RETRANSMITTABLE_DATA); - if (result.status == WRITE_STATUS_BLOCKED) { + if (IsWriteBlockedStatus(result.status)) { if (probing_writer == writer_) { // Visitor should not be write blocked if the probing writer is not the // default packet writer. visitor_->OnWriteBlocked(); } - if (probing_writer->IsWriteBlockedDataBuffered()) { + if (result.status == WRITE_STATUS_BLOCKED_DATA_BUFFERED) { QUIC_DLOG(INFO) << ENDPOINT << "Write probing packet blocked"; } } @@ -3228,7 +3288,7 @@ QUIC_BUG << "No migration underway."; return; } - highest_packet_sent_before_effective_peer_migration_ = 0; + highest_packet_sent_before_effective_peer_migration_.Clear(); active_effective_peer_migration_type_ = NO_CHANGE; } @@ -3382,8 +3442,9 @@ } current_packet_content_ = NOT_PADDED_PING; - if (last_header_.packet_number == - received_packet_manager_.GetLargestObserved()) { + if (received_packet_manager_.GetLargestObserved().IsInitialized() && + last_header_.packet_number == + received_packet_manager_.GetLargestObserved()) { direct_peer_address_ = last_packet_source_address_; if (current_effective_peer_migration_type_ != NO_CHANGE) { // Start effective peer migration immediately when the current packet is
diff --git a/quic/core/quic_connection.h b/quic/core/quic_connection.h index 0f50e96..221754f 100644 --- a/quic/core/quic_connection.h +++ b/quic/core/quic_connection.h
@@ -297,6 +297,9 @@ // Called when RTT may have changed, including when an RTT is read from // the config. virtual void OnRttChanged(QuicTime::Delta rtt) const {} + + // Called when a StopSendingFrame has been parsed. + virtual void OnStopSendingFrame(const QuicStopSendingFrame& frame) {} }; class QUIC_EXPORT_PRIVATE QuicConnectionHelperInterface { @@ -792,6 +795,20 @@ fill_up_link_during_probing_ = new_value; } + // This setting may be changed during the crypto handshake in order to + // enable/disable padding of different packets in the crypto handshake. + // + // This setting should never be set to false in public facing endpoints. It + // can only be set to false if there is some other mechanism of preventing + // amplification attacks, such as ICE (plus its a non-standard quic). + void set_fully_pad_crypto_hadshake_packets(bool new_value) { + packet_generator_.set_fully_pad_crypto_hadshake_packets(new_value); + } + + bool fully_pad_during_crypto_handshake() const { + return packet_generator_.fully_pad_crypto_handshake_packets(); + } + size_t min_received_before_ack_decimation() const { return min_received_before_ack_decimation_; } @@ -803,7 +820,7 @@ return ack_frequency_before_ack_decimation_; } void set_ack_frequency_before_ack_decimation(size_t new_value) { - DCHECK_GT(new_value, 0); + DCHECK_GT(new_value, 0u); ack_frequency_before_ack_decimation_ = new_value; } @@ -827,20 +844,9 @@ bool IsPathDegrading() const { return is_path_degrading_; } - // TODO(wub): Remove this function once - // quic_donot_retransmit_old_window_update flag is deprecated. - void set_donot_retransmit_old_window_updates(bool value) { - donot_retransmit_old_window_updates_ = value; - } - // Attempts to process any queued undecryptable packets. void MaybeProcessUndecryptablePackets(); - // Whether the handshake is confirmed from this connection's perspective. - bool IsHandshakeConfirmed() const { - return sent_packet_manager_.handshake_confirmed(); - } - enum PacketContent : uint8_t { NO_FRAMES_RECEIVED, // TODO(fkastenholz): Change name when we get rid of padded ping/ @@ -851,6 +857,11 @@ NOT_PADDED_PING, // Set if the packet is not {PING, PADDING}. }; + // Whether the handshake is confirmed from this connection's perspective. + bool IsHandshakeConfirmed() const { + return sent_packet_manager_.handshake_confirmed(); + } + protected: // Calls cancel() on all the alarms owned by this connection. void CancelAllAlarms(); @@ -1076,10 +1087,9 @@ // Contents received in the current packet, especially used to identify // whether the current packet is a padded PING packet. PacketContent current_packet_content_; - // True if the packet currently being processed is a connectivity probing - // packet. Is set to false when a new packet is received, and will be set to - // true as soon as |current_packet_content_| is set to - // SECOND_FRAME_IS_PADDING. + // Set to true as soon as the packet currently being processed has been + // detected as a connectivity probing. + // Always false outside the context of ProcessUdpPacket(). bool is_current_packet_connectivity_probing_; // Caches the current effective peer migration type if a effective peer @@ -1385,16 +1395,13 @@ // Time this connection can release packets into the future. QuicTime::Delta release_time_into_future_; - // Latched value of quic_donot_retransmit_old_window_update flag. - bool donot_retransmit_old_window_updates_; - // Indicates whether server connection does version negotiation. Server // connection does not support version negotiation if a single version is // provided in constructor. const bool no_version_negotiation_; - // Latched value of quic_decrypt_packets_on_key_change flag. - const bool decrypt_packets_on_key_change_; + // 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
diff --git a/quic/core/quic_connection_stats.h b/quic/core/quic_connection_stats.h index 07ca80f..8123fb0 100644 --- a/quic/core/quic_connection_stats.h +++ b/quic/core/quic_connection_stats.h
@@ -73,7 +73,7 @@ // Number of packets received out of packet number order. QuicPacketCount packets_reordered; // Maximum reordering observed in packet number space. - QuicPacketNumber max_sequence_reordering; + QuicPacketCount max_sequence_reordering; // Maximum reordering observed in microseconds int64_t max_time_reordering_us;
diff --git a/quic/core/quic_connection_test.cc b/quic/core/quic_connection_test.cc index 63f4453..fe851fd 100644 --- a/quic/core/quic_connection_test.cc +++ b/quic/core/quic_connection_test.cc
@@ -17,6 +17,7 @@ #include "net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h" #include "net/third_party/quiche/src/quic/core/quic_packets.h" #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_expect_bug.h" #include "net/third_party/quiche/src/quic/platform/api/quic_flags.h" @@ -102,7 +103,7 @@ bool SetIV(QuicStringPiece iv) override { return true; } bool EncryptPacket(QuicTransportVersion /*version*/, - QuicPacketNumber packet_number, + uint64_t packet_number, QuicStringPiece associated_data, QuicStringPiece plaintext, char* output, @@ -167,7 +168,7 @@ } bool DecryptPacket(QuicTransportVersion /*version*/, - QuicPacketNumber packet_number, + uint64_t packet_number, QuicStringPiece associated_data, QuicStringPiece ciphertext, char* output, @@ -288,6 +289,7 @@ last_packet_size_(0), write_blocked_(false), write_should_fail_(false), + block_on_next_flush_(false), block_on_next_write_(false), next_packet_too_large_(false), always_get_packet_too_large_(false), @@ -336,11 +338,14 @@ return WriteResult(WRITE_STATUS_ERROR, EMSGSIZE); } if (IsWriteBlocked()) { - return WriteResult(WRITE_STATUS_BLOCKED, EAGAIN); + return WriteResult(is_write_blocked_data_buffered_ + ? WRITE_STATUS_BLOCKED_DATA_BUFFERED + : WRITE_STATUS_BLOCKED, + 0); } if (ShouldWriteFail()) { - return WriteResult(WRITE_STATUS_ERROR, EAGAIN); + return WriteResult(WRITE_STATUS_ERROR, 0); } last_packet_size_ = packet.length(); @@ -380,7 +385,16 @@ return nullptr; } - WriteResult Flush() override { return WriteResult(WRITE_STATUS_OK, 0); } + WriteResult Flush() override { + if (block_on_next_flush_) { + block_on_next_flush_ = false; + SetWriteBlocked(); + return WriteResult(WRITE_STATUS_BLOCKED, /*errno*/ -1); + } + return WriteResult(WRITE_STATUS_OK, 0); + } + + void BlockOnNextFlush() { block_on_next_flush_ = true; } void BlockOnNextWrite() { block_on_next_write_ = true; } @@ -493,6 +507,8 @@ supports_release_time_ = supports_release_time; } + SimpleQuicFramer* framer() { return &framer_; } + private: ParsedQuicVersion version_; SimpleQuicFramer framer_; @@ -500,6 +516,7 @@ QuicPacketHeader last_packet_header_; bool write_blocked_; bool write_should_fail_; + bool block_on_next_flush_; bool block_on_next_write_; bool next_packet_too_large_; bool always_get_packet_too_large_; @@ -554,7 +571,7 @@ } void SendPacket(EncryptionLevel level, - QuicPacketNumber packet_number, + uint64_t packet_number, std::unique_ptr<QuicPacket> packet, HasRetransmittableData retransmittable, bool has_ack, @@ -562,10 +579,11 @@ char buffer[kMaxPacketSize]; size_t encrypted_length = QuicConnectionPeer::GetFramer(this)->EncryptPayload( - ENCRYPTION_NONE, packet_number, *packet, buffer, kMaxPacketSize); + ENCRYPTION_NONE, QuicPacketNumber(packet_number), *packet, buffer, + kMaxPacketSize); SerializedPacket serialized_packet( - packet_number, PACKET_4BYTE_PACKET_NUMBER, buffer, encrypted_length, - has_ack, has_pending_frames); + QuicPacketNumber(packet_number), PACKET_4BYTE_PACKET_NUMBER, buffer, + encrypted_length, has_ack, has_pending_frames); if (retransmittable == HAS_RETRANSMITTABLE_DATA) { serialized_packet.retransmittable_frames.push_back( QuicFrame(QuicStreamFrame())); @@ -580,7 +598,7 @@ QuicStreamOffset offset, StreamSendingState state) { ScopedPacketFlusher flusher(this, NO_ACK); - producer_.SaveStreamData(id, iov, iov_count, 0u, offset, total_length); + producer_.SaveStreamData(id, iov, iov_count, 0u, total_length); if (notifier_ != nullptr) { return notifier_->WriteOrBufferData(id, total_length, state); } @@ -902,14 +920,14 @@ QuicPacketNumber least_unacked() { if (writer_->stop_waiting_frames().empty()) { - return 0; + return QuicPacketNumber(); } return writer_->stop_waiting_frames()[0].least_unacked; } void use_tagging_decrypter() { writer_->use_tagging_decrypter(); } - void ProcessPacket(QuicPacketNumber number) { + void ProcessPacket(uint64_t number) { EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1); ProcessDataPacket(number); if (connection_.GetSendAlarm()->IsSet()) { @@ -984,7 +1002,7 @@ QuicReceivedPacket(encrypted_buffer, encrypted_length, clock_.Now())); } - size_t ProcessFramePacketAtLevel(QuicPacketNumber number, + size_t ProcessFramePacketAtLevel(uint64_t number, QuicFrame frame, EncryptionLevel level) { QuicPacketHeader header; @@ -995,32 +1013,43 @@ peer_framer_.perspective() == Perspective::IS_SERVER) { header.destination_connection_id_length = PACKET_0BYTE_CONNECTION_ID; } - header.packet_number = number; + header.packet_number = QuicPacketNumber(number); QuicFrames frames; frames.push_back(frame); std::unique_ptr<QuicPacket> packet(ConstructPacket(header, frames)); char buffer[kMaxPacketSize]; - size_t encrypted_length = - framer_.EncryptPayload(level, number, *packet, buffer, kMaxPacketSize); + size_t encrypted_length = framer_.EncryptPayload( + level, QuicPacketNumber(number), *packet, buffer, kMaxPacketSize); connection_.ProcessUdpPacket( kSelfAddress, kPeerAddress, QuicReceivedPacket(buffer, encrypted_length, QuicTime::Zero(), false)); return encrypted_length; } - size_t ProcessDataPacket(QuicPacketNumber number) { + size_t ProcessDataPacket(uint64_t number) { return ProcessDataPacketAtLevel(number, false, ENCRYPTION_NONE); } - size_t ProcessDataPacketAtLevel(QuicPacketNumber number, + size_t ProcessDataPacket(QuicPacketNumber packet_number) { + return ProcessDataPacketAtLevel(packet_number, false, ENCRYPTION_NONE); + } + + size_t ProcessDataPacketAtLevel(QuicPacketNumber packet_number, + bool has_stop_waiting, + EncryptionLevel level) { + return ProcessDataPacketAtLevel(packet_number.ToUint64(), has_stop_waiting, + level); + } + + size_t ProcessDataPacketAtLevel(uint64_t number, bool has_stop_waiting, EncryptionLevel level) { std::unique_ptr<QuicPacket> packet( ConstructDataPacket(number, has_stop_waiting)); char buffer[kMaxPacketSize]; size_t encrypted_length = peer_framer_.EncryptPayload( - level, number, *packet, buffer, kMaxPacketSize); + level, QuicPacketNumber(number), *packet, buffer, kMaxPacketSize); connection_.ProcessUdpPacket( kSelfAddress, kPeerAddress, QuicReceivedPacket(buffer, encrypted_length, clock_.Now(), false)); @@ -1030,11 +1059,12 @@ return encrypted_length; } - void ProcessClosePacket(QuicPacketNumber number) { + void ProcessClosePacket(uint64_t number) { std::unique_ptr<QuicPacket> packet(ConstructClosePacket(number)); char buffer[kMaxPacketSize]; - size_t encrypted_length = peer_framer_.EncryptPayload( - ENCRYPTION_NONE, number, *packet, buffer, kMaxPacketSize); + size_t encrypted_length = + peer_framer_.EncryptPayload(ENCRYPTION_NONE, QuicPacketNumber(number), + *packet, buffer, kMaxPacketSize); connection_.ProcessUdpPacket( kSelfAddress, kPeerAddress, QuicReceivedPacket(buffer, encrypted_length, QuicTime::Zero(), false)); @@ -1084,8 +1114,12 @@ connection_.OnStreamReset(id, error); } - void ProcessAckPacket(QuicPacketNumber packet_number, QuicAckFrame* frame) { - QuicPacketCreatorPeer::SetPacketNumber(&peer_creator_, packet_number - 1); + void ProcessAckPacket(uint64_t packet_number, QuicAckFrame* frame) { + if (packet_number > 1) { + QuicPacketCreatorPeer::SetPacketNumber(&peer_creator_, packet_number - 1); + } else { + QuicPacketCreatorPeer::ClearPacketNumber(&peer_creator_); + } ProcessFramePacket(QuicFrame(frame)); } @@ -1097,7 +1131,7 @@ ProcessFramePacket(QuicFrame(frame)); } - size_t ProcessStopWaitingPacketAtLevel(QuicPacketNumber number, + size_t ProcessStopWaitingPacketAtLevel(uint64_t number, QuicStopWaitingFrame* frame, EncryptionLevel level) { return ProcessFramePacketAtLevel(number, QuicFrame(frame), @@ -1108,8 +1142,9 @@ ProcessFramePacket(QuicFrame(frame)); } - bool IsMissing(QuicPacketNumber number) { - return IsAwaitingPacket(*outgoing_ack(), number, 0); + bool IsMissing(uint64_t number) { + return IsAwaitingPacket(*outgoing_ack(), QuicPacketNumber(number), + QuicPacketNumber()); } std::unique_ptr<QuicPacket> ConstructPacket(const QuicPacketHeader& header, @@ -1119,7 +1154,7 @@ return packet; } - std::unique_ptr<QuicPacket> ConstructDataPacket(QuicPacketNumber number, + std::unique_ptr<QuicPacket> ConstructDataPacket(uint64_t number, bool has_stop_waiting) { QuicPacketHeader header; // Set connection_id to peer's in memory representation as this data packet @@ -1131,7 +1166,7 @@ peer_framer_.perspective() == Perspective::IS_SERVER) { header.destination_connection_id_length = PACKET_0BYTE_CONNECTION_ID; } - header.packet_number = number; + header.packet_number = QuicPacketNumber(number); QuicFrames frames; frames.push_back(QuicFrame(frame1_)); @@ -1153,12 +1188,12 @@ &peer_creator_); } - std::unique_ptr<QuicPacket> ConstructClosePacket(QuicPacketNumber number) { + std::unique_ptr<QuicPacket> ConstructClosePacket(uint64_t number) { QuicPacketHeader header; // Set connection_id to peer's in memory representation as this connection // close packet is created by peer_framer. header.destination_connection_id = connection_id_; - header.packet_number = number; + header.packet_number = QuicPacketNumber(number); if (peer_framer_.transport_version() > QUIC_VERSION_43 && peer_framer_.perspective() == Perspective::IS_SERVER) { header.destination_connection_id_length = PACKET_0BYTE_CONNECTION_ID; @@ -1180,22 +1215,27 @@ return QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs); } - const QuicStopWaitingFrame InitStopWaitingFrame( - QuicPacketNumber least_unacked) { + const QuicStopWaitingFrame InitStopWaitingFrame(uint64_t least_unacked) { QuicStopWaitingFrame frame; - frame.least_unacked = least_unacked; + frame.least_unacked = QuicPacketNumber(least_unacked); return frame; } // Construct a ack_frame that acks all packet numbers between 1 and // |largest_acked|, except |missing|. // REQUIRES: 1 <= |missing| < |largest_acked| + QuicAckFrame ConstructAckFrame(uint64_t largest_acked, uint64_t missing) { + return ConstructAckFrame(QuicPacketNumber(largest_acked), + QuicPacketNumber(missing)); + } + QuicAckFrame ConstructAckFrame(QuicPacketNumber largest_acked, QuicPacketNumber missing) { - if (missing == 1) { + if (missing == QuicPacketNumber(1)) { return InitAckFrame({{missing + 1, largest_acked + 1}}); } - return InitAckFrame({{1, missing}, {missing + 1, largest_acked + 1}}); + return InitAckFrame( + {{QuicPacketNumber(1), missing}, {missing + 1, largest_acked + 1}}); } // Undo nacking a packet within the frame. @@ -1211,7 +1251,7 @@ // Call ProcessDataPacket rather than ProcessPacket, as we should not get a // packet call to the visitor. if (GetQuicRestartFlag(quic_enable_accept_random_ipn)) { - ProcessDataPacket(kMaxRandomInitialPacketNumber + 6000); + ProcessDataPacket(MaxRandomInitialPacketNumber() + 6000); } else { ProcessDataPacket(6000); } @@ -1256,8 +1296,8 @@ const QuicPacketCount packets_between_probes_base) { QuicConnectionPeer::SetPacketsBetweenMtuProbes(&connection_, packets_between_probes_base); - QuicConnectionPeer::SetNextMtuProbeAt(&connection_, - packets_between_probes_base); + QuicConnectionPeer::SetNextMtuProbeAt( + &connection_, QuicPacketNumber(packets_between_probes_base)); } bool IsDefaultTestConfiguration() { @@ -1577,9 +1617,15 @@ probing_packet->encrypted_length), clock_.Now())); + uint64_t num_probing_received = + connection_.GetStats().num_connectivity_probing_received; ProcessReceivedPacket(kSelfAddress, kPeerAddress, *received); - EXPECT_FALSE(connection_.IsCurrentPacketConnectivityProbing()); + 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()); EXPECT_EQ(kPeerAddress, connection_.effective_peer_address()); } @@ -1673,9 +1719,15 @@ probing_packet->encrypted_length), clock_.Now())); + uint64_t num_probing_received = + connection_.GetStats().num_connectivity_probing_received; ProcessReceivedPacket(kSelfAddress, kNewPeerAddress, *received); - EXPECT_TRUE(connection_.IsCurrentPacketConnectivityProbing()); + 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()); EXPECT_EQ(kPeerAddress, connection_.effective_peer_address()); @@ -1730,9 +1782,15 @@ probing_packet->encrypted_length), clock_.Now())); + uint64_t num_probing_received = + connection_.GetStats().num_connectivity_probing_received; ProcessReceivedPacket(kSelfAddress, kNewPeerAddress, *received); - EXPECT_TRUE(connection_.IsCurrentPacketConnectivityProbing()); + 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()); EXPECT_EQ(kPeerAddress, connection_.effective_peer_address()); } @@ -1819,9 +1877,15 @@ QuicEncryptedPacket(probing_packet->encrypted_buffer, probing_packet->encrypted_length), clock_.Now())); + uint64_t num_probing_received = + connection_.GetStats().num_connectivity_probing_received; ProcessReceivedPacket(kSelfAddress, kPeerAddress, *received); - EXPECT_FALSE(connection_.IsCurrentPacketConnectivityProbing()); + 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()); EXPECT_EQ(kPeerAddress, connection_.effective_peer_address()); } @@ -1861,9 +1925,15 @@ QuicEncryptedPacket(probing_packet->encrypted_buffer, probing_packet->encrypted_length), clock_.Now())); + uint64_t num_probing_received = + connection_.GetStats().num_connectivity_probing_received; ProcessReceivedPacket(kNewSelfAddress, kPeerAddress, *received); - EXPECT_TRUE(connection_.IsCurrentPacketConnectivityProbing()); + 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()); EXPECT_EQ(kPeerAddress, connection_.effective_peer_address()); } @@ -1923,7 +1993,7 @@ QuicPacketHeader header; header.destination_connection_id = connection_id_; header.version_flag = true; - header.packet_number = 1; + header.packet_number = QuicPacketNumber(1); QuicFrames frames; QuicPaddingFrame padding; @@ -1932,7 +2002,7 @@ std::unique_ptr<QuicPacket> packet(ConstructPacket(header, frames)); char buffer[kMaxPacketSize]; size_t encrypted_length = peer_framer_.EncryptPayload( - ENCRYPTION_NONE, 12, *packet, buffer, kMaxPacketSize); + ENCRYPTION_NONE, QuicPacketNumber(12), *packet, buffer, kMaxPacketSize); EXPECT_EQ(kMaxPacketSize, encrypted_length); framer_.set_version(version()); @@ -1956,7 +2026,7 @@ QuicPacketHeader header; header.destination_connection_id = connection_id_; header.version_flag = true; - header.packet_number = 1; + header.packet_number = QuicPacketNumber(1); QuicFrames frames; QuicPaddingFrame padding; @@ -1965,7 +2035,7 @@ std::unique_ptr<QuicPacket> packet(ConstructPacket(header, frames)); char buffer[kMaxPacketSize]; size_t encrypted_length = peer_framer_.EncryptPayload( - ENCRYPTION_NONE, 12, *packet, buffer, kMaxPacketSize); + ENCRYPTION_NONE, QuicPacketNumber(12), *packet, buffer, kMaxPacketSize); EXPECT_EQ(kMaxPacketSize, encrypted_length); framer_.set_version(version()); @@ -2005,15 +2075,15 @@ EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); ProcessPacket(1); - EXPECT_EQ(1u, LargestAcked(*outgoing_ack())); + EXPECT_EQ(QuicPacketNumber(1u), LargestAcked(*outgoing_ack())); EXPECT_EQ(1u, outgoing_ack()->packets.NumIntervals()); ProcessPacket(2); - EXPECT_EQ(2u, LargestAcked(*outgoing_ack())); + EXPECT_EQ(QuicPacketNumber(2u), LargestAcked(*outgoing_ack())); EXPECT_EQ(1u, outgoing_ack()->packets.NumIntervals()); ProcessPacket(3); - EXPECT_EQ(3u, LargestAcked(*outgoing_ack())); + EXPECT_EQ(QuicPacketNumber(3u), LargestAcked(*outgoing_ack())); EXPECT_EQ(1u, outgoing_ack()->packets.NumIntervals()); } @@ -2021,17 +2091,17 @@ EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); ProcessPacket(3); - EXPECT_EQ(3u, LargestAcked(*outgoing_ack())); + EXPECT_EQ(QuicPacketNumber(3u), LargestAcked(*outgoing_ack())); EXPECT_TRUE(IsMissing(2)); EXPECT_TRUE(IsMissing(1)); ProcessPacket(2); - EXPECT_EQ(3u, LargestAcked(*outgoing_ack())); + EXPECT_EQ(QuicPacketNumber(3u), LargestAcked(*outgoing_ack())); EXPECT_FALSE(IsMissing(2)); EXPECT_TRUE(IsMissing(1)); ProcessPacket(1); - EXPECT_EQ(3u, LargestAcked(*outgoing_ack())); + EXPECT_EQ(QuicPacketNumber(3u), LargestAcked(*outgoing_ack())); EXPECT_FALSE(IsMissing(2)); EXPECT_FALSE(IsMissing(1)); } @@ -2040,14 +2110,14 @@ EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); ProcessPacket(3); - EXPECT_EQ(3u, LargestAcked(*outgoing_ack())); + EXPECT_EQ(QuicPacketNumber(3u), LargestAcked(*outgoing_ack())); EXPECT_TRUE(IsMissing(2)); EXPECT_TRUE(IsMissing(1)); // Send packet 3 again, but do not set the expectation that // the visitor OnStreamFrame() will be called. ProcessDataPacket(3); - EXPECT_EQ(3u, LargestAcked(*outgoing_ack())); + EXPECT_EQ(QuicPacketNumber(3u), LargestAcked(*outgoing_ack())); EXPECT_TRUE(IsMissing(2)); EXPECT_TRUE(IsMissing(1)); } @@ -2056,16 +2126,16 @@ EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); ProcessPacket(3); - EXPECT_EQ(3u, LargestAcked(*outgoing_ack())); + EXPECT_EQ(QuicPacketNumber(3u), LargestAcked(*outgoing_ack())); EXPECT_TRUE(IsMissing(2)); EXPECT_TRUE(IsMissing(1)); ProcessPacket(2); - EXPECT_EQ(3u, LargestAcked(*outgoing_ack())); + EXPECT_EQ(QuicPacketNumber(3u), LargestAcked(*outgoing_ack())); EXPECT_TRUE(IsMissing(1)); ProcessPacket(5); - EXPECT_EQ(5u, LargestAcked(*outgoing_ack())); + EXPECT_EQ(QuicPacketNumber(5u), LargestAcked(*outgoing_ack())); EXPECT_TRUE(IsMissing(1)); EXPECT_TRUE(IsMissing(4)); @@ -2089,7 +2159,7 @@ // Call ProcessDataPacket rather than ProcessPacket, as we should not get a // packet call to the visitor. if (GetQuicRestartFlag(quic_enable_accept_random_ipn)) { - ProcessDataPacket(kMaxRandomInitialPacketNumber + 6000); + ProcessDataPacket(MaxRandomInitialPacketNumber() + 6000); } else { ProcessDataPacket(6000); } @@ -2264,7 +2334,8 @@ } TEST_P(QuicConnectionTest, AckDecimationReducesAcks) { - if (GetQuicReloadableFlag(quic_enable_ack_decimation)) { + if (GetQuicReloadableFlag(quic_enable_ack_decimation) && + !GetQuicReloadableFlag(quic_keep_ack_decimation_reordering)) { return; } @@ -2435,45 +2506,39 @@ ProcessAckPacket(&frame); } -TEST_P(QuicConnectionTest, AckAll) { - EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); - ProcessPacket(1); - - QuicPacketCreatorPeer::SetPacketNumber(&peer_creator_, 1); - QuicAckFrame frame1; - ProcessAckPacket(&frame1); -} - TEST_P(QuicConnectionTest, BasicSending) { EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); + EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1); + ProcessDataPacket(1); + QuicPacketCreatorPeer::SetPacketNumber(&peer_creator_, 2); QuicPacketNumber last_packet; SendStreamDataToPeer(1, "foo", 0, NO_FIN, &last_packet); // Packet 1 - EXPECT_EQ(1u, last_packet); + EXPECT_EQ(QuicPacketNumber(1u), last_packet); SendAckPacketToPeer(); // Packet 2 if (GetParam().no_stop_waiting) { // Expect no stop waiting frame is sent. - EXPECT_EQ(0u, least_unacked()); + EXPECT_FALSE(least_unacked().IsInitialized()); } else { - EXPECT_EQ(1u, least_unacked()); + EXPECT_EQ(QuicPacketNumber(1u), least_unacked()); } SendAckPacketToPeer(); // Packet 3 if (GetParam().no_stop_waiting) { // Expect no stop waiting frame is sent. - EXPECT_EQ(0u, least_unacked()); + EXPECT_FALSE(least_unacked().IsInitialized()); } else { - EXPECT_EQ(1u, least_unacked()); + EXPECT_EQ(QuicPacketNumber(1u), least_unacked()); } SendStreamDataToPeer(1, "bar", 3, NO_FIN, &last_packet); // Packet 4 - EXPECT_EQ(4u, last_packet); + EXPECT_EQ(QuicPacketNumber(4u), last_packet); SendAckPacketToPeer(); // Packet 5 if (GetParam().no_stop_waiting) { // Expect no stop waiting frame is sent. - EXPECT_EQ(0u, least_unacked()); + EXPECT_FALSE(least_unacked().IsInitialized()); } else { - EXPECT_EQ(1u, least_unacked()); + EXPECT_EQ(QuicPacketNumber(1u), least_unacked()); } EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _)); @@ -2487,9 +2552,9 @@ // ack for 4. if (GetParam().no_stop_waiting) { // Expect no stop waiting frame is sent. - EXPECT_EQ(0u, least_unacked()); + EXPECT_FALSE(least_unacked().IsInitialized()); } else { - EXPECT_EQ(4u, least_unacked()); + EXPECT_EQ(QuicPacketNumber(4u), least_unacked()); } EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _)); @@ -2499,34 +2564,34 @@ ProcessAckPacket(&frame2); // Acks don't instigate acks. // Verify that we did not send an ack. - EXPECT_EQ(6u, writer_->header().packet_number); + EXPECT_EQ(QuicPacketNumber(6u), writer_->header().packet_number); // So the last ack has not changed. if (GetParam().no_stop_waiting) { // Expect no stop waiting frame is sent. - EXPECT_EQ(0u, least_unacked()); + EXPECT_FALSE(least_unacked().IsInitialized()); } else { - EXPECT_EQ(4u, least_unacked()); + EXPECT_EQ(QuicPacketNumber(4u), least_unacked()); } // If we force an ack, we shouldn't change our retransmit state. SendAckPacketToPeer(); // Packet 7 if (GetParam().no_stop_waiting) { // Expect no stop waiting frame is sent. - EXPECT_EQ(0u, least_unacked()); + EXPECT_FALSE(least_unacked().IsInitialized()); } else { - EXPECT_EQ(7u, least_unacked()); + EXPECT_EQ(QuicPacketNumber(7u), least_unacked()); } // But if we send more data it should. SendStreamDataToPeer(1, "eep", 6, NO_FIN, &last_packet); // Packet 8 - EXPECT_EQ(8u, last_packet); + EXPECT_EQ(QuicPacketNumber(8u), last_packet); SendAckPacketToPeer(); // Packet 9 if (GetParam().no_stop_waiting) { // Expect no stop waiting frame is sent. - EXPECT_EQ(0u, least_unacked()); + EXPECT_FALSE(least_unacked().IsInitialized()); } else { - EXPECT_EQ(7u, least_unacked()); + EXPECT_EQ(QuicPacketNumber(7u), least_unacked()); } } @@ -2643,6 +2708,10 @@ // Process a data packet to queue up a pending ack. EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1); ProcessDataPacket(1); + QuicPacketNumber last_packet; + SendStreamDataToPeer(1, "foo", 0, NO_FIN, &last_packet); + // Verify ack is bundled with outging packet. + EXPECT_FALSE(writer_->ack_frames().empty()); EXPECT_CALL(visitor_, OnCanWrite()) .WillOnce(DoAll(IgnoreResult(InvokeWithoutArgs( @@ -2652,9 +2721,9 @@ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1); - // Process an ack to cause the visitor's OnCanWrite to be invoked. - QuicAckFrame ack_one; - ProcessAckPacket(3, &ack_one); + // Process a data packet to cause the visitor's OnCanWrite to be invoked. + EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1); + ProcessDataPacket(2); EXPECT_EQ(0u, connection_.NumQueuedPackets()); EXPECT_FALSE(connection_.HasQueuedData()); @@ -2839,7 +2908,7 @@ // Lose a packet and ensure it triggers retransmission. QuicAckFrame nack_two = ConstructAckFrame(3, 2); LostPacketVector lost_packets; - lost_packets.push_back(LostPacket(2, kMaxPacketSize)); + lost_packets.push_back(LostPacket(QuicPacketNumber(2), kMaxPacketSize)); EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _, _, _)) .WillOnce(SetArgPointee<5>(lost_packets)); EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _)); @@ -3088,7 +3157,7 @@ BlockOnNextWrite(); LostPacketVector lost_packets; - lost_packets.push_back(LostPacket(2, kMaxPacketSize)); + lost_packets.push_back(LostPacket(QuicPacketNumber(2), kMaxPacketSize)); EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _, _, _)) .WillOnce(SetArgPointee<5>(lost_packets)); EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _)); @@ -3103,7 +3172,8 @@ // Unblock the socket and attempt to send the queued packets. We will always // send the retransmission. - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, 4, _, _)).Times(1); + EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(4), _, _)) + .Times(1); writer_->SetWritable(); connection_.OnCanWrite(); @@ -3260,14 +3330,15 @@ // Process packet number 1. Can not call ProcessPacket or ProcessDataPacket // here, because they will fire the alarm after QuicConnection::ProcessPacket // is returned. - const QuicPacketNumber received_packet_num = 1; + const uint64_t received_packet_num = 1; const bool has_stop_waiting = false; const EncryptionLevel level = ENCRYPTION_NONE; std::unique_ptr<QuicPacket> packet( ConstructDataPacket(received_packet_num, has_stop_waiting)); char buffer[kMaxPacketSize]; - size_t encrypted_length = peer_framer_.EncryptPayload( - level, received_packet_num, *packet, buffer, kMaxPacketSize); + size_t encrypted_length = + peer_framer_.EncryptPayload(level, QuicPacketNumber(received_packet_num), + *packet, buffer, kMaxPacketSize); connection_.ProcessUdpPacket( kSelfAddress, kPeerAddress, QuicReceivedPacket(buffer, encrypted_length, clock_.Now(), false)); @@ -3313,6 +3384,19 @@ } } +TEST_P(QuicConnectionTest, AddToWriteBlockedListIfBlockedOnFlushPackets) { + writer_->SetBatchMode(true); + writer_->BlockOnNextFlush(); + + EXPECT_CALL(visitor_, OnWriteBlocked()).Times(1); + { + QuicConnection::ScopedPacketFlusher flusher(&connection_, + QuicConnection::NO_ACK); + // flusher's destructor will call connection_.FlushPackets, which should add + // the connection to the write blocked list. + } +} + TEST_P(QuicConnectionTest, NoLimitPacketsPerNack) { EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); int offset = 0; @@ -3324,12 +3408,13 @@ // Ack 15, nack 1-14. - QuicAckFrame nack = InitAckFrame({{15, 16}}); + QuicAckFrame nack = + InitAckFrame({{QuicPacketNumber(15), QuicPacketNumber(16)}}); // 14 packets have been NACK'd and lost. LostPacketVector lost_packets; for (int i = 1; i < 15; ++i) { - lost_packets.push_back(LostPacket(i, kMaxPacketSize)); + lost_packets.push_back(LostPacket(QuicPacketNumber(i), kMaxPacketSize)); } EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _, _, _)) .WillOnce(SetArgPointee<5>(lost_packets)); @@ -3344,23 +3429,26 @@ // Test sending multiple acks from the connection to the session. TEST_P(QuicConnectionTest, MultipleAcks) { + EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); + EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1); + ProcessDataPacket(1); + QuicPacketCreatorPeer::SetPacketNumber(&peer_creator_, 2); QuicPacketNumber last_packet; SendStreamDataToPeer(1, "foo", 0, NO_FIN, &last_packet); // Packet 1 - EXPECT_EQ(1u, last_packet); + EXPECT_EQ(QuicPacketNumber(1u), last_packet); SendStreamDataToPeer(3, "foo", 0, NO_FIN, &last_packet); // Packet 2 - EXPECT_EQ(2u, last_packet); + EXPECT_EQ(QuicPacketNumber(2u), last_packet); SendAckPacketToPeer(); // Packet 3 SendStreamDataToPeer(5, "foo", 0, NO_FIN, &last_packet); // Packet 4 - EXPECT_EQ(4u, last_packet); + EXPECT_EQ(QuicPacketNumber(4u), last_packet); SendStreamDataToPeer(1, "foo", 3, NO_FIN, &last_packet); // Packet 5 - EXPECT_EQ(5u, last_packet); + EXPECT_EQ(QuicPacketNumber(5u), last_packet); SendStreamDataToPeer(3, "foo", 3, NO_FIN, &last_packet); // Packet 6 - EXPECT_EQ(6u, last_packet); + EXPECT_EQ(QuicPacketNumber(6u), last_packet); // Client will ack packets 1, 2, [!3], 4, 5. EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _)); QuicAckFrame frame1 = ConstructAckFrame(5, 3); - EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); ProcessAckPacket(&frame1); // Now the client implicitly acks 3, and explicitly acks 6. @@ -3370,11 +3458,14 @@ } TEST_P(QuicConnectionTest, DontLatchUnackedPacket) { + EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); + EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1); + ProcessDataPacket(1); + QuicPacketCreatorPeer::SetPacketNumber(&peer_creator_, 2); SendStreamDataToPeer(1, "foo", 0, NO_FIN, nullptr); // Packet 1; // From now on, we send acks, so the send algorithm won't mark them pending. SendAckPacketToPeer(); // Packet 2 - EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _)); QuicAckFrame frame = InitAckFrame(1); ProcessAckPacket(&frame); @@ -3382,25 +3473,25 @@ // Verify that our internal state has least-unacked as 2, because we're still // waiting for a potential ack for 2. - EXPECT_EQ(2u, stop_waiting()->least_unacked); + EXPECT_EQ(QuicPacketNumber(2u), stop_waiting()->least_unacked); EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _)); frame = InitAckFrame(2); ProcessAckPacket(&frame); - EXPECT_EQ(3u, stop_waiting()->least_unacked); + EXPECT_EQ(QuicPacketNumber(3u), stop_waiting()->least_unacked); // When we send an ack, we make sure our least-unacked makes sense. In this // case since we're not waiting on an ack for 2 and all packets are acked, we // set it to 3. SendAckPacketToPeer(); // Packet 3 // Least_unacked remains at 3 until another ack is received. - EXPECT_EQ(3u, stop_waiting()->least_unacked); + EXPECT_EQ(QuicPacketNumber(3u), stop_waiting()->least_unacked); if (GetParam().no_stop_waiting) { // Expect no stop waiting frame is sent. - EXPECT_EQ(0u, least_unacked()); + EXPECT_FALSE(least_unacked().IsInitialized()); } else { // Check that the outgoing ack had its packet number as least_unacked. - EXPECT_EQ(3u, least_unacked()); + EXPECT_EQ(QuicPacketNumber(3u), least_unacked()); } // Ack the ack, which updates the rtt and raises the least unacked. @@ -3409,13 +3500,13 @@ ProcessAckPacket(&frame); SendStreamDataToPeer(1, "bar", 3, NO_FIN, nullptr); // Packet 4 - EXPECT_EQ(4u, stop_waiting()->least_unacked); + EXPECT_EQ(QuicPacketNumber(4u), stop_waiting()->least_unacked); SendAckPacketToPeer(); // Packet 5 if (GetParam().no_stop_waiting) { // Expect no stop waiting frame is sent. - EXPECT_EQ(0u, least_unacked()); + EXPECT_FALSE(least_unacked().IsInitialized()); } else { - EXPECT_EQ(4u, least_unacked()); + EXPECT_EQ(QuicPacketNumber(4u), least_unacked()); } // Send two data packets at the end, and ensure if the last one is acked, @@ -3424,30 +3515,31 @@ SendStreamDataToPeer(1, "bar", 9, NO_FIN, nullptr); // Packet 7 EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _)); - frame = InitAckFrame({{1, 5}, {7, 8}}); + frame = InitAckFrame({{QuicPacketNumber(1), QuicPacketNumber(5)}, + {QuicPacketNumber(7), QuicPacketNumber(8)}}); ProcessAckPacket(&frame); - EXPECT_EQ(6u, stop_waiting()->least_unacked); + EXPECT_EQ(QuicPacketNumber(6u), stop_waiting()->least_unacked); } TEST_P(QuicConnectionTest, TLP) { connection_.SetMaxTailLossProbes(1); SendStreamDataToPeer(3, "foo", 0, NO_FIN, nullptr); - EXPECT_EQ(1u, stop_waiting()->least_unacked); + EXPECT_EQ(QuicPacketNumber(1u), stop_waiting()->least_unacked); QuicTime retransmission_time = connection_.GetRetransmissionAlarm()->deadline(); EXPECT_NE(QuicTime::Zero(), retransmission_time); - EXPECT_EQ(1u, writer_->header().packet_number); + EXPECT_EQ(QuicPacketNumber(1u), writer_->header().packet_number); // Simulate the retransmission alarm firing and sending a tlp, // so send algorithm's OnRetransmissionTimeout is not called. clock_.AdvanceTime(retransmission_time - clock_.Now()); - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, 2u, _, _)); + EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(2), _, _)); connection_.GetRetransmissionAlarm()->Fire(); - EXPECT_EQ(2u, writer_->header().packet_number); + EXPECT_EQ(QuicPacketNumber(2u), writer_->header().packet_number); // We do not raise the high water mark yet. - EXPECT_EQ(1u, stop_waiting()->least_unacked); + EXPECT_EQ(QuicPacketNumber(1u), stop_waiting()->least_unacked); } TEST_P(QuicConnectionTest, RTO) { @@ -3456,18 +3548,18 @@ QuicTime default_retransmission_time = clock_.ApproximateNow() + DefaultRetransmissionTime(); SendStreamDataToPeer(3, "foo", 0, NO_FIN, nullptr); - EXPECT_EQ(1u, stop_waiting()->least_unacked); + EXPECT_EQ(QuicPacketNumber(1u), stop_waiting()->least_unacked); - EXPECT_EQ(1u, writer_->header().packet_number); + EXPECT_EQ(QuicPacketNumber(1u), writer_->header().packet_number); EXPECT_EQ(default_retransmission_time, connection_.GetRetransmissionAlarm()->deadline()); // Simulate the retransmission alarm firing. clock_.AdvanceTime(DefaultRetransmissionTime()); - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, 2u, _, _)); + EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(2), _, _)); connection_.GetRetransmissionAlarm()->Fire(); - EXPECT_EQ(2u, writer_->header().packet_number); + EXPECT_EQ(QuicPacketNumber(2u), writer_->header().packet_number); // We do not raise the high water mark yet. - EXPECT_EQ(1u, stop_waiting()->least_unacked); + EXPECT_EQ(QuicPacketNumber(1u), stop_waiting()->least_unacked); } TEST_P(QuicConnectionTest, RetransmitWithSameEncryptionLevel) { @@ -3490,8 +3582,10 @@ { InSequence s; - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, 3, _, _)); - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, 4, _, _)); + EXPECT_CALL(*send_algorithm_, + OnPacketSent(_, _, QuicPacketNumber(3), _, _)); + EXPECT_CALL(*send_algorithm_, + OnPacketSent(_, _, QuicPacketNumber(4), _, _)); } // Manually mark both packets for retransmission. @@ -3616,45 +3710,6 @@ ProcessDataPacketAtLevel(3, !kHasStopWaiting, ENCRYPTION_INITIAL); } -TEST_P(QuicConnectionTest, Buffer100NonDecryptablePackets) { - if (GetQuicReloadableFlag(quic_decrypt_packets_on_key_change)) { - return; - } - - // SetFromConfig is always called after construction from InitializeSession. - EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); - QuicConfig config; - config.set_max_undecryptable_packets(100); - connection_.SetFromConfig(config); - EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); - use_tagging_decrypter(); - - const uint8_t tag = 0x07; - peer_framer_.SetEncrypter(ENCRYPTION_INITIAL, - QuicMakeUnique<TaggingEncrypter>(tag)); - - // Process an encrypted packet which can not yet be decrypted which should - // result in the packet being buffered. - for (QuicPacketNumber i = 1; i <= 100; ++i) { - ProcessDataPacketAtLevel(i, !kHasStopWaiting, ENCRYPTION_INITIAL); - } - - // Transition to the new encryption state and process another encrypted packet - // which should result in the original packets being processed. - connection_.SetDecrypter(ENCRYPTION_INITIAL, - QuicMakeUnique<StrictTaggingDecrypter>(tag)); - connection_.SetDefaultEncryptionLevel(ENCRYPTION_INITIAL); - connection_.SetEncrypter(ENCRYPTION_INITIAL, - QuicMakeUnique<TaggingEncrypter>(tag)); - EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(101); - ProcessDataPacketAtLevel(101, !kHasStopWaiting, ENCRYPTION_INITIAL); - - // 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); -} - TEST_P(QuicConnectionTest, TestRetransmitOrder) { connection_.SetMaxTailLossProbes(0); @@ -3688,10 +3743,6 @@ } TEST_P(QuicConnectionTest, Buffer100NonDecryptablePacketsThenKeyChange) { - if (!GetQuicReloadableFlag(quic_decrypt_packets_on_key_change)) { - return; - } - // SetFromConfig is always called after construction from InitializeSession. EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _)); QuicConfig config; @@ -3706,7 +3757,7 @@ // Process an encrypted packet which can not yet be decrypted which should // result in the packet being buffered. - for (QuicPacketNumber i = 1; i <= 100; ++i) { + for (uint64_t i = 1; i <= 100; ++i) { ProcessDataPacketAtLevel(i, !kHasStopWaiting, ENCRYPTION_INITIAL); } @@ -3848,7 +3899,7 @@ clock_.AdvanceTime(QuicTime::Delta::FromMicroseconds(20)); QuicPacketNumber last_packet; SendStreamDataToPeer(1, "foo", 0, NO_FIN, &last_packet); - EXPECT_EQ(1u, last_packet); + EXPECT_EQ(QuicPacketNumber(1u), last_packet); // This will be the updated deadline for the connection to idle time out. QuicTime new_ddl = clock_.ApproximateNow() + QuicTime::Delta::FromSeconds(kInitialIdleTimeoutSecs - 1); @@ -3900,12 +3951,12 @@ // execution until manually adjusted. QuicPacketNumber last_packet; SendStreamDataToPeer(1, "foo", 0, NO_FIN, &last_packet); - EXPECT_EQ(1u, last_packet); + EXPECT_EQ(QuicPacketNumber(1u), last_packet); // Advance the time and send the second packet to the peer. clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(20)); SendStreamDataToPeer(1, "foo", 0, NO_FIN, &last_packet); - EXPECT_EQ(2u, last_packet); + EXPECT_EQ(QuicPacketNumber(2u), last_packet); if (GetQuicReloadableFlag( quic_fix_time_of_first_packet_sent_after_receiving)) { @@ -4092,7 +4143,7 @@ .WillOnce(SaveArg<3>(&mtu_probe_size)); connection_.SendMtuDiscoveryPacket(new_mtu); EXPECT_EQ(new_mtu, mtu_probe_size); - EXPECT_EQ(1u, creator_->packet_number()); + EXPECT_EQ(QuicPacketNumber(1u), creator_->packet_number()); // Send more than MTU worth of data. No acknowledgement was received so far, // so the MTU should be at its old value. @@ -4103,7 +4154,7 @@ .WillOnce(SaveArg<3>(&size_before_mtu_change)) .WillOnce(Return()); connection_.SendStreamDataWithString(3, data, 0, FIN); - EXPECT_EQ(3u, creator_->packet_number()); + EXPECT_EQ(QuicPacketNumber(3u), creator_->packet_number()); EXPECT_EQ(kDefaultMaxPacketSize, size_before_mtu_change); // Acknowledge all packets so far. @@ -4116,7 +4167,7 @@ // Send the same data again. Check that it fits into a single packet now. EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1); connection_.SendStreamDataWithString(3, data, 0, FIN); - EXPECT_EQ(4u, creator_->packet_number()); + EXPECT_EQ(QuicPacketNumber(4u), creator_->packet_number()); } // Tests whether MTU discovery does not happen when it is not explicitly enabled @@ -4161,7 +4212,8 @@ connection_.GetMtuDiscoveryAlarm()->Fire(); EXPECT_EQ(kMtuDiscoveryTargetPacketSizeHigh, probe_size); - const QuicPacketCount probe_packet_number = packets_between_probes_base + 1; + const QuicPacketNumber probe_packet_number = + FirstSendingPacketNumber() + packets_between_probes_base; ASSERT_EQ(probe_packet_number, creator_->packet_number()); // Acknowledge all packets sent so far. @@ -4223,12 +4275,13 @@ mtu_discovery_packets.end()); QuicPacketNumber max_packet = *max_element(mtu_discovery_packets.begin(), mtu_discovery_packets.end()); - ack.packets.AddRange(1, min_packet); - ack.packets.AddRange(max_packet + 1, creator_->packet_number() + 1); + ack.packets.AddRange(QuicPacketNumber(1), min_packet); + ack.packets.AddRange(QuicPacketNumber(max_packet + 1), + creator_->packet_number() + 1); ack.largest_acked = creator_->packet_number(); } else { - ack.packets.AddRange(1, creator_->packet_number() + 1); + ack.packets.AddRange(QuicPacketNumber(1), creator_->packet_number() + 1); ack.largest_acked = creator_->packet_number(); } @@ -4250,11 +4303,12 @@ // Ensure the number of packets between probes grows exponentially by checking // it against the closed-form expression for the packet number. ASSERT_EQ(kMtuDiscoveryAttempts, mtu_discovery_packets.size()); - for (QuicPacketNumber i = 0; i < kMtuDiscoveryAttempts; i++) { + for (uint64_t i = 0; i < kMtuDiscoveryAttempts; i++) { // 2^0 + 2^1 + 2^2 + ... + 2^n = 2^(n + 1) - 1 const QuicPacketCount packets_between_probes = packets_between_probes_base * ((1 << (i + 1)) - 1); - EXPECT_EQ(packets_between_probes + (i + 1), mtu_discovery_packets[i]); + EXPECT_EQ(QuicPacketNumber(packets_between_probes + (i + 1)), + mtu_discovery_packets[i]); } EXPECT_FALSE(connection_.GetMtuDiscoveryAlarm()->IsSet()); @@ -4290,7 +4344,8 @@ connection_.GetMtuDiscoveryAlarm()->Fire(); EXPECT_EQ(mtu_limit, probe_size); - const QuicPacketCount probe_sequence_number = packets_between_probes_base + 1; + const QuicPacketNumber probe_sequence_number = + FirstSendingPacketNumber() + packets_between_probes_base; ASSERT_EQ(probe_sequence_number, creator_->packet_number()); // Acknowledge all packets sent so far. @@ -4485,7 +4540,7 @@ const QuicTime final_timeout = rto_time + initial_idle_timeout; clock_.AdvanceTime(rto_time - clock_.Now()); ASSERT_EQ(rto_time, clock_.Now()); - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, 2u, _, _)); + EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(2u), _, _)); connection_.GetRetransmissionAlarm()->Fire(); // Advance to the original timeout and fire the alarm. The connection should @@ -4622,7 +4677,7 @@ // Retransmit the packet via tail loss probe. clock_.AdvanceTime(connection_.GetRetransmissionAlarm()->deadline() - clock_.Now()); - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, 2u, _, _)); + EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(2u), _, _)); connection_.GetRetransmissionAlarm()->Fire(); // This time, we should time out and send a connection close due to the TLP. @@ -4839,6 +4894,7 @@ // Test that if we send a packet without delay, it is not queued. QuicFramerPeer::SetPerspective(&peer_framer_, Perspective::IS_CLIENT); std::unique_ptr<QuicPacket> packet = ConstructDataPacket(1, !kHasStopWaiting); + QuicPacketCreatorPeer::SetPacketNumber(creator_, 1); EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)); connection_.SendPacket(ENCRYPTION_NONE, 1, std::move(packet), HAS_RETRANSMITTABLE_DATA, false, false); @@ -4851,6 +4907,7 @@ QuicFramerPeer::SetPerspective(&peer_framer_, Perspective::IS_CLIENT); EXPECT_CALL(visitor_, OnConnectionClosed(_, _, _)).Times(1); std::unique_ptr<QuicPacket> packet = ConstructDataPacket(1, !kHasStopWaiting); + QuicPacketCreatorPeer::SetPacketNumber(creator_, 1); writer_->SetShouldWriteFail(); connection_.SendPacket(ENCRYPTION_NONE, 1, std::move(packet), HAS_RETRANSMITTABLE_DATA, false, false); @@ -4859,8 +4916,10 @@ TEST_P(QuicConnectionTest, SendSchedulerEAGAIN) { QuicFramerPeer::SetPerspective(&peer_framer_, Perspective::IS_CLIENT); std::unique_ptr<QuicPacket> packet = ConstructDataPacket(1, !kHasStopWaiting); + QuicPacketCreatorPeer::SetPacketNumber(creator_, 1); BlockOnNextWrite(); - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, 1, _, _)).Times(0); + EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(2u), _, _)) + .Times(0); connection_.SendPacket(ENCRYPTION_NONE, 1, std::move(packet), HAS_RETRANSMITTABLE_DATA, false, false); EXPECT_EQ(1u, connection_.NumQueuedPackets()); @@ -5112,7 +5171,7 @@ frame1_.stream_id = 3; // Process all the initial packets in order so there aren't missing packets. - QuicPacketNumber kFirstDecimatedPacket = 101; + 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); @@ -5228,7 +5287,7 @@ // default delayed ack time. ack_time = clock_.ApproximateNow() + QuicTime::Delta::FromMilliseconds(kMinRttMs / 4); - QuicPacketNumber kFirstDecimatedPacket = 101; + 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); @@ -5304,7 +5363,7 @@ frame1_.stream_id = 3; // Process all the initial packets in order so there aren't missing packets. - QuicPacketNumber kFirstDecimatedPacket = 101; + 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); @@ -5357,7 +5416,7 @@ frame1_.stream_id = 3; // Process all the initial packets in order so there aren't missing packets. - QuicPacketNumber kFirstDecimatedPacket = 101; + 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); @@ -5393,7 +5452,8 @@ } TEST_P(QuicConnectionTest, SendDelayedAckDecimationWithReordering) { - if (GetQuicReloadableFlag(quic_enable_ack_decimation)) { + if (GetQuicReloadableFlag(quic_enable_ack_decimation) && + !GetQuicReloadableFlag(quic_keep_ack_decimation_reordering)) { return; } EXPECT_CALL(visitor_, OnAckNeedsRetransmittableFrame()).Times(AnyNumber()); @@ -5419,7 +5479,7 @@ frame1_.stream_id = 3; // Process all the initial packets in order so there aren't missing packets. - QuicPacketNumber kFirstDecimatedPacket = 101; + 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); @@ -5461,7 +5521,8 @@ } TEST_P(QuicConnectionTest, SendDelayedAckDecimationWithLargeReordering) { - if (GetQuicReloadableFlag(quic_enable_ack_decimation)) { + if (GetQuicReloadableFlag(quic_enable_ack_decimation) && + !GetQuicReloadableFlag(quic_keep_ack_decimation_reordering)) { return; } EXPECT_CALL(visitor_, OnAckNeedsRetransmittableFrame()).Times(AnyNumber()); @@ -5487,7 +5548,7 @@ frame1_.stream_id = 3; // Process all the initial packets in order so there aren't missing packets. - QuicPacketNumber kFirstDecimatedPacket = 101; + 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); @@ -5548,7 +5609,8 @@ } TEST_P(QuicConnectionTest, SendDelayedAckDecimationWithReorderingEighthRtt) { - if (GetQuicReloadableFlag(quic_enable_ack_decimation)) { + if (GetQuicReloadableFlag(quic_enable_ack_decimation) && + !GetQuicReloadableFlag(quic_keep_ack_decimation_reordering)) { return; } EXPECT_CALL(visitor_, OnAckNeedsRetransmittableFrame()).Times(AnyNumber()); @@ -5575,7 +5637,7 @@ frame1_.stream_id = 3; // Process all the initial packets in order so there aren't missing packets. - QuicPacketNumber kFirstDecimatedPacket = 101; + 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); @@ -5620,7 +5682,8 @@ TEST_P(QuicConnectionTest, SendDelayedAckDecimationWithLargeReorderingEighthRtt) { - if (GetQuicReloadableFlag(quic_enable_ack_decimation)) { + if (GetQuicReloadableFlag(quic_enable_ack_decimation) && + !GetQuicReloadableFlag(quic_keep_ack_decimation_reordering)) { return; } EXPECT_CALL(visitor_, OnAckNeedsRetransmittableFrame()).Times(AnyNumber()); @@ -5647,7 +5710,7 @@ frame1_.stream_id = 3; // Process all the initial packets in order so there aren't missing packets. - QuicPacketNumber kFirstDecimatedPacket = 101; + 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); @@ -5844,7 +5907,7 @@ EXPECT_EQ(1u, writer_->stream_frames().size()); EXPECT_EQ(1u, writer_->padding_frames().size()); ASSERT_FALSE(writer_->ack_frames().empty()); - EXPECT_EQ(2u, LargestAcked(writer_->ack_frames().front())); + EXPECT_EQ(QuicPacketNumber(2u), LargestAcked(writer_->ack_frames().front())); EXPECT_FALSE(connection_.GetAckAlarm()->IsSet()); } @@ -5873,7 +5936,7 @@ EXPECT_EQ(1u, writer_->stream_frames().size()); EXPECT_EQ(1u, writer_->padding_frames().size()); ASSERT_FALSE(writer_->ack_frames().empty()); - EXPECT_EQ(2u, LargestAcked(writer_->ack_frames().front())); + EXPECT_EQ(QuicPacketNumber(2u), LargestAcked(writer_->ack_frames().front())); EXPECT_FALSE(connection_.GetAckAlarm()->IsSet()); } @@ -5888,7 +5951,7 @@ // Ack the second packet, which will retransmit the first packet. QuicAckFrame ack = ConstructAckFrame(2, 1); LostPacketVector lost_packets; - lost_packets.push_back(LostPacket(1, kMaxPacketSize)); + lost_packets.push_back(LostPacket(QuicPacketNumber(1), kMaxPacketSize)); EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _, _, _)) .WillOnce(SetArgPointee<5>(lost_packets)); EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _)); @@ -5927,7 +5990,7 @@ EXPECT_FALSE(writer_->stop_waiting_frames().empty()); } EXPECT_FALSE(writer_->ack_frames().empty()); - EXPECT_EQ(3u, LargestAcked(writer_->ack_frames().front())); + EXPECT_EQ(QuicPacketNumber(3u), LargestAcked(writer_->ack_frames().front())); EXPECT_EQ(1u, writer_->stream_frames().size()); EXPECT_FALSE(connection_.GetAckAlarm()->IsSet()); } @@ -5950,7 +6013,8 @@ EXPECT_FALSE(connection_.connected()); EXPECT_FALSE(connection_.CanWriteStreamData()); std::unique_ptr<QuicPacket> packet = ConstructDataPacket(1, !kHasStopWaiting); - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, 1, _, _)).Times(0); + EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(1), _, _)) + .Times(0); connection_.SendPacket(ENCRYPTION_NONE, 1, std::move(packet), HAS_RETRANSMITTABLE_DATA, false, false); } @@ -5969,7 +6033,8 @@ EXPECT_FALSE(connection_.connected()); EXPECT_FALSE(connection_.CanWriteStreamData()); - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, 1, _, _)).Times(0); + EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(1), _, _)) + .Times(0); EXPECT_QUIC_BUG(connection_.SendConnectivityProbingPacket( writer_.get(), connection_.peer_address()), @@ -5987,7 +6052,8 @@ // affects the probing_writer which is not the default. EXPECT_CALL(visitor_, OnWriteBlocked()).Times(0); - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, 1, _, _)).Times(1); + EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(1), _, _)) + .Times(1); connection_.SendConnectivityProbingPacket(&probing_writer, connection_.peer_address()); } @@ -6003,7 +6069,8 @@ // writer to send connectivity probes. EXPECT_CALL(visitor_, OnWriteBlocked()).Times(1); - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, 1, _, _)).Times(1); + EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(1), _, _)) + .Times(1); connection_.SendConnectivityProbingPacket(writer_.get(), connection_.peer_address()); } @@ -6017,7 +6084,8 @@ // sent. EXPECT_CALL(visitor_, OnConnectionClosed(_, _, _)).Times(0); - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, 1, _, _)).Times(0); + EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(1), _, _)) + .Times(0); connection_.SendConnectivityProbingPacket(&probing_writer, connection_.peer_address()); } @@ -6031,7 +6099,8 @@ // sent. EXPECT_CALL(visitor_, OnConnectionClosed(_, _, _)).Times(0); - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, 1, _, _)).Times(0); + EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(1), _, _)) + .Times(0); connection_.SendConnectivityProbingPacket(writer_.get(), connection_.peer_address()); } @@ -6137,21 +6206,20 @@ peer_framer_.set_version_for_tests( ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_99)); } else { - peer_framer_.set_version_for_tests( - ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED)); + peer_framer_.set_version_for_tests(UnsupportedQuicVersion()); } QuicPacketHeader header; header.destination_connection_id = connection_id_; header.version_flag = true; - header.packet_number = 12; + header.packet_number = QuicPacketNumber(12); QuicFrames frames; frames.push_back(QuicFrame(frame1_)); std::unique_ptr<QuicPacket> packet(ConstructPacket(header, frames)); char buffer[kMaxPacketSize]; - size_t encrypted_length = framer_.EncryptPayload(ENCRYPTION_NONE, 12, *packet, - buffer, kMaxPacketSize); + size_t encrypted_length = framer_.EncryptPayload( + ENCRYPTION_NONE, QuicPacketNumber(12), *packet, buffer, kMaxPacketSize); framer_.set_version(version()); // Writer's framer's perspective is client, so that it needs to have the right @@ -6183,21 +6251,20 @@ peer_framer_.set_version_for_tests( ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_99)); } else { - peer_framer_.set_version_for_tests( - ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED)); + peer_framer_.set_version_for_tests(UnsupportedQuicVersion()); } QuicPacketHeader header; header.destination_connection_id = connection_id_; header.version_flag = true; - header.packet_number = 12; + header.packet_number = QuicPacketNumber(12); QuicFrames frames; frames.push_back(QuicFrame(frame1_)); std::unique_ptr<QuicPacket> packet(ConstructPacket(header, frames)); char buffer[kMaxPacketSize]; - size_t encrypted_length = framer_.EncryptPayload(ENCRYPTION_NONE, 12, *packet, - buffer, kMaxPacketSize); + size_t encrypted_length = framer_.EncryptPayload( + ENCRYPTION_NONE, QuicPacketNumber(12), *packet, buffer, kMaxPacketSize); framer_.set_version(version()); BlockOnNextWrite(); @@ -6236,21 +6303,20 @@ peer_framer_.set_version_for_tests( ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_99)); } else { - peer_framer_.set_version_for_tests( - ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED)); + peer_framer_.set_version_for_tests(UnsupportedQuicVersion()); } QuicPacketHeader header; header.destination_connection_id = connection_id_; header.version_flag = true; - header.packet_number = 12; + header.packet_number = QuicPacketNumber(12); QuicFrames frames; frames.push_back(QuicFrame(frame1_)); std::unique_ptr<QuicPacket> packet(ConstructPacket(header, frames)); char buffer[kMaxPacketSize]; - size_t encryped_length = framer_.EncryptPayload(ENCRYPTION_NONE, 12, *packet, - buffer, kMaxPacketSize); + size_t encryped_length = framer_.EncryptPayload( + ENCRYPTION_NONE, QuicPacketNumber(12), *packet, buffer, kMaxPacketSize); framer_.set_version(version()); set_perspective(Perspective::IS_SERVER); @@ -6297,14 +6363,14 @@ QuicPacketHeader header; header.destination_connection_id = connection_id_; header.destination_connection_id_length = PACKET_0BYTE_CONNECTION_ID; - header.packet_number = 12; + header.packet_number = QuicPacketNumber(12); header.version_flag = false; QuicFrames frames; frames.push_back(QuicFrame(frame1_)); std::unique_ptr<QuicPacket> packet(ConstructPacket(header, frames)); char buffer[kMaxPacketSize]; size_t encrypted_length = peer_framer_.EncryptPayload( - ENCRYPTION_NONE, 12, *packet, buffer, kMaxPacketSize); + ENCRYPTION_NONE, QuicPacketNumber(12), *packet, buffer, kMaxPacketSize); ASSERT_NE(0u, encrypted_length); EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1); EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); @@ -6355,11 +6421,13 @@ connection_.GetRetransmissionAlarm()->Fire(); // Retransmit due to explicit nacks. - QuicAckFrame nack_three = InitAckFrame({{2, 3}, {4, 5}}); + QuicAckFrame nack_three = + InitAckFrame({{QuicPacketNumber(2), QuicPacketNumber(3)}, + {QuicPacketNumber(4), QuicPacketNumber(5)}}); LostPacketVector lost_packets; - lost_packets.push_back(LostPacket(1, kMaxPacketSize)); - lost_packets.push_back(LostPacket(3, kMaxPacketSize)); + lost_packets.push_back(LostPacket(QuicPacketNumber(1), kMaxPacketSize)); + lost_packets.push_back(LostPacket(QuicPacketNumber(3), kMaxPacketSize)); EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _, _, _)) .WillOnce(SetArgPointee<5>(lost_packets)); EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _)); @@ -6395,7 +6463,7 @@ if (peer_framer_.transport_version() > QUIC_VERSION_43) { header.destination_connection_id_length = PACKET_0BYTE_CONNECTION_ID; } - header.packet_number = 1; + header.packet_number = QuicPacketNumber(1); header.version_flag = false; QuicConnectionCloseFrame qccf; @@ -6408,7 +6476,7 @@ EXPECT_TRUE(nullptr != packet); char buffer[kMaxPacketSize]; size_t encrypted_length = peer_framer_.EncryptPayload( - ENCRYPTION_NONE, 1, *packet, buffer, kMaxPacketSize); + ENCRYPTION_NONE, QuicPacketNumber(1), *packet, buffer, kMaxPacketSize); EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_PEER_GOING_AWAY, _, ConnectionCloseSource::FROM_PEER)); @@ -6442,8 +6510,7 @@ // Shouldn't be able to find a mutually supported version. ParsedQuicVersionVector unsupported_version; - unsupported_version.push_back( - ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED)); + unsupported_version.push_back(UnsupportedQuicVersion()); EXPECT_FALSE(connection_.SelectMutualVersion(unsupported_version)); } @@ -6490,7 +6557,7 @@ TEST_P(QuicConnectionTest, OnPacketHeaderDebugVisitor) { QuicPacketHeader header; - header.packet_number = 1; + header.packet_number = QuicPacketNumber(1); if (GetParam().version.transport_version > QUIC_VERSION_43) { header.form = IETF_QUIC_LONG_HEADER_PACKET; } @@ -6594,6 +6661,9 @@ } TEST_P(QuicConnectionTest, SendAcksImmediately) { + EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); + EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1); + ProcessDataPacket(1); CongestionBlockWrites(); SendAckPacketToPeer(); } @@ -6727,7 +6797,8 @@ EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); } EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _)); - QuicAckFrame frame = InitAckFrame({{1u + 2u * i, 2u + 2u * i}}); + QuicAckFrame frame = InitAckFrame( + {{QuicPacketNumber(1u + 2u * i), QuicPacketNumber(2u + 2u * i)}}); ProcessAckPacket(&frame); EXPECT_TRUE(connection_.GetPathDegradingAlarm()->IsSet()); // Check the deadline of the path degrading alarm. @@ -6742,7 +6813,7 @@ // degrading alarm. clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5)); EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _)); - frame = InitAckFrame({{2, 3}}); + frame = InitAckFrame({{QuicPacketNumber(2), QuicPacketNumber(3)}}); ProcessAckPacket(&frame); EXPECT_FALSE(connection_.GetPathDegradingAlarm()->IsSet()); } else { @@ -6797,7 +6868,8 @@ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5)); EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _)); - QuicAckFrame frame = InitAckFrame({{1, 2}}); + QuicAckFrame frame = + InitAckFrame({{QuicPacketNumber(1), QuicPacketNumber(2)}}); ProcessAckPacket(&frame); // No more retransmittable packets on the wire, so the path degrading alarm // should be cancelled, and the ping alarm should be set to the @@ -6860,7 +6932,8 @@ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5)); EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _)); - QuicAckFrame frame = InitAckFrame({{1u, 2u}}); + QuicAckFrame frame = + InitAckFrame({{QuicPacketNumber(1u), QuicPacketNumber(2u)}}); ProcessAckPacket(&frame); EXPECT_TRUE(connection_.GetPathDegradingAlarm()->IsSet()); // Check the deadline of the path degrading alarm. @@ -6925,7 +6998,8 @@ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5)); EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _)); - QuicAckFrame frame = InitAckFrame({{1u, 2u}}); + QuicAckFrame frame = + InitAckFrame({{QuicPacketNumber(1u), QuicPacketNumber(2u)}}); ProcessAckPacket(&frame); EXPECT_TRUE(connection_.GetPathDegradingAlarm()->IsSet()); // Check the deadline of the path degrading alarm. @@ -6955,7 +7029,7 @@ // degrading. And will set a timer to detect new path degrading. clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5)); EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _)); - frame = InitAckFrame({{2, 3}}); + frame = InitAckFrame({{QuicPacketNumber(2), QuicPacketNumber(3)}}); ProcessAckPacket(&frame); EXPECT_FALSE(connection_.IsPathDegrading()); EXPECT_TRUE(connection_.GetPathDegradingAlarm()->IsSet()); @@ -6978,13 +7052,17 @@ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5)); EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _)); - QuicAckFrame frame = InitAckFrame({{1u, 2u}}); + QuicAckFrame frame = + InitAckFrame({{QuicPacketNumber(1u), QuicPacketNumber(2u)}}); ProcessAckPacket(&frame); EXPECT_FALSE(connection_.IsPathDegrading()); EXPECT_FALSE(connection_.GetPathDegradingAlarm()->IsSet()); } TEST_P(QuicConnectionTest, NoPathDegradingAfterSendingAck) { + EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); + EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1); + ProcessDataPacket(1); SendAckPacketToPeer(); EXPECT_FALSE(connection_.sent_packet_manager().unacked_packets().empty()); EXPECT_FALSE(connection_.sent_packet_manager().HasInFlightPackets()); @@ -7310,7 +7388,8 @@ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5)); EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _)); - QuicAckFrame frame = InitAckFrame({{1, 2}}); + QuicAckFrame frame = + InitAckFrame({{QuicPacketNumber(1), QuicPacketNumber(2)}}); ProcessAckPacket(&frame); EXPECT_TRUE(connection_.sent_packet_manager().HasInFlightPackets()); // The ping alarm is set for the ping timeout, not the shorter @@ -7327,7 +7406,7 @@ // the wire. clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5)); EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _)); - frame = InitAckFrame({{2, 3}}); + frame = InitAckFrame({{QuicPacketNumber(2), QuicPacketNumber(3)}}); ProcessAckPacket(&frame); EXPECT_TRUE(connection_.GetPingAlarm()->IsSet()); EXPECT_EQ(clock_.ApproximateNow() + retransmittable_on_wire_timeout, @@ -7337,7 +7416,7 @@ // the ping alarm. QuicTime prev_deadline = connection_.GetPingAlarm()->deadline(); clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5)); - frame = InitAckFrame({{2, 3}}); + frame = InitAckFrame({{QuicPacketNumber(2), QuicPacketNumber(3)}}); ProcessAckPacket(&frame); EXPECT_TRUE(connection_.GetPingAlarm()->IsSet()); EXPECT_EQ(prev_deadline, connection_.GetPingAlarm()->deadline()); @@ -7394,7 +7473,8 @@ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5)); EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _)); - QuicAckFrame frame = InitAckFrame({{1, 2}}); + QuicAckFrame frame = + InitAckFrame({{QuicPacketNumber(1), QuicPacketNumber(2)}}); ProcessAckPacket(&frame); EXPECT_TRUE(connection_.GetPingAlarm()->IsSet()); EXPECT_EQ(clock_.ApproximateNow() + retransmittable_on_wire_timeout, @@ -7412,7 +7492,7 @@ // the wire. clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5)); EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _)); - frame = InitAckFrame({{2, 3}}); + frame = InitAckFrame({{QuicPacketNumber(2), QuicPacketNumber(3)}}); ProcessAckPacket(&frame); EXPECT_TRUE(connection_.GetPingAlarm()->IsSet()); EXPECT_EQ(clock_.ApproximateNow() + retransmittable_on_wire_timeout, @@ -7452,13 +7532,14 @@ EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _)); EXPECT_CALL(visitor_, OnForwardProgressConfirmed()); - QuicAckFrame frame = InitAckFrame({{1, 2}}); + QuicAckFrame frame = + InitAckFrame({{QuicPacketNumber(1), QuicPacketNumber(2)}}); ProcessAckPacket(&frame); // Ack packet 1 again. largest_acked remains at 1, so // OnForwardProgressConfirmed() should not be called. clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5)); - frame = InitAckFrame({{1, 2}}); + frame = InitAckFrame({{QuicPacketNumber(1), QuicPacketNumber(2)}}); ProcessAckPacket(&frame); // Ack packet 2. This increases the largest_acked to 2, so @@ -7466,7 +7547,7 @@ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5)); EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _)); EXPECT_CALL(visitor_, OnForwardProgressConfirmed()); - frame = InitAckFrame({{2, 3}}); + frame = InitAckFrame({{QuicPacketNumber(2), QuicPacketNumber(3)}}); ProcessAckPacket(&frame); } @@ -7655,7 +7736,7 @@ std::unique_ptr<QuicPacket> packet(ConstructDataPacket(2, !kHasStopWaiting)); char buffer[kMaxPacketSize]; size_t encrypted_length = peer_framer_.EncryptPayload( - ENCRYPTION_NONE, 2, *packet, buffer, kMaxPacketSize); + ENCRYPTION_NONE, QuicPacketNumber(2), *packet, buffer, kMaxPacketSize); // Make sure no stream frame is processed. EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(0); connection_.ProcessUdpPacket( @@ -7666,6 +7747,29 @@ EXPECT_EQ(1u, connection_.GetStats().packets_processed); } +TEST_P(QuicConnectionTest, AcceptPacketNumberZero) { + if (!GetQuicRestartFlag(quic_uint64max_uninitialized_pn) || + version().transport_version != QUIC_VERSION_99) { + return; + } + // Set first_sending_packet_number to be 0 to allow successfully processing + // acks which ack packet number 0. + QuicFramerPeer::SetFirstSendingPacketNumber(writer_->framer()->framer(), 0); + EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_)); + + ProcessPacket(0); + EXPECT_EQ(QuicPacketNumber(0), LargestAcked(*outgoing_ack())); + EXPECT_EQ(1u, outgoing_ack()->packets.NumIntervals()); + + ProcessPacket(1); + EXPECT_EQ(QuicPacketNumber(1), LargestAcked(*outgoing_ack())); + EXPECT_EQ(1u, outgoing_ack()->packets.NumIntervals()); + + ProcessPacket(2); + EXPECT_EQ(QuicPacketNumber(2), LargestAcked(*outgoing_ack())); + EXPECT_EQ(1u, outgoing_ack()->packets.NumIntervals()); +} + } // namespace } // namespace test } // namespace quic
diff --git a/quic/core/quic_constants.cc b/quic/core/quic_constants.cc index 344a94a..8e46f88 100644 --- a/quic/core/quic_constants.cc +++ b/quic/core/quic_constants.cc
@@ -11,4 +11,15 @@ const char* const kEPIDGoogleFrontEnd = "GFE"; const char* const kEPIDGoogleFrontEnd0 = "GFE0"; +QuicPacketNumber MaxRandomInitialPacketNumber() { + static const QuicPacketNumber kMaxRandomInitialPacketNumber = + QuicPacketNumber(0x7fffffff); + return kMaxRandomInitialPacketNumber; +} + +QuicPacketNumber FirstSendingPacketNumber() { + static const QuicPacketNumber kFirstSendingPacketNumber = QuicPacketNumber(1); + return kFirstSendingPacketNumber; +} + } // namespace quic
diff --git a/quic/core/quic_constants.h b/quic/core/quic_constants.h index fa76c21..cf27bef 100644 --- a/quic/core/quic_constants.h +++ b/quic/core/quic_constants.h
@@ -181,7 +181,7 @@ // The largest gap in packets we'll accept without closing the connection. // This will likely have to be tuned. -const QuicPacketNumber kMaxPacketGap = 5000; +const QuicPacketCount kMaxPacketGap = 5000; // The maximum number of random padding bytes to add. const QuicByteCount kMaxNumRandomPaddingBytes = 256; @@ -193,7 +193,7 @@ // For When using Random Initial Packet Numbers, they can start // anyplace in the range 1...((2^31)-1) or 0x7fffffff -const QuicPacketNumber kMaxRandomInitialPacketNumber = 0x7fffffff; +QUIC_EXPORT_PRIVATE QuicPacketNumber MaxRandomInitialPacketNumber(); // Used to represent an invalid or no control frame id. const QuicControlFrameId kInvalidControlFrameId = 0; @@ -224,8 +224,10 @@ // Maximum length allowed for the token in a NEW_TOKEN frame. const size_t kMaxNewTokenTokenLength = 0xffff; -// Used to represent an invalid packet number. -const QuicPacketNumber kInvalidPacketNumber = 0; +// Packet number of first sending packet of a connection. Please note, this +// cannot be used as first received packet because peer can choose its starting +// packet number. +QUIC_EXPORT_PRIVATE QuicPacketNumber FirstSendingPacketNumber(); // Used by clients to tell if a public reset is sent from a Google frontend. QUIC_EXPORT_PRIVATE extern const char* const kEPIDGoogleFrontEnd;
diff --git a/quic/core/quic_control_frame_manager.cc b/quic/core/quic_control_frame_manager.cc index ece6324..c2b5192 100644 --- a/quic/core/quic_control_frame_manager.cc +++ b/quic/core/quic_control_frame_manager.cc
@@ -17,9 +17,7 @@ : last_control_frame_id_(kInvalidControlFrameId), least_unacked_(1), least_unsent_(1), - session_(session), - donot_retransmit_old_window_updates_( - GetQuicReloadableFlag(quic_donot_retransmit_old_window_update2)) {} + session_(session) {} QuicControlFrameManager::~QuicControlFrameManager() { while (!control_frames_.empty()) { @@ -129,13 +127,11 @@ << "Send or retransmit a control frame with invalid control frame id"; return; } - if (donot_retransmit_old_window_updates_ && - frame.type == WINDOW_UPDATE_FRAME) { + if (frame.type == WINDOW_UPDATE_FRAME) { QuicStreamId stream_id = frame.window_update_frame->stream_id; if (QuicContainsKey(window_update_frames_, stream_id) && id > window_update_frames_[stream_id]) { // Consider the older window update of the same stream as acked. - QUIC_RELOADABLE_FLAG_COUNT(quic_donot_retransmit_old_window_update2); OnControlFrameIdAcked(window_update_frames_[stream_id]); } window_update_frames_[stream_id] = id; @@ -161,8 +157,7 @@ if (!OnControlFrameIdAcked(id)) { return false; } - if (donot_retransmit_old_window_updates_ && - frame.type == WINDOW_UPDATE_FRAME) { + if (frame.type == WINDOW_UPDATE_FRAME) { QuicStreamId stream_id = frame.window_update_frame->stream_id; if (QuicContainsKey(window_update_frames_, stream_id) && window_update_frames_[stream_id] == id) {
diff --git a/quic/core/quic_control_frame_manager.h b/quic/core/quic_control_frame_manager.h index a08d5c3..ace08c6 100644 --- a/quic/core/quic_control_frame_manager.h +++ b/quic/core/quic_control_frame_manager.h
@@ -102,12 +102,6 @@ // sent. bool WillingToWrite() const; - // TODO(wub): Remove this function once - // quic_donot_retransmit_old_window_update flag is deprecated. - bool donot_retransmit_old_window_updates() const { - return donot_retransmit_old_window_updates_; - } - private: friend class test::QuicControlFrameManagerPeer; @@ -158,9 +152,6 @@ // Last sent window update frame for each stream. QuicSmallMap<QuicStreamId, QuicControlFrameId, 10> window_update_frames_; - - // Latched value of quic_donot_retransmit_old_window_update2 flag. - const bool donot_retransmit_old_window_updates_; }; } // namespace quic
diff --git a/quic/core/quic_control_frame_manager_test.cc b/quic/core/quic_control_frame_manager_test.cc index a0e0b33..ccddadd 100644 --- a/quic/core/quic_control_frame_manager_test.cc +++ b/quic/core/quic_control_frame_manager_test.cc
@@ -235,7 +235,6 @@ } TEST_F(QuicControlFrameManagerTest, DonotRetransmitOldWindowUpdates) { - SetQuicReloadableFlag(quic_donot_retransmit_old_window_update2, true); Initialize(); // Send two more window updates of the same stream. manager_->WriteOrBufferWindowUpdate(kTestStreamId, 200); @@ -271,7 +270,6 @@ } TEST_F(QuicControlFrameManagerTest, RetransmitWindowUpdateOfDifferentStreams) { - SetQuicReloadableFlag(quic_donot_retransmit_old_window_update2, true); Initialize(); // Send two more window updates of different streams. manager_->WriteOrBufferWindowUpdate(kTestStreamId + 2, 200);
diff --git a/quic/core/quic_crypto_client_handshaker.cc b/quic/core/quic_crypto_client_handshaker.cc index 88bfccd..81487df 100644 --- a/quic/core/quic_crypto_client_handshaker.cc +++ b/quic/core/quic_crypto_client_handshaker.cc
@@ -338,11 +338,10 @@ "CHLO too large"); return; } - // TODO(rch): Remove this when we remove quic_use_chlo_packet_size flag. - out.set_minimum_size( - static_cast<size_t>(max_packet_size - kFramingOverhead)); next_state_ = STATE_RECV_REJ; CryptoUtils::HashHandshakeMessage(out, &chlo_hash_, Perspective::IS_CLIENT); + session()->connection()->set_fully_pad_crypto_hadshake_packets( + crypto_config_->pad_inchoate_hello()); SendHandshakeMessage(out); return; } @@ -377,6 +376,8 @@ *cached->proof_verify_details()); } next_state_ = STATE_RECV_SHLO; + session()->connection()->set_fully_pad_crypto_hadshake_packets( + crypto_config_->pad_full_hello()); SendHandshakeMessage(out); // Be prepared to decrypt with the new server write key. session()->connection()->SetAlternativeDecrypter(
diff --git a/quic/core/quic_crypto_client_handshaker_test.cc b/quic/core/quic_crypto_client_handshaker_test.cc new file mode 100644 index 0000000..389be97 --- /dev/null +++ b/quic/core/quic_crypto_client_handshaker_test.cc
@@ -0,0 +1,213 @@ +// Copyright (c) 2012 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/quic_crypto_client_handshaker.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "net/third_party/quiche/src/quic/core/proto/crypto_server_config.proto.h" +#include "net/third_party/quiche/src/quic/core/tls_client_handshaker.h" +#include "net/third_party/quiche/src/quic/core/tls_server_handshaker.h" +#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h" + +namespace quic { +namespace { + +using ::testing::Test; + +class TestProofHandler : public QuicCryptoClientStream::ProofHandler { + public: + ~TestProofHandler() override {} + void OnProofValid( + const QuicCryptoClientConfig::CachedState& cached) override {} + void OnProofVerifyDetailsAvailable( + const ProofVerifyDetails& verify_details) override {} +}; + +class InsecureProofVerifier : public ProofVerifier { + public: + InsecureProofVerifier() {} + ~InsecureProofVerifier() override {} + + // ProofVerifier override. + QuicAsyncStatus VerifyProof( + const QuicString& hostname, + const uint16_t port, + const QuicString& server_config, + QuicTransportVersion transport_version, + QuicStringPiece chlo_hash, + const std::vector<QuicString>& certs, + const QuicString& cert_sct, + const QuicString& signature, + const ProofVerifyContext* context, + QuicString* error_details, + std::unique_ptr<ProofVerifyDetails>* verify_details, + std::unique_ptr<ProofVerifierCallback> callback) override { + return QUIC_SUCCESS; + } + + QuicAsyncStatus VerifyCertChain( + const QuicString& hostname, + const std::vector<QuicString>& certs, + const ProofVerifyContext* context, + QuicString* error_details, + std::unique_ptr<ProofVerifyDetails>* details, + std::unique_ptr<ProofVerifierCallback> callback) override { + return QUIC_SUCCESS; + } + + std::unique_ptr<ProofVerifyContext> CreateDefaultContext() override { + return nullptr; + } +}; + +class DummyProofSource : public ProofSource { + public: + DummyProofSource() {} + ~DummyProofSource() override {} + + // ProofSource override. + void GetProof(const QuicSocketAddress& server_address, + const QuicString& hostname, + const QuicString& server_config, + QuicTransportVersion transport_version, + QuicStringPiece chlo_hash, + std::unique_ptr<Callback> callback) override { + QuicReferenceCountedPointer<ProofSource::Chain> chain = + GetCertChain(server_address, hostname); + QuicCryptoProof proof; + proof.signature = "Dummy signature"; + proof.leaf_cert_scts = "Dummy timestamp"; + callback->Run(true, chain, proof, nullptr /* details */); + } + + QuicReferenceCountedPointer<Chain> GetCertChain( + const QuicSocketAddress& server_address, + const QuicString& hostname) override { + std::vector<QuicString> certs; + certs.push_back("Dummy cert"); + return QuicReferenceCountedPointer<ProofSource::Chain>( + new ProofSource::Chain(certs)); + } + + void ComputeTlsSignature( + const QuicSocketAddress& server_address, + const QuicString& hostname, + uint16_t signature_algorithm, + QuicStringPiece in, + std::unique_ptr<SignatureCallback> callback) override { + callback->Run(true, "Dummy signature"); + } +}; + +class Handshaker : public QuicCryptoClientHandshaker { + public: + Handshaker(const QuicServerId& server_id, + QuicCryptoClientStream* stream, + QuicSession* session, + std::unique_ptr<ProofVerifyContext> verify_context, + QuicCryptoClientConfig* crypto_config, + QuicCryptoClientStream::ProofHandler* proof_handler) + : QuicCryptoClientHandshaker(server_id, + stream, + session, + std::move(verify_context), + crypto_config, + proof_handler) {} + + void DoSendCHLOTest(QuicCryptoClientConfig::CachedState* cached) { + QuicCryptoClientHandshaker::DoSendCHLO(cached); + } +}; + +class QuicCryptoClientHandshakerTest : public Test { + protected: + QuicCryptoClientHandshakerTest() + : proof_handler_(), + helper_(), + alarm_factory_(), + server_id_("host", 123), + connection_(new test::MockQuicConnection(&helper_, + &alarm_factory_, + Perspective::IS_CLIENT)), + session_(connection_, false), + crypto_client_config_(QuicMakeUnique<InsecureProofVerifier>(), + quic::TlsClientHandshaker::CreateSslCtx()), + client_stream_(new QuicCryptoClientStream(server_id_, + &session_, + nullptr, + &crypto_client_config_, + &proof_handler_)), + handshaker_(server_id_, + client_stream_, + &session_, + nullptr, + &crypto_client_config_, + &proof_handler_), + state_() { + // Session takes the ownership of the client stream! (but handshaker also + // takes a reference to it, but doesn't take the ownership). + session_.SetCryptoStream(client_stream_); + session_.Initialize(); + } + + void InitializeServerParametersToEnableFullHello() { + QuicCryptoServerConfig::ConfigOptions options; + std::unique_ptr<QuicServerConfigProtobuf> config = + QuicCryptoServerConfig::GenerateConfig(helper_.GetRandomGenerator(), + helper_.GetClock(), options); + state_.Initialize( + config->config(), "sourcetoken", std::vector<QuicString>{"Dummy cert"}, + "", "chlo_hash", "signature", helper_.GetClock()->WallNow(), + helper_.GetClock()->WallNow().Add(QuicTime::Delta::FromSeconds(30))); + + state_.SetProofValid(); + } + + TestProofHandler proof_handler_; + test::MockQuicConnectionHelper helper_; + test::MockAlarmFactory alarm_factory_; + QuicServerId server_id_; + // Session takes the ownership of the connection. + test::MockQuicConnection* connection_; + test::MockQuicSession session_; + QuicCryptoClientConfig crypto_client_config_; + QuicCryptoClientStream* client_stream_; + Handshaker handshaker_; + QuicCryptoClientConfig::CachedState state_; +}; + +TEST_F(QuicCryptoClientHandshakerTest, TestSendFullPaddingInInchoateHello) { + handshaker_.DoSendCHLOTest(&state_); + + EXPECT_TRUE(connection_->fully_pad_during_crypto_handshake()); +} + +TEST_F(QuicCryptoClientHandshakerTest, TestDisabledPaddingInInchoateHello) { + crypto_client_config_.set_pad_inchoate_hello(false); + handshaker_.DoSendCHLOTest(&state_); + EXPECT_FALSE(connection_->fully_pad_during_crypto_handshake()); +} + +TEST_F(QuicCryptoClientHandshakerTest, + TestPaddingInFullHelloEvenIfInchoateDisabled) { + // Disable inchoate, but full hello should still be padded. + crypto_client_config_.set_pad_inchoate_hello(false); + + InitializeServerParametersToEnableFullHello(); + + handshaker_.DoSendCHLOTest(&state_); + EXPECT_TRUE(connection_->fully_pad_during_crypto_handshake()); +} + +TEST_F(QuicCryptoClientHandshakerTest, TestNoPaddingInFullHelloWhenDisabled) { + crypto_client_config_.set_pad_full_hello(false); + + InitializeServerParametersToEnableFullHello(); + + handshaker_.DoSendCHLOTest(&state_); + EXPECT_FALSE(connection_->fully_pad_during_crypto_handshake()); +} + +} // namespace +} // namespace quic
diff --git a/quic/core/quic_crypto_client_stream_test.cc b/quic/core/quic_crypto_client_stream_test.cc index 14f34a7..d9b344a 100644 --- a/quic/core/quic_crypto_client_stream_test.cc +++ b/quic/core/quic_crypto_client_stream_test.cc
@@ -329,54 +329,6 @@ EXPECT_FALSE(stream()->WasChannelIDSourceCallbackRun()); } -TEST_F(QuicCryptoClientStreamTest, TokenBindingNegotiation) { - server_options_.token_binding_params = QuicTagVector{kTB10, kP256}; - crypto_config_.tb_key_params = QuicTagVector{kTB10}; - - CompleteCryptoHandshake(); - EXPECT_TRUE(stream()->encryption_established()); - EXPECT_TRUE(stream()->handshake_confirmed()); - EXPECT_EQ(kTB10, - stream()->crypto_negotiated_params().token_binding_key_param); -} - -TEST_F(QuicCryptoClientStreamTest, NoTokenBindingWithoutServerSupport) { - crypto_config_.tb_key_params = QuicTagVector{kTB10, kP256}; - - CompleteCryptoHandshake(); - EXPECT_TRUE(stream()->encryption_established()); - EXPECT_TRUE(stream()->handshake_confirmed()); - EXPECT_EQ(0u, stream()->crypto_negotiated_params().token_binding_key_param); -} - -TEST_F(QuicCryptoClientStreamTest, NoTokenBindingWithoutClientSupport) { - server_options_.token_binding_params = QuicTagVector{kTB10, kP256}; - - CompleteCryptoHandshake(); - EXPECT_TRUE(stream()->encryption_established()); - EXPECT_TRUE(stream()->handshake_confirmed()); - EXPECT_EQ(0u, stream()->crypto_negotiated_params().token_binding_key_param); -} - -TEST_F(QuicCryptoClientStreamTest, TokenBindingNotNegotiated) { - CompleteCryptoHandshake(); - EXPECT_TRUE(stream()->encryption_established()); - EXPECT_TRUE(stream()->handshake_confirmed()); - EXPECT_EQ(0u, stream()->crypto_negotiated_params().token_binding_key_param); -} - -TEST_F(QuicCryptoClientStreamTest, NoTokenBindingInPrivacyMode) { - server_options_.token_binding_params = QuicTagVector{kTB10}; - crypto_config_.tb_key_params = QuicTagVector{kTB10}; - server_id_ = QuicServerId(kServerHostname, kServerPort, true); - CreateConnection(); - - CompleteCryptoHandshake(); - EXPECT_TRUE(stream()->encryption_established()); - EXPECT_TRUE(stream()->handshake_confirmed()); - EXPECT_EQ(0u, stream()->crypto_negotiated_params().token_binding_key_param); -} - TEST_F(QuicCryptoClientStreamTest, PreferredVersion) { // This mimics the case where client receives version negotiation packet, such // that, the preferred version is different from the packets' version. @@ -440,7 +392,7 @@ client_session_->GetMutableCryptoStream()->CryptoConnect(); EXPECT_CALL(*server_session_->helper(), CanAcceptClientHello(_, _, _, _, _)) .Times(testing::AnyNumber()); - EXPECT_CALL(*server_session_->helper(), GenerateConnectionIdForReject(_)) + EXPECT_CALL(*server_session_->helper(), GenerateConnectionIdForReject(_, _)) .Times(testing::AnyNumber()); crypto_test_utils::AdvanceHandshake( client_connection_, client_session_->GetMutableCryptoStream(), 0,
diff --git a/quic/core/quic_crypto_server_handshaker.cc b/quic/core/quic_crypto_server_handshaker.cc index 2b38c4b..e79a60c 100644 --- a/quic/core/quic_crypto_server_handshaker.cc +++ b/quic/core/quic_crypto_server_handshaker.cc
@@ -184,6 +184,8 @@ // retransmitted. session()->connection()->EnableSavingCryptoPackets(); } + session()->connection()->set_fully_pad_crypto_hadshake_packets( + crypto_config_->pad_rej()); SendHandshakeMessage(*reply); if (reply->tag() == kSREJ) { @@ -233,6 +235,8 @@ std::move(crypto_negotiated_params_->initial_crypters.decrypter)); session()->connection()->SetDiversificationNonce(*diversification_nonce); + session()->connection()->set_fully_pad_crypto_hadshake_packets( + crypto_config_->pad_shlo()); SendHandshakeMessage(*reply); session()->connection()->SetEncrypter( @@ -463,7 +467,7 @@ return EmptyQuicConnectionId(); } return helper_->GenerateConnectionIdForReject( - session()->connection()->connection_id()); + transport_version(), session()->connection()->connection_id()); } const QuicSocketAddress QuicCryptoServerHandshaker::GetClientAddress() {
diff --git a/quic/core/quic_crypto_server_stream.h b/quic/core/quic_crypto_server_stream.h index 63de376..c4de9b0 100644 --- a/quic/core/quic_crypto_server_stream.h +++ b/quic/core/quic_crypto_server_stream.h
@@ -141,6 +141,7 @@ // Given the current connection_id, generates a new ConnectionId to // be returned with a stateless reject. virtual QuicConnectionId GenerateConnectionIdForReject( + QuicTransportVersion version, QuicConnectionId connection_id) const = 0; // Returns true if |message|, which was received on |self_address| is
diff --git a/quic/core/quic_crypto_server_stream_test.cc b/quic/core/quic_crypto_server_stream_test.cc index 027e412..33635d8 100644 --- a/quic/core/quic_crypto_server_stream_test.cc +++ b/quic/core/quic_crypto_server_stream_test.cc
@@ -104,7 +104,7 @@ server_session_.reset(server_session); EXPECT_CALL(*server_session_->helper(), CanAcceptClientHello(_, _, _, _, _)) .Times(testing::AnyNumber()); - EXPECT_CALL(*server_session_->helper(), GenerateConnectionIdForReject(_)) + EXPECT_CALL(*server_session_->helper(), GenerateConnectionIdForReject(_, _)) .Times(testing::AnyNumber()); crypto_test_utils::FakeServerOptions options; options.token_binding_params = QuicTagVector{kTB10}; @@ -489,28 +489,6 @@ QuicCryptoServerStreamPeer::DoesPeerSupportStatelessRejects(message_)); } -TEST_P(QuicCryptoServerStreamTest, TokenBindingNegotiated) { - Initialize(); - - client_options_.token_binding_params = QuicTagVector{kTB10, kP256}; - CompleteCryptoHandshake(); - EXPECT_EQ( - kTB10, - server_stream()->crypto_negotiated_params().token_binding_key_param); - EXPECT_TRUE(server_stream()->encryption_established()); - EXPECT_TRUE(server_stream()->handshake_confirmed()); -} - -TEST_P(QuicCryptoServerStreamTest, NoTokenBindingWithoutClientSupport) { - Initialize(); - - CompleteCryptoHandshake(); - EXPECT_EQ( - 0u, server_stream()->crypto_negotiated_params().token_binding_key_param); - EXPECT_TRUE(server_stream()->encryption_established()); - EXPECT_TRUE(server_stream()->handshake_confirmed()); -} - class QuicCryptoServerStreamTestWithFailingProofSource : public QuicCryptoServerStreamTest { public:
diff --git a/quic/core/quic_crypto_stream.cc b/quic/core/quic_crypto_stream.cc index 440a480..8199571 100644 --- a/quic/core/quic_crypto_stream.cc +++ b/quic/core/quic_crypto_stream.cc
@@ -111,19 +111,6 @@ result); } -bool QuicCryptoStream::ExportTokenBindingKeyingMaterial( - QuicString* result) const { - if (!encryption_established()) { - QUIC_BUG << "ExportTokenBindingKeyingMaterial was called before initial" - << "encryption was established."; - return false; - } - return CryptoUtils::ExportKeyingMaterial( - crypto_negotiated_params().initial_subkey_secret, - "EXPORTER-Token-Binding", - /* context= */ "", 32, result); -} - void QuicCryptoStream::WriteCryptoData(EncryptionLevel level, QuicStringPiece data) { // TODO(nharper): This approach to writing data, by setting the encryption
diff --git a/quic/core/quic_crypto_stream.h b/quic/core/quic_crypto_stream.h index a2cf9fe..0593f44 100644 --- a/quic/core/quic_crypto_stream.h +++ b/quic/core/quic_crypto_stream.h
@@ -56,16 +56,6 @@ size_t result_len, QuicString* result) const; - // Performs key extraction for Token Binding. Unlike ExportKeyingMaterial, - // this function can be called before forward-secure encryption is - // established. Returns false if initial encryption has not been established, - // and true on success. - // - // Since this depends only on the initial keys, a signature over it can be - // repurposed by an attacker who obtains the client's or server's DH private - // value. - bool ExportTokenBindingKeyingMaterial(QuicString* result) const; - // Writes |data| to the QuicStream at level |level|. virtual void WriteCryptoData(EncryptionLevel level, QuicStringPiece data);
diff --git a/quic/core/quic_default_packet_writer.cc b/quic/core/quic_default_packet_writer.cc index 6e8e833..2c162e0 100644 --- a/quic/core/quic_default_packet_writer.cc +++ b/quic/core/quic_default_packet_writer.cc
@@ -24,7 +24,7 @@ << "QuicDefaultPacketWriter does not accept any options."; WriteResult result = QuicSocketUtils::WritePacket(fd_, buffer, buf_len, self_address, peer_address); - if (result.status == WRITE_STATUS_BLOCKED) { + if (IsWriteBlockedStatus(result.status)) { write_blocked_ = true; } return result;
diff --git a/quic/core/quic_dispatcher.cc b/quic/core/quic_dispatcher.cc index f476a47..0cb03aa 100644 --- a/quic/core/quic_dispatcher.cc +++ b/quic/core/quic_dispatcher.cc
@@ -92,6 +92,13 @@ } return WRITE_FAILED; } + bool WriteCryptoData(EncryptionLevel level, + QuicStreamOffset offset, + QuicByteCount data_length, + QuicDataWriter* writer) override { + QUIC_BUG << "PacketCollector::WriteCryptoData is unimplemented."; + return false; + } std::vector<std::unique_ptr<QuicEncryptedPacket>>* packets() { return &packets_; @@ -235,9 +242,9 @@ if (helper_->CanAcceptClientHello(chlo, client_address_, peer_address_, self_address_, &error_details_)) { can_accept_ = true; - rejector_->OnChlo(version, connection_id, - helper_->GenerateConnectionIdForReject(connection_id), - chlo); + rejector_->OnChlo( + version, connection_id, + helper_->GenerateConnectionIdForReject(version, connection_id), chlo); } } @@ -506,27 +513,29 @@ } // initial packet number of 0 is always invalid. - if (header.packet_number == kInvalidPacketNumber) { + if (!header.packet_number.IsInitialized()) { return kFateTimeWait; } if (GetQuicRestartFlag(quic_enable_accept_random_ipn)) { QUIC_RESTART_FLAG_COUNT_N(quic_enable_accept_random_ipn, 1, 2); // Accepting Initial Packet Numbers in 1...((2^31)-1) range... check // maximum accordingly. - if (header.packet_number > kMaxRandomInitialPacketNumber) { + if (header.packet_number > MaxRandomInitialPacketNumber()) { return kFateTimeWait; } } else { // 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 > kMaxReasonableInitialPacketNumber) && - (header.packet_number <= kMaxRandomInitialPacketNumber)) { + if ((header.packet_number > + QuicPacketNumber(kMaxReasonableInitialPacketNumber)) && + (header.packet_number <= MaxRandomInitialPacketNumber())) { QUIC_CODE_COUNT_N(had_possibly_random_ipn, 1, 2); } // Check that the sequence number is within the range that the client is // expected to send before receiving a response from the server. - if (header.packet_number > kMaxReasonableInitialPacketNumber) { + if (header.packet_number > + QuicPacketNumber(kMaxReasonableInitialPacketNumber)) { return kFateTimeWait; } } @@ -552,9 +561,7 @@ // expediency. Stop doing this when removing flag // quic_always_reset_ietf_connections. if (!GetQuicReloadableFlag(quic_always_reset_ietf_connections) && - (!GetQuicReloadableFlag( - quic_send_reset_for_post_handshake_connections_without_termination_packets) || // NOLINT - (source == ConnectionCloseSource::FROM_PEER))) { + source == ConnectionCloseSource::FROM_PEER) { action = QuicTimeWaitListManager::DO_NOTHING; } else if (!connection->IsHandshakeConfirmed()) { QUIC_CODE_COUNT(quic_v44_add_to_time_wait_list_with_handshake_failed); @@ -727,6 +734,8 @@ void QuicDispatcher::OnRstStreamReceived(const QuicRstStreamFrame& frame) {} +void QuicDispatcher::OnStopSendingReceived(const QuicStopSendingFrame& frame) {} + void QuicDispatcher::OnConnectionAddedToTimeWaitList( QuicConnectionId connection_id) { QUIC_DLOG(INFO) << "Connection " << connection_id
diff --git a/quic/core/quic_dispatcher.h b/quic/core/quic_dispatcher.h index 3597a97..d6eb35b 100644 --- a/quic/core/quic_dispatcher.h +++ b/quic/core/quic_dispatcher.h
@@ -91,6 +91,11 @@ // Collects reset error code received on streams. void OnRstStreamReceived(const QuicRstStreamFrame& frame) override; + // QuicSession::Visitor interface implementation (via inheritance of + // QuicTimeWaitListManager::Visitor): + // Collects reset error code received on streams. + void OnStopSendingReceived(const QuicStopSendingFrame& frame) override; + // QuicTimeWaitListManager::Visitor interface implementation // Called whenever the time wait list manager adds a new connection to the // time-wait list. @@ -110,7 +115,7 @@ // send a handshake and then up to 50 or so data packets, and then it may // resend the handshake packet up to 10 times. (Retransmitted packets are // sent with unique packet numbers.) - static const QuicPacketNumber kMaxReasonableInitialPacketNumber = 100; + static const uint64_t kMaxReasonableInitialPacketNumber = 100; static_assert(kMaxReasonableInitialPacketNumber >= kInitialCongestionWindow + 10, "kMaxReasonableInitialPacketNumber is unreasonably small " @@ -348,7 +353,7 @@ // Please do not use this method. // TODO(fayang): Remove this method when deprecating - // quic_proxy_use_real_packet_format_when_reject flag. + // quic_fix_last_packet_is_ietf_quic flag. PacketHeaderFormat GetLastPacketFormat() const; private:
diff --git a/quic/core/quic_dispatcher_test.cc b/quic/core/quic_dispatcher_test.cc index afc4687..0381cf5 100644 --- a/quic/core/quic_dispatcher_test.cc +++ b/quic/core/quic_dispatcher_test.cc
@@ -268,7 +268,7 @@ const QuicString& data, QuicConnectionIdLength connection_id_length, QuicPacketNumberLength packet_number_length, - QuicPacketNumber packet_number) { + uint64_t packet_number) { ProcessPacket(peer_address, connection_id, has_version_flag, CurrentSupportedVersions().front(), data, connection_id_length, packet_number_length, packet_number); @@ -282,7 +282,7 @@ const QuicString& data, QuicConnectionIdLength connection_id_length, QuicPacketNumberLength packet_number_length, - QuicPacketNumber packet_number) { + uint64_t packet_number) { ParsedQuicVersionVector versions(SupportedVersions(version)); std::unique_ptr<QuicEncryptedPacket> packet(ConstructEncryptedPacket( connection_id, EmptyQuicConnectionId(), has_version_flag, false, @@ -676,18 +676,19 @@ SetQuicRestartFlag(quic_enable_accept_random_ipn, true); ProcessPacket(client_address, connection_id, true, SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID, PACKET_4BYTE_PACKET_NUMBER, - kMaxRandomInitialPacketNumber + + MaxRandomInitialPacketNumber().ToUint64() + QuicDispatcher::kMaxReasonableInitialPacketNumber + 1); } TEST_F(QuicDispatcherTest, SupportedTransportVersionsChangeInFlight) { - static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 7u, + static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 8u, "Supported versions out of sync"); SetQuicReloadableFlag(quic_disable_version_35, 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); @@ -741,6 +742,39 @@ SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID, PACKET_4BYTE_PACKET_NUMBER, 1); + // Turn off version 47. + SetQuicReloadableFlag(quic_enable_version_47, 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_47), + SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID, + PACKET_4BYTE_PACKET_NUMBER, 1); + + // Turn on version 47. + SetQuicReloadableFlag(quic_enable_version_47, 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_47), + SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID, + PACKET_4BYTE_PACKET_NUMBER, 1); + // Turn off version 46. SetQuicReloadableFlag(quic_enable_version_46, false); connection_id = TestConnectionId(++conn_id); @@ -1956,7 +1990,7 @@ // Process another |kDefaultMaxUndecryptablePackets| + 1 data packets. The // last one should be dropped. - for (QuicPacketNumber packet_number = 2; + for (uint64_t packet_number = 2; packet_number <= kDefaultMaxUndecryptablePackets + 2; ++packet_number) { ProcessPacket(client_addr_, last_connection_id, true, "data packet"); }
diff --git a/quic/core/quic_epoll_alarm_factory.cc b/quic/core/quic_epoll_alarm_factory.cc index 550ee13..2ec2f6f 100644 --- a/quic/core/quic_epoll_alarm_factory.cc +++ b/quic/core/quic_epoll_alarm_factory.cc
@@ -14,7 +14,7 @@ class QuicEpollAlarm : public QuicAlarm { public: - QuicEpollAlarm(gfe2::EpollServer* epoll_server, + QuicEpollAlarm(QuicEpollServer* epoll_server, QuicArenaScopedPtr<QuicAlarm::Delegate> delegate) : QuicAlarm(std::move(delegate)), epoll_server_(epoll_server), @@ -44,13 +44,13 @@ } private: - class EpollAlarmImpl : public gfe2::EpollAlarm { + class EpollAlarmImpl : public QuicEpollAlarmBase { public: explicit EpollAlarmImpl(QuicEpollAlarm* alarm) : alarm_(alarm) {} // Use the same integer type as the base class. int64 /* allow-non-std-int */ OnAlarm() override { - EpollAlarm::OnAlarm(); + QuicEpollAlarmBase::OnAlarm(); alarm_->Fire(); // Fire will take care of registering the alarm, if needed. return 0; @@ -60,13 +60,13 @@ QuicEpollAlarm* alarm_; }; - gfe2::EpollServer* epoll_server_; + QuicEpollServer* epoll_server_; EpollAlarmImpl epoll_alarm_impl_; }; } // namespace -QuicEpollAlarmFactory::QuicEpollAlarmFactory(gfe2::EpollServer* epoll_server) +QuicEpollAlarmFactory::QuicEpollAlarmFactory(QuicEpollServer* epoll_server) : epoll_server_(epoll_server) {} QuicEpollAlarmFactory::~QuicEpollAlarmFactory() {}
diff --git a/quic/core/quic_epoll_alarm_factory.h b/quic/core/quic_epoll_alarm_factory.h index d1ec7ca..fc9b45c 100644 --- a/quic/core/quic_epoll_alarm_factory.h +++ b/quic/core/quic_epoll_alarm_factory.h
@@ -5,17 +5,17 @@ #ifndef QUICHE_QUIC_CORE_QUIC_EPOLL_ALARM_FACTORY_H_ #define QUICHE_QUIC_CORE_QUIC_EPOLL_ALARM_FACTORY_H_ -#include "gfe/gfe2/base/epoll_server.h" #include "net/third_party/quiche/src/quic/core/quic_alarm.h" #include "net/third_party/quiche/src/quic/core/quic_alarm_factory.h" #include "net/third_party/quiche/src/quic/core/quic_one_block_arena.h" +#include "net/third_party/quiche/src/quic/platform/api/quic_epoll.h" namespace quic { // Creates alarms that use the supplied EpollServer for timing and firing. class QuicEpollAlarmFactory : public QuicAlarmFactory { public: - explicit QuicEpollAlarmFactory(gfe2::EpollServer* eps); + explicit QuicEpollAlarmFactory(QuicEpollServer* eps); QuicEpollAlarmFactory(const QuicEpollAlarmFactory&) = delete; QuicEpollAlarmFactory& operator=(const QuicEpollAlarmFactory&) = delete; ~QuicEpollAlarmFactory() override; @@ -27,7 +27,7 @@ QuicConnectionArena* arena) override; private: - gfe2::EpollServer* epoll_server_; // Not owned. + QuicEpollServer* epoll_server_; // Not owned. }; } // namespace quic
diff --git a/quic/core/quic_epoll_connection_helper.cc b/quic/core/quic_epoll_connection_helper.cc index 3070c99..49002f6 100644 --- a/quic/core/quic_epoll_connection_helper.cc +++ b/quic/core/quic_epoll_connection_helper.cc
@@ -16,7 +16,7 @@ namespace quic { QuicEpollConnectionHelper::QuicEpollConnectionHelper( - gfe2::EpollServer* epoll_server, + QuicEpollServer* epoll_server, QuicAllocator type) : clock_(epoll_server), random_generator_(QuicRandom::GetInstance()),
diff --git a/quic/core/quic_epoll_connection_helper.h b/quic/core/quic_epoll_connection_helper.h index 858954a..62e030c 100644 --- a/quic/core/quic_epoll_connection_helper.h +++ b/quic/core/quic_epoll_connection_helper.h
@@ -18,6 +18,7 @@ #include "net/third_party/quiche/src/quic/core/quic_packets.h" #include "net/third_party/quiche/src/quic/core/quic_simple_buffer_allocator.h" #include "net/third_party/quiche/src/quic/core/quic_time.h" +#include "net/third_party/quiche/src/quic/platform/api/quic_epoll.h" #include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h" #include "net/quic/platform/impl/quic_epoll_clock.h" @@ -43,7 +44,7 @@ class QuicEpollConnectionHelper : public QuicConnectionHelperInterface { public: - QuicEpollConnectionHelper(gfe2::EpollServer* eps, QuicAllocator allocator); + QuicEpollConnectionHelper(QuicEpollServer* eps, QuicAllocator allocator); QuicEpollConnectionHelper(const QuicEpollConnectionHelper&) = delete; QuicEpollConnectionHelper& operator=(const QuicEpollConnectionHelper&) = delete;
diff --git a/quic/core/quic_framer.cc b/quic/core/quic_framer.cc index e659b38..1b93074 100644 --- a/quic/core/quic_framer.cc +++ b/quic/core/quic_framer.cc
@@ -130,7 +130,7 @@ const uint8_t kSourceConnectionIdLengthMask = 0x0F; // Returns the absolute value of the difference between |a| and |b|. -QuicPacketNumber Delta(QuicPacketNumber a, QuicPacketNumber b) { +uint64_t Delta(uint64_t a, uint64_t b) { // Since these are unsigned numbers, we can't just return abs(a - b) if (a < b) { return b - a; @@ -138,12 +138,18 @@ return a - b; } -QuicPacketNumber ClosestTo(QuicPacketNumber target, - QuicPacketNumber a, - QuicPacketNumber b) { +uint64_t ClosestTo(uint64_t target, uint64_t a, uint64_t b) { return (Delta(target, a) < Delta(target, b)) ? a : b; } +uint64_t PacketNumberIntervalLength( + const QuicInterval<QuicPacketNumber>& interval) { + if (interval.Empty()) { + return 0u; + } + return interval.max() - interval.min(); +} + QuicPacketNumberLength ReadSequenceNumberLength(uint8_t flags) { switch (flags & PACKET_FLAGS_8BYTE_PACKET) { case PACKET_FLAGS_8BYTE_PACKET: @@ -180,7 +186,7 @@ uint8_t PacketNumberLengthToOnWireValue( QuicTransportVersion version, QuicPacketNumberLength packet_number_length) { - if (version == QUIC_VERSION_99) { + if (version > QUIC_VERSION_46) { return packet_number_length - 1; } switch (packet_number_length) { @@ -203,7 +209,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_99 + infer_packet_header_type_from_version ? version > QUIC_VERSION_46 : (type & FLAGS_FIXED_BIT); if (two_bits_packet_number_length) { *packet_number_length = @@ -231,13 +237,13 @@ QuicLongHeaderType type) { switch (type) { case INITIAL: - return version == QUIC_VERSION_99 ? 0 : 0x7F; + return version > QUIC_VERSION_46 ? 0 : 0x7F; case ZERO_RTT_PROTECTED: - return version == QUIC_VERSION_99 ? 1 << 4 : 0x7C; + return version > QUIC_VERSION_46 ? 1 << 4 : 0x7C; case HANDSHAKE: - return version == QUIC_VERSION_99 ? 2 << 4 : 0x7D; + return version > QUIC_VERSION_46 ? 2 << 4 : 0x7D; case RETRY: - return version == QUIC_VERSION_99 ? 3 << 4 : 0x7E; + return version > QUIC_VERSION_46 ? 3 << 4 : 0x7E; case VERSION_NEGOTIATION: return 0xF0; // Value does not matter default: @@ -250,7 +256,7 @@ uint8_t type, QuicLongHeaderType* long_header_type) { DCHECK((type & FLAGS_LONG_HEADER) && version != QUIC_VERSION_UNSUPPORTED); - if (version == QUIC_VERSION_99) { + if (version > QUIC_VERSION_46) { switch ((type & 0x30) >> 4) { case 0: *long_header_type = INITIAL; @@ -297,7 +303,7 @@ QuicPacketNumberLength GetLongHeaderPacketNumberLength( QuicTransportVersion version, uint8_t type) { - if (version == QUIC_VERSION_99) { + if (version > QUIC_VERSION_46) { return static_cast<QuicPacketNumberLength>((type & 0x03) + 1); } return PACKET_4BYTE_PACKET_NUMBER; @@ -324,6 +330,19 @@ return static_cast<uint8_t>(length - kConnectionIdLengthAdjustment); } +bool IsValidPacketNumberLength(QuicPacketNumberLength packet_number_length) { + size_t length = packet_number_length; + return length == 1 || length == 2 || length == 4 || length == 6 || + length == 8; +} + +bool IsValidFullPacketNumber(uint64_t full_packet_number, + QuicTransportVersion version) { + return full_packet_number > 0 || + (GetQuicRestartFlag(quic_uint64max_uninitialized_pn) && + version == QUIC_VERSION_99); +} + } // namespace QuicFramer::QuicFramer(const ParsedQuicVersionVector& supported_versions, @@ -331,7 +350,6 @@ Perspective perspective) : visitor_(nullptr), error_(QUIC_NO_ERROR), - largest_packet_number_(0), last_serialized_connection_id_(EmptyQuicConnectionId()), last_version_label_(0), last_header_form_(GOOGLE_QUIC_PACKET), @@ -345,9 +363,8 @@ process_timestamps_(false), creation_time_(creation_time), last_timestamp_(QuicTime::Delta::Zero()), + first_sending_packet_number_(FirstSendingPacketNumber()), data_producer_(nullptr), - process_stateless_reset_at_client_only_( - GetQuicReloadableFlag(quic_process_stateless_reset_at_client_only)), infer_packet_header_type_from_version_(perspective == Perspective::IS_CLIENT) { DCHECK(!supported_versions.empty()); @@ -377,6 +394,13 @@ } // static +size_t QuicFramer::GetMinCryptoFrameSize(QuicStreamOffset offset, + QuicPacketLength data_length) { + return kQuicFrameTypeSize + QuicDataWriter::GetVarInt62Len(offset) + + QuicDataWriter::GetVarInt62Len(data_length); +} + +// static size_t QuicFramer::GetMessageFrameSize(QuicTransportVersion version, bool last_frame_in_packet, QuicByteCount length) { @@ -500,6 +524,9 @@ 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) { // return size of IETF QUIC Blocked frame return kQuicFrameTypeSize + QuicDataWriter::GetVarInt62Len(frame.offset); @@ -869,7 +896,6 @@ 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"; @@ -1050,10 +1076,30 @@ return writer.length(); } +size_t QuicFramer::BuildIetfConnectivityProbingPacket( + const QuicPacketHeader& header, + char* buffer, + size_t packet_length) { + QuicFrames frames; + + // Write a PING frame, which has no data payload. + QuicPingFrame ping_frame; + frames.push_back(QuicFrame(ping_frame)); + + // Add padding to the rest of the packet. + QuicPaddingFrame padding_frame; + frames.push_back(QuicFrame(padding_frame)); + + return BuildIetfDataPacket(header, frames, buffer, packet_length); +} + 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); + } QuicDataWriter writer(packet_length, buffer, endianness()); if (!AppendPacketHeader(header, &writer)) { @@ -1088,47 +1134,25 @@ size_t packet_length, QuicPathFrameBuffer* payload, QuicRandom* randomizer) { - QuicDataWriter writer(packet_length, buffer, endianness()); - DCHECK_EQ(version_.transport_version, QUIC_VERSION_99) - << "Attempt to build a PATH_CHALLENGE Connectivity Probing packet and " - "not doing IETF QUIC"; - - if (!AppendPacketHeader(header, &writer)) { - QUIC_BUG << "AppendPacketHeader failed"; + if (version_.transport_version != QUIC_VERSION_99) { + QUIC_BUG << "Attempt to build a PATH_CHALLENGE Connectivity Probing " + "packet and not doing IETF QUIC"; return 0; } + QuicFrames frames; // Write a PATH_CHALLENGE frame, which has a random 8-byte payload randomizer->RandBytes(payload->data(), payload->size()); QuicPathChallengeFrame path_challenge_frame(0, *payload); - if (!AppendTypeByte(QuicFrame(&path_challenge_frame), - /* last_frame_in_packet = */ false, &writer)) { - QUIC_BUG - << "AppendTypeByte failed for PATH_CHALLENGE frame in probing packet"; - return 0; - } - - if (!AppendPathChallengeFrame(path_challenge_frame, &writer)) { - QUIC_BUG << "AppendPathChallengeFrame failed for PATH_CHALLENGE frame in " - "probing packet"; - return 0; - } + frames.push_back(QuicFrame(&path_challenge_frame)); // Add padding to the rest of the packet in order to assess Path MTU // characteristics. QuicPaddingFrame padding_frame; - if (!AppendTypeByte(QuicFrame(padding_frame), true, &writer)) { - QUIC_BUG << "AppendTypeByte failed for padding frame in probing packet"; - return 0; - } - if (!AppendPaddingFrame(padding_frame, &writer)) { - QUIC_BUG << "AppendPaddingFrame of " << padding_frame.num_padding_bytes - << " failed"; - return 0; - } + frames.push_back(QuicFrame(padding_frame)); - return writer.length(); + return BuildIetfDataPacket(header, frames, buffer, packet_length); } size_t QuicFramer::BuildPathResponsePacket( @@ -1142,53 +1166,33 @@ << "Attempt to generate connectivity response with no request payloads"; return 0; } - - QuicDataWriter writer(packet_length, buffer, endianness()); - - DCHECK_EQ(version_.transport_version, QUIC_VERSION_99) - << "Attempt to build a PATH_RESPONSE Connectivity Probing packet and " - "not doing IETF QUIC"; - - if (!AppendPacketHeader(header, &writer)) { - QUIC_BUG << "AppendPacketHeader failed"; + if (version_.transport_version != QUIC_VERSION_99) { + QUIC_BUG << "Attempt to build a PATH_RESPONSE Connectivity Probing " + "packet and not doing IETF QUIC"; return 0; } - // Write a set of PATH_RESPONSE frames to a single packet, each with the - // 8-byte payload of the corresponding PATH_REQUEST frame from a single - // received packet. + std::vector<std::unique_ptr<QuicPathResponseFrame>> path_response_frames; for (const QuicPathFrameBuffer& payload : payloads) { // Note that the control frame ID can be 0 since this is not retransmitted. - QuicPathResponseFrame path_response_frame(0, payload); + path_response_frames.push_back( + QuicMakeUnique<QuicPathResponseFrame>(0, payload)); + } - if (!AppendTypeByte(QuicFrame(&path_response_frame), false, &writer)) { - QUIC_BUG - << "AppendTypeByte failed for PATH_RESPONSE frame in probing packet"; - return 0; - } - - if (!AppendPathResponseFrame(path_response_frame, &writer)) { - QUIC_BUG << "AppendPathChallengeFrame failed for PATH_CHALLENGE frame in " - "probing packet"; - return 0; - } + QuicFrames frames; + for (const std::unique_ptr<QuicPathResponseFrame>& path_response_frame : + path_response_frames) { + frames.push_back(QuicFrame(path_response_frame.get())); } if (is_padded) { // Add padding to the rest of the packet in order to assess Path MTU // characteristics. QuicPaddingFrame padding_frame; - if (!AppendTypeByte(QuicFrame(padding_frame), true, &writer)) { - QUIC_BUG << "AppendTypeByte failed for padding frame in probing packet"; - return 0; - } - if (!AppendPaddingFrame(padding_frame, &writer)) { - QUIC_BUG << "AppendPaddingFrame of " << padding_frame.num_padding_bytes - << " failed"; - return 0; - } + frames.push_back(QuicFrame(padding_frame)); } - return writer.length(); + + return BuildIetfDataPacket(header, frames, buffer, packet_length); } // static @@ -1274,7 +1278,7 @@ } else { // Append an random packet number. QuicPacketNumber random_packet_number = - QuicRandom::GetInstance()->RandUint64() % 255 + 1; + QuicPacketNumber(QuicRandom::GetInstance()->RandUint64() % 255 + 1); if (!AppendPacketNumber(PACKET_1BYTE_PACKET_NUMBER, random_packet_number, &writer)) { return nullptr; @@ -1470,35 +1474,17 @@ size_t buffer_length) { DCHECK_NE(GOOGLE_QUIC_PACKET, header->form); DCHECK(!header->has_possible_stateless_reset_token); - if (header->form == IETF_QUIC_SHORT_HEADER_PACKET) { - if (!process_stateless_reset_at_client_only_) { - // Peak possible stateless reset token. Will only be used on decryption - // failure. - QuicStringPiece remaining = encrypted_reader->PeekRemainingPayload(); - if (remaining.length() >= - sizeof(header->possible_stateless_reset_token)) { - remaining.copy( - reinterpret_cast<char*>(&header->possible_stateless_reset_token), - sizeof(header->possible_stateless_reset_token), - remaining.length() - - sizeof(header->possible_stateless_reset_token)); - } - } else { - QUIC_RELOADABLE_FLAG_COUNT(quic_process_stateless_reset_at_client_only); - if (perspective_ == Perspective::IS_CLIENT) { - // Peek possible stateless reset token. Will only be used on decryption - // failure. - QuicStringPiece remaining = encrypted_reader->PeekRemainingPayload(); - if (remaining.length() >= - sizeof(header->possible_stateless_reset_token)) { - header->has_possible_stateless_reset_token = true; - memcpy( - &header->possible_stateless_reset_token, - &remaining.data()[remaining.length() - - sizeof(header->possible_stateless_reset_token)], - sizeof(header->possible_stateless_reset_token)); - } - } + if (header->form == IETF_QUIC_SHORT_HEADER_PACKET && + perspective_ == Perspective::IS_CLIENT) { + // Peek possible stateless reset token. Will only be used on decryption + // failure. + QuicStringPiece remaining = encrypted_reader->PeekRemainingPayload(); + if (remaining.length() >= sizeof(header->possible_stateless_reset_token)) { + header->has_possible_stateless_reset_token = true; + memcpy(&header->possible_stateless_reset_token, + &remaining.data()[remaining.length() - + sizeof(header->possible_stateless_reset_token)], + sizeof(header->possible_stateless_reset_token)); } } @@ -1506,15 +1492,15 @@ header->long_packet_type != VERSION_NEGOTIATION) { // Process packet number. QuicPacketNumber base_packet_number = largest_packet_number_; - + uint64_t full_packet_number; if (!ProcessAndCalculatePacketNumber( encrypted_reader, header->packet_number_length, base_packet_number, - &header->packet_number)) { + &full_packet_number)) { set_detailed_error("Unable to read packet number."); return RaiseError(QUIC_INVALID_PACKET_HEADER); } - if (header->packet_number == kInvalidPacketNumber) { + if (!IsValidFullPacketNumber(full_packet_number, transport_version())) { if (IsIetfStatelessResetPacket(*header)) { // This is a stateless reset packet. QuicIetfStatelessResetPacket packet( @@ -1525,6 +1511,7 @@ set_detailed_error("packet numbers cannot be 0."); return RaiseError(QUIC_INVALID_PACKET_HEADER); } + header->packet_number = QuicPacketNumber(full_packet_number); } // A nonce should only present in SHLO from the server to the client when @@ -1567,8 +1554,12 @@ // Update the largest packet number after we have decrypted the packet // so we are confident is not attacker controlled. - largest_packet_number_ = - std::max(header->packet_number, largest_packet_number_); + if (largest_packet_number_.IsInitialized()) { + largest_packet_number_ = + std::max(header->packet_number, largest_packet_number_); + } else { + largest_packet_number_ = header->packet_number; + } if (!visitor_->OnPacketHeader(*header)) { // The visitor suppresses further processing of the packet. @@ -1629,8 +1620,12 @@ // Update the largest packet number after we have decrypted the packet // so we are confident is not attacker controlled. - largest_packet_number_ = - std::max(header->packet_number, largest_packet_number_); + if (largest_packet_number_.IsInitialized()) { + largest_packet_number_ = + std::max(header->packet_number, largest_packet_number_); + } else { + largest_packet_number_ = header->packet_number; + } if (!visitor_->OnPacketHeader(*header)) { // The visitor suppresses further processing of the packet. @@ -1699,10 +1694,11 @@ bool QuicFramer::IsIetfStatelessResetPacket( const QuicPacketHeader& header) const { - return perspective_ == Perspective::IS_CLIENT && - header.form == IETF_QUIC_SHORT_HEADER_PACKET && - (!process_stateless_reset_at_client_only_ || - header.has_possible_stateless_reset_token) && + QUIC_BUG_IF(header.has_possible_stateless_reset_token && + perspective_ != Perspective::IS_CLIENT) + << "has_possible_stateless_reset_token can only be true at client side."; + return header.form == IETF_QUIC_SHORT_HEADER_PACKET && + header.has_possible_stateless_reset_token && visitor_->IsValidStatelessResetToken( header.possible_stateless_reset_token); } @@ -1737,12 +1733,13 @@ } break; case PACKET_8BYTE_CONNECTION_ID: - QUIC_BUG_IF(header.destination_connection_id.length() != - kQuicDefaultConnectionIdLength && - transport_version() < QUIC_VERSION_99) - << "Cannot use connection ID of length " - << header.destination_connection_id.length() << " with version " + QUIC_BUG_IF(!QuicUtils::IsConnectionIdValidForVersion( + header.destination_connection_id, transport_version())) + << "AppendPacketHeader: attempted to use connection ID " + << header.destination_connection_id + << " which is invalid with version " << QuicVersionToString(transport_version()); + public_flags |= PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID; if (perspective_ == Perspective::IS_CLIENT) { public_flags |= PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID_OLD; @@ -1784,7 +1781,7 @@ bool QuicFramer::AppendIetfHeaderTypeByte(const QuicPacketHeader& header, QuicDataWriter* writer) { uint8_t type = 0; - if (transport_version() == QUIC_VERSION_99) { + if (transport_version() > QUIC_VERSION_46) { if (header.version_flag) { type = static_cast<uint8_t>( FLAGS_LONG_HEADER | FLAGS_FIXED_BIT | @@ -1819,11 +1816,10 @@ bool QuicFramer::AppendIetfPacketHeader(const QuicPacketHeader& header, QuicDataWriter* writer) { QUIC_DVLOG(1) << ENDPOINT << "Appending IETF header: " << header; - QUIC_BUG_IF(header.destination_connection_id.length() != - kQuicDefaultConnectionIdLength && - transport_version() < QUIC_VERSION_99) - << "Cannot use connection ID of length " - << header.destination_connection_id.length() << " with version " + QUIC_BUG_IF(!QuicUtils::IsConnectionIdValidForVersion( + header.destination_connection_id, transport_version())) + << "AppendIetfPacketHeader: attempted to use connection ID " + << header.destination_connection_id << " which is invalid with version " << QuicVersionToString(transport_version()); if (!AppendIetfHeaderTypeByte(header, writer)) { return false; @@ -1892,10 +1888,10 @@ return QuicTime::Delta::FromMicroseconds(time); } -QuicPacketNumber QuicFramer::CalculatePacketNumberFromWire( +uint64_t QuicFramer::CalculatePacketNumberFromWire( QuicPacketNumberLength packet_number_length, QuicPacketNumber base_packet_number, - QuicPacketNumber packet_number) const { + uint64_t packet_number) const { // The new packet number might have wrapped to the next epoch, or // it might have reverse wrapped to the previous epoch, or it might // remain in the same epoch. Select the packet number closest to the @@ -1904,12 +1900,14 @@ // epoch_delta is the delta between epochs the packet number was serialized // with, so the correct value is likely the same epoch as the last sequence // number or an adjacent epoch. - const QuicPacketNumber epoch_delta = UINT64_C(1) - << (8 * packet_number_length); - QuicPacketNumber next_packet_number = base_packet_number + 1; - QuicPacketNumber epoch = base_packet_number & ~(epoch_delta - 1); - QuicPacketNumber prev_epoch = epoch - epoch_delta; - QuicPacketNumber next_epoch = epoch + epoch_delta; + if (!base_packet_number.IsInitialized()) { + return packet_number; + } + const uint64_t epoch_delta = UINT64_C(1) << (8 * packet_number_length); + uint64_t next_packet_number = base_packet_number.ToUint64() + 1; + uint64_t epoch = base_packet_number.ToUint64() & ~(epoch_delta - 1); + uint64_t prev_epoch = epoch - epoch_delta; + uint64_t next_epoch = epoch + epoch_delta; return ClosestTo(next_packet_number, epoch + packet_number, ClosestTo(next_packet_number, prev_epoch + packet_number, @@ -2009,11 +2007,15 @@ QuicPacketNumberLength QuicFramer::GetMinPacketNumberLength( QuicTransportVersion version, QuicPacketNumber packet_number) { - if (packet_number < 1 << (PACKET_1BYTE_PACKET_NUMBER * 8)) { + DCHECK(packet_number.IsInitialized()); + if (packet_number < QuicPacketNumber(1 << (PACKET_1BYTE_PACKET_NUMBER * 8))) { return PACKET_1BYTE_PACKET_NUMBER; - } else if (packet_number < 1 << (PACKET_2BYTE_PACKET_NUMBER * 8)) { + } else if (packet_number < + QuicPacketNumber(1 << (PACKET_2BYTE_PACKET_NUMBER * 8))) { return PACKET_2BYTE_PACKET_NUMBER; - } else if (packet_number < UINT64_C(1) << (PACKET_4BYTE_PACKET_NUMBER * 8)) { + } else if (packet_number < + QuicPacketNumber(UINT64_C(1) + << (PACKET_4BYTE_PACKET_NUMBER * 8))) { return PACKET_4BYTE_PACKET_NUMBER; } else { return PACKET_6BYTE_PACKET_NUMBER; @@ -2051,7 +2053,7 @@ new_ack_info.first_block_length = frame.packets.LastIntervalLength(); auto itr = frame.packets.rbegin(); QuicPacketNumber previous_start = itr->min(); - new_ack_info.max_block_length = itr->Length(); + new_ack_info.max_block_length = PacketNumberIntervalLength(*itr); ++itr; // Don't do any more work after getting information for 256 ACK blocks; any @@ -2060,12 +2062,12 @@ new_ack_info.num_ack_blocks < std::numeric_limits<uint8_t>::max(); previous_start = itr->min(), ++itr) { const auto& interval = *itr; - const QuicPacketNumber total_gap = previous_start - interval.max(); + const QuicPacketCount total_gap = previous_start - interval.max(); new_ack_info.num_ack_blocks += (total_gap + std::numeric_limits<uint8_t>::max() - 1) / std::numeric_limits<uint8_t>::max(); - new_ack_info.max_block_length = - std::max(new_ack_info.max_block_length, interval.Length()); + new_ack_info.max_block_length = std::max( + new_ack_info.max_block_length, PacketNumberIntervalLength(interval)); } return new_ack_info; } @@ -2073,18 +2075,19 @@ bool QuicFramer::ProcessUnauthenticatedHeader(QuicDataReader* encrypted_reader, QuicPacketHeader* header) { QuicPacketNumber base_packet_number = largest_packet_number_; - + uint64_t full_packet_number; if (!ProcessAndCalculatePacketNumber( encrypted_reader, header->packet_number_length, base_packet_number, - &header->packet_number)) { + &full_packet_number)) { set_detailed_error("Unable to read packet number."); return RaiseError(QUIC_INVALID_PACKET_HEADER); } - if (header->packet_number == kInvalidPacketNumber) { + if (!IsValidFullPacketNumber(full_packet_number, transport_version())) { set_detailed_error("packet numbers cannot be 0."); return RaiseError(QUIC_INVALID_PACKET_HEADER); } + header->packet_number = QuicPacketNumber(full_packet_number); if (!visitor_->OnUnauthenticatedHeader(*header)) { set_detailed_error( @@ -2130,7 +2133,7 @@ } else { header->version = ParseQuicVersionLabel(version_label); if (header->version.transport_version != QUIC_VERSION_UNSUPPORTED) { - if (header->version.transport_version == QUIC_VERSION_99 && + if (header->version.transport_version > QUIC_VERSION_46 && !(type & FLAGS_FIXED_BIT)) { set_detailed_error("Fixed bit is 0 in long header."); return false; @@ -2167,7 +2170,7 @@ header->destination_connection_id = last_serialized_connection_id_; } if (infer_packet_header_type_from_version_ && - transport_version() == QUIC_VERSION_99 && !(type & FLAGS_FIXED_BIT)) { + transport_version() > QUIC_VERSION_46 && !(type & FLAGS_FIXED_BIT)) { set_detailed_error("Fixed bit is 0 in short header."); return false; } @@ -2240,8 +2243,8 @@ QuicDataReader* reader, QuicPacketNumberLength packet_number_length, QuicPacketNumber base_packet_number, - QuicPacketNumber* packet_number) { - QuicPacketNumber wire_packet_number; + uint64_t* packet_number) { + uint64_t wire_packet_number; if (!reader->ReadBytesToUInt64(packet_number_length, &wire_packet_number)) { return false; } @@ -2459,7 +2462,8 @@ encoded_bytes -= reader->BytesRemaining(); // Check that the frame type is minimally encoded. - if (encoded_bytes != QuicDataWriter::GetVarInt62Len(frame_type)) { + if (encoded_bytes != + static_cast<size_t>(QuicDataWriter::GetVarInt62Len(frame_type))) { // The frame type was not minimally encoded. set_detailed_error("Frame type not minimally encoded."); return RaiseError(IETF_QUIC_PROTOCOL_VIOLATION); @@ -2917,12 +2921,21 @@ ExtractBits(frame_type, kQuicSequenceNumberLengthNumBits, kLargestAckedOffset)); - QuicPacketNumber largest_acked; + uint64_t largest_acked; if (!reader->ReadBytesToUInt64(largest_acked_length, &largest_acked)) { set_detailed_error("Unable to read largest acked."); 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); + // Connection always sends packet starting from kFirstSendingPacketNumber > + // 0, peer has observed an unsent packet. + set_detailed_error("Largest acked is 0."); + return false; + } + uint64_t ack_delay_time_us; if (!reader->ReadUFloat16(&ack_delay_time_us)) { set_detailed_error("Unable to read ack delay time."); @@ -2930,7 +2943,7 @@ } if (!visitor_->OnAckFrameStart( - largest_acked, + QuicPacketNumber(largest_acked), ack_delay_time_us == kUFloat16MaxValue ? QuicTime::Delta::Infinite() : QuicTime::Delta::FromMicroseconds(ack_delay_time_us))) { @@ -2954,6 +2967,8 @@ 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 " @@ -2963,9 +2978,16 @@ .c_str()); return false; } + DCHECK(!GetQuicReloadableFlag(quic_disallow_peer_ack_0)); } - - if (first_block_length > largest_acked + 1) { + 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); + first_ack_block_underflow = true; + } + if (first_ack_block_underflow) { set_detailed_error(QuicStrCat("Underflow with first ack block length ", first_block_length, " largest acked is ", largest_acked, ".") @@ -2973,8 +2995,9 @@ return false; } - QuicPacketNumber first_received = largest_acked + 1 - first_block_length; - if (!visitor_->OnAckRange(first_received, largest_acked + 1)) { + uint64_t first_received = largest_acked + 1 - first_block_length; + if (!visitor_->OnAckRange(QuicPacketNumber(first_received), + QuicPacketNumber(largest_acked + 1))) { // The visitor suppresses further processing of the packet. Although // this is not a parsing error, returns false as this is in middle // of processing an ack frame, @@ -2994,7 +3017,14 @@ set_detailed_error("Unable to ack block length."); return false; } - if (first_received < gap + current_block_length) { + bool ack_block_underflow = first_received < gap + current_block_length; + if (GetQuicReloadableFlag(quic_disallow_peer_ack_0) && + 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) { set_detailed_error( QuicStrCat("Underflow with ack block length ", current_block_length, ", end of block is ", first_received - gap, ".") @@ -3004,8 +3034,9 @@ first_received -= (gap + current_block_length); if (current_block_length > 0) { - if (!visitor_->OnAckRange(first_received, - first_received + current_block_length)) { + if (!visitor_->OnAckRange( + QuicPacketNumber(first_received), + QuicPacketNumber(first_received) + current_block_length)) { // The visitor suppresses further processing of the packet. Although // this is not a parsing error, returns false as this is in middle // of processing an ack frame, @@ -3022,13 +3053,13 @@ return false; } - if (!ProcessTimestampsInAckFrame(num_received_packets, largest_acked, - reader)) { + if (!ProcessTimestampsInAckFrame(num_received_packets, + QuicPacketNumber(largest_acked), reader)) { return false; } // Done processing the ACK frame. - return visitor_->OnAckFrameEnd(first_received); + return visitor_->OnAckFrameEnd(QuicPacketNumber(first_received)); } bool QuicFramer::ProcessTimestampsInAckFrame(uint8_t num_received_packets, @@ -3084,11 +3115,17 @@ bool QuicFramer::ProcessIetfAckFrame(QuicDataReader* reader, uint64_t frame_type, QuicAckFrame* ack_frame) { - QuicPacketNumber largest_acked; + uint64_t largest_acked; if (!reader->ReadVarInt62(&largest_acked)) { set_detailed_error("Unable to read largest acked."); return false; } + 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."); + return false; + } ack_frame->largest_acked = static_cast<QuicPacketNumber>(largest_acked); uint64_t ack_delay_time_in_us; if (!reader->ReadVarInt62(&ack_delay_time_in_us)) { @@ -3125,7 +3162,8 @@ ack_frame->ect_1_count = 0; ack_frame->ecn_ce_count = 0; } - if (!visitor_->OnAckFrameStart(largest_acked, ack_frame->ack_delay_time)) { + if (!visitor_->OnAckFrameStart(QuicPacketNumber(largest_acked), + ack_frame->ack_delay_time)) { // The visitor suppresses further processing of the packet. Although this is // not a parsing error, returns false as this is in middle of processing an // ACK frame. @@ -3150,14 +3188,15 @@ } // Calculate the packets being acked in the first block. // +1 because AddRange implementation requires [low,high) - QuicPacketNumber block_high = largest_acked + 1; - QuicPacketNumber block_low = largest_acked - ack_block_value; + uint64_t block_high = largest_acked + 1; + uint64_t block_low = largest_acked - ack_block_value; // ack_block_value is the number of packets preceding the // largest_acked packet which are in the block being acked. Thus, // its maximum value is largest_acked-1. Test this, reporting an // error if the value is wrong. - if (ack_block_value > largest_acked) { + if (ack_block_value + first_sending_packet_number_.ToUint64() > + largest_acked) { set_detailed_error(QuicStrCat("Underflow with first ack block length ", ack_block_value + 1, " largest acked is ", largest_acked, ".") @@ -3165,7 +3204,8 @@ return false; } - if (!visitor_->OnAckRange(block_low, block_high)) { + if (!visitor_->OnAckRange(QuicPacketNumber(block_low), + QuicPacketNumber(block_high))) { // The visitor suppresses further processing of the packet. Although // this is not a parsing error, returns false as this is in middle // of processing an ACK frame. @@ -3208,7 +3248,8 @@ set_detailed_error("Unable to read ack block value."); return false; } - if (ack_block_value > (block_high - 1)) { + if (ack_block_value + first_sending_packet_number_.ToUint64() > + (block_high - 1)) { set_detailed_error( QuicStrCat("Underflow with ack block length ", ack_block_value + 1, " latest ack block end is ", block_high - 1, ".") @@ -3218,7 +3259,8 @@ // Calculate the low end of the new nth ack block. The +1 is // because the encoded value is the blocksize-1. block_low = block_high - 1 - ack_block_value; - if (!visitor_->OnAckRange(block_low, block_high)) { + if (!visitor_->OnAckRange(QuicPacketNumber(block_low), + QuicPacketNumber(block_high))) { // The visitor suppresses further processing of the packet. Although // this is not a parsing error, returns false as this is in middle // of processing an ACK frame. @@ -3230,19 +3272,22 @@ ack_block_count--; } - return visitor_->OnAckFrameEnd(block_low); + return visitor_->OnAckFrameEnd(QuicPacketNumber(block_low)); } bool QuicFramer::ProcessStopWaitingFrame(QuicDataReader* reader, const QuicPacketHeader& header, QuicStopWaitingFrame* stop_waiting) { - QuicPacketNumber least_unacked_delta; + uint64_t least_unacked_delta; if (!reader->ReadBytesToUInt64(header.packet_number_length, &least_unacked_delta)) { set_detailed_error("Unable to read least unacked delta."); return false; } - if (header.packet_number < least_unacked_delta) { + if (header.packet_number.ToUint64() < least_unacked_delta || + (GetQuicReloadableFlag( + quic_close_connection_with_zero_least_unacked_stop_waiting) && + header.packet_number.ToUint64() == least_unacked_delta)) { set_detailed_error("Invalid unacked delta."); return false; } @@ -3461,9 +3506,10 @@ size_t total_len, size_t buffer_len, char* buffer) { + DCHECK(packet_number.IsInitialized()); size_t output_length = 0; if (!encrypter_[level]->EncryptPacket( - version_.transport_version, packet_number, + version_.transport_version, packet_number.ToUint64(), QuicStringPiece(buffer, ad_len), // Associated data QuicStringPiece(buffer + ad_len, total_len - ad_len), // Plaintext buffer + ad_len, // Destination buffer @@ -3480,6 +3526,7 @@ const QuicPacket& packet, char* buffer, size_t buffer_len) { + DCHECK(packet_number.IsInitialized()); DCHECK(encrypter_[level] != nullptr); QuicStringPiece associated_data = @@ -3491,7 +3538,7 @@ // Encrypt the plaintext into the buffer. size_t output_length = 0; if (!encrypter_[level]->EncryptPacket( - version_.transport_version, packet_number, associated_data, + version_.transport_version, packet_number.ToUint64(), associated_data, packet.Plaintext(version_.transport_version), buffer + ad_len, &output_length, buffer_len - ad_len)) { RaiseError(QUIC_ENCRYPTION_FAILURE); @@ -3533,8 +3580,9 @@ header.nonce != nullptr, header.packet_number_length); bool success = decrypter_->DecryptPacket( - version_.transport_version, header.packet_number, associated_data, - encrypted, decrypted_buffer, decrypted_length, buffer_length); + version_.transport_version, header.packet_number.ToUint64(), + associated_data, encrypted, decrypted_buffer, decrypted_length, + buffer_length); if (success) { visitor_->OnDecryptedPacket(decrypter_level_); } else if (alternative_decrypter_ != nullptr) { @@ -3556,8 +3604,9 @@ if (try_alternative_decryption) { success = alternative_decrypter_->DecryptPacket( - version_.transport_version, header.packet_number, associated_data, - encrypted, decrypted_buffer, decrypted_length, buffer_length); + version_.transport_version, header.packet_number.ToUint64(), + associated_data, encrypted, decrypted_buffer, decrypted_length, + buffer_length); } if (success) { visitor_->OnDecryptedPacket(alternative_decrypter_level_); @@ -3590,7 +3639,7 @@ // Type byte, largest_acked, and delay_time are straight-forward. size_t ack_frame_size = kQuicFrameTypeSize; QuicPacketNumber largest_acked = LargestAcked(frame); - ack_frame_size += QuicDataWriter::GetVarInt62Len(largest_acked); + ack_frame_size += QuicDataWriter::GetVarInt62Len(largest_acked.ToUint64()); uint64_t ack_delay_time_us; ack_delay_time_us = frame.ack_delay_time.ToMicroseconds(); ack_delay_time_us = ack_delay_time_us >> kIetfAckTimestampShift; @@ -3650,18 +3699,18 @@ size_t ack_block_count_size = QuicDataWriter::GetVarInt62Len(ack_block_count); ack_frame_size += ack_block_count_size; - QuicPacketNumber first_ack_block = ack_block_largest - ack_block_smallest; + uint64_t first_ack_block = ack_block_largest - ack_block_smallest; size_t first_ack_block_size = QuicDataWriter::GetVarInt62Len(first_ack_block); ack_frame_size += first_ack_block_size; // Account for the remaining Intervals, if any. while (ack_block_count != 0) { - QuicPacketNumber gap_size = ack_block_smallest - itr->max(); + uint64_t gap_size = ack_block_smallest - itr->max(); // Decrement per the protocol specification size_t size_of_gap_size = QuicDataWriter::GetVarInt62Len(gap_size - 1); ack_frame_size += size_of_gap_size; - QuicPacketNumber block_size = itr->max() - itr->min(); + uint64_t block_size = itr->max() - itr->min(); // Decrement per the protocol specification size_t size_of_block_size = QuicDataWriter::GetVarInt62Len(block_size - 1); ack_frame_size += size_of_block_size; @@ -3677,6 +3726,7 @@ size_t QuicFramer::GetAckFrameSize( const QuicAckFrame& ack, QuicPacketNumberLength packet_number_length) { + DCHECK(!ack.packets.Empty()); size_t ack_size = 0; if (version_.transport_version == QUIC_VERSION_99) { @@ -3686,7 +3736,7 @@ QuicPacketNumberLength largest_acked_length = GetMinPacketNumberLength(version_.transport_version, LargestAcked(ack)); QuicPacketNumberLength ack_block_length = GetMinPacketNumberLength( - version_.transport_version, ack_info.max_block_length); + version_.transport_version, QuicPacketNumber(ack_info.max_block_length)); ack_size = GetMinAckFrameSize(version_.transport_version, largest_acked_length); @@ -3727,7 +3777,10 @@ frame.stream_frame.offset, last_frame_in_packet, frame.stream_frame.data_length) + frame.stream_frame.data_length; - // TODO(nharper): Add a case for CRYPTO_FRAME here? + case CRYPTO_FRAME: + return GetMinCryptoFrameSize(frame.crypto_frame->offset, + frame.crypto_frame->data_length) + + frame.crypto_frame->data_length; case ACK_FRAME: { return GetAckFrameSize(*frame.ack_frame, packet_number_length); } @@ -3913,12 +3966,13 @@ bool QuicFramer::AppendPacketNumber(QuicPacketNumberLength packet_number_length, QuicPacketNumber packet_number, QuicDataWriter* writer) { - size_t length = packet_number_length; - if (length != 1 && length != 2 && length != 4 && length != 6 && length != 8) { - QUIC_BUG << "Invalid packet_number_length: " << length; + DCHECK(packet_number.IsInitialized()); + if (!IsValidPacketNumberLength(packet_number_length)) { + QUIC_BUG << "Invalid packet_number_length: " << packet_number_length; return false; } - return writer->WriteBytesToUInt64(packet_number_length, packet_number); + return writer->WriteBytesToUInt64(packet_number_length, + packet_number.ToUint64()); } // static @@ -3947,10 +4001,18 @@ // static bool QuicFramer::AppendAckBlock(uint8_t gap, QuicPacketNumberLength length_length, - QuicPacketNumber length, + uint64_t length, QuicDataWriter* writer) { + if (length == 0) { + if (!IsValidPacketNumberLength(length_length)) { + QUIC_BUG << "Invalid packet_number_length: " << length_length; + return false; + } + return writer->WriteUInt8(gap) && + writer->WriteBytesToUInt64(length_length, length); + } return writer->WriteUInt8(gap) && - AppendPacketNumber(length_length, length, writer); + AppendPacketNumber(length_length, QuicPacketNumber(length), writer); } bool QuicFramer::AppendStreamFrame(const QuicStreamFrame& frame, @@ -4120,8 +4182,20 @@ set_detailed_error("Writing data length failed."); return false; } - // TODO(nharper): Append stream frame contents. - return false; + if (data_producer_ == nullptr) { + if (frame.data_buffer == nullptr || + !writer->WriteBytes(frame.data_buffer, frame.data_length)) { + set_detailed_error("Writing frame data failed."); + return false; + } + } else { + DCHECK_EQ(nullptr, frame.data_buffer); + if (!data_producer_->WriteCryptoData(frame.level, frame.offset, + frame.data_length, writer)) { + return false; + } + } + return true; } void QuicFramer::set_version(const ParsedQuicVersion version) { @@ -4139,8 +4213,9 @@ QuicPacketNumber largest_acked = LargestAcked(frame); QuicPacketNumberLength largest_acked_length = GetMinPacketNumberLength(version_.transport_version, largest_acked); - QuicPacketNumberLength ack_block_length = GetMinPacketNumberLength( - version_.transport_version, new_ack_info.max_block_length); + QuicPacketNumberLength ack_block_length = + GetMinPacketNumberLength(version_.transport_version, + QuicPacketNumber(new_ack_info.max_block_length)); // Calculate available bytes for timestamps and ack blocks. int32_t available_timestamp_and_ack_block_bytes = writer->capacity() - writer->length() - ack_block_length - @@ -4199,7 +4274,8 @@ } // First ack block length. - if (!AppendPacketNumber(ack_block_length, new_ack_info.first_block_length, + if (!AppendPacketNumber(ack_block_length, + QuicPacketNumber(new_ack_info.first_block_length), writer)) { return false; } @@ -4223,7 +4299,7 @@ itr != frame.packets.rend() && num_ack_blocks_written < num_ack_blocks; previous_start = itr->min(), ++itr) { const auto& interval = *itr; - const QuicPacketNumber total_gap = previous_start - interval.max(); + const uint64_t total_gap = previous_start - interval.max(); const size_t num_encoded_gaps = (total_gap + std::numeric_limits<uint8_t>::max() - 1) / std::numeric_limits<uint8_t>::max(); @@ -4251,8 +4327,8 @@ total_gap - (num_encoded_gaps - 1) * std::numeric_limits<uint8_t>::max(); // Append the final ACK block with a non-empty size. - if (!AppendAckBlock(last_gap, ack_block_length, interval.Length(), - writer)) { + if (!AppendAckBlock(last_gap, ack_block_length, + PacketNumberIntervalLength(interval), writer)) { return false; } ++num_ack_blocks_written; @@ -4297,8 +4373,7 @@ auto it = frame.received_packet_times.begin(); QuicPacketNumber packet_number = it->first; - QuicPacketNumber delta_from_largest_observed = - LargestAcked(frame) - packet_number; + uint64_t delta_from_largest_observed = LargestAcked(frame) - packet_number; DCHECK_GE(std::numeric_limits<uint8_t>::max(), delta_from_largest_observed); if (delta_from_largest_observed > std::numeric_limits<uint8_t>::max()) { @@ -4345,10 +4420,11 @@ const QuicStopWaitingFrame& frame, QuicDataWriter* writer) { DCHECK_GE(QUIC_VERSION_43, version_.transport_version); - DCHECK_GE(header.packet_number, frame.least_unacked); - const QuicPacketNumber least_unacked_delta = + DCHECK(frame.least_unacked.IsInitialized() && + header.packet_number >= frame.least_unacked); + const uint64_t least_unacked_delta = header.packet_number - frame.least_unacked; - const QuicPacketNumber length_shift = header.packet_number_length * 8; + const uint64_t length_shift = header.packet_number_length * 8; if (least_unacked_delta >> length_shift > 0) { QUIC_BUG << "packet_number_length " << header.packet_number_length @@ -4358,8 +4434,12 @@ << " version:" << version_.transport_version; return false; } - if (!AppendPacketNumber(header.packet_number_length, least_unacked_delta, - writer)) { + if (least_unacked_delta == 0) { + return writer->WriteBytesToUInt64(header.packet_number_length, + least_unacked_delta); + } + if (!AppendPacketNumber(header.packet_number_length, + QuicPacketNumber(least_unacked_delta), writer)) { QUIC_BUG << " seq failed: " << header.packet_number_length; return false; } @@ -4382,7 +4462,7 @@ return 0; } available_space -= encoded_size; - uint64_t previous_ack_end = itr->min(); + QuicPacketNumber previous_ack_end = itr->min(); ack_block_count--; while (ack_block_count) { @@ -4426,7 +4506,7 @@ } QuicPacketNumber largest_acked = LargestAcked(frame); - if (!writer->WriteVarInt62(largest_acked)) { + if (!writer->WriteVarInt62(largest_acked.ToUint64())) { set_detailed_error("No room for largest-acked in ack frame"); return false; } @@ -4480,9 +4560,9 @@ // Case 2 or 3 auto itr = frame.packets.rbegin(); - QuicPacketNumber ack_block_largest = largest_acked; + QuicPacketNumber ack_block_largest(largest_acked); QuicPacketNumber ack_block_smallest; - if ((itr->max() - 1) == largest_acked) { + if ((itr->max() - 1) == QuicPacketNumber(largest_acked)) { // If largest_acked + 1 is equal to the Max() of the first Interval // in the QuicAckFrame then the first Interval is the first ack block of the // frame; remaining Intervals are additional ack blocks. The QuicAckFrame's @@ -4513,7 +4593,7 @@ return false; } - QuicPacketNumber first_ack_block = ack_block_largest - ack_block_smallest; + uint64_t first_ack_block = ack_block_largest - ack_block_smallest; if (!writer->WriteVarInt62(first_ack_block)) { set_detailed_error("No room for first ack block in ack frame"); return false; @@ -4521,13 +4601,13 @@ // For the remaining QuicAckFrame Intervals, if any while (ack_block_count != 0) { - QuicPacketNumber gap_size = ack_block_smallest - itr->max(); + uint64_t gap_size = ack_block_smallest - itr->max(); if (!writer->WriteVarInt62(gap_size - 1)) { set_detailed_error("No room for gap block in ack frame"); return false; } - QuicPacketNumber block_size = itr->max() - itr->min(); + uint64_t block_size = itr->max() - itr->min(); if (!writer->WriteVarInt62(block_size - 1)) { set_detailed_error("No room for nth ack block in ack frame"); return false; @@ -4608,6 +4688,9 @@ 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) { return AppendIetfBlockedFrame(frame, writer); } @@ -4985,6 +5068,9 @@ 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; if (!reader->ReadVarInt62(&frame->offset)) { set_detailed_error("Can not read blocked offset.");
diff --git a/quic/core/quic_framer.h b/quic/core/quic_framer.h index 828daa0..46280c5 100644 --- a/quic/core/quic_framer.h +++ b/quic/core/quic_framer.h
@@ -270,6 +270,10 @@ QuicStreamOffset offset, bool last_frame_in_packet, QuicPacketLength data_length); + // Returns the overhead of framing a CRYPTO frame with the specific offset and + // data length provided, but not counting the size of the data payload. + static size_t GetMinCryptoFrameSize(QuicStreamOffset offset, + QuicPacketLength data_length); static size_t GetMessageFrameSize(QuicTransportVersion version, bool last_frame_in_packet, QuicByteCount length); @@ -374,6 +378,12 @@ char* buffer, size_t packet_length); + // 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); + // Serialize a probing packet that uses IETF QUIC's PATH CHALLENGE frame. Also // fills the packet with padding. size_t BuildPaddedPathChallengePacket(const QuicPacketHeader& header, @@ -506,7 +516,7 @@ // Returns header wire format of last received packet. // Please do not use this method. // TODO(fayang): Remove last_header_form_ when deprecating - // quic_proxy_use_real_packet_format_when_reject flag. + // quic_fix_last_packet_is_ietf_quic flag. PacketHeaderFormat GetLastPacketFormat() const; void set_validate_flags(bool value) { validate_flags_ = value; } @@ -534,6 +544,10 @@ QuicTime creation_time() const { return creation_time_; } + QuicPacketNumber first_sending_packet_number() const { + return first_sending_packet_number_; + } + private: friend class test::QuicFramerPeer; @@ -545,9 +559,9 @@ ~AckFrameInfo(); // The maximum ack block length. - QuicPacketNumber max_block_length; + QuicPacketCount max_block_length; // Length of first ack block. - QuicPacketNumber first_block_length; + QuicPacketCount first_block_length; // Number of ACK blocks needed for the ACK frame. size_t num_ack_blocks; }; @@ -597,7 +611,7 @@ QuicDataReader* reader, QuicPacketNumberLength packet_number_length, QuicPacketNumber base_packet_number, - QuicPacketNumber* packet_number); + uint64_t* packet_number); bool ProcessFrameData(QuicDataReader* reader, const QuicPacketHeader& header); bool ProcessIetfFrameData(QuicDataReader* reader, const QuicPacketHeader& header); @@ -635,10 +649,10 @@ // Returns the full packet number from the truncated // wire format version and the last seen packet number. - QuicPacketNumber CalculatePacketNumberFromWire( + uint64_t CalculatePacketNumberFromWire( QuicPacketNumberLength packet_number_length, QuicPacketNumber base_packet_number, - QuicPacketNumber packet_number) const; + uint64_t packet_number) const; // Returns the QuicTime::Delta corresponding to the time from when the framer // was created. @@ -675,7 +689,7 @@ // successfully appended. static bool AppendAckBlock(uint8_t gap, QuicPacketNumberLength length_length, - QuicPacketNumber length, + uint64_t length, QuicDataWriter* writer); static uint8_t GetPacketNumberFlags( @@ -869,13 +883,15 @@ // The last timestamp received if process_timestamps_ is true. QuicTime::Delta last_timestamp_; + // If this is a framer of a connection, this is the packet number of first + // sending packet. If this is a framer of a framer of dispatcher, this is the + // packet number of sent packets (for those which have packet number). + const QuicPacketNumber first_sending_packet_number_; + // If not null, framer asks data_producer_ to write stream frame data. Not // owned. TODO(fayang): Consider add data producer to framer's constructor. QuicStreamFrameDataProducer* data_producer_; - // Latched value of quic_process_stateless_reset_at_client_only flag. - const bool process_stateless_reset_at_client_only_; - // If true, framer infers packet header type (IETF/GQUIC) from version_. // Otherwise, framer infers packet header type from first byte of a received // packet.
diff --git a/quic/core/quic_framer_test.cc b/quic/core/quic_framer_test.cc index a75bceb..888c87e 100644 --- a/quic/core/quic_framer_test.cc +++ b/quic/core/quic_framer_test.cc
@@ -36,8 +36,8 @@ namespace test { namespace { -const QuicPacketNumber kEpoch = UINT64_C(1) << 32; -const QuicPacketNumber kMask = kEpoch - 1; +const uint64_t kEpoch = UINT64_C(1) << 32; +const uint64_t kMask = kEpoch - 1; const QuicUint128 kTestStatelessResetToken = 1010101; // 0x0F69B5 @@ -51,10 +51,11 @@ return TestConnectionId(UINT64_C(0xFEDCBA9876543211)); } -const QuicPacketNumber kPacketNumber = UINT64_C(0x12345678); -const QuicPacketNumber kSmallLargestObserved = UINT16_C(0x1234); -const QuicPacketNumber kSmallMissingPacket = UINT16_C(0x1233); -const QuicPacketNumber kLeastUnacked = UINT64_C(0x012345670); +const QuicPacketNumber kPacketNumber = QuicPacketNumber(UINT64_C(0x12345678)); +const QuicPacketNumber kSmallLargestObserved = + QuicPacketNumber(UINT16_C(0x1234)); +const QuicPacketNumber kSmallMissingPacket = QuicPacketNumber(UINT16_C(0x1233)); +const QuicPacketNumber kLeastUnacked = QuicPacketNumber(UINT64_C(0x012345670)); const QuicStreamId kStreamId = UINT64_C(0x01020304); // Note that the high 4 bits of the stream offset must be less than 0x40 // in order to ensure that the value can be encoded using VarInt62 encoding. @@ -65,7 +66,7 @@ // This is the largest packet number that can be represented in IETF QUIC // varint62 format. const QuicPacketNumber kLargestIetfLargestObserved = - UINT64_C(0x3fffffffffffffff); + QuicPacketNumber(UINT64_C(0x3fffffffffffffff)); // Encodings for the two bits in a VarInt62 that // describe the length of the VarInt61. For binary packet // formats in this file, the convention is to code the @@ -83,14 +84,14 @@ bool SetNoncePrefix(QuicStringPiece nonce_prefix) override { return true; } bool SetIV(QuicStringPiece iv) override { return true; } bool EncryptPacket(QuicTransportVersion version, - QuicPacketNumber packet_number, + 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_ = packet_number; + packet_number_ = QuicPacketNumber(packet_number); associated_data_ = QuicString(associated_data); plaintext_ = QuicString(plaintext); memcpy(output, plaintext.data(), plaintext.length()); @@ -129,14 +130,14 @@ return true; } bool DecryptPacket(QuicTransportVersion version, - QuicPacketNumber packet_number, + 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_ = packet_number; + packet_number_ = QuicPacketNumber(packet_number); associated_data_ = QuicString(associated_data); ciphertext_ = QuicString(ciphertext); memcpy(output, ciphertext.data(), ciphertext.length()); @@ -223,7 +224,13 @@ } bool OnCryptoFrame(const QuicCryptoFrame& frame) override { - // TODO(nharper): Implement. + ++frame_count_; + // Save a copy of the data so it is valid after the packet is processed. + QuicString* string_data = + new QuicString(frame.data_buffer, frame.data_length); + crypto_data_.push_back(QuicWrapUnique(string_data)); + crypto_frames_.push_back(QuicMakeUnique<QuicCryptoFrame>( + ENCRYPTION_NONE, frame.offset, *string_data)); return true; } @@ -373,6 +380,7 @@ std::unique_ptr<QuicIetfStatelessResetPacket> stateless_reset_packet_; std::unique_ptr<QuicVersionNegotiationPacket> version_negotiation_packet_; std::vector<std::unique_ptr<QuicStreamFrame>> stream_frames_; + std::vector<std::unique_ptr<QuicCryptoFrame>> crypto_frames_; std::vector<std::unique_ptr<QuicAckFrame>> ack_frames_; std::vector<std::unique_ptr<QuicStopWaitingFrame>> stop_waiting_frames_; std::vector<std::unique_ptr<QuicPaddingFrame>> padding_frames_; @@ -393,6 +401,7 @@ QuicRetireConnectionIdFrame retire_connection_id_; QuicNewTokenFrame new_token_; std::vector<std::unique_ptr<QuicString>> stream_data_; + std::vector<std::unique_ptr<QuicString>> crypto_data_; }; // Simple struct for defining a packet's content, and associated @@ -428,6 +437,7 @@ std::unique_ptr<QuicEncrypter>(encrypter_)); framer_.set_visitor(&visitor_); + framer_.InferPacketHeaderTypeFromVersion(); } // Helper function to get unsigned char representation of the handshake @@ -577,9 +587,9 @@ EXPECT_EQ(str, QuicString(frame->data_buffer, frame->data_length)); } - void CheckCalculatePacketNumber(QuicPacketNumber expected_packet_number, + void CheckCalculatePacketNumber(uint64_t expected_packet_number, QuicPacketNumber last_packet_number) { - QuicPacketNumber wire_packet_number = expected_packet_number & kMask; + uint64_t wire_packet_number = expected_packet_number & kMask; EXPECT_EQ(expected_packet_number, QuicFramerPeer::CalculatePacketNumberFromWire( &framer_, PACKET_4BYTE_PACKET_NUMBER, last_packet_number, @@ -623,12 +633,17 @@ TEST_P(QuicFramerTest, CalculatePacketNumberFromWireNearEpochStart) { // A few quick manual sanity checks. - CheckCalculatePacketNumber(UINT64_C(1), UINT64_C(0)); - CheckCalculatePacketNumber(kEpoch + 1, kMask); - CheckCalculatePacketNumber(kEpoch, kMask); + CheckCalculatePacketNumber(UINT64_C(1), QuicPacketNumber()); + CheckCalculatePacketNumber(kEpoch + 1, QuicPacketNumber(kMask)); + CheckCalculatePacketNumber(kEpoch, QuicPacketNumber(kMask)); + for (uint64_t j = 0; j < 10; j++) { + CheckCalculatePacketNumber(j, QuicPacketNumber()); + CheckCalculatePacketNumber(kEpoch - 1 - j, QuicPacketNumber()); + } // Cases where the last number was close to the start of the range. - for (uint64_t last = 0; last < 10; last++) { + for (QuicPacketNumber last = QuicPacketNumber(1); last < QuicPacketNumber(10); + last++) { // Small numbers should not wrap (even if they're out of order). for (uint64_t j = 0; j < 10; j++) { CheckCalculatePacketNumber(j, last); @@ -644,7 +659,7 @@ TEST_P(QuicFramerTest, CalculatePacketNumberFromWireNearEpochEnd) { // Cases where the last number was close to the end of the range for (uint64_t i = 0; i < 10; i++) { - QuicPacketNumber last = kEpoch - i; + QuicPacketNumber last = QuicPacketNumber(kEpoch - i); // Small numbers should wrap. for (uint64_t j = 0; j < 10; j++) { @@ -665,7 +680,7 @@ const uint64_t cur_epoch = 2 * kEpoch; // Cases where the last number was close to the start of the range for (uint64_t i = 0; i < 10; i++) { - uint64_t last = cur_epoch + i; + QuicPacketNumber last = QuicPacketNumber(cur_epoch + i); // Small number should not wrap (even if they're out of order). for (uint64_t j = 0; j < 10; j++) { CheckCalculatePacketNumber(cur_epoch + j, last); @@ -684,7 +699,7 @@ const uint64_t next_epoch = 3 * kEpoch; // Cases where the last number was close to the end of the range for (uint64_t i = 0; i < 10; i++) { - QuicPacketNumber last = next_epoch - 1 - i; + QuicPacketNumber last = QuicPacketNumber(next_epoch - 1 - i); // Small numbers should wrap. for (uint64_t j = 0; j < 10; j++) { @@ -707,7 +722,7 @@ for (uint64_t i = 0; i < 10; i++) { // Subtract 1, because the expected next packet number is 1 more than the // last packet number. - QuicPacketNumber last = max_number - i - 1; + QuicPacketNumber last = QuicPacketNumber(max_number - i - 1); // Small numbers should not wrap, because they have nowhere to go. for (uint64_t j = 0; j < 10; j++) { @@ -749,10 +764,21 @@ // packet number 0x78, 0x56, 0x34, 0x12, }; + unsigned char packet47[kMaxPacketSize + 1] = { + // type (short header 4 byte packet number) + 0x43, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x78, 0x56, 0x34, 0x12, + }; // clang-format on unsigned char* p = packet; size_t p_size = QUIC_ARRAYSIZE(packet); - if (framer_.transport_version() > QUIC_VERSION_43) { + if (framer_.transport_version() > QUIC_VERSION_46) { + p = packet47; + p_size = QUIC_ARRAYSIZE(packet47); + } else if (framer_.transport_version() > QUIC_VERSION_43) { p = packet44; p_size = QUIC_ARRAYSIZE(packet44); } @@ -826,9 +852,9 @@ TEST_P(QuicFramerTest, LongPacketHeader) { // clang-format off - PacketFragments packet = { + PacketFragments packet44 = { // type (long header with packet type INITIAL) - {"Unable to read public flags.", + {"Unable to read type.", {0xFF}}, // version tag {"Unable to read protocol version.", @@ -843,14 +869,33 @@ {"Unable to read packet number.", {0x12, 0x34, 0x56, 0x78}}, }; + PacketFragments packet47 = { + // type (long header with packet type INITIAL) + {"Unable to read type.", + {0xC3}}, + // 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}}, + // packet number + {"Unable to read packet number.", + {0x12, 0x34, 0x56, 0x78}}, + }; // clang-format on if (framer_.transport_version() <= QUIC_VERSION_43) { return; } + PacketFragments& fragments = + framer_.transport_version() > QUIC_VERSION_46 ? packet47 : packet44; std::unique_ptr<QuicEncryptedPacket> encrypted( - AssemblePacketFromFragments(packet)); + AssemblePacketFromFragments(fragments)); EXPECT_FALSE(framer_.ProcessPacket(*encrypted)); EXPECT_EQ(QUIC_MISSING_PAYLOAD, framer_.error()); @@ -861,7 +906,9 @@ EXPECT_TRUE(visitor_.header_->version_flag); EXPECT_EQ(kPacketNumber, visitor_.header_->packet_number); - CheckFramingBoundaries(packet, QUIC_INVALID_PACKET_HEADER); + CheckFramingBoundaries( + framer_.transport_version() > QUIC_VERSION_46 ? packet47 : packet44, + QUIC_INVALID_PACKET_HEADER); } TEST_P(QuicFramerTest, PacketHeaderWith0ByteConnectionId) { @@ -900,7 +947,7 @@ {0x12, 0x34, 0x56, 0x78}}, }; - PacketFragments packet99 = { + PacketFragments packet47 = { // type (short header, 4 byte packet number) {"Unable to read type.", {0x43}}, @@ -912,8 +959,8 @@ // clang-format on 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 ? packet @@ -966,7 +1013,7 @@ PacketFragments packet44 = { // type (long header with packet type ZERO_RTT_PROTECTED) - {"Unable to read public flags.", + {"Unable to read type.", {0xFC}}, // version tag {"Unable to read protocol version.", @@ -982,10 +1029,10 @@ {0x12, 0x34, 0x56, 0x78}}, }; - PacketFragments packet99 = { + PacketFragments packet47 = { // type (long header with packet type ZERO_RTT_PROTECTED and 4 bytes // packet number) - {"Unable to read public flags.", + {"Unable to read type.", {0xD3}}, // version tag {"Unable to read protocol version.", @@ -1003,8 +1050,8 @@ // clang-format on 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 ? packet @@ -1054,7 +1101,7 @@ PacketFragments packet44 = { // type (short header, 4 byte packet number) - {"Unable to read public flags.", + {"Unable to read type.", {0x32}}, // connection_id {"Unable to read Destination ConnectionId.", @@ -1063,13 +1110,27 @@ {"Unable to read packet number.", {0x12, 0x34, 0x56, 0x78}}, }; + + PacketFragments packet47 = { + // type (short header, 4 byte packet number) + {"Unable to read type.", + {0x43}}, + // connection_id + {"Unable to read Destination ConnectionId.", + {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}}, + // packet number + {"Unable to read packet number.", + {0x12, 0x34, 0x56, 0x78}}, + }; // clang-format on PacketFragments& fragments = - framer_.transport_version() > QUIC_VERSION_43 - ? packet44 - : (framer_.transport_version() == QUIC_VERSION_35 ? packet - : packet39); + framer_.transport_version() > QUIC_VERSION_46 + ? packet47 + : (framer_.transport_version() > QUIC_VERSION_43 + ? packet44 + : (framer_.transport_version() == QUIC_VERSION_35 ? packet + : packet39)); std::unique_ptr<QuicEncryptedPacket> encrypted( AssemblePacketFromFragments(fragments)); EXPECT_FALSE(framer_.ProcessPacket(*encrypted)); @@ -1114,7 +1175,7 @@ PacketFragments packet44 = { // type (short header, 2 byte packet number) - {"Unable to read public flags.", + {"Unable to read type.", {0x31}}, // connection_id {"Unable to read Destination ConnectionId.", @@ -1123,13 +1184,27 @@ {"Unable to read packet number.", {0x56, 0x78}}, }; + + PacketFragments packet47 = { + // type (short header, 2 byte packet number) + {"Unable to read type.", + {0x41}}, + // connection_id + {"Unable to read Destination ConnectionId.", + {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}}, + // packet number + {"Unable to read packet number.", + {0x56, 0x78}}, + }; // clang-format on PacketFragments& fragments = - framer_.transport_version() > QUIC_VERSION_43 - ? packet44 - : (framer_.transport_version() == QUIC_VERSION_35 ? packet - : packet39); + framer_.transport_version() > QUIC_VERSION_46 + ? packet47 + : (framer_.transport_version() > QUIC_VERSION_43 + ? packet44 + : (framer_.transport_version() == QUIC_VERSION_35 ? packet + : packet39)); std::unique_ptr<QuicEncryptedPacket> encrypted( AssemblePacketFromFragments(fragments)); EXPECT_FALSE(framer_.ProcessPacket(*encrypted)); @@ -1163,7 +1238,7 @@ PacketFragments packet44 = { // type (8 byte connection_id and 1 byte packet number) - {"Unable to read public flags.", + {"Unable to read type.", {0x30}}, // connection_id {"Unable to read Destination ConnectionId.", @@ -1173,10 +1248,24 @@ {0x78}}, }; + PacketFragments packet47 = { + // type (8 byte connection_id and 1 byte packet number) + {"Unable to read type.", + {0x40}}, + // connection_id + {"Unable to read Destination ConnectionId.", + {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}}, + // packet number + {"Unable to read packet number.", + {0x78}}, + }; + // clang-format on PacketFragments& fragments = - framer_.transport_version() > QUIC_VERSION_43 ? packet44 : packet; + framer_.transport_version() > QUIC_VERSION_46 + ? packet47 + : (framer_.transport_version() > QUIC_VERSION_43 ? packet44 : packet); std::unique_ptr<QuicEncryptedPacket> encrypted( AssemblePacketFromFragments(fragments)); EXPECT_FALSE(framer_.ProcessPacket(*encrypted)); @@ -1318,7 +1407,7 @@ 0x00, 0x00, 0x00, 0x00 }; - unsigned char packet99[] = { + unsigned char packet47[] = { // type: Long header with packet type ZERO_RTT_PROTECTED and 1 byte packet // number. 0xD0, @@ -1344,9 +1433,9 @@ 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); + if (framer_.transport_version() > QUIC_VERSION_46) { + p = packet47; + p_size = QUIC_ARRAYSIZE(packet47); } else if (framer_.transport_version() > QUIC_VERSION_43) { p = packet44; p_size = QUIC_ARRAYSIZE(packet44); @@ -1571,9 +1660,9 @@ 0x00, 0x00, }; - unsigned char packet99[] = { + unsigned char packet47[] = { // type (short header, 4 byte packet number) - 0x32, + 0x43, // connection_id 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, // packet number @@ -1581,8 +1670,35 @@ // paddings 0x00, 0x00, - // frame type - Stream with FIN, LEN, and OFFSET bits set. - 0x10 | 0x01 | 0x02 | 0x04, + // frame type (stream frame with fin) + 0xFF, + // stream id + 0x01, 0x02, 0x03, 0x04, + // offset + 0x3A, 0x98, 0xFE, 0xDC, + 0x32, 0x10, 0x76, 0x54, + // data length + 0x00, 0x0c, + // data + 'h', 'e', 'l', 'l', + 'o', ' ', 'w', 'o', + 'r', 'l', 'd', '!', + // paddings + 0x00, 0x00, + }; + + unsigned char packet99[] = { + // type (short header, 4 byte packet number) + 0x43, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + + // paddings + 0x00, 0x00, + // frame type - IETF_STREAM with FIN, LEN, and OFFSET bits set. + 0x08 | 0x01 | 0x02 | 0x04, // stream id kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04, @@ -1608,6 +1724,9 @@ 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_43) { p = packet44; p_size = QUIC_ARRAYSIZE(packet44); @@ -1726,6 +1845,36 @@ 'r', 'l', 'd', '!'}}, }; + PacketFragments packet47 = { + // type (short header, 4 byte packet number) + {"", + {0x43}}, + // connection_id + {"", + {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}}, + // packet number + {"", + {0x12, 0x34, 0x56, 0x78}}, + // frame type (stream frame with fin) + {"", + {0xFF}}, + // stream id + {"Unable to read stream_id.", + {0x01, 0x02, 0x03, 0x04}}, + // offset + {"Unable to read offset.", + {0x3A, 0x98, 0xFE, 0xDC, + 0x32, 0x10, 0x76, 0x54}}, + {"Unable to read frame data.", + { + // data length + 0x00, 0x0c, + // data + 'h', 'e', 'l', 'l', + 'o', ' ', 'w', 'o', + 'r', 'l', 'd', '!'}}, + }; + PacketFragments packet99 = { // type (short header, 4 byte packet number) {"", @@ -1736,9 +1885,9 @@ // packet number {"", {0x12, 0x34, 0x56, 0x78}}, - // frame type - Stream with FIN, LEN, and OFFSET bits set. + // frame type - IETF_STREAM with FIN, LEN, and OFFSET bits set. {"", - { 0x10 | 0x01 | 0x02 | 0x04 }}, + { 0x08 | 0x01 | 0x02 | 0x04 }}, // stream id {"Unable to read stream_id.", {kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04}}, @@ -1760,10 +1909,13 @@ PacketFragments& fragments = framer_.transport_version() == QUIC_VERSION_99 ? packet99 - : (framer_.transport_version() > QUIC_VERSION_43 - ? packet44 - : (framer_.transport_version() != QUIC_VERSION_35 ? packet39 - : packet)); + : (framer_.transport_version() > QUIC_VERSION_46 + ? packet47 + : (framer_.transport_version() > QUIC_VERSION_43 + ? packet44 + : (framer_.transport_version() != QUIC_VERSION_35 + ? packet39 + : packet))); std::unique_ptr<QuicEncryptedPacket> encrypted( AssemblePacketFromFragments(fragments)); EXPECT_TRUE(framer_.ProcessPacket(*encrypted)); @@ -1802,9 +1954,9 @@ // packet number {"", {0x12, 0x34, 0x56, 0x78}}, - // frame type - Stream with FIN, LEN, and OFFSET bits set. + // frame type - IETF_STREAM with FIN, LEN, and OFFSET bits set. {"", - { 0x10 | 0x01 | 0x02 | 0x04 }}, + { 0x08 | 0x01 | 0x02 | 0x04 }}, // stream id {"Unable to read stream_id.", {kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04}}, @@ -2123,6 +2275,36 @@ 'r', 'l', 'd', '!'}}, }; + PacketFragments packet47 = { + // type (short header, 4 byte packet number) + {"", + {0x43}}, + // connection_id + {"", + {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}}, + // packet number + {"", + {0x12, 0x34, 0x56, 0x78}}, + // frame type (stream frame with fin) + {"", + {0xFD}}, + // stream id + {"Unable to read stream_id.", + {0x03, 0x04}}, + // offset + {"Unable to read offset.", + {0x3A, 0x98, 0xFE, 0xDC, + 0x32, 0x10, 0x76, 0x54}}, + {"Unable to read frame data.", + { + // data length + 0x00, 0x0c, + // data + 'h', 'e', 'l', 'l', + 'o', ' ', 'w', 'o', + 'r', 'l', 'd', '!'}}, + }; + PacketFragments packet99 = { // type (short header, 4 byte packet number) {"", @@ -2133,9 +2315,9 @@ // packet number {"", {0x12, 0x34, 0x56, 0x78}}, - // frame type (stream frame with LEN, FIN, and OFFSET bits set) + // frame type (IETF_STREAM frame with LEN, FIN, and OFFSET bits set) {"", - {0x10 | 0x01 | 0x02 | 0x04}}, + {0x08 | 0x01 | 0x02 | 0x04}}, // stream id {"Unable to read stream_id.", {kVarInt62TwoBytes + 0x03, 0x04}}, @@ -2157,10 +2339,13 @@ PacketFragments& fragments = framer_.transport_version() == QUIC_VERSION_99 ? packet99 - : (framer_.transport_version() > QUIC_VERSION_43 - ? packet44 - : (framer_.transport_version() != QUIC_VERSION_35 ? packet39 - : packet)); + : (framer_.transport_version() > QUIC_VERSION_46 + ? packet47 + : (framer_.transport_version() > QUIC_VERSION_43 + ? packet44 + : (framer_.transport_version() != QUIC_VERSION_35 + ? packet39 + : packet))); std::unique_ptr<QuicEncryptedPacket> encrypted( AssemblePacketFromFragments(fragments)); EXPECT_TRUE(framer_.ProcessPacket(*encrypted)); @@ -2274,6 +2459,36 @@ 'r', 'l', 'd', '!'}}, }; + PacketFragments packet47 = { + // type (short header, 4 byte packet number) + {"", + {0x43}}, + // connection_id + {"", + {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}}, + // packet number + {"", + {0x12, 0x34, 0x56, 0x78}}, + // frame type (stream frame with fin) + {"", + {0xFC}}, + // stream id + {"Unable to read stream_id.", + {0x04}}, + // offset + {"Unable to read offset.", + {0x3A, 0x98, 0xFE, 0xDC, + 0x32, 0x10, 0x76, 0x54}}, + {"Unable to read frame data.", + { + // data length + 0x00, 0x0c, + // data + 'h', 'e', 'l', 'l', + 'o', ' ', 'w', 'o', + 'r', 'l', 'd', '!'}}, + }; + PacketFragments packet99 = { // type (short header, 4 byte packet number) {"", @@ -2284,9 +2499,9 @@ // packet number {"", {0x12, 0x34, 0x56, 0x78}}, - // frame type (stream frame with LEN, FIN, and OFFSET bits set) + // frame type (IETF_STREAM frame with LEN, FIN, and OFFSET bits set) {"", - {0x10 | 0x01 | 0x02 | 0x04}}, + {0x08 | 0x01 | 0x02 | 0x04}}, // stream id {"Unable to read stream_id.", {kVarInt62OneByte + 0x04}}, @@ -2308,10 +2523,13 @@ PacketFragments& fragments = framer_.transport_version() == QUIC_VERSION_99 ? packet99 - : (framer_.transport_version() > QUIC_VERSION_43 - ? packet44 - : (framer_.transport_version() != QUIC_VERSION_35 ? packet39 - : packet)); + : (framer_.transport_version() > QUIC_VERSION_46 + ? packet47 + : (framer_.transport_version() > QUIC_VERSION_43 + ? packet44 + : (framer_.transport_version() != QUIC_VERSION_35 + ? packet39 + : packet))); std::unique_ptr<QuicEncryptedPacket> encrypted( AssemblePacketFromFragments(fragments)); EXPECT_TRUE(framer_.ProcessPacket(*encrypted)); @@ -2437,6 +2655,43 @@ 'r', 'l', 'd', '!'}}, }; + PacketFragments packet47 = { + // public flags (long header with packet type ZERO_RTT_PROTECTED and + // 4-byte packet number) + {"", + {0xD3}}, + // version tag + {"", + {QUIC_VERSION_BYTES}}, + // connection_id length + {"", + {0x50}}, + // connection_id + {"", + {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}}, + // packet number + {"", + {0x12, 0x34, 0x56, 0x78}}, + // frame type (stream frame with fin) + {"", + {0xFE}}, + // stream id + {"Unable to read stream_id.", + {0x02, 0x03, 0x04}}, + // offset + {"Unable to read offset.", + {0x3A, 0x98, 0xFE, 0xDC, + 0x32, 0x10, 0x76, 0x54}}, + {"Unable to read frame data.", + { + // data length + 0x00, 0x0c, + // data + 'h', 'e', 'l', 'l', + 'o', ' ', 'w', 'o', + 'r', 'l', 'd', '!'}}, + }; + PacketFragments packet99 = { // public flags (long header with packet type ZERO_RTT_PROTECTED and // 4-byte packet number) @@ -2454,9 +2709,9 @@ // packet number {"", {0x12, 0x34, 0x56, 0x78}}, - // frame type (stream frame with FIN, LEN, and OFFSET bits set) + // frame type (IETF_STREAM frame with FIN, LEN, and OFFSET bits set) {"", - {0x10 | 0x01 | 0x02 | 0x04}}, + {0x08 | 0x01 | 0x02 | 0x04}}, // stream id {"Unable to read stream_id.", {kVarInt62FourBytes + 0x00, 0x02, 0x03, 0x04}}, @@ -2478,10 +2733,13 @@ PacketFragments& fragments = framer_.transport_version() == QUIC_VERSION_99 ? packet99 - : (framer_.transport_version() > QUIC_VERSION_43 - ? packet44 - : (framer_.transport_version() != QUIC_VERSION_35 ? packet39 - : packet)); + : (framer_.transport_version() > QUIC_VERSION_46 + ? packet47 + : (framer_.transport_version() > QUIC_VERSION_43 + ? packet44 + : (framer_.transport_version() != QUIC_VERSION_35 + ? packet39 + : packet))); std::unique_ptr<QuicEncryptedPacket> encrypted( AssemblePacketFromFragments(fragments)); EXPECT_TRUE(framer_.ProcessPacket(*encrypted)); @@ -2575,10 +2833,35 @@ 'o', ' ', 'w', 'o', 'r', 'l', 'd', '!', }; + + unsigned char packet47[] = { + // type (short header, 4 byte packet number) + 0x43, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + + // frame type (STREAM Frame with FIN, LEN, and OFFSET bits set) + 0x10 | 0x01 | 0x02 | 0x04, + // stream id + kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04, + // offset + kVarInt62EightBytes + 0x3A, 0x98, 0xFE, 0xDC, + 0x32, 0x10, 0x76, 0x54, + // data length + kVarInt62OneByte + 0x0c, + // data + 'h', 'e', 'l', 'l', + 'o', ' ', 'w', 'o', + 'r', 'l', 'd', '!', + }; // clang-format on unsigned char* p = packet; - if (framer_.transport_version() > QUIC_VERSION_43) { + if (framer_.transport_version() > QUIC_VERSION_46) { + p = packet47; + } else if (framer_.transport_version() > QUIC_VERSION_43) { p = packet44; } else if (framer_.transport_version() != QUIC_VERSION_35) { p = packet39; @@ -2619,19 +2902,33 @@ // packet number 0x01, }; + + unsigned char packet47[] = { + // type (short header, 1 byte packet number) + 0x40, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x01, + }; // clang-format on QuicEncryptedPacket encrypted( - framer_.transport_version() > QUIC_VERSION_43 ? AsChars(packet44) - : AsChars(packet), - framer_.transport_version() > QUIC_VERSION_43 ? QUIC_ARRAYSIZE(packet44) - : QUIC_ARRAYSIZE(packet), + framer_.transport_version() > QUIC_VERSION_46 + ? AsChars(packet47) + : (framer_.transport_version() > QUIC_VERSION_43 ? AsChars(packet44) + : AsChars(packet)), + framer_.transport_version() > QUIC_VERSION_46 + ? QUIC_ARRAYSIZE(packet47) + : (framer_.transport_version() > QUIC_VERSION_43 + ? QUIC_ARRAYSIZE(packet44) + : QUIC_ARRAYSIZE(packet)), false); EXPECT_TRUE(framer_.ProcessPacket(encrypted)); EXPECT_EQ(QUIC_NO_ERROR, framer_.error()); ASSERT_TRUE(visitor_.header_.get()); - EXPECT_EQ(0u, visitor_.header_->packet_number); + EXPECT_FALSE(visitor_.header_->packet_number.IsInitialized()); } TEST_P(QuicFramerTest, AckFrameOneAckBlock) { @@ -2720,22 +3017,50 @@ {0x00}} }; - PacketFragments packet99 = { + PacketFragments packet47 = { // type (short packet, 4 byte packet number) {"", - {0x32}}, + {0x43}}, // connection_id {"", {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}}, // packet number {"", {0x12, 0x34, 0x56, 0x78}}, - // frame type (ack frame) + // frame type (ack frame) + // (one ack block, 2 byte largest observed, 2 byte block length) + {"", + {0x45}}, + // largest acked + {"Unable to read largest acked.", + {0x12, 0x34}}, + // Zero delta time. + {"Unable to read ack delay time.", + {0x00, 0x00}}, + // first ack block length. + {"Unable to read first ack block length.", + {0x12, 0x34}}, + // num timestamps. + {"Unable to read num received packets.", + {0x00}} + }; + + PacketFragments packet99 = { + // type (short packet, 4 byte packet number) + {"", + {0x43}}, + // connection_id + {"", + {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}}, + // packet number + {"", + {0x12, 0x34, 0x56, 0x78}}, + // frame type (IETF_ACK) // (one ack block, 2 byte largest observed, 2 byte block length) // IETF-Quic ignores the bit-fields in the ack type, all of // that information is encoded elsewhere in the frame. {"", - {0x1a}}, + {0x02}}, // largest acked {"Unable to read largest acked.", {kVarInt62TwoBytes + 0x12, 0x34}}, @@ -2759,10 +3084,13 @@ PacketFragments& fragments = framer_.transport_version() == QUIC_VERSION_99 ? packet99 - : (framer_.transport_version() > QUIC_VERSION_43 - ? packet44 - : (framer_.transport_version() != QUIC_VERSION_35 ? packet39 - : packet)); + : (framer_.transport_version() > QUIC_VERSION_46 + ? packet47 + : (framer_.transport_version() > QUIC_VERSION_43 + ? packet44 + : (framer_.transport_version() != QUIC_VERSION_35 + ? packet39 + : packet))); std::unique_ptr<QuicEncryptedPacket> encrypted( AssemblePacketFromFragments(fragments)); EXPECT_TRUE(framer_.ProcessPacket(*encrypted)); @@ -2871,6 +3199,34 @@ {0x00}} }; + PacketFragments packet47 = { + // type (short header, 4 byte packet number) + {"", + {0x43}}, + // 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) + {"", + {0x45}}, + // largest acked + {"Unable to read largest acked.", + {0x12, 0x34}}, + // 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 packet99 = { // type (short header, 4 byte packet number) {"", @@ -2881,9 +3237,9 @@ // packet number {"", {0x12, 0x34, 0x56, 0x78}}, - // frame type (ack frame) + // frame type (IETF_ACK) {"", - {0x1a}}, + {0x02}}, // largest acked {"Unable to read largest acked.", {kVarInt62TwoBytes + 0x12, 0x34}}, @@ -2902,10 +3258,13 @@ PacketFragments& fragments = framer_.transport_version() == QUIC_VERSION_99 ? packet99 - : (framer_.transport_version() > QUIC_VERSION_43 - ? packet44 - : (framer_.transport_version() != QUIC_VERSION_35 ? packet39 - : packet)); + : (framer_.transport_version() > QUIC_VERSION_46 + ? packet47 + : (framer_.transport_version() > QUIC_VERSION_43 + ? packet44 + : (framer_.transport_version() != QUIC_VERSION_35 + ? packet39 + : packet))); std::unique_ptr<QuicEncryptedPacket> encrypted( AssemblePacketFromFragments(fragments)); EXPECT_FALSE(framer_.ProcessPacket(*encrypted)); @@ -2931,9 +3290,9 @@ // packet number {"", {0x12, 0x34, 0x56, 0x78}}, - // frame type (ack frame) + // frame type (IETF_ACK frame) {"", - {0x1a}}, + {0x02}}, // largest acked {"Unable to read largest acked.", {kVarInt62OneByte + 63}}, @@ -2988,9 +3347,9 @@ // packet number {"", {0x12, 0x34, 0x56, 0x78}}, - // frame type (ack frame) + // frame type (IETF_ACK frame) {"", - {0x1a}}, + {0x02}}, // largest acked {"Unable to read largest acked.", {kVarInt62OneByte + 63}}, @@ -3043,9 +3402,9 @@ // packet number {"", {0x12, 0x34, 0x56, 0x78}}, - // frame type (ack frame) + // frame type (IETF_ACK frame) {"", - {0x1a}}, + {0x02}}, // largest acked {"Unable to read largest acked.", {kVarInt62OneByte + 10}}, @@ -3092,9 +3451,9 @@ // packet number {"", {0x12, 0x34, 0x56, 0x78}}, - // frame type (ack frame) + // frame type (IETF_ACK frame) {"", - {0x1a}}, + {0x02}}, // largest acked {"Unable to read largest acked.", {kVarInt62OneByte + 10}}, @@ -3123,7 +3482,7 @@ CheckFramingBoundaries(packet99, QUIC_INVALID_ACK_DATA); } -// An ack block that acks the entire range, 0...0x3fffffffffffffff +// An ack block that acks the entire range, 1...0x3fffffffffffffff TEST_P(QuicFramerTest, AckBlockAcksEverything) { if (framer_.transport_version() != QUIC_VERSION_99) { // for now, only v99 @@ -3140,9 +3499,9 @@ // packet number {"", {0x12, 0x34, 0x56, 0x78}}, - // frame type (ack frame) + // frame type (IETF_ACK frame) {"", - {0x1a}}, + {0x02}}, // largest acked {"Unable to read largest acked.", {kVarInt62EightBytes + 0x3f, 0xff, 0xff, 0xff, @@ -3156,7 +3515,7 @@ // first ack block length. {"Unable to read first ack block length.", {kVarInt62EightBytes + 0x3f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff}}, + 0xff, 0xff, 0xff, 0xfe}}, }; // clang-format on @@ -3167,8 +3526,8 @@ const QuicAckFrame& frame = *visitor_.ack_frames_[0]; EXPECT_EQ(1u, frame.packets.NumIntervals()); EXPECT_EQ(kLargestIetfLargestObserved, LargestAcked(frame)); - // +1 because it's 0..Largest, inclusive. - EXPECT_EQ(kLargestIetfLargestObserved + 1, frame.packets.NumPacketsSlow()); + EXPECT_EQ(kLargestIetfLargestObserved.ToUint64(), + frame.packets.NumPacketsSlow()); } // This test looks for a malformed ack where @@ -3312,12 +3671,55 @@ { 0x00 }}, }; + PacketFragments packet47 = { + // type (short header, 4 byte packet number) + {"", + { 0x43 }}, + // connection_id + {"", + { 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 }}, + // packet number + {"", + { 0x12, 0x34, 0x56, 0x78 }}, + + // 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.", + { 0x12, 0x34 }}, + // 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.", + { 0x0e, 0xaf }}, + // Number of timestamps. + { "First block length is zero but ACK is not empty. " + "largest acked is 4660, num ack blocks is 1.", + { 0x00 }}, + }; + // clang-format on PacketFragments& fragments = - framer_.transport_version() > QUIC_VERSION_43 - ? packet44 - : (framer_.transport_version() != QUIC_VERSION_35 ? packet39 - : packet); + framer_.transport_version() > QUIC_VERSION_46 + ? packet47 + : (framer_.transport_version() > QUIC_VERSION_43 + ? packet44 + : (framer_.transport_version() != QUIC_VERSION_35 ? packet39 + : packet)); std::unique_ptr<QuicEncryptedPacket> encrypted( AssemblePacketFromFragments(fragments)); @@ -3422,6 +3824,34 @@ {0x00}} }; + PacketFragments packet47 = { + // type (short header, 4 byte packet number) + {"", + {0x43}}, + // connection_id + {"", + {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}}, + // packet number + {"", + {0x56, 0x78, 0x9A, 0xBC}}, + // frame type (ack frame) + // (one ack block, 4 byte largest observed, 2 byte block length) + {"", + {0x49}}, + // largest acked + {"Unable to read largest acked.", + {0x12, 0x34, 0x56, 0x78}}, + // Zero delta time. + {"Unable to read ack delay time.", + {0x00, 0x00}}, + // first ack block length. + {"Unable to read first ack block length.", + {0x12, 0x34}}, + // num timestamps. + {"Unable to read num received packets.", + {0x00}} + }; + PacketFragments packet99 = { // type (short header, 4 byte packet number) {"", @@ -3432,9 +3862,9 @@ // packet number {"", {0x56, 0x78, 0x9A, 0xBC}}, - // frame type (ack frame) + // frame type (IETF_ACK frame) {"", - {0x1a}}, + {0x02}}, // largest acked {"Unable to read largest acked.", {kVarInt62FourBytes + 0x12, 0x34, 0x56, 0x78}}, @@ -3453,10 +3883,13 @@ PacketFragments& fragments = framer_.transport_version() == QUIC_VERSION_99 ? packet99 - : (framer_.transport_version() > QUIC_VERSION_43 - ? packet44 - : (framer_.transport_version() != QUIC_VERSION_35 ? packet39 - : packet)); + : (framer_.transport_version() > QUIC_VERSION_46 + ? packet47 + : (framer_.transport_version() > QUIC_VERSION_43 + ? packet44 + : (framer_.transport_version() != QUIC_VERSION_35 + ? packet39 + : packet))); std::unique_ptr<QuicEncryptedPacket> encrypted( AssemblePacketFromFragments(fragments)); EXPECT_TRUE(framer_.ProcessPacket(*encrypted)); @@ -3684,10 +4117,10 @@ { 0x32, 0x10 }}, }; - PacketFragments packet99 = { + PacketFragments packet47 = { // type (short header, 4 byte packet number) {"", - { 0x32 }}, + { 0x43 }}, // connection_id {"", { 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 }}, @@ -3696,8 +4129,76 @@ { 0x12, 0x34, 0x56, 0x78 }}, // frame type (ack frame) + // (more than one ack block, 2 byte largest observed, 2 byte block length) {"", - { 0x1a }}, + { 0x65 }}, + // largest acked + {"Unable to read largest acked.", + { 0x12, 0x34 }}, + // 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.", + { 0x00, 0x01 }}, + // gap to next block. + { "Unable to read gap to next ack block.", + { 0x01 }}, + // ack block length. + { "Unable to ack block length.", + { 0x0e, 0xaf }}, + // gap to next block. + { "Unable to read gap to next ack block.", + { 0xff }}, + // ack block length. + { "Unable to ack block length.", + { 0x00, 0x00 }}, + // gap to next block. + { "Unable to read gap to next ack block.", + { 0x91 }}, + // ack block length. + { "Unable to ack block length.", + { 0x01, 0xea }}, + // gap to next block. + { "Unable to read gap to next ack block.", + { 0x05 }}, + // ack block length. + { "Unable to ack block length.", + { 0x00, 0x04 }}, + // Number of timestamps. + { "Unable to read num received packets.", + { 0x02 }}, + // Delta from largest observed. + { "Unable to read sequence delta in received packets.", + { 0x01 }}, + // Delta time. + { "Unable to read time delta in received packets.", + { 0x76, 0x54, 0x32, 0x10 }}, + // Delta from largest observed. + { "Unable to read sequence delta in received packets.", + { 0x02 }}, + // Delta time. + { "Unable to read incremental time delta in received packets.", + { 0x32, 0x10 }}, + }; + + PacketFragments packet99 = { + // type (short header, 4 byte packet number) + {"", + { 0x43 }}, + // connection_id + {"", + { 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 }}, + // packet number + {"", + { 0x12, 0x34, 0x56, 0x78 }}, + + // frame type (IETF_ACK frame) + {"", + { 0x02 }}, // largest acked {"Unable to read largest acked.", { kVarInt62TwoBytes + 0x12, 0x34 }}, // = 4660 @@ -3744,10 +4245,13 @@ PacketFragments& fragments = framer_.transport_version() == QUIC_VERSION_99 ? packet99 - : (framer_.transport_version() > QUIC_VERSION_43 - ? packet44 - : (framer_.transport_version() != QUIC_VERSION_35 ? packet39 - : packet)); + : (framer_.transport_version() > QUIC_VERSION_46 + ? packet47 + : (framer_.transport_version() > QUIC_VERSION_43 + ? packet44 + : (framer_.transport_version() != QUIC_VERSION_35 + ? packet39 + : packet))); std::unique_ptr<QuicEncryptedPacket> encrypted( AssemblePacketFromFragments(fragments)); @@ -3833,13 +4337,33 @@ {"Unable to read least unacked delta.", {0x00, 0x00, 0x00, 0x08}} }; + + PacketFragments packet47 = { + // type (short header, 4 byte packet number) + {"", + {0x43}}, + // connection_id + {"", + {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}}, + // packet number + {"", + {0x12, 0x34, 0x56, 0x78}}, + // frame type (stop waiting frame) + {"", + {0x06}}, + // least packet number awaiting an ack, delta from packet number. + {"Unable to read least unacked delta.", + {0x00, 0x00, 0x00, 0x08}} + }; // clang-format on PacketFragments& fragments = - framer_.transport_version() > QUIC_VERSION_43 - ? packet44 - : (framer_.transport_version() != QUIC_VERSION_35 ? packet39 - : packet); + framer_.transport_version() > QUIC_VERSION_46 + ? packet47 + : (framer_.transport_version() > QUIC_VERSION_43 + ? packet44 + : (framer_.transport_version() != QUIC_VERSION_35 ? packet39 + : packet)); std::unique_ptr<QuicEncryptedPacket> encrypted( AssemblePacketFromFragments(fragments)); EXPECT_TRUE(framer_.ProcessPacket(*encrypted)); @@ -3903,14 +4427,29 @@ // least packet number awaiting an ack, delta from packet number. 0x57, 0x78, 0x9A, 0xA8, }; + + unsigned char packet47[] = { + // type (short header, 4 byte packet number) + 0x43, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + // frame type (stop waiting frame) + 0x06, + // least packet number awaiting an ack, delta from packet number. + 0x57, 0x78, 0x9A, 0xA8, + }; // 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_46 + ? packet47 + : (framer_.transport_version() > QUIC_VERSION_43 + ? packet44 + : (framer_.transport_version() == QUIC_VERSION_35 + ? packet + : packet39))), framer_.transport_version() > QUIC_VERSION_43 ? QUIC_ARRAYSIZE(packet44) : QUIC_ARRAYSIZE(packet), false); @@ -3996,7 +4535,7 @@ {0x00, 0x00, 0x00, 0x01}} }; - PacketFragments packet99 = { + PacketFragments packet47 = { // type (short header, 4 byte packet number) {"", {0x43}}, @@ -4010,6 +4549,31 @@ {"", {0x01}}, // stream id + {"Unable to read stream_id.", + {0x01, 0x02, 0x03, 0x04}}, + // sent byte offset + {"Unable to read rst stream sent byte offset.", + {0x3A, 0x98, 0xFE, 0xDC, + 0x32, 0x10, 0x76, 0x54}}, + // error code + {"Unable to read rst stream error code.", + {0x00, 0x00, 0x00, 0x01}} + }; + + PacketFragments packet99 = { + // type (short header, 4 byte packet number) + {"", + {0x43}}, + // connection_id + {"", + {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}}, + // packet number + {"", + {0x12, 0x34, 0x56, 0x78}}, + // frame type (IETF_RST_STREAM frame) + {"", + {0x04}}, + // stream id {"Unable to read rst stream stream id.", {kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04}}, // application error code @@ -4024,10 +4588,13 @@ PacketFragments& fragments = framer_.transport_version() == QUIC_VERSION_99 ? packet99 - : (framer_.transport_version() > QUIC_VERSION_43 - ? packet44 - : (framer_.transport_version() != QUIC_VERSION_35 ? packet39 - : packet)); + : (framer_.transport_version() > QUIC_VERSION_46 + ? packet47 + : (framer_.transport_version() > QUIC_VERSION_43 + ? packet44 + : (framer_.transport_version() != QUIC_VERSION_35 + ? packet39 + : packet))); std::unique_ptr<QuicEncryptedPacket> encrypted( AssemblePacketFromFragments(fragments)); EXPECT_TRUE(framer_.ProcessPacket(*encrypted)); @@ -4130,7 +4697,7 @@ } }; - PacketFragments packet99 = { + PacketFragments packet47 = { // type (short header, 4 byte packet number) {"", {0x43}}, @@ -4145,6 +4712,34 @@ {0x02}}, // error code {"Unable to read connection close error code.", + {0x00, 0x00, 0x00, 0x11}}, + {"Unable to read connection close error details.", + { + // error details length + 0x0, 0x0d, + // error details + 'b', 'e', 'c', 'a', + 'u', 's', 'e', ' ', + 'I', ' ', 'c', 'a', + 'n'} + } + }; + + PacketFragments packet99 = { + // type (short header, 4 byte packet number) + {"", + {0x43}}, + // connection_id + {"", + {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}}, + // packet number + {"", + {0x12, 0x34, 0x56, 0x78}}, + // frame type (IETF_CONNECTION_CLOSE frame) + {"", + {0x1c}}, + // error code + {"Unable to read connection close error code.", {0x00, 0x11}}, {"Unable to read connection close frame type.", {kVarInt62TwoBytes + 0x12, 0x34 }}, @@ -4164,10 +4759,13 @@ PacketFragments& fragments = framer_.transport_version() == QUIC_VERSION_99 ? packet99 - : (framer_.transport_version() > QUIC_VERSION_43 - ? packet44 - : (framer_.transport_version() != QUIC_VERSION_35 ? packet39 - : packet)); + : (framer_.transport_version() > QUIC_VERSION_46 + ? packet47 + : (framer_.transport_version() > QUIC_VERSION_43 + ? packet44 + : (framer_.transport_version() != QUIC_VERSION_35 + ? packet39 + : packet))); std::unique_ptr<QuicEncryptedPacket> encrypted( AssemblePacketFromFragments(fragments)); EXPECT_TRUE(framer_.ProcessPacket(*encrypted)); @@ -4208,9 +4806,9 @@ // packet number {"", {0x12, 0x34, 0x56, 0x78}}, - // frame type (application close frame) + // frame type (IETF_APPLICATION_CLOSE frame) {"", - {0x03}}, + {0x1d}}, // error code {"Unable to read application close error code.", {0x00, 0x11}}, @@ -4347,13 +4945,47 @@ 'n'} } }; + + PacketFragments packet47 = { + // type (short header, 4 byte packet number) + {"", + {0x43}}, + // connection_id + {"", + {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}}, + // packet number + {"", + {0x12, 0x34, 0x56, 0x78}}, + // frame type (go away frame) + {"", + {0x03}}, + // error code + {"Unable to read go away error code.", + {0x00, 0x00, 0x00, 0x09}}, + // stream id + {"Unable to read last good stream id.", + {0x01, 0x02, 0x03, 0x04}}, + // stream id + {"Unable to read goaway reason.", + { + // error details length + 0x0, 0x0d, + // error details + 'b', 'e', 'c', 'a', + 'u', 's', 'e', ' ', + 'I', ' ', 'c', 'a', + 'n'} + } + }; // clang-format on PacketFragments& fragments = - framer_.transport_version() > QUIC_VERSION_43 - ? packet44 - : (framer_.transport_version() != QUIC_VERSION_35 ? packet39 - : packet); + framer_.transport_version() > QUIC_VERSION_46 + ? packet47 + : (framer_.transport_version() > QUIC_VERSION_43 + ? packet44 + : (framer_.transport_version() != QUIC_VERSION_35 ? packet39 + : packet)); std::unique_ptr<QuicEncryptedPacket> encrypted( AssemblePacketFromFragments(fragments)); EXPECT_TRUE(framer_.ProcessPacket(*encrypted)); @@ -4425,6 +5057,28 @@ PacketFragments packet44 = { // type (short header, 4 byte packet number) {"", + {0x32}}, + // connection_id + {"", + {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}}, + // packet number + {"", + {0x12, 0x34, 0x56, 0x78}}, + // frame type (window update frame) + {"", + {0x04}}, + // stream id + {"Unable to read stream_id.", + {0x01, 0x02, 0x03, 0x04}}, + // byte offset + {"Unable to read window byte_offset.", + {0x3A, 0x98, 0xFE, 0xDC, + 0x32, 0x10, 0x76, 0x54}}, + }; + + PacketFragments packet47 = { + // type (short header, 4 byte packet number) + {"", {0x43}}, // connection_id {"", @@ -4447,10 +5101,12 @@ // clang-format on PacketFragments& fragments = - framer_.transport_version() > QUIC_VERSION_43 - ? packet44 - : (framer_.transport_version() != QUIC_VERSION_35 ? packet39 - : packet); + framer_.transport_version() > QUIC_VERSION_46 + ? packet47 + : (framer_.transport_version() > QUIC_VERSION_43 + ? packet44 + : (framer_.transport_version() != QUIC_VERSION_35 ? packet39 + : packet)); std::unique_ptr<QuicEncryptedPacket> encrypted( AssemblePacketFromFragments(fragments)); EXPECT_TRUE(framer_.ProcessPacket(*encrypted)); @@ -4483,9 +5139,9 @@ // packet number {"", {0x12, 0x34, 0x56, 0x78}}, - // frame type (IETF max data frame) + // frame type (IETF_MAX_DATA frame) {"", - {0x04}}, + {0x10}}, // byte offset {"Can not read MAX_DATA byte-offset", {kVarInt62EightBytes + 0x3A, 0x98, 0xFE, 0xDC, @@ -4525,9 +5181,9 @@ // packet number {"", {0x12, 0x34, 0x56, 0x78}}, - // frame type (ietf max stream data frame) + // frame type (IETF_MAX_STREAM_DATA frame) {"", - {0x05}}, + {0x11}}, // stream id {"Can not read MAX_STREAM_DATA stream id", {kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04}}, @@ -4610,6 +5266,24 @@ {0x01, 0x02, 0x03, 0x04}}, }; + PacketFragments packet47 = { + // type (short header, 4 byte packet number) + {"", + {0x43}}, + // connection_id + {"", + {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}}, + // packet number + {"", + {0x12, 0x34, 0x56, 0x78}}, + // frame type (blocked frame) + {"", + {0x05}}, + // stream id + {"Unable to read stream_id.", + {0x01, 0x02, 0x03, 0x04}}, + }; + PacketFragments packet99 = { // type (short header, 4 byte packet number) {"", @@ -4620,9 +5294,9 @@ // packet number {"", {0x12, 0x34, 0x56, 0x78}}, - // frame type (IETF stream blocked frame) + // frame type (IETF_STREAM_BLOCKED frame) {"", - {0x09}}, + {0x15}}, // stream id {"Can not read stream blocked stream id.", {kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04}}, @@ -4635,10 +5309,13 @@ PacketFragments& fragments = framer_.transport_version() == QUIC_VERSION_99 ? packet99 - : (framer_.transport_version() > QUIC_VERSION_43 - ? packet44 - : (framer_.transport_version() != QUIC_VERSION_35 ? packet39 - : packet)); + : (framer_.transport_version() > QUIC_VERSION_46 + ? packet47 + : (framer_.transport_version() > QUIC_VERSION_43 + ? packet44 + : (framer_.transport_version() != QUIC_VERSION_35 + ? packet39 + : packet))); std::unique_ptr<QuicEncryptedPacket> encrypted( AssemblePacketFromFragments(fragments)); EXPECT_TRUE(framer_.ProcessPacket(*encrypted)); @@ -4700,16 +5377,49 @@ // frame type 0x07, }; + + unsigned char packet47[] = { + // type (short header, 4 byte packet number) + 0x43, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + + // frame type + 0x07, + }; + + unsigned char packet99[] = { + // type (short header, 4 byte packet number) + 0x43, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + + // frame type (IETF_PING frame) + 0x01, + }; // clang-format on QuicEncryptedPacket encrypted( - AsChars(framer_.transport_version() > QUIC_VERSION_43 - ? packet44 - : (framer_.transport_version() == QUIC_VERSION_35 - ? packet - : packet39)), - framer_.transport_version() > QUIC_VERSION_43 ? QUIC_ARRAYSIZE(packet44) - : QUIC_ARRAYSIZE(packet), + AsChars(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 + ? packet + : packet39))), + framer_.transport_version() == QUIC_VERSION_99 + ? QUIC_ARRAYSIZE(packet99) + : (framer_.transport_version() > QUIC_VERSION_46 + ? QUIC_ARRAYSIZE(packet47) + : framer_.transport_version() > QUIC_VERSION_43 + ? QUIC_ARRAYSIZE(packet44) + : QUIC_ARRAYSIZE(packet)), false); EXPECT_TRUE(framer_.ProcessPacket(encrypted)); @@ -4755,10 +5465,37 @@ {{}, {'m', 'e', 's', 's', 'a', 'g', 'e', '2'}}, }; + + PacketFragments packet47 = { + // type (short header, 4 byte packet number) + {"", + {0x43}}, + // connection_id + {"", + {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}}, + // packet number + {"", + {0x12, 0x34, 0x56, 0x78}}, + // message frame type. + {"", + { 0x21 }}, + // message length + {"Unable to read message length", + {0x07}}, + // message data + {"Unable to read message data", + {'m', 'e', 's', 's', 'a', 'g', 'e'}}, + // message frame no length. + {"", + { 0x20 }}, + // message data + {{}, + {'m', 'e', 's', 's', 'a', 'g', 'e', '2'}}, + }; // clang-format on - std::unique_ptr<QuicEncryptedPacket> encrypted( - AssemblePacketFromFragments(packet45)); + std::unique_ptr<QuicEncryptedPacket> encrypted(AssemblePacketFromFragments( + framer_.transport_version() > QUIC_VERSION_46 ? packet47 : packet45)); EXPECT_TRUE(framer_.ProcessPacket(*encrypted)); EXPECT_EQ(QUIC_NO_ERROR, framer_.error()); @@ -4771,7 +5508,9 @@ EXPECT_EQ(7u, visitor_.message_frames_[0]->message_data.length()); EXPECT_EQ(8u, visitor_.message_frames_[1]->message_data.length()); - CheckFramingBoundaries(packet45, QUIC_INVALID_MESSAGE_DATA); + CheckFramingBoundaries( + framer_.transport_version() > QUIC_VERSION_46 ? packet47 : packet45, + QUIC_INVALID_MESSAGE_DATA); } TEST_P(QuicFramerTest, PublicResetPacketV33) { @@ -5186,6 +5925,19 @@ 0x00, 0x00, 0x00, 0x00 }; + unsigned char packet47[kMaxPacketSize] = { + // type (short header, 4 byte packet number) + 0x43, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + + // frame type (padding frame) + 0x00, + 0x00, 0x00, 0x00, 0x00 + }; + unsigned char packet99[kMaxPacketSize] = { // type (short header, 4 byte packet number) 0x43, @@ -5203,6 +5955,8 @@ unsigned char* p = packet; if (framer_.transport_version() == QUIC_VERSION_99) { p = packet99; + } else if (framer_.transport_version() > QUIC_VERSION_46) { + p = packet47; } else if (framer_.transport_version() > QUIC_VERSION_43) { p = packet44; } else if (framer_.transport_version() != QUIC_VERSION_35) { @@ -5321,6 +6075,33 @@ 0x00, 0x00, }; + unsigned char packet47[] = { + // type (short header, 4 byte packet number) + 0x43, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + + // paddings + 0x00, 0x00, + // frame type (stream frame with fin) + 0xFF, + // stream id + 0x01, 0x02, 0x03, 0x04, + // offset + 0x3A, 0x98, 0xFE, 0xDC, + 0x32, 0x10, 0x76, 0x54, + // data length + 0x00, 0x0c, + // data + 'h', 'e', 'l', 'l', + 'o', ' ', 'w', 'o', + 'r', 'l', 'd', '!', + // paddings + 0x00, 0x00, + }; + unsigned char packet99[] = { // type (short header, 4 byte packet number) 0x43, @@ -5331,8 +6112,8 @@ // paddings 0x00, 0x00, - // frame type (stream frame with FIN, LEN, and OFFSET bits set) - 0x10 | 0x01 | 0x02 | 0x04, + // frame type (IETF_STREAM with FIN, LEN, and OFFSET bits set) + 0x08 | 0x01 | 0x02 | 0x04, // stream id kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04, // offset @@ -5357,6 +6138,9 @@ 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_43) { p = packet44; p_size = QUIC_ARRAYSIZE(packet44); @@ -5419,6 +6203,19 @@ 0x00, 0x00, 0x00, 0x00 }; + unsigned char packet47[kMaxPacketSize] = { + // type (short header, 4 byte packet number) + 0x43, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + + // frame type (padding frame) + 0x00, + 0x00, 0x00, 0x00, 0x00 + }; + unsigned char packet99[kMaxPacketSize] = { // type (short header, 4 byte packet number) 0x43, @@ -5436,6 +6233,8 @@ unsigned char* p = packet; if (framer_.transport_version() == QUIC_VERSION_99) { p = packet99; + } else if (framer_.transport_version() > QUIC_VERSION_46) { + p = packet47; } else if (framer_.transport_version() > QUIC_VERSION_43) { p = packet44; } else if (framer_.transport_version() != QUIC_VERSION_35) { @@ -5507,6 +6306,19 @@ 0x00, 0x00, 0x00, 0x00 }; + unsigned char packet47[kMaxPacketSize] = { + // type (short header, 2 byte packet number) + 0x41, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x56, 0x78, + + // frame type (padding frame) + 0x00, + 0x00, 0x00, 0x00, 0x00 + }; + unsigned char packet99[kMaxPacketSize] = { // type (short header, 2 byte packet number) 0x41, @@ -5524,6 +6336,8 @@ unsigned char* p = packet; if (framer_.transport_version() == QUIC_VERSION_99) { p = packet99; + } else if (framer_.transport_version() > QUIC_VERSION_46) { + p = packet47; } else if (framer_.transport_version() > QUIC_VERSION_43) { p = packet44; } else if (framer_.transport_version() != QUIC_VERSION_35) { @@ -5582,6 +6396,19 @@ 0x00, 0x00, 0x00, 0x00 }; + unsigned char packet47[kMaxPacketSize] = { + // type (short header, 1 byte packet number) + 0x40, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x78, + + // frame type (padding frame) + 0x00, + 0x00, 0x00, 0x00, 0x00 + }; + unsigned char packet99[kMaxPacketSize] = { // type (short header, 1 byte packet number) 0x40, @@ -5599,6 +6426,8 @@ unsigned char* p = packet; if (framer_.transport_version() == QUIC_VERSION_99) { p = packet99; + } else if (framer_.transport_version() > QUIC_VERSION_46) { + p = packet47; } else if (framer_.transport_version() > QUIC_VERSION_43) { p = packet44; } @@ -5694,6 +6523,27 @@ 'r', 'l', 'd', '!', }; + unsigned char packet47[] = { + // type (short header, 4 byte packet number) + 0x43, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + + // frame type (stream frame with fin and no length) + 0xDF, + // stream id + 0x01, 0x02, 0x03, 0x04, + // offset + 0x3A, 0x98, 0xFE, 0xDC, + 0x32, 0x10, 0x76, 0x54, + // data + 'h', 'e', 'l', 'l', + 'o', ' ', 'w', 'o', + 'r', 'l', 'd', '!', + }; + unsigned char packet99[] = { // type (short header, 4 byte packet number) 0x43, @@ -5702,8 +6552,8 @@ // packet number 0x12, 0x34, 0x56, 0x78, - // frame type (stream frame with FIN and OFFSET, no length) - 0x10 | 0x01 | 0x04, + // frame type (IETF_STREAM frame with FIN and OFFSET, no length) + 0x08 | 0x01 | 0x04, // stream id kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04, // offset @@ -5724,6 +6574,9 @@ 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_43) { p = packet44; p_size = QUIC_ARRAYSIZE(packet44); @@ -5811,6 +6664,28 @@ 'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '!', }; + unsigned char packet47[] = { + // type (long header with packet type ZERO_RTT_PROTECTED) + 0xD3, + // version tag + QUIC_VERSION_BYTES, + // connection_id length + 0x50, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + + // frame type (stream frame with fin and no length) + 0xDF, + // stream id + 0x01, 0x02, 0x03, 0x04, + // offset + 0x3A, 0x98, 0xFE, 0xDC, 0x32, 0x10, 0x76, 0x54, + // data + 'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '!', + }; + unsigned char packet99[] = { // type (long header with packet type ZERO_RTT_PROTECTED) 0xD3, @@ -5823,8 +6698,8 @@ // packet number 0x12, 0x34, 0x56, 0x78, - // frame type (stream frame with fin and offset, no length) - 0x10 | 0x01 | 0x04, + // frame type (IETF_STREAM frame with fin and offset, no length) + 0x08 | 0x01 | 0x04, // stream id kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04, // offset @@ -5843,6 +6718,9 @@ 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_43) { p = packet44; p_size = QUIC_ARRAYSIZE(packet44); @@ -5853,6 +6731,112 @@ data->length(), AsChars(p), p_size); } +TEST_P(QuicFramerTest, BuildCryptoFramePacket) { + if (framer_.transport_version() < QUIC_VERSION_99) { + // CRYPTO frames aren't supported prior to v46. + return; + } + QuicPacketHeader header; + header.destination_connection_id = FramerTestConnectionId(); + header.reset_flag = false; + header.version_flag = false; + header.packet_number = kPacketNumber; + + SimpleDataProducer data_producer; + framer_.set_data_producer(&data_producer); + + QuicStringPiece crypto_frame_contents("hello world!"); + QuicCryptoFrame crypto_frame(ENCRYPTION_NONE, kStreamOffset, + crypto_frame_contents.length()); + data_producer.SaveCryptoData(ENCRYPTION_NONE, kStreamOffset, + crypto_frame_contents); + + QuicFrames frames = {QuicFrame(&crypto_frame)}; + + // clang-format off + unsigned char packet[] = { + // type (short header, 4 byte packet number) + 0x43, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + + // frame type (IETF_CRYPTO frame) + 0x06, + // offset + kVarInt62EightBytes + 0x3A, 0x98, 0xFE, 0xDC, + 0x32, 0x10, 0x76, 0x54, + // length + kVarInt62OneByte + 12, + // data + 'h', 'e', 'l', 'l', + 'o', ' ', 'w', 'o', + 'r', 'l', 'd', '!', + }; + // clang-format on + + size_t packet_size = QUIC_ARRAYSIZE(packet); + + std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames)); + ASSERT_TRUE(data != nullptr); + test::CompareCharArraysWithHexError("constructed packet", data->data(), + data->length(), AsChars(packet), + packet_size); +} + +TEST_P(QuicFramerTest, CryptoFrame) { + if (framer_.transport_version() < QUIC_VERSION_99) { + // CRYPTO frames aren't supported prior to v46. + return; + } + + // clang-format off + PacketFragments packet = { + // type (short header, 4 byte packet number) + {"", + {0x43}}, + // connection_id + {"", + {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}}, + // packet number + {"", + {0x12, 0x34, 0x56, 0x78}}, + // frame type (IETF_CRYPTO frame) + {"", + {0x06}}, + // offset + {"", + {kVarInt62EightBytes + 0x3A, 0x98, 0xFE, 0xDC, + 0x32, 0x10, 0x76, 0x54}}, + // data length + {"Invalid data length.", + {kVarInt62OneByte + 12}}, + // data + {"Unable to read frame data.", + {'h', 'e', 'l', 'l', + 'o', ' ', 'w', 'o', + 'r', 'l', 'd', '!'}}, + }; + // clang-format on + + std::unique_ptr<QuicEncryptedPacket> encrypted( + AssemblePacketFromFragments(packet)); + 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(1u, visitor_.crypto_frames_.size()); + QuicCryptoFrame* frame = visitor_.crypto_frames_[0].get(); + EXPECT_EQ(kStreamOffset, frame->offset); + EXPECT_EQ("hello world!", QuicString(frame->data_buffer, frame->data_length)); + + CheckFramingBoundaries(packet, QUIC_INVALID_FRAME_DATA); +} + TEST_P(QuicFramerTest, BuildVersionNegotiationPacket) { // clang-format off unsigned char packet[] = { @@ -5969,7 +6953,7 @@ 0x00, }; - unsigned char packet99[] = { + unsigned char packet47[] = { // type (short header, 4 byte packet number) 0x43, // connection_id @@ -5978,7 +6962,28 @@ 0x12, 0x34, 0x56, 0x78, // frame type (ack frame) - 0x1a, + // (no ack blocks, 2 byte largest observed, 2 byte block length) + 0x45, + // largest acked + 0x12, 0x34, + // Zero delta time. + 0x00, 0x00, + // first ack block length. + 0x12, 0x34, + // num timestamps. + 0x00, + }; + + unsigned char packet99[] = { + // type (short header, 4 byte packet number) + 0x43, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + + // frame type (IETF_ACK frame) + 0x02, // largest acked kVarInt62TwoBytes + 0x12, 0x34, // Zero delta time. @@ -5994,6 +6999,9 @@ 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_43) { p = packet44; p_size = QUIC_ARRAYSIZE(packet44); @@ -6083,6 +7091,27 @@ 0x00, }; + unsigned char packet47[] = { + // type (short header, 4 byte packet number) + 0x43, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + + // frame type (ack frame) + // (no ack blocks, 4 byte largest observed, 4 byte block length) + 0x4A, + // largest acked + 0x12, 0x34, 0x56, 0x78, + // Zero delta time. + 0x00, 0x00, + // first ack block length. + 0x12, 0x34, 0x56, 0x78, + // num timestamps. + 0x00, + }; + unsigned char packet99[] = { // type (short header, 4 byte packet number) @@ -6092,8 +7121,8 @@ // packet number 0x12, 0x34, 0x56, 0x78, - // frame type (ack frame) - 0x1a, + // frame type (IETF_ACK frame) + 0x02, // largest acked kVarInt62FourBytes + 0x12, 0x34, 0x56, 0x78, // Zero delta time. @@ -6109,6 +7138,9 @@ 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_43) { p = packet44; p_size = QUIC_ARRAYSIZE(packet44); @@ -6131,9 +7163,9 @@ // Use kSmallLargestObserved to make this test finished in a short time. QuicAckFrame ack_frame = - InitAckFrame({{1, 5}, - {10, 500}, - {900, kSmallMissingPacket}, + InitAckFrame({{QuicPacketNumber(1), QuicPacketNumber(5)}, + {QuicPacketNumber(10), QuicPacketNumber(500)}, + {QuicPacketNumber(900), kSmallMissingPacket}, {kSmallMissingPacket + 1, kSmallLargestObserved + 1}}); ack_frame.ack_delay_time = QuicTime::Delta::Zero(); @@ -6257,7 +7289,7 @@ 0x00, }; - unsigned char packet99[] = { + unsigned char packet47[] = { // type (short header, 4 byte packet number) 0x43, // connection_id @@ -6266,7 +7298,46 @@ 0x12, 0x34, 0x56, 0x78, // frame type (ack frame) - 0x1a, + // (has ack blocks, 2 byte largest observed, 2 byte block length) + 0x65, + // largest acked + 0x12, 0x34, + // Zero delta time. + 0x00, 0x00, + // num ack blocks ranges. + 0x04, + // first ack block length. + 0x00, 0x01, + // gap to next block. + 0x01, + // ack block length. + 0x0e, 0xaf, + // gap to next block. + 0xff, + // ack block length. + 0x00, 0x00, + // gap to next block. + 0x91, + // ack block length. + 0x01, 0xea, + // gap to next block. + 0x05, + // ack block length. + 0x00, 0x04, + // num timestamps. + 0x00, + }; + + unsigned char packet99[] = { + // type (short header, 4 byte packet number) + 0x43, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + + // frame type (IETF_ACK frame) + 0x02, // largest acked kVarInt62TwoBytes + 0x12, 0x34, // Zero delta time. @@ -6297,6 +7368,9 @@ 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_43) { p = packet44; p_size = QUIC_ARRAYSIZE(packet44); @@ -6324,9 +7398,9 @@ ack_frame.ack_delay_time = QuicTime::Delta::Zero(); // 300 ack blocks. for (size_t i = 2; i < 2 * 300; i += 2) { - ack_frame.packets.Add(i); + ack_frame.packets.Add(QuicPacketNumber(i)); } - ack_frame.packets.AddRange(600, kSmallLargestObserved + 1); + ack_frame.packets.AddRange(QuicPacketNumber(600), kSmallLargestObserved + 1); QuicFrames frames = {QuicFrame(&ack_frame)}; @@ -6610,7 +7684,7 @@ 0x00, }; - unsigned char packet99[] = { + unsigned char packet47[] = { // type (short header, 4 byte packet number) 0x43, // connection_id @@ -6618,7 +7692,100 @@ // packet number 0x12, 0x34, 0x56, 0x78, // frame type (ack frame) - 0x1a, + // (has ack blocks, 2 byte largest observed, 2 byte block length) + 0x65, + // largest acked + 0x12, 0x34, + // Zero delta time. + 0x00, 0x00, + // num ack blocks ranges. + 0xff, + // first ack block length. + 0x0f, 0xdd, + // 255 = 4 * 63 + 3 + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, + // num timestamps. + 0x00, + }; + + unsigned char packet99[] = { + // type (short header, 4 byte packet number) + 0x43, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + // frame type (IETF_ACK frame) + 0x02, // largest acked kVarInt62TwoBytes + 0x12, 0x34, // Zero delta time. @@ -6700,6 +7867,9 @@ 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_43) { p = packet44; p_size = QUIC_ARRAYSIZE(packet44); @@ -6848,7 +8018,7 @@ 0x05, 0x06, 0x07, 0x08, }; - unsigned char packet99[] = { + unsigned char packet47[] = { // type (short packet, 4 byte packet number) 0x43, // connection_id @@ -6859,6 +8029,25 @@ // frame type (rst stream frame) 0x01, // stream id + 0x01, 0x02, 0x03, 0x04, + // sent byte offset + 0x08, 0x07, 0x06, 0x05, + 0x04, 0x03, 0x02, 0x01, + // error code + 0x05, 0x06, 0x07, 0x08, + }; + + unsigned char packet99[] = { + // type (short packet, 4 byte packet number) + 0x43, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + + // frame type (IETF_RST_STREAM frame) + 0x04, + // stream id kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04, // error code (not VarInt32 encoded) 0x00, 0x01, @@ -6877,6 +8066,9 @@ 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_43) { p = packet44; p_size = QUIC_ARRAYSIZE(packet44); @@ -6972,7 +8164,7 @@ 'n', }; - unsigned char packet99[] = { + unsigned char packet47[] = { // type (short header, 4 byte packet number) 0x43, // connection_id @@ -6983,6 +8175,27 @@ // frame type (connection close frame) 0x02, // error code + 0x05, 0x06, 0x07, 0x08, + // error details length + 0x00, 0x0d, + // error details + 'b', 'e', 'c', 'a', + 'u', 's', 'e', ' ', + 'I', ' ', 'c', 'a', + 'n', + }; + + unsigned char packet99[] = { + // type (short header, 4 byte packet number) + 0x43, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + + // frame type (IETF_CONNECTION_CLOSE frame) + 0x1c, + // error code 0x00, 0x11, // Frame type within the CONNECTION_CLOSE frame kVarInt62OneByte + 0x05, @@ -7001,6 +8214,9 @@ 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_43) { p = packet44; p_size = QUIC_ARRAYSIZE(packet44); @@ -7180,7 +8396,7 @@ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', }; - unsigned char packet99[] = { + unsigned char packet47[] = { // type (short header, 4 byte packet number) 0x43, // connection_id @@ -7191,6 +8407,55 @@ // frame type (connection close frame) 0x02, // error code + 0x05, 0x06, 0x07, 0x08, + // error details length + 0x01, 0x00, + // error details (truncated to 256 bytes) + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + }; + + unsigned char packet99[] = { + // type (short header, 4 byte packet number) + 0x43, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + + // frame type (IETF_CONNECTION_CLOSE frame) + 0x1c, + // error code 0x00, 0x0a, // Frame type within the CONNECTION_CLOSE frame kVarInt62OneByte + 0x00, @@ -7237,6 +8502,9 @@ 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_43) { p = packet44; p_size = QUIC_ARRAYSIZE(packet44); @@ -7278,8 +8546,8 @@ // packet number 0x12, 0x34, 0x56, 0x78, - // frame type (application close frame) - 0x03, + // frame type (IETF_APPLICATION_CLOSE frame) + 0x1d, // error code 0x00, 0x11, // error details length @@ -7326,8 +8594,8 @@ // packet number 0x12, 0x34, 0x56, 0x78, - // frame type - 0x03, + // frame type (IETF_APPLICATION_CLOSE frame) + 0x1d, // error code 0x00, 0x11, // error details length @@ -7464,11 +8732,37 @@ 'n', }; + unsigned char packet47[] = { + // type (short header, 4 byte packet number) + 0x43, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + + // frame type (go away frame) + 0x03, + // error code + 0x05, 0x06, 0x07, 0x08, + // stream id + 0x01, 0x02, 0x03, 0x04, + // error details length + 0x00, 0x0d, + // error details + 'b', 'e', 'c', 'a', + 'u', 's', 'e', ' ', + 'I', ' ', 'c', 'a', + 'n', + }; + // clang-format on unsigned char* p = packet; size_t p_size = QUIC_ARRAYSIZE(packet); - if (framer_.transport_version() > QUIC_VERSION_43) { + if (framer_.transport_version() > QUIC_VERSION_46) { + p = packet47; + p_size = QUIC_ARRAYSIZE(packet47); + } else if (framer_.transport_version() > QUIC_VERSION_43) { p = packet44; p_size = QUIC_ARRAYSIZE(packet44); } else if (framer_.transport_version() != QUIC_VERSION_35) { @@ -7653,11 +8947,65 @@ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', }; + + unsigned char packet47[] = { + // type (short header, 4 byte packet number) + 0x43, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + + // frame type (go away frame) + 0x03, + // error code + 0x05, 0x06, 0x07, 0x08, + // stream id + 0x01, 0x02, 0x03, 0x04, + // error details length + 0x01, 0x00, + // error details (truncated to 256 bytes) + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', + }; // clang-format on unsigned char* p = packet; size_t p_size = QUIC_ARRAYSIZE(packet); - if (framer_.transport_version() > QUIC_VERSION_43) { + if (framer_.transport_version() > QUIC_VERSION_46) { + p = packet47; + p_size = QUIC_ARRAYSIZE(packet47); + } else if (framer_.transport_version() > QUIC_VERSION_43) { p = packet44; p_size = QUIC_ARRAYSIZE(packet44); } else if (framer_.transport_version() != QUIC_VERSION_35) { @@ -7736,6 +9084,23 @@ 0x55, 0x66, 0x77, 0x88, }; + unsigned char packet47[] = { + // type (short header, 4 byte packet number) + 0x43, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + + // frame type (window update frame) + 0x04, + // stream id + 0x01, 0x02, 0x03, 0x04, + // byte offset + 0x11, 0x22, 0x33, 0x44, + 0x55, 0x66, 0x77, 0x88, + }; + unsigned char packet99[] = { // type (short header, 4 byte packet number) 0x43, @@ -7744,8 +9109,8 @@ // packet number 0x12, 0x34, 0x56, 0x78, - // frame type (max stream data frame) - 0x05, + // frame type (IETF_MAX_STREAM_DATA frame) + 0x11, // stream id kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04, // byte offset @@ -7762,6 +9127,9 @@ 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_43) { p = packet44; p_size = QUIC_ARRAYSIZE(packet44); @@ -7799,8 +9167,8 @@ // packet number 0x12, 0x34, 0x56, 0x78, - // frame type (max stream data frame) - 0x05, + // frame type (IETF_MAX_STREAM_DATA frame) + 0x11, // stream id kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04, // byte offset @@ -7843,8 +9211,8 @@ // packet number 0x12, 0x34, 0x56, 0x78, - // frame type (max data frame) - 0x04, + // frame type (IETF_MAX_DATA frame) + 0x10, // byte offset kVarInt62EightBytes + 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, @@ -7867,7 +9235,16 @@ header.packet_number = kPacketNumber; QuicBlockedFrame blocked_frame; - blocked_frame.stream_id = kStreamId; + if (framer_.transport_version() == QUIC_VERSION_99) { + // For V99, the stream ID must be 0 for the frame + // to be a BLOCKED frame. if non-0, it will be a + // STREAM_BLOCKED frame. + // TODO(fkastenholz): This should be converted to use + // QuicUtils::GetInvalidStreamId to get the correct invalid stream id value. + blocked_frame.stream_id = 0; + } else { + blocked_frame.stream_id = kStreamId; + } blocked_frame.offset = kStreamOffset; QuicFrames frames = {QuicFrame(&blocked_frame)}; @@ -7915,6 +9292,20 @@ 0x01, 0x02, 0x03, 0x04, }; + unsigned char packet47[] = { + // type (short packet, 4 byte packet number) + 0x43, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + + // frame type (blocked frame) + 0x05, + // stream id + 0x01, 0x02, 0x03, 0x04, + }; + unsigned char packet99[] = { // type (short packet, 4 byte packet number) 0x43, @@ -7923,10 +9314,8 @@ // packet number 0x12, 0x34, 0x56, 0x78, - // frame type - 0x09, - // stream id - kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04, + // frame type (IETF_BLOCKED frame) wahoo + 0x14, // Offset kVarInt62EightBytes + 0x3a, 0x98, 0xFE, 0xDC, 0x32, 0x10, 0x76, 0x54 }; @@ -7940,6 +9329,9 @@ 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_43) { p = packet44; p_size = QUIC_ARRAYSIZE(packet44); @@ -7997,7 +9389,7 @@ 0x07, }; - unsigned char packet99[] = { + unsigned char packet47[] = { // type (short header, 4 byte packet number) 0x43, // connection_id @@ -8008,11 +9400,25 @@ // frame type 0x07, }; + + unsigned char packet99[] = { + // type (short header, 4 byte packet number) + 0x43, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + + // frame type (IETF_PING frame) + 0x01, + }; // clang-format on unsigned char* p = packet; if (framer_.transport_version() == QUIC_VERSION_99) { p = packet99; + } else if (framer_.transport_version() > QUIC_VERSION_46) { + p = packet47; } else if (framer_.transport_version() > QUIC_VERSION_43) { p = packet44; } else if (framer_.transport_version() != QUIC_VERSION_35) { @@ -8063,7 +9469,7 @@ 'm', 'e', 's', 's', 'a', 'g', 'e', '2' }; - unsigned char packet99[] = { + unsigned char packet47[] = { // type (short header, 4 byte packet number) 0x43, // connection_id @@ -8082,11 +9488,33 @@ // Message Data 'm', 'e', 's', 's', 'a', 'g', 'e', '2' }; + + unsigned char packet99[] = { + // type (short header, 4 byte packet number) + 0x43, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + + // frame type (IETF_MESSAGE frame) + 0x21, + // Length + 0x07, + // Message Data + 'm', 'e', 's', 's', 'a', 'g', 'e', + // frame type (message frame no length) + 0x20, + // Message Data + 'm', 'e', 's', 's', 'a', 'g', 'e', '2' + }; // clang-format on unsigned char* p = packet45; if (framer_.transport_version() == QUIC_VERSION_99) { p = packet99; + } else if (framer_.transport_version() > QUIC_VERSION_46) { + p = packet47; } std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames)); @@ -8152,7 +9580,7 @@ 0x00, 0x00, 0x00, 0x00 }; - unsigned char packet99[] = { + unsigned char packet47[] = { // type (short header, 4 byte packet number) 0x43, // connection_id @@ -8166,6 +9594,21 @@ 0x00, 0x00, 0x00, 0x00, 0x00 }; + + unsigned char packet99[] = { + // type (short header, 4 byte packet number) + 0x43, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + + // frame type (IETF_PING frame) + 0x01, + // frame type (padding frame) + 0x00, + 0x00, 0x00, 0x00, 0x00 + }; // clang-format on unsigned char* p = packet; @@ -8173,6 +9616,9 @@ if (framer_.transport_version() == QUIC_VERSION_99) { p = packet99; packet_size = QUIC_ARRAYSIZE(packet99); + } else if (framer_.transport_version() > QUIC_VERSION_46) { + p = packet47; + packet_size = QUIC_ARRAYSIZE(packet47); } else if (framer_.transport_version() > QUIC_VERSION_43) { p = packet44; packet_size = QUIC_ARRAYSIZE(packet44); @@ -8196,6 +9642,49 @@ data.length(), AsChars(p), packet_size); } +// Test that the IETF connectivity probing packet is serialized correctly as a +// padded PING packet, v99 only. +TEST_P(QuicFramerTest, BuildIetfConnectivityProbingPacket) { + if (framer_.transport_version() != QUIC_VERSION_99) { + return; + } + QuicPacketHeader header; + header.destination_connection_id = FramerTestConnectionId(); + header.reset_flag = false; + header.version_flag = false; + header.packet_number = kPacketNumber; + + unsigned char packet99[] = {// type (short header, 4 byte packet number) + 0x43, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + + // frame type (IETF_PING frame) + 0x01, + // frame type (padding frame) + 0x00, 0x00, 0x00, 0x00, 0x00}; + // clang-format on + + unsigned char* p = packet99; + size_t packet_size = QUIC_ARRAYSIZE(packet99); + + std::unique_ptr<char[]> buffer(new char[kMaxPacketSize]); + + size_t length = framer_.BuildIetfConnectivityProbingPacket( + header, buffer.get(), packet_size); + + EXPECT_NE(0u, length); + QuicPacket data(buffer.release(), length, true, + header.destination_connection_id_length, + header.source_connection_id_length, header.version_flag, + header.nonce != nullptr, header.packet_number_length); + + test::CompareCharArraysWithHexError("constructed packet", data.data(), + data.length(), AsChars(p), packet_size); +} + // Test that the path challenge connectivity probing packet is serialized // correctly as a padded PATH CHALLENGE packet. TEST_P(QuicFramerTest, BuildPaddedPathChallengePacket) { @@ -8219,8 +9708,8 @@ // packet number 0x12, 0x34, 0x56, 0x78, - // Path Challenge Frame type - 0x0e, + // Path Challenge Frame type (IETF_PATH_CHALLENGE) + 0x1a, // 8 "random" bytes, MockRandom makes lots of r's 'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r', // frame type (padding frame) @@ -8277,8 +9766,8 @@ // packet number 0x12, 0x34, 0x56, 0x78, - // Path Challenge Frame type - 0x0f, + // Path Response Frame type (IETF_PATH_RESPONSE) + 0x1b, // 8 "random" bytes 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, }; @@ -8323,8 +9812,8 @@ // packet number 0x12, 0x34, 0x56, 0x78, - // Path Challenge Frame type - 0x0f, + // Path Response Frame type (IETF_PATH_RESPONSE) + 0x1b, // 8 "random" bytes 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // Padding type and pad @@ -8375,10 +9864,10 @@ // packet number 0x12, 0x34, 0x56, 0x78, - // 3 path challenge frames (type byte and payload) - 0x0f, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, - 0x0f, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, - 0x0f, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, + // 3 path response frames (IETF_PATH_RESPONSE type byte and payload) + 0x1b, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x1b, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x1b, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, }; // clang-format on @@ -8428,10 +9917,10 @@ // packet number 0x12, 0x34, 0x56, 0x78, - // 3 path challenge frames (type byte and payload) - 0x0f, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, - 0x0f, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, - 0x0f, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, + // 3 path response frames (IETF_PATH_RESPONSE byte and payload) + 0x1b, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x1b, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x1b, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, // Padding 0x00, 0x00, 0x00, 0x00, 0x00 }; @@ -8503,7 +9992,7 @@ 0x07, }; - unsigned char packet99[] = { + unsigned char packet47[] = { // type (short header, 4 byte packet number) 0x43, // connection_id @@ -8514,6 +10003,18 @@ // frame type 0x07, }; + + unsigned char packet99[] = { + // type (short header, 4 byte packet number) + 0x43, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + + // frame type (IETF_PING frame) + 0x01, + }; // clang-format on std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames)); @@ -8522,6 +10023,8 @@ unsigned char* p = packet; if (framer_.transport_version() == QUIC_VERSION_99) { p = packet99; + } else if (framer_.transport_version() > QUIC_VERSION_46) { + p = packet47; } else if (framer_.transport_version() > QUIC_VERSION_43) { p = packet44; } else if (framer_.transport_version() != QUIC_VERSION_35) { @@ -8784,6 +10287,21 @@ 'm', 'n', 'o', 'p', }; + unsigned char packet47[] = { + // type (short header, 4 byte packet number) + 0x43, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + + // redundancy + 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', + 'i', 'j', 'k', 'l', + 'm', 'n', 'o', 'p', + }; + unsigned char packet99[] = { // type (short header, 4 byte packet number) 0x43, @@ -8803,6 +10321,8 @@ unsigned char* p = packet; if (framer_.transport_version() == QUIC_VERSION_99) { p = packet99; + } else if (framer_.transport_version() > QUIC_VERSION_46) { + p = packet47; } else if (framer_.transport_version() > QUIC_VERSION_43) { p = packet44; } else if (framer_.transport_version() != QUIC_VERSION_35) { @@ -8877,6 +10397,25 @@ 'm', 'n', 'o', 'p', }; + unsigned char packet47[] = { + // type (long header with packet type ZERO_RTT_PROTECTED) + 0xD3, + // version tag + 'Q', '.', '1', '0', + // connection_id length + 0x50, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + + // redundancy + 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', + 'i', 'j', 'k', 'l', + 'm', 'n', 'o', 'p', + }; + unsigned char packet99[] = { // type (long header with packet type ZERO_RTT_PROTECTED) 0xD3, @@ -8900,6 +10439,8 @@ unsigned char* p = packet; if (framer_.transport_version() == QUIC_VERSION_99) { p = packet99; + } else if (framer_.transport_version() > QUIC_VERSION_46) { + p = packet47; } else if (framer_.transport_version() > QUIC_VERSION_43) { p = packet44; } else if (framer_.transport_version() != QUIC_VERSION_35) { @@ -8954,10 +10495,10 @@ QuicEncryptedPacket(buffer, encrypted_length, false))); ASSERT_EQ(1u, visitor_.ack_frames_.size()); QuicAckFrame& processed_ack_frame = *visitor_.ack_frames_[0]; - EXPECT_EQ(600u, LargestAcked(processed_ack_frame)); + EXPECT_EQ(QuicPacketNumber(600u), LargestAcked(processed_ack_frame)); ASSERT_EQ(256u, processed_ack_frame.packets.NumPacketsSlow()); - EXPECT_EQ(90u, processed_ack_frame.packets.Min()); - EXPECT_EQ(600u, processed_ack_frame.packets.Max()); + EXPECT_EQ(QuicPacketNumber(90u), processed_ack_frame.packets.Min()); + EXPECT_EQ(QuicPacketNumber(600u), processed_ack_frame.packets.Max()); } TEST_P(QuicFramerTest, AckTruncationSmallPacket) { @@ -8994,10 +10535,10 @@ QuicEncryptedPacket(buffer, encrypted_length, false))); ASSERT_EQ(1u, visitor_.ack_frames_.size()); QuicAckFrame& processed_ack_frame = *visitor_.ack_frames_[0]; - EXPECT_EQ(600u, LargestAcked(processed_ack_frame)); + EXPECT_EQ(QuicPacketNumber(600u), LargestAcked(processed_ack_frame)); ASSERT_EQ(240u, processed_ack_frame.packets.NumPacketsSlow()); - EXPECT_EQ(122u, processed_ack_frame.packets.Min()); - EXPECT_EQ(600u, processed_ack_frame.packets.Max()); + EXPECT_EQ(QuicPacketNumber(122u), processed_ack_frame.packets.Min()); + EXPECT_EQ(QuicPacketNumber(600u), processed_ack_frame.packets.Max()); } TEST_P(QuicFramerTest, CleanTruncation) { @@ -9158,6 +10699,43 @@ 0x9A, 0xBE, }; + unsigned char packet47[] = { + // type (short header, 4 byte packet number) + 0x43, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + + // frame type (stream frame with fin) + 0xFF, + // stream id + 0x01, 0x02, 0x03, 0x04, + // offset + 0x3A, 0x98, 0xFE, 0xDC, + 0x32, 0x10, 0x76, 0x54, + // data length + 0x00, 0x0c, + // data + 'h', 'e', 'l', 'l', + 'o', ' ', 'w', 'o', + 'r', 'l', 'd', '!', + + // frame type (ack frame) + 0x40, + // least packet number awaiting an ack + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xA0, + // largest observed packet number + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBF, + // num missing packets + 0x01, + // missing packet + 0x12, 0x34, 0x56, 0x78, + 0x9A, 0xBE, + }; + unsigned char packet99[] = { // type (short header, 4 byte packet number) 0x43, @@ -9166,8 +10744,8 @@ // packet number 0x12, 0x34, 0x56, 0x78, - // frame type (stream frame with fin, length, and offset bits set) - 0x10 | 0x01 | 0x02 | 0x04, + // frame type (IETF_STREAM frame with fin, length, and offset bits set) + 0x08 | 0x01 | 0x02 | 0x04, // stream id kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04, // offset @@ -9212,6 +10790,9 @@ 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_43) { p = packet44; p_size = QUIC_ARRAYSIZE(packet44); @@ -9411,7 +10992,7 @@ 'r', 'l', 'd', '!', }; - unsigned char packet99[] = { + unsigned char packet47[] = { // type (short header, 4 byte packet number) 0x43, // packet number @@ -9431,11 +11012,34 @@ 'o', ' ', 'w', 'o', 'r', 'l', 'd', '!', }; + + unsigned char packet99[] = { + // type (short header, 4 byte packet number) + 0x43, + // packet number + 0x12, 0x34, 0x56, 0x78, + + // frame type (IETF_STREAM frame with fin, length, and offset bits set) + 0x08 | 0x01 | 0x02 | 0x04, + // stream id + 0x01, 0x02, 0x03, 0x04, + // offset + 0x3A, 0x98, 0xFE, 0xDC, + 0x32, 0x10, 0x76, 0x54, + // data length + 0x00, 0x0c, + // data + 'h', 'e', 'l', 'l', + 'o', ' ', 'w', 'o', + 'r', 'l', 'd', '!', + }; // clang-format on unsigned char* p = packet; if (framer_.transport_version() == QUIC_VERSION_99) { p = packet99; + } else if (framer_.transport_version() > QUIC_VERSION_46) { + p = packet47; } else if (framer_.transport_version() > QUIC_VERSION_43) { p = packet44; } else if (framer_.transport_version() != QUIC_VERSION_35) { @@ -9457,7 +11061,7 @@ iovec.iov_len = data.length(); producer.SaveStreamData( QuicUtils::GetCryptoStreamId(framer_.transport_version()), &iovec, 1, 0, - 0, data.length()); + data.length()); for (size_t offset = 0; offset < 5; ++offset) { if (offset == 0 || offset == 4) { EXPECT_TRUE(framer_.StartsWithChlo( @@ -9486,9 +11090,9 @@ // packet number {"", {0x12, 0x34, 0x9A, 0xBC}}, - // frame type (blocked) + // frame type (IETF_BLOCKED) {"", - {0x08}}, + {0x14}}, // blocked offset {"Can not read blocked offset.", {kVarInt62EightBytes + 0x3a, 0x98, 0xFE, 0xDC, 0x32, 0x10, 0x76, 0x54}}, @@ -9536,8 +11140,8 @@ // packet number 0x12, 0x34, 0x56, 0x78, - // frame type (blocked) - 0x08, + // frame type (IETF_BLOCKED) + 0x14, // Offset kVarInt62EightBytes + 0x3a, 0x98, 0xFE, 0xDC, 0x32, 0x10, 0x76, 0x54 }; @@ -9568,9 +11172,9 @@ // packet number {"", {0x12, 0x34, 0x9A, 0xBC}}, - // frame type (blocked) + // frame type (IETF_STREAM_BLOCKED) {"", - {0x09}}, + {0x15}}, // blocked offset {"Can not read stream blocked stream id.", {kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04}}, @@ -9621,8 +11225,8 @@ // packet number 0x12, 0x34, 0x56, 0x78, - // frame type (blocked) - 0x09, + // frame type (IETF_STREAM_BLOCKED) + 0x15, // Stream ID kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04, // Offset @@ -9655,9 +11259,9 @@ // packet number {"", {0x12, 0x34, 0x9A, 0xBC}}, - // frame type (max stream id) + // frame type (IETF_MAX_STREAM_ID) {"", - {0x06}}, + {0x12}}, // max. stream id {"Can not read MAX_STREAM_ID stream id.", {kVarInt62OneByte + 0x01}}, @@ -9704,8 +11308,8 @@ // packet number 0x12, 0x34, 0x56, 0x78, - // frame type (max stream id frame) - 0x06, + // frame type (IETF_MAX_STREAM_ID frame) + 0x12, // Max stream id kVarInt62OneByte + 0x01 }; @@ -9736,9 +11340,9 @@ // packet number {"", {0x12, 0x34, 0x9A, 0xBC}}, - // frame type (stream id blocked) + // frame type (IETF_STREAM_ID_BLOCKED frame) {"", - {0x0a}}, + {0x16}}, // stream id {"Can not read STREAM_ID_BLOCKED stream id.", {kVarInt62OneByte + 0x01}}, @@ -9785,8 +11389,8 @@ // packet number 0x12, 0x34, 0x56, 0x78, - // frame type (stream id blocked frame) - 0x0a, + // frame type (IETF_STREAM_ID_BLOCKED frame) + 0x16, // Max stream id kVarInt62OneByte + 0x01 }; @@ -9816,9 +11420,9 @@ // packet number {"", {0x12, 0x34, 0x56, 0x78}}, - // frame type (new connection id frame) + // frame type (IETF_NEW_CONNECTION_ID frame) {"", - {0x0b}}, + {0x18}}, // error code {"Unable to read new connection ID frame sequence number.", {kVarInt62OneByte + 0x11}}, @@ -9884,8 +11488,8 @@ // packet number 0x12, 0x34, 0x56, 0x78, - // frame type (new connection id frame) - 0x0b, + // frame type (IETF_NEW_CONNECTION_ID frame) + 0x18, // sequence number kVarInt62OneByte + 0x11, // new connection id length @@ -9922,9 +11526,9 @@ // packet number {"", {0x12, 0x34, 0x56, 0x78}}, - // frame type (new token frame) + // frame type (IETF_NEW_TOKEN frame) {"", - {0x19}}, + {0x07}}, // Length {"Unable to read new token length.", {kVarInt62OneByte + 0x08}}, @@ -9982,8 +11586,8 @@ // packet number 0x12, 0x34, 0x56, 0x78, - // frame type (new token frame) - 0x19, + // frame type (IETF_NEW_TOKEN frame) + 0x07, // Length and token kVarInt62OneByte + 0x08, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 @@ -10015,9 +11619,9 @@ // packet number {"", {0x12, 0x34, 0x9A, 0xBC}}, - // frame type (stop sending) + // frame type (IETF_STOP_SENDING frame) {"", - {0x0c}}, + {0x05}}, // stream id {"Unable to read stop sending stream id.", {kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04}}, @@ -10068,8 +11672,8 @@ // packet number 0x12, 0x34, 0x56, 0x78, - // frame type (stop sending) - 0x0c, + // frame type (IETF_STOP_SENDING frame) + 0x05, // Stream ID kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04, // Application error code @@ -10102,9 +11706,9 @@ // packet number {"", {0x12, 0x34, 0x9A, 0xBC}}, - // frame type (path challenge) + // frame type (IETF_PATH_CHALLENGE) {"", - {0x0e}}, + {0x1a}}, // data {"Can not read path challenge data.", {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}}, @@ -10152,8 +11756,8 @@ // packet number 0x12, 0x34, 0x56, 0x78, - // frame type (path challenge) - 0x0e, + // frame type (IETF_PATH_CHALLENGE) + 0x1a, // Data 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }; @@ -10184,9 +11788,9 @@ // packet number {"", {0x12, 0x34, 0x9A, 0xBC}}, - // frame type (path response) + // frame type (IETF_PATH_RESPONSE) {"", - {0x0f}}, + {0x1b}}, // data {"Can not read path response data.", {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}}, @@ -10234,8 +11838,8 @@ // packet number 0x12, 0x34, 0x56, 0x78, - // frame type (path response) - 0x0f, + // frame type (IETF_PATH_RESPONSE) + 0x1b, // Data 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }; @@ -10978,9 +12582,9 @@ // packet number {"", {0x12, 0x34, 0x56, 0x78}}, - // frame type (retire connection id frame) + // frame type (IETF_RETIRE_CONNECTION_ID frame) {"", - {0x0d}}, + {0x19}}, // Sequence number {"Unable to read retire connection ID frame sequence number.", {kVarInt62TwoBytes + 0x11, 0x22}} @@ -11031,8 +12635,8 @@ // packet number 0x12, 0x34, 0x56, 0x78, - // frame type (retire connection id frame) - 0x0d, + // frame type (IETF_RETIRE_CONNECTION_ID frame) + 0x19, // sequence number kVarInt62TwoBytes + 0x11, 0x22 }; @@ -11046,6 +12650,444 @@ QUIC_ARRAYSIZE(packet99)); } +TEST_P(QuicFramerTest, AckFrameWithInvalidLargestObserved) { + // clang-format off + unsigned char packet[] = { + // public flags (8 byte connection_id) + 0x2C, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x78, 0x56, 0x34, 0x12, + + // frame type (ack frame) + 0x45, + // largest observed + 0x00, 0x00, + // Zero delta time. + 0x00, 0x00, + // first ack block length. + 0x00, 0x00, + // num timestamps. + 0x00 + }; + + unsigned char 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) + 0x45, + // largest observed + 0x00, 0x00, + // Zero delta time. + 0x00, 0x00, + // first ack block length. + 0x00, 0x00, + // num timestamps. + 0x00 + }; + + unsigned char packet44[] = { + // type (short header, 4 byte packet number) + 0x32, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + + // frame type (ack frame) + 0x45, + // largest observed + 0x00, 0x00, + // Zero delta time. + 0x00, 0x00, + // first ack block length. + 0x00, 0x00, + // num timestamps. + 0x00 + }; + + unsigned char packet47[] = { + // type (short header, 4 byte packet number) + 0x43, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + + // frame type (ack frame) + 0x45, + // largest observed + 0x00, 0x00, + // Zero delta time. + 0x00, 0x00, + // first ack block length. + 0x00, 0x00, + // num timestamps. + 0x00 + }; + + unsigned char packet99[] = { + // type (short header, 4 byte packet number) + 0x43, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + + // frame type (IETF_ACK frame) + 0x02, + // Largest acked + kVarInt62OneByte + 0x00, + // Zero delta time. + kVarInt62OneByte + 0x00, + // Ack block count 0 + kVarInt62OneByte + 0x00, + // First ack block length + kVarInt62OneByte + 0x00, + }; + // clang-format on + + 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; + } 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); + if (!GetQuicReloadableFlag(quic_disallow_peer_ack_0) && + framer_.transport_version() != QUIC_VERSION_99) { + EXPECT_TRUE(framer_.ProcessPacket(encrypted)); + return; + } + EXPECT_FALSE(framer_.ProcessPacket(encrypted)); + EXPECT_EQ(framer_.detailed_error(), "Largest acked is 0."); +} + +TEST_P(QuicFramerTest, FirstAckBlockJustUnderFlow) { + // clang-format off + unsigned char packet[] = { + // public flags (8 byte connection_id) + 0x2C, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x78, 0x56, 0x34, 0x12, + + // frame type (ack frame) + 0x45, + // largest observed + 0x02, 0x00, + // Zero delta time. + 0x00, 0x00, + // first ack block length. + 0x03, 0x00, + // num timestamps. + 0x00 + }; + + unsigned char 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) + 0x45, + // largest observed + 0x00, 0x02, + // Zero delta time. + 0x00, 0x00, + // first ack block length. + 0x00, 0x03, + // num timestamps. + 0x00 + }; + + unsigned char packet44[] = { + // type (short header, 4 byte packet number) + 0x32, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + + // frame type (ack frame) + 0x45, + // largest observed + 0x00, 0x02, + // Zero delta time. + 0x00, 0x00, + // first ack block length. + 0x00, 0x03, + // num timestamps. + 0x00 + }; + + unsigned char packet47[] = { + // type (short header, 4 byte packet number) + 0x43, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + + // frame type (ack frame) + 0x45, + // largest observed + 0x00, 0x02, + // Zero delta time. + 0x00, 0x00, + // first ack block length. + 0x00, 0x03, + // num timestamps. + 0x00 + }; + + unsigned char packet99[] = { + // type (short header, 4 byte packet number) + 0x43, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + + // frame type (IETF_ACK frame) + 0x02, + // Largest acked + kVarInt62OneByte + 0x02, + // Zero delta time. + kVarInt62OneByte + 0x00, + // Ack block count 0 + kVarInt62OneByte + 0x00, + // First ack block length + kVarInt62OneByte + 0x02, + }; + // clang-format on + + 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_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); + if (!GetQuicReloadableFlag(quic_disallow_peer_ack_0) && + framer_.transport_version() != QUIC_VERSION_99) { + EXPECT_TRUE(framer_.ProcessPacket(encrypted)); + return; + } + EXPECT_FALSE(framer_.ProcessPacket(encrypted)); + EXPECT_EQ(framer_.detailed_error(), + "Underflow with first ack block length 3 largest acked is 2."); +} + +TEST_P(QuicFramerTest, ThirdAckBlockJustUnderflow) { + // clang-format off + unsigned char packet[] = { + // public flags (8 byte connection_id) + 0x2C, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x78, 0x56, 0x34, 0x12, + + // frame type (ack frame) + 0x60, + // largest observed + 0x0A, + // Zero delta time. + 0x00, 0x00, + // Num of ack blocks + 0x02, + // first ack block length. + 0x02, + // gap to next block + 0x01, + // ack block length + 0x01, + // gap to next block + 0x01, + // ack block length + 0x06, + // num timestamps. + 0x00 + }; + + unsigned char 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) + 0x60, + // largest observed + 0x0A, + // Zero delta time. + 0x00, 0x00, + // Num of ack blocks + 0x02, + // first ack block length. + 0x02, + // gap to next block + 0x01, + // ack block length + 0x01, + // gap to next block + 0x01, + // ack block length + 0x06, + // num timestamps. + 0x00 + }; + + unsigned char packet44[] = { + // type (short header, 4 byte packet number) + 0x32, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + + // frame type (ack frame) + 0x60, + // largest observed + 0x0A, + // Zero delta time. + 0x00, 0x00, + // Num of ack blocks + 0x02, + // first ack block length. + 0x02, + // gap to next block + 0x01, + // ack block length + 0x01, + // gap to next block + 0x01, + // ack block length + 0x06, + // num timestamps. + 0x00 + }; + + unsigned char packet47[] = { + // type (short header, 4 byte packet number) + 0x43, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + + // frame type (ack frame) + 0x60, + // largest observed + 0x0A, + // Zero delta time. + 0x00, 0x00, + // Num of ack blocks + 0x02, + // first ack block length. + 0x02, + // gap to next block + 0x01, + // ack block length + 0x01, + // gap to next block + 0x01, + // ack block length + 0x06, + // num timestamps. + 0x00 + }; + + unsigned char packet99[] = { + // type (short header, 4 byte packet number) + 0x43, + // connection_id + 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, + // packet number + 0x12, 0x34, 0x56, 0x78, + + // frame type (IETF_ACK frame) + 0x02, + // Largest acked + kVarInt62OneByte + 0x0A, + // Zero delta time. + kVarInt62OneByte + 0x00, + // Ack block count 2 + kVarInt62OneByte + 0x02, + // First ack block length + kVarInt62OneByte + 0x01, + // gap to next block length + kVarInt62OneByte + 0x00, + // ack block length + kVarInt62OneByte + 0x00, + // gap to next block length + kVarInt62OneByte + 0x00, + // ack block length + kVarInt62OneByte + 0x05, + }; + // clang-format on + + 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_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); + if (!GetQuicReloadableFlag(quic_disallow_peer_ack_0) && + framer_.transport_version() != QUIC_VERSION_99) { + EXPECT_TRUE(framer_.ProcessPacket(encrypted)); + return; + } + EXPECT_FALSE(framer_.ProcessPacket(encrypted)); + if (framer_.transport_version() == QUIC_VERSION_99) { + EXPECT_EQ(framer_.detailed_error(), + "Underflow with ack block length 6 latest ack block end is 5."); + } else { + EXPECT_EQ(framer_.detailed_error(), + "Underflow with ack block length 6, end of block is 6."); + } +} + } // namespace } // namespace test } // namespace quic
diff --git a/quic/core/quic_ietf_framer_test.cc b/quic/core/quic_ietf_framer_test.cc index 2e10b61..d35800a 100644 --- a/quic/core/quic_ietf_framer_test.cc +++ b/quic/core/quic_ietf_framer_test.cc
@@ -623,6 +623,39 @@ } } +TEST_F(QuicIetfFramerTest, CryptoFrame) { + SimpleDataProducer data_producer; + framer_.set_data_producer(&data_producer); + char packet_buffer[kNormalPacketBufferSize]; + + QuicStringPiece frame_data("This is a CRYPTO frame."); + + QuicStreamOffset offsets[] = {kOffset8, kOffset4, kOffset2, kOffset1, + kOffset0}; + for (QuicStreamOffset offset : offsets) { + QuicCryptoFrame frame(ENCRYPTION_NONE, offset, frame_data.length()); + data_producer.SaveCryptoData(ENCRYPTION_NONE, offset, frame_data); + + QuicDataWriter writer(QUIC_ARRAYSIZE(packet_buffer), packet_buffer, + NETWORK_BYTE_ORDER); + + // Write the frame. + EXPECT_TRUE(QuicFramerPeer::AppendCryptoFrame(&framer_, frame, &writer)); + EXPECT_NE(0u, writer.length()); + // Read it back. + QuicDataReader reader(packet_buffer, writer.length(), NETWORK_BYTE_ORDER); + QuicCryptoFrame read_frame; + EXPECT_TRUE( + QuicFramerPeer::ProcessCryptoFrame(&framer_, &reader, &read_frame)); + + // Check that the frames match: + QuicStringPiece read_data(read_frame.data_buffer, read_frame.data_length); + EXPECT_EQ(read_frame.data_length, frame.data_length); + EXPECT_EQ(read_frame.offset, frame.offset); + EXPECT_EQ(read_data, frame_data); + } +} + TEST_F(QuicIetfFramerTest, ConnectionCloseEmptyString) { char packet_buffer[kNormalPacketBufferSize]; @@ -695,35 +728,187 @@ // Testing for the IETF ACK framer. // clang-format off struct ack_frame ack_frame_variants[] = { - { 90000, false, 0, 0, 0, {{1000, 2001}}, IETF_ACK }, - { 0, false, 0, 0, 0, {{1000, 2001}}, IETF_ACK }, - { 1, false, 0, 0, 0, {{1, 2}, {5, 6}}, IETF_ACK }, - { 63, false, 0, 0, 0, {{1, 2}, {5, 6}}, IETF_ACK }, - { 64, false, 0, 0, 0, {{1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 10}, {11, 12}}, - IETF_ACK}, - { 10000, false, 0, 0, 0, {{1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 10}, {11, 12}}, - IETF_ACK}, - { 100000000, false, 0, 0, 0, - {{1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 10}, {11, 12}}, - IETF_ACK}, - { 0, false, 0, 0, 0, {{1, 65}}, IETF_ACK }, - { 9223372036854775807, false, 0, 0, 0, {{1, 11}, {74, 138}}, IETF_ACK }, - // This ack is for packets 60 & 125. There are 64 packets in the gap. - // The encoded value is gap_size - 1, or 63. Crosses a VarInt62 encoding - // boundary... - { 1, false, 0, 0, 0, {{60, 61}, {125, 126}}, IETF_ACK }, - { 2, false, 0, 0, 0, {{ 1, 65}, {129, 130}}, IETF_ACK }, - { 3, false, 0, 0, 0, {{ 1, 65}, {129, 195}}, IETF_ACK }, - { 4, false, 0, 0, 0, {{ 1, 65}, {129, 194}}, IETF_ACK }, - { 5, false, 0, 0, 0, {{ 1, 65}, {129, 193}}, IETF_ACK }, - { 6, false, 0, 0, 0, {{ 1, 65}, {129, 192}}, IETF_ACK }, - // declare some ack_ecn frames to try. - { 6, false, 100, 200, 300, {{ 1, 65}, {129, 192}}, IETF_ACK }, - { 6, true, 100, 200, 300, {{ 1, 65}, {129, 192}}, IETF_ACK_ECN }, - { 6, true, 100, 0, 0, {{ 1, 65}, {129, 192}}, IETF_ACK_ECN }, - { 6, true, 0, 200, 0, {{ 1, 65}, {129, 192}}, IETF_ACK_ECN }, - { 6, true, 0, 0, 300, {{ 1, 65}, {129, 192}}, IETF_ACK_ECN }, - { 6, true, 0, 0, 0, {{ 1, 65}, {129, 192}}, IETF_ACK }, + {90000, + false, + 0, + 0, + 0, + {{QuicPacketNumber(1000), QuicPacketNumber(2001)}}, + IETF_ACK}, + {0, + false, + 0, + 0, + 0, + {{QuicPacketNumber(1000), QuicPacketNumber(2001)}}, + IETF_ACK}, + {1, + false, + 0, + 0, + 0, + {{QuicPacketNumber(1), QuicPacketNumber(2)}, + {QuicPacketNumber(5), QuicPacketNumber(6)}}, + IETF_ACK}, + {63, + false, + 0, + 0, + 0, + {{QuicPacketNumber(1), QuicPacketNumber(2)}, + {QuicPacketNumber(5), QuicPacketNumber(6)}}, + IETF_ACK}, + {64, + false, + 0, + 0, + 0, + {{QuicPacketNumber(1), QuicPacketNumber(2)}, + {QuicPacketNumber(3), QuicPacketNumber(4)}, + {QuicPacketNumber(5), QuicPacketNumber(6)}, + {QuicPacketNumber(7), QuicPacketNumber(8)}, + {QuicPacketNumber(9), QuicPacketNumber(10)}, + {QuicPacketNumber(11), QuicPacketNumber(12)}}, + IETF_ACK}, + {10000, + false, + 0, + 0, + 0, + {{QuicPacketNumber(1), QuicPacketNumber(2)}, + {QuicPacketNumber(3), QuicPacketNumber(4)}, + {QuicPacketNumber(5), QuicPacketNumber(6)}, + {QuicPacketNumber(7), QuicPacketNumber(8)}, + {QuicPacketNumber(9), QuicPacketNumber(10)}, + {QuicPacketNumber(11), QuicPacketNumber(12)}}, + IETF_ACK}, + {100000000, + false, + 0, + 0, + 0, + {{QuicPacketNumber(1), QuicPacketNumber(2)}, + {QuicPacketNumber(3), QuicPacketNumber(4)}, + {QuicPacketNumber(5), QuicPacketNumber(6)}, + {QuicPacketNumber(7), QuicPacketNumber(8)}, + {QuicPacketNumber(9), QuicPacketNumber(10)}, + {QuicPacketNumber(11), QuicPacketNumber(12)}}, + IETF_ACK}, + {0, + false, + 0, + 0, + 0, + {{QuicPacketNumber(1), QuicPacketNumber(65)}}, + IETF_ACK}, + {9223372036854775807, + false, + 0, + 0, + 0, + {{QuicPacketNumber(1), QuicPacketNumber(11)}, + {QuicPacketNumber(74), QuicPacketNumber(138)}}, + IETF_ACK}, + // This ack is for packets 60 & 125. There are 64 packets in the gap. + // The encoded value is gap_size - 1, or 63. Crosses a VarInt62 encoding + // boundary... + {1, + false, + 0, + 0, + 0, + {{QuicPacketNumber(60), QuicPacketNumber(61)}, + {QuicPacketNumber(125), QuicPacketNumber(126)}}, + IETF_ACK}, + {2, + false, + 0, + 0, + 0, + {{QuicPacketNumber(1), QuicPacketNumber(65)}, + {QuicPacketNumber(129), QuicPacketNumber(130)}}, + IETF_ACK}, + {3, + false, + 0, + 0, + 0, + {{QuicPacketNumber(1), QuicPacketNumber(65)}, + {QuicPacketNumber(129), QuicPacketNumber(195)}}, + IETF_ACK}, + {4, + false, + 0, + 0, + 0, + {{QuicPacketNumber(1), QuicPacketNumber(65)}, + {QuicPacketNumber(129), QuicPacketNumber(194)}}, + IETF_ACK}, + {5, + false, + 0, + 0, + 0, + {{QuicPacketNumber(1), QuicPacketNumber(65)}, + {QuicPacketNumber(129), QuicPacketNumber(193)}}, + IETF_ACK}, + {6, + false, + 0, + 0, + 0, + {{QuicPacketNumber(1), QuicPacketNumber(65)}, + {QuicPacketNumber(129), QuicPacketNumber(192)}}, + IETF_ACK}, + // declare some ack_ecn frames to try. + {6, + false, + 100, + 200, + 300, + {{QuicPacketNumber(1), QuicPacketNumber(65)}, + {QuicPacketNumber(129), QuicPacketNumber(192)}}, + IETF_ACK}, + {6, + true, + 100, + 200, + 300, + {{QuicPacketNumber(1), QuicPacketNumber(65)}, + {QuicPacketNumber(129), QuicPacketNumber(192)}}, + IETF_ACK_ECN}, + {6, + true, + 100, + 0, + 0, + {{QuicPacketNumber(1), QuicPacketNumber(65)}, + {QuicPacketNumber(129), QuicPacketNumber(192)}}, + IETF_ACK_ECN}, + {6, + true, + 0, + 200, + 0, + {{QuicPacketNumber(1), QuicPacketNumber(65)}, + {QuicPacketNumber(129), QuicPacketNumber(192)}}, + IETF_ACK_ECN}, + {6, + true, + 0, + 0, + 300, + {{QuicPacketNumber(1), QuicPacketNumber(65)}, + {QuicPacketNumber(129), QuicPacketNumber(192)}}, + IETF_ACK_ECN}, + {6, + true, + 0, + 0, + 0, + {{QuicPacketNumber(1), QuicPacketNumber(65)}, + {QuicPacketNumber(129), QuicPacketNumber(192)}}, + IETF_ACK}, }; // clang-format on @@ -749,7 +934,7 @@ NETWORK_BYTE_ORDER); QuicAckFrame transmit_frame; - transmit_frame.largest_acked = 1; + transmit_frame.largest_acked = QuicPacketNumber(1); transmit_frame.ack_delay_time = QuicTime::Delta::FromMicroseconds(0); size_t expected_size = @@ -759,7 +944,7 @@ &framer_, transmit_frame, &writer)); uint8_t packet[] = { - 0x1a, // type + 0x02, // type, IETF_ACK 0x01, // largest_acked, 0x00, // delay 0x00, // count of additional ack blocks
diff --git a/quic/core/quic_lru_cache.h b/quic/core/quic_lru_cache.h index 12e140b..b8c78c6 100644 --- a/quic/core/quic_lru_cache.h +++ b/quic/core/quic_lru_cache.h
@@ -10,7 +10,6 @@ #include "net/third_party/quiche/src/quic/platform/api/quic_containers.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_lru_cache.h" namespace quic { @@ -18,13 +17,12 @@ // This cache CANNOT be shared by multiple threads (even with locks) because // Value* returned by Lookup() can be invalid if the entry is evicted by other // threads. -// TODO(vasilvv): rename this class when quic_new_lru_cache flag is deprecated. template <class K, class V> -class QuicLRUCacheNew { +class QuicLRUCache { public: - explicit QuicLRUCacheNew(size_t capacity) : capacity_(capacity) {} - QuicLRUCacheNew(const QuicLRUCacheNew&) = delete; - QuicLRUCacheNew& operator=(const QuicLRUCacheNew&) = delete; + explicit QuicLRUCache(size_t capacity) : capacity_(capacity) {} + QuicLRUCache(const QuicLRUCache&) = delete; + QuicLRUCache& operator=(const QuicLRUCache&) = delete; // Inserts one unit of |key|, |value| pair to the cache. Cache takes ownership // of inserted |value|. @@ -45,7 +43,6 @@ // value is guaranteed to be valid until Insert or Clear. // Else return nullptr. V* Lookup(const K& key) { - QUIC_RELOADABLE_FLAG_COUNT(quic_new_lru_cache); auto it = cache_.find(key); if (it == cache_.end()) { return nullptr; @@ -72,63 +69,6 @@ const size_t capacity_; }; -// TODO(vasilvv): remove this class when quic_new_lru_cache flag is deprecated. -template <class K, class V> -class QuicLRUCache { - public: - explicit QuicLRUCache(size_t capacity) - : QuicLRUCache(capacity, GetQuicReloadableFlag(quic_new_lru_cache)) {} - QuicLRUCache(size_t capacity, bool use_new) - : new_(capacity), old_(capacity), use_new_(use_new) {} - QuicLRUCache(const QuicLRUCache&) = delete; - QuicLRUCache& operator=(const QuicLRUCache&) = delete; - - void Insert(const K& key, std::unique_ptr<V> value) { - if (use_new_) { - new_.Insert(key, std::move(value)); - } else { - old_.Insert(key, std::move(value)); - } - } - - V* Lookup(const K& key) { - if (use_new_) { - return new_.Lookup(key); - } else { - return old_.Lookup(key); - } - } - - void Clear() { - if (use_new_) { - new_.Clear(); - } else { - old_.Clear(); - } - } - - size_t MaxSize() const { - if (use_new_) { - return new_.MaxSize(); - } else { - return old_.MaxSize(); - } - } - - size_t Size() const { - if (use_new_) { - return new_.Size(); - } else { - return old_.Size(); - } - } - - private: - QuicLRUCacheNew<K, V> new_; - QuicLRUCacheOld<K, V> old_; - bool use_new_; -}; - } // namespace quic #endif // QUICHE_QUIC_CORE_QUIC_LRU_CACHE_H_
diff --git a/quic/core/quic_lru_cache_test.cc b/quic/core/quic_lru_cache_test.cc index c335d5b..92f788b 100644 --- a/quic/core/quic_lru_cache_test.cc +++ b/quic/core/quic_lru_cache_test.cc
@@ -16,12 +16,8 @@ uint32_t value; }; -class QuicLRUCacheTest : public QuicTestWithParam<bool> {}; - -INSTANTIATE_TEST_CASE_P(QuicLRUCacheTests, QuicLRUCacheTest, testing::Bool()); - -TEST_P(QuicLRUCacheTest, InsertAndLookup) { - QuicLRUCache<int, CachedItem> cache(5, GetParam()); +TEST(QuicLRUCacheTest, InsertAndLookup) { + QuicLRUCache<int, CachedItem> cache(5); EXPECT_EQ(nullptr, cache.Lookup(1)); EXPECT_EQ(0u, cache.Size()); EXPECT_EQ(5u, cache.MaxSize()); @@ -48,8 +44,8 @@ EXPECT_EQ(0u, cache.Size()); } -TEST_P(QuicLRUCacheTest, Eviction) { - QuicLRUCache<int, CachedItem> cache(3, GetParam()); +TEST(QuicLRUCacheTest, Eviction) { + QuicLRUCache<int, CachedItem> cache(3); for (size_t i = 1; i <= 4; ++i) { std::unique_ptr<CachedItem> item(new CachedItem(10 + i));
diff --git a/quic/core/quic_packet_creator.cc b/quic/core/quic_packet_creator.cc index 7f48c74..cc4f50e 100644 --- a/quic/core/quic_packet_creator.cc +++ b/quic/core/quic_packet_creator.cc
@@ -49,7 +49,12 @@ connection_id_length_(PACKET_8BYTE_CONNECTION_ID), packet_size_(0), connection_id_(connection_id), - packet_(0, PACKET_1BYTE_PACKET_NUMBER, nullptr, 0, false, false), + packet_(QuicPacketNumber(), + PACKET_1BYTE_PACKET_NUMBER, + nullptr, + 0, + false, + false), long_header_type_(HANDSHAKE), pending_padding_bytes_(0), needs_full_padding_(false), @@ -120,11 +125,11 @@ } DCHECK_LE(least_packet_awaited_by_peer, packet_.packet_number + 1); - const QuicPacketNumber current_delta = + const uint64_t current_delta = packet_.packet_number + 1 - least_packet_awaited_by_peer; const uint64_t delta = std::max(current_delta, max_packets_in_flight); packet_.packet_number_length = QuicFramer::GetMinPacketNumberLength( - framer_->transport_version(), delta * 4); + framer_->transport_version(), QuicPacketNumber(delta * 4)); } bool QuicPacketCreator::ConsumeData(QuicStreamId id, @@ -334,14 +339,14 @@ packet_.has_stop_waiting = false; packet_.has_crypto_handshake = NOT_HANDSHAKE; packet_.num_padding_bytes = 0; - packet_.original_packet_number = kInvalidPacketNumber; + packet_.original_packet_number.Clear(); if (!can_set_transmission_type_ || ShouldSetTransmissionTypeForNextFrame()) { packet_.transmission_type = NOT_RETRANSMISSION; } packet_.encrypted_buffer = nullptr; packet_.encrypted_length = 0; DCHECK(packet_.retransmittable_frames.empty()); - packet_.largest_acked = kInvalidPacketNumber; + packet_.largest_acked.Clear(); needs_full_padding_ = false; } @@ -655,8 +660,8 @@ // TODO(b/74062209): Make this a public method of framer? SerializedPacket QuicPacketCreator::NoPacket() { - return SerializedPacket(0, PACKET_1BYTE_PACKET_NUMBER, nullptr, 0, false, - false); + return SerializedPacket(QuicPacketNumber(), PACKET_1BYTE_PACKET_NUMBER, + nullptr, 0, false, false); } QuicConnectionIdLength QuicPacketCreator::GetDestinationConnectionIdLength() @@ -699,7 +704,12 @@ } else { header->nonce = nullptr; } - header->packet_number = ++packet_.packet_number; + if (!packet_.packet_number.IsInitialized()) { + packet_.packet_number = framer_->first_sending_packet_number(); + } else { + ++packet_.packet_number; + } + header->packet_number = packet_.packet_number; header->packet_number_length = GetPacketNumberLength(); if (!HasIetfLongHeader()) { return;
diff --git a/quic/core/quic_packet_creator_test.cc b/quic/core/quic_packet_creator_test.cc index 0ea9b13..5dd4abb 100644 --- a/quic/core/quic_packet_creator_test.cc +++ b/quic/core/quic_packet_creator_test.cc
@@ -91,8 +91,7 @@ // Save data before data is consumed. QuicByteCount data_length = total_length - iov_offset; if (data_length > 0) { - producer_->SaveStreamData(id, iov, iov_count, iov_offset, offset, - data_length); + producer_->SaveStreamData(id, iov, iov_count, iov_offset, data_length); } return QuicPacketCreator::ConsumeData(id, data_length, iov_offset, offset, fin, needs_full_padding, @@ -228,9 +227,10 @@ int num_padding_bytes, EncryptionLevel encryption_level, QuicPacketNumberLength packet_number_length) { - return QuicPendingRetransmission( - 1u, NOT_RETRANSMISSION, retransmittable_frames, has_crypto_handshake, - num_padding_bytes, encryption_level, packet_number_length); + return QuicPendingRetransmission(QuicPacketNumber(1u), NOT_RETRANSMISSION, + retransmittable_frames, + has_crypto_handshake, num_padding_bytes, + encryption_level, packet_number_length); } bool IsDefaultTestConfiguration() { @@ -269,7 +269,7 @@ for (int i = ENCRYPTION_NONE; i < NUM_ENCRYPTION_LEVELS; ++i) { EncryptionLevel level = static_cast<EncryptionLevel>(i); creator_.set_encryption_level(level); - frames_.push_back(QuicFrame(new QuicAckFrame())); + frames_.push_back(QuicFrame(new QuicAckFrame(InitAckFrame(1)))); frames_.push_back(QuicFrame(QuicStreamFrame( QuicUtils::GetCryptoStreamId(client_framer_.transport_version()), false, 0u, QuicStringPiece()))); @@ -290,21 +290,11 @@ EXPECT_CALL(framer_visitor_, OnPacketHeader(_)); EXPECT_CALL(framer_visitor_, OnAckFrameStart(_, _)) .WillOnce(Return(true)); - // This test includes an ack frame with largest_acked == 0 and - // the size of the first ack-block == 1 (serialized as - // 0). This is an invalid format for pre-version99, valid - // for version 99. - if (client_framer_.transport_version() != QUIC_VERSION_99) { - // pre-version 99; ensure that the error is gracefully - // handled. - EXPECT_CALL(framer_visitor_, OnAckRange(1, 1)).WillOnce(Return(true)); - EXPECT_CALL(framer_visitor_, OnAckFrameEnd(1)).WillOnce(Return(true)); - } else { - // version 99; ensure that the correct packet is signalled - // properly. - EXPECT_CALL(framer_visitor_, OnAckRange(0, 1)).WillOnce(Return(true)); - EXPECT_CALL(framer_visitor_, OnAckFrameEnd(0)).WillOnce(Return(true)); - } + EXPECT_CALL(framer_visitor_, + OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2))) + .WillOnce(Return(true)); + EXPECT_CALL(framer_visitor_, OnAckFrameEnd(QuicPacketNumber(1))) + .WillOnce(Return(true)); EXPECT_CALL(framer_visitor_, OnStreamFrame(_)); EXPECT_CALL(framer_visitor_, OnStreamFrame(_)); EXPECT_CALL(framer_visitor_, OnPacketComplete()); @@ -394,7 +384,7 @@ MakeIOVector("fake handshake message data", &iov_); producer_.SaveStreamData( QuicUtils::GetCryptoStreamId(client_framer_.transport_version()), &iov_, - 1u, 0u, 0u, iov_.iov_len); + 1u, 0u, iov_.iov_len); QuicPacketCreatorPeer::CreateStreamFrame( &creator_, QuicUtils::GetCryptoStreamId(client_framer_.transport_version()), @@ -417,7 +407,7 @@ MakeIOVector("fake message data", &iov_); producer_.SaveStreamData( QuicUtils::GetCryptoStreamId(client_framer_.transport_version()), &iov_, - 1u, 0u, 0u, iov_.iov_len); + 1u, 0u, iov_.iov_len); QuicPacketCreatorPeer::CreateStreamFrame( &creator_, QuicUtils::GetCryptoStreamId(client_framer_.transport_version()), @@ -483,7 +473,7 @@ SimpleDataProducer producer; producer.SaveStreamData( QuicUtils::GetCryptoStreamId(client_framer_.transport_version()), &iov_, - 1u, 0u, 0u, iov_.iov_len); + 1u, 0u, iov_.iov_len); QuicPacketCreatorPeer::framer(&creator_)->set_data_producer(&producer); QuicPacketCreatorPeer::CreateStreamFrame( &creator_, @@ -523,8 +513,8 @@ frames.push_back(QuicFrame(&frame)); SerializedPacket serialized = SerializeAllFrames(frames); EXPECT_EQ(ENCRYPTION_NONE, serialized.encryption_level); - ASSERT_EQ(1u, serialized.packet_number); - ASSERT_EQ(1u, creator_.packet_number()); + ASSERT_EQ(QuicPacketNumber(1u), serialized.packet_number); + ASSERT_EQ(QuicPacketNumber(1u), creator_.packet_number()); InSequence s; EXPECT_CALL(framer_visitor_, OnPacket()); @@ -1026,28 +1016,33 @@ } QuicPacketCreatorPeer::SetPacketNumber(&creator_, 64); - creator_.UpdatePacketNumberLength(2, 10000 / kDefaultMaxPacketSize); + creator_.UpdatePacketNumberLength(QuicPacketNumber(2), + 10000 / kDefaultMaxPacketSize); EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER, QuicPacketCreatorPeer::GetPacketNumberLength(&creator_)); QuicPacketCreatorPeer::SetPacketNumber(&creator_, 64 * 256); - creator_.UpdatePacketNumberLength(2, 10000 / kDefaultMaxPacketSize); + creator_.UpdatePacketNumberLength(QuicPacketNumber(2), + 10000 / kDefaultMaxPacketSize); EXPECT_EQ(PACKET_2BYTE_PACKET_NUMBER, QuicPacketCreatorPeer::GetPacketNumberLength(&creator_)); QuicPacketCreatorPeer::SetPacketNumber(&creator_, 64 * 256 * 256); - creator_.UpdatePacketNumberLength(2, 10000 / kDefaultMaxPacketSize); + creator_.UpdatePacketNumberLength(QuicPacketNumber(2), + 10000 / kDefaultMaxPacketSize); EXPECT_EQ(PACKET_4BYTE_PACKET_NUMBER, QuicPacketCreatorPeer::GetPacketNumberLength(&creator_)); QuicPacketCreatorPeer::SetPacketNumber(&creator_, UINT64_C(64) * 256 * 256 * 256 * 256); - creator_.UpdatePacketNumberLength(2, 10000 / kDefaultMaxPacketSize); + creator_.UpdatePacketNumberLength(QuicPacketNumber(2), + 10000 / kDefaultMaxPacketSize); EXPECT_EQ(PACKET_6BYTE_PACKET_NUMBER, QuicPacketCreatorPeer::GetPacketNumberLength(&creator_)); } TEST_P(QuicPacketCreatorTest, UpdatePacketSequenceNumberLengthCwnd) { + QuicPacketCreatorPeer::SetPacketNumber(&creator_, 1); if (GetParam().version.transport_version > QUIC_VERSION_43 && GetParam().version.transport_version != QUIC_VERSION_99) { EXPECT_EQ(PACKET_4BYTE_PACKET_NUMBER, @@ -1058,21 +1053,24 @@ QuicPacketCreatorPeer::GetPacketNumberLength(&creator_)); } - creator_.UpdatePacketNumberLength(1, 10000 / kDefaultMaxPacketSize); + creator_.UpdatePacketNumberLength(QuicPacketNumber(1), + 10000 / kDefaultMaxPacketSize); EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER, QuicPacketCreatorPeer::GetPacketNumberLength(&creator_)); - creator_.UpdatePacketNumberLength(1, 10000 * 256 / kDefaultMaxPacketSize); + creator_.UpdatePacketNumberLength(QuicPacketNumber(1), + 10000 * 256 / kDefaultMaxPacketSize); EXPECT_EQ(PACKET_2BYTE_PACKET_NUMBER, QuicPacketCreatorPeer::GetPacketNumberLength(&creator_)); - creator_.UpdatePacketNumberLength(1, + creator_.UpdatePacketNumberLength(QuicPacketNumber(1), 10000 * 256 * 256 / kDefaultMaxPacketSize); EXPECT_EQ(PACKET_4BYTE_PACKET_NUMBER, QuicPacketCreatorPeer::GetPacketNumberLength(&creator_)); creator_.UpdatePacketNumberLength( - 1, UINT64_C(1000) * 256 * 256 * 256 * 256 / kDefaultMaxPacketSize); + QuicPacketNumber(1), + UINT64_C(1000) * 256 * 256 * 256 * 256 / kDefaultMaxPacketSize); EXPECT_EQ(PACKET_6BYTE_PACKET_NUMBER, QuicPacketCreatorPeer::GetPacketNumberLength(&creator_)); } @@ -1191,7 +1189,7 @@ ASSERT_EQ(1u, retransmittable.size()); EXPECT_EQ(STREAM_FRAME, retransmittable[0].type); EXPECT_TRUE(serialized_packet_.has_ack); - EXPECT_EQ(10u, serialized_packet_.largest_acked); + EXPECT_EQ(QuicPacketNumber(10u), serialized_packet_.largest_acked); DeleteSerializedPacket(); EXPECT_FALSE(creator_.HasPendingFrames()); @@ -1217,7 +1215,7 @@ MakeIOVector("test", &iov_); producer_.SaveStreamData( QuicUtils::GetHeadersStreamId(client_framer_.transport_version()), &iov_, - 1u, 0u, 0u, iov_.iov_len); + 1u, 0u, iov_.iov_len); EXPECT_CALL(delegate_, OnSerializedPacket(_)) .WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket)); size_t num_bytes_consumed; @@ -1357,7 +1355,7 @@ MakeIOVector("fake handshake message data", &iov_); producer_.SaveStreamData( QuicUtils::GetCryptoStreamId(client_framer_.transport_version()), &iov_, - 1u, 0u, 0u, iov_.iov_len); + 1u, 0u, iov_.iov_len); QuicPacketCreatorPeer::CreateStreamFrame( &creator_, QuicUtils::GetCryptoStreamId(client_framer_.transport_version()), @@ -1476,7 +1474,9 @@ // failure. While this test is not applicable to versions other than version 99, // it should still work. Hence, it is not made version-specific. TEST_P(QuicPacketCreatorTest, IetfAckGapErrorRegression) { - QuicAckFrame ack_frame = InitAckFrame({{60, 61}, {125, 126}}); + QuicAckFrame ack_frame = + InitAckFrame({{QuicPacketNumber(60), QuicPacketNumber(61)}, + {QuicPacketNumber(125), QuicPacketNumber(126)}}); frames_.push_back(QuicFrame(&ack_frame)); SerializeAllFrames(frames_); } @@ -1563,7 +1563,7 @@ creator_.set_can_set_transmission_type(true); creator_.SetTransmissionType(NOT_RETRANSMISSION); - QuicAckFrame temp_ack_frame; + QuicAckFrame temp_ack_frame = InitAckFrame(1); QuicFrame ack_frame(&temp_ack_frame); ASSERT_FALSE(QuicUtils::IsRetransmittableFrame(ack_frame.type));
diff --git a/quic/core/quic_packet_generator.cc b/quic/core/quic_packet_generator.cc index 5c1c330..12978a3 100644 --- a/quic/core/quic_packet_generator.cc +++ b/quic/core/quic_packet_generator.cc
@@ -26,7 +26,8 @@ flusher_attached_(false), should_send_ack_(false), should_send_stop_waiting_(false), - random_generator_(random_generator) {} + random_generator_(random_generator), + fully_pad_crypto_handshake_packets_(true) {} QuicPacketGenerator::~QuicPacketGenerator() { DeleteFrames(&queued_control_frames_); @@ -93,10 +94,13 @@ HAS_RETRANSMITTABLE_DATA, has_handshake ? IS_HANDSHAKE : NOT_HANDSHAKE)) { QuicFrame frame; + bool needs_full_padding = + has_handshake && fully_pad_crypto_handshake_packets_; + if (!packet_creator_.ConsumeData(id, write_length, total_bytes_consumed, offset + total_bytes_consumed, fin, - has_handshake, next_transmission_type_, - &frame)) { + needs_full_padding, + next_transmission_type_, &frame)) { // The creator is always flushed if there's not enough room for a new // stream frame before ConsumeData, so ConsumeData should always succeed. QUIC_BUG << "Failed to ConsumeData, stream:" << id;
diff --git a/quic/core/quic_packet_generator.h b/quic/core/quic_packet_generator.h index 18e102c..572d170 100644 --- a/quic/core/quic_packet_generator.h +++ b/quic/core/quic_packet_generator.h
@@ -221,6 +221,14 @@ bool should_send_ack() const { return should_send_ack_; } + void set_fully_pad_crypto_hadshake_packets(bool new_value) { + fully_pad_crypto_handshake_packets_ = new_value; + } + + bool fully_pad_crypto_handshake_packets() const { + return fully_pad_crypto_handshake_packets_; + } + private: friend class test::QuicPacketGeneratorPeer; @@ -265,6 +273,9 @@ QuicStopWaitingFrame pending_stop_waiting_frame_; QuicRandom* random_generator_; + + // Whether crypto handshake packets should be fully padded. + bool fully_pad_crypto_handshake_packets_; }; } // namespace quic
diff --git a/quic/core/quic_packet_generator_test.cc b/quic/core/quic_packet_generator_test.cc index b824a5c..b85a4f7 100644 --- a/quic/core/quic_packet_generator_test.cc +++ b/quic/core/quic_packet_generator_test.cc
@@ -121,7 +121,7 @@ bool fin) { // Save data before data is consumed. if (total_length > 0) { - producer_->SaveStreamData(id, iov, iov_count, 0, offset, total_length); + producer_->SaveStreamData(id, iov, iov_count, 0, total_length); } return QuicPacketGenerator::ConsumeDataFastPath(id, total_length, offset, fin, 0); @@ -135,7 +135,7 @@ StreamSendingState state) { // Save data before data is consumed. if (total_length > 0) { - producer_->SaveStreamData(id, iov, iov_count, 0, offset, total_length); + producer_->SaveStreamData(id, iov, iov_count, 0, total_length); } return QuicPacketGenerator::ConsumeData(id, total_length, offset, state); } @@ -154,7 +154,8 @@ &random_generator_, &delegate_, &producer_), - creator_(QuicPacketGeneratorPeer::GetPacketCreator(&generator_)) { + creator_(QuicPacketGeneratorPeer::GetPacketCreator(&generator_)), + ack_frame_(InitAckFrame(1)) { EXPECT_CALL(delegate_, GetPacketBuffer()).WillRepeatedly(Return(nullptr)); creator_->SetEncrypter( ENCRYPTION_FORWARD_SECURE, @@ -470,6 +471,35 @@ EXPECT_EQ(kDefaultMaxPacketSize, packets_[0].encrypted_length); } +// Test the behavior of ConsumeData when the data is for the crypto handshake +// stream, but padding is disabled. +TEST_F(QuicPacketGeneratorTest, ConsumeData_Handshake_PaddingDisabled) { + generator_.set_fully_pad_crypto_hadshake_packets(false); + + delegate_.SetCanWriteAnything(); + + EXPECT_CALL(delegate_, OnSerializedPacket(_)) + .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket)); + MakeIOVector("foo", &iov_); + QuicConsumedData consumed = generator_.ConsumeData( + QuicUtils::GetCryptoStreamId(framer_.transport_version()), &iov_, 1u, + iov_.iov_len, 0, NO_FIN); + EXPECT_EQ(3u, consumed.bytes_consumed); + EXPECT_FALSE(generator_.HasQueuedFrames()); + EXPECT_FALSE(generator_.HasRetransmittableFrames()); + + PacketContents contents; + contents.num_stream_frames = 1; + contents.num_padding_frames = 0; + CheckPacketContains(contents, 0); + + ASSERT_EQ(1u, packets_.size()); + + // Packet is not fully padded, but we want to future packets to be larger. + ASSERT_EQ(kDefaultMaxPacketSize, generator_.GetCurrentMaxPacketLength()); + EXPECT_EQ(27, packets_[0].encrypted_length); +} + TEST_F(QuicPacketGeneratorTest, ConsumeData_EmptyData) { EXPECT_QUIC_BUG(generator_.ConsumeData(QuicUtils::GetHeadersStreamId( framer_.transport_version()), @@ -829,7 +859,7 @@ QuicConsumedData consumed = generator_.ConsumeData(stream1_id, &iov_, 1u, iov_.iov_len, 0, NO_FIN); EXPECT_EQ(data_len, consumed.bytes_consumed); - ASSERT_EQ(0, creator_->BytesFree()) + ASSERT_EQ(0u, creator_->BytesFree()) << "Test setup failed: Please increase data_len to " << data_len + creator_->BytesFree() << " bytes."; @@ -846,9 +876,9 @@ EXPECT_EQ(data_len, consumed.bytes_consumed); // Ensure the packet is successfully created. - ASSERT_EQ(1, packets_.size()); + ASSERT_EQ(1u, packets_.size()); ASSERT_TRUE(packets_[0].encrypted_buffer); - ASSERT_EQ(1, packets_[0].retransmittable_frames.size()); + ASSERT_EQ(1u, packets_[0].retransmittable_frames.size()); EXPECT_EQ(stream1_id, packets_[0].retransmittable_frames[0].stream_frame.stream_id); if (GetQuicReloadableFlag(quic_set_transmission_type_for_next_frame)) {
diff --git a/quic/core/quic_packet_number.cc b/quic/core/quic_packet_number.cc new file mode 100644 index 0000000..f0a497f --- /dev/null +++ b/quic/core/quic_packet_number.cc
@@ -0,0 +1,132 @@ +// 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/quic_packet_number.h" + +namespace quic { + +QuicPacketNumber::QuicPacketNumber() + : packet_number_(UninitializedPacketNumber()) {} + +QuicPacketNumber::QuicPacketNumber(uint64_t packet_number) + : packet_number_(packet_number) { + DCHECK_NE(UninitializedPacketNumber(), packet_number) + << "Use default constructor for uninitialized packet number"; +} + +void QuicPacketNumber::Clear() { + packet_number_ = UninitializedPacketNumber(); +} + +uint64_t QuicPacketNumber::Hash() const { + DCHECK(IsInitialized()); + return packet_number_; +} + +uint64_t QuicPacketNumber::ToUint64() const { + DCHECK(IsInitialized()); + return packet_number_; +} + +bool QuicPacketNumber::IsInitialized() const { + return packet_number_ != UninitializedPacketNumber(); +} + +QuicPacketNumber& QuicPacketNumber::operator++() { +#ifndef NDEBUG + DCHECK(IsInitialized()); + if (GetQuicRestartFlag(quic_uint64max_uninitialized_pn)) { + DCHECK_LT(ToUint64(), std::numeric_limits<uint64_t>::max() - 1); + } else { + DCHECK_LT(ToUint64(), std::numeric_limits<uint64_t>::max()); + } +#endif + packet_number_++; + return *this; +} + +QuicPacketNumber QuicPacketNumber::operator++(int) { +#ifndef NDEBUG + DCHECK(IsInitialized()); + if (GetQuicRestartFlag(quic_uint64max_uninitialized_pn)) { + DCHECK_LT(ToUint64(), std::numeric_limits<uint64_t>::max() - 1); + } else { + DCHECK_LT(ToUint64(), std::numeric_limits<uint64_t>::max()); + } +#endif + QuicPacketNumber previous(*this); + packet_number_++; + return previous; +} + +QuicPacketNumber& QuicPacketNumber::operator--() { +#ifndef NDEBUG + DCHECK(IsInitialized()); + if (GetQuicRestartFlag(quic_uint64max_uninitialized_pn)) { + DCHECK_GE(ToUint64(), 1); + } else { + DCHECK_GT(ToUint64(), 1); + } +#endif + packet_number_--; + return *this; +} + +QuicPacketNumber QuicPacketNumber::operator--(int) { +#ifndef NDEBUG + DCHECK(IsInitialized()); + if (GetQuicRestartFlag(quic_uint64max_uninitialized_pn)) { + DCHECK_GE(ToUint64(), 1); + } else { + DCHECK_GT(ToUint64(), 1); + } +#endif + QuicPacketNumber previous(*this); + packet_number_--; + return previous; +} + +QuicPacketNumber& QuicPacketNumber::operator+=(uint64_t delta) { +#ifndef NDEBUG + DCHECK(IsInitialized()); + if (GetQuicRestartFlag(quic_uint64max_uninitialized_pn)) { + DCHECK_GT(std::numeric_limits<uint64_t>::max() - ToUint64(), delta); + } else { + DCHECK_GE(std::numeric_limits<uint64_t>::max() - ToUint64(), delta); + } +#endif + packet_number_ += delta; + return *this; +} + +QuicPacketNumber& QuicPacketNumber::operator-=(uint64_t delta) { +#ifndef NDEBUG + DCHECK(IsInitialized()); + if (GetQuicRestartFlag(quic_uint64max_uninitialized_pn)) { + DCHECK_GE(ToUint64(), delta); + } else { + DCHECK_GT(ToUint64(), delta); + } +#endif + packet_number_ -= delta; + return *this; +} + +std::ostream& operator<<(std::ostream& os, const QuicPacketNumber& p) { + if (p.IsInitialized()) { + os << p.packet_number_; + } else { + os << "uninitialized"; + } + return os; +} + +// static +uint64_t QuicPacketNumber::UninitializedPacketNumber() { + return GetQuicRestartFlag(quic_uint64max_uninitialized_pn) + ? std::numeric_limits<uint64_t>::max() + : 0; +} + +} // namespace quic
diff --git a/quic/core/quic_packet_number.h b/quic/core/quic_packet_number.h new file mode 100644 index 0000000..6797e3c --- /dev/null +++ b/quic/core/quic_packet_number.h
@@ -0,0 +1,154 @@ +// 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_QUIC_PACKET_NUMBER_H_ +#define QUICHE_QUIC_CORE_QUIC_PACKET_NUMBER_H_ + +#include <limits> +#include <ostream> + +#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_logging.h" +#include "net/third_party/quiche/src/quic/platform/api/quic_string.h" +#include "net/third_party/quiche/src/quic/platform/api/quic_uint128.h" + +namespace quic { + +// QuicPacketNumber can either initialized or uninitialized. An initialized +// packet number is simply an ordinal number. A sentinel value is used to +// represent an uninitialized packet number. +class QUIC_EXPORT_PRIVATE QuicPacketNumber { + public: + // Construct an uninitialized packet number. + QuicPacketNumber(); + // Construct a packet number from uint64_t. |packet_number| cannot equal the + // sentinel value. + explicit QuicPacketNumber(uint64_t packet_number); + + // Packet number becomes uninitialized after calling this function. + void Clear(); + + // REQUIRES: IsInitialized() == true. + uint64_t Hash() const; + + // Converts packet number to uint64_t. + // REQUIRES: IsInitialized() == true. + uint64_t ToUint64() const; + + // Returns true if packet number is considered initialized. + bool IsInitialized() const; + + // REQUIRES: IsInitialized() == true && ToUint64() < + // numeric_limits<uint64_t>::max() - 1. + QuicPacketNumber& operator++(); + QuicPacketNumber operator++(int); + // REQUIRES: IsInitialized() == true && ToUint64() >= 1. + QuicPacketNumber& operator--(); + QuicPacketNumber operator--(int); + + // REQUIRES: IsInitialized() == true && numeric_limits<uint64_t>::max() - + // ToUint64() > |delta|. + QuicPacketNumber& operator+=(uint64_t delta); + // REQUIRES: IsInitialized() == true && ToUint64() >= |delta|. + QuicPacketNumber& operator-=(uint64_t delta); + + QUIC_EXPORT_PRIVATE friend std::ostream& operator<<( + std::ostream& os, + const QuicPacketNumber& p); + + private: + // All following operators REQUIRE operands.Initialized() == true. + friend inline bool operator==(QuicPacketNumber lhs, QuicPacketNumber rhs); + friend inline bool operator!=(QuicPacketNumber lhs, QuicPacketNumber rhs); + friend inline bool operator<(QuicPacketNumber lhs, QuicPacketNumber rhs); + friend inline bool operator<=(QuicPacketNumber lhs, QuicPacketNumber rhs); + friend inline bool operator>(QuicPacketNumber lhs, QuicPacketNumber rhs); + friend inline bool operator>=(QuicPacketNumber lhs, QuicPacketNumber rhs); + + // REQUIRES: numeric_limits<uint64_t>::max() - lhs.ToUint64() > |delta|. + friend inline QuicPacketNumber operator+(QuicPacketNumber lhs, + uint64_t delta); + // REQUIRES: lhs.ToUint64() >= |delta|. + friend inline QuicPacketNumber operator-(QuicPacketNumber lhs, + uint64_t delta); + // REQUIRES: lhs >= rhs. + friend inline uint64_t operator-(QuicPacketNumber lhs, QuicPacketNumber rhs); + + // The sentinel value representing an uninitialized packet number. + static uint64_t UninitializedPacketNumber(); + + uint64_t packet_number_; +}; + +class QuicPacketNumberHash { + public: + uint64_t operator()(QuicPacketNumber packet_number) const noexcept { + return packet_number.Hash(); + } +}; + +inline bool operator==(QuicPacketNumber lhs, QuicPacketNumber rhs) { + DCHECK(lhs.IsInitialized() && rhs.IsInitialized()) << lhs << " vs. " << rhs; + return lhs.packet_number_ == rhs.packet_number_; +} + +inline bool operator!=(QuicPacketNumber lhs, QuicPacketNumber rhs) { + DCHECK(lhs.IsInitialized() && rhs.IsInitialized()) << lhs << " vs. " << rhs; + return lhs.packet_number_ != rhs.packet_number_; +} + +inline bool operator<(QuicPacketNumber lhs, QuicPacketNumber rhs) { + DCHECK(lhs.IsInitialized() && rhs.IsInitialized()) << lhs << " vs. " << rhs; + return lhs.packet_number_ < rhs.packet_number_; +} + +inline bool operator<=(QuicPacketNumber lhs, QuicPacketNumber rhs) { + DCHECK(lhs.IsInitialized() && rhs.IsInitialized()) << lhs << " vs. " << rhs; + return lhs.packet_number_ <= rhs.packet_number_; +} + +inline bool operator>(QuicPacketNumber lhs, QuicPacketNumber rhs) { + DCHECK(lhs.IsInitialized() && rhs.IsInitialized()) << lhs << " vs. " << rhs; + return lhs.packet_number_ > rhs.packet_number_; +} + +inline bool operator>=(QuicPacketNumber lhs, QuicPacketNumber rhs) { + DCHECK(lhs.IsInitialized() && rhs.IsInitialized()) << lhs << " vs. " << rhs; + return lhs.packet_number_ >= rhs.packet_number_; +} + +inline QuicPacketNumber operator+(QuicPacketNumber lhs, uint64_t delta) { +#ifndef NDEBUG + DCHECK(lhs.IsInitialized()); + if (GetQuicRestartFlag(quic_uint64max_uninitialized_pn)) { + DCHECK_GT(std::numeric_limits<uint64_t>::max() - lhs.ToUint64(), delta); + } else { + DCHECK_GE(std::numeric_limits<uint64_t>::max() - lhs.ToUint64(), delta); + } +#endif + return QuicPacketNumber(lhs.packet_number_ + delta); +} + +inline QuicPacketNumber operator-(QuicPacketNumber lhs, uint64_t delta) { +#ifndef NDEBUG + DCHECK(lhs.IsInitialized()); + if (GetQuicRestartFlag(quic_uint64max_uninitialized_pn)) { + DCHECK_GE(lhs.ToUint64(), delta); + } else { + DCHECK_GT(lhs.ToUint64(), delta); + } +#endif + return QuicPacketNumber(lhs.packet_number_ - delta); +} + +inline uint64_t operator-(QuicPacketNumber lhs, QuicPacketNumber rhs) { + DCHECK(lhs.IsInitialized() && rhs.IsInitialized() && lhs >= rhs) + << lhs << " vs. " << rhs; + return lhs.packet_number_ - rhs.packet_number_; +} + +} // namespace quic + +#endif // QUICHE_QUIC_CORE_QUIC_PACKET_NUMBER_H_
diff --git a/quic/core/quic_packet_number_test.cc b/quic/core/quic_packet_number_test.cc new file mode 100644 index 0000000..5e32b8c --- /dev/null +++ b/quic/core/quic_packet_number_test.cc
@@ -0,0 +1,83 @@ +// 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/quic_packet_number.h" + +#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h" +#include "net/third_party/quiche/src/quic/platform/api/quic_test.h" + +namespace quic { + +namespace test { + +namespace { + +TEST(QuicPacketNumberTest, BasicTest) { + QuicPacketNumber num; + EXPECT_FALSE(num.IsInitialized()); + + QuicPacketNumber num2(10); + EXPECT_TRUE(num2.IsInitialized()); + EXPECT_EQ(10u, num2.ToUint64()); + EXPECT_EQ(10u, num2.Hash()); + num2.Clear(); + EXPECT_FALSE(num2.IsInitialized()); + + if (!GetQuicRestartFlag(quic_uint64max_uninitialized_pn)) { + QuicPacketNumber num3(std::numeric_limits<uint64_t>::max()); + EXPECT_TRUE(num3.IsInitialized()); + EXPECT_EQ(std::numeric_limits<uint64_t>::max(), num3.ToUint64()); + EXPECT_EQ(std::numeric_limits<uint64_t>::max(), num3.Hash()); + num3.Clear(); + EXPECT_FALSE(num3.IsInitialized()); + return; + } + + QuicPacketNumber num4(0); + EXPECT_TRUE(num4.IsInitialized()); + EXPECT_EQ(0u, num4.ToUint64()); + EXPECT_EQ(0u, num4.Hash()); + num4.Clear(); + EXPECT_FALSE(num4.IsInitialized()); +} + +TEST(QuicPacketNumberTest, Operators) { + QuicPacketNumber num(100); + EXPECT_EQ(QuicPacketNumber(100), num++); + EXPECT_EQ(QuicPacketNumber(101), num); + EXPECT_EQ(QuicPacketNumber(101), num--); + EXPECT_EQ(QuicPacketNumber(100), num); + + EXPECT_EQ(QuicPacketNumber(101), ++num); + EXPECT_EQ(QuicPacketNumber(100), --num); + + if (!GetQuicRestartFlag(quic_uint64max_uninitialized_pn)) { + QuicPacketNumber num2(std::numeric_limits<uint64_t>::max()); + EXPECT_EQ(QuicPacketNumber(std::numeric_limits<uint64_t>::max()), num2--); + EXPECT_EQ(QuicPacketNumber(std::numeric_limits<uint64_t>::max() - 1), num2); + EXPECT_EQ(QuicPacketNumber(std::numeric_limits<uint64_t>::max() - 2), + --num2); + + EXPECT_EQ(QuicPacketNumber(std::numeric_limits<uint64_t>::max() - 2), + num2++); + EXPECT_EQ(QuicPacketNumber(std::numeric_limits<uint64_t>::max() - 1), num2); + EXPECT_EQ(QuicPacketNumber(std::numeric_limits<uint64_t>::max()), ++num2); + return; + } + + QuicPacketNumber num3(0); + EXPECT_EQ(QuicPacketNumber(0), num3++); + EXPECT_EQ(QuicPacketNumber(1), num3); + EXPECT_EQ(QuicPacketNumber(2), ++num3); + + EXPECT_EQ(QuicPacketNumber(2), num3--); + EXPECT_EQ(QuicPacketNumber(1), num3); + EXPECT_EQ(QuicPacketNumber(0), --num3); +} + +} // namespace + +} // namespace test + +} // namespace quic
diff --git a/quic/core/quic_packets.cc b/quic/core/quic_packets.cc index ca0ad6d..5e3ba76 100644 --- a/quic/core/quic_packets.cc +++ b/quic/core/quic_packets.cc
@@ -33,8 +33,8 @@ // Long header. return kPacketHeaderTypeSize + kConnectionIdLengthSize + destination_connection_id_length + source_connection_id_length + - (version == QUIC_VERSION_99 ? packet_number_length - : PACKET_4BYTE_PACKET_NUMBER) + + (version > QUIC_VERSION_46 ? packet_number_length + : PACKET_4BYTE_PACKET_NUMBER) + kQuicVersionSize + (include_diversification_nonce ? kDiversificationNonceSize : 0); } @@ -74,10 +74,8 @@ version_flag(false), has_possible_stateless_reset_token(false), packet_number_length(PACKET_4BYTE_PACKET_NUMBER), - version( - ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED)), + version(UnsupportedQuicVersion()), nonce(nullptr), - packet_number(kInvalidPacketNumber), form(GOOGLE_QUIC_PACKET), long_packet_type(INITIAL), possible_stateless_reset_token(0) {} @@ -294,9 +292,7 @@ encryption_level(ENCRYPTION_NONE), has_ack(has_ack), has_stop_waiting(has_stop_waiting), - transmission_type(NOT_RETRANSMISSION), - original_packet_number(kInvalidPacketNumber), - largest_acked(kInvalidPacketNumber) {} + transmission_type(NOT_RETRANSMISSION) {} SerializedPacket::SerializedPacket(const SerializedPacket& other) = default; @@ -327,7 +323,7 @@ } serialized_packet->encrypted_buffer = nullptr; serialized_packet->encrypted_length = 0; - serialized_packet->largest_acked = kInvalidPacketNumber; + serialized_packet->largest_acked.Clear(); } char* CopyBuffer(const SerializedPacket& packet) {
diff --git a/quic/core/quic_received_packet_manager.cc b/quic/core/quic_received_packet_manager.cc index d33c756..8189ff8 100644 --- a/quic/core/quic_received_packet_manager.cc +++ b/quic/core/quic_received_packet_manager.cc
@@ -25,8 +25,7 @@ } // namespace QuicReceivedPacketManager::QuicReceivedPacketManager(QuicConnectionStats* stats) - : peer_least_packet_awaiting_ack_(0), - ack_frame_updated_(false), + : ack_frame_updated_(false), max_ack_ranges_(0), time_largest_observed_(QuicTime::Zero()), save_timestamps_(false), @@ -44,7 +43,8 @@ } ack_frame_updated_ = true; - if (LargestAcked(ack_frame_) > packet_number) { + if (LargestAcked(ack_frame_).IsInitialized() && + LargestAcked(ack_frame_) > packet_number) { // Record how out of order stats. ++stats_->packets_reordered; stats_->max_sequence_reordering = @@ -55,7 +55,8 @@ stats_->max_time_reordering_us = std::max(stats_->max_time_reordering_us, reordering_time_us); } - if (packet_number > LargestAcked(ack_frame_)) { + if (!LargestAcked(ack_frame_).IsInitialized() || + packet_number > LargestAcked(ack_frame_)) { ack_frame_.largest_acked = packet_number; time_largest_observed_ = receipt_time; } @@ -77,7 +78,8 @@ } bool QuicReceivedPacketManager::IsMissing(QuicPacketNumber packet_number) { - return packet_number < LargestAcked(ack_frame_) && + return LargestAcked(ack_frame_).IsInitialized() && + packet_number < LargestAcked(ack_frame_) && !ack_frame_.packets.Contains(packet_number); } @@ -120,9 +122,14 @@ void QuicReceivedPacketManager::DontWaitForPacketsBefore( QuicPacketNumber least_unacked) { + if (!least_unacked.IsInitialized()) { + return; + } // ValidateAck() should fail if peer_least_packet_awaiting_ack shrinks. - DCHECK_LE(peer_least_packet_awaiting_ack_, least_unacked); - if (least_unacked > peer_least_packet_awaiting_ack_) { + DCHECK(!peer_least_packet_awaiting_ack_.IsInitialized() || + peer_least_packet_awaiting_ack_ <= least_unacked); + if (!peer_least_packet_awaiting_ack_.IsInitialized() || + least_unacked > peer_least_packet_awaiting_ack_) { peer_least_packet_awaiting_ack_ = least_unacked; bool packets_updated = ack_frame_.packets.RemoveUpTo(least_unacked); if (packets_updated) { @@ -132,14 +139,23 @@ } } DCHECK(ack_frame_.packets.Empty() || + !peer_least_packet_awaiting_ack_.IsInitialized() || ack_frame_.packets.Min() >= peer_least_packet_awaiting_ack_); } bool QuicReceivedPacketManager::HasMissingPackets() const { - return ack_frame_.packets.NumIntervals() > 1 || - (!ack_frame_.packets.Empty() && - ack_frame_.packets.Min() > - std::max(QuicPacketNumber(1), peer_least_packet_awaiting_ack_)); + if (ack_frame_.packets.Empty()) { + return false; + } + if (ack_frame_.packets.NumIntervals() > 1) { + return true; + } + // TODO(fayang): Fix this as this check assumes first sent packet by peer + // is 1. + return ack_frame_.packets.Min() > + (peer_least_packet_awaiting_ack_.IsInitialized() + ? peer_least_packet_awaiting_ack_ + : QuicPacketNumber(1)); } bool QuicReceivedPacketManager::HasNewMissingPackets() const {
diff --git a/quic/core/quic_received_packet_manager_test.cc b/quic/core/quic_received_packet_manager_test.cc index 7d8c811..b8264a5 100644 --- a/quic/core/quic_received_packet_manager_test.cc +++ b/quic/core/quic_received_packet_manager_test.cc
@@ -42,14 +42,13 @@ received_manager_.set_save_timestamps(true); } - void RecordPacketReceipt(QuicPacketNumber packet_number) { + void RecordPacketReceipt(uint64_t packet_number) { RecordPacketReceipt(packet_number, QuicTime::Zero()); } - void RecordPacketReceipt(QuicPacketNumber packet_number, - QuicTime receipt_time) { + void RecordPacketReceipt(uint64_t packet_number, QuicTime receipt_time) { QuicPacketHeader header; - header.packet_number = packet_number; + header.packet_number = QuicPacketNumber(packet_number); received_manager_.RecordPacketReceived(header, receipt_time); } @@ -63,20 +62,20 @@ TEST_P(QuicReceivedPacketManagerTest, DontWaitForPacketsBefore) { QuicPacketHeader header; - header.packet_number = 2u; + header.packet_number = QuicPacketNumber(2u); received_manager_.RecordPacketReceived(header, QuicTime::Zero()); - header.packet_number = 7u; + header.packet_number = QuicPacketNumber(7u); received_manager_.RecordPacketReceived(header, QuicTime::Zero()); - EXPECT_TRUE(received_manager_.IsAwaitingPacket(3u)); - EXPECT_TRUE(received_manager_.IsAwaitingPacket(6u)); - received_manager_.DontWaitForPacketsBefore(4); - EXPECT_FALSE(received_manager_.IsAwaitingPacket(3u)); - EXPECT_TRUE(received_manager_.IsAwaitingPacket(6u)); + EXPECT_TRUE(received_manager_.IsAwaitingPacket(QuicPacketNumber(3u))); + EXPECT_TRUE(received_manager_.IsAwaitingPacket(QuicPacketNumber(6u))); + received_manager_.DontWaitForPacketsBefore(QuicPacketNumber(4)); + EXPECT_FALSE(received_manager_.IsAwaitingPacket(QuicPacketNumber(3u))); + EXPECT_TRUE(received_manager_.IsAwaitingPacket(QuicPacketNumber(6u))); } TEST_P(QuicReceivedPacketManagerTest, GetUpdatedAckFrame) { QuicPacketHeader header; - header.packet_number = 2u; + header.packet_number = QuicPacketNumber(2u); QuicTime two_ms = QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(2); EXPECT_FALSE(received_manager_.ack_frame_updated()); received_manager_.RecordPacketReceived(header, two_ms); @@ -99,11 +98,11 @@ // And received packet times won't have change. EXPECT_EQ(1u, ack.ack_frame->received_packet_times.size()); - header.packet_number = 999u; + header.packet_number = QuicPacketNumber(999u); received_manager_.RecordPacketReceived(header, two_ms); - header.packet_number = 4u; + header.packet_number = QuicPacketNumber(4u); received_manager_.RecordPacketReceived(header, two_ms); - header.packet_number = 1000u; + header.packet_number = QuicPacketNumber(1000u); received_manager_.RecordPacketReceived(header, two_ms); EXPECT_TRUE(received_manager_.ack_frame_updated()); ack = received_manager_.GetUpdatedAckFrame(two_ms); @@ -134,11 +133,16 @@ EXPECT_TRUE(received_manager_.ack_frame_updated()); received_manager_.GetUpdatedAckFrame(QuicTime::Zero()); EXPECT_GE(10u, received_manager_.ack_frame().packets.NumIntervals()); - EXPECT_EQ(1u + 2 * i, received_manager_.ack_frame().packets.Max()); + EXPECT_EQ(QuicPacketNumber(1u + 2 * i), + received_manager_.ack_frame().packets.Max()); for (int j = 0; j < std::min(10, i + 1); ++j) { - EXPECT_TRUE( - received_manager_.ack_frame().packets.Contains(1 + (i - j) * 2)); - EXPECT_FALSE(received_manager_.ack_frame().packets.Contains((i - j) * 2)); + ASSERT_GE(i, j); + EXPECT_TRUE(received_manager_.ack_frame().packets.Contains( + QuicPacketNumber(1 + (i - j) * 2))); + if (i > j) { + EXPECT_FALSE(received_manager_.ack_frame().packets.Contains( + QuicPacketNumber((i - j) * 2))); + } } } }
diff --git a/quic/core/quic_sent_packet_manager.cc b/quic/core/quic_sent_packet_manager.cc index 783a78c..4bbe070 100644 --- a/quic/core/quic_sent_packet_manager.cc +++ b/quic/core/quic_sent_packet_manager.cc
@@ -86,7 +86,6 @@ loss_algorithm_(&general_loss_algorithm_), general_loss_algorithm_(loss_type), n_connection_simulation_(false), - first_rto_transmission_(0), consecutive_rto_count_(0), consecutive_tlp_count_(0), consecutive_crypto_retransmission_count_(0), @@ -103,10 +102,8 @@ QuicTime::Delta::FromMilliseconds(kMinRetransmissionTimeMs)), ietf_style_tlp_(false), ietf_style_2x_tlp_(false), - largest_newly_acked_(0), largest_mtu_acked_(0), handshake_confirmed_(false), - largest_packet_peer_knows_is_acked_(0), delayed_ack_time_( QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs)), rtt_updated_(false), @@ -452,7 +449,7 @@ } else { // Clear the recorded first packet sent after loss when version or // encryption changes. - transmission_info->retransmission = kInvalidPacketNumber; + transmission_info->retransmission.Clear(); } } @@ -479,7 +476,7 @@ return; } QuicPacketNumber retransmission = info.retransmission; - while (retransmission != kInvalidPacketNumber) { + while (retransmission.IsInitialized()) { const QuicTransmissionInfo& retransmit_info = unacked_packets_.GetTransmissionInfo(retransmission); retransmission = retransmit_info.retransmission; @@ -529,7 +526,7 @@ return packet_number; } QuicPacketNumber retransmission = transmission_info.retransmission; - while (retransmission != kInvalidPacketNumber) { + while (retransmission.IsInitialized()) { packet_number = retransmission; retransmission = unacked_packets_.GetTransmissionInfo(retransmission).retransmission; @@ -607,12 +604,12 @@ TransmissionType transmission_type, HasRetransmittableData has_retransmittable_data) { QuicPacketNumber packet_number = serialized_packet->packet_number; - DCHECK_LT(0u, packet_number); + DCHECK_LE(FirstSendingPacketNumber(), packet_number); DCHECK(!unacked_packets_.IsUnacked(packet_number)); QUIC_BUG_IF(serialized_packet->encrypted_length == 0) << "Cannot send empty packets."; - if (original_packet_number != kInvalidPacketNumber) { + if (original_packet_number.IsInitialized()) { pending_retransmissions_.erase(original_packet_number); } @@ -758,7 +755,7 @@ } // Abandon non-retransmittable data that's in flight to ensure it doesn't // fill up the congestion window. - bool has_retransmissions = it->retransmission != kInvalidPacketNumber; + bool has_retransmissions = it->retransmission.IsInitialized(); if (session_decides_what_to_write()) { has_retransmissions = it->state != OUTSTANDING; } @@ -1051,21 +1048,23 @@ DCHECK_LE(largest_acked, unacked_packets_.largest_sent_packet()); rtt_updated_ = MaybeUpdateRTT(largest_acked, ack_delay_time, ack_receive_time); - DCHECK_GE(largest_acked, unacked_packets_.largest_acked()); + DCHECK(!unacked_packets_.largest_acked().IsInitialized() || + largest_acked >= unacked_packets_.largest_acked()); last_ack_frame_.ack_delay_time = ack_delay_time; acked_packets_iter_ = last_ack_frame_.packets.rbegin(); } void QuicSentPacketManager::OnAckRange(QuicPacketNumber start, QuicPacketNumber end) { - if (end > last_ack_frame_.largest_acked + 1) { + if (!last_ack_frame_.largest_acked.IsInitialized() || + end > last_ack_frame_.largest_acked + 1) { // Largest acked increases. unacked_packets_.IncreaseLargestAcked(end - 1); last_ack_frame_.largest_acked = end - 1; } // Drop ack ranges which ack packets below least_unacked. QuicPacketNumber least_unacked = unacked_packets_.GetLeastUnacked(); - if (end <= least_unacked) { + if (least_unacked.IsInitialized() && end <= least_unacked) { return; } start = std::max(start, least_unacked); @@ -1079,6 +1078,9 @@ // Check if end is above the current range. If so add newly acked packets // in descending order. packets_acked_.push_back(AckedPacket(acked, 0, QuicTime::Zero())); + if (acked == FirstSendingPacketNumber()) { + break; + } } if (acked_packets_iter_ == last_ack_frame_.packets.rend() || start > acked_packets_iter_->min()) { @@ -1125,9 +1127,13 @@ QUIC_DVLOG(1) << ENDPOINT << "Got an ack for packet " << acked_packet.packet_number; last_ack_frame_.packets.Add(acked_packet.packet_number); - if (info->largest_acked > kInvalidPacketNumber) { - largest_packet_peer_knows_is_acked_ = - std::max(largest_packet_peer_knows_is_acked_, info->largest_acked); + if (info->largest_acked.IsInitialized()) { + if (largest_packet_peer_knows_is_acked_.IsInitialized()) { + largest_packet_peer_knows_is_acked_ = + std::max(largest_packet_peer_knows_is_acked_, info->largest_acked); + } else { + largest_packet_peer_knows_is_acked_ = info->largest_acked; + } } // If data is associated with the most recent transmission of this // packet, then inform the caller.
diff --git a/quic/core/quic_sent_packet_manager.h b/quic/core/quic_sent_packet_manager.h index 7b2501a..aad16e2 100644 --- a/quic/core/quic_sent_packet_manager.h +++ b/quic/core/quic_sent_packet_manager.h
@@ -368,7 +368,9 @@ LOSS_MODE, }; - typedef QuicLinkedHashMap<QuicPacketNumber, TransmissionType> + typedef QuicLinkedHashMap<QuicPacketNumber, + TransmissionType, + QuicPacketNumberHash> PendingRetransmissionMap; // Returns the current retransmission mode.
diff --git a/quic/core/quic_sent_packet_manager_test.cc b/quic/core/quic_sent_packet_manager_test.cc index 865f181..97e1697 100644 --- a/quic/core/quic_sent_packet_manager_test.cc +++ b/quic/core/quic_sent_packet_manager_test.cc
@@ -38,7 +38,8 @@ // Matcher to check that the packet number matches the second argument. MATCHER(PacketNumberEq, "") { - return ::testing::get<0>(arg).packet_number == ::testing::get<1>(arg); + return ::testing::get<0>(arg).packet_number == + QuicPacketNumber(::testing::get<1>(arg)); } class MockDebugDelegate : public QuicSentPacketManager::DebugDelegate { @@ -54,25 +55,26 @@ class QuicSentPacketManagerTest : public QuicTestWithParam<bool> { public: - void RetransmitCryptoPacket(QuicPacketNumber packet_number) { - EXPECT_CALL(*send_algorithm_, - OnPacketSent(_, BytesInFlight(), packet_number, kDefaultLength, - HAS_RETRANSMITTABLE_DATA)); + void RetransmitCryptoPacket(uint64_t packet_number) { + EXPECT_CALL( + *send_algorithm_, + OnPacketSent(_, BytesInFlight(), QuicPacketNumber(packet_number), + kDefaultLength, HAS_RETRANSMITTABLE_DATA)); SerializedPacket packet(CreatePacket(packet_number, false)); packet.retransmittable_frames.push_back( QuicFrame(QuicStreamFrame(1, false, 0, QuicStringPiece()))); packet.has_crypto_handshake = IS_HANDSHAKE; - manager_.OnPacketSent(&packet, 0, clock_.Now(), HANDSHAKE_RETRANSMISSION, - HAS_RETRANSMITTABLE_DATA); + manager_.OnPacketSent(&packet, QuicPacketNumber(), clock_.Now(), + HANDSHAKE_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA); } - void RetransmitDataPacket(QuicPacketNumber packet_number, - TransmissionType type) { - EXPECT_CALL(*send_algorithm_, - OnPacketSent(_, BytesInFlight(), packet_number, kDefaultLength, - HAS_RETRANSMITTABLE_DATA)); + void RetransmitDataPacket(uint64_t packet_number, TransmissionType type) { + EXPECT_CALL( + *send_algorithm_, + OnPacketSent(_, BytesInFlight(), QuicPacketNumber(packet_number), + kDefaultLength, HAS_RETRANSMITTABLE_DATA)); SerializedPacket packet(CreatePacket(packet_number, true)); - manager_.OnPacketSent(&packet, 0, clock_.Now(), type, + manager_.OnPacketSent(&packet, QuicPacketNumber(), clock_.Now(), type, HAS_RETRANSMITTABLE_DATA); } @@ -111,7 +113,7 @@ QuicByteCount BytesInFlight() { return QuicSentPacketManagerPeer::GetBytesInFlight(&manager_); } - void VerifyUnackedPackets(QuicPacketNumber* packets, size_t num_packets) { + void VerifyUnackedPackets(uint64_t* packets, size_t num_packets) { if (num_packets == 0) { EXPECT_TRUE(manager_.unacked_packets().empty()); EXPECT_EQ(0u, QuicSentPacketManagerPeer::GetNumRetransmittablePackets( @@ -120,15 +122,14 @@ } EXPECT_FALSE(manager_.unacked_packets().empty()); - EXPECT_EQ(packets[0], manager_.GetLeastUnacked()); + EXPECT_EQ(QuicPacketNumber(packets[0]), manager_.GetLeastUnacked()); for (size_t i = 0; i < num_packets; ++i) { EXPECT_TRUE(QuicSentPacketManagerPeer::IsUnacked(&manager_, packets[i])) << packets[i]; } } - void VerifyRetransmittablePackets(QuicPacketNumber* packets, - size_t num_packets) { + void VerifyRetransmittablePackets(uint64_t* packets, size_t num_packets) { EXPECT_EQ( num_packets, QuicSentPacketManagerPeer::GetNumRetransmittablePackets(&manager_)); @@ -139,7 +140,7 @@ } } - void ExpectAck(QuicPacketNumber largest_observed) { + void ExpectAck(uint64_t largest_observed) { EXPECT_CALL( *send_algorithm_, // Ensure the AckedPacketVector argument contains largest_observed. @@ -149,15 +150,15 @@ EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); } - void ExpectUpdatedRtt(QuicPacketNumber largest_observed) { + void ExpectUpdatedRtt(uint64_t largest_observed) { EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, IsEmpty(), IsEmpty())); EXPECT_CALL(*network_change_visitor_, OnCongestionChange()); } void ExpectAckAndLoss(bool rtt_updated, - QuicPacketNumber largest_observed, - QuicPacketNumber lost_packet) { + uint64_t largest_observed, + uint64_t lost_packet) { EXPECT_CALL( *send_algorithm_, OnCongestionEvent(rtt_updated, _, _, @@ -168,17 +169,17 @@ // |packets_acked| and |packets_lost| should be in packet number order. void ExpectAcksAndLosses(bool rtt_updated, - QuicPacketNumber* packets_acked, + uint64_t* packets_acked, size_t num_packets_acked, - QuicPacketNumber* packets_lost, + uint64_t* packets_lost, size_t num_packets_lost) { std::vector<QuicPacketNumber> ack_vector; for (size_t i = 0; i < num_packets_acked; ++i) { - ack_vector.push_back(packets_acked[i]); + ack_vector.push_back(QuicPacketNumber(packets_acked[i])); } std::vector<QuicPacketNumber> lost_vector; for (size_t i = 0; i < num_packets_lost; ++i) { - lost_vector.push_back(packets_lost[i]); + lost_vector.push_back(QuicPacketNumber(packets_lost[i])); } EXPECT_CALL(*send_algorithm_, OnCongestionEvent(rtt_updated, _, _, @@ -188,14 +189,14 @@ .Times(AnyNumber()); } - void RetransmitAndSendPacket(QuicPacketNumber old_packet_number, - QuicPacketNumber new_packet_number) { + void RetransmitAndSendPacket(uint64_t old_packet_number, + uint64_t new_packet_number) { RetransmitAndSendPacket(old_packet_number, new_packet_number, TLP_RETRANSMISSION); } - void RetransmitAndSendPacket(QuicPacketNumber old_packet_number, - QuicPacketNumber new_packet_number, + void RetransmitAndSendPacket(uint64_t old_packet_number, + uint64_t new_packet_number, TransmissionType transmission_type) { bool is_lost = false; if (manager_.session_decides_what_to_write()) { @@ -219,38 +220,42 @@ if (!is_lost) { return; } - EXPECT_CALL(*send_algorithm_, - OnPacketSent(_, BytesInFlight(), new_packet_number, - kDefaultLength, HAS_RETRANSMITTABLE_DATA)); + EXPECT_CALL( + *send_algorithm_, + OnPacketSent(_, BytesInFlight(), QuicPacketNumber(new_packet_number), + kDefaultLength, HAS_RETRANSMITTABLE_DATA)); SerializedPacket packet(CreatePacket(new_packet_number, true)); - manager_.OnPacketSent(&packet, 0, clock_.Now(), transmission_type, - HAS_RETRANSMITTABLE_DATA); + manager_.OnPacketSent(&packet, QuicPacketNumber(), clock_.Now(), + transmission_type, HAS_RETRANSMITTABLE_DATA); return; } EXPECT_TRUE(manager_.HasPendingRetransmissions()); QuicPendingRetransmission next_retransmission = manager_.NextPendingRetransmission(); - EXPECT_EQ(old_packet_number, next_retransmission.packet_number); + EXPECT_EQ(QuicPacketNumber(old_packet_number), + next_retransmission.packet_number); EXPECT_EQ(transmission_type, next_retransmission.transmission_type); - EXPECT_CALL(*send_algorithm_, - OnPacketSent(_, BytesInFlight(), new_packet_number, - kDefaultLength, HAS_RETRANSMITTABLE_DATA)); + EXPECT_CALL( + *send_algorithm_, + OnPacketSent(_, BytesInFlight(), QuicPacketNumber(new_packet_number), + kDefaultLength, HAS_RETRANSMITTABLE_DATA)); SerializedPacket packet(CreatePacket(new_packet_number, false)); - manager_.OnPacketSent(&packet, old_packet_number, clock_.Now(), - transmission_type, HAS_RETRANSMITTABLE_DATA); + manager_.OnPacketSent(&packet, QuicPacketNumber(old_packet_number), + clock_.Now(), transmission_type, + HAS_RETRANSMITTABLE_DATA); EXPECT_TRUE(QuicSentPacketManagerPeer::IsRetransmission(&manager_, new_packet_number)); } - SerializedPacket CreateDataPacket(QuicPacketNumber packet_number) { + SerializedPacket CreateDataPacket(uint64_t packet_number) { return CreatePacket(packet_number, true); } - SerializedPacket CreatePacket(QuicPacketNumber packet_number, - bool retransmittable) { - SerializedPacket packet(packet_number, PACKET_4BYTE_PACKET_NUMBER, nullptr, - kDefaultLength, false, false); + SerializedPacket CreatePacket(uint64_t packet_number, bool retransmittable) { + SerializedPacket packet(QuicPacketNumber(packet_number), + PACKET_4BYTE_PACKET_NUMBER, nullptr, kDefaultLength, + false, false); if (retransmittable) { packet.retransmittable_frames.push_back( QuicFrame(QuicStreamFrame(kStreamId, false, 0, QuicStringPiece()))); @@ -258,47 +263,50 @@ return packet; } - void SendDataPacket(QuicPacketNumber packet_number) { + void SendDataPacket(uint64_t packet_number) { EXPECT_CALL(*send_algorithm_, - OnPacketSent(_, BytesInFlight(), packet_number, _, _)); + OnPacketSent(_, BytesInFlight(), + QuicPacketNumber(packet_number), _, _)); SerializedPacket packet(CreateDataPacket(packet_number)); - manager_.OnPacketSent(&packet, 0, clock_.Now(), NOT_RETRANSMISSION, - HAS_RETRANSMITTABLE_DATA); + manager_.OnPacketSent(&packet, QuicPacketNumber(), clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA); } - void SendCryptoPacket(QuicPacketNumber packet_number) { - EXPECT_CALL(*send_algorithm_, - OnPacketSent(_, BytesInFlight(), packet_number, kDefaultLength, - HAS_RETRANSMITTABLE_DATA)); + void SendCryptoPacket(uint64_t packet_number) { + EXPECT_CALL( + *send_algorithm_, + OnPacketSent(_, BytesInFlight(), QuicPacketNumber(packet_number), + kDefaultLength, HAS_RETRANSMITTABLE_DATA)); SerializedPacket packet(CreatePacket(packet_number, false)); packet.retransmittable_frames.push_back( QuicFrame(QuicStreamFrame(1, false, 0, QuicStringPiece()))); packet.has_crypto_handshake = IS_HANDSHAKE; - manager_.OnPacketSent(&packet, 0, clock_.Now(), NOT_RETRANSMISSION, - HAS_RETRANSMITTABLE_DATA); + manager_.OnPacketSent(&packet, QuicPacketNumber(), clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA); if (manager_.session_decides_what_to_write()) { EXPECT_CALL(notifier_, HasUnackedCryptoData()) .WillRepeatedly(Return(true)); } } - void SendAckPacket(QuicPacketNumber packet_number, - QuicPacketNumber largest_acked) { - EXPECT_CALL(*send_algorithm_, - OnPacketSent(_, BytesInFlight(), packet_number, kDefaultLength, - NO_RETRANSMITTABLE_DATA)); + void SendAckPacket(uint64_t packet_number, uint64_t largest_acked) { + EXPECT_CALL( + *send_algorithm_, + OnPacketSent(_, BytesInFlight(), QuicPacketNumber(packet_number), + kDefaultLength, NO_RETRANSMITTABLE_DATA)); SerializedPacket packet(CreatePacket(packet_number, false)); - packet.largest_acked = largest_acked; - manager_.OnPacketSent(&packet, 0, clock_.Now(), NOT_RETRANSMISSION, - NO_RETRANSMITTABLE_DATA); + packet.largest_acked = QuicPacketNumber(largest_acked); + manager_.OnPacketSent(&packet, QuicPacketNumber(), clock_.Now(), + NOT_RETRANSMISSION, NO_RETRANSMITTABLE_DATA); } // Based on QuicConnection's WritePendingRetransmissions. - void RetransmitNextPacket(QuicPacketNumber retransmission_packet_number) { + void RetransmitNextPacket(uint64_t retransmission_packet_number) { EXPECT_TRUE(manager_.HasPendingRetransmissions()); - EXPECT_CALL(*send_algorithm_, - OnPacketSent(_, _, retransmission_packet_number, kDefaultLength, - HAS_RETRANSMITTABLE_DATA)); + EXPECT_CALL( + *send_algorithm_, + OnPacketSent(_, _, QuicPacketNumber(retransmission_packet_number), + kDefaultLength, HAS_RETRANSMITTABLE_DATA)); const QuicPendingRetransmission pending = manager_.NextPendingRetransmission(); SerializedPacket packet(CreatePacket(retransmission_packet_number, false)); @@ -320,9 +328,9 @@ VerifyUnackedPackets(nullptr, 0); SendDataPacket(1); - QuicPacketNumber unacked[] = {1}; + uint64_t unacked[] = {1}; VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked)); - QuicPacketNumber retransmittable[] = {1}; + uint64_t retransmittable[] = {1}; VerifyRetransmittablePackets(retransmittable, QUIC_ARRAYSIZE(retransmittable)); } @@ -332,9 +340,9 @@ RetransmitAndSendPacket(1, 2); EXPECT_TRUE(QuicSentPacketManagerPeer::IsRetransmission(&manager_, 2)); - QuicPacketNumber unacked[] = {1, 2}; + uint64_t unacked[] = {1, 2}; VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked)); - std::vector<QuicPacketNumber> retransmittable; + std::vector<uint64_t> retransmittable; if (manager_.session_decides_what_to_write()) { retransmittable = {1, 2}; } else { @@ -349,14 +357,15 @@ // Ack 2 but not 1. ExpectAck(2); - manager_.OnAckFrameStart(2, QuicTime::Delta::Infinite(), clock_.Now()); - manager_.OnAckRange(2, 3); + manager_.OnAckFrameStart(QuicPacketNumber(2), QuicTime::Delta::Infinite(), + clock_.Now()); + manager_.OnAckRange(QuicPacketNumber(2), QuicPacketNumber(3)); EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now())); if (manager_.session_decides_what_to_write()) { EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false)); } // Packet 1 is unacked, pending, but not retransmittable. - QuicPacketNumber unacked[] = {1}; + uint64_t unacked[] = {1}; VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked)); EXPECT_TRUE(QuicSentPacketManagerPeer::HasPendingPackets(&manager_)); VerifyRetransmittablePackets(nullptr, 0); @@ -379,8 +388,9 @@ } // Ack 1. ExpectAck(1); - manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite(), clock_.Now()); - manager_.OnAckRange(1, 2); + manager_.OnAckFrameStart(QuicPacketNumber(1), QuicTime::Delta::Infinite(), + clock_.Now()); + manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2)); EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now())); // There should no longer be a pending retransmission. @@ -388,7 +398,7 @@ if (manager_.session_decides_what_to_write()) { EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false)); - QuicPacketNumber unacked[] = {2}; + uint64_t unacked[] = {2}; VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked)); // We do not know packet 2 is a spurious retransmission until it gets acked. } else { @@ -418,7 +428,7 @@ // There should no longer be a pending retransmission. EXPECT_FALSE(manager_.HasPendingRetransmissions()); - QuicPacketNumber unacked[] = {1}; + uint64_t unacked[] = {1}; VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked)); VerifyRetransmittablePackets(nullptr, 0); EXPECT_EQ(0u, stats_.packets_spuriously_retransmitted); @@ -432,14 +442,15 @@ // Ack 1 but not 2. ExpectAck(1); - manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite(), clock_.Now()); - manager_.OnAckRange(1, 2); + manager_.OnAckFrameStart(QuicPacketNumber(1), QuicTime::Delta::Infinite(), + clock_.Now()); + manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2)); EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now())); if (manager_.session_decides_what_to_write()) { EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false)); } // 2 remains unacked, but no packets have retransmittable data. - QuicPacketNumber unacked[] = {2}; + uint64_t unacked[] = {2}; VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked)); EXPECT_TRUE(QuicSentPacketManagerPeer::HasPendingPackets(&manager_)); VerifyRetransmittablePackets(nullptr, 0); @@ -447,8 +458,9 @@ // Ack 2 causes 2 be considered as spurious retransmission. EXPECT_CALL(notifier_, OnFrameAcked(_, _)).WillOnce(Return(false)); ExpectAck(2); - manager_.OnAckFrameStart(2, QuicTime::Delta::Infinite(), clock_.Now()); - manager_.OnAckRange(1, 3); + manager_.OnAckFrameStart(QuicPacketNumber(2), QuicTime::Delta::Infinite(), + clock_.Now()); + manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(3)); EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now())); } @@ -463,8 +475,9 @@ // First, ACK packet 1 which makes packet 2 non-retransmittable. ExpectAck(1); - manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite(), clock_.Now()); - manager_.OnAckRange(1, 2); + manager_.OnAckFrameStart(QuicPacketNumber(1), QuicTime::Delta::Infinite(), + clock_.Now()); + manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2)); EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now())); SendDataPacket(3); @@ -474,15 +487,17 @@ // Next, NACK packet 2 three times. ExpectAck(3); - manager_.OnAckFrameStart(3, QuicTime::Delta::Infinite(), clock_.Now()); - manager_.OnAckRange(3, 4); - manager_.OnAckRange(1, 2); + manager_.OnAckFrameStart(QuicPacketNumber(3), QuicTime::Delta::Infinite(), + clock_.Now()); + manager_.OnAckRange(QuicPacketNumber(3), QuicPacketNumber(4)); + manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2)); EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now())); ExpectAck(4); - manager_.OnAckFrameStart(4, QuicTime::Delta::Infinite(), clock_.Now()); - manager_.OnAckRange(3, 5); - manager_.OnAckRange(1, 2); + manager_.OnAckFrameStart(QuicPacketNumber(4), QuicTime::Delta::Infinite(), + clock_.Now()); + manager_.OnAckRange(QuicPacketNumber(3), QuicPacketNumber(5)); + manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2)); EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now())); ExpectAckAndLoss(true, 5, 2); @@ -495,14 +510,15 @@ EXPECT_CALL(notifier_, OnFrameLost(_)).Times(1); } } - manager_.OnAckFrameStart(5, QuicTime::Delta::Infinite(), clock_.Now()); - manager_.OnAckRange(3, 6); - manager_.OnAckRange(1, 2); + manager_.OnAckFrameStart(QuicPacketNumber(5), QuicTime::Delta::Infinite(), + clock_.Now()); + manager_.OnAckRange(QuicPacketNumber(3), QuicPacketNumber(6)); + manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2)); EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now())); if (manager_.session_decides_what_to_write() && GetQuicReloadableFlag(quic_fix_mark_for_loss_retransmission)) { - QuicPacketNumber unacked[] = {2}; + uint64_t unacked[] = {2}; VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked)); } else { // No packets remain unacked. @@ -532,12 +548,13 @@ // send algorithm is not informed that it has been ACK'd. ExpectUpdatedRtt(1); EXPECT_CALL(*send_algorithm_, RevertRetransmissionTimeout()); - manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite(), clock_.Now()); - manager_.OnAckRange(1, 2); + manager_.OnAckFrameStart(QuicPacketNumber(1), QuicTime::Delta::Infinite(), + clock_.Now()); + manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2)); EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now())); // Since 2 was marked for retransmit, when 1 is acked, 2 is kept for RTT. - QuicPacketNumber unacked[] = {2}; + uint64_t unacked[] = {2}; VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked)); EXPECT_FALSE(QuicSentPacketManagerPeer::HasPendingPackets(&manager_)); VerifyRetransmittablePackets(nullptr, 0); @@ -568,8 +585,9 @@ // Ack 1 but not 2 or 3. ExpectAck(1); - manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite(), clock_.Now()); - manager_.OnAckRange(1, 2); + manager_.OnAckFrameStart(QuicPacketNumber(1), QuicTime::Delta::Infinite(), + clock_.Now()); + manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2)); EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now())); if (manager_.session_decides_what_to_write()) { // Frames in packets 2 and 3 are acked. @@ -579,7 +597,7 @@ } // 2 and 3 remain unacked, but no packets have retransmittable data. - QuicPacketNumber unacked[] = {2, 3}; + uint64_t unacked[] = {2, 3}; VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked)); EXPECT_TRUE(QuicSentPacketManagerPeer::HasPendingPackets(&manager_)); VerifyRetransmittablePackets(nullptr, 0); @@ -592,20 +610,22 @@ .WillOnce(Return(false)) .WillRepeatedly(Return(true)); } - QuicPacketNumber acked[] = {3, 4}; + uint64_t acked[] = {3, 4}; ExpectAcksAndLosses(true, acked, QUIC_ARRAYSIZE(acked), nullptr, 0); - manager_.OnAckFrameStart(4, QuicTime::Delta::Infinite(), clock_.Now()); - manager_.OnAckRange(3, 5); - manager_.OnAckRange(1, 2); + manager_.OnAckFrameStart(QuicPacketNumber(4), QuicTime::Delta::Infinite(), + clock_.Now()); + manager_.OnAckRange(QuicPacketNumber(3), QuicPacketNumber(5)); + manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2)); EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now())); - QuicPacketNumber unacked2[] = {2}; + uint64_t unacked2[] = {2}; VerifyUnackedPackets(unacked2, QUIC_ARRAYSIZE(unacked2)); EXPECT_TRUE(QuicSentPacketManagerPeer::HasPendingPackets(&manager_)); SendDataPacket(5); ExpectAckAndLoss(true, 5, 2); - EXPECT_CALL(debug_delegate, OnPacketLoss(2, LOSS_RETRANSMISSION, _)); + EXPECT_CALL(debug_delegate, + OnPacketLoss(QuicPacketNumber(2), LOSS_RETRANSMISSION, _)); if (manager_.session_decides_what_to_write()) { // Frames in all packets are acked. EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false)); @@ -615,14 +635,15 @@ EXPECT_CALL(notifier_, OnFrameLost(_)).Times(1); } } - manager_.OnAckFrameStart(5, QuicTime::Delta::Infinite(), clock_.Now()); - manager_.OnAckRange(3, 6); - manager_.OnAckRange(1, 2); + manager_.OnAckFrameStart(QuicPacketNumber(5), QuicTime::Delta::Infinite(), + clock_.Now()); + manager_.OnAckRange(QuicPacketNumber(3), QuicPacketNumber(6)); + manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2)); EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now())); if (manager_.session_decides_what_to_write() && GetQuicReloadableFlag(quic_fix_mark_for_loss_retransmission)) { - QuicPacketNumber unacked[] = {2}; + uint64_t unacked[] = {2}; VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked)); } else { VerifyUnackedPackets(nullptr, 0); @@ -649,8 +670,9 @@ { ExpectAck(1); EXPECT_CALL(*loss_algorithm, DetectLosses(_, _, _, _, _, _)); - manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite(), clock_.Now()); - manager_.OnAckRange(1, 2); + manager_.OnAckFrameStart(QuicPacketNumber(1), QuicTime::Delta::Infinite(), + clock_.Now()); + manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2)); EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now())); } @@ -660,22 +682,25 @@ { ExpectAck(4); EXPECT_CALL(*loss_algorithm, DetectLosses(_, _, _, _, _, _)); - manager_.OnAckFrameStart(4, QuicTime::Delta::Infinite(), clock_.Now()); - manager_.OnAckRange(4, 5); - manager_.OnAckRange(1, 2); + manager_.OnAckFrameStart(QuicPacketNumber(4), QuicTime::Delta::Infinite(), + clock_.Now()); + manager_.OnAckRange(QuicPacketNumber(4), QuicPacketNumber(5)); + manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2)); EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now())); RetransmitAndSendPacket(3, 5, LOSS_RETRANSMISSION); } // Ack 3, which causes SpuriousRetransmitDetected to be called. { - QuicPacketNumber acked[] = {3}; + uint64_t acked[] = {3}; ExpectAcksAndLosses(false, acked, QUIC_ARRAYSIZE(acked), nullptr, 0); EXPECT_CALL(*loss_algorithm, DetectLosses(_, _, _, _, _, _)); - EXPECT_CALL(*loss_algorithm, SpuriousRetransmitDetected(_, _, _, 5)); - manager_.OnAckFrameStart(4, QuicTime::Delta::Infinite(), clock_.Now()); - manager_.OnAckRange(3, 5); - manager_.OnAckRange(1, 2); + EXPECT_CALL(*loss_algorithm, + SpuriousRetransmitDetected(_, _, _, QuicPacketNumber(5))); + manager_.OnAckFrameStart(QuicPacketNumber(4), QuicTime::Delta::Infinite(), + clock_.Now()); + manager_.OnAckRange(QuicPacketNumber(3), QuicPacketNumber(5)); + manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2)); EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now())); if (manager_.session_decides_what_to_write()) { // Ack 3 will not cause 5 be considered as a spurious retransmission. Ack @@ -684,57 +709,60 @@ ExpectAck(5); EXPECT_CALL(*loss_algorithm, DetectLosses(_, _, _, _, _, _)); EXPECT_CALL(notifier_, OnFrameAcked(_, _)).WillOnce(Return(false)); - manager_.OnAckFrameStart(5, QuicTime::Delta::Infinite(), clock_.Now()); - manager_.OnAckRange(3, 6); - manager_.OnAckRange(1, 2); + manager_.OnAckFrameStart(QuicPacketNumber(5), QuicTime::Delta::Infinite(), + clock_.Now()); + manager_.OnAckRange(QuicPacketNumber(3), QuicPacketNumber(6)); + manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2)); EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now())); } } } TEST_P(QuicSentPacketManagerTest, GetLeastUnacked) { - EXPECT_EQ(1u, manager_.GetLeastUnacked()); + EXPECT_EQ(QuicPacketNumber(1u), manager_.GetLeastUnacked()); } TEST_P(QuicSentPacketManagerTest, GetLeastUnackedUnacked) { SendDataPacket(1); - EXPECT_EQ(1u, manager_.GetLeastUnacked()); + EXPECT_EQ(QuicPacketNumber(1u), manager_.GetLeastUnacked()); } TEST_P(QuicSentPacketManagerTest, AckAckAndUpdateRtt) { - EXPECT_EQ(0u, manager_.largest_packet_peer_knows_is_acked()); + EXPECT_FALSE(manager_.largest_packet_peer_knows_is_acked().IsInitialized()); SendDataPacket(1); SendAckPacket(2, 1); // Now ack the ack and expect an RTT update. - QuicPacketNumber acked[] = {1, 2}; + uint64_t acked[] = {1, 2}; ExpectAcksAndLosses(true, acked, QUIC_ARRAYSIZE(acked), nullptr, 0); - manager_.OnAckFrameStart(2, QuicTime::Delta::FromMilliseconds(5), - clock_.Now()); - manager_.OnAckRange(1, 3); + manager_.OnAckFrameStart(QuicPacketNumber(2), + QuicTime::Delta::FromMilliseconds(5), clock_.Now()); + manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(3)); EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now())); - EXPECT_EQ(1u, manager_.largest_packet_peer_knows_is_acked()); + EXPECT_EQ(QuicPacketNumber(1), manager_.largest_packet_peer_knows_is_acked()); SendAckPacket(3, 3); // Now ack the ack and expect only an RTT update. - QuicPacketNumber acked2[] = {3}; + uint64_t acked2[] = {3}; ExpectAcksAndLosses(true, acked2, QUIC_ARRAYSIZE(acked2), nullptr, 0); - manager_.OnAckFrameStart(3, QuicTime::Delta::Infinite(), clock_.Now()); - manager_.OnAckRange(1, 4); + manager_.OnAckFrameStart(QuicPacketNumber(3), QuicTime::Delta::Infinite(), + clock_.Now()); + manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(4)); EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now())); - EXPECT_EQ(3u, manager_.largest_packet_peer_knows_is_acked()); + EXPECT_EQ(QuicPacketNumber(3u), + manager_.largest_packet_peer_knows_is_acked()); } TEST_P(QuicSentPacketManagerTest, Rtt) { - QuicPacketNumber packet_number = 1; QuicTime::Delta expected_rtt = QuicTime::Delta::FromMilliseconds(20); - SendDataPacket(packet_number); + SendDataPacket(1); clock_.AdvanceTime(expected_rtt); - ExpectAck(packet_number); - manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite(), clock_.Now()); - manager_.OnAckRange(1, 2); + ExpectAck(1); + manager_.OnAckFrameStart(QuicPacketNumber(1), QuicTime::Delta::Infinite(), + clock_.Now()); + manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2)); EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now())); EXPECT_EQ(expected_rtt, manager_.GetRttStats()->latest_rtt()); } @@ -743,15 +771,14 @@ // Expect that the RTT is equal to the local time elapsed, since the // ack_delay_time is larger than the local time elapsed // and is hence invalid. - QuicPacketNumber packet_number = 1; QuicTime::Delta expected_rtt = QuicTime::Delta::FromMilliseconds(10); - SendDataPacket(packet_number); + SendDataPacket(1); clock_.AdvanceTime(expected_rtt); - ExpectAck(packet_number); - manager_.OnAckFrameStart(1, QuicTime::Delta::FromMilliseconds(11), - clock_.Now()); - manager_.OnAckRange(1, 2); + ExpectAck(1); + manager_.OnAckFrameStart(QuicPacketNumber(1), + QuicTime::Delta::FromMilliseconds(11), clock_.Now()); + manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2)); EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now())); EXPECT_EQ(expected_rtt, manager_.GetRttStats()->latest_rtt()); } @@ -759,14 +786,14 @@ TEST_P(QuicSentPacketManagerTest, RttWithInfiniteDelta) { // Expect that the RTT is equal to the local time elapsed, since the // ack_delay_time is infinite, and is hence invalid. - QuicPacketNumber packet_number = 1; QuicTime::Delta expected_rtt = QuicTime::Delta::FromMilliseconds(10); - SendDataPacket(packet_number); + SendDataPacket(1); clock_.AdvanceTime(expected_rtt); - ExpectAck(packet_number); - manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite(), clock_.Now()); - manager_.OnAckRange(1, 2); + ExpectAck(1); + manager_.OnAckFrameStart(QuicPacketNumber(1), QuicTime::Delta::Infinite(), + clock_.Now()); + manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2)); EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now())); EXPECT_EQ(expected_rtt, manager_.GetRttStats()->latest_rtt()); } @@ -774,14 +801,14 @@ TEST_P(QuicSentPacketManagerTest, RttZeroDelta) { // Expect that the RTT is the time between send and receive since the // ack_delay_time is zero. - QuicPacketNumber packet_number = 1; QuicTime::Delta expected_rtt = QuicTime::Delta::FromMilliseconds(10); - SendDataPacket(packet_number); + SendDataPacket(1); clock_.AdvanceTime(expected_rtt); - ExpectAck(packet_number); - manager_.OnAckFrameStart(1, QuicTime::Delta::Zero(), clock_.Now()); - manager_.OnAckRange(1, 2); + ExpectAck(1); + manager_.OnAckFrameStart(QuicPacketNumber(1), QuicTime::Delta::Zero(), + clock_.Now()); + manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2)); EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now())); EXPECT_EQ(expected_rtt, manager_.GetRttStats()->latest_rtt()); } @@ -790,8 +817,7 @@ QuicSentPacketManagerPeer::SetMaxTailLossProbes(&manager_, 2); // Send 1 packet. - QuicPacketNumber packet_number = 1; - SendDataPacket(packet_number); + SendDataPacket(1); // The first tail loss probe retransmits 1 packet. manager_.OnRetransmissionTimeout(); @@ -830,8 +856,9 @@ // Ack the third and ensure the first two are still pending. ExpectAck(3); - manager_.OnAckFrameStart(3, QuicTime::Delta::Infinite(), clock_.Now()); - manager_.OnAckRange(3, 4); + manager_.OnAckFrameStart(QuicPacketNumber(3), QuicTime::Delta::Infinite(), + clock_.Now()); + manager_.OnAckRange(QuicPacketNumber(3), QuicPacketNumber(4)); EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now())); EXPECT_TRUE(QuicSentPacketManagerPeer::HasPendingPackets(&manager_)); @@ -839,8 +866,8 @@ // Acking two more packets will lose both of them due to nacks. SendDataPacket(4); SendDataPacket(5); - QuicPacketNumber acked[] = {4, 5}; - QuicPacketNumber lost[] = {1, 2}; + uint64_t acked[] = {4, 5}; + uint64_t lost[] = {1, 2}; ExpectAcksAndLosses(true, acked, QUIC_ARRAYSIZE(acked), lost, QUIC_ARRAYSIZE(lost)); if (manager_.session_decides_what_to_write()) { @@ -852,8 +879,9 @@ EXPECT_CALL(notifier_, OnFrameLost(_)).Times(2); } } - manager_.OnAckFrameStart(5, QuicTime::Delta::Infinite(), clock_.Now()); - manager_.OnAckRange(3, 6); + manager_.OnAckFrameStart(QuicPacketNumber(5), QuicTime::Delta::Infinite(), + clock_.Now()); + manager_.OnAckRange(QuicPacketNumber(3), QuicPacketNumber(6)); EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now())); EXPECT_FALSE(manager_.HasPendingRetransmissions()); @@ -945,7 +973,7 @@ EXPECT_TRUE(manager_.HasPendingRetransmissions()); RetransmitNextPacket(103); } - QuicPacketNumber largest_acked = 103; + QuicPacketNumber largest_acked = QuicPacketNumber(103); EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout(true)); EXPECT_CALL(*send_algorithm_, OnCongestionEvent( @@ -974,8 +1002,9 @@ EXPECT_CALL(notifier_, OnFrameLost(_)).Times(101); } } - manager_.OnAckFrameStart(103, QuicTime::Delta::Infinite(), clock_.Now()); - manager_.OnAckRange(103, 104); + manager_.OnAckFrameStart(QuicPacketNumber(103), QuicTime::Delta::Infinite(), + clock_.Now()); + manager_.OnAckRange(QuicPacketNumber(103), QuicPacketNumber(104)); EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now())); // All packets before 103 should be lost. if (manager_.session_decides_what_to_write()) { @@ -1032,15 +1061,16 @@ // Now ack the two crypto packets and the speculatively encrypted request, // and ensure the first four crypto packets get abandoned, but not lost. - QuicPacketNumber acked[] = {3, 4, 5, 8, 9}; + uint64_t acked[] = {3, 4, 5, 8, 9}; ExpectAcksAndLosses(true, acked, QUIC_ARRAYSIZE(acked), nullptr, 0); if (manager_.session_decides_what_to_write()) { EXPECT_CALL(notifier_, HasUnackedCryptoData()) .WillRepeatedly(Return(false)); } - manager_.OnAckFrameStart(9, QuicTime::Delta::Infinite(), clock_.Now()); - manager_.OnAckRange(8, 10); - manager_.OnAckRange(3, 6); + manager_.OnAckFrameStart(QuicPacketNumber(9), QuicTime::Delta::Infinite(), + clock_.Now()); + manager_.OnAckRange(QuicPacketNumber(8), QuicPacketNumber(10)); + manager_.OnAckRange(QuicPacketNumber(3), QuicPacketNumber(6)); EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now())); EXPECT_FALSE(QuicSentPacketManagerPeer::HasUnackedCryptoPackets(&manager_)); @@ -1090,9 +1120,11 @@ RetransmitDataPacket(12, ALL_UNACKED_RETRANSMISSION); } else { ASSERT_TRUE(manager_.HasPendingRetransmissions()); - EXPECT_EQ(6u, manager_.NextPendingRetransmission().packet_number); + EXPECT_EQ(QuicPacketNumber(6u), + manager_.NextPendingRetransmission().packet_number); RetransmitNextPacket(8); - EXPECT_EQ(7u, manager_.NextPendingRetransmission().packet_number); + EXPECT_EQ(QuicPacketNumber(7u), + manager_.NextPendingRetransmission().packet_number); RetransmitNextPacket(9); EXPECT_TRUE(manager_.HasPendingRetransmissions()); // Send 3 more data packets and ensure the least unacked is raised. @@ -1102,19 +1134,20 @@ EXPECT_FALSE(manager_.HasPendingRetransmissions()); } - EXPECT_EQ(1u, manager_.GetLeastUnacked()); + EXPECT_EQ(QuicPacketNumber(1u), manager_.GetLeastUnacked()); // Least unacked isn't raised until an ack is received, so ack the // crypto packets. - QuicPacketNumber acked[] = {8, 9}; + uint64_t acked[] = {8, 9}; ExpectAcksAndLosses(true, acked, QUIC_ARRAYSIZE(acked), nullptr, 0); - manager_.OnAckFrameStart(9, QuicTime::Delta::Infinite(), clock_.Now()); - manager_.OnAckRange(8, 10); + manager_.OnAckFrameStart(QuicPacketNumber(9), QuicTime::Delta::Infinite(), + clock_.Now()); + manager_.OnAckRange(QuicPacketNumber(8), QuicPacketNumber(10)); EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now())); if (manager_.session_decides_what_to_write()) { EXPECT_CALL(notifier_, HasUnackedCryptoData()) .WillRepeatedly(Return(false)); } - EXPECT_EQ(10u, manager_.GetLeastUnacked()); + EXPECT_EQ(QuicPacketNumber(10u), manager_.GetLeastUnacked()); } TEST_P(QuicSentPacketManagerTest, CryptoHandshakeSpuriousRetransmission) { @@ -1144,19 +1177,20 @@ // Now ack the second crypto packet, and ensure the first gets removed, but // the third does not. - QuicPacketNumber acked[] = {2}; + uint64_t acked[] = {2}; ExpectAcksAndLosses(true, acked, QUIC_ARRAYSIZE(acked), nullptr, 0); if (manager_.session_decides_what_to_write()) { EXPECT_CALL(notifier_, HasUnackedCryptoData()) .WillRepeatedly(Return(false)); EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false)); } - manager_.OnAckFrameStart(2, QuicTime::Delta::Infinite(), clock_.Now()); - manager_.OnAckRange(2, 3); + manager_.OnAckFrameStart(QuicPacketNumber(2), QuicTime::Delta::Infinite(), + clock_.Now()); + manager_.OnAckRange(QuicPacketNumber(2), QuicPacketNumber(3)); EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now())); EXPECT_FALSE(QuicSentPacketManagerPeer::HasUnackedCryptoPackets(&manager_)); - QuicPacketNumber unacked[] = {3}; + uint64_t unacked[] = {3}; VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked)); } @@ -1214,7 +1248,7 @@ } else { // Packet 2 is useful because it does not get retransmitted and still has // retransmittable frames. - QuicPacketNumber unacked[] = {1, 2}; + uint64_t unacked[] = {1, 2}; VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked)); EXPECT_TRUE(manager_.HasPendingRetransmissions()); } @@ -1260,7 +1294,7 @@ EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false)); } EXPECT_FALSE(QuicSentPacketManagerPeer::HasUnackedCryptoPackets(&manager_)); - QuicPacketNumber unacked[] = {1, 2, 3}; + uint64_t unacked[] = {1, 2, 3}; VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked)); VerifyRetransmittablePackets(nullptr, 0); EXPECT_FALSE(manager_.HasPendingRetransmissions()); @@ -1268,10 +1302,11 @@ EXPECT_FALSE(QuicSentPacketManagerPeer::HasPendingPackets(&manager_)); // Ensure both packets get discarded when packet 2 is acked. - QuicPacketNumber acked[] = {3}; + uint64_t acked[] = {3}; ExpectAcksAndLosses(true, acked, QUIC_ARRAYSIZE(acked), nullptr, 0); - manager_.OnAckFrameStart(3, QuicTime::Delta::Infinite(), clock_.Now()); - manager_.OnAckRange(3, 4); + manager_.OnAckFrameStart(QuicPacketNumber(3), QuicTime::Delta::Infinite(), + clock_.Now()); + manager_.OnAckRange(QuicPacketNumber(3), QuicPacketNumber(4)); EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now())); VerifyUnackedPackets(nullptr, 0); VerifyRetransmittablePackets(nullptr, 0); @@ -1314,7 +1349,7 @@ // Ack a retransmission. // Ensure no packets are lost. - QuicPacketNumber largest_acked = 102; + QuicPacketNumber largest_acked = QuicPacketNumber(102); EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, Pointwise(PacketNumberEq(), {largest_acked}), @@ -1324,7 +1359,8 @@ // RTO's use loss detection instead of immediately declaring retransmitted // packets lost. for (int i = 1; i <= 99; ++i) { - EXPECT_CALL(debug_delegate, OnPacketLoss(i, LOSS_RETRANSMISSION, _)); + EXPECT_CALL(debug_delegate, + OnPacketLoss(QuicPacketNumber(i), LOSS_RETRANSMISSION, _)); } if (manager_.session_decides_what_to_write()) { if (GetQuicReloadableFlag(quic_fix_mark_for_loss_retransmission)) { @@ -1349,8 +1385,9 @@ EXPECT_CALL(notifier_, OnFrameLost(_)).Times(98); } } - manager_.OnAckFrameStart(102, QuicTime::Delta::Zero(), clock_.Now()); - manager_.OnAckRange(102, 103); + manager_.OnAckFrameStart(QuicPacketNumber(102), QuicTime::Delta::Zero(), + clock_.Now()); + manager_.OnAckRange(QuicPacketNumber(102), QuicPacketNumber(103)); EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now())); } @@ -1448,7 +1485,7 @@ // Ack a retransmission and expect no call to OnRetransmissionTimeout. // This will include packets in the lost packet map. - QuicPacketNumber largest_acked = 102; + QuicPacketNumber largest_acked = QuicPacketNumber(102); EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, Pointwise(PacketNumberEq(), {largest_acked}), @@ -1477,8 +1514,9 @@ EXPECT_CALL(notifier_, OnFrameLost(_)).Times(98); } } - manager_.OnAckFrameStart(102, QuicTime::Delta::Zero(), clock_.Now()); - manager_.OnAckRange(102, 103); + manager_.OnAckFrameStart(QuicPacketNumber(102), QuicTime::Delta::Zero(), + clock_.Now()); + manager_.OnAckRange(QuicPacketNumber(102), QuicPacketNumber(103)); EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now())); } @@ -1524,8 +1562,9 @@ // Ack a retransmission and ensure OnRetransmissionTimeout is called. EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout(true)); ExpectAck(2); - manager_.OnAckFrameStart(2, QuicTime::Delta::Zero(), clock_.Now()); - manager_.OnAckRange(2, 3); + manager_.OnAckFrameStart(QuicPacketNumber(2), QuicTime::Delta::Zero(), + clock_.Now()); + manager_.OnAckRange(QuicPacketNumber(2), QuicPacketNumber(3)); EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now())); // The original packet and newest should be outstanding. @@ -1575,8 +1614,9 @@ // Ack a retransmission and ensure OnRetransmissionTimeout is called. EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout(true)); ExpectAck(3); - manager_.OnAckFrameStart(3, QuicTime::Delta::Zero(), clock_.Now()); - manager_.OnAckRange(3, 4); + manager_.OnAckFrameStart(QuicPacketNumber(3), QuicTime::Delta::Zero(), + clock_.Now()); + manager_.OnAckRange(QuicPacketNumber(3), QuicPacketNumber(4)); EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now())); // The first two packets should still be outstanding. @@ -1776,8 +1816,9 @@ // Ack a packet before the first RTO and ensure the RTO timeout returns to the // original value and OnRetransmissionTimeout is not called or reverted. ExpectAck(2); - manager_.OnAckFrameStart(2, QuicTime::Delta::Infinite(), clock_.Now()); - manager_.OnAckRange(2, 3); + manager_.OnAckFrameStart(QuicPacketNumber(2), QuicTime::Delta::Infinite(), + clock_.Now()); + manager_.OnAckRange(QuicPacketNumber(2), QuicPacketNumber(3)); EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now())); EXPECT_FALSE(manager_.HasPendingRetransmissions()); EXPECT_EQ(5 * kDefaultLength, @@ -1910,8 +1951,9 @@ // set the loss timeout. ExpectAck(2); EXPECT_CALL(*loss_algorithm, DetectLosses(_, _, _, _, _, _)); - manager_.OnAckFrameStart(2, QuicTime::Delta::Infinite(), clock_.Now()); - manager_.OnAckRange(2, 3); + manager_.OnAckFrameStart(QuicPacketNumber(2), QuicTime::Delta::Infinite(), + clock_.Now()); + manager_.OnAckRange(QuicPacketNumber(2), QuicPacketNumber(3)); EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now())); QuicTime timeout(clock_.Now() + QuicTime::Delta::FromMilliseconds(10)); @@ -2416,19 +2458,21 @@ } TEST_P(QuicSentPacketManagerTest, PathMtuIncreased) { - EXPECT_CALL(*send_algorithm_, OnPacketSent(_, BytesInFlight(), 1, _, _)); - SerializedPacket packet(1, PACKET_4BYTE_PACKET_NUMBER, nullptr, - kDefaultLength + 100, false, false); - manager_.OnPacketSent(&packet, 0, clock_.Now(), NOT_RETRANSMISSION, - HAS_RETRANSMITTABLE_DATA); + EXPECT_CALL(*send_algorithm_, + OnPacketSent(_, BytesInFlight(), QuicPacketNumber(1), _, _)); + SerializedPacket packet(QuicPacketNumber(1), PACKET_4BYTE_PACKET_NUMBER, + nullptr, kDefaultLength + 100, false, false); + manager_.OnPacketSent(&packet, QuicPacketNumber(), clock_.Now(), + NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA); // Ack the large packet and expect the path MTU to increase. ExpectAck(1); EXPECT_CALL(*network_change_visitor_, OnPathMtuIncreased(kDefaultLength + 100)); QuicAckFrame ack_frame = InitAckFrame(1); - manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite(), clock_.Now()); - manager_.OnAckRange(1, 2); + manager_.OnAckFrameStart(QuicPacketNumber(1), QuicTime::Delta::Infinite(), + clock_.Now()); + manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2)); EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now())); } @@ -2438,26 +2482,28 @@ SendDataPacket(i); } // Ack [5, 7), [10, 12), [15, 17). - QuicPacketNumber acked1[] = {5, 6, 10, 11, 15, 16}; - QuicPacketNumber lost1[] = {1, 2, 3, 4, 7, 8, 9, 12, 13}; + uint64_t acked1[] = {5, 6, 10, 11, 15, 16}; + uint64_t lost1[] = {1, 2, 3, 4, 7, 8, 9, 12, 13}; ExpectAcksAndLosses(true, acked1, QUIC_ARRAYSIZE(acked1), lost1, QUIC_ARRAYSIZE(lost1)); EXPECT_CALL(notifier_, OnFrameLost(_)).Times(AnyNumber()); - manager_.OnAckFrameStart(16, QuicTime::Delta::Infinite(), clock_.Now()); - manager_.OnAckRange(15, 17); - manager_.OnAckRange(10, 12); - manager_.OnAckRange(5, 7); + manager_.OnAckFrameStart(QuicPacketNumber(16), QuicTime::Delta::Infinite(), + clock_.Now()); + manager_.OnAckRange(QuicPacketNumber(15), QuicPacketNumber(17)); + manager_.OnAckRange(QuicPacketNumber(10), QuicPacketNumber(12)); + manager_.OnAckRange(QuicPacketNumber(5), QuicPacketNumber(7)); // Make sure empty range does not harm. - manager_.OnAckRange(4, 4); + manager_.OnAckRange(QuicPacketNumber(4), QuicPacketNumber(4)); EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now())); // Ack [4, 8), [9, 13), [14, 21). - QuicPacketNumber acked2[] = {4, 7, 9, 12, 14, 17, 18, 19, 20}; + uint64_t acked2[] = {4, 7, 9, 12, 14, 17, 18, 19, 20}; ExpectAcksAndLosses(true, acked2, QUIC_ARRAYSIZE(acked2), nullptr, 0); - manager_.OnAckFrameStart(20, QuicTime::Delta::Infinite(), clock_.Now()); - manager_.OnAckRange(14, 21); - manager_.OnAckRange(9, 13); - manager_.OnAckRange(4, 8); + manager_.OnAckFrameStart(QuicPacketNumber(20), QuicTime::Delta::Infinite(), + clock_.Now()); + manager_.OnAckRange(QuicPacketNumber(14), QuicPacketNumber(21)); + manager_.OnAckRange(QuicPacketNumber(9), QuicPacketNumber(13)); + manager_.OnAckRange(QuicPacketNumber(4), QuicPacketNumber(8)); EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now())); }
diff --git a/quic/core/quic_session.cc b/quic/core/quic_session.cc index 0eae3d4..b5e88ff 100644 --- a/quic/core/quic_session.cc +++ b/quic/core/quic_session.cc
@@ -88,10 +88,6 @@ connection_->SetDataProducer(this); connection_->SetFromConfig(config_); - // Make sure connection and control frame manager latch the same flag values. - connection_->set_donot_retransmit_old_window_updates( - control_frame_manager_.donot_retransmit_old_window_updates()); - DCHECK_EQ(QuicUtils::GetCryptoStreamId(connection_->transport_version()), GetMutableCryptoStream()->id()); RegisterStaticStream( @@ -189,6 +185,10 @@ return false; } + if (visitor_) { + visitor_->OnStopSendingReceived(frame); + } + // If stream is closed, ignore the frame if (IsClosedStream(stream_id)) { QUIC_DVLOG(1) @@ -223,8 +223,15 @@ return true; } stream->OnStopSending(frame.application_error_code); - // TODO(fkastenholz): Add in code to start rst-stream in the opposite - // direction once we add IETF-QUIC semantics for rst-stream. + + stream->set_stream_error( + static_cast<QuicRstStreamErrorCode>(frame.application_error_code)); + SendRstStreamInner( + stream->id(), + static_cast<quic::QuicRstStreamErrorCode>(frame.application_error_code), + stream->stream_bytes_written(), + /*close_write_side_only=*/true); + stream->set_rst_sent(true); return true; } @@ -561,26 +568,34 @@ void QuicSession::SendRstStream(QuicStreamId id, QuicRstStreamErrorCode error, QuicStreamOffset bytes_written) { - if (QuicContainsKey(static_stream_map_, id)) { - QUIC_BUG << "Cannot send RST for a static stream with ID " << id; - return; - } + SendRstStreamInner(id, error, bytes_written, /*close_write_side_only=*/false); +} +void QuicSession::SendRstStreamInner(QuicStreamId id, + QuicRstStreamErrorCode error, + QuicStreamOffset bytes_written, + bool close_write_side_only) { if (connection()->connected()) { - // Only send a RST_STREAM frame if still connected. - // Send a RST_STREAM frame. If version 99, will include - // an IETF-QUIC STOP_SENDING frame in the packet so that - // the peer also shuts down and sends a RST_STREAM back. - QuicConnection::ScopedPacketFlusher* flusher = - (connection_->transport_version() == QUIC_VERSION_99) - ? new QuicConnection::ScopedPacketFlusher( - connection(), QuicConnection::SEND_ACK_IF_QUEUED) - : nullptr; - control_frame_manager_.WriteOrBufferRstStreamStopSending(id, error, - bytes_written); - if (flusher) { - delete flusher; - flusher = nullptr; + // Only send if still connected. + if (close_write_side_only) { + DCHECK_EQ(QUIC_VERSION_99, connection_->transport_version()); + // Send a RST_STREAM frame. + control_frame_manager_.WriteOrBufferRstStream(id, error, bytes_written); + } else { + // Send a RST_STREAM frame plus, if version 99, an IETF + // QUIC STOP_SENDING frame. Both sre sent to emulate + // the two-way close that Google QUIC's RST_STREAM does. + QuicConnection::ScopedPacketFlusher* flusher = + (connection_->transport_version() == QUIC_VERSION_99) + ? new QuicConnection::ScopedPacketFlusher( + connection(), QuicConnection::SEND_ACK_IF_QUEUED) + : nullptr; + control_frame_manager_.WriteOrBufferRstStreamStopSending(id, error, + bytes_written); + if (flusher) { + delete flusher; + flusher = nullptr; + } } connection_->OnStreamReset(id, error); } @@ -588,7 +603,18 @@ OnStreamDoneWaitingForAcks(id); return; } - CloseStreamInner(id, true); + if (close_write_side_only) { + DCHECK_EQ(QUIC_VERSION_99, connection_->transport_version()); + DynamicStreamMap::iterator it = dynamic_stream_map_.find(id); + if (it != dynamic_stream_map_.end()) { + QuicStream* stream = it->second.get(); + if (stream) { + stream->CloseWriteSide(); + } + } + } else { + CloseStreamInner(id, true); + } } void QuicSession::SendGoAway(QuicErrorCode error_code, @@ -671,7 +697,6 @@ InsertLocallyClosedStreamsHighestOffset( stream_id, stream->flow_controller()->highest_received_byte_offset()); } - dynamic_stream_map_.erase(it); if (IsIncomingStream(stream_id)) { --num_dynamic_incoming_streams_; @@ -719,6 +744,7 @@ if (pending_stream_map_.find(stream_id) != pending_stream_map_.end()) { pending_stream_map_.erase(stream_id); } + --num_dynamic_incoming_streams_; if (connection_->transport_version() == QUIC_VERSION_99) { @@ -952,10 +978,7 @@ // Discard originally encrypted packets, since they can't be decrypted by // the peer. NeuterUnencryptedData(); - if (GetQuicReloadableFlag(quic_optimize_encryption_established)) { - QUIC_RELOADABLE_FLAG_COUNT(quic_optimize_encryption_established); - is_handshake_confirmed_ = true; - } + is_handshake_confirmed_ = true; break; default: @@ -1468,6 +1491,14 @@ return WRITE_FAILED; } +bool QuicSession::WriteCryptoData(EncryptionLevel level, + QuicStreamOffset offset, + QuicByteCount data_length, + QuicDataWriter* writer) { + QUIC_BUG << "QuicSession::WriteCryptoData is unimplemented"; + return false; +} + QuicUint128 QuicSession::GetStatelessResetToken() const { if (!QuicConnectionIdSupportsVariableLength(perspective())) { return QuicConnectionIdToUInt64(connection_->connection_id());
diff --git a/quic/core/quic_session.h b/quic/core/quic_session.h index c542977..23778e7 100644 --- a/quic/core/quic_session.h +++ b/quic/core/quic_session.h
@@ -62,6 +62,10 @@ // Called when the session receives reset on a stream from the peer. virtual void OnRstStreamReceived(const QuicRstStreamFrame& frame) = 0; + + // Called when the session receives a STOP_SENDING for a stream from the + // peer. + virtual void OnStopSendingReceived(const QuicStopSendingFrame& frame) = 0; }; // CryptoHandshakeEvent enumerates the events generated by a QuicCryptoStream. @@ -130,6 +134,10 @@ QuicStreamOffset offset, QuicByteCount data_length, QuicDataWriter* writer) override; + bool WriteCryptoData(EncryptionLevel level, + QuicStreamOffset offset, + QuicByteCount data_length, + QuicDataWriter* writer) override; // SessionNotifierInterface methods: bool OnFrameAcked(const QuicFrame& frame, @@ -498,9 +506,6 @@ return stream_id_manager_; } - private: - friend class test::QuicSessionPeer; - // A StreamHandler represents an object which can receive a STREAM or // or RST_STREAM frame. struct StreamHandler { @@ -524,6 +529,11 @@ }; }; + StreamHandler GetOrCreateStreamImpl(QuicStreamId stream_id, bool may_buffer); + + private: + friend class test::QuicSessionPeer; + // Called in OnConfigNegotiated when we receive a new stream level flow // control window in a negotiated config. Closes the connection if invalid. void OnNewStreamFlowControlWindow(QuicStreamOffset new_window); @@ -551,7 +561,6 @@ // closed. QuicStream* GetStream(QuicStreamId id) const; - StreamHandler GetOrCreateStreamImpl(QuicStreamId stream_id, bool may_buffer); StreamHandler GetOrCreateDynamicStreamImpl(QuicStreamId stream_id, bool may_buffer); @@ -562,6 +571,17 @@ // Closes the pending stream |stream_id| before it has been created. void ClosePendingStream(QuicStreamId stream_id); + // Does actual work of sending reset-stream or reset-stream&stop-sending + // If the connection is not version 99/IETF QUIC, will always send a + // RESET_STREAM and close_write_side_only is ignored. If the connection is + // IETF QUIC/Version 99 then will send a RESET_STREAM and STOP_SENDING if + // close_write_side_only is false, just a RESET_STREAM if + // close_write_side_only is true. + void SendRstStreamInner(QuicStreamId id, + QuicRstStreamErrorCode error, + QuicStreamOffset bytes_written, + bool close_write_side_only); + // Keep track of highest received byte offset of locally closed streams, while // waiting for a definitive final highest offset from the peer. std::map<QuicStreamId, QuicStreamOffset>
diff --git a/quic/core/quic_session_test.cc b/quic/core/quic_session_test.cc index 3baae32..6bf26ab 100644 --- a/quic/core/quic_session_test.cc +++ b/quic/core/quic_session_test.cc
@@ -1291,18 +1291,30 @@ 1 + kInitialSessionFlowControlWindowForTest / 2; if (transport_version() == QUIC_VERSION_99) { + // Two more control frames than in Google QUIC, one is the STOP_SENDING + // frame, the other is the RST_STREAM generated in response. EXPECT_CALL(*connection_, SendControlFrame(_)) - .Times(3) + .Times(4) .WillRepeatedly(Invoke(&session_, &TestSession::ClearControlFrame)); + EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _)).Times(2); } else { EXPECT_CALL(*connection_, SendControlFrame(_)) .Times(2) .WillRepeatedly(Invoke(&session_, &TestSession::ClearControlFrame)); + 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); + if (transport_version() == QUIC_VERSION_99) { + // The test is predicated on the stream being fully closed. For V99, the + // RST_STREAM only does one side (the read side from the perspective of the + // node receiving the RST_STREAM). This is needed to fully close the + // stream and therefore fulfill all of the expects. + QuicStopSendingFrame frame(kInvalidControlFrameId, stream->id(), + QUIC_STREAM_CANCELLED); + EXPECT_TRUE(session_.OnStopSendingFrame(frame)); + } EXPECT_EQ(kByteOffset, session_.flow_controller()->bytes_consumed()); } @@ -1732,16 +1744,26 @@ if (transport_version() == QUIC_VERSION_99) { // Once for the RST_STREAM, once for the STOP_SENDING EXPECT_CALL(*connection_, SendControlFrame(_)) - .Times(2) + .Times(3) .WillRepeatedly(Invoke(&session_, &TestSession::ClearControlFrame)); + EXPECT_CALL(*connection_, OnStreamReset(stream2->id(), _)).Times(2); } else { // Just for the RST_STREAM EXPECT_CALL(*connection_, SendControlFrame(_)) .WillOnce(Invoke(&session_, &TestSession::ClearControlFrame)); + EXPECT_CALL(*connection_, + OnStreamReset(stream2->id(), QUIC_RST_ACKNOWLEDGEMENT)); } - EXPECT_CALL(*connection_, - OnStreamReset(stream2->id(), QUIC_RST_ACKNOWLEDGEMENT)); stream2->OnStreamReset(rst_frame); + if (transport_version() == QUIC_VERSION_99) { + // The test is predicated on the stream being fully closed. For V99, the + // RST_STREAM only does one side (the read side from the perspective of the + // node receiving the RST_STREAM). This is needed to fully close the + // stream and therefore fulfill all of the expects. + QuicStopSendingFrame frame(kInvalidControlFrameId, stream2->id(), + QUIC_STREAM_CANCELLED); + EXPECT_TRUE(session_.OnStopSendingFrame(frame)); + } EXPECT_FALSE(QuicContainsKey(session_.zombie_streams(), stream2->id())); ASSERT_EQ(1u, session_.closed_streams()->size()); EXPECT_EQ(stream2->id(), session_.closed_streams()->front()->id()); @@ -1759,6 +1781,10 @@ EXPECT_CALL(*connection_, OnStreamReset(stream4->id(), QUIC_STREAM_CANCELLED)); stream4->WriteOrBufferData(body, false, nullptr); + // Note well: Reset() actually closes the stream in both directions. For + // GOOGLE QUIC it sends a RST_STREAM (which does a 2-way close), for IETF + // QUIC/V99 it sends both a RST_STREAM and a STOP_SENDING (each of which + // closes in only one direction). stream4->Reset(QUIC_STREAM_CANCELLED); EXPECT_FALSE(QuicContainsKey(session_.zombie_streams(), stream4->id())); EXPECT_EQ(2u, session_.closed_streams()->size()); @@ -2279,10 +2305,24 @@ } TestStream* stream = session_.CreateOutgoingBidirectionalStream(); + + // Ensure that the stream starts out open in both directions. + EXPECT_FALSE(QuicStreamPeer::write_side_closed(stream)); + EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream)); + QuicStreamId stream_id = stream->id(); QuicStopSendingFrame frame(1, stream_id, 123); EXPECT_CALL(*stream, OnStopSending(123)); + // Expect a reset to come back out.xxxxx + EXPECT_CALL(*connection_, SendControlFrame(_)); + EXPECT_CALL( + *connection_, + OnStreamReset(stream_id, static_cast<QuicRstStreamErrorCode>(123))); EXPECT_TRUE(session_.OnStopSendingFrame(frame)); + // When the STOP_SENDING is received, the node generates a RST_STREAM, + // which closes the stream in the write direction. Ensure this. + EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream)); + EXPECT_TRUE(QuicStreamPeer::write_side_closed(stream)); } } // namespace
diff --git a/quic/core/quic_stream.cc b/quic/core/quic_stream.cc index 30c02e0..6c8ea8d 100644 --- a/quic/core/quic_stream.cc +++ b/quic/core/quic_stream.cc
@@ -293,12 +293,15 @@ (kMaxStreamLength - frame.offset < frame.data_length); if (is_stream_too_long) { // Close connection if stream becomes too long. - QUIC_PEER_BUG - << "Receive stream frame reaches max stream length. frame offset " - << frame.offset << " length " << frame.data_length; + QUIC_PEER_BUG << "Receive stream frame on stream " << id_ + << " reaches max stream length. frame offset " << frame.offset + << " length " << frame.data_length << ". " + << sequencer_.DebugString(); CloseConnectionWithDetails( QUIC_STREAM_LENGTH_OVERFLOW, - "Peer sends more data than allowed on this stream."); + QuicStrCat("Peer sends more data than allowed on stream ", id_, + ". frame: offset = ", frame.offset, ", length = ", + frame.data_length, ". ", sequencer_.DebugString())); return; } if (frame.fin) { @@ -364,7 +367,11 @@ } stream_error_ = frame.error_code; - CloseWriteSide(); + // Google QUIC closes both sides of the stream in response to a + // RESET_STREAM, IETF QUIC closes only the read side. + if (transport_version() != QUIC_VERSION_99) { + CloseWriteSide(); + } CloseReadSide(); }
diff --git a/quic/core/quic_stream.h b/quic/core/quic_stream.h index bc440d3..13a6b2c 100644 --- a/quic/core/quic_stream.h +++ b/quic/core/quic_stream.h
@@ -45,7 +45,8 @@ class QuicStream; // Buffers frames for a stream until the first byte of that frame arrives. -class PendingStream : public QuicStreamSequencer::StreamInterface { +class QUIC_EXPORT_PRIVATE PendingStream + : public QuicStreamSequencer::StreamInterface { public: PendingStream(QuicStreamId id, QuicSession* session); PendingStream(const PendingStream&) = delete; @@ -70,6 +71,9 @@ // If the final offset violates flow control, the connection will be closed. void OnRstStreamFrame(const QuicRstStreamFrame& frame); + // Returns the number of bytes read on this stream. + uint64_t stream_bytes_read() { return stream_bytes_read_; } + private: friend class QuicStream; @@ -341,6 +345,11 @@ // QuicStream class. virtual void OnStopSending(uint16_t code); + // Close the write side of the socket. Further writes will fail. + // Can be called by the subclass or internally. + // Does not send a FIN. May cause the stream to be closed. + virtual void CloseWriteSide(); + protected: // Sends as many bytes in the first |count| buffers of |iov| to the connection // as the connection will consume. If FIN is consumed, the write side is @@ -358,11 +367,6 @@ QuicStreamOffset offset, bool fin); - // Close the write side of the socket. Further writes will fail. - // Can be called by the subclass or internally. - // Does not send a FIN. May cause the stream to be closed. - virtual void CloseWriteSide(); - // Close the read side of the socket. May cause the stream to be closed. // Subclasses and consumers should use StopReading to terminate reading early // if expecting a FIN. Can be used directly by subclasses if not expecting a
diff --git a/quic/core/quic_stream_frame_data_producer.h b/quic/core/quic_stream_frame_data_producer.h index 56922b1..ab67d54 100644 --- a/quic/core/quic_stream_frame_data_producer.h +++ b/quic/core/quic_stream_frame_data_producer.h
@@ -24,6 +24,14 @@ QuicStreamOffset offset, QuicByteCount data_length, QuicDataWriter* writer) = 0; + + // Writes the data for a CRYPTO frame to |writer| for a frame at encryption + // level |level| starting at offset |offset| for |data_length| bytes. Returns + // whether writing the data was successful. + virtual bool WriteCryptoData(EncryptionLevel level, + QuicStreamOffset offset, + QuicByteCount data_length, + QuicDataWriter* writer) = 0; }; } // namespace quic
diff --git a/quic/core/quic_stream_id_manager.cc b/quic/core/quic_stream_id_manager.cc index ede2056..ce08e59 100644 --- a/quic/core/quic_stream_id_manager.cc +++ b/quic/core/quic_stream_id_manager.cc
@@ -1,3 +1,6 @@ +// Copyright (c) 2018 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/quic_stream_id_manager.h" #include "net/third_party/quiche/src/quic/core/quic_connection.h"
diff --git a/quic/core/quic_stream_id_manager.h b/quic/core/quic_stream_id_manager.h index d30f5cd..95951c0 100644 --- a/quic/core/quic_stream_id_manager.h +++ b/quic/core/quic_stream_id_manager.h
@@ -1,3 +1,6 @@ +// Copyright (c) 2018 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_QUIC_STREAM_ID_MANAGER_H_ #define QUICHE_QUIC_CORE_QUIC_STREAM_ID_MANAGER_H_
diff --git a/quic/core/quic_stream_id_manager_test.cc b/quic/core/quic_stream_id_manager_test.cc index 80252c3..5647d75 100644 --- a/quic/core/quic_stream_id_manager_test.cc +++ b/quic/core/quic_stream_id_manager_test.cc
@@ -1,3 +1,6 @@ +// Copyright (c) 2018 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/quic_stream_id_manager.h" #include <cstdint>
diff --git a/quic/core/quic_stream_sequencer.h b/quic/core/quic_stream_sequencer.h index 00ead04..dfe5e7d 100644 --- a/quic/core/quic_stream_sequencer.h +++ b/quic/core/quic_stream_sequencer.h
@@ -20,8 +20,6 @@ class QuicStreamSequencerPeer; } // namespace test -class QuicStream; - // Buffers frames until we have something which can be passed // up to the next layer. class QUIC_EXPORT_PRIVATE QuicStreamSequencer {
diff --git a/quic/core/quic_stream_sequencer_buffer.cc b/quic/core/quic_stream_sequencer_buffer.cc index 6e720e0..b96a89a 100644 --- a/quic/core/quic_stream_sequencer_buffer.cc +++ b/quic/core/quic_stream_sequencer_buffer.cc
@@ -91,7 +91,7 @@ // Extend the right edge of last interval. // TODO(fayang): Encapsulate this into a future version of QuicIntervalSet // if this is more efficient than Add. - const_cast<QuicInterval<QuicPacketNumber>*>(&(*bytes_received_.rbegin())) + const_cast<QuicInterval<QuicStreamOffset>*>(&(*bytes_received_.rbegin())) ->SetMax(starting_offset + size); } else { bytes_received_.Add(starting_offset, starting_offset + size);
diff --git a/quic/core/quic_stream_test.cc b/quic/core/quic_stream_test.cc index 3b49f72..e8338b3 100644 --- a/quic/core/quic_stream_test.cc +++ b/quic/core/quic_stream_test.cc
@@ -8,6 +8,7 @@ #include "net/third_party/quiche/src/quic/core/quic_connection.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" @@ -126,6 +127,18 @@ return true; } + bool ClearResetStreamFrame(const QuicFrame& frame) { + EXPECT_EQ(RST_STREAM_FRAME, frame.type); + DeleteFrame(&const_cast<QuicFrame&>(frame)); + return true; + } + + bool ClearStopSendingFrame(const QuicFrame& frame) { + EXPECT_EQ(STOP_SENDING_FRAME, frame.type); + DeleteFrame(&const_cast<QuicFrame&>(frame)); + return true; + } + protected: MockQuicConnectionHelper helper_; MockAlarmFactory alarm_factory_; @@ -686,7 +699,8 @@ QuicStreamFrame stream_frame(stream_->id(), false, kMaxStreamLength, QuicStringPiece(".")); EXPECT_QUIC_PEER_BUG(stream_->OnStreamFrame(stream_frame), - "Receive stream frame reaches max stream length"); + QuicStrCat("Receive stream frame on stream ", + stream_->id(), " reaches max stream length")); } TEST_P(QuicParameterizedStreamTest, SetDrainingIncomingOutgoing) { @@ -1067,7 +1081,6 @@ QuicConsumedData consumed = stream_->WriteMemSlices(storage.ToSpan(), false); EXPECT_EQ(data.length(), consumed.bytes_consumed); struct iovec iov2 = {const_cast<char*>(data.data()), 1u}; - SimpleBufferAllocator allocator2; QuicMemSliceStorage storage2( &iov2, 1, session_->connection()->helper()->GetStreamSendBufferAllocator(), 1024); @@ -1445,6 +1458,10 @@ TEST_P(QuicParameterizedStreamTest, CheckStopSending) { Initialize(); const int kStopSendingCode = 123; + // These must start as false. + EXPECT_FALSE(QuicStreamPeer::write_side_closed(stream_)); + EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_)); + // Expect to actually see a stop sending if and only if we are in version 99. if (connection_->transport_version() == QUIC_VERSION_99) { EXPECT_CALL(*session_, SendStopSending(kStopSendingCode, stream_->id())) .Times(1); @@ -1452,6 +1469,74 @@ EXPECT_CALL(*session_, SendStopSending(_, _)).Times(0); } stream_->SendStopSending(kStopSendingCode); + // Sending a STOP_SENDING does not actually close the local stream. + // Our implementation waits for the responding RESET_STREAM to effect the + // closes. Therefore, read- and write-side closes should both be false. + EXPECT_FALSE(QuicStreamPeer::write_side_closed(stream_)); + EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_)); +} + +// Test that OnStreamReset does one-way (read) closes if version 99, two way +// (read and write) if not version 99. +TEST_P(QuicStreamTest, OnStreamResetReadOrReadWrite) { + Initialize(); + EXPECT_FALSE(QuicStreamPeer::write_side_closed(stream_)); + EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_)); + + QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream_->id(), + QUIC_STREAM_CANCELLED, 1234); + stream_->OnStreamReset(rst_frame); + if (connection_->transport_version() == QUIC_VERSION_99) { + // Version 99/IETF QUIC should close just the read side. + EXPECT_TRUE(QuicStreamPeer::read_side_closed(stream_)); + EXPECT_FALSE(QuicStreamPeer::write_side_closed(stream_)); + } else { + // Google QUIC should close both sides of the stream. + EXPECT_TRUE(QuicStreamPeer::write_side_closed(stream_)); + EXPECT_TRUE(QuicStreamPeer::read_side_closed(stream_)); + } +} + +// Test that receiving a STOP_SENDING just closes the write side of the stream. +// If not V99, the test is a noop (no STOP_SENDING in Google QUIC). +TEST_P(QuicStreamTest, OnStopSendingReadOrReadWrite) { + Initialize(); + if (connection_->transport_version() != QUIC_VERSION_99) { + return; + } + + EXPECT_FALSE(QuicStreamPeer::write_side_closed(stream_)); + EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_)); + + // Simulate receipt of a STOP_SENDING. + stream_->OnStopSending(123); + + // Should close just the read side. + EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_)); + EXPECT_TRUE(QuicStreamPeer::write_side_closed(stream_)); +} + +// SendOnlyRstStream must only send a RESET_STREAM (no bundled STOP_SENDING). +TEST_P(QuicStreamTest, SendOnlyRstStream) { + Initialize(); + if (connection_->transport_version() != QUIC_VERSION_99) { + return; + } + + EXPECT_CALL(*connection_, + OnStreamReset(stream_->id(), QUIC_BAD_APPLICATION_PAYLOAD)); + EXPECT_CALL(*connection_, SendControlFrame(_)) + .Times(1) + .WillOnce(Invoke(this, &QuicStreamTest::ClearResetStreamFrame)); + + QuicSessionPeer::SendRstStreamInner(session_.get(), stream_->id(), + QUIC_BAD_APPLICATION_PAYLOAD, + stream_->stream_bytes_written(), + /*close_write_side_only=*/true); + + // ResetStreamOnly should just close the write side. + EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_)); + EXPECT_TRUE(QuicStreamPeer::write_side_closed(stream_)); } } // namespace
diff --git a/quic/core/quic_time_wait_list_manager.cc b/quic/core/quic_time_wait_list_manager.cc index 86be54d..731df3e 100644 --- a/quic/core/quic_time_wait_list_manager.cc +++ b/quic/core/quic_time_wait_list_manager.cc
@@ -12,6 +12,7 @@ #include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h" #include "net/third_party/quiche/src/quic/core/crypto/quic_decrypter.h" #include "net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h" +#include "net/third_party/quiche/src/quic/core/quic_connection_id.h" #include "net/third_party/quiche/src/quic/core/quic_framer.h" #include "net/third_party/quiche/src/quic/core/quic_packets.h" #include "net/third_party/quiche/src/quic/core/quic_utils.h" @@ -245,11 +246,11 @@ result = writer_->Flush(); } - if (result.status == WRITE_STATUS_BLOCKED) { + if (IsWriteBlockedStatus(result.status)) { // If blocked and unbuffered, return false to retry sending. DCHECK(writer_->IsWriteBlocked()); visitor_->OnWriteBlocked(this); - return writer_->IsWriteBlockedDataBuffered(); + return result.status == WRITE_STATUS_BLOCKED_DATA_BUFFERED; } else if (IsWriteError(result.status)) { QUIC_LOG_FIRST_N(WARNING, 1) << "Received unknown error while sending termination packet to "
diff --git a/quic/core/quic_time_wait_list_manager_test.cc b/quic/core/quic_time_wait_list_manager_test.cc index 0fced02..0d3244b 100644 --- a/quic/core/quic_time_wait_list_manager_test.cc +++ b/quic/core/quic_time_wait_list_manager_test.cc
@@ -185,7 +185,7 @@ QuicEncryptedPacket* ConstructEncryptedPacket( QuicConnectionId destination_connection_id, QuicConnectionId source_connection_id, - QuicPacketNumber packet_number) { + uint64_t packet_number) { return quic::test::ConstructEncryptedPacket(destination_connection_id, source_connection_id, false, false, packet_number, "data"); @@ -406,9 +406,8 @@ QuicConnectionId connection_id = TestConnectionId(1); EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id)); AddConnectionId(connection_id, QuicTimeWaitListManager::SEND_STATELESS_RESET); - QuicPacketNumber packet_number = 234; std::unique_ptr<QuicEncryptedPacket> packet(ConstructEncryptedPacket( - connection_id, EmptyQuicConnectionId(), packet_number)); + connection_id, EmptyQuicConnectionId(), /*packet_number=*/234)); // Let first write through. EXPECT_CALL(writer_, WritePacket(_, _, self_address_.host(), peer_address_, _)) @@ -433,9 +432,8 @@ EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(other_connection_id)); AddConnectionId(other_connection_id, QuicTimeWaitListManager::SEND_STATELESS_RESET); - QuicPacketNumber other_packet_number = 23423; std::unique_ptr<QuicEncryptedPacket> other_packet(ConstructEncryptedPacket( - other_connection_id, EmptyQuicConnectionId(), other_packet_number)); + other_connection_id, EmptyQuicConnectionId(), /*packet_number=*/23423)); EXPECT_CALL(writer_, WritePacket(_, _, _, _, _)).Times(0); EXPECT_CALL(visitor_, OnWriteBlocked(&time_wait_list_manager_)); ProcessPacket(other_connection_id);
diff --git a/quic/core/quic_trace_visitor.cc b/quic/core/quic_trace_visitor.cc index 08363e2..b0fc8ae 100644 --- a/quic/core/quic_trace_visitor.cc +++ b/quic/core/quic_trace_visitor.cc
@@ -59,7 +59,7 @@ quic_trace::Event* event = trace_.add_events(); event->set_event_type(quic_trace::PACKET_SENT); event->set_time_us(ConvertTimestampToRecordedFormat(sent_time)); - event->set_packet_number(serialized_packet.packet_number); + event->set_packet_number(serialized_packet.packet_number.ToUint64()); event->set_packet_size(serialized_packet.encrypted_length); event->set_encryption_level( EncryptionLevelToProto(serialized_packet.encryption_level)); @@ -140,8 +140,8 @@ quic_trace::AckBlock* block = info->add_acked_packets(); // We record intervals as [a, b], whereas the in-memory representation // we currently use is [a, b). - block->set_first_packet(interval.min()); - block->set_last_packet(interval.max() - 1); + block->set_first_packet(interval.min().ToUint64()); + block->set_last_packet(interval.max().ToUint64() - 1); } break; } @@ -240,7 +240,7 @@ quic_trace::Event* event = trace_.add_events(); event->set_time_us(ConvertTimestampToRecordedFormat(ack_receive_time)); event->set_packet_number( - connection_->received_packet_manager().GetLargestObserved()); + connection_->received_packet_manager().GetLargestObserved().ToUint64()); event->set_event_type(quic_trace::PACKET_RECEIVED); // TODO(vasilvv): consider removing this copy. @@ -255,7 +255,7 @@ quic_trace::Event* event = trace_.add_events(); event->set_time_us(ConvertTimestampToRecordedFormat(detection_time)); event->set_event_type(quic_trace::PACKET_LOST); - event->set_packet_number(lost_packet_number); + event->set_packet_number(lost_packet_number.ToUint64()); PopulateTransportState(event->mutable_transport_state()); } @@ -265,7 +265,7 @@ event->set_time_us(ConvertTimestampToRecordedFormat(receive_time)); event->set_event_type(quic_trace::PACKET_RECEIVED); event->set_packet_number( - connection_->received_packet_manager().GetLargestObserved()); + connection_->received_packet_manager().GetLargestObserved().ToUint64()); // TODO(vasilvv): consider removing this copy. QuicWindowUpdateFrame copy_of_update = frame;
diff --git a/quic/core/quic_trace_visitor_test.cc b/quic/core/quic_trace_visitor_test.cc index 5d98d55..402fa77 100644 --- a/quic/core/quic_trace_visitor_test.cc +++ b/quic/core/quic_trace_visitor_test.cc
@@ -135,20 +135,22 @@ const quic_trace::AckInfo& info = frame.ack_info(); for (const auto& block : info.acked_packets()) { - packets.Add(block.first_packet(), block.last_packet() + 1); + packets.Add(QuicPacketNumber(block.first_packet()), + QuicPacketNumber(block.last_packet()) + 1); } } } if (packet.event_type() == quic_trace::PACKET_LOST) { - packets.Add(packet.packet_number(), packet.packet_number() + 1); + packets.Add(QuicPacketNumber(packet.packet_number()), + QuicPacketNumber(packet.packet_number()) + 1); } } ASSERT_EQ(1u, packets.Size()); - EXPECT_EQ(1u, packets.begin()->min()); + EXPECT_EQ(QuicPacketNumber(1u), packets.begin()->min()); // We leave some room (20 packets) for the packets which did not receive // conclusive status at the end of simulation. - EXPECT_GT(packets.rbegin()->max(), packets_sent_ - 20); + EXPECT_GT(packets.rbegin()->max(), QuicPacketNumber(packets_sent_ - 20)); } TEST_F(QuicTraceVisitorTest, TransportState) {
diff --git a/quic/core/quic_transmission_info.cc b/quic/core/quic_transmission_info.cc index 582f939..6e9d02c 100644 --- a/quic/core/quic_transmission_info.cc +++ b/quic/core/quic_transmission_info.cc
@@ -15,9 +15,7 @@ in_flight(false), state(OUTSTANDING), has_crypto_handshake(false), - num_padding_bytes(0), - retransmission(kInvalidPacketNumber), - largest_acked(kInvalidPacketNumber) {} + num_padding_bytes(0) {} QuicTransmissionInfo::QuicTransmissionInfo( EncryptionLevel level, @@ -35,9 +33,7 @@ in_flight(false), state(OUTSTANDING), has_crypto_handshake(has_crypto_handshake), - num_padding_bytes(num_padding_bytes), - retransmission(kInvalidPacketNumber), - largest_acked(kInvalidPacketNumber) {} + num_padding_bytes(num_padding_bytes) {} QuicTransmissionInfo::QuicTransmissionInfo(const QuicTransmissionInfo& other) = default;
diff --git a/quic/core/quic_types.h b/quic/core/quic_types.h index 47811c7..7718468 100644 --- a/quic/core/quic_types.h +++ b/quic/core/quic_types.h
@@ -12,6 +12,7 @@ #include <vector> #include "net/third_party/quiche/src/quic/core/quic_connection_id.h" +#include "net/third_party/quiche/src/quic/core/quic_packet_number.h" #include "net/third_party/quiche/src/quic/core/quic_time.h" #include "net/third_party/quiche/src/quic/platform/api/quic_export.h" @@ -27,7 +28,6 @@ typedef uint64_t QuicByteCount; typedef uint64_t QuicPacketCount; -typedef uint64_t QuicPacketNumber; typedef uint64_t QuicPublicResetNonceProof; typedef uint64_t QuicStreamOffset; typedef std::array<char, 32> DiversificationNonce; @@ -80,7 +80,10 @@ // TODO(wtc): see if WriteStatus can be replaced by QuicAsyncStatus. enum WriteStatus { WRITE_STATUS_OK, + // Write is blocked, caller needs to retry. WRITE_STATUS_BLOCKED, + // Write is blocked but the packet data is buffered, caller should not retry. + WRITE_STATUS_BLOCKED_DATA_BUFFERED, // To make the IsWriteError(WriteStatus) function work properly: // - Non-errors MUST be added before WRITE_STATUS_ERROR. // - Errors MUST be added after WRITE_STATUS_ERROR. @@ -89,6 +92,11 @@ WRITE_STATUS_NUM_VALUES, }; +inline bool IsWriteBlockedStatus(WriteStatus status) { + return status == WRITE_STATUS_BLOCKED || + status == WRITE_STATUS_BLOCKED_DATA_BUFFERED; +} + inline bool IsWriteError(WriteStatus status) { return status >= WRITE_STATUS_ERROR; } @@ -107,6 +115,7 @@ case WRITE_STATUS_OK: return bytes_written == other.bytes_written; case WRITE_STATUS_BLOCKED: + case WRITE_STATUS_BLOCKED_DATA_BUFFERED: return true; default: return error_code == other.error_code; @@ -208,32 +217,41 @@ // encodings. enum QuicIetfFrameType : uint8_t { IETF_PADDING = 0x00, - IETF_RST_STREAM = 0x01, - IETF_CONNECTION_CLOSE = 0x02, - IETF_APPLICATION_CLOSE = 0x03, - IETF_MAX_DATA = 0x04, - IETF_MAX_STREAM_DATA = 0x05, - IETF_MAX_STREAM_ID = 0x06, - IETF_PING = 0x07, - IETF_BLOCKED = 0x08, - IETF_STREAM_BLOCKED = 0x09, - IETF_STREAM_ID_BLOCKED = 0x0a, - IETF_NEW_CONNECTION_ID = 0x0b, - IETF_STOP_SENDING = 0x0c, - IETF_RETIRE_CONNECTION_ID = 0x0d, - IETF_PATH_CHALLENGE = 0x0e, - IETF_PATH_RESPONSE = 0x0f, + IETF_PING = 0x01, + IETF_ACK = 0x02, + IETF_ACK_ECN = 0x03, + IETF_RST_STREAM = 0x04, + IETF_STOP_SENDING = 0x05, + IETF_CRYPTO = 0x06, + IETF_NEW_TOKEN = 0x07, // the low-3 bits of the stream frame type value are actually flags // declaring what parts of the frame are/are-not present, as well as // some other control information. The code would then do something - // along the lines of "if ((frame_type & 0xf8) == 0x10)" to determine + // along the lines of "if ((frame_type & 0xf8) == 0x08)" to determine // whether the frame is a stream frame or not, and then examine each // bit specifically when/as needed. - IETF_STREAM = 0x10, - IETF_CRYPTO = 0x18, - IETF_NEW_TOKEN = 0x19, - IETF_ACK = 0x1a, - IETF_ACK_ECN = 0x1b, + IETF_STREAM = 0x08, + // 0x09 through 0x0f are various flag settings of the IETF_STREAM frame. + IETF_MAX_DATA = 0x10, + IETF_MAX_STREAM_DATA = 0x11, + IETF_MAX_STREAM_ID = 0x12, // TODO(fkastenholz): Will become IETF_MAX_STREAMS + // 0x13 reserved, a flag setting for IETF_MAX_STREAMS. + IETF_BLOCKED = 0x14, // TODO(fkastenholz): Should, eventually, be renamed to + // IETF_DATA_BLOCKED + IETF_STREAM_BLOCKED = 0x15, // TODO(fkastenholz): Should, eventually, be + // renamed to IETF_STREAM_DATA_BLOCKED + IETF_STREAM_ID_BLOCKED = + 0x16, // TODO(fkastenholz): Will become IETF_STREAMS_BLOCKED + // 0x17 reserved, a flag setting for IETF_STREAMS_BLOCKED + IETF_NEW_CONNECTION_ID = 0x18, + IETF_RETIRE_CONNECTION_ID = 0x19, + IETF_PATH_CHALLENGE = 0x1a, + IETF_PATH_RESPONSE = 0x1b, + IETF_CONNECTION_CLOSE = 0x1c, + // 0x1d reserved, a flag setting for IETF_CONNECTION_CLOSE + // TODO(fkastenholz): IETF_APPLICATION_CLOSE disappears in the next version of + // QUIC. It is retained temporarily + IETF_APPLICATION_CLOSE = 0x1d, // MESSAGE frame type is not yet determined, use 0x2x temporarily to give // stream frame some wiggle room. @@ -256,7 +274,7 @@ enum QuicPacketNumberLength : uint8_t { PACKET_1BYTE_PACKET_NUMBER = 1, PACKET_2BYTE_PACKET_NUMBER = 2, - PACKET_3BYTE_PACKET_NUMBER = 3, // Only used in v99. + PACKET_3BYTE_PACKET_NUMBER = 3, // Used in version > QUIC_VERSION_46. PACKET_4BYTE_PACKET_NUMBER = 4, // TODO(rch): Remove this when we remove QUIC_VERSION_39. PACKET_6BYTE_PACKET_NUMBER = 6,
diff --git a/quic/core/quic_unacked_packet_map.cc b/quic/core/quic_unacked_packet_map.cc index 3da540e..32fd272 100644 --- a/quic/core/quic_unacked_packet_map.cc +++ b/quic/core/quic_unacked_packet_map.cc
@@ -25,11 +25,7 @@ } // namespace QuicUnackedPacketMap::QuicUnackedPacketMap() - : largest_sent_packet_(0), - largest_sent_retransmittable_packet_(0), - largest_sent_largest_acked_(0), - largest_acked_(0), - least_unacked_(1), + : least_unacked_(FirstSendingPacketNumber()), bytes_in_flight_(0), pending_crypto_packet_count_(0), last_crypto_packet_sent_time_(QuicTime::Zero()), @@ -49,7 +45,10 @@ bool set_in_flight) { QuicPacketNumber packet_number = packet->packet_number; QuicPacketLength bytes_sent = packet->encrypted_length; - QUIC_BUG_IF(largest_sent_packet_ >= packet_number) << packet_number; + QUIC_BUG_IF(largest_sent_packet_.IsInitialized() && + largest_sent_packet_ >= packet_number) + << "largest_sent_packet_: " << largest_sent_packet_ + << ", packet_number: " << packet_number; DCHECK_GE(packet_number, least_unacked_ + unacked_packets_.size()); while (least_unacked_ + unacked_packets_.size() < packet_number) { unacked_packets_.push_back(QuicTransmissionInfo()); @@ -62,9 +61,13 @@ packet->encryption_level, packet->packet_number_length, transmission_type, sent_time, bytes_sent, has_crypto_handshake, packet->num_padding_bytes); info.largest_acked = packet->largest_acked; - largest_sent_largest_acked_ = - std::max(largest_sent_largest_acked_, packet->largest_acked); - if (old_packet_number > 0) { + if (packet->largest_acked.IsInitialized()) { + largest_sent_largest_acked_ = + largest_sent_largest_acked_.IsInitialized() + ? std::max(largest_sent_largest_acked_, packet->largest_acked) + : packet->largest_acked; + } + if (old_packet_number.IsInitialized()) { TransferRetransmissionInfo(old_packet_number, packet_number, transmission_type, &info); } @@ -78,7 +81,7 @@ unacked_packets_.push_back(info); // Swap the retransmittable frames to avoid allocations. // TODO(ianswett): Could use emplace_back when Chromium can. - if (old_packet_number == kInvalidPacketNumber) { + if (!old_packet_number.IsInitialized()) { if (has_crypto_handshake) { ++pending_crypto_packet_count_; last_crypto_packet_sent_time_ = sent_time; @@ -180,12 +183,12 @@ QuicTransmissionInfo* info) { if (session_decides_what_to_write_) { DeleteFrames(&info->retransmittable_frames); - info->retransmission = kInvalidPacketNumber; + info->retransmission.Clear(); return; } - while (info->retransmission != kInvalidPacketNumber) { + while (info->retransmission.IsInitialized()) { const QuicPacketNumber retransmission = info->retransmission; - info->retransmission = kInvalidPacketNumber; + info->retransmission.Clear(); info = &unacked_packets_[retransmission - least_unacked_]; } @@ -209,7 +212,7 @@ void QuicUnackedPacketMap::IncreaseLargestAcked( QuicPacketNumber largest_acked) { - DCHECK_LE(largest_acked_, largest_acked); + DCHECK(!largest_acked_.IsInitialized() || largest_acked_ <= largest_acked); largest_acked_ = largest_acked; } @@ -218,7 +221,8 @@ const QuicTransmissionInfo& info) const { // Packet can be used for RTT measurement if it may yet be acked as the // largest observed packet by the receiver. - return QuicUtils::IsAckable(info.state) && packet_number > largest_acked_; + return QuicUtils::IsAckable(info.state) && + (!largest_acked_.IsInitialized() || packet_number > largest_acked_); } bool QuicUnackedPacketMap::IsPacketUsefulForCongestionControl( @@ -233,15 +237,16 @@ // Packet may have retransmittable frames, or the data may have been // retransmitted with a new packet number. // Allow for an extra 1 RTT before stopping to track old packets. - return info.retransmission > largest_acked_ || + return (info.retransmission.IsInitialized() && + (!largest_acked_.IsInitialized() || + info.retransmission > largest_acked_)) || HasRetransmittableFrames(info); } // Wait for 1 RTT before giving up on the lost packet. - if (info.retransmission > largest_acked_) { - return true; - } - return false; + return info.retransmission.IsInitialized() && + (!largest_acked_.IsInitialized() || + info.retransmission > largest_acked_); } bool QuicUnackedPacketMap::IsPacketUseless( @@ -472,7 +477,7 @@ void QuicUnackedPacketMap::SetSessionDecideWhatToWrite( bool session_decides_what_to_write) { - if (largest_sent_packet_ > 0) { + if (largest_sent_packet_.IsInitialized()) { QUIC_BUG << "Cannot change session_decide_what_to_write with packets sent."; return; }
diff --git a/quic/core/quic_unacked_packet_map_test.cc b/quic/core/quic_unacked_packet_map_test.cc index a4d0289..df14321 100644 --- a/quic/core/quic_unacked_packet_map_test.cc +++ b/quic/core/quic_unacked_packet_map_test.cc
@@ -46,30 +46,31 @@ ~QuicUnackedPacketMapTest() override {} - SerializedPacket CreateRetransmittablePacket(QuicPacketNumber packet_number) { + SerializedPacket CreateRetransmittablePacket(uint64_t packet_number) { return CreateRetransmittablePacketForStream( packet_number, QuicUtils::GetHeadersStreamId( CurrentSupportedVersions()[0].transport_version)); } SerializedPacket CreateRetransmittablePacketForStream( - QuicPacketNumber packet_number, + uint64_t packet_number, QuicStreamId stream_id) { - SerializedPacket packet(packet_number, PACKET_1BYTE_PACKET_NUMBER, nullptr, - kDefaultLength, false, false); + SerializedPacket packet(QuicPacketNumber(packet_number), + PACKET_1BYTE_PACKET_NUMBER, nullptr, kDefaultLength, + false, false); QuicStreamFrame frame; frame.stream_id = stream_id; packet.retransmittable_frames.push_back(QuicFrame(frame)); return packet; } - SerializedPacket CreateNonRetransmittablePacket( - QuicPacketNumber packet_number) { - return SerializedPacket(packet_number, PACKET_1BYTE_PACKET_NUMBER, nullptr, - kDefaultLength, false, false); + SerializedPacket CreateNonRetransmittablePacket(uint64_t packet_number) { + return SerializedPacket(QuicPacketNumber(packet_number), + PACKET_1BYTE_PACKET_NUMBER, nullptr, kDefaultLength, + false, false); } - void VerifyInFlightPackets(QuicPacketNumber* packets, size_t num_packets) { + void VerifyInFlightPackets(uint64_t* packets, size_t num_packets) { unacked_packets_.RemoveObsoletePackets(); if (num_packets == 0) { EXPECT_FALSE(unacked_packets_.HasInFlightPackets()); @@ -79,12 +80,16 @@ if (num_packets == 1) { EXPECT_TRUE(unacked_packets_.HasInFlightPackets()); EXPECT_FALSE(unacked_packets_.HasMultipleInFlightPackets()); - ASSERT_TRUE(unacked_packets_.IsUnacked(packets[0])); - EXPECT_TRUE(unacked_packets_.GetTransmissionInfo(packets[0]).in_flight); + ASSERT_TRUE(unacked_packets_.IsUnacked(QuicPacketNumber(packets[0]))); + EXPECT_TRUE( + unacked_packets_.GetTransmissionInfo(QuicPacketNumber(packets[0])) + .in_flight); } for (size_t i = 0; i < num_packets; ++i) { - ASSERT_TRUE(unacked_packets_.IsUnacked(packets[i])); - EXPECT_TRUE(unacked_packets_.GetTransmissionInfo(packets[i]).in_flight); + ASSERT_TRUE(unacked_packets_.IsUnacked(QuicPacketNumber(packets[i]))); + EXPECT_TRUE( + unacked_packets_.GetTransmissionInfo(QuicPacketNumber(packets[i])) + .in_flight); } size_t in_flight_count = 0; for (QuicUnackedPacketMap::const_iterator it = unacked_packets_.begin(); @@ -96,7 +101,7 @@ EXPECT_EQ(num_packets, in_flight_count); } - void VerifyUnackedPackets(QuicPacketNumber* packets, size_t num_packets) { + void VerifyUnackedPackets(uint64_t* packets, size_t num_packets) { unacked_packets_.RemoveObsoletePackets(); if (num_packets == 0) { EXPECT_TRUE(unacked_packets_.empty()); @@ -107,13 +112,13 @@ } EXPECT_FALSE(unacked_packets_.empty()); for (size_t i = 0; i < num_packets; ++i) { - EXPECT_TRUE(unacked_packets_.IsUnacked(packets[i])) << packets[i]; + EXPECT_TRUE(unacked_packets_.IsUnacked(QuicPacketNumber(packets[i]))) + << packets[i]; } EXPECT_EQ(num_packets, unacked_packets_.GetNumUnackedPacketsDebugOnly()); } - void VerifyRetransmittablePackets(QuicPacketNumber* packets, - size_t num_packets) { + void VerifyRetransmittablePackets(uint64_t* packets, size_t num_packets) { unacked_packets_.RemoveObsoletePackets(); size_t num_retransmittable_packets = 0; for (QuicUnackedPacketMap::const_iterator it = unacked_packets_.begin(); @@ -124,29 +129,33 @@ } EXPECT_EQ(num_packets, num_retransmittable_packets); for (size_t i = 0; i < num_packets; ++i) { - EXPECT_TRUE(unacked_packets_.HasRetransmittableFrames(packets[i])) + EXPECT_TRUE(unacked_packets_.HasRetransmittableFrames( + QuicPacketNumber(packets[i]))) << " packets[" << i << "]:" << packets[i]; } } - void UpdatePacketState(QuicPacketNumber packet_number, - SentPacketState state) { - unacked_packets_.GetMutableTransmissionInfo(packet_number)->state = state; + void UpdatePacketState(uint64_t packet_number, SentPacketState state) { + unacked_packets_ + .GetMutableTransmissionInfo(QuicPacketNumber(packet_number)) + ->state = state; } - void RetransmitAndSendPacket(QuicPacketNumber old_packet_number, - QuicPacketNumber new_packet_number, + void RetransmitAndSendPacket(uint64_t old_packet_number, + uint64_t new_packet_number, TransmissionType transmission_type) { - DCHECK(unacked_packets_.HasRetransmittableFrames(old_packet_number)); + DCHECK(unacked_packets_.HasRetransmittableFrames( + QuicPacketNumber(old_packet_number))); if (!unacked_packets_.session_decides_what_to_write()) { SerializedPacket packet( CreateNonRetransmittablePacket(new_packet_number)); - unacked_packets_.AddSentPacket(&packet, old_packet_number, + unacked_packets_.AddSentPacket(&packet, + QuicPacketNumber(old_packet_number), transmission_type, now_, true); return; } - QuicTransmissionInfo* info = - unacked_packets_.GetMutableTransmissionInfo(old_packet_number); + QuicTransmissionInfo* info = unacked_packets_.GetMutableTransmissionInfo( + QuicPacketNumber(old_packet_number)); QuicStreamId stream_id = QuicUtils::GetHeadersStreamId( CurrentSupportedVersions()[0].transport_version); for (const auto& frame : info->retransmittable_frames) { @@ -158,10 +167,11 @@ UpdatePacketState( old_packet_number, QuicUtils::RetransmissionTypeToPacketState(transmission_type)); - info->retransmission = new_packet_number; + info->retransmission = QuicPacketNumber(new_packet_number); SerializedPacket packet( CreateRetransmittablePacketForStream(new_packet_number, stream_id)); - unacked_packets_.AddSentPacket(&packet, 0, transmission_type, now_, true); + unacked_packets_.AddSentPacket(&packet, QuicPacketNumber(), + transmission_type, now_, true); } QuicUnackedPacketMap unacked_packets_; QuicTime now_; @@ -173,14 +183,15 @@ TEST_P(QuicUnackedPacketMapTest, RttOnly) { // Acks are only tracked for RTT measurement purposes. SerializedPacket packet(CreateNonRetransmittablePacket(1)); - unacked_packets_.AddSentPacket(&packet, 0, NOT_RETRANSMISSION, now_, false); + unacked_packets_.AddSentPacket(&packet, QuicPacketNumber(), + NOT_RETRANSMISSION, now_, false); - QuicPacketNumber unacked[] = {1}; + uint64_t unacked[] = {1}; VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked)); VerifyInFlightPackets(nullptr, 0); VerifyRetransmittablePackets(nullptr, 0); - unacked_packets_.IncreaseLargestAcked(1); + unacked_packets_.IncreaseLargestAcked(QuicPacketNumber(1)); VerifyUnackedPackets(nullptr, 0); VerifyInFlightPackets(nullptr, 0); VerifyRetransmittablePackets(nullptr, 0); @@ -189,24 +200,25 @@ TEST_P(QuicUnackedPacketMapTest, RetransmittableInflightAndRtt) { // Simulate a retransmittable packet being sent and acked. SerializedPacket packet(CreateRetransmittablePacket(1)); - unacked_packets_.AddSentPacket(&packet, 0, NOT_RETRANSMISSION, now_, true); + unacked_packets_.AddSentPacket(&packet, QuicPacketNumber(), + NOT_RETRANSMISSION, now_, true); - QuicPacketNumber unacked[] = {1}; + uint64_t unacked[] = {1}; VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked)); VerifyInFlightPackets(unacked, QUIC_ARRAYSIZE(unacked)); VerifyRetransmittablePackets(unacked, QUIC_ARRAYSIZE(unacked)); - unacked_packets_.RemoveRetransmittability(1); + unacked_packets_.RemoveRetransmittability(QuicPacketNumber(1)); VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked)); VerifyInFlightPackets(unacked, QUIC_ARRAYSIZE(unacked)); VerifyRetransmittablePackets(nullptr, 0); - unacked_packets_.IncreaseLargestAcked(1); + unacked_packets_.IncreaseLargestAcked(QuicPacketNumber(1)); VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked)); VerifyInFlightPackets(unacked, QUIC_ARRAYSIZE(unacked)); VerifyRetransmittablePackets(nullptr, 0); - unacked_packets_.RemoveFromInFlight(1); + unacked_packets_.RemoveFromInFlight(QuicPacketNumber(1)); VerifyUnackedPackets(nullptr, 0); VerifyInFlightPackets(nullptr, 0); VerifyRetransmittablePackets(nullptr, 0); @@ -215,12 +227,13 @@ TEST_P(QuicUnackedPacketMapTest, StopRetransmission) { const QuicStreamId stream_id = 2; SerializedPacket packet(CreateRetransmittablePacketForStream(1, stream_id)); - unacked_packets_.AddSentPacket(&packet, 0, NOT_RETRANSMISSION, now_, true); + unacked_packets_.AddSentPacket(&packet, QuicPacketNumber(), + NOT_RETRANSMISSION, now_, true); - QuicPacketNumber unacked[] = {1}; + uint64_t unacked[] = {1}; VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked)); VerifyInFlightPackets(unacked, QUIC_ARRAYSIZE(unacked)); - QuicPacketNumber retransmittable[] = {1}; + uint64_t retransmittable[] = {1}; VerifyRetransmittablePackets(retransmittable, QUIC_ARRAYSIZE(retransmittable)); @@ -237,12 +250,13 @@ TEST_P(QuicUnackedPacketMapTest, StopRetransmissionOnOtherStream) { const QuicStreamId stream_id = 2; SerializedPacket packet(CreateRetransmittablePacketForStream(1, stream_id)); - unacked_packets_.AddSentPacket(&packet, 0, NOT_RETRANSMISSION, now_, true); + unacked_packets_.AddSentPacket(&packet, QuicPacketNumber(), + NOT_RETRANSMISSION, now_, true); - QuicPacketNumber unacked[] = {1}; + uint64_t unacked[] = {1}; VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked)); VerifyInFlightPackets(unacked, QUIC_ARRAYSIZE(unacked)); - QuicPacketNumber retransmittable[] = {1}; + uint64_t retransmittable[] = {1}; VerifyRetransmittablePackets(retransmittable, QUIC_ARRAYSIZE(retransmittable)); @@ -259,13 +273,14 @@ TEST_P(QuicUnackedPacketMapTest, StopRetransmissionAfterRetransmission) { const QuicStreamId stream_id = 2; SerializedPacket packet1(CreateRetransmittablePacketForStream(1, stream_id)); - unacked_packets_.AddSentPacket(&packet1, 0, NOT_RETRANSMISSION, now_, true); + unacked_packets_.AddSentPacket(&packet1, QuicPacketNumber(), + NOT_RETRANSMISSION, now_, true); RetransmitAndSendPacket(1, 2, LOSS_RETRANSMISSION); - QuicPacketNumber unacked[] = {1, 2}; + uint64_t unacked[] = {1, 2}; VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked)); VerifyInFlightPackets(unacked, QUIC_ARRAYSIZE(unacked)); - std::vector<QuicPacketNumber> retransmittable; + std::vector<uint64_t> retransmittable; if (unacked_packets_.session_decides_what_to_write()) { retransmittable = {1, 2}; } else { @@ -287,13 +302,14 @@ // Simulate a retransmittable packet being sent, retransmitted, and the first // transmission being acked. SerializedPacket packet1(CreateRetransmittablePacket(1)); - unacked_packets_.AddSentPacket(&packet1, 0, NOT_RETRANSMISSION, now_, true); + unacked_packets_.AddSentPacket(&packet1, QuicPacketNumber(), + NOT_RETRANSMISSION, now_, true); RetransmitAndSendPacket(1, 2, LOSS_RETRANSMISSION); - QuicPacketNumber unacked[] = {1, 2}; + uint64_t unacked[] = {1, 2}; VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked)); VerifyInFlightPackets(unacked, QUIC_ARRAYSIZE(unacked)); - std::vector<QuicPacketNumber> retransmittable; + std::vector<uint64_t> retransmittable; if (unacked_packets_.session_decides_what_to_write()) { retransmittable = {1, 2}; } else { @@ -302,23 +318,23 @@ VerifyRetransmittablePackets(&retransmittable[0], retransmittable.size()); EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false)); - unacked_packets_.RemoveRetransmittability(1); + unacked_packets_.RemoveRetransmittability(QuicPacketNumber(1)); VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked)); VerifyInFlightPackets(unacked, QUIC_ARRAYSIZE(unacked)); VerifyRetransmittablePackets(nullptr, 0); - unacked_packets_.IncreaseLargestAcked(2); + unacked_packets_.IncreaseLargestAcked(QuicPacketNumber(2)); VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked)); VerifyInFlightPackets(unacked, QUIC_ARRAYSIZE(unacked)); VerifyRetransmittablePackets(nullptr, 0); - unacked_packets_.RemoveFromInFlight(2); - QuicPacketNumber unacked2[] = {1}; + unacked_packets_.RemoveFromInFlight(QuicPacketNumber(2)); + uint64_t unacked2[] = {1}; VerifyUnackedPackets(unacked2, QUIC_ARRAYSIZE(unacked2)); VerifyInFlightPackets(unacked2, QUIC_ARRAYSIZE(unacked2)); VerifyRetransmittablePackets(nullptr, 0); - unacked_packets_.RemoveFromInFlight(1); + unacked_packets_.RemoveFromInFlight(QuicPacketNumber(1)); VerifyUnackedPackets(nullptr, 0); VerifyInFlightPackets(nullptr, 0); VerifyRetransmittablePackets(nullptr, 0); @@ -327,31 +343,34 @@ TEST_P(QuicUnackedPacketMapTest, RetransmitThreeTimes) { // Simulate a retransmittable packet being sent and retransmitted twice. SerializedPacket packet1(CreateRetransmittablePacket(1)); - unacked_packets_.AddSentPacket(&packet1, 0, NOT_RETRANSMISSION, now_, true); + unacked_packets_.AddSentPacket(&packet1, QuicPacketNumber(), + NOT_RETRANSMISSION, now_, true); SerializedPacket packet2(CreateRetransmittablePacket(2)); - unacked_packets_.AddSentPacket(&packet2, 0, NOT_RETRANSMISSION, now_, true); + unacked_packets_.AddSentPacket(&packet2, QuicPacketNumber(), + NOT_RETRANSMISSION, now_, true); - QuicPacketNumber unacked[] = {1, 2}; + uint64_t unacked[] = {1, 2}; VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked)); VerifyInFlightPackets(unacked, QUIC_ARRAYSIZE(unacked)); - QuicPacketNumber retransmittable[] = {1, 2}; + uint64_t retransmittable[] = {1, 2}; VerifyRetransmittablePackets(retransmittable, QUIC_ARRAYSIZE(retransmittable)); // Early retransmit 1 as 3 and send new data as 4. - unacked_packets_.IncreaseLargestAcked(2); - unacked_packets_.RemoveFromInFlight(2); - unacked_packets_.RemoveRetransmittability(2); - unacked_packets_.RemoveFromInFlight(1); + unacked_packets_.IncreaseLargestAcked(QuicPacketNumber(2)); + unacked_packets_.RemoveFromInFlight(QuicPacketNumber(2)); + unacked_packets_.RemoveRetransmittability(QuicPacketNumber(2)); + unacked_packets_.RemoveFromInFlight(QuicPacketNumber(1)); RetransmitAndSendPacket(1, 3, LOSS_RETRANSMISSION); SerializedPacket packet4(CreateRetransmittablePacket(4)); - unacked_packets_.AddSentPacket(&packet4, 0, NOT_RETRANSMISSION, now_, true); + unacked_packets_.AddSentPacket(&packet4, QuicPacketNumber(), + NOT_RETRANSMISSION, now_, true); - QuicPacketNumber unacked2[] = {1, 3, 4}; + uint64_t unacked2[] = {1, 3, 4}; VerifyUnackedPackets(unacked2, QUIC_ARRAYSIZE(unacked2)); - QuicPacketNumber pending2[] = {3, 4}; + uint64_t pending2[] = {3, 4}; VerifyInFlightPackets(pending2, QUIC_ARRAYSIZE(pending2)); - std::vector<QuicPacketNumber> retransmittable2; + std::vector<uint64_t> retransmittable2; if (unacked_packets_.session_decides_what_to_write()) { retransmittable2 = {1, 3, 4}; } else { @@ -360,15 +379,16 @@ VerifyRetransmittablePackets(&retransmittable2[0], retransmittable2.size()); // Early retransmit 3 (formerly 1) as 5, and remove 1 from unacked. - unacked_packets_.IncreaseLargestAcked(4); - unacked_packets_.RemoveFromInFlight(4); - unacked_packets_.RemoveRetransmittability(4); + unacked_packets_.IncreaseLargestAcked(QuicPacketNumber(4)); + unacked_packets_.RemoveFromInFlight(QuicPacketNumber(4)); + unacked_packets_.RemoveRetransmittability(QuicPacketNumber(4)); RetransmitAndSendPacket(3, 5, LOSS_RETRANSMISSION); SerializedPacket packet6(CreateRetransmittablePacket(6)); - unacked_packets_.AddSentPacket(&packet6, 0, NOT_RETRANSMISSION, now_, true); + unacked_packets_.AddSentPacket(&packet6, QuicPacketNumber(), + NOT_RETRANSMISSION, now_, true); - std::vector<QuicPacketNumber> unacked3; - std::vector<QuicPacketNumber> retransmittable3; + std::vector<uint64_t> unacked3; + std::vector<uint64_t> retransmittable3; if (unacked_packets_.session_decides_what_to_write()) { unacked3 = {3, 5, 6}; retransmittable3 = {3, 5, 6}; @@ -378,17 +398,17 @@ } VerifyUnackedPackets(&unacked3[0], unacked3.size()); VerifyRetransmittablePackets(&retransmittable3[0], retransmittable3.size()); - QuicPacketNumber pending3[] = {3, 5, 6}; + uint64_t pending3[] = {3, 5, 6}; VerifyInFlightPackets(pending3, QUIC_ARRAYSIZE(pending3)); // Early retransmit 5 as 7 and ensure in flight packet 3 is not removed. - unacked_packets_.IncreaseLargestAcked(6); - unacked_packets_.RemoveFromInFlight(6); - unacked_packets_.RemoveRetransmittability(6); + unacked_packets_.IncreaseLargestAcked(QuicPacketNumber(6)); + unacked_packets_.RemoveFromInFlight(QuicPacketNumber(6)); + unacked_packets_.RemoveRetransmittability(QuicPacketNumber(6)); RetransmitAndSendPacket(5, 7, LOSS_RETRANSMISSION); - std::vector<QuicPacketNumber> unacked4; - std::vector<QuicPacketNumber> retransmittable4; + std::vector<uint64_t> unacked4; + std::vector<uint64_t> retransmittable4; if (unacked_packets_.session_decides_what_to_write()) { unacked4 = {3, 5, 7}; retransmittable4 = {3, 5, 7}; @@ -398,42 +418,44 @@ } VerifyUnackedPackets(&unacked4[0], unacked4.size()); VerifyRetransmittablePackets(&retransmittable4[0], retransmittable4.size()); - QuicPacketNumber pending4[] = {3, 5, 7}; + uint64_t pending4[] = {3, 5, 7}; VerifyInFlightPackets(pending4, QUIC_ARRAYSIZE(pending4)); // Remove the older two transmissions from in flight. - unacked_packets_.RemoveFromInFlight(3); - unacked_packets_.RemoveFromInFlight(5); - QuicPacketNumber pending5[] = {7}; + unacked_packets_.RemoveFromInFlight(QuicPacketNumber(3)); + unacked_packets_.RemoveFromInFlight(QuicPacketNumber(5)); + uint64_t pending5[] = {7}; VerifyInFlightPackets(pending5, QUIC_ARRAYSIZE(pending5)); } TEST_P(QuicUnackedPacketMapTest, RetransmitFourTimes) { // Simulate a retransmittable packet being sent and retransmitted twice. SerializedPacket packet1(CreateRetransmittablePacket(1)); - unacked_packets_.AddSentPacket(&packet1, 0, NOT_RETRANSMISSION, now_, true); + unacked_packets_.AddSentPacket(&packet1, QuicPacketNumber(), + NOT_RETRANSMISSION, now_, true); SerializedPacket packet2(CreateRetransmittablePacket(2)); - unacked_packets_.AddSentPacket(&packet2, 0, NOT_RETRANSMISSION, now_, true); + unacked_packets_.AddSentPacket(&packet2, QuicPacketNumber(), + NOT_RETRANSMISSION, now_, true); - QuicPacketNumber unacked[] = {1, 2}; + uint64_t unacked[] = {1, 2}; VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked)); VerifyInFlightPackets(unacked, QUIC_ARRAYSIZE(unacked)); - QuicPacketNumber retransmittable[] = {1, 2}; + uint64_t retransmittable[] = {1, 2}; VerifyRetransmittablePackets(retransmittable, QUIC_ARRAYSIZE(retransmittable)); // Early retransmit 1 as 3. - unacked_packets_.IncreaseLargestAcked(2); - unacked_packets_.RemoveFromInFlight(2); - unacked_packets_.RemoveRetransmittability(2); - unacked_packets_.RemoveFromInFlight(1); + unacked_packets_.IncreaseLargestAcked(QuicPacketNumber(2)); + unacked_packets_.RemoveFromInFlight(QuicPacketNumber(2)); + unacked_packets_.RemoveRetransmittability(QuicPacketNumber(2)); + unacked_packets_.RemoveFromInFlight(QuicPacketNumber(1)); RetransmitAndSendPacket(1, 3, LOSS_RETRANSMISSION); - QuicPacketNumber unacked2[] = {1, 3}; + uint64_t unacked2[] = {1, 3}; VerifyUnackedPackets(unacked2, QUIC_ARRAYSIZE(unacked2)); - QuicPacketNumber pending2[] = {3}; + uint64_t pending2[] = {3}; VerifyInFlightPackets(pending2, QUIC_ARRAYSIZE(pending2)); - std::vector<QuicPacketNumber> retransmittable2; + std::vector<uint64_t> retransmittable2; if (unacked_packets_.session_decides_what_to_write()) { retransmittable2 = {1, 3}; } else { @@ -444,13 +466,14 @@ // TLP 3 (formerly 1) as 4, and don't remove 1 from unacked. RetransmitAndSendPacket(3, 4, TLP_RETRANSMISSION); SerializedPacket packet5(CreateRetransmittablePacket(5)); - unacked_packets_.AddSentPacket(&packet5, 0, NOT_RETRANSMISSION, now_, true); + unacked_packets_.AddSentPacket(&packet5, QuicPacketNumber(), + NOT_RETRANSMISSION, now_, true); - QuicPacketNumber unacked3[] = {1, 3, 4, 5}; + uint64_t unacked3[] = {1, 3, 4, 5}; VerifyUnackedPackets(unacked3, QUIC_ARRAYSIZE(unacked3)); - QuicPacketNumber pending3[] = {3, 4, 5}; + uint64_t pending3[] = {3, 4, 5}; VerifyInFlightPackets(pending3, QUIC_ARRAYSIZE(pending3)); - std::vector<QuicPacketNumber> retransmittable3; + std::vector<uint64_t> retransmittable3; if (unacked_packets_.session_decides_what_to_write()) { retransmittable3 = {1, 3, 4, 5}; } else { @@ -459,23 +482,23 @@ VerifyRetransmittablePackets(&retransmittable3[0], retransmittable3.size()); // Early retransmit 4 as 6 and ensure in flight packet 3 is removed. - unacked_packets_.IncreaseLargestAcked(5); - unacked_packets_.RemoveFromInFlight(5); - unacked_packets_.RemoveRetransmittability(5); - unacked_packets_.RemoveFromInFlight(3); - unacked_packets_.RemoveFromInFlight(4); + unacked_packets_.IncreaseLargestAcked(QuicPacketNumber(5)); + unacked_packets_.RemoveFromInFlight(QuicPacketNumber(5)); + unacked_packets_.RemoveRetransmittability(QuicPacketNumber(5)); + unacked_packets_.RemoveFromInFlight(QuicPacketNumber(3)); + unacked_packets_.RemoveFromInFlight(QuicPacketNumber(4)); RetransmitAndSendPacket(4, 6, LOSS_RETRANSMISSION); - std::vector<QuicPacketNumber> unacked4; + std::vector<uint64_t> unacked4; if (unacked_packets_.session_decides_what_to_write()) { unacked4 = {4, 6}; } else { unacked4 = {4, 6}; } VerifyUnackedPackets(&unacked4[0], unacked4.size()); - QuicPacketNumber pending4[] = {6}; + uint64_t pending4[] = {6}; VerifyInFlightPackets(pending4, QUIC_ARRAYSIZE(pending4)); - std::vector<QuicPacketNumber> retransmittable4; + std::vector<uint64_t> retransmittable4; if (unacked_packets_.session_decides_what_to_write()) { retransmittable4 = {4, 6}; } else { @@ -488,18 +511,20 @@ // Simulate a retransmittable packet being sent, retransmitted, and the first // transmission being acked. SerializedPacket packet1(CreateRetransmittablePacket(1)); - unacked_packets_.AddSentPacket(&packet1, 0, NOT_RETRANSMISSION, now_, true); + unacked_packets_.AddSentPacket(&packet1, QuicPacketNumber(), + NOT_RETRANSMISSION, now_, true); SerializedPacket packet3(CreateRetransmittablePacket(3)); - unacked_packets_.AddSentPacket(&packet3, 0, NOT_RETRANSMISSION, now_, true); + unacked_packets_.AddSentPacket(&packet3, QuicPacketNumber(), + NOT_RETRANSMISSION, now_, true); RetransmitAndSendPacket(3, 5, LOSS_RETRANSMISSION); - EXPECT_EQ(1u, unacked_packets_.GetLeastUnacked()); - EXPECT_TRUE(unacked_packets_.IsUnacked(1)); - EXPECT_FALSE(unacked_packets_.IsUnacked(2)); - EXPECT_TRUE(unacked_packets_.IsUnacked(3)); - EXPECT_FALSE(unacked_packets_.IsUnacked(4)); - EXPECT_TRUE(unacked_packets_.IsUnacked(5)); - EXPECT_EQ(5u, unacked_packets_.largest_sent_packet()); + EXPECT_EQ(QuicPacketNumber(1u), unacked_packets_.GetLeastUnacked()); + EXPECT_TRUE(unacked_packets_.IsUnacked(QuicPacketNumber(1))); + EXPECT_FALSE(unacked_packets_.IsUnacked(QuicPacketNumber(2))); + EXPECT_TRUE(unacked_packets_.IsUnacked(QuicPacketNumber(3))); + EXPECT_FALSE(unacked_packets_.IsUnacked(QuicPacketNumber(4))); + EXPECT_TRUE(unacked_packets_.IsUnacked(QuicPacketNumber(5))); + EXPECT_EQ(QuicPacketNumber(5u), unacked_packets_.largest_sent_packet()); } TEST_P(QuicUnackedPacketMapTest, AggregateContiguousAckedStreamFrames) {
diff --git a/quic/core/quic_utils.cc b/quic/core/quic_utils.cc index a08328c..be6eeea 100644 --- a/quic/core/quic_utils.cc +++ b/quic/core/quic_utils.cc
@@ -443,6 +443,37 @@ QUIC_ARRAYSIZE(connection_id_bytes)); } +// static +bool QuicUtils::VariableLengthConnectionIdAllowedForVersion( + QuicTransportVersion version) { + // TODO(dschinazi): Allow in appropriate version when supported. + return false; +} + +// static +QuicConnectionId QuicUtils::CreateZeroConnectionId( + QuicTransportVersion version) { + if (!QuicConnectionIdSupportsVariableLength(Perspective::IS_SERVER) || + !QuicConnectionIdSupportsVariableLength(Perspective::IS_CLIENT)) { + return QuicConnectionIdFromUInt64(0); + } + if (!VariableLengthConnectionIdAllowedForVersion(version)) { + char connection_id_bytes[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + return QuicConnectionId(static_cast<char*>(connection_id_bytes), + QUIC_ARRAYSIZE(connection_id_bytes)); + } + return EmptyQuicConnectionId(); +} + +// static +bool QuicUtils::IsConnectionIdValidForVersion(QuicConnectionId connection_id, + QuicTransportVersion version) { + if (VariableLengthConnectionIdAllowedForVersion(version)) { + return true; + } + return connection_id.length() == kQuicDefaultConnectionIdLength; +} + QuicUint128 QuicUtils::GenerateStatelessResetToken( QuicConnectionId connection_id) { if (!QuicConnectionIdUseNetworkByteOrder()) {
diff --git a/quic/core/quic_utils.h b/quic/core/quic_utils.h index 114465e..111080a 100644 --- a/quic/core/quic_utils.h +++ b/quic/core/quic_utils.h
@@ -151,6 +151,19 @@ static QuicConnectionId CreateRandomConnectionId(QuicRandom* random, Perspective perspective); + // Returns true if the QUIC version allows variable length connection IDs. + static bool VariableLengthConnectionIdAllowedForVersion( + QuicTransportVersion version); + + // Returns true if the connection ID is valid for this QUIC version. + static bool IsConnectionIdValidForVersion(QuicConnectionId connection_id, + QuicTransportVersion version); + + // Returns a connection ID suitable for QUIC use-cases that do not need the + // connection ID for multiplexing. If the version allows variable lengths, + // a connection of length zero is returned, otherwise 64bits set to zero. + static QuicConnectionId CreateZeroConnectionId(QuicTransportVersion version); + // Generates a 128bit stateless reset token based on a connection ID. static QuicUint128 GenerateStatelessResetToken( QuicConnectionId connection_id);
diff --git a/quic/core/quic_utils_test.cc b/quic/core/quic_utils_test.cc index d725e72..d1b5268 100644 --- a/quic/core/quic_utils_test.cc +++ b/quic/core/quic_utils_test.cc
@@ -183,6 +183,23 @@ EXPECT_NE(connection_id, TestConnectionId(1)); } +TEST_F(QuicUtilsTest, VariableLengthConnectionId) { + EXPECT_FALSE( + QuicUtils::VariableLengthConnectionIdAllowedForVersion(QUIC_VERSION_35)); + EXPECT_TRUE(QuicUtils::IsConnectionIdValidForVersion( + QuicUtils::CreateZeroConnectionId(QUIC_VERSION_35), QUIC_VERSION_35)); + EXPECT_TRUE(QuicUtils::IsConnectionIdValidForVersion( + QuicUtils::CreateZeroConnectionId(QUIC_VERSION_99), QUIC_VERSION_99)); + if (!QuicConnectionIdSupportsVariableLength(quic::Perspective::IS_SERVER) || + !QuicConnectionIdSupportsVariableLength(quic::Perspective::IS_CLIENT)) { + return; + } + EXPECT_NE(QuicUtils::CreateZeroConnectionId(QUIC_VERSION_35), + EmptyQuicConnectionId()); + EXPECT_FALSE(QuicUtils::IsConnectionIdValidForVersion(EmptyQuicConnectionId(), + QUIC_VERSION_35)); +} + TEST_F(QuicUtilsTest, StatelessResetToken) { QuicConnectionId connection_id1a = test::TestConnectionId(1); QuicConnectionId connection_id1b = test::TestConnectionId(1);
diff --git a/quic/core/quic_version_manager.cc b/quic/core/quic_version_manager.cc index 7d5e3f3..064e932 100644 --- a/quic/core/quic_version_manager.cc +++ b/quic/core/quic_version_manager.cc
@@ -15,6 +15,7 @@ QuicVersionManager::QuicVersionManager( ParsedQuicVersionVector supported_versions) : enable_version_99_(GetQuicReloadableFlag(quic_enable_version_99)), + enable_version_47_(GetQuicReloadableFlag(quic_enable_version_47)), enable_version_46_(GetQuicReloadableFlag(quic_enable_version_46)), enable_version_45_(GetQuicReloadableFlag(quic_enable_version_45)), enable_version_44_(GetQuicReloadableFlag(quic_enable_version_44)), @@ -39,12 +40,14 @@ void QuicVersionManager::MaybeRefilterSupportedVersions() { if (enable_version_99_ != GetQuicReloadableFlag(quic_enable_version_99) || + enable_version_47_ != GetQuicReloadableFlag(quic_enable_version_47) || enable_version_46_ != GetQuicReloadableFlag(quic_enable_version_46) || enable_version_45_ != GetQuicReloadableFlag(quic_enable_version_45) || enable_version_44_ != GetQuicReloadableFlag(quic_enable_version_44) || enable_version_43_ != GetQuicReloadableFlag(quic_enable_version_43) || disable_version_35_ != GetQuicReloadableFlag(quic_disable_version_35)) { enable_version_99_ = GetQuicReloadableFlag(quic_enable_version_99); + enable_version_47_ = GetQuicReloadableFlag(quic_enable_version_47); enable_version_46_ = GetQuicReloadableFlag(quic_enable_version_46); enable_version_45_ = GetQuicReloadableFlag(quic_enable_version_45); enable_version_44_ = GetQuicReloadableFlag(quic_enable_version_44);
diff --git a/quic/core/quic_version_manager.h b/quic/core/quic_version_manager.h index d3b18fe..1196c31 100644 --- a/quic/core/quic_version_manager.h +++ b/quic/core/quic_version_manager.h
@@ -37,6 +37,8 @@ private: // quic_enable_version_99 flag bool enable_version_99_; + // quic_enable_version_47 flag + bool enable_version_47_; // quic_enable_version_46 flag bool enable_version_46_; // quic_enable_version_45 flag
diff --git a/quic/core/quic_version_manager_test.cc b/quic/core/quic_version_manager_test.cc index d70b852..b734b89 100644 --- a/quic/core/quic_version_manager_test.cc +++ b/quic/core/quic_version_manager_test.cc
@@ -16,9 +16,10 @@ class QuicVersionManagerTest : public QuicTest {}; TEST_F(QuicVersionManagerTest, QuicVersionManager) { - static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 7u, + static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 8u, "Supported versions out of sync"); SetQuicReloadableFlag(quic_enable_version_99, false); + SetQuicReloadableFlag(quic_enable_version_47, false); SetQuicReloadableFlag(quic_enable_version_46, false); SetQuicReloadableFlag(quic_enable_version_45, false); SetQuicReloadableFlag(quic_enable_version_44, false); @@ -58,11 +59,18 @@ QUIC_VERSION_39, QUIC_VERSION_35}), manager.GetSupportedTransportVersions()); + SetQuicReloadableFlag(quic_enable_version_47, true); + EXPECT_EQ( + QuicTransportVersionVector( + {QUIC_VERSION_47, QUIC_VERSION_46, QUIC_VERSION_45, QUIC_VERSION_44, + QUIC_VERSION_43, QUIC_VERSION_39, QUIC_VERSION_35}), + manager.GetSupportedTransportVersions()); + SetQuicReloadableFlag(quic_enable_version_99, true); EXPECT_EQ( QuicTransportVersionVector( - {QUIC_VERSION_99, QUIC_VERSION_46, QUIC_VERSION_45, QUIC_VERSION_44, - QUIC_VERSION_43, QUIC_VERSION_39, QUIC_VERSION_35}), + {QUIC_VERSION_99, QUIC_VERSION_47, QUIC_VERSION_46, QUIC_VERSION_45, + QUIC_VERSION_44, QUIC_VERSION_43, QUIC_VERSION_39, QUIC_VERSION_35}), manager.GetSupportedTransportVersions()); // Ensure that all versions are now supported.
diff --git a/quic/core/quic_versions.cc b/quic/core/quic_versions.cc index 7db4254..6f050dd 100644 --- a/quic/core/quic_versions.cc +++ b/quic/core/quic_versions.cc
@@ -66,6 +66,8 @@ return MakeVersionLabel(proto, '0', '4', '5'); case QUIC_VERSION_46: return MakeVersionLabel(proto, '0', '4', '6'); + case QUIC_VERSION_47: + return MakeVersionLabel(proto, '0', '4', '7'); case QUIC_VERSION_99: return MakeVersionLabel(proto, '0', '9', '9'); default: @@ -103,7 +105,7 @@ // Reading from the client so this should not be considered an ERROR. QUIC_DLOG(INFO) << "Unsupported QuicVersionLabel version: " << QuicVersionLabelToString(version_label); - return ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED); + return UnsupportedQuicVersion(); } QuicTransportVersionVector AllSupportedTransportVersions() { @@ -159,6 +161,15 @@ for (ParsedQuicVersion version : versions) { if (version.transport_version == QUIC_VERSION_99) { if (GetQuicReloadableFlag(quic_enable_version_99) && + GetQuicReloadableFlag(quic_enable_version_47) && + GetQuicReloadableFlag(quic_enable_version_46) && + GetQuicReloadableFlag(quic_enable_version_45) && + GetQuicReloadableFlag(quic_enable_version_44) && + GetQuicReloadableFlag(quic_enable_version_43)) { + filtered_versions.push_back(version); + } + } else if (version.transport_version == QUIC_VERSION_47) { + if (GetQuicReloadableFlag(quic_enable_version_47) && GetQuicReloadableFlag(quic_enable_version_46) && GetQuicReloadableFlag(quic_enable_version_45) && GetQuicReloadableFlag(quic_enable_version_44) && @@ -219,8 +230,7 @@ if (index >= 0 && index < version_count) { version.push_back(versions[index]); } else { - version.push_back( - ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED)); + version.push_back(UnsupportedQuicVersion()); } return version; } @@ -286,6 +296,7 @@ RETURN_STRING_LITERAL(QUIC_VERSION_44); RETURN_STRING_LITERAL(QUIC_VERSION_45); RETURN_STRING_LITERAL(QUIC_VERSION_46); + RETURN_STRING_LITERAL(QUIC_VERSION_47); RETURN_STRING_LITERAL(QUIC_VERSION_99); default: return "QUIC_VERSION_UNSUPPORTED"; @@ -327,9 +338,7 @@ } ParsedQuicVersion UnsupportedQuicVersion() { - static const ParsedQuicVersion kUnsupportedQuicVersion( - PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED); - return kUnsupportedQuicVersion; + return ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED); } #undef RETURN_STRING_LITERAL // undef for jumbo builds
diff --git a/quic/core/quic_versions.h b/quic/core/quic_versions.h index 2f780ab..2c3ba1f 100644 --- a/quic/core/quic_versions.h +++ b/quic/core/quic_versions.h
@@ -102,6 +102,8 @@ QUIC_VERSION_44 = 44, // Use IETF header format. QUIC_VERSION_45 = 45, // Added MESSAGE frame. QUIC_VERSION_46 = 46, // Use CRYPTO frames for QuicCryptoStreams. + QUIC_VERSION_47 = 47, // Use IETF draft-17 header format with demultiplexing + // bit. QUIC_VERSION_99 = 99, // Dumping ground for IETF QUIC changes which are not // yet ready for production. }; @@ -164,8 +166,8 @@ // // See go/new-quic-version for more details on how to roll out new versions. static const QuicTransportVersion kSupportedTransportVersions[] = { - QUIC_VERSION_99, QUIC_VERSION_46, QUIC_VERSION_45, QUIC_VERSION_44, - QUIC_VERSION_43, QUIC_VERSION_39, QUIC_VERSION_35}; + QUIC_VERSION_99, QUIC_VERSION_47, QUIC_VERSION_46, QUIC_VERSION_45, + QUIC_VERSION_44, QUIC_VERSION_43, QUIC_VERSION_39, QUIC_VERSION_35}; // This vector contains all crypto handshake protocols that are supported. static const HandshakeProtocol kSupportedHandshakeProtocols[] = { @@ -206,8 +208,7 @@ VersionOfIndex(const QuicTransportVersionVector& versions, int index); // Returns QUIC version of |index| in result of |versions|. Returns -// ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED) if |index| -// is out of bounds. +// UnsupportedQuicVersion() if |index| is out of bounds. QUIC_EXPORT_PRIVATE ParsedQuicVersionVector ParsedVersionOfIndex(const ParsedQuicVersionVector& versions, int index);
diff --git a/quic/core/quic_versions_test.cc b/quic/core/quic_versions_test.cc index e9e1854..a0f664e 100644 --- a/quic/core/quic_versions_test.cc +++ b/quic/core/quic_versions_test.cc
@@ -53,8 +53,10 @@ CREATE_QUIC_MOCK_LOG(log); log.StartCapturingLogs(); - EXPECT_QUIC_LOG_CALL_CONTAINS(log, ERROR, - "Unsupported QuicTransportVersion: 0"); + if (QUIC_LOG_ERROR_IS_ON()) { + EXPECT_QUIC_LOG_CALL_CONTAINS(log, ERROR, + "Unsupported QuicTransportVersion: 0"); + } EXPECT_EQ(0u, QuicVersionToQuicVersionLabel(QUIC_VERSION_UNSUPPORTED)); } @@ -90,11 +92,11 @@ TEST_F(QuicVersionsTest, QuicVersionLabelToQuicVersionUnsupported) { CREATE_QUIC_MOCK_LOG(log); -#if QUIC_DLOG_INFO_IS_ON - EXPECT_QUIC_LOG_CALL_CONTAINS(log, INFO, - "Unsupported QuicVersionLabel version: EKAF") - .Times(1); -#endif + if (QUIC_DLOG_INFO_IS_ON()) { + EXPECT_QUIC_LOG_CALL_CONTAINS(log, INFO, + "Unsupported QuicVersionLabel version: EKAF") + .Times(1); + } log.StartCapturingLogs(); EXPECT_EQ(QUIC_VERSION_UNSUPPORTED, @@ -119,11 +121,11 @@ EXPECT_EQ(PROTOCOL_TLS1_3, QuicVersionLabelToHandshakeProtocol(tls_tag)); FLAGS_quic_supports_tls_handshake = false; -#if QUIC_DLOG_INFO_IS_ON - EXPECT_QUIC_LOG_CALL_CONTAINS(log, INFO, - "Unsupported QuicVersionLabel version: T043") - .Times(1); -#endif + if (QUIC_DLOG_INFO_IS_ON()) { + EXPECT_QUIC_LOG_CALL_CONTAINS(log, INFO, + "Unsupported QuicVersionLabel version: T043") + .Times(1); + } EXPECT_EQ(PROTOCOL_UNSUPPORTED, QuicVersionLabelToHandshakeProtocol(tls_tag)); } @@ -140,6 +142,8 @@ ParseQuicVersionLabel(MakeVersionLabel('Q', '0', '4', '5'))); EXPECT_EQ(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_46), ParseQuicVersionLabel(MakeVersionLabel('Q', '0', '4', '6'))); + EXPECT_EQ(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_47), + ParseQuicVersionLabel(MakeVersionLabel('Q', '0', '4', '7'))); // Test a TLS version: FLAGS_quic_supports_tls_handshake = true; @@ -155,20 +159,24 @@ ParseQuicVersionLabel(MakeVersionLabel('T', '0', '4', '5'))); EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_46), ParseQuicVersionLabel(MakeVersionLabel('T', '0', '4', '6'))); + EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_47), + ParseQuicVersionLabel(MakeVersionLabel('T', '0', '4', '7'))); FLAGS_quic_supports_tls_handshake = false; - EXPECT_EQ(ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED), + EXPECT_EQ(UnsupportedQuicVersion(), ParseQuicVersionLabel(MakeVersionLabel('T', '0', '3', '5'))); - EXPECT_EQ(ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED), + EXPECT_EQ(UnsupportedQuicVersion(), ParseQuicVersionLabel(MakeVersionLabel('T', '0', '3', '9'))); - EXPECT_EQ(ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED), + EXPECT_EQ(UnsupportedQuicVersion(), ParseQuicVersionLabel(MakeVersionLabel('T', '0', '4', '3'))); - EXPECT_EQ(ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED), + EXPECT_EQ(UnsupportedQuicVersion(), ParseQuicVersionLabel(MakeVersionLabel('T', '0', '4', '4'))); - EXPECT_EQ(ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED), + EXPECT_EQ(UnsupportedQuicVersion(), ParseQuicVersionLabel(MakeVersionLabel('T', '0', '4', '5'))); - EXPECT_EQ(ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED), + EXPECT_EQ(UnsupportedQuicVersion(), ParseQuicVersionLabel(MakeVersionLabel('T', '0', '4', '6'))); + EXPECT_EQ(UnsupportedQuicVersion(), + ParseQuicVersionLabel(MakeVersionLabel('T', '0', '4', '7'))); } TEST_F(QuicVersionsTest, CreateQuicVersionLabel) { @@ -190,6 +198,9 @@ EXPECT_EQ(MakeVersionLabel('Q', '0', '4', '6'), CreateQuicVersionLabel( ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_46))); + EXPECT_EQ(MakeVersionLabel('Q', '0', '4', '7'), + CreateQuicVersionLabel( + ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_47))); // Test a TLS version: FLAGS_quic_supports_tls_handshake = true; @@ -211,20 +222,25 @@ EXPECT_EQ(MakeVersionLabel('T', '0', '4', '6'), CreateQuicVersionLabel( ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_46))); + EXPECT_EQ(MakeVersionLabel('T', '0', '4', '7'), + CreateQuicVersionLabel( + ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_47))); FLAGS_quic_supports_tls_handshake = false; - EXPECT_EQ(ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED), + EXPECT_EQ(UnsupportedQuicVersion(), ParseQuicVersionLabel(MakeVersionLabel('T', '0', '3', '5'))); - EXPECT_EQ(ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED), + EXPECT_EQ(UnsupportedQuicVersion(), ParseQuicVersionLabel(MakeVersionLabel('T', '0', '3', '9'))); - EXPECT_EQ(ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED), + EXPECT_EQ(UnsupportedQuicVersion(), ParseQuicVersionLabel(MakeVersionLabel('T', '0', '4', '3'))); - EXPECT_EQ(ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED), + EXPECT_EQ(UnsupportedQuicVersion(), ParseQuicVersionLabel(MakeVersionLabel('T', '0', '4', '4'))); - EXPECT_EQ(ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED), + EXPECT_EQ(UnsupportedQuicVersion(), ParseQuicVersionLabel(MakeVersionLabel('T', '0', '4', '5'))); - EXPECT_EQ(ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED), + EXPECT_EQ(UnsupportedQuicVersion(), ParseQuicVersionLabel(MakeVersionLabel('T', '0', '4', '6'))); + EXPECT_EQ(UnsupportedQuicVersion(), + ParseQuicVersionLabel(MakeVersionLabel('T', '0', '4', '7'))); } TEST_F(QuicVersionsTest, QuicVersionLabelToString) { @@ -274,7 +290,7 @@ } TEST_F(QuicVersionsTest, ParsedQuicVersionToString) { - ParsedQuicVersion unsupported(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED); + ParsedQuicVersion unsupported = UnsupportedQuicVersion(); ParsedQuicVersion version35(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_35); EXPECT_EQ("Q035", ParsedQuicVersionToString(version35)); EXPECT_EQ("0", ParsedQuicVersionToString(unsupported)); @@ -313,14 +329,15 @@ 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); ParsedQuicVersionVector parsed_versions; for (QuicTransportVersion version : all_versions) { parsed_versions.push_back(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, version)); } QuicTransportVersionVector expected_versions = { - QUIC_VERSION_99, QUIC_VERSION_46, QUIC_VERSION_45, QUIC_VERSION_44, - QUIC_VERSION_43, QUIC_VERSION_39, QUIC_VERSION_35}; + QUIC_VERSION_99, QUIC_VERSION_47, QUIC_VERSION_46, QUIC_VERSION_45, + QUIC_VERSION_44, QUIC_VERSION_43, QUIC_VERSION_39, QUIC_VERSION_35}; ParsedQuicVersionVector expected_parsed_versions; for (QuicTransportVersion version : expected_versions) { expected_parsed_versions.push_back( @@ -338,6 +355,33 @@ 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, false); + ParsedQuicVersionVector parsed_versions; + for (QuicTransportVersion version : all_versions) { + parsed_versions.push_back(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, version)); + } + QuicTransportVersionVector expected_versions = { + QUIC_VERSION_47, QUIC_VERSION_46, QUIC_VERSION_45, QUIC_VERSION_44, + QUIC_VERSION_43, QUIC_VERSION_39, QUIC_VERSION_35}; + ParsedQuicVersionVector expected_parsed_versions; + for (QuicTransportVersion version : expected_versions) { + expected_parsed_versions.push_back( + ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, version)); + } + + ASSERT_EQ(expected_versions, FilterSupportedTransportVersions(all_versions)); + ASSERT_EQ(expected_parsed_versions, FilterSupportedVersions(parsed_versions)); +} + +TEST_F(QuicVersionsTest, FilterSupportedTransportVersionsNo47) { + QuicTransportVersionVector all_versions = AllSupportedTransportVersions(); + SetQuicReloadableFlag(quic_disable_version_35, 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, false); SetQuicReloadableFlag(quic_enable_version_99, false); ParsedQuicVersionVector parsed_versions; for (QuicTransportVersion version : all_versions) { @@ -363,6 +407,7 @@ SetQuicReloadableFlag(quic_enable_version_44, true); SetQuicReloadableFlag(quic_enable_version_45, true); SetQuicReloadableFlag(quic_enable_version_46, false); + SetQuicReloadableFlag(quic_enable_version_47, false); SetQuicReloadableFlag(quic_enable_version_99, false); ParsedQuicVersionVector parsed_versions; for (QuicTransportVersion version : all_versions) { @@ -388,6 +433,7 @@ SetQuicReloadableFlag(quic_enable_version_44, true); SetQuicReloadableFlag(quic_enable_version_45, false); SetQuicReloadableFlag(quic_enable_version_46, false); + SetQuicReloadableFlag(quic_enable_version_47, false); SetQuicReloadableFlag(quic_enable_version_99, false); ParsedQuicVersionVector parsed_versions; for (QuicTransportVersion version : all_versions) { @@ -412,6 +458,7 @@ SetQuicReloadableFlag(quic_enable_version_44, false); SetQuicReloadableFlag(quic_enable_version_45, false); SetQuicReloadableFlag(quic_enable_version_46, false); + SetQuicReloadableFlag(quic_enable_version_47, false); SetQuicReloadableFlag(quic_enable_version_99, false); ParsedQuicVersionVector parsed_versions; for (QuicTransportVersion version : all_versions) { @@ -436,6 +483,7 @@ SetQuicReloadableFlag(quic_enable_version_44, false); SetQuicReloadableFlag(quic_enable_version_45, false); SetQuicReloadableFlag(quic_enable_version_46, false); + SetQuicReloadableFlag(quic_enable_version_47, false); SetQuicReloadableFlag(quic_enable_version_99, false); ParsedQuicVersionVector parsed_versions; for (QuicTransportVersion version : all_versions) { @@ -460,6 +508,7 @@ SetQuicReloadableFlag(quic_enable_version_44, false); SetQuicReloadableFlag(quic_enable_version_45, false); SetQuicReloadableFlag(quic_enable_version_46, false); + SetQuicReloadableFlag(quic_enable_version_47, false); SetQuicReloadableFlag(quic_enable_version_99, false); ParsedQuicVersionVector parsed_versions; for (QuicTransportVersion version : all_versions) { @@ -495,9 +544,8 @@ if (i >= 0 && i < version_count) { EXPECT_EQ(all_versions[i], ParsedVersionOfIndex(all_versions, i)[0]); } else { - EXPECT_EQ( - ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED), - ParsedVersionOfIndex(all_versions, i)[0]); + EXPECT_EQ(UnsupportedQuicVersion(), + ParsedVersionOfIndex(all_versions, i)[0]); } } } @@ -516,7 +564,7 @@ // yet a typo was made in doing the #defines and it was caught // only in some test far removed from here... Better safe than sorry. TEST_F(QuicVersionsTest, CheckVersionNumbersForTypos) { - static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 7u, + static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 8u, "Supported versions out of sync"); EXPECT_EQ(QUIC_VERSION_35, 35); EXPECT_EQ(QUIC_VERSION_39, 39); @@ -524,6 +572,7 @@ EXPECT_EQ(QUIC_VERSION_44, 44); EXPECT_EQ(QUIC_VERSION_45, 45); EXPECT_EQ(QUIC_VERSION_46, 46); + EXPECT_EQ(QUIC_VERSION_47, 47); EXPECT_EQ(QUIC_VERSION_99, 99); } } // namespace
diff --git a/quic/core/stateless_rejector_test.cc b/quic/core/stateless_rejector_test.cc index 609c6a0..497fe54 100644 --- a/quic/core/stateless_rejector_test.cc +++ b/quic/core/stateless_rejector_test.cc
@@ -52,8 +52,7 @@ // Test various combinations of QUIC version and flag state. struct TestParams { - ParsedQuicVersion version = - ParsedQuicVersion{PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED}; + ParsedQuicVersion version = UnsupportedQuicVersion(); FlagsMode flags; };
diff --git a/quic/core/tls_client_handshaker.cc b/quic/core/tls_client_handshaker.cc index dd52515..5edce8a 100644 --- a/quic/core/tls_client_handshaker.cc +++ b/quic/core/tls_client_handshaker.cc
@@ -65,8 +65,9 @@ bool TlsClientHandshaker::CryptoConnect() { CrypterPair crypters; - CryptoUtils::CreateTlsInitialCrypters(Perspective::IS_CLIENT, - session()->connection_id(), &crypters); + CryptoUtils::CreateTlsInitialCrypters( + Perspective::IS_CLIENT, session()->connection()->transport_version(), + session()->connection_id(), &crypters); session()->connection()->SetEncrypter(ENCRYPTION_NONE, std::move(crypters.encrypter)); session()->connection()->SetDecrypter(ENCRYPTION_NONE,
diff --git a/quic/core/tls_server_handshaker.cc b/quic/core/tls_server_handshaker.cc index f7a3242..a96e406 100644 --- a/quic/core/tls_server_handshaker.cc +++ b/quic/core/tls_server_handshaker.cc
@@ -62,8 +62,9 @@ proof_source_(proof_source), crypto_negotiated_params_(new QuicCryptoNegotiatedParameters) { CrypterPair crypters; - CryptoUtils::CreateTlsInitialCrypters(Perspective::IS_SERVER, - session->connection_id(), &crypters); + CryptoUtils::CreateTlsInitialCrypters( + Perspective::IS_SERVER, session->connection()->transport_version(), + session->connection_id(), &crypters); session->connection()->SetEncrypter(ENCRYPTION_NONE, std::move(crypters.encrypter)); session->connection()->SetDecrypter(ENCRYPTION_NONE,
diff --git a/quic/core/uber_quic_stream_id_manager.cc b/quic/core/uber_quic_stream_id_manager.cc index 7531952..51ea994 100644 --- a/quic/core/uber_quic_stream_id_manager.cc +++ b/quic/core/uber_quic_stream_id_manager.cc
@@ -1,3 +1,7 @@ +// Copyright (c) 2018 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/uber_quic_stream_id_manager.h" #include "net/third_party/quiche/src/quic/core/quic_session.h"
diff --git a/quic/core/uber_quic_stream_id_manager.h b/quic/core/uber_quic_stream_id_manager.h index f07694a..bf5a588 100644 --- a/quic/core/uber_quic_stream_id_manager.h +++ b/quic/core/uber_quic_stream_id_manager.h
@@ -1,3 +1,7 @@ +// Copyright (c) 2018 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_UBER_QUIC_STREAM_ID_MANAGER_H_ #define QUICHE_QUIC_CORE_UBER_QUIC_STREAM_ID_MANAGER_H_
diff --git a/quic/core/uber_quic_stream_id_manager_test.cc b/quic/core/uber_quic_stream_id_manager_test.cc index 258b157..a413a0b 100644 --- a/quic/core/uber_quic_stream_id_manager_test.cc +++ b/quic/core/uber_quic_stream_id_manager_test.cc
@@ -1,3 +1,7 @@ +// Copyright (c) 2018 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/uber_quic_stream_id_manager.h" #include "net/third_party/quiche/src/quic/core/quic_utils.h"
diff --git a/quic/platform/api/quic_cert_utils.h b/quic/platform/api/quic_cert_utils.h new file mode 100644 index 0000000..1c660b5 --- /dev/null +++ b/quic/platform/api/quic_cert_utils.h
@@ -0,0 +1,23 @@ +// Copyright 2016 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_PLATFORM_API_QUIC_CERT_UTILS_H_ +#define QUICHE_QUIC_PLATFORM_API_QUIC_CERT_UTILS_H_ + +#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h" +#include "net/quic/platform/impl/quic_cert_utils_impl.h" + +namespace quic { + +class QuicCertUtils { + public: + static bool ExtractSubjectNameFromDERCert(QuicStringPiece cert, + QuicStringPiece* subject_out) { + return QuicCertUtilsImpl::ExtractSubjectNameFromDERCert(cert, subject_out); + } +}; + +} // namespace quic + +#endif // QUICHE_QUIC_PLATFORM_API_QUIC_CERT_UTILS_H_
diff --git a/quic/platform/api/quic_client_stats.h b/quic/platform/api/quic_client_stats.h index d1a3154..b780ba6 100644 --- a/quic/platform/api/quic_client_stats.h +++ b/quic/platform/api/quic_client_stats.h
@@ -1,3 +1,7 @@ +// Copyright 2018 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_PLATFORM_API_QUIC_CLIENT_STATS_H_ #define QUICHE_QUIC_PLATFORM_API_QUIC_CLIENT_STATS_H_
diff --git a/quic/platform/api/quic_epoll.h b/quic/platform/api/quic_epoll.h new file mode 100644 index 0000000..c289ef4 --- /dev/null +++ b/quic/platform/api/quic_epoll.h
@@ -0,0 +1,15 @@ +#ifndef QUICHE_QUIC_PLATFORM_API_QUIC_EPOLL_H_ +#define QUICHE_QUIC_PLATFORM_API_QUIC_EPOLL_H_ + +#include "net/quic/platform/impl/quic_epoll_impl.h" + +namespace quic { + +using QuicEpollServer = QuicEpollServerImpl; +using QuicEpollEvent = QuicEpollEventImpl; +using QuicEpollAlarmBase = QuicEpollAlarmBaseImpl; +using QuicEpollCallbackInterface = QuicEpollCallbackInterfaceImpl; + +} // namespace quic + +#endif // QUICHE_QUIC_PLATFORM_API_QUIC_EPOLL_H_
diff --git a/quic/platform/api/quic_file_utils.cc b/quic/platform/api/quic_file_utils.cc new file mode 100644 index 0000000..5492b83 --- /dev/null +++ b/quic/platform/api/quic_file_utils.cc
@@ -0,0 +1,22 @@ +// 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/platform/api/quic_file_utils.h" + +#include "net/quic/platform/impl/quic_file_utils_impl.h" + +namespace quic { + +// Traverses the directory |dirname| and retuns all of the files +// it contains. +std::vector<QuicString> ReadFileContents(const QuicString& dirname) { + return ReadFileContentsImpl(dirname); +} + +// Reads the contents of |filename| as a string into |contents|. +void ReadFileContents(QuicStringPiece filename, QuicString* contents) { + ReadFileContentsImpl(filename, contents); +} + +} // namespace quic
diff --git a/quic/platform/api/quic_file_utils.h b/quic/platform/api/quic_file_utils.h index 463af0d..0f270ef 100644 --- a/quic/platform/api/quic_file_utils.h +++ b/quic/platform/api/quic_file_utils.h
@@ -7,22 +7,20 @@ #include <vector> +#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" -#include "net/quic/platform/impl/quic_file_utils_impl.h" namespace quic { // Traverses the directory |dirname| and retuns all of the files // it contains. -std::vector<QuicString> ReadFileContents(const QuicString& dirname) { - return ReadFileContentsImpl(dirname); -} +QUIC_EXPORT_PRIVATE std::vector<QuicString> ReadFileContents( + const QuicString& dirname); // Reads the contents of |filename| as a string into |contents|. -void ReadFileContents(QuicStringPiece filename, QuicString* contents) { - ReadFileContentsImpl(filename, contents); -} +QUIC_EXPORT_PRIVATE void ReadFileContents(QuicStringPiece filename, + QuicString* contents); } // namespace quic
diff --git a/quic/platform/api/quic_goog_cc_sender.h b/quic/platform/api/quic_goog_cc_sender.h deleted file mode 100644 index ba08cb3..0000000 --- a/quic/platform/api/quic_goog_cc_sender.h +++ /dev/null
@@ -1,36 +0,0 @@ -// Copyright (c) 2018 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_PLATFORM_API_QUIC_GOOG_CC_SENDER_H_ -#define QUICHE_QUIC_PLATFORM_API_QUIC_GOOG_CC_SENDER_H_ - -#include "net/third_party/quiche/src/quic/core/congestion_control/rtt_stats.h" -#include "net/third_party/quiche/src/quic/core/congestion_control/send_algorithm_interface.h" -#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h" -#include "net/third_party/quiche/src/quic/core/quic_connection_stats.h" -#include "net/third_party/quiche/src/quic/core/quic_types.h" -#include "net/third_party/quiche/src/quic/core/quic_unacked_packet_map.h" -#include "net/third_party/quiche/src/quic/platform/api/quic_clock.h" -#include "net/quic/platform/impl/quic_goog_cc_sender_impl.h" - -namespace quic { - -// Interface for creating a GoogCC SendAlgorithmInterface. -// TODO(b/122312335): Remove this file. -SendAlgorithmInterface* CreateGoogCcSender( - const QuicClock* clock, - const RttStats* rtt_stats, - const QuicUnackedPacketMap* unacked_packets, - QuicRandom* random, - QuicConnectionStats* stats, - QuicPacketCount initial_congestion_window, - QuicPacketCount max_congestion_window) { - return CreateGoogCcSenderImpl(clock, rtt_stats, unacked_packets, random, - stats, initial_congestion_window, - max_congestion_window); -} - -} // namespace quic - -#endif // QUICHE_QUIC_PLATFORM_API_QUIC_GOOG_CC_SENDER_H_
diff --git a/quic/platform/api/quic_hostname_utils.h b/quic/platform/api/quic_hostname_utils.h index 61958c2..7f2b98a 100644 --- a/quic/platform/api/quic_hostname_utils.h +++ b/quic/platform/api/quic_hostname_utils.h
@@ -5,7 +5,6 @@ #ifndef QUICHE_QUIC_PLATFORM_API_QUIC_HOSTNAME_UTILS_H_ #define QUICHE_QUIC_PLATFORM_API_QUIC_HOSTNAME_UTILS_H_ -#include "base/macros.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"
diff --git a/quic/platform/api/quic_logging.h b/quic/platform/api/quic_logging.h index d8dc682..ba48dc1 100644 --- a/quic/platform/api/quic_logging.h +++ b/quic/platform/api/quic_logging.h
@@ -31,8 +31,9 @@ #define QUIC_PLOG(severity) QUIC_PLOG_IMPL(severity) -#define QUIC_DLOG_INFO_IS_ON QUIC_DLOG_INFO_IS_ON_IMPL -#define QUIC_LOG_INFO_IS_ON QUIC_LOG_INFO_IS_ON_IMPL -#define QUIC_LOG_WARNING_IS_ON QUIC_LOG_WARNING_IS_ON_IMPL +#define QUIC_DLOG_INFO_IS_ON() QUIC_DLOG_INFO_IS_ON_IMPL() +#define QUIC_LOG_INFO_IS_ON() QUIC_LOG_INFO_IS_ON_IMPL() +#define QUIC_LOG_WARNING_IS_ON() QUIC_LOG_WARNING_IS_ON_IMPL() +#define QUIC_LOG_ERROR_IS_ON() QUIC_LOG_ERROR_IS_ON_IMPL() #endif // QUICHE_QUIC_PLATFORM_API_QUIC_LOGGING_H_
diff --git a/quic/platform/api/quic_lru_cache.h b/quic/platform/api/quic_lru_cache.h deleted file mode 100644 index 7789670..0000000 --- a/quic/platform/api/quic_lru_cache.h +++ /dev/null
@@ -1,52 +0,0 @@ -// Copyright (c) 2016 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_PLATFORM_API_QUIC_LRU_CACHE_H_ -#define QUICHE_QUIC_PLATFORM_API_QUIC_LRU_CACHE_H_ - -#include <memory> - -#include "net/quic/platform/impl/quic_lru_cache_impl.h" - -namespace quic { - -// A LRU cache that maps from type Key to Value* in QUIC. -// This cache CANNOT be shared by multiple threads (even with locks) because -// Value* returned by Lookup() can be invalid if the entry is evicted by other -// threads. -template <class K, class V> -class QuicLRUCacheOld { - public: - explicit QuicLRUCacheOld(int64_t total_units) : impl_(total_units) {} - QuicLRUCacheOld(const QuicLRUCacheOld&) = delete; - QuicLRUCacheOld& operator=(const QuicLRUCacheOld&) = delete; - - // Inserts one unit of |key|, |value| pair to the cache. Cache takes ownership - // of inserted |value|. - void Insert(const K& key, std::unique_ptr<V> value) { - impl_.Insert(key, std::move(value)); - } - - // If cache contains an entry for |key|, return a pointer to it. This returned - // value is guaranteed to be valid until Insert or Clear. - // Else return nullptr. - V* Lookup(const K& key) { return impl_.Lookup(key); } - - // Removes all entries from the cache. This method MUST be called before - // destruction. - void Clear() { impl_.Clear(); } - - // Returns maximum size of the cache. - int64_t MaxSize() const { return impl_.MaxSize(); } - - // Returns current size of the cache. - int64_t Size() const { return impl_.Size(); } - - private: - QuicLRUCacheImpl<K, V> impl_; -}; - -} // namespace quic - -#endif // QUICHE_QUIC_PLATFORM_API_QUIC_LRU_CACHE_H_
diff --git a/quic/platform/api/quic_mem_slice_span.h b/quic/platform/api/quic_mem_slice_span.h index 890556b..39436be 100644 --- a/quic/platform/api/quic_mem_slice_span.h +++ b/quic/platform/api/quic_mem_slice_span.h
@@ -6,7 +6,6 @@ #define QUICHE_QUIC_PLATFORM_API_QUIC_MEM_SLICE_SPAN_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/quic/platform/impl/quic_mem_slice_span_impl.h" namespace quic {
diff --git a/quic/platform/api/quic_mutex.h b/quic/platform/api/quic_mutex.h index c57a937..162863a 100644 --- a/quic/platform/api/quic_mutex.h +++ b/quic/platform/api/quic_mutex.h
@@ -5,7 +5,6 @@ #ifndef QUICHE_QUIC_PLATFORM_API_QUIC_MUTEX_H_ #define QUICHE_QUIC_PLATFORM_API_QUIC_MUTEX_H_ -#include "base/macros.h" #include "net/quic/platform/impl/quic_mutex_impl.h" namespace quic {
diff --git a/quic/platform/api/quic_server_stats.h b/quic/platform/api/quic_server_stats.h index d3b49ee..5364844 100644 --- a/quic/platform/api/quic_server_stats.h +++ b/quic/platform/api/quic_server_stats.h
@@ -1,3 +1,7 @@ +// Copyright 2018 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_PLATFORM_API_QUIC_SERVER_STATS_H_ #define QUICHE_QUIC_PLATFORM_API_QUIC_SERVER_STATS_H_
diff --git a/quic/quartc/quartc_factory.cc b/quic/quartc/quartc_factory.cc index bff445f..ee637e5 100644 --- a/quic/quartc/quartc_factory.cc +++ b/quic/quartc/quartc_factory.cc
@@ -35,7 +35,10 @@ SetQuicReloadableFlag(quic_fix_spurious_ack_alarm, true); // Enable version 45+ to enable SendMessage API. + // Enable version 47+ to enable 'quic bit' per draft 17. SetQuicReloadableFlag(quic_enable_version_45, true); + SetQuicReloadableFlag(quic_enable_version_46, true); + SetQuicReloadableFlag(quic_enable_version_47, true); // Fix for inconsistent reporting of crypto handshake. SetQuicReloadableFlag(quic_fix_has_pending_crypto_data, true);
diff --git a/quic/quartc/quartc_interval_counter.h b/quic/quartc/quartc_interval_counter.h index 0597f76..a9b827c 100644 --- a/quic/quartc/quartc_interval_counter.h +++ b/quic/quartc/quartc_interval_counter.h
@@ -1,3 +1,7 @@ +// Copyright (c) 2018 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_QUARTC_QUARTC_INTERVAL_COUNTER_H_ #define QUICHE_QUIC_QUARTC_QUARTC_INTERVAL_COUNTER_H_
diff --git a/quic/quartc/quartc_interval_counter_test.cc b/quic/quartc/quartc_interval_counter_test.cc index c0edccb..9ba14b2 100644 --- a/quic/quartc/quartc_interval_counter_test.cc +++ b/quic/quartc/quartc_interval_counter_test.cc
@@ -1,3 +1,7 @@ +// Copyright (c) 2018 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/quartc/quartc_interval_counter.h" #include "testing/gmock/include/gmock/gmock.h"
diff --git a/quic/quartc/quartc_session.cc b/quic/quartc/quartc_session.cc index ebd7a7d..37d2cbe 100644 --- a/quic/quartc/quartc_session.cc +++ b/quic/quartc/quartc_session.cc
@@ -4,6 +4,7 @@ #include "net/third_party/quiche/src/quic/quartc/quartc_session.h" +#include "net/third_party/quiche/src/quic/core/quic_utils.h" #include "net/third_party/quiche/src/quic/core/tls_client_handshaker.h" #include "net/third_party/quiche/src/quic/core/tls_server_handshaker.h" #include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h" @@ -104,8 +105,9 @@ } // namespace QuicConnectionId QuartcCryptoServerStreamHelper::GenerateConnectionIdForReject( + QuicTransportVersion version, QuicConnectionId connection_id) const { - return EmptyQuicConnectionId(); + return QuicUtils::CreateZeroConnectionId(version); } bool QuartcCryptoServerStreamHelper::CanAcceptClientHello( @@ -142,6 +144,8 @@ std::unique_ptr<ProofVerifier> proof_verifier(new InsecureProofVerifier); quic_crypto_client_config_ = QuicMakeUnique<QuicCryptoClientConfig>( std::move(proof_verifier), TlsClientHandshaker::CreateSslCtx()); + quic_crypto_client_config_->set_pad_inchoate_hello(false); + quic_crypto_client_config_->set_pad_full_hello(false); } else { std::unique_ptr<ProofSource> proof_source(new DummyProofSource); // Generate a random source address token secret. For long-running servers @@ -154,6 +158,29 @@ QuicString(source_address_token_secret, kInputKeyingMaterialLength), helper_->GetRandomGenerator(), std::move(proof_source), KeyExchangeSource::Default(), TlsServerHandshaker::CreateSslCtx()); + + // Effectively disables the anti-amplification measures (we don't need + // them because we use ICE, and we need to disable them because we disable + // padding of crypto packets). + // This multiplier must be large enough so that the crypto handshake packet + // (approx. 300 bytes) multiplied by this multiplier is larger than a fully + // sized packet (currently 1200 bytes). + // 1500 is a bit extreme: if you can imagine sending a 1 byte packet, and + // your largest MTU would be below 1500 bytes, 1500*1 >= + // any_packet_that_you_can_imagine_sending. + // (again, we hardcode packet size to 1200, so we are not dealing with jumbo + // frames). + quic_crypto_server_config_->set_chlo_multiplier(1500); + + // We are sending small client hello, we must not validate its size. + quic_crypto_server_config_->set_validate_chlo_size(false); + + // We run QUIC over ICE, and ICE is verifying remote side with STUN pings. + // We disable source address token validation in order to allow for 0-rtt + // setup (plus source ip addresses are changing even during the connection + // when ICE is used). + quic_crypto_server_config_->set_validate_source_address_token(false); + // Provide server with serialized config string to prove ownership. QuicCryptoServerConfig::ConfigOptions options; // The |message| is used to handle the return value of AddDefaultConfig @@ -161,6 +188,8 @@ std::unique_ptr<CryptoHandshakeMessage> message( quic_crypto_server_config_->AddDefaultConfig( helper_->GetRandomGenerator(), helper_->GetClock(), options)); + quic_crypto_server_config_->set_pad_rej(false); + quic_crypto_server_config_->set_pad_shlo(false); } } @@ -257,12 +286,25 @@ void QuartcSession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) { QuicSession::OnCryptoHandshakeEvent(event); - if (event == HANDSHAKE_CONFIRMED) { - DCHECK(IsEncryptionEstablished()); - DCHECK(IsCryptoHandshakeConfirmed()); + switch (event) { + case ENCRYPTION_FIRST_ESTABLISHED: + case ENCRYPTION_REESTABLISHED: + // 1-rtt setup triggers 'ENCRYPTION_REESTABLISHED' (after REJ, when the + // CHLO is sent). + DCHECK(IsEncryptionEstablished()); + DCHECK(session_delegate_); + session_delegate_->OnConnectionWritable(); + break; + case HANDSHAKE_CONFIRMED: + // On the server, handshake confirmed is the first time when you can start + // writing packets. + DCHECK(IsEncryptionEstablished()); + DCHECK(IsCryptoHandshakeConfirmed()); - DCHECK(session_delegate_); - session_delegate_->OnCryptoHandshakeComplete(); + DCHECK(session_delegate_); + session_delegate_->OnConnectionWritable(); + session_delegate_->OnCryptoHandshakeComplete(); + break; } }
diff --git a/quic/quartc/quartc_session.h b/quic/quartc/quartc_session.h index fbbf111..411c94c 100644 --- a/quic/quartc/quartc_session.h +++ b/quic/quartc/quartc_session.h
@@ -24,6 +24,7 @@ class QuartcCryptoServerStreamHelper : public QuicCryptoServerStream::Helper { public: QuicConnectionId GenerateConnectionIdForReject( + QuicTransportVersion version, QuicConnectionId connection_id) const override; bool CanAcceptClientHello(const CryptoHandshakeMessage& message, @@ -126,9 +127,18 @@ public: virtual ~Delegate() {} - // Called when the crypto handshake is complete. + // Called when the crypto handshake is complete. Crypto handshake on the + // client is only completed _after_ SHLO is received, but we can actually + // start sending media data right after CHLO is sent. virtual void OnCryptoHandshakeComplete() = 0; + // Connection can be writable even before crypto handshake is complete. + // In particular, on the client, we can start sending data after sending + // full CHLO, without waiting for SHLO. This reduces a send delay by 1-rtt. + // + // This may be called multiple times. + virtual void OnConnectionWritable() = 0; + // Called when a new stream is received from the remote endpoint. virtual void OnIncomingStream(QuartcStream* stream) = 0;
diff --git a/quic/quartc/quartc_session_test.cc b/quic/quartc/quartc_session_test.cc index f3e4978..78efa9e 100644 --- a/quic/quartc/quartc_session_test.cc +++ b/quic/quartc/quartc_session_test.cc
@@ -6,11 +6,11 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -#include "net/third_party/quiche/src/quic/core/proto/crypto_server_config.proto.h" #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/tls_client_handshaker.h" #include "net/third_party/quiche/src/quic/core/tls_server_handshaker.h" +#include "net/third_party/quiche/src/quic/platform/api/quic_clock.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_utils.h" #include "net/third_party/quiche/src/quic/platform/api/quic_test.h" @@ -31,18 +31,30 @@ class FakeQuartcSessionDelegate : public QuartcSession::Delegate { public: - explicit FakeQuartcSessionDelegate(QuartcStream::Delegate* stream_delegate) - : stream_delegate_(stream_delegate) {} + explicit FakeQuartcSessionDelegate(QuartcStream::Delegate* stream_delegate, + const QuicClock* clock) + : stream_delegate_(stream_delegate), clock_(clock) {} + + void OnConnectionWritable() override { + LOG(INFO) << "Connection writable!"; + if (!writable_time_.IsInitialized()) { + writable_time_ = clock_->Now(); + } + } + // Called when peers have established forward-secure encryption void OnCryptoHandshakeComplete() override { LOG(INFO) << "Crypto handshake complete!"; + crypto_handshake_time_ = clock_->Now(); } + // Called when connection closes locally, or remotely by peer. void OnConnectionClosed(QuicErrorCode error_code, const QuicString& error_details, ConnectionCloseSource source) override { connected_ = false; } + // Called when an incoming QUIC stream is created. void OnIncomingStream(QuartcStream* quartc_stream) override { last_incoming_stream_ = quartc_stream; @@ -65,12 +77,17 @@ } bool connected() { return connected_; } + QuicTime writable_time() const { return writable_time_; } + QuicTime crypto_handshake_time() const { return crypto_handshake_time_; } private: QuartcStream* last_incoming_stream_; std::vector<QuicString> incoming_messages_; bool connected_ = true; QuartcStream::Delegate* stream_delegate_; + QuicTime writable_time_ = QuicTime::Zero(); + QuicTime crypto_handshake_time_ = QuicTime::Zero(); + const QuicClock* clock_; }; class FakeQuartcStreamDelegate : public QuartcStream::Delegate { @@ -128,11 +145,11 @@ client_stream_delegate_ = QuicMakeUnique<FakeQuartcStreamDelegate>(); client_session_delegate_ = QuicMakeUnique<FakeQuartcSessionDelegate>( - client_stream_delegate_.get()); + client_stream_delegate_.get(), simulator_.GetClock()); server_stream_delegate_ = QuicMakeUnique<FakeQuartcStreamDelegate>(); server_session_delegate_ = QuicMakeUnique<FakeQuartcSessionDelegate>( - server_stream_delegate_.get()); + server_stream_delegate_.get(), simulator_.GetClock()); QuartcFactoryConfig factory_config; factory_config.alarm_factory = simulator_.GetAlarmFactory(); @@ -358,6 +375,29 @@ TestSendLongMessage(); } +TEST_F(QuartcSessionTest, TestCryptoHandshakeCanWriteTriggers) { + CreateClientAndServerSessions(QuartcSessionConfig()); + + StartHandshake(); + + RunTasks(); + + ASSERT_TRUE(client_session_delegate_->writable_time().IsInitialized()); + ASSERT_TRUE( + client_session_delegate_->crypto_handshake_time().IsInitialized()); + // On client, we are writable 1-rtt before crypto handshake is complete. + ASSERT_LT(client_session_delegate_->writable_time(), + client_session_delegate_->crypto_handshake_time()); + + ASSERT_TRUE(server_session_delegate_->writable_time().IsInitialized()); + ASSERT_TRUE( + server_session_delegate_->crypto_handshake_time().IsInitialized()); + // On server, the writable time and crypto handshake are the same. (when SHLO + // is sent). + ASSERT_EQ(server_session_delegate_->writable_time(), + server_session_delegate_->crypto_handshake_time()); +} + TEST_F(QuartcSessionTest, PreSharedKeyHandshake) { CreateClientAndServerSessions(QuartcSessionConfig()); client_peer_->SetPreSharedKey("foo");
diff --git a/quic/quartc/quartc_stream_test.cc b/quic/quartc/quartc_stream_test.cc index f560185..075aca1 100644 --- a/quic/quartc/quartc_stream_test.cc +++ b/quic/quartc/quartc_stream_test.cc
@@ -24,6 +24,7 @@ #include "net/third_party/quiche/src/quic/core/quic_simple_buffer_allocator.h" #include "net/third_party/quiche/src/quic/core/quic_time.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/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_clock.h" @@ -225,9 +226,10 @@ alarm_factory_ = QuicMakeUnique<test::MockAlarmFactory>(); connection_ = QuicMakeUnique<QuicConnection>( - EmptyQuicConnectionId(), QuicSocketAddress(ip, 0), - this /*QuicConnectionHelperInterface*/, alarm_factory_.get(), - new DummyPacketWriter(), owns_writer, perspective, + QuicUtils::CreateZeroConnectionId( + CurrentSupportedVersions()[0].transport_version), + QuicSocketAddress(ip, 0), this /*QuicConnectionHelperInterface*/, + alarm_factory_.get(), new DummyPacketWriter(), owns_writer, perspective, ParsedVersionOfIndex(CurrentSupportedVersions(), 0)); clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1)); session_ = QuicMakeUnique<MockQuicSession>(connection_.get(), QuicConfig(), @@ -589,16 +591,16 @@ EXPECT_EQ("Foo bar", write_buffer_); stream_->OnStreamFrameLost(0, 4, false); - EXPECT_EQ(stream_->BytesPendingRetransmission(), 4); - EXPECT_EQ(mock_stream_delegate_->last_bytes_pending_retransmission(), 4); + EXPECT_EQ(stream_->BytesPendingRetransmission(), 4u); + EXPECT_EQ(mock_stream_delegate_->last_bytes_pending_retransmission(), 4u); stream_->OnStreamFrameLost(4, 3, false); - EXPECT_EQ(stream_->BytesPendingRetransmission(), 7); - EXPECT_EQ(mock_stream_delegate_->last_bytes_pending_retransmission(), 7); + EXPECT_EQ(stream_->BytesPendingRetransmission(), 7u); + EXPECT_EQ(mock_stream_delegate_->last_bytes_pending_retransmission(), 7u); stream_->OnCanWrite(); - EXPECT_EQ(stream_->BytesPendingRetransmission(), 0); - EXPECT_EQ(mock_stream_delegate_->last_bytes_pending_retransmission(), 0); + EXPECT_EQ(stream_->BytesPendingRetransmission(), 0u); + EXPECT_EQ(mock_stream_delegate_->last_bytes_pending_retransmission(), 0u); EXPECT_EQ("Foo barFoo bar", write_buffer_); EXPECT_EQ(stream_->stream_error(), QUIC_STREAM_NO_ERROR); @@ -615,16 +617,16 @@ EXPECT_EQ("Foo bar", write_buffer_); stream_->OnStreamFrameLost(0, 4, false); - EXPECT_EQ(stream_->BytesPendingRetransmission(), 0); - EXPECT_EQ(mock_stream_delegate_->last_bytes_pending_retransmission(), 0); + EXPECT_EQ(stream_->BytesPendingRetransmission(), 0u); + EXPECT_EQ(mock_stream_delegate_->last_bytes_pending_retransmission(), 0u); stream_->OnStreamFrameLost(4, 3, false); - EXPECT_EQ(stream_->BytesPendingRetransmission(), 0); - EXPECT_EQ(mock_stream_delegate_->last_bytes_pending_retransmission(), 0); + EXPECT_EQ(stream_->BytesPendingRetransmission(), 0u); + EXPECT_EQ(mock_stream_delegate_->last_bytes_pending_retransmission(), 0u); stream_->OnCanWrite(); - EXPECT_EQ(stream_->BytesPendingRetransmission(), 0); - EXPECT_EQ(mock_stream_delegate_->last_bytes_pending_retransmission(), 0); + EXPECT_EQ(stream_->BytesPendingRetransmission(), 0u); + EXPECT_EQ(mock_stream_delegate_->last_bytes_pending_retransmission(), 0u); EXPECT_EQ("Foo bar", write_buffer_); EXPECT_EQ(stream_->stream_error(), QUIC_STREAM_CANCELLED);
diff --git a/quic/test_tools/crypto_test_utils.cc b/quic/test_tools/crypto_test_utils.cc index 1f14306..fd270c3 100644 --- a/quic/test_tools/crypto_test_utils.cc +++ b/quic/test_tools/crypto_test_utils.cc
@@ -407,7 +407,7 @@ testing::_, testing::_)) .Times(testing::AnyNumber()); EXPECT_CALL(*server_session.helper(), - GenerateConnectionIdForReject(testing::_)) + GenerateConnectionIdForReject(testing::_, testing::_)) .Times(testing::AnyNumber()); EXPECT_CALL(*server_conn, OnCanWrite()).Times(testing::AnyNumber()); EXPECT_CALL(*client_conn, OnCanWrite()).Times(testing::AnyNumber()); @@ -783,8 +783,6 @@ EXPECT_TRUE(server->ExportKeyingMaterial(kSampleLabel, kSampleContext, kSampleOutputLength, &server_key_extraction)); - EXPECT_TRUE(client->ExportTokenBindingKeyingMaterial(&client_tb_ekm)); - EXPECT_TRUE(server->ExportTokenBindingKeyingMaterial(&server_tb_ekm)); CompareCharArraysWithHexError("client write key", client_encrypter_key.data(), client_encrypter_key.length(), @@ -1002,11 +1000,8 @@ QuicStringPiece orbit; CHECK(msg->GetStringPiece(kORBT, &orbit)); QuicString nonce; - CryptoUtils::GenerateNonce( - clock->WallNow(), QuicRandom::GetInstance(), - QuicStringPiece(reinterpret_cast<const char*>(orbit.data()), - sizeof(static_cast<int64>(orbit.size()))), - &nonce); + CryptoUtils::GenerateNonce(clock->WallNow(), QuicRandom::GetInstance(), orbit, + &nonce); return ("#" + QuicTextUtils::HexEncode(nonce)); }
diff --git a/quic/test_tools/crypto_test_utils_test.cc b/quic/test_tools/crypto_test_utils_test.cc index c6be73a..601103c 100644 --- a/quic/test_tools/crypto_test_utils_test.cc +++ b/quic/test_tools/crypto_test_utils_test.cc
@@ -135,11 +135,8 @@ QuicStringPiece orbit; ASSERT_TRUE(msg->GetStringPiece(kORBT, &orbit)); QuicString nonce; - CryptoUtils::GenerateNonce( - clock.WallNow(), QuicRandom::GetInstance(), - QuicStringPiece(reinterpret_cast<const char*>(orbit.data()), - sizeof(static_cast<int64>(orbit.size()))), - &nonce); + CryptoUtils::GenerateNonce(clock.WallNow(), QuicRandom::GetInstance(), orbit, + &nonce); QuicString nonce_hex = "#" + QuicTextUtils::HexEncode(nonce); char public_value[32];
diff --git a/quic/test_tools/limited_mtu_test_writer.cc b/quic/test_tools/limited_mtu_test_writer.cc index cd9be17..bc71c7c 100644 --- a/quic/test_tools/limited_mtu_test_writer.cc +++ b/quic/test_tools/limited_mtu_test_writer.cc
@@ -9,7 +9,7 @@ LimitedMtuTestWriter::LimitedMtuTestWriter(QuicByteCount mtu) : mtu_(mtu) {} -LimitedMtuTestWriter::~LimitedMtuTestWriter() {} +LimitedMtuTestWriter::~LimitedMtuTestWriter() = default; WriteResult LimitedMtuTestWriter::WritePacket( const char* buffer,
diff --git a/quic/test_tools/mock_quic_session_visitor.cc b/quic/test_tools/mock_quic_session_visitor.cc index e8d2b66..fea8414 100644 --- a/quic/test_tools/mock_quic_session_visitor.cc +++ b/quic/test_tools/mock_quic_session_visitor.cc
@@ -7,13 +7,13 @@ namespace quic { namespace test { -MockQuicSessionVisitor::MockQuicSessionVisitor() {} +MockQuicSessionVisitor::MockQuicSessionVisitor() = default; -MockQuicSessionVisitor::~MockQuicSessionVisitor() {} +MockQuicSessionVisitor::~MockQuicSessionVisitor() = default; -MockQuicCryptoServerStreamHelper::MockQuicCryptoServerStreamHelper() {} +MockQuicCryptoServerStreamHelper::MockQuicCryptoServerStreamHelper() = default; -MockQuicCryptoServerStreamHelper::~MockQuicCryptoServerStreamHelper() {} +MockQuicCryptoServerStreamHelper::~MockQuicCryptoServerStreamHelper() = default; } // namespace test } // namespace quic
diff --git a/quic/test_tools/mock_quic_session_visitor.h b/quic/test_tools/mock_quic_session_visitor.h index a75a852..fb01da6 100644 --- a/quic/test_tools/mock_quic_session_visitor.h +++ b/quic/test_tools/mock_quic_session_visitor.h
@@ -27,6 +27,7 @@ MOCK_METHOD1(OnWriteBlocked, void(QuicBlockedWriterInterface* blocked_writer)); MOCK_METHOD1(OnRstStreamReceived, void(const QuicRstStreamFrame& frame)); + MOCK_METHOD1(OnStopSendingReceived, void(const QuicStopSendingFrame& frame)); MOCK_METHOD1(OnConnectionAddedToTimeWaitList, void(QuicConnectionId connection_id)); }; @@ -39,8 +40,9 @@ MockQuicCryptoServerStreamHelper& operator=( const MockQuicCryptoServerStreamHelper&) = delete; ~MockQuicCryptoServerStreamHelper() override; - MOCK_CONST_METHOD1(GenerateConnectionIdForReject, - QuicConnectionId(QuicConnectionId connection_id)); + MOCK_CONST_METHOD2(GenerateConnectionIdForReject, + QuicConnectionId(QuicTransportVersion version, + QuicConnectionId connection_id)); MOCK_CONST_METHOD5(CanAcceptClientHello, bool(const CryptoHandshakeMessage& message, const QuicSocketAddress& client_address,
diff --git a/quic/test_tools/mock_quic_time_wait_list_manager.cc b/quic/test_tools/mock_quic_time_wait_list_manager.cc index bf3d075..ec63558 100644 --- a/quic/test_tools/mock_quic_time_wait_list_manager.cc +++ b/quic/test_tools/mock_quic_time_wait_list_manager.cc
@@ -26,7 +26,7 @@ QuicTimeWaitListManager_AddConnectionIdToTimeWait)); } -MockTimeWaitListManager::~MockTimeWaitListManager() {} +MockTimeWaitListManager::~MockTimeWaitListManager() = default; } // namespace test } // namespace quic
diff --git a/quic/test_tools/mock_random.cc b/quic/test_tools/mock_random.cc index 683e504..a01a5a7 100644 --- a/quic/test_tools/mock_random.cc +++ b/quic/test_tools/mock_random.cc
@@ -4,6 +4,8 @@ #include "net/third_party/quiche/src/quic/test_tools/mock_random.h" +#include <string.h> + namespace quic { namespace test {
diff --git a/quic/test_tools/packet_dropping_test_writer.cc b/quic/test_tools/packet_dropping_test_writer.cc index 51d8fed..d296367 100644 --- a/quic/test_tools/packet_dropping_test_writer.cc +++ b/quic/test_tools/packet_dropping_test_writer.cc
@@ -15,7 +15,7 @@ // An alarm that is scheduled if a blocked socket is simulated to indicate // it's writable again. -class WriteUnblockedAlarm : public quic::QuicAlarm::Delegate { +class WriteUnblockedAlarm : public QuicAlarm::Delegate { public: explicit WriteUnblockedAlarm(PacketDroppingTestWriter* writer) : writer_(writer) {} @@ -31,7 +31,7 @@ // An alarm that is scheduled every time a new packet is to be written at a // later point. -class DelayAlarm : public quic::QuicAlarm::Delegate { +class DelayAlarm : public QuicAlarm::Delegate { public: explicit DelayAlarm(PacketDroppingTestWriter* writer) : writer_(writer) {} @@ -58,12 +58,12 @@ fake_bandwidth_(QuicBandwidth::Zero()), buffer_size_(0), num_consecutive_packet_lost_(0) { - uint32_t seed = RandomBase::WeakSeed32(); + uint64_t seed = QuicRandom::GetInstance()->RandUint64(); QUIC_LOG(INFO) << "Seeding packet loss with " << seed; simple_random_.set_seed(seed); } -PacketDroppingTestWriter::~PacketDroppingTestWriter() {} +PacketDroppingTestWriter::~PacketDroppingTestWriter() = default; void PacketDroppingTestWriter::Initialize( QuicConnectionHelperInterface* helper,
diff --git a/quic/test_tools/packet_dropping_test_writer.h b/quic/test_tools/packet_dropping_test_writer.h index ae1df42..404be81 100644 --- a/quic/test_tools/packet_dropping_test_writer.h +++ b/quic/test_tools/packet_dropping_test_writer.h
@@ -16,7 +16,6 @@ #include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h" namespace quic { - namespace test { // Simulates a connection that drops packets a configured percentage of the time @@ -143,17 +142,17 @@ ~DelayedWrite(); QuicString buffer; - const QuicIpAddress self_address; - const QuicSocketAddress peer_address; + QuicIpAddress self_address; + QuicSocketAddress peer_address; std::unique_ptr<PerPacketOptions> options; QuicTime send_time; }; typedef std::list<DelayedWrite> DelayedPacketList; - const quic::QuicClock* clock_; - std::unique_ptr<quic::QuicAlarm> write_unblocked_alarm_; - std::unique_ptr<quic::QuicAlarm> delay_alarm_; + const QuicClock* clock_; + std::unique_ptr<QuicAlarm> write_unblocked_alarm_; + std::unique_ptr<QuicAlarm> delay_alarm_; std::unique_ptr<Delegate> on_can_write_; SimpleRandom simple_random_; // Stored packets delayed by fake packet delay or bandwidth restrictions.
diff --git a/quic/test_tools/quic_client_peer.h b/quic/test_tools/quic_client_peer.h index 934495a..66987e4 100644 --- a/quic/test_tools/quic_client_peer.h +++ b/quic/test_tools/quic_client_peer.h
@@ -10,7 +10,6 @@ namespace quic { class QuicClient; -class QuicCryptoClientConfig; class QuicPacketWriter; namespace test {
diff --git a/quic/test_tools/quic_connection_peer.cc b/quic/test_tools/quic_connection_peer.cc index dde870b..e813c1e 100644 --- a/quic/test_tools/quic_connection_peer.cc +++ b/quic/test_tools/quic_connection_peer.cc
@@ -275,9 +275,8 @@ } // static -bool QuicConnectionPeer::HasRetransmittableFrames( - QuicConnection* connection, - QuicPacketNumber packet_number) { +bool QuicConnectionPeer::HasRetransmittableFrames(QuicConnection* connection, + uint64_t packet_number) { return QuicSentPacketManagerPeer::HasRetransmittableFrames( GetSentPacketManager(connection), packet_number); }
diff --git a/quic/test_tools/quic_connection_peer.h b/quic/test_tools/quic_connection_peer.h index 58bdec9..d58d1d7 100644 --- a/quic/test_tools/quic_connection_peer.h +++ b/quic/test_tools/quic_connection_peer.h
@@ -123,7 +123,7 @@ static void SetAckDecimationDelay(QuicConnection* connection, float ack_decimation_delay); static bool HasRetransmittableFrames(QuicConnection* connection, - QuicPacketNumber packet_number); + uint64_t packet_number); static bool GetNoStopWaitingFrames(QuicConnection* connection); static void SetNoStopWaitingFrames(QuicConnection* connection, bool no_stop_waiting_frames);
diff --git a/quic/test_tools/quic_framer_peer.cc b/quic/test_tools/quic_framer_peer.cc index 6202669..20cbc49 100644 --- a/quic/test_tools/quic_framer_peer.cc +++ b/quic/test_tools/quic_framer_peer.cc
@@ -12,11 +12,11 @@ namespace test { // static -QuicPacketNumber QuicFramerPeer::CalculatePacketNumberFromWire( +uint64_t QuicFramerPeer::CalculatePacketNumberFromWire( QuicFramer* framer, QuicPacketNumberLength packet_number_length, QuicPacketNumber last_packet_number, - QuicPacketNumber packet_number) { + uint64_t packet_number) { return framer->CalculatePacketNumberFromWire( packet_number_length, last_packet_number, packet_number); } @@ -338,5 +338,12 @@ packet_number_length); } +// static +void QuicFramerPeer::SetFirstSendingPacketNumber(QuicFramer* framer, + uint64_t packet_number) { + *const_cast<QuicPacketNumber*>(&framer->first_sending_packet_number_) = + QuicPacketNumber(packet_number); +} + } // namespace test } // namespace quic
diff --git a/quic/test_tools/quic_framer_peer.h b/quic/test_tools/quic_framer_peer.h index 57a05aa..1fa7351 100644 --- a/quic/test_tools/quic_framer_peer.h +++ b/quic/test_tools/quic_framer_peer.h
@@ -18,11 +18,11 @@ public: QuicFramerPeer() = delete; - static QuicPacketNumber CalculatePacketNumberFromWire( + static uint64_t CalculatePacketNumberFromWire( QuicFramer* framer, QuicPacketNumberLength packet_number_length, QuicPacketNumber last_packet_number, - QuicPacketNumber packet_number); + uint64_t packet_number); static void SetLastSerializedConnectionId(QuicFramer* framer, QuicConnectionId connection_id); static void SetLargestPacketNumber(QuicFramer* framer, @@ -161,6 +161,8 @@ const QuicFrame& frame, bool last_frame_in_packet, QuicPacketNumberLength packet_number_length); + static void SetFirstSendingPacketNumber(QuicFramer* framer, + uint64_t packet_number); }; } // namespace test
diff --git a/quic/test_tools/quic_packet_creator_peer.cc b/quic/test_tools/quic_packet_creator_peer.cc index 5168688..efcda92 100644 --- a/quic/test_tools/quic_packet_creator_peer.cc +++ b/quic/test_tools/quic_packet_creator_peer.cc
@@ -44,8 +44,14 @@ } void QuicPacketCreatorPeer::SetPacketNumber(QuicPacketCreator* creator, - QuicPacketNumber s) { - creator->packet_.packet_number = s; + uint64_t s) { + DCHECK_NE(0u, s); + creator->packet_.packet_number = QuicPacketNumber(s); +} + +// static +void QuicPacketCreatorPeer::ClearPacketNumber(QuicPacketCreator* creator) { + creator->packet_.packet_number.Clear(); } // static
diff --git a/quic/test_tools/quic_packet_creator_peer.h b/quic/test_tools/quic_packet_creator_peer.h index add0712..94c461a 100644 --- a/quic/test_tools/quic_packet_creator_peer.h +++ b/quic/test_tools/quic_packet_creator_peer.h
@@ -27,7 +27,8 @@ QuicPacketNumberLength packet_number_length); static QuicPacketNumberLength GetPacketNumberLength( QuicPacketCreator* creator); - static void SetPacketNumber(QuicPacketCreator* creator, QuicPacketNumber s); + static void SetPacketNumber(QuicPacketCreator* creator, uint64_t s); + static void ClearPacketNumber(QuicPacketCreator* creator); static void FillPacketHeader(QuicPacketCreator* creator, QuicPacketHeader* header); static void CreateStreamFrame(QuicPacketCreator* creator,
diff --git a/quic/test_tools/quic_sent_packet_manager_peer.cc b/quic/test_tools/quic_sent_packet_manager_peer.cc index 7699520..469fa40 100644 --- a/quic/test_tools/quic_sent_packet_manager_peer.cc +++ b/quic/test_tools/quic_sent_packet_manager_peer.cc
@@ -85,18 +85,19 @@ // static bool QuicSentPacketManagerPeer::IsRetransmission( QuicSentPacketManager* sent_packet_manager, - QuicPacketNumber packet_number) { + uint64_t packet_number) { DCHECK(HasRetransmittableFrames(sent_packet_manager, packet_number)); if (!HasRetransmittableFrames(sent_packet_manager, packet_number)) { return false; } if (sent_packet_manager->session_decides_what_to_write()) { return sent_packet_manager->unacked_packets_ - .GetTransmissionInfo(packet_number) + .GetTransmissionInfo(QuicPacketNumber(packet_number)) .transmission_type != NOT_RETRANSMISSION; } for (auto transmission_info : sent_packet_manager->unacked_packets_) { - if (transmission_info.retransmission == packet_number) { + if (transmission_info.retransmission.IsInitialized() && + transmission_info.retransmission == QuicPacketNumber(packet_number)) { return true; } } @@ -106,9 +107,10 @@ // static void QuicSentPacketManagerPeer::MarkForRetransmission( QuicSentPacketManager* sent_packet_manager, - QuicPacketNumber packet_number, + uint64_t packet_number, TransmissionType transmission_type) { - sent_packet_manager->MarkForRetransmission(packet_number, transmission_type); + sent_packet_manager->MarkForRetransmission(QuicPacketNumber(packet_number), + transmission_type); } // static @@ -198,16 +200,17 @@ // static bool QuicSentPacketManagerPeer::IsUnacked( QuicSentPacketManager* sent_packet_manager, - QuicPacketNumber packet_number) { - return sent_packet_manager->unacked_packets_.IsUnacked(packet_number); + uint64_t packet_number) { + return sent_packet_manager->unacked_packets_.IsUnacked( + QuicPacketNumber(packet_number)); } // static bool QuicSentPacketManagerPeer::HasRetransmittableFrames( QuicSentPacketManager* sent_packet_manager, - QuicPacketNumber packet_number) { + uint64_t packet_number) { return sent_packet_manager->unacked_packets_.HasRetransmittableFrames( - packet_number); + QuicPacketNumber(packet_number)); } // static
diff --git a/quic/test_tools/quic_sent_packet_manager_peer.h b/quic/test_tools/quic_sent_packet_manager_peer.h index 9f9f6a1..b8ec1d3 100644 --- a/quic/test_tools/quic_sent_packet_manager_peer.h +++ b/quic/test_tools/quic_sent_packet_manager_peer.h
@@ -52,10 +52,10 @@ // Returns true if |packet_number| is a retransmission of a packet. static bool IsRetransmission(QuicSentPacketManager* sent_packet_manager, - QuicPacketNumber packet_number); + uint64_t packet_number); static void MarkForRetransmission(QuicSentPacketManager* sent_packet_manager, - QuicPacketNumber packet_number, + uint64_t packet_number, TransmissionType transmission_type); static QuicTime::Delta GetRetransmissionDelay( @@ -93,11 +93,11 @@ static bool UsingPacing(const QuicSentPacketManager* sent_packet_manager); static bool IsUnacked(QuicSentPacketManager* sent_packet_manager, - QuicPacketNumber packet_number); + uint64_t packet_number); static bool HasRetransmittableFrames( QuicSentPacketManager* sent_packet_manager, - QuicPacketNumber packet_number); + uint64_t packet_number); static QuicUnackedPacketMap* GetUnackedPacketMap( QuicSentPacketManager* sent_packet_manager);
diff --git a/quic/test_tools/quic_session_peer.cc b/quic/test_tools/quic_session_peer.cc index 6bacca9..37e5013 100644 --- a/quic/test_tools/quic_session_peer.cc +++ b/quic/test_tools/quic_session_peer.cc
@@ -184,5 +184,14 @@ return &session->v99_streamid_manager_.unidirectional_stream_id_manager_; } +// static +void QuicSessionPeer::SendRstStreamInner(QuicSession* session, + QuicStreamId id, + QuicRstStreamErrorCode error, + QuicStreamOffset bytes_written, + bool close_write_side_only) { + session->SendRstStreamInner(id, error, bytes_written, close_write_side_only); +} + } // namespace test } // namespace quic
diff --git a/quic/test_tools/quic_session_peer.h b/quic/test_tools/quic_session_peer.h index 917d203..8c2e72c 100644 --- a/quic/test_tools/quic_session_peer.h +++ b/quic/test_tools/quic_session_peer.h
@@ -67,6 +67,11 @@ QuicSession* session); static QuicStreamIdManager* v99_unidirectional_stream_id_manager( QuicSession* session); + static void SendRstStreamInner(QuicSession* session, + QuicStreamId id, + QuicRstStreamErrorCode error, + QuicStreamOffset bytes_written, + bool close_write_side_only); }; } // namespace test
diff --git a/quic/test_tools/quic_stream_id_manager_peer.cc b/quic/test_tools/quic_stream_id_manager_peer.cc index 8bdfd16..705ee27 100644 --- a/quic/test_tools/quic_stream_id_manager_peer.cc +++ b/quic/test_tools/quic_stream_id_manager_peer.cc
@@ -1,3 +1,6 @@ +// Copyright (c) 2018 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/test_tools/quic_stream_id_manager_peer.h" #include "net/third_party/quiche/src/quic/core/quic_stream_id_manager.h"
diff --git a/quic/test_tools/quic_stream_id_manager_peer.h b/quic/test_tools/quic_stream_id_manager_peer.h index 7b42888..2ec07b1 100644 --- a/quic/test_tools/quic_stream_id_manager_peer.h +++ b/quic/test_tools/quic_stream_id_manager_peer.h
@@ -1,7 +1,10 @@ +// Copyright (c) 2018 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_TEST_TOOLS_QUIC_STREAM_ID_MANAGER_PEER_H_ #define QUICHE_QUIC_TEST_TOOLS_QUIC_STREAM_ID_MANAGER_PEER_H_ -#include "base/macros.h" +#include <stddef.h> namespace quic {
diff --git a/quic/test_tools/quic_stream_peer.cc b/quic/test_tools/quic_stream_peer.cc index d5ac1e4..e512ba4 100644 --- a/quic/test_tools/quic_stream_peer.cc +++ b/quic/test_tools/quic_stream_peer.cc
@@ -33,6 +33,11 @@ } // static +bool QuicStreamPeer::write_side_closed(QuicStream* stream) { + return stream->write_side_closed(); +} + +// static void QuicStreamPeer::CloseReadSide(QuicStream* stream) { stream->CloseReadSide(); }
diff --git a/quic/test_tools/quic_stream_peer.h b/quic/test_tools/quic_stream_peer.h index fbbbbb6..e1ba33a 100644 --- a/quic/test_tools/quic_stream_peer.h +++ b/quic/test_tools/quic_stream_peer.h
@@ -27,6 +27,7 @@ static void SetWriteSideClosed(bool value, QuicStream* stream); static void SetStreamBytesWritten(QuicStreamOffset stream_bytes_written, QuicStream* stream); + static bool write_side_closed(QuicStream* stream); static bool read_side_closed(QuicStream* stream); static void CloseReadSide(QuicStream* stream);
diff --git a/quic/test_tools/quic_test_client.cc b/quic/test_tools/quic_test_client.cc index 878ac83..a6298a6 100644 --- a/quic/test_tools/quic_test_client.cc +++ b/quic/test_tools/quic_test_client.cc
@@ -120,7 +120,7 @@ : public QuicClientEpollNetworkHelper { public: using QuicClientEpollNetworkHelper::QuicClientEpollNetworkHelper; - ~MockableQuicClientEpollNetworkHelper() override {} + ~MockableQuicClientEpollNetworkHelper() override = default; void ProcessPacket(const QuicSocketAddress& self_address, const QuicSocketAddress& peer_address, @@ -172,7 +172,7 @@ QuicSocketAddress server_address, const QuicServerId& server_id, const ParsedQuicVersionVector& supported_versions, - gfe2::EpollServer* epoll_server) + QuicEpollServer* epoll_server) : MockableQuicClient(server_address, server_id, QuicConfig(), @@ -184,7 +184,7 @@ const QuicServerId& server_id, const QuicConfig& config, const ParsedQuicVersionVector& supported_versions, - gfe2::EpollServer* epoll_server) + QuicEpollServer* epoll_server) : MockableQuicClient(server_address, server_id, config, @@ -197,7 +197,7 @@ const QuicServerId& server_id, const QuicConfig& config, const ParsedQuicVersionVector& supported_versions, - gfe2::EpollServer* epoll_server, + QuicEpollServer* epoll_server, std::unique_ptr<ProofVerifier> proof_verifier) : QuicClient( server_address, @@ -209,7 +209,8 @@ this), QuicWrapUnique( new RecordingProofVerifier(std::move(proof_verifier)))), - override_connection_id_(EmptyQuicConnectionId()) {} + override_connection_id_(EmptyQuicConnectionId()), + connection_id_overridden_(false) {} MockableQuicClient::~MockableQuicClient() { if (connected()) { @@ -230,12 +231,12 @@ } QuicConnectionId MockableQuicClient::GenerateNewConnectionId() { - return !override_connection_id_.IsEmpty() - ? override_connection_id_ - : QuicClient::GenerateNewConnectionId(); + return connection_id_overridden_ ? override_connection_id_ + : QuicClient::GenerateNewConnectionId(); } void MockableQuicClient::UseConnectionId(QuicConnectionId connection_id) { + connection_id_overridden_ = true; override_connection_id_ = connection_id; } @@ -294,7 +295,7 @@ Initialize(); } -QuicTestClient::QuicTestClient() {} +QuicTestClient::QuicTestClient() = default; QuicTestClient::~QuicTestClient() { for (std::pair<QuicStreamId, QuicSpdyClientStream*> stream : open_streams_) { @@ -805,7 +806,7 @@ test_client_(test_client), ack_listener_(std::move(ack_listener)) {} -QuicTestClient::TestClientDataToResend::~TestClientDataToResend() {} +QuicTestClient::TestClientDataToResend::~TestClientDataToResend() = default; void QuicTestClient::TestClientDataToResend::Resend() { test_client_->GetOrCreateStreamAndSendRequest(headers_.get(), body_, fin_, @@ -847,7 +848,7 @@ bytes_written(bytes_written), response_body_size(response_body_size) {} -QuicTestClient::PerStreamState::~PerStreamState() {} +QuicTestClient::PerStreamState::~PerStreamState() = default; bool QuicTestClient::PopulateHeaderBlockFromUrl( const QuicString& uri,
diff --git a/quic/test_tools/quic_test_client.h b/quic/test_tools/quic_test_client.h index 08f8808..9142fd9 100644 --- a/quic/test_tools/quic_test_client.h +++ b/quic/test_tools/quic_test_client.h
@@ -15,6 +15,7 @@ #include "net/third_party/quiche/src/quic/core/quic_packet_creator.h" #include "net/third_party/quiche/src/quic/core/quic_packets.h" #include "net/third_party/quiche/src/quic/platform/api/quic_containers.h" +#include "net/third_party/quiche/src/quic/platform/api/quic_epoll.h" #include "net/third_party/quiche/src/quic/platform/api/quic_map_util.h" #include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h" #include "net/third_party/quiche/src/quic/tools/quic_client.h" @@ -34,19 +35,19 @@ MockableQuicClient(QuicSocketAddress server_address, const QuicServerId& server_id, const ParsedQuicVersionVector& supported_versions, - gfe2::EpollServer* epoll_server); + QuicEpollServer* epoll_server); MockableQuicClient(QuicSocketAddress server_address, const QuicServerId& server_id, const QuicConfig& config, const ParsedQuicVersionVector& supported_versions, - gfe2::EpollServer* epoll_server); + QuicEpollServer* epoll_server); MockableQuicClient(QuicSocketAddress server_address, const QuicServerId& server_id, const QuicConfig& config, const ParsedQuicVersionVector& supported_versions, - gfe2::EpollServer* epoll_server, + QuicEpollServer* epoll_server, std::unique_ptr<ProofVerifier> proof_verifier); MockableQuicClient(const MockableQuicClient&) = delete; MockableQuicClient& operator=(const MockableQuicClient&) = delete; @@ -68,7 +69,9 @@ const MockableQuicClientEpollNetworkHelper* mockable_network_helper() const; private: - QuicConnectionId override_connection_id_; // ConnectionId to use, if nonzero + // ConnectionId to use, if connection_id_overridden_ + QuicConnectionId override_connection_id_; + bool connection_id_overridden_; CachedNetworkParameters cached_network_paramaters_; }; @@ -253,7 +256,7 @@ void WaitForWriteToFlush(); - gfe2::EpollServer* epoll_server() { return &epoll_server_; } + QuicEpollServer* epoll_server() { return &epoll_server_; } size_t num_requests() const { return num_requests_; } @@ -356,7 +359,7 @@ // tracking its state. void SetLatestCreatedStream(QuicSpdyClientStream* stream); - gfe2::EpollServer epoll_server_; + QuicEpollServer epoll_server_; std::unique_ptr<MockableQuicClient> client_; // The actual client QuicSpdyClientStream* latest_created_stream_; std::map<QuicStreamId, QuicSpdyClientStream*> open_streams_;
diff --git a/quic/test_tools/quic_test_utils.cc b/quic/test_tools/quic_test_utils.cc index 49b871d..da76b33 100644 --- a/quic/test_tools/quic_test_utils.cc +++ b/quic/test_tools/quic_test_utils.cc
@@ -66,7 +66,7 @@ DCHECK_GT(ack_blocks.size(), 0u); QuicAckFrame ack; - QuicPacketNumber end_of_previous_block = 1; + QuicPacketNumber end_of_previous_block(1); for (const QuicAckBlock& block : ack_blocks) { DCHECK_GE(block.start, end_of_previous_block); DCHECK_GT(block.limit, block.start); @@ -79,17 +79,22 @@ return ack; } +QuicAckFrame InitAckFrame(uint64_t largest_acked) { + return InitAckFrame(QuicPacketNumber(largest_acked)); +} + QuicAckFrame InitAckFrame(QuicPacketNumber largest_acked) { - return InitAckFrame({{1, largest_acked + 1}}); + return InitAckFrame({{QuicPacketNumber(1), largest_acked + 1}}); } QuicAckFrame MakeAckFrameWithAckBlocks(size_t num_ack_blocks, - QuicPacketNumber least_unacked) { + uint64_t least_unacked) { QuicAckFrame ack; - ack.largest_acked = 2 * num_ack_blocks + least_unacked; + ack.largest_acked = QuicPacketNumber(2 * num_ack_blocks + least_unacked); // Add enough received packets to get num_ack_blocks ack blocks. - for (QuicPacketNumber i = 2; i < 2 * num_ack_blocks + 1; i += 2) { - ack.packets.Add(least_unacked + i); + for (QuicPacketNumber i = QuicPacketNumber(2); + i < QuicPacketNumber(2 * num_ack_blocks + 1); i += 2) { + ack.packets.Add(i + least_unacked); } return ack; } @@ -464,7 +469,7 @@ // Transfer ownership of the packet to the SentPacketManager and the // ack notifier to the AckNotifierManager. QuicConnectionPeer::GetSentPacketManager(this)->OnPacketSent( - packet, 0, QuicTime::Zero(), NOT_RETRANSMISSION, + packet, QuicPacketNumber(), QuicTime::Zero(), NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA); } @@ -600,7 +605,7 @@ crypto_config, compressed_certs_cache) { Initialize(); - ON_CALL(helper_, GenerateConnectionIdForReject(_)) + ON_CALL(helper_, GenerateConnectionIdForReject(_, _)) .WillByDefault(testing::Return( QuicUtils::CreateRandomConnectionId(connection->random_generator()))); ON_CALL(helper_, CanAcceptClientHello(_, _, _, _, _)) @@ -786,7 +791,7 @@ QuicConnectionId source_connection_id, bool version_flag, bool reset_flag, - QuicPacketNumber packet_number, + uint64_t packet_number, const QuicString& data) { return ConstructEncryptedPacket( destination_connection_id, source_connection_id, version_flag, reset_flag, @@ -799,7 +804,7 @@ QuicConnectionId source_connection_id, bool version_flag, bool reset_flag, - QuicPacketNumber packet_number, + uint64_t packet_number, const QuicString& data, QuicConnectionIdLength destination_connection_id_length, QuicConnectionIdLength source_connection_id_length, @@ -815,7 +820,7 @@ QuicConnectionId source_connection_id, bool version_flag, bool reset_flag, - QuicPacketNumber packet_number, + uint64_t packet_number, const QuicString& data, QuicConnectionIdLength destination_connection_id_length, QuicConnectionIdLength source_connection_id_length, @@ -832,7 +837,7 @@ QuicConnectionId source_connection_id, bool version_flag, bool reset_flag, - QuicPacketNumber packet_number, + uint64_t packet_number, const QuicString& data, QuicConnectionIdLength destination_connection_id_length, QuicConnectionIdLength source_connection_id_length, @@ -847,7 +852,7 @@ header.version_flag = version_flag; header.reset_flag = reset_flag; header.packet_number_length = packet_number_length; - header.packet_number = packet_number; + header.packet_number = QuicPacketNumber(packet_number); QuicFrame frame(QuicStreamFrame( QuicUtils::GetCryptoStreamId( versions != nullptr @@ -864,8 +869,9 @@ BuildUnsizedDataPacket(&framer, header, frames)); EXPECT_TRUE(packet != nullptr); char* buffer = new char[kMaxPacketSize]; - size_t encrypted_length = framer.EncryptPayload( - ENCRYPTION_NONE, packet_number, *packet, buffer, kMaxPacketSize); + size_t encrypted_length = + framer.EncryptPayload(ENCRYPTION_NONE, QuicPacketNumber(packet_number), + *packet, buffer, kMaxPacketSize); EXPECT_NE(0u, encrypted_length); return new QuicEncryptedPacket(buffer, encrypted_length, true); } @@ -884,7 +890,7 @@ QuicConnectionId source_connection_id, bool version_flag, bool reset_flag, - QuicPacketNumber packet_number, + uint64_t packet_number, const QuicString& data, QuicConnectionIdLength destination_connection_id_length, QuicConnectionIdLength source_connection_id_length, @@ -899,7 +905,7 @@ header.version_flag = version_flag; header.reset_flag = reset_flag; header.packet_number_length = packet_number_length; - header.packet_number = packet_number; + header.packet_number = QuicPacketNumber(packet_number); QuicFrame frame(QuicStreamFrame(1, false, 0, QuicStringPiece(data))); QuicFrames frames; frames.push_back(frame); @@ -918,8 +924,9 @@ false /* no diversification nonce */, packet_number_length)] = 0x1F; char* buffer = new char[kMaxPacketSize]; - size_t encrypted_length = framer.EncryptPayload( - ENCRYPTION_NONE, packet_number, *packet, buffer, kMaxPacketSize); + size_t encrypted_length = + framer.EncryptPayload(ENCRYPTION_NONE, QuicPacketNumber(packet_number), + *packet, buffer, kMaxPacketSize); EXPECT_NE(0u, encrypted_length); return new QuicEncryptedPacket(buffer, encrypted_length, true); }
diff --git a/quic/test_tools/quic_test_utils.h b/quic/test_tools/quic_test_utils.h index 61b60e4..8b52d4f 100644 --- a/quic/test_tools/quic_test_utils.h +++ b/quic/test_tools/quic_test_utils.h
@@ -77,7 +77,7 @@ QuicConnectionId source_connection_id, bool version_flag, bool reset_flag, - QuicPacketNumber packet_number, + uint64_t packet_number, const QuicString& data, QuicConnectionIdLength destination_connection_id_length, QuicConnectionIdLength source_connection_id_length, @@ -94,7 +94,7 @@ QuicConnectionId source_connection_id, bool version_flag, bool reset_flag, - QuicPacketNumber packet_number, + uint64_t packet_number, const QuicString& data, QuicConnectionIdLength destination_connection_id_length, QuicConnectionIdLength source_connection_id_length, @@ -107,7 +107,7 @@ QuicConnectionId source_connection_id, bool version_flag, bool reset_flag, - QuicPacketNumber packet_number, + uint64_t packet_number, const QuicString& data, QuicConnectionIdLength destination_connection_id_length, QuicConnectionIdLength source_connection_id_length, @@ -121,7 +121,7 @@ QuicConnectionId source_connection_id, bool version_flag, bool reset_flag, - QuicPacketNumber packet_number, + uint64_t packet_number, const QuicString& data); // Constructs a received packet for testing. The caller must take ownership of @@ -140,7 +140,7 @@ QuicConnectionId source_connection_id, bool version_flag, bool reset_flag, - QuicPacketNumber packet_number, + uint64_t packet_number, const QuicString& data, QuicConnectionIdLength destination_connection_id_length, QuicConnectionIdLength source_connection_id_length, @@ -195,12 +195,13 @@ // Testing convenience method to construct a QuicAckFrame with 1 ack block which // covers packet number range [1, |largest_acked| + 1). // Equivalent to InitAckFrame({{1, largest_acked + 1}}) +QuicAckFrame InitAckFrame(uint64_t largest_acked); QuicAckFrame InitAckFrame(QuicPacketNumber largest_acked); // Testing convenience method to construct a QuicAckFrame with |num_ack_blocks| // ack blocks of width 1 packet, starting from |least_unacked| + 2. QuicAckFrame MakeAckFrameWithAckBlocks(size_t num_ack_blocks, - QuicPacketNumber least_unacked); + uint64_t least_unacked); // Returns a QuicPacket that is owned by the caller, and // is populated with the fields in |header| and |frames|, or is nullptr if the @@ -553,6 +554,7 @@ QuicConnection::SendConnectivityProbingResponsePacket(peer_address); } MOCK_METHOD1(OnPathResponseFrame, bool(const QuicPathResponseFrame&)); + MOCK_METHOD1(OnStopSendingFrame, bool(const QuicStopSendingFrame& frame)); }; class PacketSavingConnection : public MockQuicConnection {
diff --git a/quic/test_tools/quic_test_utils_test.cc b/quic/test_tools/quic_test_utils_test.cc index c9627c2..01791e0 100644 --- a/quic/test_tools/quic_test_utils_test.cc +++ b/quic/test_tools/quic_test_utils_test.cc
@@ -18,8 +18,8 @@ EXPECT_EQ(TestConnectionId(), TestConnectionId()); EXPECT_EQ(TestConnectionId(33), TestConnectionId(33)); EXPECT_NE(TestConnectionId(0xdead), TestConnectionId(0xbeef)); - EXPECT_EQ(0x1337, TestConnectionIdToUInt64(TestConnectionId(0x1337))); - EXPECT_NE(0xdead, TestConnectionIdToUInt64(TestConnectionId(0xbeef))); + EXPECT_EQ(0x1337u, TestConnectionIdToUInt64(TestConnectionId(0x1337))); + EXPECT_NE(0xdeadu, TestConnectionIdToUInt64(TestConnectionId(0xbeef))); } TEST_F(QuicTestUtilsTest, BasicApproxEq) {
diff --git a/quic/test_tools/simple_data_producer.cc b/quic/test_tools/simple_data_producer.cc index 1b010eb..ab98fd1 100644 --- a/quic/test_tools/simple_data_producer.cc +++ b/quic/test_tools/simple_data_producer.cc
@@ -4,6 +4,8 @@ #include "net/third_party/quiche/src/quic/test_tools/simple_data_producer.h" +#include "net/third_party/quiche/src/quic/core/quic_data_writer.h" +#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h" #include "net/third_party/quiche/src/quic/platform/api/quic_flags.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" @@ -13,13 +15,13 @@ namespace test { SimpleDataProducer::SimpleDataProducer() {} + SimpleDataProducer::~SimpleDataProducer() {} void SimpleDataProducer::SaveStreamData(QuicStreamId id, const struct iovec* iov, int iov_count, size_t iov_offset, - QuicStreamOffset offset, QuicByteCount data_length) { if (data_length == 0) { return; @@ -30,6 +32,13 @@ send_buffer_map_[id]->SaveStreamData(iov, iov_count, iov_offset, data_length); } +void SimpleDataProducer::SaveCryptoData(EncryptionLevel level, + QuicStreamOffset offset, + QuicStringPiece data) { + auto key = std::make_pair(level, offset); + crypto_buffer_map_[key] = data; +} + WriteStreamDataResult SimpleDataProducer::WriteStreamData( QuicStreamId id, QuicStreamOffset offset, @@ -45,6 +54,17 @@ return WRITE_FAILED; } +bool SimpleDataProducer::WriteCryptoData(EncryptionLevel level, + QuicStreamOffset offset, + QuicByteCount data_length, + QuicDataWriter* writer) { + auto it = crypto_buffer_map_.find(std::make_pair(level, offset)); + if (it == crypto_buffer_map_.end() || it->second.length() != data_length) { + return false; + } + return writer->WriteStringPiece(it->second); +} + } // namespace test } // namespace quic
diff --git a/quic/test_tools/simple_data_producer.h b/quic/test_tools/simple_data_producer.h index 88622c1..d51ec69 100644 --- a/quic/test_tools/simple_data_producer.h +++ b/quic/test_tools/simple_data_producer.h
@@ -21,26 +21,67 @@ SimpleDataProducer(); ~SimpleDataProducer() override; + // Saves data to be provided when WriteStreamData is called. Data of length + // |data_length| is buffered to be provided for stream |id|. Multiple calls to + // SaveStreamData for the same stream ID append to the buffer for that stream. + // The data to be buffered is provided in |iov_count| iovec structs, with + // |iov| pointing to the first, and |iov_offset| indicating how many bytes + // into the iovec structs the data starts. void SaveStreamData(QuicStreamId id, const struct iovec* iov, int iov_count, size_t iov_offset, - QuicStreamOffset offset, QuicByteCount data_length); + void SaveCryptoData(EncryptionLevel level, + QuicStreamOffset offset, + QuicStringPiece data); + // QuicStreamFrameDataProducer WriteStreamDataResult WriteStreamData(QuicStreamId id, QuicStreamOffset offset, QuicByteCount data_length, QuicDataWriter* writer) override; + bool WriteCryptoData(EncryptionLevel level, + QuicStreamOffset offset, + QuicByteCount data_length, + QuicDataWriter* writer) override; + + // TODO(wub): Allow QuicDefaultHasher to accept a pair. Then remove this. + class PairHash { + public: + template <class T1, class T2> + size_t operator()(const std::pair<T1, T2>& pair) const { + return std::hash<T1>()(pair.first) ^ std::hash<T2>()(pair.second); + } + }; private: using SendBufferMap = QuicUnorderedMap<QuicStreamId, std::unique_ptr<QuicStreamSendBuffer>>; + using CryptoBufferMap = + QuicUnorderedMap<std::pair<EncryptionLevel, QuicStreamOffset>, + QuicStringPiece, + PairHash>; + SimpleBufferAllocator allocator_; SendBufferMap send_buffer_map_; + + // |crypto_buffer_map_| stores data provided by SaveCryptoData to later write + // in WriteCryptoData. The level and data passed into SaveCryptoData are used + // as the key to identify the data when WriteCryptoData is called. + // WriteCryptoData will only succeed if there is data in the map for the + // provided level and offset, and the data in the map matches the data_length + // passed into WriteCryptoData. + // + // Unlike SaveStreamData/WriteStreamData which uses a map of + // QuicStreamSendBuffers (for each stream ID), this map provides data for + // specific offsets. Using a QuicStreamSendBuffer requires that all data + // before an offset exist, whereas this allows providing data that exists at + // arbitrary offsets for testing. + CryptoBufferMap crypto_buffer_map_; }; } // namespace test
diff --git a/quic/test_tools/simulator/quic_endpoint.cc b/quic/test_tools/simulator/quic_endpoint.cc index 4cf236b..2867d82 100644 --- a/quic/test_tools/simulator/quic_endpoint.cc +++ b/quic/test_tools/simulator/quic_endpoint.cc
@@ -222,6 +222,7 @@ // Sanity check against very pathological connections. DCHECK_LE(offsets_received_.Size(), 1000u); } + void QuicEndpoint::OnCanWrite() { if (notifier_ != nullptr) { notifier_->OnCanWrite(); @@ -354,6 +355,14 @@ return WRITE_SUCCESS; } +bool QuicEndpoint::DataProducer::WriteCryptoData(EncryptionLevel leve, + QuicStreamOffset offset, + QuicByteCount data_length, + QuicDataWriter* writer) { + QUIC_BUG << "QuicEndpoint::DataProducer::WriteCryptoData is unimplemented"; + return false; +} + void QuicEndpoint::WriteStreamData() { // Instantiate a flusher which would normally be here due to QuicSession. QuicConnection::ScopedPacketFlusher flusher(
diff --git a/quic/test_tools/simulator/quic_endpoint.h b/quic/test_tools/simulator/quic_endpoint.h index 1a31ab2..600a1d1 100644 --- a/quic/test_tools/simulator/quic_endpoint.h +++ b/quic/test_tools/simulator/quic_endpoint.h
@@ -166,6 +166,10 @@ QuicStreamOffset offset, QuicByteCount data_length, QuicDataWriter* writer) override; + bool WriteCryptoData(EncryptionLevel level, + QuicStreamOffset offset, + QuicByteCount data_length, + QuicDataWriter* writer) override; }; // Write stream data until |bytes_to_transfer_| is zero or the connection is
diff --git a/quic/test_tools/simulator/simulator_test.cc b/quic/test_tools/simulator/simulator_test.cc index cb0c3a6..b2221c7 100644 --- a/quic/test_tools/simulator/simulator_test.cc +++ b/quic/test_tools/simulator/simulator_test.cc
@@ -310,10 +310,9 @@ saturator.SetTxPort(&local_link); queue.set_tx_port(&bottleneck_link); - const QuicPacketCount packets_received = 1000; - simulator.RunUntil([&counter, packets_received]() { - return counter.packets() == packets_received; - }); + static const QuicPacketCount packets_received = 1000; + simulator.RunUntil( + [&counter]() { return counter.packets() == packets_received; }); const double loss_ratio = 1 - static_cast<double>(packets_received) / saturator.packets_transmitted(); EXPECT_NEAR(loss_ratio, 0.9, 0.001);
diff --git a/quic/tools/quic_client.cc b/quic/tools/quic_client.cc index 84e1844..7705907 100644 --- a/quic/tools/quic_client.cc +++ b/quic/tools/quic_client.cc
@@ -35,7 +35,7 @@ QuicClient::QuicClient(QuicSocketAddress server_address, const QuicServerId& server_id, const ParsedQuicVersionVector& supported_versions, - gfe2::EpollServer* epoll_server, + QuicEpollServer* epoll_server, std::unique_ptr<ProofVerifier> proof_verifier) : QuicClient( server_address, @@ -50,7 +50,7 @@ QuicSocketAddress server_address, const QuicServerId& server_id, const ParsedQuicVersionVector& supported_versions, - gfe2::EpollServer* epoll_server, + QuicEpollServer* epoll_server, std::unique_ptr<QuicClientEpollNetworkHelper> network_helper, std::unique_ptr<ProofVerifier> proof_verifier) : QuicClient(server_address, @@ -66,7 +66,7 @@ const QuicServerId& server_id, const ParsedQuicVersionVector& supported_versions, const QuicConfig& config, - gfe2::EpollServer* epoll_server, + QuicEpollServer* epoll_server, std::unique_ptr<QuicClientEpollNetworkHelper> network_helper, std::unique_ptr<ProofVerifier> proof_verifier) : QuicSpdyClientBase( @@ -80,7 +80,7 @@ set_server_address(server_address); } -QuicClient::~QuicClient() {} +QuicClient::~QuicClient() = default; std::unique_ptr<QuicSession> QuicClient::CreateQuicClientSession( const ParsedQuicVersionVector& supported_versions,
diff --git a/quic/tools/quic_client.h b/quic/tools/quic_client.h index 71ff7f4..03a029d 100644 --- a/quic/tools/quic_client.h +++ b/quic/tools/quic_client.h
@@ -21,6 +21,7 @@ #include "net/third_party/quiche/src/quic/core/quic_packet_reader.h" #include "net/third_party/quiche/src/quic/core/quic_process_packet_interface.h" #include "net/third_party/quiche/src/quic/platform/api/quic_containers.h" +#include "net/third_party/quiche/src/quic/platform/api/quic_epoll.h" #include "net/third_party/quiche/src/quic/tools/quic_client_epoll_network_helper.h" #include "net/third_party/quiche/src/quic/tools/quic_spdy_client_base.h" @@ -38,20 +39,20 @@ QuicClient(QuicSocketAddress server_address, const QuicServerId& server_id, const ParsedQuicVersionVector& supported_versions, - gfe2::EpollServer* epoll_server, + QuicEpollServer* epoll_server, std::unique_ptr<ProofVerifier> proof_verifier); // This will take ownership of a passed in network primitive. QuicClient(QuicSocketAddress server_address, const QuicServerId& server_id, const ParsedQuicVersionVector& supported_versions, - gfe2::EpollServer* epoll_server, + QuicEpollServer* epoll_server, std::unique_ptr<QuicClientEpollNetworkHelper> network_helper, std::unique_ptr<ProofVerifier> proof_verifier); QuicClient(QuicSocketAddress server_address, const QuicServerId& server_id, const ParsedQuicVersionVector& supported_versions, const QuicConfig& config, - gfe2::EpollServer* epoll_server, + QuicEpollServer* epoll_server, std::unique_ptr<QuicClientEpollNetworkHelper> network_helper, std::unique_ptr<ProofVerifier> proof_verifier); QuicClient(const QuicClient&) = delete;
diff --git a/quic/tools/quic_client_base.cc b/quic/tools/quic_client_base.cc index 8a469a6..f824811 100644 --- a/quic/tools/quic_client_base.cc +++ b/quic/tools/quic_client_base.cc
@@ -86,7 +86,7 @@ // Resend any previously queued data. ResendSavedData(); } - ParsedQuicVersion version(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED); + ParsedQuicVersion version = UnsupportedQuicVersion(); if (session() != nullptr && session()->error() != QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT && !CanReconnectWithDifferentVersion(&version)) { @@ -110,8 +110,7 @@ DCHECK(initialized_); DCHECK(!connected()); QuicPacketWriter* writer = network_helper_->CreateQuicPacketWriter(); - ParsedQuicVersion mutual_version(PROTOCOL_UNSUPPORTED, - QUIC_VERSION_UNSUPPORTED); + ParsedQuicVersion mutual_version = UnsupportedQuicVersion(); const bool can_reconnect_with_different_version = CanReconnectWithDifferentVersion(&mutual_version); if (connected_or_attempting_connect()) { @@ -180,7 +179,7 @@ network_helper_->RunEventLoop(); DCHECK(session() != nullptr); - ParsedQuicVersion version(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED); + ParsedQuicVersion version = UnsupportedQuicVersion(); if (!connected() && (session()->error() == QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT || CanReconnectWithDifferentVersion(&version))) {
diff --git a/quic/tools/quic_client_base.h b/quic/tools/quic_client_base.h index 8257cef..c751bfd 100644 --- a/quic/tools/quic_client_base.h +++ b/quic/tools/quic_client_base.h
@@ -136,17 +136,6 @@ crypto_config_.SetChannelIDSource(source); } - // UseTokenBinding enables token binding negotiation in the client. This - // should only be called before the initial Connect(). The client will still - // need to check that token binding is negotiated with the server, and add - // token binding headers to requests if so. server, and add token binding - // headers to requests if so. The negotiated token binding parameters can be - // found on the QuicCryptoNegotiatedParameters object in - // token_binding_key_param. - void UseTokenBinding() { - crypto_config_.tb_key_params = QuicTagVector{kTB10}; - } - const ParsedQuicVersionVector& supported_versions() const { return supported_versions_; }
diff --git a/quic/tools/quic_client_bin.cc b/quic/tools/quic_client_bin.cc index dc82b0f..629b980 100644 --- a/quic/tools/quic_client_bin.cc +++ b/quic/tools/quic_client_bin.cc
@@ -124,9 +124,13 @@ "for_connecting_to_google/roots.pem", "Path to the root certificate which the server's certificate is " "required to chain to."); -ABSL_FLAG(bool, disable_certificate_verification, false, +ABSL_FLAG(bool, + disable_certificate_verification, + false, "If true, don't verify the server certificate."); -ABSL_FLAG(bool, drop_response_body, false, +ABSL_FLAG(bool, + drop_response_body, + false, "If true, drop response body immediately after it is received."); using quic::QuicStringPiece; @@ -169,7 +173,7 @@ cout << "Resolved " << host << " to " << host_port << endl; // Build the client, and try to connect. - gfe2::EpollServer epoll_server; + quic::QuicEpollServer epoll_server; quic::QuicServerId server_id(url.host(), port, false); quic::ParsedQuicVersionVector versions = quic::CurrentSupportedVersions(); if (FLAGS_quic_version != -1) {
diff --git a/quic/tools/quic_client_epoll_network_helper.cc b/quic/tools/quic_client_epoll_network_helper.cc index b12148c..6a48ad3 100644 --- a/quic/tools/quic_client_epoll_network_helper.cc +++ b/quic/tools/quic_client_epoll_network_helper.cc
@@ -36,7 +36,7 @@ } // namespace QuicClientEpollNetworkHelper::QuicClientEpollNetworkHelper( - gfe2::EpollServer* epoll_server, + QuicEpollServer* epoll_server, QuicClientBase* client) : epoll_server_(epoll_server), packets_dropped_(0), @@ -120,14 +120,14 @@ epoll_server_->WaitForEventsAndExecuteCallbacks(); } -void QuicClientEpollNetworkHelper::OnRegistration(gfe2::EpollServer* eps, +void QuicClientEpollNetworkHelper::OnRegistration(QuicEpollServer* eps, int fd, int event_mask) {} void QuicClientEpollNetworkHelper::OnModification(int fd, int event_mask) {} void QuicClientEpollNetworkHelper::OnUnregistration(int fd, bool replaced) {} -void QuicClientEpollNetworkHelper::OnShutdown(gfe2::EpollServer* eps, int fd) {} +void QuicClientEpollNetworkHelper::OnShutdown(QuicEpollServer* eps, int fd) {} -void QuicClientEpollNetworkHelper::OnEvent(int fd, gfe2::EpollEvent* event) { +void QuicClientEpollNetworkHelper::OnEvent(int fd, QuicEpollEvent* event) { DCHECK_EQ(fd, GetLatestFD()); if (event->in_events & EPOLLIN) {
diff --git a/quic/tools/quic_client_epoll_network_helper.h b/quic/tools/quic_client_epoll_network_helper.h index 23a1c91..5871cd0 100644 --- a/quic/tools/quic_client_epoll_network_helper.h +++ b/quic/tools/quic_client_epoll_network_helper.h
@@ -21,6 +21,7 @@ #include "net/third_party/quiche/src/quic/core/quic_packet_reader.h" #include "net/third_party/quiche/src/quic/core/quic_process_packet_interface.h" #include "net/third_party/quiche/src/quic/platform/api/quic_containers.h" +#include "net/third_party/quiche/src/quic/platform/api/quic_epoll.h" #include "net/third_party/quiche/src/quic/tools/quic_spdy_client_base.h" namespace quic { @@ -32,12 +33,12 @@ // An implementation of the QuicClientBase::NetworkHelper based off // the epoll server. class QuicClientEpollNetworkHelper : public QuicClientBase::NetworkHelper, - public gfe2::EpollCallbackInterface, + public QuicEpollCallbackInterface, public ProcessPacketInterface { public: // Create a quic client, which will have events managed by an externally owned // EpollServer. - QuicClientEpollNetworkHelper(gfe2::EpollServer* epoll_server, + QuicClientEpollNetworkHelper(QuicEpollServer* epoll_server, QuicClientBase* client); QuicClientEpollNetworkHelper(const QuicClientEpollNetworkHelper&) = delete; QuicClientEpollNetworkHelper& operator=(const QuicClientEpollNetworkHelper&) = @@ -49,14 +50,14 @@ QuicString Name() const override; // From EpollCallbackInterface - void OnRegistration(gfe2::EpollServer* eps, int fd, int event_mask) override; + void OnRegistration(QuicEpollServer* eps, int fd, int event_mask) override; void OnModification(int fd, int event_mask) override; - void OnEvent(int fd, gfe2::EpollEvent* event) override; + void OnEvent(int fd, QuicEpollEvent* event) override; // |fd_| can be unregistered without the client being disconnected. This // happens in b3m QuicProber where we unregister |fd_| to feed in events to // the client from the SelectServer. void OnUnregistration(int fd, bool replaced) override; - void OnShutdown(gfe2::EpollServer* eps, int fd) override; + void OnShutdown(QuicEpollServer* eps, int fd) override; // From ProcessPacketInterface. This will be called for each received // packet. @@ -75,7 +76,7 @@ // Accessors provided for convenience, not part of any interface. - gfe2::EpollServer* epoll_server() { return epoll_server_; } + QuicEpollServer* epoll_server() { return epoll_server_; } const QuicLinkedHashMap<int, QuicSocketAddress>& fd_address_map() const { return fd_address_map_; @@ -110,7 +111,7 @@ void CleanUpUDPSocketImpl(int fd); // Listens for events on the client socket. - gfe2::EpollServer* epoll_server_; + QuicEpollServer* epoll_server_; // Map mapping created UDP sockets to their addresses. By using linked hash // map, the order of socket creation can be recorded.
diff --git a/quic/tools/quic_client_test.cc b/quic/tools/quic_client_test.cc index 1c8c7ad..4f139b3 100644 --- a/quic/tools/quic_client_test.cc +++ b/quic/tools/quic_client_test.cc
@@ -17,8 +17,6 @@ #include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h" #include "net/third_party/quiche/src/quic/test_tools/quic_client_peer.h" -using gfe2::EpollServer; - namespace quic { namespace test { namespace { @@ -51,7 +49,7 @@ // Creates a new QuicClient and Initializes it. Caller is responsible for // deletion. -QuicClient* CreateAndInitializeQuicClient(EpollServer* eps, uint16_t port) { +QuicClient* CreateAndInitializeQuicClient(QuicEpollServer* eps, uint16_t port) { QuicSocketAddress server_address(QuicSocketAddress(TestLoopback(), port)); QuicServerId server_id("hostname", server_address.port(), false); ParsedQuicVersionVector versions = AllSupportedVersions(); @@ -69,7 +67,7 @@ // port exhaustion in long running processes which repeatedly create clients. // Record initial number of FDs, after creation of EpollServer. - EpollServer eps; + QuicEpollServer eps; size_t number_of_open_fds = NumOpenSocketFDs(); // Create a number of clients, initialize them, and verify this has resulted @@ -88,7 +86,7 @@ } TEST_F(QuicClientTest, CreateAndCleanUpUDPSockets) { - EpollServer eps; + QuicEpollServer eps; size_t number_of_open_fds = NumOpenSocketFDs(); std::unique_ptr<QuicClient> client(
diff --git a/quic/tools/quic_memory_cache_backend.cc b/quic/tools/quic_memory_cache_backend.cc index 94d795a..fa80e7e 100644 --- a/quic/tools/quic_memory_cache_backend.cc +++ b/quic/tools/quic_memory_cache_backend.cc
@@ -107,9 +107,9 @@ host_ = base.substr(0, path_start); size_t query_start = base.find_first_of(','); if (query_start > 0) { - path_ = absl::ClippedSubstr(base, path_start, query_start - 1); + path_ = base.substr(path_start, query_start - 1); } else { - path_ = absl::ClippedSubstr(base, path_start); + path_ = base.substr(path_start); } }
diff --git a/quic/tools/quic_server.cc b/quic/tools/quic_server.cc index 7e8dc95..eaec5d4 100644 --- a/quic/tools/quic_server.cc +++ b/quic/tools/quic_server.cc
@@ -182,7 +182,7 @@ fd_ = -1; } -void QuicServer::OnEvent(int fd, gfe2::EpollEvent* event) { +void QuicServer::OnEvent(int fd, QuicEpollEvent* event) { DCHECK_EQ(fd, fd_); event->out_ready_mask = 0;
diff --git a/quic/tools/quic_server.h b/quic/tools/quic_server.h index 712eceb..af60f95 100644 --- a/quic/tools/quic_server.h +++ b/quic/tools/quic_server.h
@@ -21,6 +21,7 @@ #include "net/third_party/quiche/src/quic/core/quic_framer.h" #include "net/third_party/quiche/src/quic/core/quic_packet_writer.h" #include "net/third_party/quiche/src/quic/core/quic_version_manager.h" +#include "net/third_party/quiche/src/quic/platform/api/quic_epoll.h" #include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h" #include "net/third_party/quiche/src/quic/tools/quic_simple_server_backend.h" @@ -33,7 +34,7 @@ class QuicDispatcher; class QuicPacketReader; -class QuicServer : public gfe2::EpollCallbackInterface { +class QuicServer : public QuicEpollCallbackInterface { public: QuicServer(std::unique_ptr<ProofSource> proof_source, QuicSimpleServerBackend* quic_simple_server_backend); @@ -62,13 +63,12 @@ virtual void Shutdown(); // From EpollCallbackInterface - void OnRegistration(gfe2::EpollServer* eps, int fd, int event_mask) override { - } + void OnRegistration(QuicEpollServer* eps, int fd, int event_mask) override {} void OnModification(int fd, int event_mask) override {} - void OnEvent(int fd, gfe2::EpollEvent* event) override; + void OnEvent(int fd, QuicEpollEvent* event) override; void OnUnregistration(int fd, bool replaced) override {} - void OnShutdown(gfe2::EpollServer* eps, int fd) override {} + void OnShutdown(QuicEpollServer* eps, int fd) override {} void SetChloMultiplier(size_t multiplier) { crypto_config_.set_chlo_multiplier(multiplier); @@ -91,7 +91,7 @@ const QuicConfig& config() const { return config_; } const QuicCryptoServerConfig& crypto_config() const { return crypto_config_; } - gfe2::EpollServer* epoll_server() { return &epoll_server_; } + QuicEpollServer* epoll_server() { return &epoll_server_; } QuicDispatcher* dispatcher() { return dispatcher_.get(); } @@ -112,7 +112,7 @@ // Accepts data from the framer and demuxes clients to sessions. std::unique_ptr<QuicDispatcher> dispatcher_; // Frames incoming packets and hands them to the dispatcher. - gfe2::EpollServer epoll_server_; + QuicEpollServer epoll_server_; // The port the server is listening on. int port_;
diff --git a/quic/tools/quic_server_test.cc b/quic/tools/quic_server_test.cc index a3c0fb0..f549ad4 100644 --- a/quic/tools/quic_server_test.cc +++ b/quic/tools/quic_server_test.cc
@@ -28,7 +28,6 @@ namespace quic { namespace test { -using gfe2::EpollServer; using ::testing::_; namespace { @@ -228,7 +227,7 @@ QuicConfig config_; QuicCryptoServerConfig crypto_config_; QuicVersionManager version_manager_; - EpollServer eps_; + QuicEpollServer eps_; QuicMemoryCacheBackend quic_simple_server_backend_; MockQuicDispatcher dispatcher_; };
diff --git a/quic/tools/quic_simple_crypto_server_stream_helper.cc b/quic/tools/quic_simple_crypto_server_stream_helper.cc index af4e152..567c670 100644 --- a/quic/tools/quic_simple_crypto_server_stream_helper.cc +++ b/quic/tools/quic_simple_crypto_server_stream_helper.cc
@@ -17,6 +17,7 @@ QuicConnectionId QuicSimpleCryptoServerStreamHelper::GenerateConnectionIdForReject( + QuicTransportVersion /*version*/, QuicConnectionId /*connection_id*/) const { return QuicUtils::CreateRandomConnectionId(random_, Perspective::IS_SERVER); }
diff --git a/quic/tools/quic_simple_crypto_server_stream_helper.h b/quic/tools/quic_simple_crypto_server_stream_helper.h index 2c1e19a..c058f1a 100644 --- a/quic/tools/quic_simple_crypto_server_stream_helper.h +++ b/quic/tools/quic_simple_crypto_server_stream_helper.h
@@ -20,13 +20,14 @@ ~QuicSimpleCryptoServerStreamHelper() override; QuicConnectionId GenerateConnectionIdForReject( + QuicTransportVersion /*version*/, QuicConnectionId /*connection_id*/) const override; bool CanAcceptClientHello(const CryptoHandshakeMessage& message, const QuicSocketAddress& client_address, const QuicSocketAddress& peer_address, const QuicSocketAddress& self_address, - string* error_details) const override; + QuicString* error_details) const override; private: QuicRandom* random_; // Unowned.
diff --git a/quic/tools/quic_simple_crypto_server_stream_helper_test.cc b/quic/tools/quic_simple_crypto_server_stream_helper_test.cc index e64ba69..652f282 100644 --- a/quic/tools/quic_simple_crypto_server_stream_helper_test.cc +++ b/quic/tools/quic_simple_crypto_server_stream_helper_test.cc
@@ -14,7 +14,12 @@ QuicSimpleCryptoServerStreamHelper helper(&random); EXPECT_EQ(QuicUtils::CreateRandomConnectionId(&random), - helper.GenerateConnectionIdForReject(test::TestConnectionId())); + helper.GenerateConnectionIdForReject(QUIC_VERSION_35, + test::TestConnectionId())); + + EXPECT_EQ(QuicUtils::CreateRandomConnectionId(&random), + helper.GenerateConnectionIdForReject(QUIC_VERSION_99, + test::TestConnectionId())); } } // namespace quic
diff --git a/quic/tools/quic_simple_server_session.cc b/quic/tools/quic_simple_server_session.cc index 685d9f5..a3e8208 100644 --- a/quic/tools/quic_simple_server_session.cc +++ b/quic/tools/quic_simple_server_session.cc
@@ -13,8 +13,6 @@ #include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h" #include "net/third_party/quiche/src/quic/tools/quic_simple_server_stream.h" -using spdy::SpdyHeaderBlock; - namespace quic { QuicSimpleServerSession::QuicSimpleServerSession(
diff --git a/quic/tools/quic_simple_server_session_test.cc b/quic/tools/quic_simple_server_session_test.cc index a76facd..1ba330d 100644 --- a/quic/tools/quic_simple_server_session_test.cc +++ b/quic/tools/quic_simple_server_session_test.cc
@@ -251,6 +251,25 @@ *session_, n); } + void InjectStopSending(QuicStreamId stream_id, + QuicRstStreamErrorCode rst_stream_code) { + // 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 (connection_->transport_version() != QUIC_VERSION_99) { + // Only needed for version 99/IETF QUIC. + return; + } + EXPECT_CALL(owner_, OnStopSendingReceived(_)).Times(1); + QuicStopSendingFrame stop_sending( + kInvalidControlFrameId, stream_id, + static_cast<QuicApplicationErrorCode>(rst_stream_code)); + // Expect the RESET_STREAM that is generated in response to receiving a + // STOP_SENDING. + EXPECT_CALL(*connection_, OnStreamReset(stream_id, rst_stream_code)); + session_->OnStopSendingFrame(stop_sending); + } + StrictMock<MockQuicSessionVisitor> owner_; StrictMock<MockQuicCryptoServerStreamHelper> stream_helper_; MockQuicConnectionHelper helper_; @@ -287,6 +306,11 @@ OnStreamReset(GetNthClientInitiatedBidirectionalId(0), QUIC_RST_ACKNOWLEDGEMENT)); visitor_->OnRstStream(rst1); + // 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. + InjectStopSending(GetNthClientInitiatedBidirectionalId(0), + QUIC_ERROR_PROCESSING_STREAM); EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams()); // Send the same two bytes of payload in a new packet. @@ -310,6 +334,12 @@ OnStreamReset(GetNthClientInitiatedBidirectionalId(0), QUIC_RST_ACKNOWLEDGEMENT)); visitor_->OnRstStream(rst1); + // 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. + InjectStopSending(GetNthClientInitiatedBidirectionalId(0), + QUIC_ERROR_PROCESSING_STREAM); + EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams()); // Send two bytes of payload. @@ -344,6 +374,11 @@ OnStreamReset(GetNthClientInitiatedBidirectionalId(0), QUIC_RST_ACKNOWLEDGEMENT)); visitor_->OnRstStream(rst); + // 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. + InjectStopSending(GetNthClientInitiatedBidirectionalId(0), + QUIC_ERROR_PROCESSING_STREAM); // If we were tracking, we'd probably want to reject this because it's data // past the reset point of stream 3. As it's a closed stream we just drop the @@ -794,6 +829,10 @@ QuicMaxStreamIdFrame(0, GetNthServerInitiatedUnidirectionalId(10))); } visitor_->OnRstStream(rst); + // 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. + InjectStopSending(stream_got_reset, QUIC_STREAM_CANCELLED); } } // namespace
diff --git a/quic/tools/quic_simple_server_stream_test.cc b/quic/tools/quic_simple_server_stream_test.cc index 3916bd8..4e9e68d 100644 --- a/quic/tools/quic_simple_server_stream_test.cc +++ b/quic/tools/quic_simple_server_stream_test.cc
@@ -170,6 +170,8 @@ using QuicSession::ActivateStream; + MOCK_METHOD1(OnStopSendingReceived, void(const QuicStopSendingFrame& frame)); + spdy::SpdyHeaderBlock original_request_headers_; }; @@ -197,7 +199,8 @@ &memory_cache_backend_), quic_response_(new QuicBackendResponse), body_("hello world"), - is_verion_99_(connection_->transport_version() == QUIC_VERSION_99) { + is_version_99_(connection_->transport_version() == QUIC_VERSION_99) { + connection_->set_visitor(&session_); header_list_.OnHeaderBlockStart(); header_list_.OnHeader(":authority", "www.google.com"); header_list_.OnHeader(":path", "/"); @@ -245,7 +248,7 @@ QuicString body_; QuicHeaderList header_list_; HttpEncoder encoder_; - bool is_verion_99_; + bool is_version_99_; }; INSTANTIATE_TEST_CASE_P(Tests, @@ -261,7 +264,7 @@ QuicByteCount header_length = encoder_.SerializeDataFrameHeader(body_.length(), &buffer); QuicString header = QuicString(buffer.get(), header_length); - QuicString data = is_verion_99_ ? header + body_ : body_; + QuicString data = is_version_99_ ? header + body_ : body_; stream_->OnStreamFrame( QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, data)); EXPECT_EQ("11", StreamHeadersValue("content-length")); @@ -280,7 +283,7 @@ QuicByteCount header_length = encoder_.SerializeDataFrameHeader(body_.length(), &buffer); QuicString header = QuicString(buffer.get(), header_length); - QuicString data = is_verion_99_ ? header + body_ : body_; + QuicString data = is_version_99_ ? header + body_ : body_; stream_->OnStreamFrame( QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, data)); EXPECT_EQ("11", StreamHeadersValue("content-length")); @@ -310,7 +313,7 @@ // We'll automatically write out an error (headers + body) EXPECT_CALL(session_, WriteHeadersMock(_, _, _, _, _)); - if (is_verion_99_) { + if (is_version_99_) { EXPECT_CALL(session_, WritevData(_, _, _, _, _)) .WillOnce(Invoke(MockQuicSession::ConsumeData)); } @@ -324,7 +327,7 @@ QuicByteCount header_length = encoder_.SerializeDataFrameHeader(body_.length(), &buffer); QuicString header = QuicString(buffer.get(), header_length); - QuicString data = is_verion_99_ ? header + body_ : body_; + QuicString data = is_version_99_ ? header + body_ : body_; stream_->OnStreamFrame( QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, data)); @@ -333,7 +336,7 @@ header_length = encoder_.SerializeDataFrameHeader(large_body.length(), &buffer); header = QuicString(buffer.get(), header_length); - QuicString data2 = is_verion_99_ ? header + large_body : large_body; + QuicString data2 = is_version_99_ ? header + large_body : large_body; stream_->OnStreamFrame( QuicStreamFrame(stream_->id(), /*fin=*/true, data.size(), data2)); EXPECT_EQ("11", StreamHeadersValue("content-length")); @@ -365,7 +368,7 @@ InSequence s; EXPECT_CALL(session_, WriteHeadersMock(stream_->id(), _, false, _, _)); - if (is_verion_99_) { + if (is_version_99_) { EXPECT_CALL(session_, WritevData(_, _, _, _, _)) .Times(1) .WillOnce(Return(QuicConsumedData(header_length, false))); @@ -405,7 +408,7 @@ InSequence s; EXPECT_CALL(session_, WriteHeadersMock(stream_->id(), _, false, _, _)); - if (is_verion_99_) { + if (is_version_99_) { EXPECT_CALL(session_, WritevData(_, _, _, _, _)) .Times(1) .WillOnce(Return(QuicConsumedData(header_length, false))); @@ -474,7 +477,7 @@ InSequence s; EXPECT_CALL(session_, WriteHeadersMock(stream_->id(), _, false, _, _)); - if (is_verion_99_) { + if (is_version_99_) { EXPECT_CALL(session_, WritevData(_, _, _, _, _)) .Times(1) .WillOnce(Return(QuicConsumedData(header_length, false))); @@ -523,7 +526,7 @@ session_, 0), _)); EXPECT_CALL(session_, WriteHeadersMock(stream_->id(), _, false, _, _)); - if (is_verion_99_) { + if (is_version_99_) { EXPECT_CALL(session_, WritevData(_, _, _, _, _)) .Times(1) .WillOnce(Return(QuicConsumedData(header_length, false))); @@ -588,7 +591,7 @@ server_initiated_stream->priority(), _)); InSequence s; - if (is_verion_99_) { + if (is_version_99_) { EXPECT_CALL(session_, WritevData(_, kServerInitiatedStreamId, _, _, _)) .Times(1) .WillOnce(Return(QuicConsumedData(header_length, false))); @@ -612,7 +615,7 @@ InSequence s; EXPECT_CALL(session_, WriteHeadersMock(_, _, _, _, _)); - if (is_verion_99_) { + if (is_version_99_) { EXPECT_CALL(session_, WritevData(_, _, _, _, _)) .Times(1) .WillOnce(Return(QuicConsumedData(2, false))); @@ -685,7 +688,12 @@ QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream_->id(), QUIC_STREAM_CANCELLED, 1234); stream_->OnStreamReset(rst_frame); - + if (connection_->transport_version() == QUIC_VERSION_99) { + // For V99 receiving a RST_STREAM causes a 1-way close; the test requires + // a full close. A CloseWriteSide closes the other half of the stream. + // Everything should then work properly. + stream_->CloseWriteSide(); + } EXPECT_TRUE(stream_->reading_stopped()); EXPECT_TRUE(stream_->write_side_closed()); }
diff --git a/quic/tools/quic_spdy_client_base.cc b/quic/tools/quic_spdy_client_base.cc index 22db8df..f03b678 100644 --- a/quic/tools/quic_spdy_client_base.cc +++ b/quic/tools/quic_spdy_client_base.cc
@@ -27,7 +27,7 @@ bool fin) : headers_(std::move(headers)), body_(body), fin_(fin) {} -QuicSpdyClientBase::QuicDataToResend::~QuicDataToResend() {} +QuicSpdyClientBase::QuicDataToResend::~QuicDataToResend() = default; QuicSpdyClientBase::QuicSpdyClientBase( const QuicServerId& server_id,
diff --git a/spdy/core/hpack/hpack_constants.cc b/spdy/core/hpack/hpack_constants.cc index da41c0e..9c1498a 100644 --- a/spdy/core/hpack/hpack_constants.cc +++ b/spdy/core/hpack/hpack_constants.cc
@@ -6,13 +6,12 @@ #include <cstddef> #include <memory> +#include <vector> #include "base/logging.h" -#include "base/once.h" #include "net/third_party/quiche/src/spdy/core/hpack/hpack_huffman_table.h" #include "net/third_party/quiche/src/spdy/core/hpack/hpack_static_table.h" #include "net/third_party/quiche/src/spdy/platform/api/spdy_arraysize.h" -#include "net/third_party/quiche/src/spdy/platform/api/spdy_ptr_util.h" namespace spdy { @@ -26,7 +25,7 @@ // HpackHuffmanSymbol entries are initialized as {code, length, id}. // Codes are specified in the |length| most-significant bits of |code|. const std::vector<HpackHuffmanSymbol>& HpackHuffmanCodeVector() { - static const std::vector<HpackHuffmanSymbol> kHpackHuffmanCode = { + static const auto* kHpackHuffmanCode = new std::vector<HpackHuffmanSymbol>{ {0xffc00000ul, 13, 0}, // 11111111|11000 {0xffffb000ul, 23, 1}, // 11111111|11111111|1011000 {0xfffffe20ul, 28, 2}, // 11111111|11111111|11111110|0010 @@ -285,7 +284,7 @@ {0xfffffb80ul, 26, 255}, // 11111111|11111111|11111011|10 {0xfffffffcul, 30, 256}, // EOS 11111111|11111111|11111111|111111 }; - return kHpackHuffmanCode; + return *kHpackHuffmanCode; } // The "constructor" for a HpackStaticEntry that computes the lengths at @@ -294,7 +293,7 @@ { name, SPDY_ARRAYSIZE(name) - 1, value, SPDY_ARRAYSIZE(value) - 1 } const std::vector<HpackStaticEntry>& HpackStaticTableVector() { - static const std::vector<HpackStaticEntry> kHpackStaticTable = { + static const auto* kHpackStaticTable = new std::vector<HpackStaticEntry>{ STATIC_ENTRY(":authority", ""), // 1 STATIC_ENTRY(":method", "GET"), // 2 STATIC_ENTRY(":method", "POST"), // 3 @@ -357,7 +356,7 @@ STATIC_ENTRY("via", ""), // 60 STATIC_ENTRY("www-authenticate", ""), // 61 }; - return kHpackStaticTable; + return *kHpackStaticTable; } #undef STATIC_ENTRY
diff --git a/spdy/core/hpack/hpack_decoder_adapter.cc b/spdy/core/hpack/hpack_decoder_adapter.cc index 77ff703..309af39 100644 --- a/spdy/core/hpack/hpack_decoder_adapter.cc +++ b/spdy/core/hpack/hpack_decoder_adapter.cc
@@ -7,6 +7,7 @@ #include "base/logging.h" #include "net/third_party/quiche/src/http2/decoder/decode_buffer.h" #include "net/third_party/quiche/src/http2/decoder/decode_status.h" +#include "net/third_party/quiche/src/spdy/platform/api/spdy_estimate_memory_usage.h" using ::http2::DecodeBuffer; using ::http2::HpackEntryType; @@ -107,6 +108,10 @@ hpack_decoder_.set_max_string_size_bytes(max_decode_buffer_size_bytes); } +size_t HpackDecoderAdapter::EstimateMemoryUsage() const { + return SpdyEstimateMemoryUsage(hpack_decoder_); +} + HpackDecoderAdapter::ListenerAdapter::ListenerAdapter() : handler_(nullptr) {} HpackDecoderAdapter::ListenerAdapter::~ListenerAdapter() = default;
diff --git a/spdy/core/hpack/hpack_decoder_adapter.h b/spdy/core/hpack/hpack_decoder_adapter.h index 3f2ba88..b497fe7 100644 --- a/spdy/core/hpack/hpack_decoder_adapter.h +++ b/spdy/core/hpack/hpack_decoder_adapter.h
@@ -80,6 +80,8 @@ // of individual transport buffers. void set_max_decode_buffer_size_bytes(size_t max_decode_buffer_size_bytes); + size_t EstimateMemoryUsage() const; + private: class SPDY_EXPORT_PRIVATE ListenerAdapter : public http2::HpackDecoderListener,
diff --git a/spdy/core/hpack/hpack_decoder_adapter_test.cc b/spdy/core/hpack/hpack_decoder_adapter_test.cc index bef5c65..765c2ea 100644 --- a/spdy/core/hpack/hpack_decoder_adapter_test.cc +++ b/spdy/core/hpack/hpack_decoder_adapter_test.cc
@@ -6,16 +6,19 @@ // Tests of HpackDecoderAdapter. +#include <stdint.h> + +#include <tuple> #include <utility> #include <vector> #include "base/logging.h" #include "testing/gmock/include/gmock/gmock.h" -#include "testing/base/public/googletest.h" #include "testing/gtest/include/gtest/gtest.h" #include "net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_state.h" #include "net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_tables.h" #include "net/third_party/quiche/src/http2/hpack/tools/hpack_block_builder.h" +#include "net/third_party/quiche/src/http2/test_tools/http2_random.h" #include "net/third_party/quiche/src/spdy/core/hpack/hpack_constants.h" #include "net/third_party/quiche/src/spdy/core/hpack/hpack_encoder.h" #include "net/third_party/quiche/src/spdy/core/hpack/hpack_output_stream.h" @@ -23,12 +26,12 @@ #include "net/third_party/quiche/src/spdy/platform/api/spdy_arraysize.h" #include "net/third_party/quiche/src/spdy/platform/api/spdy_string.h" #include "net/third_party/quiche/src/spdy/platform/api/spdy_string_utils.h" -#include "util/random/mt_random.h" using ::http2::HpackEntryType; using ::http2::HpackString; using ::http2::HpackStringPair; using ::http2::test::HpackBlockBuilder; +using ::http2::test::HpackDecoderPeer; using ::testing::ElementsAre; using ::testing::Pair; @@ -58,8 +61,6 @@ namespace spdy { namespace test { -using ::http2::test::HpackDecoderPeer; - class HpackDecoderAdapterPeer { public: explicit HpackDecoderAdapterPeer(HpackDecoderAdapter* decoder) @@ -112,14 +113,8 @@ class HpackDecoderAdapterTest : public ::testing::TestWithParam<std::tuple<StartChoice, bool>> { - public: - static void SetUpTestCase() { - LOG(INFO) << "Flag --test_random_seed=" << FLAGS_test_random_seed; - } - protected: - HpackDecoderAdapterTest() - : random_(FLAGS_test_random_seed), decoder_(), decoder_peer_(&decoder_) {} + HpackDecoderAdapterTest() : decoder_(), decoder_peer_(&decoder_) {} void SetUp() override { std::tie(start_choice_, randomly_split_input_buffer_) = GetParam(); @@ -254,7 +249,7 @@ return result; } - MTRandom random_; + http2::test::Http2Random random_; HpackDecoderAdapter decoder_; test::HpackDecoderAdapterPeer decoder_peer_; TestHeadersHandler handler_; @@ -407,13 +402,14 @@ decoder_.HandleControlFrameHeadersComplete(nullptr); // Resulting decoded headers are in the same order as the inputs. - EXPECT_THAT(decoded_block(), - ElementsAre(Pair("cookie", " part 1; part 2 ; part3; fin!"), - Pair("passed-through", SpdyString("foo\0baz", 7)), - Pair("joined", "not joined"), - Pair("joineD", SpdyString("value 1\0value 2", 15)), - Pair("empty", ""), - Pair("empty-joined", SpdyString("\0foo\0\0", 6)))); + EXPECT_THAT( + decoded_block(), + ElementsAre(Pair("cookie", " part 1; part 2 ; part3; fin!"), + Pair("passed-through", SpdyStringPiece("foo\0baz", 7)), + Pair("joined", "not joined"), + Pair("joineD", SpdyStringPiece("value 1\0value 2", 15)), + Pair("empty", ""), + Pair("empty-joined", SpdyStringPiece("\0foo\0\0", 6)))); } // Decoding indexed static table field should work. @@ -678,8 +674,7 @@ SpdyString first = SpdyHexDecode("418cf1e3c2e5f23a6ba0ab90f4ff"); EXPECT_TRUE(DecodeHeaderBlock(first)); - first[1] = 0x8d; - first.push_back(0xff); + first = SpdyHexDecode("418df1e3c2e5f23a6ba0ab90f4ffff"); EXPECT_FALSE(DecodeHeaderBlock(first)); } @@ -705,8 +700,9 @@ // RFC 7541, Section C.4: Request Examples with Huffman Coding // http://httpwg.org/specs/rfc7541.html#rfc.section.C.4 TEST_P(HpackDecoderAdapterTest, SectionC4RequestHuffmanExamples) { - // TODO(jamessynge): Use gfe/http2/hpack/tools/hpack_example.h to parse the + // TODO(jamessynge): Use http2/hpack/tools/hpack_example.h to parse the // example directly, instead of having it as a comment. + // // 82 | == Indexed - Add == // | idx = 2 // | -> :method: GET
diff --git a/spdy/core/hpack/hpack_encoder.cc b/spdy/core/hpack/hpack_encoder.cc index 7608b06..a9981b9 100644 --- a/spdy/core/hpack/hpack_encoder.cc +++ b/spdy/core/hpack/hpack_encoder.cc
@@ -12,6 +12,7 @@ #include "net/third_party/quiche/src/spdy/core/hpack/hpack_header_table.h" #include "net/third_party/quiche/src/spdy/core/hpack/hpack_huffman_table.h" #include "net/third_party/quiche/src/spdy/core/hpack/hpack_output_stream.h" +#include "net/third_party/quiche/src/spdy/platform/api/spdy_estimate_memory_usage.h" #include "net/third_party/quiche/src/spdy/platform/api/spdy_ptr_util.h" namespace spdy { @@ -123,6 +124,12 @@ should_emit_table_size_ = true; } +size_t HpackEncoder::EstimateMemoryUsage() const { + // |huffman_table_| is a singleton. It's accounted for in spdy_session_pool.cc + return SpdyEstimateMemoryUsage(header_table_) + + SpdyEstimateMemoryUsage(output_stream_); +} + void HpackEncoder::EncodeRepresentations(RepresentationIterator* iter, SpdyString* output) { MaybeEmitTableSize(); @@ -228,18 +235,17 @@ if (first == SpdyStringPiece::npos) { cookie_value = SpdyStringPiece(); } else { - cookie_value = absl::ClippedSubstr(cookie_value, first, (last - first) + 1); + cookie_value = cookie_value.substr(first, (last - first) + 1); } for (size_t pos = 0;;) { size_t end = cookie_value.find(";", pos); if (end == SpdyStringPiece::npos) { - out->push_back( - std::make_pair(cookie.first, absl::ClippedSubstr(cookie_value, pos))); + out->push_back(std::make_pair(cookie.first, cookie_value.substr(pos))); break; } - out->push_back(std::make_pair( - cookie.first, absl::ClippedSubstr(cookie_value, pos, end - pos))); + out->push_back( + std::make_pair(cookie.first, cookie_value.substr(pos, end - pos))); // Consume next space if present. pos = end + 1; @@ -258,8 +264,8 @@ end = header_field.second.find('\0', pos); out->push_back(std::make_pair( header_field.first, - absl::ClippedSubstr(header_field.second, pos, - end == SpdyStringPiece::npos ? end : end - pos))); + header_field.second.substr( + pos, end == SpdyStringPiece::npos ? end : end - pos))); pos = end + 1; } }
diff --git a/spdy/core/hpack/hpack_encoder.h b/spdy/core/hpack/hpack_encoder.h index 22bed4e..486d536 100644 --- a/spdy/core/hpack/hpack_encoder.h +++ b/spdy/core/hpack/hpack_encoder.h
@@ -97,6 +97,9 @@ void DisableCompression() { enable_compression_ = false; } + // Returns the estimate of dynamically allocated memory in bytes. + size_t EstimateMemoryUsage() const; + private: friend class test::HpackEncoderPeer;
diff --git a/spdy/core/hpack/hpack_encoder_test.cc b/spdy/core/hpack/hpack_encoder_test.cc index e639650..8ead1c2 100644 --- a/spdy/core/hpack/hpack_encoder_test.cc +++ b/spdy/core/hpack/hpack_encoder_test.cc
@@ -7,12 +7,11 @@ #include <cstdint> #include <map> -#include "base/arena.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/absl/random/random.h" +#include "net/third_party/quiche/src/http2/test_tools/http2_random.h" #include "net/third_party/quiche/src/spdy/core/hpack/hpack_huffman_table.h" -#include "util/random/acmrandom.h" +#include "net/third_party/quiche/src/spdy/platform/api/spdy_unsafe_arena.h" namespace spdy { @@ -86,11 +85,11 @@ std::unique_ptr<HpackEncoder::ProgressiveEncoder> encoderator = encoder->EncodeHeaderSet(header_set); SpdyString output_buffer; - ACMRandom random(FLAGS_test_random_seed); - encoderator->Next(absl::Uniform<uint32_t>(random, 0, 16), &output_buffer); + http2::test::Http2Random random; + encoderator->Next(random.UniformInRange(0, 16), &output_buffer); while (encoderator->HasNext()) { SpdyString second_buffer; - encoderator->Next(absl::Uniform<uint32_t>(random, 0, 16), &second_buffer); + encoderator->Next(random.UniformInRange(0, 16), &second_buffer); output_buffer.append(second_buffer); } *output = std::move(output_buffer); @@ -201,7 +200,7 @@ const HpackEntry* cookie_a_; const HpackEntry* cookie_c_; - UnsafeArena headers_storage_; + SpdyUnsafeArena headers_storage_; std::vector<std::pair<SpdyStringPiece, SpdyStringPiece>> headers_observed_; HpackOutputStream expected_;
diff --git a/spdy/core/hpack/hpack_entry.h b/spdy/core/hpack/hpack_entry.h index 2b4c427..28dee47 100644 --- a/spdy/core/hpack/hpack_entry.h +++ b/spdy/core/hpack/hpack_entry.h
@@ -5,6 +5,7 @@ #ifndef QUICHE_SPDY_CORE_HPACK_HPACK_ENTRY_H_ #define QUICHE_SPDY_CORE_HPACK_HPACK_ENTRY_H_ +#include <cstddef> #include <cstdint> #include "base/macros.h"
diff --git a/spdy/core/hpack/hpack_header_table.cc b/spdy/core/hpack/hpack_header_table.cc index e08ca8f..dbe565f 100644 --- a/spdy/core/hpack/hpack_header_table.cc +++ b/spdy/core/hpack/hpack_header_table.cc
@@ -9,15 +9,14 @@ #include "base/logging.h" #include "net/third_party/quiche/src/spdy/core/hpack/hpack_constants.h" #include "net/third_party/quiche/src/spdy/core/hpack/hpack_static_table.h" +#include "net/third_party/quiche/src/spdy/platform/api/spdy_containers.h" #include "net/third_party/quiche/src/spdy/platform/api/spdy_estimate_memory_usage.h" -#include "util/hash/hash.h" namespace spdy { size_t HpackHeaderTable::EntryHasher::operator()( const HpackEntry* entry) const { - return GoodFastHash<std::pair<SpdyStringPiece, SpdyStringPiece>>()( - std::make_pair(entry->name(), entry->value())); + return SpdyHashStringPair(entry->name(), entry->value()); } bool HpackHeaderTable::EntriesEq::operator()(const HpackEntry* lhs,
diff --git a/spdy/core/hpack/hpack_header_table.h b/spdy/core/hpack/hpack_header_table.h index 2529551..e85edb7 100644 --- a/spdy/core/hpack/hpack_header_table.h +++ b/spdy/core/hpack/hpack_header_table.h
@@ -14,8 +14,8 @@ #include "net/third_party/quiche/src/spdy/core/hpack/hpack_entry.h" #include "net/third_party/quiche/src/spdy/platform/api/spdy_containers.h" #include "net/third_party/quiche/src/spdy/platform/api/spdy_export.h" +#include "net/third_party/quiche/src/spdy/platform/api/spdy_macros.h" #include "net/third_party/quiche/src/spdy/platform/api/spdy_string_piece.h" -#include "util/hash/hash.h" // All section references below are to http://tools.ietf.org/html/rfc7541. @@ -54,10 +54,12 @@ // HpackHeaderTable takes advantage of the deque property that references // remain valid, so long as insertions & deletions are at the head & tail. - // If this changes (eg we start to drop entries from the middle of the table), - // this needs to be a std::list, in which case |*_index_| can be trivially - // extended to map to list iterators. - typedef std::deque<HpackEntry> EntryTable; + // This precludes the use of base::circular_deque. + // + // If this changes (we want to change to circular_deque or we start to drop + // entries from the middle of the table), this should to be a std::list, in + // which case |*_index_| can be trivially extended to map to list iterators. + using EntryTable = std::deque<HpackEntry>; struct SPDY_EXPORT_PRIVATE EntryHasher { size_t operator()(const HpackEntry* entry) const; @@ -66,7 +68,8 @@ bool operator()(const HpackEntry* lhs, const HpackEntry* rhs) const; }; using UnorderedEntrySet = SpdyHashSet<HpackEntry*, EntryHasher, EntriesEq>; - using NameToEntryMap = SpdyHashMap<SpdyStringPiece, const HpackEntry*>; + using NameToEntryMap = + SpdyHashMap<SpdyStringPiece, const HpackEntry*, SpdyStringPieceHash>; HpackHeaderTable(); HpackHeaderTable(const HpackHeaderTable&) = delete; @@ -117,7 +120,7 @@ // evicted and the empty table is of insufficent size for the representation. const HpackEntry* TryAddEntry(SpdyStringPiece name, SpdyStringPiece value); - void DebugLogTableState() const ABSL_ATTRIBUTE_UNUSED; + void DebugLogTableState() const SPDY_UNUSED; void set_debug_visitor(std::unique_ptr<DebugVisitorInterface> visitor) { debug_visitor_ = std::move(visitor);
diff --git a/spdy/core/hpack/hpack_huffman_table.cc b/spdy/core/hpack/hpack_huffman_table.cc index 2ff2101..c917767 100644 --- a/spdy/core/hpack/hpack_huffman_table.cc +++ b/spdy/core/hpack/hpack_huffman_table.cc
@@ -6,10 +6,12 @@ #include <algorithm> #include <cmath> +#include <limits> #include <memory> #include "base/logging.h" #include "net/third_party/quiche/src/spdy/core/hpack/hpack_output_stream.h" +#include "net/third_party/quiche/src/spdy/platform/api/spdy_estimate_memory_usage.h" namespace spdy { @@ -35,6 +37,7 @@ bool HpackHuffmanTable::Initialize(const HpackHuffmanSymbol* input_symbols, size_t symbol_count) { CHECK(!IsInitialized()); + DCHECK_LE(symbol_count, std::numeric_limits<uint16_t>::max()); std::vector<Symbol> symbols(symbol_count); // Validate symbol id sequence, and copy into |symbols|. @@ -140,4 +143,9 @@ return bit_count / 8; } +size_t HpackHuffmanTable::EstimateMemoryUsage() const { + return SpdyEstimateMemoryUsage(code_by_id_) + + SpdyEstimateMemoryUsage(length_by_id_); +} + } // namespace spdy
diff --git a/spdy/core/hpack/hpack_huffman_table.h b/spdy/core/hpack/hpack_huffman_table.h index efa5e2d..80d9e52 100644 --- a/spdy/core/hpack/hpack_huffman_table.h +++ b/spdy/core/hpack/hpack_huffman_table.h
@@ -51,6 +51,9 @@ // Returns the encoded size of the input string. size_t EncodedSize(SpdyStringPiece in) const; + // Returns the estimate of dynamically allocated memory in bytes. + size_t EstimateMemoryUsage() const; + private: // Expects symbols ordered on ID ascending. void BuildEncodeTable(const std::vector<Symbol>& symbols);
diff --git a/spdy/core/hpack/hpack_output_stream.cc b/spdy/core/hpack/hpack_output_stream.cc index 77fea53..30b5662 100644 --- a/spdy/core/hpack/hpack_output_stream.cc +++ b/spdy/core/hpack/hpack_output_stream.cc
@@ -7,6 +7,7 @@ #include <utility> #include "base/logging.h" +#include "net/third_party/quiche/src/spdy/platform/api/spdy_estimate_memory_usage.h" namespace spdy { @@ -89,4 +90,8 @@ } } +size_t HpackOutputStream::EstimateMemoryUsage() const { + return SpdyEstimateMemoryUsage(buffer_); +} + } // namespace spdy
diff --git a/spdy/core/hpack/hpack_output_stream.h b/spdy/core/hpack/hpack_output_stream.h index d2a0804..450803f 100644 --- a/spdy/core/hpack/hpack_output_stream.h +++ b/spdy/core/hpack/hpack_output_stream.h
@@ -59,6 +59,9 @@ // Size in bytes of stream's internal buffer. size_t size() const { return buffer_.size(); } + // Returns the estimate of dynamically allocated memory in bytes. + size_t EstimateMemoryUsage() const; + private: // The internal bit buffer. SpdyString buffer_;
diff --git a/spdy/core/hpack/hpack_round_trip_test.cc b/spdy/core/hpack/hpack_round_trip_test.cc index 105566a..4b3a848 100644 --- a/spdy/core/hpack/hpack_round_trip_test.cc +++ b/spdy/core/hpack/hpack_round_trip_test.cc
@@ -8,16 +8,16 @@ #include <vector> #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/absl/random/random.h" +#include "net/third_party/quiche/src/http2/test_tools/http2_random.h" #include "net/third_party/quiche/src/spdy/core/hpack/hpack_constants.h" #include "net/third_party/quiche/src/spdy/core/hpack/hpack_decoder_adapter.h" #include "net/third_party/quiche/src/spdy/core/hpack/hpack_encoder.h" #include "net/third_party/quiche/src/spdy/core/spdy_test_utils.h" #include "net/third_party/quiche/src/spdy/platform/api/spdy_string.h" -#include "util/random/mt_random.h" namespace spdy { namespace test { + namespace { // Supports testing with the input split at every byte boundary. @@ -73,7 +73,7 @@ sanity_bound); } - MTRandom random_; + http2::test::Http2Random random_; HpackEncoder encoder_; HpackDecoderAdapter decoder_; }; @@ -170,10 +170,6 @@ values.push_back("baz=bing; foo=bar; garbage"); values.push_back("baz=bing; fizzle=fazzle; garbage"); - uint32_t seed = absl::Uniform<uint32_t>(random_); - LOG(INFO) << "Seeding with " << seed << ""; - random_.Reset(seed); - for (size_t i = 0; i != 2000; ++i) { SpdyHeaderBlock headers;
diff --git a/spdy/core/hpack/hpack_static_table.cc b/spdy/core/hpack/hpack_static_table.cc index f462fa4..14e282e 100644 --- a/spdy/core/hpack/hpack_static_table.cc +++ b/spdy/core/hpack/hpack_static_table.cc
@@ -7,6 +7,7 @@ #include "base/logging.h" #include "net/third_party/quiche/src/spdy/core/hpack/hpack_constants.h" #include "net/third_party/quiche/src/spdy/core/hpack/hpack_entry.h" +#include "net/third_party/quiche/src/spdy/platform/api/spdy_estimate_memory_usage.h" #include "net/third_party/quiche/src/spdy/platform/api/spdy_string_piece.h" namespace spdy { @@ -40,4 +41,10 @@ return !static_entries_.empty(); } +size_t HpackStaticTable::EstimateMemoryUsage() const { + return SpdyEstimateMemoryUsage(static_entries_) + + SpdyEstimateMemoryUsage(static_index_) + + SpdyEstimateMemoryUsage(static_name_index_); +} + } // namespace spdy
diff --git a/spdy/core/hpack/hpack_static_table.h b/spdy/core/hpack/hpack_static_table.h index 2f2a6dd..f354a12 100644 --- a/spdy/core/hpack/hpack_static_table.h +++ b/spdy/core/hpack/hpack_static_table.h
@@ -40,6 +40,9 @@ return static_name_index_; } + // Returns the estimate of dynamically allocated memory in bytes. + size_t EstimateMemoryUsage() const; + private: HpackHeaderTable::EntryTable static_entries_; HpackHeaderTable::UnorderedEntrySet static_index_;
diff --git a/spdy/core/hpack/hpack_static_table_test.cc b/spdy/core/hpack/hpack_static_table_test.cc index c5f8403..4550be0 100644 --- a/spdy/core/hpack/hpack_static_table_test.cc +++ b/spdy/core/hpack/hpack_static_table_test.cc
@@ -9,7 +9,6 @@ #include "testing/gtest/include/gtest/gtest.h" #include "net/third_party/quiche/src/spdy/core/hpack/hpack_constants.h" -#include "net/third_party/quiche/src/spdy/platform/api/spdy_arraysize.h" #include "net/third_party/quiche/src/spdy/platform/api/spdy_string_piece.h" namespace spdy {
diff --git a/spdy/core/http2_frame_decoder_adapter.cc b/spdy/core/http2_frame_decoder_adapter.cc index 5c05fd1..c4e728d 100644 --- a/spdy/core/http2_frame_decoder_adapter.cc +++ b/spdy/core/http2_frame_decoder_adapter.cc
@@ -16,7 +16,6 @@ #include <utility> #include "base/logging.h" -#include "strings/escaping.h" #include "net/third_party/quiche/src/http2/decoder/decode_buffer.h" #include "net/third_party/quiche/src/http2/decoder/decode_status.h" #include "net/third_party/quiche/src/http2/decoder/http2_frame_decoder.h" @@ -27,17 +26,16 @@ #include "net/third_party/quiche/src/spdy/core/hpack/hpack_decoder_adapter.h" #include "net/third_party/quiche/src/spdy/core/hpack/hpack_header_table.h" #include "net/third_party/quiche/src/spdy/core/spdy_alt_svc_wire_format.h" -#include "net/third_party/quiche/src/spdy/core/spdy_bug_tracker.h" #include "net/third_party/quiche/src/spdy/core/spdy_header_block.h" #include "net/third_party/quiche/src/spdy/core/spdy_headers_handler_interface.h" #include "net/third_party/quiche/src/spdy/core/spdy_protocol.h" +#include "net/third_party/quiche/src/spdy/platform/api/spdy_bug_tracker.h" +#include "net/third_party/quiche/src/spdy/platform/api/spdy_endianness_util.h" +#include "net/third_party/quiche/src/spdy/platform/api/spdy_estimate_memory_usage.h" #include "net/third_party/quiche/src/spdy/platform/api/spdy_flags.h" #include "net/third_party/quiche/src/spdy/platform/api/spdy_ptr_util.h" #include "net/third_party/quiche/src/spdy/platform/api/spdy_string_utils.h" -#include "util/endian/endian.h" -#include "util/gtl/labs/optional.h" -using absl::nullopt; using ::spdy::ExtensionVisitorInterface; using ::spdy::HpackDecoderAdapter; using ::spdy::HpackHeaderTable; @@ -45,6 +43,7 @@ using ::spdy::ParseFrameType; using ::spdy::SpdyAltSvcWireFormat; using ::spdy::SpdyErrorCode; +using ::spdy::SpdyEstimateMemoryUsage; using ::spdy::SpdyFramerDebugVisitorInterface; using ::spdy::SpdyFramerVisitorInterface; using ::spdy::SpdyFrameType; @@ -71,7 +70,7 @@ uint64_t ToSpdyPingId(const Http2PingFields& ping) { uint64_t v; std::memcpy(&v, ping.opaque_bytes, Http2PingFields::EncodedSize()); - return gntohll(v); + return spdy::SpdyNetToHost64(v); } // Overwrites the fields of the header with invalid values, for the purpose @@ -248,6 +247,13 @@ return latched_probable_http_response_; } +size_t Http2DecoderAdapter::EstimateMemoryUsage() const { + // Skip |frame_decoder_|, |frame_header_| and |hpack_first_frame_header_| as + // they don't allocate. + return SpdyEstimateMemoryUsage(alt_svc_origin_) + + SpdyEstimateMemoryUsage(alt_svc_value_); +} + // =========================================================================== // Implementations of the methods declared by Http2FrameDecoderListener. @@ -354,7 +360,7 @@ if (frame_header().IsEndStream()) { visitor()->OnStreamEnd(frame_header().stream_id); } - opt_pad_length_ = nullopt; + opt_pad_length_.reset(); } void Http2DecoderAdapter::OnHeadersStart(const Http2FrameHeader& header) { @@ -407,7 +413,7 @@ void Http2DecoderAdapter::OnHeadersEnd() { DVLOG(1) << "OnHeadersEnd"; CommonHpackFragmentEnd(); - opt_pad_length_ = nullopt; + opt_pad_length_.reset(); } void Http2DecoderAdapter::OnPriorityFrame(const Http2FrameHeader& header, @@ -521,7 +527,7 @@ void Http2DecoderAdapter::OnPushPromiseEnd() { DVLOG(1) << "OnPushPromiseEnd"; CommonHpackFragmentEnd(); - opt_pad_length_ = nullopt; + opt_pad_length_.reset(); } void Http2DecoderAdapter::OnPing(const Http2FrameHeader& header,
diff --git a/spdy/core/http2_frame_decoder_adapter.h b/spdy/core/http2_frame_decoder_adapter.h index b2bf31a..02deafd 100644 --- a/spdy/core/http2_frame_decoder_adapter.h +++ b/spdy/core/http2_frame_decoder_adapter.h
@@ -11,13 +11,13 @@ #include <memory> #include "net/third_party/quiche/src/http2/decoder/http2_frame_decoder.h" +#include "net/third_party/quiche/src/http2/platform/api/http2_optional.h" #include "net/third_party/quiche/src/spdy/core/hpack/hpack_decoder_adapter.h" #include "net/third_party/quiche/src/spdy/core/hpack/hpack_header_table.h" #include "net/third_party/quiche/src/spdy/core/spdy_alt_svc_wire_format.h" #include "net/third_party/quiche/src/spdy/core/spdy_headers_handler_interface.h" #include "net/third_party/quiche/src/spdy/core/spdy_protocol.h" #include "net/third_party/quiche/src/spdy/platform/api/spdy_string_piece.h" -#include "util/gtl/labs/optional.h" namespace spdy { @@ -137,6 +137,9 @@ // has responded with an HTTP/1.1 (or earlier) response. bool probable_http_response() const; + // Returns the estimate of dynamically allocated memory in bytes. + size_t EstimateMemoryUsage() const; + spdy::HpackDecoderAdapter* GetHpackDecoder(); bool HasError() const; @@ -242,7 +245,7 @@ // Amount of trailing padding. Currently used just as an indicator of whether // OnPadLength has been called. - absl::optional<size_t> opt_pad_length_; + Http2Optional<size_t> opt_pad_length_; // Temporary buffers for the AltSvc fields. Http2String alt_svc_origin_;
diff --git a/spdy/core/priority_write_scheduler.h b/spdy/core/priority_write_scheduler.h index 25f8b49..d5c3c44 100644 --- a/spdy/core/priority_write_scheduler.h +++ b/spdy/core/priority_write_scheduler.h
@@ -6,16 +6,19 @@ #define QUICHE_SPDY_CORE_PRIORITY_WRITE_SCHEDULER_H_ #include <algorithm> +#include <cstddef> #include <cstdint> -#include <deque> #include <tuple> #include <unordered_map> #include <utility> +#include <vector> #include "base/logging.h" -#include "net/third_party/quiche/src/spdy/core/spdy_bug_tracker.h" +#include "net/third_party/quiche/src/http2/platform/api/http2_containers.h" #include "net/third_party/quiche/src/spdy/core/spdy_protocol.h" #include "net/third_party/quiche/src/spdy/core/write_scheduler.h" +#include "net/third_party/quiche/src/spdy/platform/api/spdy_bug_tracker.h" +#include "net/third_party/quiche/src/spdy/platform/api/spdy_macros.h" #include "net/third_party/quiche/src/spdy/platform/api/spdy_string.h" #include "net/third_party/quiche/src/spdy/platform/api/spdy_string_utils.h" @@ -52,7 +55,8 @@ // parent_id not used here, but may as well validate it. However, // parent_id may legitimately not be registered yet--see b/15676312. StreamIdType parent_id = precedence.parent_id(); - VLOG_IF(1, parent_id != kHttp2RootStreamId && !StreamRegistered(parent_id)) + SPDY_DVLOG_IF( + 1, parent_id != kHttp2RootStreamId && !StreamRegistered(parent_id)) << "Parent stream " << parent_id << " not registered"; if (stream_id == kHttp2RootStreamId) { @@ -88,7 +92,7 @@ StreamIdType stream_id) const override { auto it = stream_infos_.find(stream_id); if (it == stream_infos_.end()) { - VLOG(1) << "Stream " << stream_id << " not registered"; + DVLOG(1) << "Stream " << stream_id << " not registered"; return StreamPrecedenceType(kV3LowestPriority); } return StreamPrecedenceType(it->second.priority); @@ -102,13 +106,14 @@ // parent_id not used here, but may as well validate it. However, // parent_id may legitimately not be registered yet--see b/15676312. StreamIdType parent_id = precedence.parent_id(); - VLOG_IF(1, parent_id != kHttp2RootStreamId && !StreamRegistered(parent_id)) + SPDY_DVLOG_IF( + 1, parent_id != kHttp2RootStreamId && !StreamRegistered(parent_id)) << "Parent stream " << parent_id << " not registered"; auto it = stream_infos_.find(stream_id); if (it == stream_infos_.end()) { // TODO(mpw): add to stream_infos_ on demand--see b/15676312. - VLOG(1) << "Stream " << stream_id << " not registered"; + DVLOG(1) << "Stream " << stream_id << " not registered"; return; } StreamInfo& stream_info = it->second; @@ -278,8 +283,8 @@ bool ready; }; - // 0(1) size lookup, 0(1) insert at front or back. - typedef std::deque<StreamInfo*> ReadyList; + // O(1) size lookup, O(1) insert at front or back (amortized). + using ReadyList = http2::Http2Deque<StreamInfo*>; // State kept for each priority level. struct PriorityInfo {
diff --git a/spdy/core/priority_write_scheduler_test.cc b/spdy/core/priority_write_scheduler_test.cc index 127ab17..a285cb2 100644 --- a/spdy/core/priority_write_scheduler_test.cc +++ b/spdy/core/priority_write_scheduler_test.cc
@@ -4,9 +4,7 @@ #include "net/third_party/quiche/src/spdy/core/priority_write_scheduler.h" -#include "testing/base/public/benchmark.h" #include "testing/gtest/include/gtest/gtest.h" -#include "testing/base/public/test_utils.h" #include "net/third_party/quiche/src/spdy/core/spdy_protocol.h" #include "net/third_party/quiche/src/spdy/core/spdy_test_utils.h" @@ -203,7 +201,7 @@ EXPECT_SPDY_BUG(scheduler_.MarkStreamReady(1, false), "Stream 1 not registered"); EXPECT_FALSE(scheduler_.HasReadyStreams()); - EXPECT_SPDY_BUG(EXPECT_EQ(0, scheduler_.PopNextReadyStream()), + EXPECT_SPDY_BUG(EXPECT_EQ(0u, scheduler_.PopNextReadyStream()), "No ready streams available"); // Add a bunch of ready streams to tail of per-priority lists.
diff --git a/spdy/core/spdy_alt_svc_wire_format.h b/spdy/core/spdy_alt_svc_wire_format.h index 5e12ead..ac834bc 100644 --- a/spdy/core/spdy_alt_svc_wire_format.h +++ b/spdy/core/spdy_alt_svc_wire_format.h
@@ -13,11 +13,10 @@ #include <cstdint> #include <vector> -#include "third_party/absl/container/inlined_vector.h" +#include "net/third_party/quiche/src/spdy/platform/api/spdy_containers.h" #include "net/third_party/quiche/src/spdy/platform/api/spdy_export.h" #include "net/third_party/quiche/src/spdy/platform/api/spdy_string.h" #include "net/third_party/quiche/src/spdy/platform/api/spdy_string_piece.h" -#include "util/gtl/inlined_vector.h" namespace spdy { @@ -27,11 +26,12 @@ class SPDY_EXPORT_PRIVATE SpdyAltSvcWireFormat { public: - using VersionVector = absl::InlinedVector<uint32_t, 8>; + using VersionVector = SpdyInlinedVector<uint32_t, 8>; struct SPDY_EXPORT_PRIVATE AlternativeService { SpdyString protocol_id; SpdyString host; + // Default is 0: invalid port. uint16_t port = 0; // Default is one day.
diff --git a/spdy/core/spdy_alt_svc_wire_format_test.cc b/spdy/core/spdy_alt_svc_wire_format_test.cc index e145b83..c2595f0 100644 --- a/spdy/core/spdy_alt_svc_wire_format_test.cc +++ b/spdy/core/spdy_alt_svc_wire_format_test.cc
@@ -6,7 +6,7 @@ #include "base/logging.h" #include "testing/gmock/include/gmock/gmock.h" -#include "testing/base/public/test_utils.h" +#include "testing/gtest/include/gtest/gtest.h" namespace spdy {
diff --git a/spdy/core/spdy_bug_tracker.h b/spdy/core/spdy_bug_tracker.h deleted file mode 100644 index 06e3204..0000000 --- a/spdy/core/spdy_bug_tracker.h +++ /dev/null
@@ -1,35 +0,0 @@ -// Copyright (c) 2016 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_SPDY_CORE_SPDY_BUG_TRACKER_H_ -#define QUICHE_SPDY_CORE_SPDY_BUG_TRACKER_H_ - -// Defined in Blaze when targetting non-production platforms (iOS, Android, etc) -// The fallback implimentation is the same as in Chromium which simply delegates -// to LOG(DFATAL) which is part of PG3. -#if SPDY_GENERIC_BUG - -#define SPDY_BUG LOG(DFATAL) -#define SPDY_BUG_IF(condition) LOG_IF(DFATAL, condition) -#define FLAGS_spdy_always_log_bugs_for_tests true - -#else - -#include "gfe/gfe2/base/bug_utils.h" - -// For external SPDY, SPDY_BUG should be #defined to LOG(DFATAL) and -// SPDY_BUG_IF(condition) to LOG_IF(DFATAL, condition) as client-side log rate -// limiting is less important and chrome doesn't LOG_FIRST_N anyway. -// -// This file should change infrequently if ever, so update cost should be -// minimal. Meanwhile we do want different macros so we can rate limit server -// side, so the google3 shared code increments GFE varz, and chrome can have its -// own custom hooks. -#define SPDY_BUG GFE_BUG -#define SPDY_BUG_IF GFE_BUG_IF -#define FLAGS_spdy_always_log_bugs_for_tests FLAGS_gfe_always_log_bug_for_tests - -#endif // __ANDROID__ - -#endif // QUICHE_SPDY_CORE_SPDY_BUG_TRACKER_H_
diff --git a/spdy/core/spdy_deframer_visitor.cc b/spdy/core/spdy_deframer_visitor.cc index 8a30f79..76188e9 100644 --- a/spdy/core/spdy_deframer_visitor.cc +++ b/spdy/core/spdy_deframer_visitor.cc
@@ -7,13 +7,13 @@ #include <stdlib.h> #include <algorithm> +#include <cstdint> #include <limits> #include <memory> -#include "base/log_severity.h" #include "base/logging.h" -#include "strings/cord.h" #include "testing/gmock/include/gmock/gmock.h" +#include "net/third_party/quiche/src/http2/platform/api/http2_macros.h" #include "net/third_party/quiche/src/spdy/core/hpack/hpack_constants.h" #include "net/third_party/quiche/src/spdy/core/mock_spdy_framer_visitor.h" #include "net/third_party/quiche/src/spdy/core/spdy_frame_reader.h" @@ -35,7 +35,7 @@ enum class HeaderDirection { REQUEST, RESPONSE }; // Types of HTTP/2 frames, per RFC 7540. -// TODO(jamessynge): Switch to using //gfe/http2/http2_constants.h when ready. +// TODO(jamessynge): Switch to using http2/http2_constants.h when ready. enum Http2FrameType { DATA = 0, HEADERS = 1, @@ -54,7 +54,7 @@ UNKNOWN = -2, }; -// TODO(jamessynge): Switch to using //gfe/http2/http2_constants.h when ready. +// TODO(jamessynge): Switch to using http2/http2_constants.h when ready. const char* Http2FrameTypeToString(Http2FrameType v) { switch (v) { case DATA: @@ -88,7 +88,7 @@ } } -// TODO(jamessynge): Switch to using //gfe/http2/http2_constants.h when ready. +// TODO(jamessynge): Switch to using http2/http2_constants.h when ready. inline std::ostream& operator<<(std::ostream& out, Http2FrameType v) { return out << Http2FrameTypeToString(v); } @@ -97,7 +97,7 @@ // (see https://httpwg.github.io/specs/rfc7540.html#FrameHeader for details on // the fixed 9-octet header structure shared by all frames). // Flag bits are only valid for specified frame types. -// TODO(jamessynge): Switch to using //gfe/http2/http2_constants.h when ready. +// TODO(jamessynge): Switch to using http2/http2_constants.h when ready. enum Http2HeaderFlag { NO_FLAGS = 0, @@ -109,7 +109,7 @@ }; // Returns name of frame type. -// TODO(jamessynge): Switch to using //gfe/http2/http2_constants.h when ready. +// TODO(jamessynge): Switch to using http2/http2_constants.h when ready. const char* Http2FrameTypeToString(Http2FrameType v); void SpdyDeframerVisitorInterface::OnPingAck( @@ -268,7 +268,7 @@ void SpdyTestDeframerImpl::AtGoAwayEnd() { DVLOG(1) << "AtDataEnd"; CHECK_EQ(frame_type_, GOAWAY); - if (ABSL_DIE_IF_NULL(goaway_description_)->empty()) { + if (HTTP2_DIE_IF_NULL(goaway_description_)->empty()) { listener_->OnGoAway(std::move(goaway_ir_)); } else { listener_->OnGoAway(SpdyMakeUnique<SpdyGoAwayIR>( @@ -751,7 +751,7 @@ CHECK(frame_type_ == HEADERS || frame_type_ == PUSH_PROMISE) << " frame_type_=" << Http2FrameTypeToString(frame_type_); CHECK(headers_ != nullptr); - CHECK_EQ(headers_->size(), 0u); + CHECK_EQ(0u, headers_->size()); got_hpack_end_ = false; } @@ -761,8 +761,8 @@ frame_type_ == PUSH_PROMISE) << " frame_type_=" << Http2FrameTypeToString(frame_type_); CHECK(!got_hpack_end_); - ABSL_DIE_IF_NULL(headers_)->emplace_back(SpdyString(key), SpdyString(value)); - ABSL_DIE_IF_NULL(headers_handler_)->OnHeader(key, value); + HTTP2_DIE_IF_NULL(headers_)->emplace_back(SpdyString(key), SpdyString(value)); + HTTP2_DIE_IF_NULL(headers_handler_)->OnHeader(key, value); } void SpdyTestDeframerImpl::OnHeaderBlockEnd( @@ -896,11 +896,11 @@ return *this; } -::testing::AssertionResult CollectedFrame::VerifyHasHeaders( +AssertionResult CollectedFrame::VerifyHasHeaders( const StringPairVector& expected_headers) const { VERIFY_NE(headers.get(), nullptr); VERIFY_THAT(*headers, ::testing::ContainerEq(expected_headers)); - return ::testing::AssertionSuccess(); + return AssertionSuccess(); } AssertionResult CollectedFrame::VerifyHasSettings( @@ -912,7 +912,7 @@ DeframerCallbackCollector::DeframerCallbackCollector( std::vector<CollectedFrame>* collected_frames) - : collected_frames_(ABSL_DIE_IF_NULL(collected_frames)) {} + : collected_frames_(HTTP2_DIE_IF_NULL(collected_frames)) {} void DeframerCallbackCollector::OnAltSvc( std::unique_ptr<SpdyAltSvcIR> frame_ir) {
diff --git a/spdy/core/spdy_deframer_visitor.h b/spdy/core/spdy_deframer_visitor.h index 6d57ffd..50d9987 100644 --- a/spdy/core/spdy_deframer_visitor.h +++ b/spdy/core/spdy_deframer_visitor.h
@@ -111,7 +111,7 @@ virtual ~SpdyDeframerVisitorInterface() {} // Wrap a visitor in another SpdyDeframerVisitorInterface that will - // VLOG each call, and will then forward the calls to the wrapped visitor + // DVLOG each call, and will then forward the calls to the wrapped visitor // (if provided; nullptr is OK). Takes ownership of the wrapped visitor. static std::unique_ptr<SpdyDeframerVisitorInterface> LogBeforeVisiting( std::unique_ptr<SpdyDeframerVisitorInterface> wrapped_visitor); @@ -195,8 +195,7 @@ typename X = typename std::enable_if<std::is_base_of<SpdyFrameIR, T>::value>> ::testing::AssertionResult VerifyHasFrame(const T& expected_ir) const { - VERIFY_SUCCESS(VerifySpdyFrameIREquals(expected_ir, frame_ir.get())); - return ::testing::AssertionSuccess(); + return VerifySpdyFrameIREquals(expected_ir, frame_ir.get()); } // Compare the collected headers against a StringPairVector. Ignores
diff --git a/spdy/core/spdy_deframer_visitor_test.cc b/spdy/core/spdy_deframer_visitor_test.cc index e1accec..ede1a20 100644 --- a/spdy/core/spdy_deframer_visitor_test.cc +++ b/spdy/core/spdy_deframer_visitor_test.cc
@@ -8,14 +8,10 @@ #include <algorithm> #include <limits> -#include <memory> -#include <utility> -#include "base/log_severity.h" #include "base/logging.h" -#include "strings/cord.h" -#include "testing/base/public/googletest.h" // for FLAGS_test_random_seed #include "testing/gtest/include/gtest/gtest.h" +#include "net/third_party/quiche/src/http2/test_tools/http2_random.h" #include "net/third_party/quiche/src/spdy/core/hpack/hpack_constants.h" #include "net/third_party/quiche/src/spdy/core/mock_spdy_framer_visitor.h" #include "net/third_party/quiche/src/spdy/core/spdy_frame_builder.h" @@ -25,7 +21,6 @@ #include "net/third_party/quiche/src/spdy/core/spdy_protocol_test_utils.h" #include "net/third_party/quiche/src/spdy/core/spdy_test_utils.h" #include "net/third_party/quiche/src/spdy/platform/api/spdy_ptr_util.h" -#include "util/random/mt_random.h" namespace spdy { namespace test { @@ -33,11 +28,7 @@ class SpdyDeframerVisitorTest : public ::testing::Test { protected: - SpdyDeframerVisitorTest() - : encoder_(SpdyFramer::ENABLE_COMPRESSION), - random_(FLAGS_test_random_seed) { - DLOG(INFO) << "Random seed (--test_random_seed): " - << FLAGS_test_random_seed; + SpdyDeframerVisitorTest() : encoder_(SpdyFramer::ENABLE_COMPRESSION) { decoder_.set_process_single_input_frame(true); auto collector = SpdyMakeUnique<DeframerCallbackCollector>(&collected_frames_); @@ -77,7 +68,7 @@ std::unique_ptr<SpdyTestDeframer> deframer_; private: - MTRandom random_; + http2::test::Http2Random random_; }; TEST_F(SpdyDeframerVisitorTest, DataFrame) { @@ -161,12 +152,12 @@ TEST_F(SpdyDeframerVisitorTest, PriorityFrame) { const char kFrameData[] = { - 0x00, 0x00, 0x05, // Length: 5 - 0x02, // Type: PRIORITY - 0x00, // Flags: none - 0x00, 0x00, 0x00, 0x65, // Stream: 101 - 0x80, 0x00, 0x00, 0x01, // Parent: 1 (Exclusive) - 0x10, // Weight: 17 + 0x00, 0x00, 0x05, // Length: 5 + 0x02, // Type: PRIORITY + 0x00, // Flags: none + 0x00, 0x00, 0x00, 0x65, // Stream: 101 + '\x80', 0x00, 0x00, 0x01, // Parent: 1 (Exclusive) + 0x10, // Weight: 17 }; EXPECT_TRUE(DeframeInput(kFrameData, sizeof kFrameData)); @@ -194,14 +185,14 @@ // values. The last one will be in the decoded SpdySettingsIR, but the vector // of settings will have both, in the same order. const char kFrameData[] = { - 0x00, 0x00, 0x0c, // Length - 0x04, // Type (SETTINGS) - 0x00, // Flags - 0x00, 0x00, 0x00, 0x00, // Stream id (must be zero) - 0x00, 0x04, // Setting id (SETTINGS_INITIAL_WINDOW_SIZE) - 0x0a, 0x0b, 0x0c, 0x0d, // Setting value - 0x00, 0x04, // Setting id (SETTINGS_INITIAL_WINDOW_SIZE) - 0x00, 0x00, 0x00, 0xff, // Setting value + 0x00, 0x00, 0x0c, // Length + 0x04, // Type (SETTINGS) + 0x00, // Flags + 0x00, 0x00, 0x00, 0x00, // Stream id (must be zero) + 0x00, 0x04, // Setting id (SETTINGS_INITIAL_WINDOW_SIZE) + 0x0a, 0x0b, 0x0c, 0x0d, // Setting value + 0x00, 0x04, // Setting id (SETTINGS_INITIAL_WINDOW_SIZE) + 0x00, 0x00, 0x00, '\xff', // Setting value }; EXPECT_TRUE(DeframeInput(kFrameData, sizeof kFrameData));
diff --git a/spdy/core/spdy_frame_builder.cc b/spdy/core/spdy_frame_builder.cc index 4a3753b..a056b70 100644 --- a/spdy/core/spdy_frame_builder.cc +++ b/spdy/core/spdy_frame_builder.cc
@@ -10,9 +10,9 @@ #include <new> #include "base/logging.h" -#include "net/third_party/quiche/src/spdy/core/spdy_bug_tracker.h" #include "net/third_party/quiche/src/spdy/core/spdy_protocol.h" #include "net/third_party/quiche/src/spdy/core/zero_copy_output_buffer.h" +#include "net/third_party/quiche/src/spdy/platform/api/spdy_bug_tracker.h" namespace spdy { @@ -90,7 +90,7 @@ uint8_t raw_frame_type = SerializeFrameType(type); DCHECK(IsDefinedFrameType(raw_frame_type)); DCHECK_EQ(0u, stream_id & ~kStreamIdMask); - SPDY_BUG_IF(length > spdy::kHttp2DefaultFramePayloadLimit) + SPDY_BUG_IF(length > kHttp2DefaultFramePayloadLimit) << "Frame length " << length_ << " is longer than frame size limit."; return BeginNewFrameInternal(raw_frame_type, flags, stream_id, length); }
diff --git a/spdy/core/spdy_frame_builder.h b/spdy/core/spdy_frame_builder.h index e0a853c..c569c8c 100644 --- a/spdy/core/spdy_frame_builder.h +++ b/spdy/core/spdy_frame_builder.h
@@ -5,17 +5,17 @@ #ifndef QUICHE_SPDY_CORE_SPDY_FRAME_BUILDER_H_ #define QUICHE_SPDY_CORE_SPDY_FRAME_BUILDER_H_ +#include <cstddef> #include <cstdint> #include <memory> -#include "base/logging.h" -#include "testing/production_stub/public/gunit_prod.h" -#include "net/third_party/quiche/src/spdy/core/spdy_bug_tracker.h" #include "net/third_party/quiche/src/spdy/core/spdy_protocol.h" #include "net/third_party/quiche/src/spdy/core/zero_copy_output_buffer.h" +#include "net/third_party/quiche/src/spdy/platform/api/spdy_bug_tracker.h" #include "net/third_party/quiche/src/spdy/platform/api/spdy_endianness_util.h" #include "net/third_party/quiche/src/spdy/platform/api/spdy_export.h" #include "net/third_party/quiche/src/spdy/platform/api/spdy_string_piece.h" +#include "net/third_party/quiche/src/spdy/platform/api/spdy_test_utils_prod.h" namespace spdy { @@ -88,23 +88,22 @@ return WriteBytes(reinterpret_cast<char*>(&value) + 1, sizeof(value) - 1); } bool WriteUInt32(uint32_t value) { - value = htonl(value); + value = SpdyHostToNet32(value); return WriteBytes(&value, sizeof(value)); } bool WriteUInt64(uint64_t value) { - uint32_t upper = htonl(value >> 32); - uint32_t lower = htonl(static_cast<uint32_t>(value)); + uint32_t upper = SpdyHostToNet32(static_cast<uint32_t>(value >> 32)); + uint32_t lower = SpdyHostToNet32(static_cast<uint32_t>(value)); return (WriteBytes(&upper, sizeof(upper)) && WriteBytes(&lower, sizeof(lower))); } bool WriteStringPiece32(const SpdyStringPiece value); - bool WriteBytes(const void* data, uint32_t data_len); private: - FRIEND_TEST(SpdyFrameBuilderTest, GetWritableBuffer); - FRIEND_TEST(SpdyFrameBuilderTest, GetWritableOutput); - FRIEND_TEST(SpdyFrameBuilderTest, GetWritableOutputNegative); + SPDY_FRIEND_TEST(SpdyFrameBuilderTest, GetWritableBuffer); + SPDY_FRIEND_TEST(SpdyFrameBuilderTest, GetWritableOutput); + SPDY_FRIEND_TEST(SpdyFrameBuilderTest, GetWritableOutputNegative); // Populates this frame with a HTTP2 frame prefix with type and length // information.
diff --git a/spdy/core/spdy_frame_reader.h b/spdy/core/spdy_frame_reader.h index 3ef69ea..dc6c064 100644 --- a/spdy/core/spdy_frame_reader.h +++ b/spdy/core/spdy_frame_reader.h
@@ -7,7 +7,6 @@ #include <cstdint> -#include "base/basictypes.h" #include "net/third_party/quiche/src/spdy/platform/api/spdy_export.h" #include "net/third_party/quiche/src/spdy/platform/api/spdy_string_piece.h"
diff --git a/spdy/core/spdy_frame_reader_test.cc b/spdy/core/spdy_frame_reader_test.cc index ad8c824..8caf60f 100644 --- a/spdy/core/spdy_frame_reader_test.cc +++ b/spdy/core/spdy_frame_reader_test.cc
@@ -3,9 +3,9 @@ // found in the LICENSE file. #include "net/third_party/quiche/src/spdy/core/spdy_frame_reader.h" + #include <cstdint> -#include "base/macros.h" #include "testing/gtest/include/gtest/gtest.h" #include "net/third_party/quiche/src/spdy/platform/api/spdy_arraysize.h" #include "net/third_party/quiche/src/spdy/platform/api/spdy_endianness_util.h" @@ -37,7 +37,7 @@ // Frame data in network byte order. const uint32_t kFrameData[] = { SpdyHostToNet32(1), - SpdyHostToNet32(static_cast<uint32_t>(1) << 31), + SpdyHostToNet32(0x80000000), }; SpdyFrameReader frame_reader(reinterpret_cast<const char*>(kFrameData),
diff --git a/spdy/core/spdy_framer.cc b/spdy/core/spdy_framer.cc index 7d60d84..fc9cc2e 100644 --- a/spdy/core/spdy_framer.cc +++ b/spdy/core/spdy_framer.cc
@@ -10,21 +10,16 @@ #include <list> #include <new> -#include "base/casts.h" -#include "base/commandlineflags.h" #include "base/logging.h" -#include "base/macros.h" -#include "gfe/gfe2/base/flag_utils.h" -#include "strings/ascii_ctype.h" -#include "third_party/absl/strings/case.h" +#include "net/third_party/quiche/src/http2/platform/api/http2_macros.h" #include "net/third_party/quiche/src/spdy/core/hpack/hpack_constants.h" #include "net/third_party/quiche/src/spdy/core/spdy_bitmasks.h" -#include "net/third_party/quiche/src/spdy/core/spdy_bug_tracker.h" #include "net/third_party/quiche/src/spdy/core/spdy_frame_builder.h" #include "net/third_party/quiche/src/spdy/core/spdy_frame_reader.h" +#include "net/third_party/quiche/src/spdy/platform/api/spdy_bug_tracker.h" +#include "net/third_party/quiche/src/spdy/platform/api/spdy_estimate_memory_usage.h" #include "net/third_party/quiche/src/spdy/platform/api/spdy_ptr_util.h" #include "net/third_party/quiche/src/spdy/platform/api/spdy_string_utils.h" -#include "util/gtl/lazy_static_ptr.h" namespace spdy { @@ -134,7 +129,7 @@ } if (!ret) { - DLOG(INFO) << "Failed to build HEADERS. Not enough space in output"; + DLOG(WARNING) << "Failed to build HEADERS. Not enough space in output"; } return ret; } @@ -427,7 +422,7 @@ } case SpdyFrameType::DATA: { DVLOG(1) << "Serialize a stream end DATA frame for VTL"; - ABSL_FALLTHROUGH_INTENDED; + HTTP2_FALLTHROUGH; } default: { return SpdyMakeUnique<SpdyControlFrameIterator>(framer, @@ -1293,4 +1288,8 @@ GetHpackEncoder()->SetHeaderTableDebugVisitor(std::move(visitor)); } +size_t SpdyFramer::EstimateMemoryUsage() const { + return SpdyEstimateMemoryUsage(hpack_encoder_); +} + } // namespace spdy
diff --git a/spdy/core/spdy_framer.h b/spdy/core/spdy_framer.h index 9c59642..e268994 100644 --- a/spdy/core/spdy_framer.h +++ b/spdy/core/spdy_framer.h
@@ -220,6 +220,9 @@ // Get (and lazily initialize) the HPACK encoder state. HpackEncoder* GetHpackEncoder(); + // Returns the estimate of dynamically allocated memory in bytes. + size_t EstimateMemoryUsage() const; + protected: friend class test::SpdyFramerPeer; friend class test::SpdyFramerTest_MultipleContinuationFramesWithIterator_Test;
diff --git a/spdy/core/spdy_framer_test.cc b/spdy/core/spdy_framer_test.cc index 163a769..a08d7d7 100644 --- a/spdy/core/spdy_framer_test.cc +++ b/spdy/core/spdy_framer_test.cc
@@ -12,14 +12,10 @@ #include <tuple> #include <vector> -#include "base/log_severity.h" #include "base/logging.h" #include "base/macros.h" -#include "strings/cord.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -#include "testing/base/public/mock-log.h" -#include "testing/base/public/test_utils.h" #include "net/third_party/quiche/src/spdy/core/array_output_buffer.h" #include "net/third_party/quiche/src/spdy/core/hpack/hpack_constants.h" #include "net/third_party/quiche/src/spdy/core/mock_spdy_framer_visitor.h" @@ -51,8 +47,6 @@ char frame_list_char[buffer_size] = ""; } // namespace -using ::spdy::operator==; - class MockDebugVisitor : public SpdyFramerDebugVisitorInterface { public: MOCK_METHOD4(OnSendCompressedFrame, @@ -120,7 +114,7 @@ SpdyFramer::SpdyHeaderFrameIterator it(framer, CloneSpdyHeadersIR(headers)); while (it.HasNextFrame()) { size_t size_before = frame_list_buffer.Size(); - EXPECT_GT(it.NextFrame(&frame_list_buffer), 0); + EXPECT_GT(it.NextFrame(&frame_list_buffer), 0u); frame_list.emplace_back( SpdySerializedFrame(frame_list_buffer.Begin() + size_before, frame_list_buffer.Size() - size_before, false)); @@ -150,7 +144,7 @@ SpdyFramer::SpdyHeaderFrameIterator it(framer, CloneSpdyHeadersIR(headers)); while (it.HasNextFrame()) { size_t size_before = frame_list_buffer.Size(); - EXPECT_GT(it.NextFrame(&frame_list_buffer), 0); + EXPECT_GT(it.NextFrame(&frame_list_buffer), 0u); frame_list.emplace_back( SpdySerializedFrame(frame_list_buffer.Begin() + size_before, frame_list_buffer.Size() - size_before, false)); @@ -189,7 +183,7 @@ framer, CloneSpdyPushPromiseIR(push_promise)); while (it.HasNextFrame()) { size_t size_before = frame_list_buffer.Size(); - EXPECT_GT(it.NextFrame(&frame_list_buffer), 0); + EXPECT_GT(it.NextFrame(&frame_list_buffer), 0u); frame_list.emplace_back( SpdySerializedFrame(frame_list_buffer.Begin() + size_before, frame_list_buffer.Size() - size_before, false)); @@ -222,7 +216,7 @@ framer, CloneSpdyPushPromiseIR(push_promise)); while (it.HasNextFrame()) { size_t size_before = frame_list_buffer.Size(); - EXPECT_GT(it.NextFrame(&frame_list_buffer), 0); + EXPECT_GT(it.NextFrame(&frame_list_buffer), 0u); frame_list.emplace_back( SpdySerializedFrame(frame_list_buffer.Begin() + size_before, frame_list_buffer.Size() - size_before, false)); @@ -579,8 +573,8 @@ // Exposes SpdyUnknownIR::set_length() for testing purposes. class TestSpdyUnknownIR : public SpdyUnknownIR { public: - using SpdyUnknownIR::SpdyUnknownIR; using SpdyUnknownIR::set_length; + using SpdyUnknownIR::SpdyUnknownIR; }; enum Output { USE, NOT_USE }; @@ -1130,8 +1124,24 @@ reinterpret_cast<unsigned char*>(control_frame.data()), control_frame.size()); - EXPECT_THAT(visitor.headers_, - testing::ElementsAre(testing::Pair("name", value))); + EXPECT_THAT(visitor.headers_, testing::ElementsAre(testing::Pair( + "name", SpdyStringPiece(value)))); +} + +TEST_P(SpdyFramerTest, CompressEmptyHeaders) { + // See https://crbug.com/172383/ + SpdyHeadersIR headers(1); + headers.SetHeader("server", "SpdyServer 1.0"); + headers.SetHeader("date", "Mon 12 Jan 2009 12:12:12 PST"); + headers.SetHeader("status", "200"); + headers.SetHeader("version", "HTTP/1.1"); + headers.SetHeader("content-type", "text/html"); + headers.SetHeader("content-length", "12"); + headers.SetHeader("x-empty-header", ""); + + SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION); + SpdySerializedFrame frame1( + SpdyFramerPeer::SerializeHeaders(&framer, headers, &output_)); } TEST_P(SpdyFramerTest, Basic) { @@ -1539,11 +1549,15 @@ SpdySerializedFrame frame(framer_.SerializeData(data_ir)); CompareFrame(kDescription, frame, kH2FrameData, SPDY_ARRAYSIZE(kH2FrameData)); + + frame = framer_.SerializeDataFrameHeaderWithPaddingLengthField(data_ir); + CompareCharArraysWithHexError( + kDescription, reinterpret_cast<const unsigned char*>(frame.data()), + kDataFrameMinimumSize, kH2FrameData, kDataFrameMinimumSize); } { const char kDescription[] = "Data frame with max stream ID"; - // clang-format on const unsigned char kH2FrameData[] = { 0x00, 0x00, 0x05, // Length: 5 0x00, // Type: DATA @@ -1582,7 +1596,6 @@ { const char kDescription[] = "RST_STREAM frame with max stream ID"; - // clang-format off const unsigned char kH2FrameData[] = { 0x00, 0x00, 0x04, // Length: 4 0x03, // Type: RST_STREAM @@ -1764,8 +1777,8 @@ 0x00, 0x00, 0x00, 0x00, // Error: NO_ERROR 0x47, 0x41, // Description }; - SpdyGoAwayIR goaway_ir(/* last_good_stream_id = */ 0, - ERROR_CODE_NO_ERROR, "GA"); + SpdyGoAwayIR goaway_ir(/* last_good_stream_id = */ 0, ERROR_CODE_NO_ERROR, + "GA"); SpdySerializedFrame frame(framer_.SerializeGoAway(goaway_ir)); if (use_output_) { ASSERT_TRUE(framer_.SerializeGoAway(goaway_ir, &output_)); @@ -2068,8 +2081,7 @@ if (use_output_) { output_.Reset(); ASSERT_TRUE(framer_.SerializeWindowUpdate( - SpdyWindowUpdateIR(/* stream_id = */ 1, /* delta = */ 1), - &output_)); + SpdyWindowUpdateIR(/* stream_id = */ 1, /* delta = */ 1), &output_)); frame = SpdySerializedFrame(output_.Begin(), output_.Size(), false); } CompareFrame(kDescription, frame, kH2FrameData, @@ -2094,8 +2106,8 @@ &output_)); frame = SpdySerializedFrame(output_.Begin(), output_.Size(), false); } - CompareFrame( - kDescription, frame, kH2FrameData, SPDY_ARRAYSIZE(kH2FrameData)); + CompareFrame(kDescription, frame, kH2FrameData, + SPDY_ARRAYSIZE(kH2FrameData)); } { @@ -2116,8 +2128,8 @@ &output_)); frame = SpdySerializedFrame(output_.Begin(), output_.Size(), false); } - CompareFrame( - kDescription, frame, kH2FrameData, SPDY_ARRAYSIZE(kH2FrameData)); + CompareFrame(kDescription, frame, kH2FrameData, + SPDY_ARRAYSIZE(kH2FrameData)); } } @@ -3699,8 +3711,8 @@ EXPECT_EQ(11u, kGetAltSvcFrameMinimumSize); EXPECT_EQ(9u, kFrameMinimumSize); - EXPECT_EQ(16384u, spdy::kHttp2DefaultFramePayloadLimit); - EXPECT_EQ(16393u, spdy::kHttp2DefaultFrameSizeLimit); + EXPECT_EQ(16384u, kHttp2DefaultFramePayloadLimit); + EXPECT_EQ(16393u, kHttp2DefaultFrameSizeLimit); } TEST_P(SpdyFramerTest, StateToStringTest) { @@ -4145,7 +4157,7 @@ headers_ir.SetHeader("foo", "bar"); SpdySerializedFrame frame0; if (use_output_) { - EXPECT_GT(framer.SerializeHeaders(headers_ir, &output_), 0); + EXPECT_TRUE(framer.SerializeHeaders(headers_ir, &output_)); frame0 = SpdySerializedFrame(output_.Begin(), output_.Size(), false); } else { frame0 = framer.SerializeHeaders(headers_ir); @@ -4156,7 +4168,7 @@ SpdySerializedFrame frame1; if (use_output_) { char* begin = output_.Begin() + output_.Size(); - EXPECT_GT(framer.SerializeContinuation(continuation, &output_), 0); + ASSERT_TRUE(framer.SerializeContinuation(continuation, &output_)); frame1 = SpdySerializedFrame(begin, output_.Size() - frame0.size(), false); } else { @@ -4283,7 +4295,8 @@ SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector; altsvc_vector.push_back(altsvc1); altsvc_vector.push_back(altsvc2); - EXPECT_CALL(visitor, OnAltSvc(kStreamId, "o_r|g!n", altsvc_vector)); + EXPECT_CALL(visitor, + OnAltSvc(kStreamId, SpdyStringPiece("o_r|g!n"), altsvc_vector)); SpdyAltSvcIR altsvc_ir(kStreamId); altsvc_ir.set_origin("o_r|g!n"); @@ -4317,7 +4330,7 @@ SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector; altsvc_vector.push_back(altsvc1); altsvc_vector.push_back(altsvc2); - EXPECT_CALL(visitor, OnAltSvc(kStreamId, "", altsvc_vector)); + EXPECT_CALL(visitor, OnAltSvc(kStreamId, SpdyStringPiece(""), altsvc_vector)); SpdyAltSvcIR altsvc_ir(kStreamId); altsvc_ir.add_altsvc(altsvc1); @@ -4374,6 +4387,7 @@ deframer_.set_visitor(&visitor); visitor.SimulateInFramer(kFrameDataOriginLenLargerThanFrame, sizeof(kFrameDataOriginLenLargerThanFrame)); + EXPECT_EQ(1, visitor.error_count_); EXPECT_EQ(Http2DecoderAdapter::SPDY_INVALID_CONTROL_FRAME, visitor.deframer_.spdy_framer_error());
diff --git a/spdy/core/spdy_header_block.cc b/spdy/core/spdy_header_block.cc index a6f49b9..dcf84b9 100644 --- a/spdy/core/spdy_header_block.cc +++ b/spdy/core/spdy_header_block.cc
@@ -9,12 +9,12 @@ #include <algorithm> #include <utility> -#include "base/arena.h" #include "base/logging.h" #include "base/macros.h" #include "net/third_party/quiche/src/spdy/platform/api/spdy_estimate_memory_usage.h" #include "net/third_party/quiche/src/spdy/platform/api/spdy_ptr_util.h" #include "net/third_party/quiche/src/spdy/platform/api/spdy_string_utils.h" +#include "net/third_party/quiche/src/spdy/platform/api/spdy_unsafe_arena.h" namespace spdy { namespace { @@ -90,8 +90,13 @@ size_t bytes_allocated() const { return arena_.status().bytes_allocated(); } + // TODO(xunjieli): https://crbug.com/669108. Merge this with bytes_allocated() + size_t EstimateMemoryUsage() const { + return arena_.status().bytes_allocated(); + } + private: - UnsafeArena arena_; + SpdyUnsafeArena arena_; }; SpdyHeaderBlock::HeaderValue::HeaderValue(Storage* storage,
diff --git a/spdy/core/spdy_header_block.h b/spdy/core/spdy_header_block.h index a63c52e..f453246 100644 --- a/spdy/core/spdy_header_block.h +++ b/spdy/core/spdy_header_block.h
@@ -10,13 +10,14 @@ #include <list> #include <memory> #include <utility> +#include <vector> #include "base/macros.h" -#include "base/port.h" +#include "net/third_party/quiche/src/spdy/platform/api/spdy_containers.h" #include "net/third_party/quiche/src/spdy/platform/api/spdy_export.h" +#include "net/third_party/quiche/src/spdy/platform/api/spdy_macros.h" #include "net/third_party/quiche/src/spdy/platform/api/spdy_string.h" #include "net/third_party/quiche/src/spdy/platform/api/spdy_string_piece.h" -#include "util/gtl/linked_hash_map.h" namespace spdy { @@ -81,7 +82,8 @@ size_t separator_size_ = 0; }; - typedef gtl::linked_hash_map<SpdyStringPiece, HeaderValue> MapType; + typedef SpdyLinkedHashMap<SpdyStringPiece, HeaderValue, SpdyStringPieceHash> + MapType; public: typedef std::pair<SpdyStringPiece, SpdyStringPiece> value_type; @@ -179,10 +181,10 @@ const SpdyStringPiece value); // Allows either lookup or mutation of the value associated with a key. - ValueProxy operator[](const SpdyStringPiece key) ABSL_MUST_USE_RESULT; + ValueProxy operator[](const SpdyStringPiece key) SPDY_MUST_USE_RESULT; // This object provides automatic conversions that allow SpdyHeaderBlock to be - // nearly a drop-in replacement for linked_hash_map<SpdyString, SpdyString>. + // nearly a drop-in replacement for SpdyLinkedHashMap<SpdyString, SpdyString>. // It reads data from or writes data to a SpdyHeaderBlock::Storage. class SPDY_EXPORT_PRIVATE ValueProxy { public:
diff --git a/spdy/core/spdy_protocol.cc b/spdy/core/spdy_protocol.cc index b9af3fe..f51dc6e 100644 --- a/spdy/core/spdy_protocol.cc +++ b/spdy/core/spdy_protocol.cc
@@ -6,7 +6,7 @@ #include <ostream> -#include "net/third_party/quiche/src/spdy/core/spdy_bug_tracker.h" +#include "net/third_party/quiche/src/spdy/platform/api/spdy_bug_tracker.h" #include "net/third_party/quiche/src/spdy/platform/api/spdy_ptr_util.h" #include "net/third_party/quiche/src/spdy/platform/api/spdy_string_utils.h"
diff --git a/spdy/core/spdy_protocol.h b/spdy/core/spdy_protocol.h index c384f2e..d300d10 100644 --- a/spdy/core/spdy_protocol.h +++ b/spdy/core/spdy_protocol.h
@@ -9,24 +9,25 @@ #ifndef QUICHE_SPDY_CORE_SPDY_PROTOCOL_H_ #define QUICHE_SPDY_CORE_SPDY_PROTOCOL_H_ +#include <cstddef> #include <cstdint> #include <iosfwd> #include <limits> #include <map> #include <memory> +#include <new> #include <utility> #include "base/logging.h" #include "base/macros.h" #include "net/third_party/quiche/src/spdy/core/spdy_alt_svc_wire_format.h" #include "net/third_party/quiche/src/spdy/core/spdy_bitmasks.h" -#include "net/third_party/quiche/src/spdy/core/spdy_bug_tracker.h" #include "net/third_party/quiche/src/spdy/core/spdy_header_block.h" +#include "net/third_party/quiche/src/spdy/platform/api/spdy_bug_tracker.h" #include "net/third_party/quiche/src/spdy/platform/api/spdy_export.h" #include "net/third_party/quiche/src/spdy/platform/api/spdy_ptr_util.h" #include "net/third_party/quiche/src/spdy/platform/api/spdy_string.h" #include "net/third_party/quiche/src/spdy/platform/api/spdy_string_piece.h" -#include "util/gtl/linked_hash_map.h" namespace spdy { @@ -230,7 +231,7 @@ // Reserved ID for root stream of HTTP/2 stream dependency tree, as specified // in RFC 7540 section 5.3.1. -const int kHttp2RootStreamId = 0; +const unsigned int kHttp2RootStreamId = 0; typedef uint64_t SpdyPingId; @@ -668,7 +669,6 @@ SpdyStreamId last_good_stream_id() const { return last_good_stream_id_; } void set_last_good_stream_id(SpdyStreamId last_good_stream_id) { - DCHECK_LE(0u, last_good_stream_id); DCHECK_EQ(0u, last_good_stream_id & ~kStreamIdMask); last_good_stream_id_ = last_good_stream_id; } @@ -986,6 +986,9 @@ return buffer; } + // Returns the estimate of dynamically allocated memory in bytes. + size_t EstimateMemoryUsage() const { return owns_buffer_ ? size_ : 0; } + protected: char* frame_;
diff --git a/spdy/core/spdy_protocol_test.cc b/spdy/core/spdy_protocol_test.cc index b1f999e..09a56cb 100644 --- a/spdy/core/spdy_protocol_test.cc +++ b/spdy/core/spdy_protocol_test.cc
@@ -9,7 +9,6 @@ #include <memory> #include "testing/gtest/include/gtest/gtest.h" -#include "testing/base/public/test_utils.h" #include "net/third_party/quiche/src/spdy/core/spdy_bitmasks.h" #include "net/third_party/quiche/src/spdy/core/spdy_test_utils.h"
diff --git a/spdy/core/spdy_test_utils.cc b/spdy/core/spdy_test_utils.cc index 7318e62..dd6c417 100644 --- a/spdy/core/spdy_test_utils.cc +++ b/spdy/core/spdy_test_utils.cc
@@ -7,10 +7,11 @@ #include <algorithm> #include <cstring> #include <memory> +#include <new> #include <utility> +#include <vector> #include "base/logging.h" -#include "strings/strcat.h" #include "testing/gtest/include/gtest/gtest.h" #include "net/third_party/quiche/src/spdy/platform/api/spdy_endianness_util.h" @@ -32,7 +33,7 @@ } SpdyString hex; - for (const unsigned char *row = data; length > 0; + for (const unsigned char* row = data; length > 0; row += kColumns, length -= kColumns) { for (const unsigned char* p = row; p < row + 4; ++p) { if (p < row + length) {
diff --git a/spdy/core/spdy_test_utils.h b/spdy/core/spdy_test_utils.h index a7375aa..bf62eeb 100644 --- a/spdy/core/spdy_test_utils.h +++ b/spdy/core/spdy_test_utils.h
@@ -5,21 +5,17 @@ #ifndef QUICHE_SPDY_CORE_SPDY_TEST_UTILS_H_ #define QUICHE_SPDY_CORE_SPDY_TEST_UTILS_H_ +#include <cstddef> #include <cstdint> -#include "gfe/gfe2/test_tools/failure.h" -#include "net/third_party/quiche/src/spdy/core/spdy_bug_tracker.h" +#include "net/third_party/quiche/src/http2/platform/api/http2_test_helpers.h" #include "net/third_party/quiche/src/spdy/core/spdy_header_block.h" #include "net/third_party/quiche/src/spdy/core/spdy_headers_handler_interface.h" #include "net/third_party/quiche/src/spdy/core/spdy_protocol.h" +#include "net/third_party/quiche/src/spdy/platform/api/spdy_bug_tracker.h" #include "net/third_party/quiche/src/spdy/platform/api/spdy_string.h" #include "net/third_party/quiche/src/spdy/platform/api/spdy_string_piece.h" - -// EXPECT_SPDY_BUG is like EXPECT_DFATAL, except it ensures that no DFATAL -// logging is skipped due to exponential backoff. -// -// For external SPDY, EXPECT_SPDY_BUG should be #defined to EXPECT_DFATAL. -#define EXPECT_SPDY_BUG EXPECT_GFE_BUG +#include "net/third_party/quiche/src/spdy/platform/api/spdy_test_helpers.h" namespace spdy {
diff --git a/spdy/platform/api/spdy_bug_tracker.h b/spdy/platform/api/spdy_bug_tracker.h new file mode 100644 index 0000000..d750a21 --- /dev/null +++ b/spdy/platform/api/spdy_bug_tracker.h
@@ -0,0 +1,15 @@ +// 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_SPDY_PLATFORM_API_SPDY_BUG_TRACKER_H_ +#define QUICHE_SPDY_PLATFORM_API_SPDY_BUG_TRACKER_H_ + +#include "net/spdy/platform/impl/spdy_bug_tracker_impl.h" + +#define SPDY_BUG SPDY_BUG_IMPL +#define SPDY_BUG_IF(condition) SPDY_BUG_IF_IMPL(condition) +#define FLAGS_spdy_always_log_bugs_for_tests \ + FLAGS_spdy_always_log_bugs_for_tests_impl + +#endif // QUICHE_SPDY_PLATFORM_API_SPDY_BUG_TRACKER_H_
diff --git a/spdy/platform/api/spdy_containers.h b/spdy/platform/api/spdy_containers.h index 71a20de..e4f4c49 100644 --- a/spdy/platform/api/spdy_containers.h +++ b/spdy/platform/api/spdy_containers.h
@@ -5,6 +5,7 @@ #ifndef QUICHE_SPDY_PLATFORM_API_SPDY_CONTAINERS_H_ #define QUICHE_SPDY_PLATFORM_API_SPDY_CONTAINERS_H_ +#include "net/third_party/quiche/src/spdy/platform/api/spdy_string_piece.h" #include "net/spdy/platform/impl/spdy_containers_impl.h" namespace spdy { @@ -22,6 +23,20 @@ template <typename ElementType, typename Hasher, typename Eq> using SpdyHashSet = SpdyHashSetImpl<ElementType, Hasher, Eq>; +// A map which offers insertion-ordered iteration. +template <typename Key, typename Value, typename Hash = SpdyHash<Key>> +using SpdyLinkedHashMap = SpdyLinkedHashMapImpl<Key, Value, Hash>; + +// A vector optimized for small sizes. Provides the same APIs as a std::vector. +template <typename T, size_t N, typename A = std::allocator<T>> +using SpdyInlinedVector = SpdyInlinedVectorImpl<T, N, A>; + +using SpdyStringPieceHash = SpdyStringPieceHashImpl; + +inline size_t SpdyHashStringPair(SpdyStringPiece a, SpdyStringPiece b) { + return SpdyHashStringPairImpl(a, b); +} + } // namespace spdy #endif // QUICHE_SPDY_PLATFORM_API_SPDY_CONTAINERS_H_
diff --git a/spdy/platform/api/spdy_endianness_util.h b/spdy/platform/api/spdy_endianness_util.h index 313a075..e4074d7 100644 --- a/spdy/platform/api/spdy_endianness_util.h +++ b/spdy/platform/api/spdy_endianness_util.h
@@ -1,3 +1,7 @@ +// Copyright (c) 2018 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_SPDY_PLATFORM_API_SPDY_ENDIANNESS_UTIL_H_ #define QUICHE_SPDY_PLATFORM_API_SPDY_ENDIANNESS_UTIL_H_
diff --git a/spdy/platform/api/spdy_macros.h b/spdy/platform/api/spdy_macros.h new file mode 100644 index 0000000..a75c957 --- /dev/null +++ b/spdy/platform/api/spdy_macros.h
@@ -0,0 +1,15 @@ +// 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_SPDY_PLATFORM_API_SPDY_MACROS_H_ +#define QUICHE_SPDY_PLATFORM_API_SPDY_MACROS_H_ + +#include "net/spdy/platform/impl/spdy_macros_impl.h" + +#define SPDY_MUST_USE_RESULT SPDY_MUST_USE_RESULT_IMPL +#define SPDY_UNUSED SPDY_UNUSED_IMPL + +#define SPDY_DVLOG_IF SPDY_DVLOG_IF_IMPL + +#endif // QUICHE_SPDY_PLATFORM_API_SPDY_MACROS_H_
diff --git a/spdy/platform/api/spdy_test_helpers.h b/spdy/platform/api/spdy_test_helpers.h new file mode 100644 index 0000000..367d330 --- /dev/null +++ b/spdy/platform/api/spdy_test_helpers.h
@@ -0,0 +1,12 @@ +// 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_SPDY_PLATFORM_API_SPDY_TEST_HELPERS_H_ +#define QUICHE_SPDY_PLATFORM_API_SPDY_TEST_HELPERS_H_ + +#include "net/spdy/platform/impl/spdy_test_helpers_impl.h" + +#define EXPECT_SPDY_BUG EXPECT_SPDY_BUG_IMPL + +#endif // QUICHE_SPDY_PLATFORM_API_SPDY_TEST_HELPERS_H_
diff --git a/spdy/platform/api/spdy_test_utils_prod.h b/spdy/platform/api/spdy_test_utils_prod.h new file mode 100644 index 0000000..1466770 --- /dev/null +++ b/spdy/platform/api/spdy_test_utils_prod.h
@@ -0,0 +1,12 @@ +// 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_SPDY_PLATFORM_API_SPDY_TEST_UTILS_PROD_H_ +#define QUICHE_SPDY_PLATFORM_API_SPDY_TEST_UTILS_PROD_H_ + +#include "net/spdy/platform/impl/spdy_test_utils_prod_impl.h" + +#define SPDY_FRIEND_TEST SPDY_FRIEND_TEST_IMPL + +#endif // QUICHE_SPDY_PLATFORM_API_SPDY_TEST_UTILS_PROD_H_
diff --git a/spdy/platform/api/spdy_unsafe_arena.h b/spdy/platform/api/spdy_unsafe_arena.h new file mode 100644 index 0000000..77185e1 --- /dev/null +++ b/spdy/platform/api/spdy_unsafe_arena.h
@@ -0,0 +1,16 @@ +// 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_SPDY_PLATFORM_API_SPDY_UNSAFE_ARENA_H_ +#define QUICHE_SPDY_PLATFORM_API_SPDY_UNSAFE_ARENA_H_ + +#include "net/spdy/platform/impl/spdy_unsafe_arena_impl.h" + +namespace spdy { + +using SpdyUnsafeArena = SpdyUnsafeArenaImpl; + +} // namespace spdy + +#endif // QUICHE_SPDY_PLATFORM_API_SPDY_UNSAFE_ARENA_H_