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 = {