Project import generated by Copybara.
PiperOrigin-RevId: 231652158
Change-Id: I80001699b542a5c823722d90d24fcdd014ef99e7
diff --git a/http2/hpack/decoder/hpack_entry_decoder.cc b/http2/hpack/decoder/hpack_entry_decoder.cc
index b227b18..96b9f06 100644
--- a/http2/hpack/decoder/hpack_entry_decoder.cc
+++ b/http2/hpack/decoder/hpack_entry_decoder.cc
@@ -192,7 +192,7 @@
bool HpackEntryDecoder::DispatchOnType(HpackEntryDecoderListener* listener) {
const HpackEntryType entry_type = entry_type_decoder_.entry_type();
- const uint64_t varint = entry_type_decoder_.varint();
+ const uint32_t varint = static_cast<uint32_t>(entry_type_decoder_.varint());
switch (entry_type) {
case HpackEntryType::kIndexedHeader:
// The entry consists solely of the entry type and varint. See:
diff --git a/http2/hpack/decoder/hpack_string_decoder.h b/http2/hpack/decoder/hpack_string_decoder.h
index 5e0d220..2128728 100644
--- a/http2/hpack/decoder/hpack_string_decoder.h
+++ b/http2/hpack/decoder/hpack_string_decoder.h
@@ -13,7 +13,6 @@
#include <algorithm>
#include <cstdint>
-#include <limits>
#include "base/logging.h"
#include "base/macros.h"
@@ -169,16 +168,8 @@
// false otherwise, in which case status set.
template <class Listener>
void OnStringStart(Listener* cb, DecodeStatus* status) {
- // HpackVarintDecoder::value() returns uint64_t.
- const uint64_t value = length_decoder_.value();
- // |remaining_| is size_t. Check for truncation on 32-bit platforms.
- // numeric_limits::max() is constexpr. On platforms where size_t is at
- // least 64 bit wide, the compiler should optimize away this branch.
- if (value > std::numeric_limits<size_t>::max()) {
- *status = DecodeStatus::kDecodeError;
- return;
- }
- remaining_ = static_cast<size_t>(value);
+ // TODO(vasilvv): fail explicitly in case of truncation.
+ remaining_ = static_cast<size_t>(length_decoder_.value());
// Make callback so consumer knows what is coming.
cb->OnStringStart(huffman_encoded_, remaining_);
}
diff --git a/http2/hpack/varint/hpack_varint_decoder.cc b/http2/hpack/varint/hpack_varint_decoder.cc
index dd64025..ac85247 100644
--- a/http2/hpack/varint/hpack_varint_decoder.cc
+++ b/http2/hpack/varint/hpack_varint_decoder.cc
@@ -4,7 +4,6 @@
#include "net/third_party/quiche/src/http2/hpack/varint/hpack_varint_decoder.h"
-#include "net/third_party/quiche/src/http2/platform/api/http2_flag_utils.h"
#include "net/third_party/quiche/src/http2/platform/api/http2_string_utils.h"
namespace http2 {
@@ -43,96 +42,67 @@
}
DecodeStatus HpackVarintDecoder::Resume(DecodeBuffer* db) {
- if (decode_64_bits_) {
- HTTP2_RELOADABLE_FLAG_COUNT(http2_varint_decode_64_bits);
- // There can be at most 10 continuation bytes. Offset is zero for the
- // first one and increases by 7 for each subsequent one.
- const uint8_t kMaxOffset = 63;
- CheckNotDone();
-
- // Process most extension bytes without the need for overflow checking.
- while (offset_ < kMaxOffset) {
- if (db->Empty()) {
- return DecodeStatus::kDecodeInProgress;
- }
-
- uint8_t byte = db->DecodeUInt8();
- uint64_t summand = byte & 0x7f;
-
- // Shifting a 7 bit value to the left by at most 56 places can never
- // overflow on uint64_t.
- DCHECK_LE(offset_, 56);
- DCHECK_LE(summand, std::numeric_limits<uint64_t>::max() >> offset_);
-
- summand <<= offset_;
-
- // At this point,
- // |value_| is at most (2^prefix_length - 1) + (2^49 - 1), and
- // |summand| is at most 255 << 56 (which is smaller than 2^63),
- // so adding them can never overflow on uint64_t.
- DCHECK_LE(value_, std::numeric_limits<uint64_t>::max() - summand);
-
- value_ += summand;
-
- // Decoding ends if continuation flag is not set.
- if ((byte & 0x80) == 0) {
- MarkDone();
- return DecodeStatus::kDecodeDone;
- }
-
- offset_ += 7;
- }
-
- if (db->Empty()) {
- return DecodeStatus::kDecodeInProgress;
- }
-
- DCHECK_EQ(kMaxOffset, offset_);
-
- uint8_t byte = db->DecodeUInt8();
- // No more extension bytes are allowed after this.
- if ((byte & 0x80) == 0) {
- uint64_t summand = byte & 0x7f;
- // Check for overflow in left shift.
- if (summand <= std::numeric_limits<uint64_t>::max() >> offset_) {
- summand <<= offset_;
- // Check for overflow in addition.
- if (value_ <= std::numeric_limits<uint64_t>::max() - summand) {
- value_ += summand;
- MarkDone();
- return DecodeStatus::kDecodeDone;
- }
- }
- }
-
- // Signal error if value is too large or there are too many extension bytes.
- DLOG(WARNING) << "Variable length int encoding is too large or too long. "
- << DebugString();
- MarkDone();
- return DecodeStatus::kDecodeError;
- }
-
- // Old code path. TODO(bnc): remove.
- DCHECK(!decode_64_bits_);
- const uint8_t kMaxOffset = 28;
+ // There can be at most 10 continuation bytes. Offset is zero for the
+ // first one and increases by 7 for each subsequent one.
+ const uint8_t kMaxOffset = 63;
CheckNotDone();
- do {
+
+ // Process most extension bytes without the need for overflow checking.
+ while (offset_ < kMaxOffset) {
if (db->Empty()) {
return DecodeStatus::kDecodeInProgress;
}
+
uint8_t byte = db->DecodeUInt8();
- if (offset_ == kMaxOffset && byte != 0)
- break;
- DCHECK(offset_ <= kMaxOffset - 7 || byte == 0);
- // Shifting a 7 bit value to the left by at most 21 places can never
- // overflow on uint32_t. Shifting 0 to the left cannot overflow either.
- value_ += (byte & 0x7f) << offset_;
+ uint64_t summand = byte & 0x7f;
+
+ // Shifting a 7 bit value to the left by at most 56 places can never
+ // overflow on uint64_t.
+ DCHECK_LE(offset_, 56);
+ DCHECK_LE(summand, std::numeric_limits<uint64_t>::max() >> offset_);
+
+ summand <<= offset_;
+
+ // At this point,
+ // |value_| is at most (2^prefix_length - 1) + (2^49 - 1), and
+ // |summand| is at most 255 << 56 (which is smaller than 2^63),
+ // so adding them can never overflow on uint64_t.
+ DCHECK_LE(value_, std::numeric_limits<uint64_t>::max() - summand);
+
+ value_ += summand;
+
+ // Decoding ends if continuation flag is not set.
if ((byte & 0x80) == 0) {
MarkDone();
return DecodeStatus::kDecodeDone;
}
+
offset_ += 7;
- } while (offset_ <= kMaxOffset);
+ }
+
+ if (db->Empty()) {
+ return DecodeStatus::kDecodeInProgress;
+ }
+
+ DCHECK_EQ(kMaxOffset, offset_);
+
+ uint8_t byte = db->DecodeUInt8();
+ // No more extension bytes are allowed after this.
+ if ((byte & 0x80) == 0) {
+ uint64_t summand = byte & 0x7f;
+ // Check for overflow in left shift.
+ if (summand <= std::numeric_limits<uint64_t>::max() >> offset_) {
+ summand <<= offset_;
+ // Check for overflow in addition.
+ if (value_ <= std::numeric_limits<uint64_t>::max() - summand) {
+ value_ += summand;
+ MarkDone();
+ return DecodeStatus::kDecodeDone;
+ }
+ }
+ }
+
+ // Signal error if value is too large or there are too many extension bytes.
DLOG(WARNING) << "Variable length int encoding is too large or too long. "
<< DebugString();
MarkDone();
diff --git a/http2/hpack/varint/hpack_varint_decoder.h b/http2/hpack/varint/hpack_varint_decoder.h
index c793500..5c99b5c 100644
--- a/http2/hpack/varint/hpack_varint_decoder.h
+++ b/http2/hpack/varint/hpack_varint_decoder.h
@@ -13,23 +13,16 @@
// For details of the encoding, see:
// http://httpwg.org/specs/rfc7541.html#integer.representation
//
-// If GetHttp2ReloadableFlag(http2_varint_decode_64_bits) is true, then this
-// decoder supports decoding any integer that can be represented on uint64_t,
-// thereby exceeding the requirements for QPACK: "QPACK implementations MUST be
-// able to decode integers up to 62 bits long." See
+// HpackVarintDecoder supports decoding any integer that can be represented on
+// uint64_t, thereby exceeding the requirements for QPACK: "QPACK
+// implementations MUST be able to decode integers up to 62 bits long." See
// https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#rfc.section.5.1.1
//
-// If GetHttp2ReloadableFlag(http2_varint_decode_64_bits) is false, then this
-// decoder supports decoding integers up to 2^28 + 2^prefix_length - 2.
-//
// This decoder supports at most 10 extension bytes (bytes following the prefix,
-// also called continuation bytes) if
-// GetHttp2ReloadableFlag(http2_varint_decode_64_bits) is true, and at most 5
-// extension bytes if GetHttp2ReloadableFlag(http2_varint_decode_64_bits) is
-// false. An encoder is allowed to zero pad the encoded integer on the left,
-// thereby increasing the number of extension bytes. If an encoder uses so much
-// padding that the number of extension bytes exceeds the limit, then this
-// decoder signals an error.
+// also called continuation bytes). An encoder is allowed to zero pad the
+// encoded integer on the left, thereby increasing the number of extension
+// bytes. If an encoder uses so much padding that the number of extension bytes
+// exceeds the limit, then this decoder signals an error.
#ifndef QUICHE_HTTP2_HPACK_VARINT_HPACK_VARINT_DECODER_H_
#define QUICHE_HTTP2_HPACK_VARINT_HPACK_VARINT_DECODER_H_
@@ -41,7 +34,6 @@
#include "net/third_party/quiche/src/http2/decoder/decode_buffer.h"
#include "net/third_party/quiche/src/http2/decoder/decode_status.h"
#include "net/third_party/quiche/src/http2/platform/api/http2_export.h"
-#include "net/third_party/quiche/src/http2/platform/api/http2_flags.h"
#include "net/third_party/quiche/src/http2/platform/api/http2_string.h"
namespace http2 {
@@ -119,12 +111,6 @@
#endif
}
- // If true, decode integers up to 2^64 - 1, and accept at most 10 extension
- // bytes (some of which might be padding).
- // If false, decode integers up to 2^28 + 2^prefix_length - 2, and accept at
- // most 5 extension bytes (some of which might be padding).
- bool decode_64_bits_ = GetHttp2ReloadableFlag(http2_varint_decode_64_bits);
-
// These fields are initialized just to keep ASAN happy about reading
// them from DebugString().
diff --git a/http2/hpack/varint/hpack_varint_decoder_test.cc b/http2/hpack/varint/hpack_varint_decoder_test.cc
index e36ad07..32a4a30 100644
--- a/http2/hpack/varint/hpack_varint_decoder_test.cc
+++ b/http2/hpack/varint/hpack_varint_decoder_test.cc
@@ -22,32 +22,13 @@
namespace test {
namespace {
-// Save previous value of flag and restore on destruction.
-class FlagSaver {
- public:
- FlagSaver() = delete;
- explicit FlagSaver(bool decode_64_bits)
- : saved_value_(GetHttp2ReloadableFlag(http2_varint_decode_64_bits)) {
- SetHttp2ReloadableFlag(http2_varint_decode_64_bits, decode_64_bits);
- }
- ~FlagSaver() {
- SetHttp2ReloadableFlag(http2_varint_decode_64_bits, saved_value_);
- }
-
- private:
- const bool saved_value_;
-};
-
-class HpackVarintDecoderTest
- : public RandomDecoderTest,
- public ::testing::WithParamInterface<
- ::testing::tuple<bool, uint8_t, const char*>> {
+class HpackVarintDecoderTest : public RandomDecoderTest,
+ public ::testing::WithParamInterface<
+ ::testing::tuple<uint8_t, const char*>> {
protected:
HpackVarintDecoderTest()
- : decode_64_bits_(::testing::get<0>(GetParam())),
- high_bits_(::testing::get<1>(GetParam())),
- suffix_(Http2HexDecode(::testing::get<2>(GetParam()))),
- flag_saver_(decode_64_bits_),
+ : high_bits_(::testing::get<0>(GetParam())),
+ suffix_(Http2HexDecode(::testing::get<1>(GetParam()))),
prefix_length_(0) {}
void DecodeExpectSuccess(Http2StringPiece data,
@@ -81,8 +62,6 @@
EXPECT_TRUE(Decode(data, prefix_length, validator));
}
- bool decode_64_bits() const { return decode_64_bits_; }
-
private:
AssertionResult Decode(Http2StringPiece data,
uint32_t prefix_length,
@@ -119,16 +98,11 @@
return decoder_.Resume(b);
}
- // Test new or old behavior.
- const bool decode_64_bits_;
// Bits of the first byte not part of the prefix.
const uint8_t high_bits_;
// Extra bytes appended to the input.
const Http2String suffix_;
- // |flag_saver_| must preceed |decoder_| so that the flag is already set when
- // |decoder_| is constructed.
- FlagSaver flag_saver_;
HpackVarintDecoder decoder_;
uint8_t prefix_length_;
};
@@ -137,15 +111,11 @@
HpackVarintDecoderTest,
HpackVarintDecoderTest,
::testing::Combine(
- // Test both the new version (supporting 64 bit integers) and the old
- // one (only supporting up to 2^28 + 2^prefix_length - 2.
- ::testing::Bool(),
// Bits of the first byte not part of the prefix should be ignored.
::testing::Values(0b00000000, 0b11111111, 0b10101010),
// Extra bytes appended to the input should be ignored.
::testing::Values("", "00", "666f6f")));
-// Test data used when decode_64_bits() == true.
struct {
const char* data;
uint32_t prefix_length;
@@ -289,124 +259,14 @@
{"1f9a0a", 5, 1337},
};
-// Test data used when decode_64_bits() == false.
-struct {
- const char* data;
- uint32_t prefix_length;
- uint64_t expected_value;
-} kSuccessTestDataOld[] = {
- // Zero value with different prefix lengths.
- {"00", 3, 0},
- {"00", 4, 0},
- {"00", 5, 0},
- {"00", 6, 0},
- {"00", 7, 0},
- // Small values that fit in the prefix.
- {"06", 3, 6},
- {"0d", 4, 13},
- {"10", 5, 16},
- {"29", 6, 41},
- {"56", 7, 86},
- // Values of 2^n-1, which have an all-zero extension byte.
- {"0700", 3, 7},
- {"0f00", 4, 15},
- {"1f00", 5, 31},
- {"3f00", 6, 63},
- {"7f00", 7, 127},
- // Values of 2^n-1, plus one extra byte of padding.
- {"078000", 3, 7},
- {"0f8000", 4, 15},
- {"1f8000", 5, 31},
- {"3f8000", 6, 63},
- {"7f8000", 7, 127},
- // Values requiring one extension byte.
- {"0760", 3, 103},
- {"0f2a", 4, 57},
- {"1f7f", 5, 158},
- {"3f02", 6, 65},
- {"7f49", 7, 200},
- // Values requiring one extension byte, plus one byte of padding.
- {"07e000", 3, 103},
- {"0faa00", 4, 57},
- {"1fff00", 5, 158},
- {"3f8200", 6, 65},
- {"7fc900", 7, 200},
- // Values requiring one extension byte, plus two bytes of padding.
- {"07e08000", 3, 103},
- {"0faa8000", 4, 57},
- {"1fff8000", 5, 158},
- {"3f828000", 6, 65},
- {"7fc98000", 7, 200},
- // Values requiring one extension byte, plus the maximum amount of padding.
- {"07e080808000", 3, 103},
- {"0faa80808000", 4, 57},
- {"1fff80808000", 5, 158},
- {"3f8280808000", 6, 65},
- {"7fc980808000", 7, 200},
- // Values requiring two extension bytes.
- {"07b260", 3, 12345},
- {"0f8a2a", 4, 5401},
- {"1fa87f", 5, 16327},
- {"3fd002", 6, 399},
- {"7fff49", 7, 9598},
- // Values requiring two extension bytes, plus one byte of padding.
- {"07b2e000", 3, 12345},
- {"0f8aaa00", 4, 5401},
- {"1fa8ff00", 5, 16327},
- {"3fd08200", 6, 399},
- {"7fffc900", 7, 9598},
- // Values requiring two extension bytes, plus the maximum amount of padding.
- {"07b2e0808000", 3, 12345},
- {"0f8aaa808000", 4, 5401},
- {"1fa8ff808000", 5, 16327},
- {"3fd082808000", 6, 399},
- {"7fffc9808000", 7, 9598},
- // Values requiring three extension bytes.
- {"078ab260", 3, 1579281},
- {"0fc18a2a", 4, 689488},
- {"1fada87f", 5, 2085964},
- {"3fa0d002", 6, 43103},
- {"7ffeff49", 7, 1212541},
- // Values requiring three extension bytes, plus one byte of padding.
- {"078ab2e000", 3, 1579281},
- {"0fc18aaa00", 4, 689488},
- {"1fada8ff00", 5, 2085964},
- {"3fa0d08200", 6, 43103},
- {"7ffeffc900", 7, 1212541},
- // Values requiring four extension bytes.
- {"079f8ab260", 3, 202147110},
- {"0fa2c18a2a", 4, 88252593},
- {"1fd0ada87f", 5, 266999535},
- {"3ff9a0d002", 6, 5509304},
- {"7f9efeff49", 7, 155189149},
- // Values requiring four extension bytes, plus one byte of padding.
- {"079f8ab2e000", 3, 202147110},
- {"0fa2c18aaa00", 4, 88252593},
- {"1fd0ada8ff00", 5, 266999535},
- {"3ff9a0d08200", 6, 5509304},
- {"7f9efeffc900", 7, 155189149},
- // Examples from RFC7541 C.1.
- {"0a", 5, 10},
- {"1f9a0a", 5, 1337},
-};
-
TEST_P(HpackVarintDecoderTest, Success) {
- if (decode_64_bits()) {
for (size_t i = 0; i < HTTP2_ARRAYSIZE(kSuccessTestData); ++i) {
DecodeExpectSuccess(Http2HexDecode(kSuccessTestData[i].data),
kSuccessTestData[i].prefix_length,
kSuccessTestData[i].expected_value);
}
- } else {
- for (size_t i = 0; i < HTTP2_ARRAYSIZE(kSuccessTestDataOld); ++i) {
- DecodeExpectSuccess(Http2HexDecode(kSuccessTestDataOld[i].data),
- kSuccessTestDataOld[i].prefix_length,
- kSuccessTestDataOld[i].expected_value);
- }
- }
}
-// Test data used when decode_64_bits() == true.
struct {
const char* data;
uint32_t prefix_length;
@@ -440,45 +300,11 @@
{"7f80ffffffffffffffff8100", 7},
{"ff80feffffffffffffff8100", 8}};
-// Test data used when decode_64_bits() == false.
-// In this mode, HpackVarintDecoder allows at most five extension bytes,
-// and fifth extension byte must be zero.
-struct {
- const char* data;
- uint32_t prefix_length;
-} kErrorTestDataOld[] = {
- // Maximum number of extension bytes but last byte is non-zero.
- {"078080808001", 3},
- {"0f8080808001", 4},
- {"1f8080808001", 5},
- {"3f8080808001", 6},
- {"7f8080808001", 7},
- // Too many extension bytes, all 0s (except for extension bit in each byte).
- {"078080808080", 3},
- {"0f8080808080", 4},
- {"1f8080808080", 5},
- {"3f8080808080", 6},
- {"7f8080808080", 7},
- // Too many extension bytes, all 1s.
- {"07ffffffffff", 3},
- {"0fffffffffff", 4},
- {"1fffffffffff", 5},
- {"3fffffffffff", 6},
- {"7fffffffffff", 7},
-};
-
TEST_P(HpackVarintDecoderTest, Error) {
- if (decode_64_bits()) {
for (size_t i = 0; i < HTTP2_ARRAYSIZE(kErrorTestData); ++i) {
DecodeExpectError(Http2HexDecode(kErrorTestData[i].data),
kErrorTestData[i].prefix_length);
}
- } else {
- for (size_t i = 0; i < HTTP2_ARRAYSIZE(kErrorTestDataOld); ++i) {
- DecodeExpectError(Http2HexDecode(kErrorTestDataOld[i].data),
- kErrorTestDataOld[i].prefix_length);
- }
- }
}
} // namespace
diff --git a/http2/hpack/varint/hpack_varint_round_trip_test.cc b/http2/hpack/varint/hpack_varint_round_trip_test.cc
index 3299d5e..cd26553 100644
--- a/http2/hpack/varint/hpack_varint_round_trip_test.cc
+++ b/http2/hpack/varint/hpack_varint_round_trip_test.cc
@@ -22,29 +22,11 @@
using ::testing::AssertionFailure;
using ::testing::AssertionSuccess;
-using ::testing::Bool;
-using ::testing::WithParamInterface;
namespace http2 {
namespace test {
namespace {
-// Save previous value of flag and restore on destruction.
-class FlagSaver {
- public:
- FlagSaver() = delete;
- explicit FlagSaver(bool decode_64_bits)
- : saved_value_(GetHttp2ReloadableFlag(http2_varint_decode_64_bits)) {
- SetHttp2ReloadableFlag(http2_varint_decode_64_bits, decode_64_bits);
- }
- ~FlagSaver() {
- SetHttp2ReloadableFlag(http2_varint_decode_64_bits, saved_value_);
- }
-
- private:
- const bool saved_value_;
-};
-
// Returns the highest value with the specified number of extension bytes
// and the specified prefix length (bits).
uint64_t HiValueOfExtensionBytes(uint32_t extension_bytes,
@@ -53,13 +35,9 @@
(extension_bytes == 0 ? 0 : (1LLU << (extension_bytes * 7)));
}
-class HpackVarintRoundTripTest : public RandomDecoderTest,
- public WithParamInterface<bool> {
+class HpackVarintRoundTripTest : public RandomDecoderTest {
protected:
- HpackVarintRoundTripTest()
- : decode_64_bits_(GetParam()),
- flag_saver_(decode_64_bits_),
- prefix_length_(0) {}
+ HpackVarintRoundTripTest() : prefix_length_(0) {}
DecodeStatus StartDecoding(DecodeBuffer* b) override {
CHECK_LT(0u, b->Remaining());
@@ -260,22 +238,14 @@
EncodeAndDecodeValues(values, prefix_length, expected_bytes);
}
- // |flag_saver_| must preceed |decoder_| so that the flag is already set when
- // |decoder_| is constructed.
- const bool decode_64_bits_;
- FlagSaver flag_saver_;
HpackVarintDecoder decoder_;
Http2String buffer_;
uint8_t prefix_length_;
};
-INSTANTIATE_TEST_CASE_P(HpackVarintRoundTripTest,
- HpackVarintRoundTripTest,
- Bool());
-
// To help me and future debuggers of varint encodings, this LOGs out the
// transition points where a new extension byte is added.
-TEST_P(HpackVarintRoundTripTest, Encode) {
+TEST_F(HpackVarintRoundTripTest, Encode) {
for (int prefix_length = 3; prefix_length <= 8; ++prefix_length) {
const uint64_t a = HiValueOfExtensionBytes(0, prefix_length);
const uint64_t b = HiValueOfExtensionBytes(1, prefix_length);
@@ -300,19 +270,13 @@
b - 1, b, b + 1, b + 2, b + 3, // Force line break.
c - 1, c, c + 1, c + 2, c + 3, // Force line break.
d - 1, d, d + 1, d + 2, d + 3, // Force line break.
- e - 1, e, e + 1, e + 2, e + 3 // Force line break.
+ e - 1, e, e + 1, e + 2, e + 3, // Force line break.
+ f - 1, f, f + 1, f + 2, f + 3, // Force line break.
+ g - 1, g, g + 1, g + 2, g + 3, // Force line break.
+ h - 1, h, h + 1, h + 2, h + 3, // Force line break.
+ i - 1, i, i + 1, i + 2, i + 3, // Force line break.
+ j - 1, j, j + 1, j + 2, j + 3, // Force line break.
};
- if (decode_64_bits_) {
- for (auto value : {
- f - 1, f, f + 1, f + 2, f + 3, // Force line break.
- g - 1, g, g + 1, g + 2, g + 3, // Force line break.
- h - 1, h, h + 1, h + 2, h + 3, // Force line break.
- i - 1, i, i + 1, i + 2, i + 3, // Force line break.
- j - 1, j, j + 1, j + 2, j + 3, // Force line break.
- }) {
- values.push_back(value);
- }
- }
for (uint64_t value : values) {
EncodeNoRandom(value, prefix_length);
@@ -323,7 +287,7 @@
}
}
-TEST_P(HpackVarintRoundTripTest, FromSpec1337) {
+TEST_F(HpackVarintRoundTripTest, FromSpec1337) {
DecodeBuffer b(Http2StringPiece("\x1f\x9a\x0a"));
uint32_t prefix_length = 5;
uint8_t p = b.DecodeUInt8();
@@ -340,7 +304,7 @@
}
// Test all the values that fit into the prefix (one less than the mask).
-TEST_P(HpackVarintRoundTripTest, ValidatePrefixOnly) {
+TEST_F(HpackVarintRoundTripTest, ValidatePrefixOnly) {
for (int prefix_length = 3; prefix_length <= 8; ++prefix_length) {
const uint8_t prefix_mask = (1 << prefix_length) - 1;
EncodeAndDecodeValuesInRange(0, prefix_mask, prefix_length, 1);
@@ -348,7 +312,7 @@
}
// Test all values that require exactly 1 extension byte.
-TEST_P(HpackVarintRoundTripTest, ValidateOneExtensionByte) {
+TEST_F(HpackVarintRoundTripTest, ValidateOneExtensionByte) {
for (int prefix_length = 3; prefix_length <= 8; ++prefix_length) {
const uint64_t start = HiValueOfExtensionBytes(0, prefix_length) + 1;
EncodeAndDecodeValuesInRange(start, 128, prefix_length, 2);
@@ -356,7 +320,7 @@
}
// Test *some* values that require exactly 2 extension bytes.
-TEST_P(HpackVarintRoundTripTest, ValidateTwoExtensionBytes) {
+TEST_F(HpackVarintRoundTripTest, ValidateTwoExtensionBytes) {
for (int prefix_length = 3; prefix_length <= 8; ++prefix_length) {
const uint64_t start = HiValueOfExtensionBytes(1, prefix_length) + 1;
const uint64_t range = 127 << 7;
@@ -366,7 +330,7 @@
}
// Test *some* values that require 3 extension bytes.
-TEST_P(HpackVarintRoundTripTest, ValidateThreeExtensionBytes) {
+TEST_F(HpackVarintRoundTripTest, ValidateThreeExtensionBytes) {
for (int prefix_length = 3; prefix_length <= 8; ++prefix_length) {
const uint64_t start = HiValueOfExtensionBytes(2, prefix_length) + 1;
const uint64_t range = 127 << 14;
@@ -376,7 +340,7 @@
}
// Test *some* values that require 4 extension bytes.
-TEST_P(HpackVarintRoundTripTest, ValidateFourExtensionBytes) {
+TEST_F(HpackVarintRoundTripTest, ValidateFourExtensionBytes) {
for (int prefix_length = 3; prefix_length <= 8; ++prefix_length) {
const uint64_t start = HiValueOfExtensionBytes(3, prefix_length) + 1;
const uint64_t range = 127 << 21;
@@ -386,11 +350,7 @@
}
// Test *some* values that require 5 extension bytes.
-TEST_P(HpackVarintRoundTripTest, ValidateFiveExtensionBytes) {
- if (!decode_64_bits_) {
- return;
- }
-
+TEST_F(HpackVarintRoundTripTest, ValidateFiveExtensionBytes) {
for (int prefix_length = 3; prefix_length <= 8; ++prefix_length) {
const uint64_t start = HiValueOfExtensionBytes(4, prefix_length) + 1;
const uint64_t range = 127llu << 28;
@@ -400,11 +360,7 @@
}
// Test *some* values that require 6 extension bytes.
-TEST_P(HpackVarintRoundTripTest, ValidateSixExtensionBytes) {
- if (!decode_64_bits_) {
- return;
- }
-
+TEST_F(HpackVarintRoundTripTest, ValidateSixExtensionBytes) {
for (int prefix_length = 3; prefix_length <= 8; ++prefix_length) {
const uint64_t start = HiValueOfExtensionBytes(5, prefix_length) + 1;
const uint64_t range = 127llu << 35;
@@ -414,11 +370,7 @@
}
// Test *some* values that require 7 extension bytes.
-TEST_P(HpackVarintRoundTripTest, ValidateSevenExtensionBytes) {
- if (!decode_64_bits_) {
- return;
- }
-
+TEST_F(HpackVarintRoundTripTest, ValidateSevenExtensionBytes) {
for (int prefix_length = 3; prefix_length <= 8; ++prefix_length) {
const uint64_t start = HiValueOfExtensionBytes(6, prefix_length) + 1;
const uint64_t range = 127llu << 42;
@@ -428,11 +380,7 @@
}
// Test *some* values that require 8 extension bytes.
-TEST_P(HpackVarintRoundTripTest, ValidateEightExtensionBytes) {
- if (!decode_64_bits_) {
- return;
- }
-
+TEST_F(HpackVarintRoundTripTest, ValidateEightExtensionBytes) {
for (int prefix_length = 3; prefix_length <= 8; ++prefix_length) {
const uint64_t start = HiValueOfExtensionBytes(7, prefix_length) + 1;
const uint64_t range = 127llu << 49;
@@ -442,11 +390,7 @@
}
// Test *some* values that require 9 extension bytes.
-TEST_P(HpackVarintRoundTripTest, ValidateNineExtensionBytes) {
- if (!decode_64_bits_) {
- return;
- }
-
+TEST_F(HpackVarintRoundTripTest, ValidateNineExtensionBytes) {
for (int prefix_length = 3; prefix_length <= 8; ++prefix_length) {
const uint64_t start = HiValueOfExtensionBytes(8, prefix_length) + 1;
const uint64_t range = 127llu << 56;
@@ -456,11 +400,7 @@
}
// Test *some* values that require 10 extension bytes.
-TEST_P(HpackVarintRoundTripTest, ValidateTenExtensionBytes) {
- if (!decode_64_bits_) {
- return;
- }
-
+TEST_F(HpackVarintRoundTripTest, ValidateTenExtensionBytes) {
for (int prefix_length = 3; prefix_length <= 8; ++prefix_length) {
const uint64_t start = HiValueOfExtensionBytes(9, prefix_length) + 1;
const uint64_t range = std::numeric_limits<uint64_t>::max() - start;
@@ -469,45 +409,6 @@
}
}
-// Test the value one larger than the largest that can be decoded.
-TEST_P(HpackVarintRoundTripTest, ValueTooLarge) {
- // New implementation can decode any integer that HpackVarintEncoder can
- // encode.
- if (decode_64_bits_) {
- return;
- }
-
- for (prefix_length_ = 3; prefix_length_ <= 8; ++prefix_length_) {
- const uint64_t too_large = (1 << 28) + (1 << prefix_length_) - 1;
- const uint32_t expected_offset = 6;
- HpackBlockBuilder bb;
- bb.AppendHighBitsAndVarint(0, prefix_length_, too_large);
- buffer_ = bb.buffer();
-
- // The validator is called after each of the several times that the input
- // DecodeBuffer is decoded, each with a different segmentation of the input.
- // Validate that decoder_.value() matches the expected value.
- bool validated = false;
- Validator validator = [&validated, expected_offset](
- const DecodeBuffer& db,
- DecodeStatus status) -> AssertionResult {
- validated = true;
- VERIFY_EQ(DecodeStatus::kDecodeError, status);
- VERIFY_EQ(expected_offset, db.Offset());
- return AssertionSuccess();
- };
-
- // StartDecoding, above, requires the DecodeBuffer be non-empty so that it
- // can call Start with the prefix byte.
- bool return_non_zero_on_first = true;
- DecodeBuffer b(buffer_);
- EXPECT_TRUE(
- DecodeAndValidateSeveralWays(&b, return_non_zero_on_first, validator));
- EXPECT_EQ(expected_offset, b.Offset());
- EXPECT_TRUE(validated);
- }
-}
-
} // namespace
} // namespace test
} // namespace http2
diff --git a/quic/core/chlo_extractor_test.cc b/quic/core/chlo_extractor_test.cc
index b1c470c..d16050b 100644
--- a/quic/core/chlo_extractor_test.cc
+++ b/quic/core/chlo_extractor_test.cc
@@ -52,7 +52,7 @@
header_.version = AllSupportedVersions().front();
header_.reset_flag = false;
header_.packet_number_length = PACKET_4BYTE_PACKET_NUMBER;
- header_.packet_number = 1;
+ header_.packet_number = QuicPacketNumber(1);
}
void MakePacket(const QuicStreamFrame& stream_frame) {
diff --git a/quic/core/congestion_control/bandwidth_sampler.cc b/quic/core/congestion_control/bandwidth_sampler.cc
index 47d55d6..c60eaa2 100644
--- a/quic/core/congestion_control/bandwidth_sampler.cc
+++ b/quic/core/congestion_control/bandwidth_sampler.cc
@@ -18,9 +18,7 @@
total_bytes_sent_at_last_acked_packet_(0),
last_acked_packet_sent_time_(QuicTime::Zero()),
last_acked_packet_ack_time_(QuicTime::Zero()),
- last_sent_packet_(0),
is_app_limited_(false),
- end_of_app_limited_phase_(0),
connection_state_map_() {}
BandwidthSampler::~BandwidthSampler() {}
diff --git a/quic/core/congestion_control/bandwidth_sampler_test.cc b/quic/core/congestion_control/bandwidth_sampler_test.cc
index 4203686..e9b74c7 100644
--- a/quic/core/congestion_control/bandwidth_sampler_test.cc
+++ b/quic/core/congestion_control/bandwidth_sampler_test.cc
@@ -40,54 +40,55 @@
BandwidthSampler sampler_;
QuicByteCount bytes_in_flight_;
- void SendPacketInner(QuicPacketNumber packet_number,
+ void SendPacketInner(uint64_t packet_number,
QuicByteCount bytes,
HasRetransmittableData has_retransmittable_data) {
- sampler_.OnPacketSent(clock_.Now(), packet_number, bytes, bytes_in_flight_,
- has_retransmittable_data);
+ sampler_.OnPacketSent(clock_.Now(), QuicPacketNumber(packet_number), bytes,
+ bytes_in_flight_, has_retransmittable_data);
if (has_retransmittable_data == HAS_RETRANSMITTABLE_DATA) {
bytes_in_flight_ += bytes;
}
}
- void SendPacket(QuicPacketNumber packet_number) {
+ void SendPacket(uint64_t packet_number) {
SendPacketInner(packet_number, kRegularPacketSize,
HAS_RETRANSMITTABLE_DATA);
}
- BandwidthSample AckPacketInner(QuicPacketNumber packet_number) {
- QuicByteCount size =
- BandwidthSamplerPeer::GetPacketSize(sampler_, packet_number);
+ BandwidthSample AckPacketInner(uint64_t packet_number) {
+ QuicByteCount size = BandwidthSamplerPeer::GetPacketSize(
+ sampler_, QuicPacketNumber(packet_number));
bytes_in_flight_ -= size;
- return sampler_.OnPacketAcknowledged(clock_.Now(), packet_number);
+ return sampler_.OnPacketAcknowledged(clock_.Now(),
+ QuicPacketNumber(packet_number));
}
// Acknowledge receipt of a packet and expect it to be not app-limited.
- QuicBandwidth AckPacket(QuicPacketNumber packet_number) {
+ QuicBandwidth AckPacket(uint64_t packet_number) {
BandwidthSample sample = AckPacketInner(packet_number);
EXPECT_FALSE(sample.is_app_limited);
return sample.bandwidth;
}
- void LosePacket(QuicPacketNumber packet_number) {
- QuicByteCount size =
- BandwidthSamplerPeer::GetPacketSize(sampler_, packet_number);
+ void LosePacket(uint64_t packet_number) {
+ QuicByteCount size = BandwidthSamplerPeer::GetPacketSize(
+ sampler_, QuicPacketNumber(packet_number));
bytes_in_flight_ -= size;
- sampler_.OnPacketLost(packet_number);
+ sampler_.OnPacketLost(QuicPacketNumber(packet_number));
}
// Sends one packet and acks it. Then, send 20 packets. Finally, send
// another 20 packets while acknowledging previous 20.
void Send40PacketsAndAckFirst20(QuicTime::Delta time_between_packets) {
// Send 20 packets at a constant inter-packet time.
- for (QuicPacketNumber i = 1; i <= 20; i++) {
+ for (int i = 1; i <= 20; i++) {
SendPacket(i);
clock_.AdvanceTime(time_between_packets);
}
// Ack packets 1 to 20, while sending new packets at the same rate as
// before.
- for (QuicPacketNumber i = 1; i <= 20; i++) {
+ for (int i = 1; i <= 20; i++) {
AckPacket(i);
SendPacket(i + 20);
clock_.AdvanceTime(time_between_packets);
@@ -102,7 +103,7 @@
QuicBandwidth::FromBytesPerSecond(kRegularPacketSize * 100);
// Send packets at the constant bandwidth.
- for (QuicPacketNumber i = 1; i < 20; i++) {
+ for (int i = 1; i < 20; i++) {
SendPacket(i);
clock_.AdvanceTime(time_between_packets);
QuicBandwidth current_sample = AckPacket(i);
@@ -110,7 +111,7 @@
}
// Send packets at the exponentially decreasing bandwidth.
- for (QuicPacketNumber i = 20; i < 25; i++) {
+ for (int i = 20; i < 25; i++) {
time_between_packets = time_between_packets * 2;
expected_bandwidth = expected_bandwidth * 0.5;
@@ -135,7 +136,7 @@
// Ack the packets 21 to 40, arriving at the correct bandwidth.
QuicBandwidth last_bandwidth = QuicBandwidth::Zero();
- for (QuicPacketNumber i = 21; i <= 40; i++) {
+ for (int i = 21; i <= 40; i++) {
last_bandwidth = AckPacket(i);
EXPECT_EQ(expected_bandwidth, last_bandwidth);
clock_.AdvanceTime(time_between_packets);
@@ -152,14 +153,14 @@
QuicBandwidth::FromKBytesPerSecond(kRegularPacketSize) * 0.5;
// Send 20 packets, each 1 ms apart.
- for (QuicPacketNumber i = 1; i <= 20; i++) {
+ for (int i = 1; i <= 20; i++) {
SendPacket(i);
clock_.AdvanceTime(time_between_packets);
}
// Ack packets 1 to 20, losing every even-numbered packet, while sending new
// packets at the same rate as before.
- for (QuicPacketNumber i = 1; i <= 20; i++) {
+ for (int i = 1; i <= 20; i++) {
if (i % 2 == 0) {
AckPacket(i);
} else {
@@ -171,7 +172,7 @@
// Ack the packets 21 to 40 with the same loss pattern.
QuicBandwidth last_bandwidth = QuicBandwidth::Zero();
- for (QuicPacketNumber i = 21; i <= 40; i++) {
+ for (int i = 21; i <= 40; i++) {
if (i % 2 == 0) {
last_bandwidth = AckPacket(i);
EXPECT_EQ(expected_bandwidth, last_bandwidth);
@@ -196,7 +197,7 @@
// Send 20 packets, each 1 ms apart. Every even packet is not congestion
// controlled.
- for (QuicPacketNumber i = 1; i <= 20; i++) {
+ for (int i = 1; i <= 20; i++) {
SendPacketInner(
i, kRegularPacketSize,
i % 2 == 0 ? HAS_RETRANSMITTABLE_DATA : NO_RETRANSMITTABLE_DATA);
@@ -208,7 +209,7 @@
// Ack packets 2 to 21, ignoring every even-numbered packet, while sending new
// packets at the same rate as before.
- for (QuicPacketNumber i = 1; i <= 20; i++) {
+ for (int i = 1; i <= 20; i++) {
if (i % 2 == 0) {
AckPacket(i);
}
@@ -220,7 +221,7 @@
// Ack the packets 22 to 41 with the same congestion controlled pattern.
QuicBandwidth last_bandwidth = QuicBandwidth::Zero();
- for (QuicPacketNumber i = 21; i <= 40; i++) {
+ for (int i = 21; i <= 40; i++) {
if (i % 2 == 0) {
last_bandwidth = AckPacket(i);
EXPECT_EQ(expected_bandwidth, last_bandwidth);
@@ -251,7 +252,7 @@
QuicBandwidth last_bandwidth = QuicBandwidth::Zero();
QuicTime::Delta ridiculously_small_time_delta =
QuicTime::Delta::FromMicroseconds(20);
- for (QuicPacketNumber i = 21; i <= 40; i++) {
+ for (int i = 21; i <= 40; i++) {
last_bandwidth = AckPacket(i);
clock_.AdvanceTime(ridiculously_small_time_delta);
}
@@ -272,7 +273,7 @@
// Ack the packets 21 to 40 in the reverse order, while sending packets 41 to
// 60.
QuicBandwidth last_bandwidth = QuicBandwidth::Zero();
- for (QuicPacketNumber i = 0; i < 20; i++) {
+ for (int i = 0; i < 20; i++) {
last_bandwidth = AckPacket(40 - i);
EXPECT_EQ(expected_bandwidth, last_bandwidth);
SendPacket(41 + i);
@@ -280,7 +281,7 @@
}
// Ack the packets 41 to 60, now in the regular order.
- for (QuicPacketNumber i = 41; i <= 60; i++) {
+ for (int i = 41; i <= 60; i++) {
last_bandwidth = AckPacket(i);
EXPECT_EQ(expected_bandwidth, last_bandwidth);
clock_.AdvanceTime(time_between_packets);
@@ -301,7 +302,7 @@
// We are now app-limited. Ack 21 to 40 as usual, but do not send anything for
// now.
sampler_.OnAppLimited();
- for (QuicPacketNumber i = 21; i <= 40; i++) {
+ for (int i = 21; i <= 40; i++) {
QuicBandwidth current_sample = AckPacket(i);
EXPECT_EQ(expected_bandwidth, current_sample);
clock_.AdvanceTime(time_between_packets);
@@ -311,14 +312,14 @@
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
// Send packets 41 to 60, all of which would be marked as app-limited.
- for (QuicPacketNumber i = 41; i <= 60; i++) {
+ for (int i = 41; i <= 60; i++) {
SendPacket(i);
clock_.AdvanceTime(time_between_packets);
}
// Ack packets 41 to 60, while sending packets 61 to 80. 41 to 60 should be
// app-limited and underestimate the bandwidth due to that.
- for (QuicPacketNumber i = 41; i <= 60; i++) {
+ for (int i = 41; i <= 60; i++) {
BandwidthSample sample = AckPacketInner(i);
EXPECT_TRUE(sample.is_app_limited);
EXPECT_LT(sample.bandwidth, 0.7f * expected_bandwidth);
@@ -329,7 +330,7 @@
// Run out of packets, and then ack packet 61 to 80, all of which should have
// correct non-app-limited samples.
- for (QuicPacketNumber i = 61; i <= 80; i++) {
+ for (int i = 61; i <= 80; i++) {
QuicBandwidth last_bandwidth = AckPacket(i);
EXPECT_EQ(expected_bandwidth, last_bandwidth);
clock_.AdvanceTime(time_between_packets);
@@ -349,7 +350,7 @@
const QuicBandwidth real_bandwidth =
QuicBandwidth::FromBytesAndTimeDelta(num_bytes, rtt);
- for (QuicPacketNumber i = 1; i <= 10; i++) {
+ for (int i = 1; i <= 10; i++) {
SendPacket(i);
clock_.AdvanceTime(time_between_packets);
}
@@ -357,7 +358,7 @@
clock_.AdvanceTime(rtt - num_packets * time_between_packets);
QuicBandwidth last_sample = QuicBandwidth::Zero();
- for (QuicPacketNumber i = 1; i <= 10; i++) {
+ for (int i = 1; i <= 10; i++) {
QuicBandwidth sample = AckPacket(i);
EXPECT_GT(sample, last_sample);
last_sample = sample;
@@ -385,9 +386,9 @@
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(100));
EXPECT_EQ(5u, BandwidthSamplerPeer::GetNumberOfTrackedPackets(sampler_));
- sampler_.RemoveObsoletePackets(4);
+ sampler_.RemoveObsoletePackets(QuicPacketNumber(4));
EXPECT_EQ(2u, BandwidthSamplerPeer::GetNumberOfTrackedPackets(sampler_));
- sampler_.OnPacketLost(4);
+ sampler_.OnPacketLost(QuicPacketNumber(4));
EXPECT_EQ(1u, BandwidthSamplerPeer::GetNumberOfTrackedPackets(sampler_));
AckPacket(5);
EXPECT_EQ(0u, BandwidthSamplerPeer::GetNumberOfTrackedPackets(sampler_));
diff --git a/quic/core/congestion_control/bbr_sender.cc b/quic/core/congestion_control/bbr_sender.cc
index 81931a1..6a7fe2b 100644
--- a/quic/core/congestion_control/bbr_sender.cc
+++ b/quic/core/congestion_control/bbr_sender.cc
@@ -87,8 +87,6 @@
random_(random),
mode_(STARTUP),
round_trip_count_(0),
- last_sent_packet_(0),
- current_round_trip_end_(0),
max_bandwidth_(kBandwidthWindowSize, QuicBandwidth::Zero(), 0),
max_ack_height_(kBandwidthWindowSize, 0, 0),
aggregation_epoch_start_time_(QuicTime::Zero()),
@@ -122,14 +120,12 @@
has_non_app_limited_sample_(false),
flexible_app_limited_(false),
recovery_state_(NOT_IN_RECOVERY),
- end_recovery_at_(0),
recovery_window_(max_congestion_window_),
is_app_limited_recovery_(false),
slower_startup_(false),
rate_based_startup_(false),
startup_rate_reduction_multiplier_(0),
startup_bytes_lost_(0),
- initial_conservation_in_startup_(CONSERVATION),
enable_ack_aggregation_during_startup_(false),
expire_ack_aggregation_in_startup_(false),
drain_to_target_(false),
@@ -263,12 +259,6 @@
if (config.HasClientRequestedIndependentOption(kBBS1, perspective)) {
rate_based_startup_ = true;
}
- if (config.HasClientRequestedIndependentOption(kBBS2, perspective)) {
- initial_conservation_in_startup_ = MEDIUM_GROWTH;
- }
- if (config.HasClientRequestedIndependentOption(kBBS3, perspective)) {
- initial_conservation_in_startup_ = GROWTH;
- }
if (GetQuicReloadableFlag(quic_bbr_startup_rate_reduction) &&
config.HasClientRequestedIndependentOption(kBBS4, perspective)) {
rate_based_startup_ = true;
@@ -467,7 +457,8 @@
}
bool BbrSender::UpdateRoundTripCounter(QuicPacketNumber last_acked_packet) {
- if (last_acked_packet > current_round_trip_end_) {
+ if (!current_round_trip_end_.IsInitialized() ||
+ last_acked_packet > current_round_trip_end_) {
round_trip_count_++;
current_round_trip_end_ = last_sent_packet_;
return true;
@@ -677,9 +668,6 @@
// Enter conservation on the first loss.
if (has_losses) {
recovery_state_ = CONSERVATION;
- if (mode_ == STARTUP) {
- recovery_state_ = initial_conservation_in_startup_;
- }
// This will cause the |recovery_window_| to be set to the correct
// value in CalculateRecoveryWindow().
recovery_window_ = 0;
@@ -695,7 +683,6 @@
break;
case CONSERVATION:
- case MEDIUM_GROWTH:
if (is_round_start) {
recovery_state_ = GROWTH;
}
@@ -759,7 +746,7 @@
return;
}
// Slow the pacing rate in STARTUP once loss has ever been detected.
- const bool has_ever_detected_loss = end_recovery_at_ > 0;
+ const bool has_ever_detected_loss = end_recovery_at_.IsInitialized();
if (slower_startup_ && has_ever_detected_loss &&
has_non_app_limited_sample_) {
pacing_rate_ = kStartupAfterLossGain * BandwidthEstimate();
@@ -848,11 +835,8 @@
// In CONSERVATION mode, just subtracting losses is sufficient. In GROWTH,
// release additional |bytes_acked| to achieve a slow-start-like behavior.
- // In MEDIUM_GROWTH, release |bytes_acked| / 2 to split the difference.
if (recovery_state_ == GROWTH) {
recovery_window_ += bytes_acked;
- } else if (recovery_state_ == MEDIUM_GROWTH) {
- recovery_window_ += bytes_acked / 2;
}
// Sanity checks. Ensure that we always allow to send at least an MSS or
diff --git a/quic/core/congestion_control/bbr_sender.h b/quic/core/congestion_control/bbr_sender.h
index 0ee730c..37e2695 100644
--- a/quic/core/congestion_control/bbr_sender.h
+++ b/quic/core/congestion_control/bbr_sender.h
@@ -58,8 +58,6 @@
NOT_IN_RECOVERY,
// Allow an extra outstanding byte for each byte acknowledged.
CONSERVATION,
- // Allow 1.5 extra outstanding bytes for each byte acknowledged.
- MEDIUM_GROWTH,
// Allow two extra outstanding bytes for each byte acknowledged (slow
// start).
GROWTH
@@ -265,7 +263,7 @@
QuicPacketNumber last_sent_packet_;
// Acknowledgement of any packet after |current_round_trip_end_| will cause
// the round trip counter to advance.
- QuicPacketCount current_round_trip_end_;
+ QuicPacketNumber current_round_trip_end_;
// The filter that tracks the maximum bandwidth over the multiple recent
// round-trips.
@@ -375,8 +373,6 @@
// Sum of bytes lost in STARTUP.
QuicByteCount startup_bytes_lost_;
- // Used as the initial packet conservation mode when first entering recovery.
- RecoveryState initial_conservation_in_startup_;
// When true, add the most recent ack aggregation measurement during STARTUP.
bool enable_ack_aggregation_during_startup_;
// When true, expire the windowed ack aggregation values in STARTUP when
diff --git a/quic/core/congestion_control/bbr_sender_test.cc b/quic/core/congestion_control/bbr_sender_test.cc
index bc7fc76..e0d5867 100644
--- a/quic/core/congestion_control/bbr_sender_test.cc
+++ b/quic/core/congestion_control/bbr_sender_test.cc
@@ -515,97 +515,6 @@
ASSERT_TRUE(simulator_result);
}
-// Ensures the code transitions loss recovery states correctly when in STARTUP
-// and the BBS2 connection option is used.
-// (NOT_IN_RECOVERY -> CONSERVATION -> GROWTH -> NOT_IN_RECOVERY).
-TEST_F(BbrSenderTest, StartupMediumRecoveryStates) {
- // Set seed to the position where the gain cycling causes the sender go
- // into conservation upon entering PROBE_BW.
- //
- // TODO(vasilvv): there should be a better way to test this.
- random_.set_seed(UINT64_C(14719894707049085006));
-
- const QuicTime::Delta timeout = QuicTime::Delta::FromSeconds(10);
- bool simulator_result;
- CreateSmallBufferSetup();
- SetConnectionOption(kBBS2);
-
- bbr_sender_.AddBytesToTransfer(100 * 1024 * 1024);
- ASSERT_EQ(BbrSender::NOT_IN_RECOVERY,
- sender_->ExportDebugState().recovery_state);
-
- simulator_result = simulator_.RunUntilOrTimeout(
- [this]() {
- return sender_->ExportDebugState().recovery_state !=
- BbrSender::NOT_IN_RECOVERY;
- },
- timeout);
- ASSERT_TRUE(simulator_result);
- ASSERT_EQ(BbrSender::MEDIUM_GROWTH,
- sender_->ExportDebugState().recovery_state);
-
- simulator_result = simulator_.RunUntilOrTimeout(
- [this]() {
- return sender_->ExportDebugState().recovery_state !=
- BbrSender::MEDIUM_GROWTH;
- },
- timeout);
- ASSERT_TRUE(simulator_result);
- ASSERT_EQ(BbrSender::GROWTH, sender_->ExportDebugState().recovery_state);
-
- simulator_result = simulator_.RunUntilOrTimeout(
- [this]() {
- return sender_->ExportDebugState().recovery_state != BbrSender::GROWTH;
- },
- timeout);
-
- ASSERT_EQ(BbrSender::PROBE_BW, sender_->ExportDebugState().mode);
- ASSERT_EQ(BbrSender::NOT_IN_RECOVERY,
- sender_->ExportDebugState().recovery_state);
- ASSERT_TRUE(simulator_result);
-}
-
-// Ensures the code transitions loss recovery states correctly when in STARTUP
-// and the BBS3 connection option is used.
-// (NOT_IN_RECOVERY -> GROWTH -> NOT_IN_RECOVERY).
-TEST_F(BbrSenderTest, StartupGrowthRecoveryStates) {
- // Set seed to the position where the gain cycling causes the sender go
- // into conservation upon entering PROBE_BW.
- //
- // TODO(vasilvv): there should be a better way to test this.
- random_.set_seed(UINT64_C(14719894707049085006));
-
- const QuicTime::Delta timeout = QuicTime::Delta::FromSeconds(10);
- bool simulator_result;
- CreateSmallBufferSetup();
- SetConnectionOption(kBBS3);
-
- bbr_sender_.AddBytesToTransfer(100 * 1024 * 1024);
- ASSERT_EQ(BbrSender::NOT_IN_RECOVERY,
- sender_->ExportDebugState().recovery_state);
-
- simulator_result = simulator_.RunUntilOrTimeout(
- [this]() {
- return sender_->ExportDebugState().recovery_state !=
- BbrSender::NOT_IN_RECOVERY;
- },
- timeout);
- ASSERT_TRUE(simulator_result);
- ASSERT_EQ(BbrSender::GROWTH, sender_->ExportDebugState().recovery_state);
-
- simulator_result = simulator_.RunUntilOrTimeout(
- [this]() {
- return sender_->ExportDebugState().recovery_state != BbrSender::GROWTH;
- },
- timeout);
- ASSERT_TRUE(simulator_result);
-
- ASSERT_EQ(BbrSender::PROBE_BW, sender_->ExportDebugState().mode);
- ASSERT_EQ(BbrSender::NOT_IN_RECOVERY,
- sender_->ExportDebugState().recovery_state);
- ASSERT_TRUE(simulator_result);
-}
-
// Verify the behavior of the algorithm in the case when the connection sends
// small bursts of data after sending continuously for a while.
TEST_F(BbrSenderTest, ApplicationLimitedBursts) {
@@ -1185,7 +1094,7 @@
QuicBandwidth pacing_rate = original_pacing_rate;
const QuicByteCount original_cwnd = sender_->GetCongestionWindow();
LostPacketVector lost_packets;
- lost_packets.push_back(LostPacket(0, kMaxPacketSize));
+ lost_packets.push_back(LostPacket(QuicPacketNumber(), kMaxPacketSize));
QuicPacketNumber largest_sent =
bbr_sender_.connection()->sent_packet_manager().GetLargestSentPacket();
for (QuicPacketNumber packet_number =
@@ -1235,7 +1144,7 @@
QuicBandwidth pacing_rate = original_pacing_rate;
const QuicByteCount original_cwnd = sender_->GetCongestionWindow();
LostPacketVector lost_packets;
- lost_packets.push_back(LostPacket(0, kMaxPacketSize));
+ lost_packets.push_back(LostPacket(QuicPacketNumber(), kMaxPacketSize));
QuicPacketNumber largest_sent =
bbr_sender_.connection()->sent_packet_manager().GetLargestSentPacket();
for (QuicPacketNumber packet_number =
diff --git a/quic/core/congestion_control/general_loss_algorithm.cc b/quic/core/congestion_control/general_loss_algorithm.cc
index 7250940..27a3ab8 100644
--- a/quic/core/congestion_control/general_loss_algorithm.cc
+++ b/quic/core/congestion_control/general_loss_algorithm.cc
@@ -31,7 +31,6 @@
GeneralLossAlgorithm::GeneralLossAlgorithm(LossDetectionType loss_type)
: loss_detection_timeout_(QuicTime::Zero()),
- largest_lost_(0),
least_in_flight_(1),
faster_detect_loss_(GetQuicReloadableFlag(quic_faster_detect_loss)) {
SetLossDetectionType(loss_type);
@@ -39,7 +38,7 @@
void GeneralLossAlgorithm::SetLossDetectionType(LossDetectionType loss_type) {
loss_detection_timeout_ = QuicTime::Zero();
- largest_sent_on_spurious_retransmit_ = kInvalidPacketNumber;
+ largest_sent_on_spurious_retransmit_.Clear();
loss_type_ = loss_type;
reordering_shift_ = loss_type == kAdaptiveTime
? kDefaultAdaptiveLossDelayShift
@@ -49,7 +48,7 @@
QUIC_RELOADABLE_FLAG_COUNT(quic_eighth_rtt_loss_detection);
reordering_shift_ = 3;
}
- largest_previously_acked_ = kInvalidPacketNumber;
+ largest_previously_acked_.Clear();
}
LossDetectionType GeneralLossAlgorithm::GetLossDetectionType() const {
@@ -91,7 +90,7 @@
QuicPacketNumber packet_number = unacked_packets.GetLeastUnacked();
auto it = unacked_packets.begin();
if (faster_detect_loss_) {
- if (least_in_flight_ >= packet_number) {
+ if (least_in_flight_.IsInitialized() && least_in_flight_ >= packet_number) {
if (least_in_flight_ > unacked_packets.largest_sent_packet() + 1) {
QUIC_BUG << "least_in_flight: " << least_in_flight_
<< " is greater than largest_sent_packet + 1: "
@@ -103,9 +102,9 @@
}
}
// Clear least_in_flight_.
- least_in_flight_ = kInvalidPacketNumber;
+ least_in_flight_.Clear();
} else {
- if (largest_lost_ >= packet_number) {
+ if (largest_lost_.IsInitialized() && largest_lost_ >= packet_number) {
if (largest_lost_ > unacked_packets.largest_sent_packet()) {
QUIC_BUG << "largest_lost: " << largest_lost_
<< " is greater than largest_sent_packet: "
@@ -132,7 +131,8 @@
} else if (loss_type_ == kLazyFack) {
// Require two in order acks to invoke FACK, which avoids spuriously
// retransmitting packets when one packet is reordered by a large amount.
- if (largest_newly_acked > largest_previously_acked_ &&
+ if (largest_previously_acked_.IsInitialized() &&
+ largest_newly_acked > largest_previously_acked_ &&
largest_previously_acked_ > packet_number &&
largest_previously_acked_ - packet_number >=
(kNumberOfNacksBeforeRetransmission - 1)) {
@@ -150,7 +150,7 @@
QuicTime when_lost = it->sent_time + loss_delay;
if (time < when_lost) {
loss_detection_timeout_ = when_lost;
- if (least_in_flight_ == kInvalidPacketNumber) {
+ if (!least_in_flight_.IsInitialized()) {
// At this point, packet_number is in flight and not detected as lost.
least_in_flight_ = packet_number;
}
@@ -166,18 +166,19 @@
packets_lost->push_back(LostPacket(packet_number, it->bytes_sent));
continue;
}
- if (least_in_flight_ == kInvalidPacketNumber) {
+ if (!least_in_flight_.IsInitialized()) {
// At this point, packet_number is in flight and not detected as lost.
least_in_flight_ = packet_number;
}
}
- if (least_in_flight_ == kInvalidPacketNumber) {
+ if (!least_in_flight_.IsInitialized()) {
// There is no in flight packet.
least_in_flight_ = largest_newly_acked + 1;
}
largest_previously_acked_ = largest_newly_acked;
if (!packets_lost->empty()) {
- DCHECK_LT(largest_lost_, packets_lost->back().packet_number);
+ DCHECK(!largest_lost_.IsInitialized() ||
+ largest_lost_ < packets_lost->back().packet_number);
largest_lost_ = packets_lost->back().packet_number;
}
}
@@ -212,7 +213,8 @@
return;
}
- if (spurious_retransmission <= largest_sent_on_spurious_retransmit_) {
+ if (largest_sent_on_spurious_retransmit_.IsInitialized() &&
+ spurious_retransmission <= largest_sent_on_spurious_retransmit_) {
return;
}
largest_sent_on_spurious_retransmit_ = unacked_packets.largest_sent_packet();
diff --git a/quic/core/congestion_control/general_loss_algorithm_test.cc b/quic/core/congestion_control/general_loss_algorithm_test.cc
index 7a8ec67..2cd19a7 100644
--- a/quic/core/congestion_control/general_loss_algorithm_test.cc
+++ b/quic/core/congestion_control/general_loss_algorithm_test.cc
@@ -31,37 +31,43 @@
~GeneralLossAlgorithmTest() override {}
- void SendDataPacket(QuicPacketNumber packet_number) {
+ void SendDataPacket(uint64_t packet_number) {
QuicStreamFrame frame;
frame.stream_id = QuicUtils::GetHeadersStreamId(
CurrentSupportedVersions()[0].transport_version);
- SerializedPacket packet(packet_number, PACKET_1BYTE_PACKET_NUMBER, nullptr,
- kDefaultLength, false, false);
+ SerializedPacket packet(QuicPacketNumber(packet_number),
+ PACKET_1BYTE_PACKET_NUMBER, nullptr, kDefaultLength,
+ false, false);
packet.retransmittable_frames.push_back(QuicFrame(frame));
- unacked_packets_.AddSentPacket(&packet, 0, NOT_RETRANSMISSION, clock_.Now(),
- true);
+ unacked_packets_.AddSentPacket(&packet, QuicPacketNumber(),
+ NOT_RETRANSMISSION, clock_.Now(), true);
}
- void SendAckPacket(QuicPacketNumber packet_number) {
- SerializedPacket packet(packet_number, PACKET_1BYTE_PACKET_NUMBER, nullptr,
- kDefaultLength, true, false);
- unacked_packets_.AddSentPacket(&packet, 0, NOT_RETRANSMISSION, clock_.Now(),
- false);
+ void SendAckPacket(uint64_t packet_number) {
+ SerializedPacket packet(QuicPacketNumber(packet_number),
+ PACKET_1BYTE_PACKET_NUMBER, nullptr, kDefaultLength,
+ true, false);
+ unacked_packets_.AddSentPacket(&packet, QuicPacketNumber(),
+ NOT_RETRANSMISSION, clock_.Now(), false);
}
- void VerifyLosses(QuicPacketNumber largest_newly_acked,
+ void VerifyLosses(uint64_t largest_newly_acked,
const AckedPacketVector& packets_acked,
- const std::vector<QuicPacketNumber>& losses_expected) {
- if (largest_newly_acked > unacked_packets_.largest_acked()) {
- unacked_packets_.IncreaseLargestAcked(largest_newly_acked);
+ const std::vector<uint64_t>& losses_expected) {
+ if (!unacked_packets_.largest_acked().IsInitialized() ||
+ QuicPacketNumber(largest_newly_acked) >
+ unacked_packets_.largest_acked()) {
+ unacked_packets_.IncreaseLargestAcked(
+ QuicPacketNumber(largest_newly_acked));
}
LostPacketVector lost_packets;
loss_algorithm_.DetectLosses(unacked_packets_, clock_.Now(), rtt_stats_,
- largest_newly_acked, packets_acked,
- &lost_packets);
+ QuicPacketNumber(largest_newly_acked),
+ packets_acked, &lost_packets);
ASSERT_EQ(losses_expected.size(), lost_packets.size());
for (size_t i = 0; i < losses_expected.size(); ++i) {
- EXPECT_EQ(lost_packets[i].packet_number, losses_expected[i]);
+ EXPECT_EQ(lost_packets[i].packet_number,
+ QuicPacketNumber(losses_expected[i]));
}
}
@@ -79,18 +85,21 @@
}
AckedPacketVector packets_acked;
// No loss on one ack.
- unacked_packets_.RemoveFromInFlight(2);
- packets_acked.push_back(AckedPacket(2, kMaxPacketSize, QuicTime::Zero()));
- VerifyLosses(2, packets_acked, std::vector<QuicPacketNumber>{});
+ unacked_packets_.RemoveFromInFlight(QuicPacketNumber(2));
+ packets_acked.push_back(
+ AckedPacket(QuicPacketNumber(2), kMaxPacketSize, QuicTime::Zero()));
+ VerifyLosses(2, packets_acked, std::vector<uint64_t>{});
packets_acked.clear();
// No loss on two acks.
- unacked_packets_.RemoveFromInFlight(3);
- packets_acked.push_back(AckedPacket(3, kMaxPacketSize, QuicTime::Zero()));
- VerifyLosses(3, packets_acked, std::vector<QuicPacketNumber>{});
+ unacked_packets_.RemoveFromInFlight(QuicPacketNumber(3));
+ packets_acked.push_back(
+ AckedPacket(QuicPacketNumber(3), kMaxPacketSize, QuicTime::Zero()));
+ VerifyLosses(3, packets_acked, std::vector<uint64_t>{});
packets_acked.clear();
// Loss on three acks.
- unacked_packets_.RemoveFromInFlight(4);
- packets_acked.push_back(AckedPacket(4, kMaxPacketSize, QuicTime::Zero()));
+ unacked_packets_.RemoveFromInFlight(QuicPacketNumber(4));
+ packets_acked.push_back(
+ AckedPacket(QuicPacketNumber(4), kMaxPacketSize, QuicTime::Zero()));
VerifyLosses(4, packets_acked, {1});
EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
}
@@ -105,12 +114,15 @@
}
AckedPacketVector packets_acked;
// Nack the first packet 3 times in a single StretchAck.
- unacked_packets_.RemoveFromInFlight(2);
- packets_acked.push_back(AckedPacket(2, kMaxPacketSize, QuicTime::Zero()));
- unacked_packets_.RemoveFromInFlight(3);
- packets_acked.push_back(AckedPacket(3, kMaxPacketSize, QuicTime::Zero()));
- unacked_packets_.RemoveFromInFlight(4);
- packets_acked.push_back(AckedPacket(4, kMaxPacketSize, QuicTime::Zero()));
+ unacked_packets_.RemoveFromInFlight(QuicPacketNumber(2));
+ packets_acked.push_back(
+ AckedPacket(QuicPacketNumber(2), kMaxPacketSize, QuicTime::Zero()));
+ unacked_packets_.RemoveFromInFlight(QuicPacketNumber(3));
+ packets_acked.push_back(
+ AckedPacket(QuicPacketNumber(3), kMaxPacketSize, QuicTime::Zero()));
+ unacked_packets_.RemoveFromInFlight(QuicPacketNumber(4));
+ packets_acked.push_back(
+ AckedPacket(QuicPacketNumber(4), kMaxPacketSize, QuicTime::Zero()));
VerifyLosses(4, packets_acked, {1});
EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
}
@@ -124,8 +136,9 @@
}
AckedPacketVector packets_acked;
// Nack the first packet 3 times in an AckFrame with three missing packets.
- unacked_packets_.RemoveFromInFlight(4);
- packets_acked.push_back(AckedPacket(4, kMaxPacketSize, QuicTime::Zero()));
+ unacked_packets_.RemoveFromInFlight(QuicPacketNumber(4));
+ packets_acked.push_back(
+ AckedPacket(QuicPacketNumber(4), kMaxPacketSize, QuicTime::Zero()));
VerifyLosses(4, packets_acked, {1});
EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
}
@@ -138,9 +151,10 @@
}
AckedPacketVector packets_acked;
// Early retransmit when the final packet gets acked and the first is nacked.
- unacked_packets_.RemoveFromInFlight(2);
- packets_acked.push_back(AckedPacket(2, kMaxPacketSize, QuicTime::Zero()));
- VerifyLosses(2, packets_acked, std::vector<QuicPacketNumber>{});
+ unacked_packets_.RemoveFromInFlight(QuicPacketNumber(2));
+ packets_acked.push_back(
+ AckedPacket(QuicPacketNumber(2), kMaxPacketSize, QuicTime::Zero()));
+ VerifyLosses(2, packets_acked, std::vector<uint64_t>{});
packets_acked.clear();
EXPECT_EQ(clock_.Now() + 1.25 * rtt_stats_.smoothed_rtt(),
loss_algorithm_.GetLossTimeout());
@@ -162,9 +176,9 @@
AckedPacketVector packets_acked;
// Early retransmit when the final packet gets acked and 1.25 RTTs have
// elapsed since the packets were sent.
- unacked_packets_.RemoveFromInFlight(kNumSentPackets);
- packets_acked.push_back(
- AckedPacket(kNumSentPackets, kMaxPacketSize, QuicTime::Zero()));
+ unacked_packets_.RemoveFromInFlight(QuicPacketNumber(kNumSentPackets));
+ packets_acked.push_back(AckedPacket(QuicPacketNumber(kNumSentPackets),
+ kMaxPacketSize, QuicTime::Zero()));
// This simulates a single ack following multiple missing packets with FACK.
VerifyLosses(kNumSentPackets, packets_acked, {1, 2});
packets_acked.clear();
@@ -190,14 +204,15 @@
}
AckedPacketVector packets_acked;
// Neuter packet 1.
- unacked_packets_.RemoveRetransmittability(1);
+ unacked_packets_.RemoveRetransmittability(QuicPacketNumber(1));
clock_.AdvanceTime(rtt_stats_.smoothed_rtt());
// Early retransmit when the final packet gets acked and the first is nacked.
- unacked_packets_.IncreaseLargestAcked(2);
- unacked_packets_.RemoveFromInFlight(2);
- packets_acked.push_back(AckedPacket(2, kMaxPacketSize, QuicTime::Zero()));
- VerifyLosses(2, packets_acked, std::vector<QuicPacketNumber>{});
+ unacked_packets_.IncreaseLargestAcked(QuicPacketNumber(2));
+ unacked_packets_.RemoveFromInFlight(QuicPacketNumber(2));
+ packets_acked.push_back(
+ AckedPacket(QuicPacketNumber(2), kMaxPacketSize, QuicTime::Zero()));
+ VerifyLosses(2, packets_acked, std::vector<uint64_t>{});
EXPECT_EQ(clock_.Now() + 0.25 * rtt_stats_.smoothed_rtt(),
loss_algorithm_.GetLossTimeout());
}
@@ -211,10 +226,11 @@
clock_.AdvanceTime(rtt_stats_.smoothed_rtt());
// Early retransmit when the final packet gets acked and the first is nacked.
- unacked_packets_.IncreaseLargestAcked(2);
- unacked_packets_.RemoveFromInFlight(2);
- packets_acked.push_back(AckedPacket(2, kMaxPacketSize, QuicTime::Zero()));
- VerifyLosses(2, packets_acked, std::vector<QuicPacketNumber>{});
+ unacked_packets_.IncreaseLargestAcked(QuicPacketNumber(2));
+ unacked_packets_.RemoveFromInFlight(QuicPacketNumber(2));
+ packets_acked.push_back(
+ AckedPacket(QuicPacketNumber(2), kMaxPacketSize, QuicTime::Zero()));
+ VerifyLosses(2, packets_acked, std::vector<uint64_t>{});
packets_acked.clear();
EXPECT_EQ(clock_.Now() + 0.25 * rtt_stats_.smoothed_rtt(),
loss_algorithm_.GetLossTimeout());
@@ -237,9 +253,10 @@
AckedPacketVector packets_acked;
// Wait another RTT and ack 2.
clock_.AdvanceTime(rtt_stats_.smoothed_rtt());
- unacked_packets_.IncreaseLargestAcked(2);
- unacked_packets_.RemoveFromInFlight(2);
- packets_acked.push_back(AckedPacket(2, kMaxPacketSize, QuicTime::Zero()));
+ unacked_packets_.IncreaseLargestAcked(QuicPacketNumber(2));
+ unacked_packets_.RemoveFromInFlight(QuicPacketNumber(2));
+ packets_acked.push_back(
+ AckedPacket(QuicPacketNumber(2), kMaxPacketSize, QuicTime::Zero()));
VerifyLosses(2, packets_acked, {1});
}
@@ -253,18 +270,21 @@
}
AckedPacketVector packets_acked;
// No loss on one ack.
- unacked_packets_.RemoveFromInFlight(2);
- packets_acked.push_back(AckedPacket(2, kMaxPacketSize, QuicTime::Zero()));
- VerifyLosses(2, packets_acked, std::vector<QuicPacketNumber>{});
+ unacked_packets_.RemoveFromInFlight(QuicPacketNumber(2));
+ packets_acked.push_back(
+ AckedPacket(QuicPacketNumber(2), kMaxPacketSize, QuicTime::Zero()));
+ VerifyLosses(2, packets_acked, std::vector<uint64_t>{});
packets_acked.clear();
// No loss on two acks.
- unacked_packets_.RemoveFromInFlight(3);
- packets_acked.push_back(AckedPacket(3, kMaxPacketSize, QuicTime::Zero()));
- VerifyLosses(3, packets_acked, std::vector<QuicPacketNumber>{});
+ unacked_packets_.RemoveFromInFlight(QuicPacketNumber(3));
+ packets_acked.push_back(
+ AckedPacket(QuicPacketNumber(3), kMaxPacketSize, QuicTime::Zero()));
+ VerifyLosses(3, packets_acked, std::vector<uint64_t>{});
packets_acked.clear();
// Loss on three acks.
- unacked_packets_.RemoveFromInFlight(4);
- packets_acked.push_back(AckedPacket(4, kMaxPacketSize, QuicTime::Zero()));
+ unacked_packets_.RemoveFromInFlight(QuicPacketNumber(4));
+ packets_acked.push_back(
+ AckedPacket(QuicPacketNumber(4), kMaxPacketSize, QuicTime::Zero()));
VerifyLosses(4, packets_acked, {1});
EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
}
@@ -281,19 +301,23 @@
}
AckedPacketVector packets_acked;
// Nack the first packet 3 times in a single StretchAck.
- unacked_packets_.RemoveFromInFlight(2);
- packets_acked.push_back(AckedPacket(2, kMaxPacketSize, QuicTime::Zero()));
- unacked_packets_.RemoveFromInFlight(3);
- packets_acked.push_back(AckedPacket(3, kMaxPacketSize, QuicTime::Zero()));
- unacked_packets_.RemoveFromInFlight(4);
- packets_acked.push_back(AckedPacket(4, kMaxPacketSize, QuicTime::Zero()));
- VerifyLosses(4, packets_acked, std::vector<QuicPacketNumber>{});
+ unacked_packets_.RemoveFromInFlight(QuicPacketNumber(2));
+ packets_acked.push_back(
+ AckedPacket(QuicPacketNumber(2), kMaxPacketSize, QuicTime::Zero()));
+ unacked_packets_.RemoveFromInFlight(QuicPacketNumber(3));
+ packets_acked.push_back(
+ AckedPacket(QuicPacketNumber(3), kMaxPacketSize, QuicTime::Zero()));
+ unacked_packets_.RemoveFromInFlight(QuicPacketNumber(4));
+ packets_acked.push_back(
+ AckedPacket(QuicPacketNumber(4), kMaxPacketSize, QuicTime::Zero()));
+ VerifyLosses(4, packets_acked, std::vector<uint64_t>{});
packets_acked.clear();
// The timer isn't set because we expect more acks.
EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
// Process another ack and then packet 1 will be lost.
- unacked_packets_.RemoveFromInFlight(5);
- packets_acked.push_back(AckedPacket(5, kMaxPacketSize, QuicTime::Zero()));
+ unacked_packets_.RemoveFromInFlight(QuicPacketNumber(5));
+ packets_acked.push_back(
+ AckedPacket(QuicPacketNumber(5), kMaxPacketSize, QuicTime::Zero()));
VerifyLosses(5, packets_acked, {1});
EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
}
@@ -308,15 +332,17 @@
}
AckedPacketVector packets_acked;
// Nack the first packet 3 times in an AckFrame with three missing packets.
- unacked_packets_.RemoveFromInFlight(4);
- packets_acked.push_back(AckedPacket(4, kMaxPacketSize, QuicTime::Zero()));
- VerifyLosses(4, packets_acked, std::vector<QuicPacketNumber>{});
+ unacked_packets_.RemoveFromInFlight(QuicPacketNumber(4));
+ packets_acked.push_back(
+ AckedPacket(QuicPacketNumber(4), kMaxPacketSize, QuicTime::Zero()));
+ VerifyLosses(4, packets_acked, std::vector<uint64_t>{});
packets_acked.clear();
// The timer isn't set because we expect more acks.
EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
// Process another ack and then packet 1 and 2 will be lost.
- unacked_packets_.RemoveFromInFlight(5);
- packets_acked.push_back(AckedPacket(5, kMaxPacketSize, QuicTime::Zero()));
+ unacked_packets_.RemoveFromInFlight(QuicPacketNumber(5));
+ packets_acked.push_back(
+ AckedPacket(QuicPacketNumber(5), kMaxPacketSize, QuicTime::Zero()));
VerifyLosses(5, packets_acked, {1, 2});
EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
}
@@ -330,10 +356,11 @@
SendDataPacket(i);
}
AckedPacketVector packets_acked;
- unacked_packets_.RemoveFromInFlight(2);
- packets_acked.push_back(AckedPacket(2, kMaxPacketSize, QuicTime::Zero()));
+ unacked_packets_.RemoveFromInFlight(QuicPacketNumber(2));
+ packets_acked.push_back(
+ AckedPacket(QuicPacketNumber(2), kMaxPacketSize, QuicTime::Zero()));
for (size_t i = 1; i < 500; ++i) {
- VerifyLosses(2, packets_acked, std::vector<QuicPacketNumber>{});
+ VerifyLosses(2, packets_acked, std::vector<uint64_t>{});
packets_acked.clear();
}
if (GetQuicReloadableFlag(quic_eighth_rtt_loss_detection)) {
@@ -357,9 +384,10 @@
// Expect the timer to not be set.
EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
// The packet should not be lost until 1.25 RTTs pass.
- unacked_packets_.RemoveFromInFlight(2);
- packets_acked.push_back(AckedPacket(2, kMaxPacketSize, QuicTime::Zero()));
- VerifyLosses(2, packets_acked, std::vector<QuicPacketNumber>{});
+ unacked_packets_.RemoveFromInFlight(QuicPacketNumber(2));
+ packets_acked.push_back(
+ AckedPacket(QuicPacketNumber(2), kMaxPacketSize, QuicTime::Zero()));
+ VerifyLosses(2, packets_acked, std::vector<uint64_t>{});
packets_acked.clear();
if (GetQuicReloadableFlag(quic_eighth_rtt_loss_detection)) {
// Expect the timer to be set to 0.25 RTT's in the future.
@@ -370,7 +398,7 @@
EXPECT_EQ(0.25 * rtt_stats_.smoothed_rtt(),
loss_algorithm_.GetLossTimeout() - clock_.Now());
}
- VerifyLosses(2, packets_acked, std::vector<QuicPacketNumber>{});
+ VerifyLosses(2, packets_acked, std::vector<uint64_t>{});
clock_.AdvanceTime(0.25 * rtt_stats_.smoothed_rtt());
VerifyLosses(2, packets_acked, {1});
EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
@@ -388,16 +416,17 @@
// Expect the timer to not be set.
EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
// The packet should not be lost without a nack.
- unacked_packets_.RemoveFromInFlight(1);
- packets_acked.push_back(AckedPacket(1, kMaxPacketSize, QuicTime::Zero()));
- VerifyLosses(1, packets_acked, std::vector<QuicPacketNumber>{});
+ unacked_packets_.RemoveFromInFlight(QuicPacketNumber(1));
+ packets_acked.push_back(
+ AckedPacket(QuicPacketNumber(1), kMaxPacketSize, QuicTime::Zero()));
+ VerifyLosses(1, packets_acked, std::vector<uint64_t>{});
packets_acked.clear();
// The timer should still not be set.
EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
clock_.AdvanceTime(0.25 * rtt_stats_.smoothed_rtt());
- VerifyLosses(1, packets_acked, std::vector<QuicPacketNumber>{});
+ VerifyLosses(1, packets_acked, std::vector<uint64_t>{});
clock_.AdvanceTime(rtt_stats_.smoothed_rtt());
- VerifyLosses(1, packets_acked, std::vector<QuicPacketNumber>{});
+ VerifyLosses(1, packets_acked, std::vector<uint64_t>{});
EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
}
@@ -414,9 +443,10 @@
// Expect the timer to not be set.
EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
// The packet should not be lost until 1.25 RTTs pass.
- unacked_packets_.RemoveFromInFlight(10);
- packets_acked.push_back(AckedPacket(10, kMaxPacketSize, QuicTime::Zero()));
- VerifyLosses(10, packets_acked, std::vector<QuicPacketNumber>{});
+ unacked_packets_.RemoveFromInFlight(QuicPacketNumber(10));
+ packets_acked.push_back(
+ AckedPacket(QuicPacketNumber(10), kMaxPacketSize, QuicTime::Zero()));
+ VerifyLosses(10, packets_acked, std::vector<uint64_t>{});
packets_acked.clear();
if (GetQuicReloadableFlag(quic_eighth_rtt_loss_detection)) {
// Expect the timer to be set to 0.25 RTT's in the future.
@@ -445,9 +475,10 @@
EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
// The packet should not be lost until 1.25 RTTs pass.
- unacked_packets_.RemoveFromInFlight(10);
- packets_acked.push_back(AckedPacket(10, kMaxPacketSize, QuicTime::Zero()));
- VerifyLosses(10, packets_acked, std::vector<QuicPacketNumber>{});
+ unacked_packets_.RemoveFromInFlight(QuicPacketNumber(10));
+ packets_acked.push_back(
+ AckedPacket(QuicPacketNumber(10), kMaxPacketSize, QuicTime::Zero()));
+ VerifyLosses(10, packets_acked, std::vector<uint64_t>{});
packets_acked.clear();
if (GetQuicReloadableFlag(quic_eighth_rtt_loss_detection)) {
// Expect the timer to be set to 0.25 RTT's in the future.
@@ -461,10 +492,11 @@
clock_.AdvanceTime(0.25 * rtt_stats_.smoothed_rtt());
// Now ack packets 1 to 9 and ensure the timer is no longer set and no packets
// are lost.
- for (QuicPacketNumber i = 1; i <= 9; ++i) {
- unacked_packets_.RemoveFromInFlight(i);
- packets_acked.push_back(AckedPacket(i, kMaxPacketSize, QuicTime::Zero()));
- VerifyLosses(i, packets_acked, std::vector<QuicPacketNumber>{});
+ for (uint64_t i = 1; i <= 9; ++i) {
+ unacked_packets_.RemoveFromInFlight(QuicPacketNumber(i));
+ packets_acked.push_back(
+ AckedPacket(QuicPacketNumber(i), kMaxPacketSize, QuicTime::Zero()));
+ VerifyLosses(i, packets_acked, std::vector<uint64_t>{});
packets_acked.clear();
EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
}
@@ -484,14 +516,15 @@
// Expect the timer to not be set.
EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
// Packet 1 should not be lost until 1/16 RTTs pass.
- unacked_packets_.RemoveFromInFlight(2);
- packets_acked.push_back(AckedPacket(2, kMaxPacketSize, QuicTime::Zero()));
- VerifyLosses(2, packets_acked, std::vector<QuicPacketNumber>{});
+ unacked_packets_.RemoveFromInFlight(QuicPacketNumber(2));
+ packets_acked.push_back(
+ AckedPacket(QuicPacketNumber(2), kMaxPacketSize, QuicTime::Zero()));
+ VerifyLosses(2, packets_acked, std::vector<uint64_t>{});
packets_acked.clear();
// Expect the timer to be set to 1/16 RTT's in the future.
EXPECT_EQ(rtt_stats_.smoothed_rtt() * (1.0f / 16),
loss_algorithm_.GetLossTimeout() - clock_.Now());
- VerifyLosses(2, packets_acked, std::vector<QuicPacketNumber>{});
+ VerifyLosses(2, packets_acked, std::vector<uint64_t>{});
clock_.AdvanceTime(rtt_stats_.smoothed_rtt() * (1.0f / 16));
VerifyLosses(2, packets_acked, {1});
EXPECT_EQ(QuicTime::Zero(), loss_algorithm_.GetLossTimeout());
@@ -508,13 +541,13 @@
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(1));
}
loss_algorithm_.SpuriousRetransmitDetected(unacked_packets_, clock_.Now(),
- rtt_stats_, 11);
+ rtt_stats_, QuicPacketNumber(11));
EXPECT_EQ(1, loss_algorithm_.reordering_shift());
// Detect another spurious retransmit and ensure the threshold doesn't
// increase again.
loss_algorithm_.SpuriousRetransmitDetected(unacked_packets_, clock_.Now(),
- rtt_stats_, 12);
+ rtt_stats_, QuicPacketNumber(12));
EXPECT_EQ(1, loss_algorithm_.reordering_shift());
}
diff --git a/quic/core/congestion_control/hybrid_slow_start.cc b/quic/core/congestion_control/hybrid_slow_start.cc
index 11a14e6..28963b1 100644
--- a/quic/core/congestion_control/hybrid_slow_start.cc
+++ b/quic/core/congestion_control/hybrid_slow_start.cc
@@ -24,8 +24,6 @@
HybridSlowStart::HybridSlowStart()
: started_(false),
hystart_found_(NOT_FOUND),
- last_sent_packet_number_(0),
- end_packet_number_(0),
rtt_sample_count_(0),
current_min_rtt_(QuicTime::Delta::Zero()) {}
@@ -56,7 +54,7 @@
}
bool HybridSlowStart::IsEndOfRound(QuicPacketNumber ack) const {
- return end_packet_number_ <= ack;
+ return !end_packet_number_.IsInitialized() || end_packet_number_ <= ack;
}
bool HybridSlowStart::ShouldExitSlowStart(QuicTime::Delta latest_rtt,
diff --git a/quic/core/congestion_control/hybrid_slow_start_test.cc b/quic/core/congestion_control/hybrid_slow_start_test.cc
index c97c616..aa2f849 100644
--- a/quic/core/congestion_control/hybrid_slow_start_test.cc
+++ b/quic/core/congestion_control/hybrid_slow_start_test.cc
@@ -24,8 +24,8 @@
};
TEST_F(HybridSlowStartTest, Simple) {
- QuicPacketNumber packet_number = 1;
- QuicPacketNumber end_packet_number = 3;
+ QuicPacketNumber packet_number(1);
+ QuicPacketNumber end_packet_number(3);
slow_start_->StartReceiveRound(end_packet_number);
EXPECT_FALSE(slow_start_->IsEndOfRound(packet_number++));
@@ -39,7 +39,7 @@
// Test without a new registered end_packet_number;
EXPECT_TRUE(slow_start_->IsEndOfRound(packet_number++));
- end_packet_number = 20;
+ end_packet_number = QuicPacketNumber(20);
slow_start_->StartReceiveRound(end_packet_number);
while (packet_number < end_packet_number) {
EXPECT_FALSE(slow_start_->IsEndOfRound(packet_number++));
@@ -52,7 +52,7 @@
// RTT of 60ms the detection will happen at 67.5 ms.
const int kHybridStartMinSamples = 8; // Number of acks required to trigger.
- QuicPacketNumber end_packet_number = 1;
+ QuicPacketNumber end_packet_number(1);
slow_start_->StartReceiveRound(end_packet_number++);
// Will not trigger since our lowest RTT in our burst is the same as the long
diff --git a/quic/core/congestion_control/pacing_sender_test.cc b/quic/core/congestion_control/pacing_sender_test.cc
index 904fb8d..0bb9258 100644
--- a/quic/core/congestion_control/pacing_sender_test.cc
+++ b/quic/core/congestion_control/pacing_sender_test.cc
@@ -50,7 +50,7 @@
if (burst_size == 0) {
EXPECT_CALL(*mock_sender_, OnCongestionEvent(_, _, _, _, _));
LostPacketVector lost_packets;
- lost_packets.push_back(LostPacket(1, kMaxPacketSize));
+ lost_packets.push_back(LostPacket(QuicPacketNumber(1), kMaxPacketSize));
AckedPacketVector empty;
pacing_sender_->OnCongestionEvent(true, 1234, clock_.Now(), empty,
lost_packets);
@@ -320,7 +320,7 @@
// Losing a packet will set clear burst tokens.
LostPacketVector lost_packets;
- lost_packets.push_back(LostPacket(1, kMaxPacketSize));
+ lost_packets.push_back(LostPacket(QuicPacketNumber(1), kMaxPacketSize));
AckedPacketVector empty_acked;
EXPECT_CALL(*mock_sender_,
OnCongestionEvent(true, kMaxPacketSize, _, IsEmpty(), _));
diff --git a/quic/core/congestion_control/rtt_stats_test.cc b/quic/core/congestion_control/rtt_stats_test.cc
index 4d154a6..83cb155 100644
--- a/quic/core/congestion_control/rtt_stats_test.cc
+++ b/quic/core/congestion_control/rtt_stats_test.cc
@@ -192,9 +192,9 @@
for (QuicTime::Delta bad_send_delta : bad_send_deltas) {
SCOPED_TRACE(Message() << "bad_send_delta = "
<< bad_send_delta.ToMicroseconds());
-#if QUIC_LOG_WARNING_IS_ON
- EXPECT_QUIC_LOG_CALL_CONTAINS(log, WARNING, "Ignoring");
-#endif
+ if (QUIC_LOG_WARNING_IS_ON()) {
+ EXPECT_QUIC_LOG_CALL_CONTAINS(log, WARNING, "Ignoring");
+ }
rtt_stats_.UpdateRtt(bad_send_delta, QuicTime::Delta::Zero(),
QuicTime::Zero());
EXPECT_EQ(initial_rtt, rtt_stats_.min_rtt());
diff --git a/quic/core/congestion_control/tcp_cubic_sender_bytes.cc b/quic/core/congestion_control/tcp_cubic_sender_bytes.cc
index 1d903ea..5b843eb 100644
--- a/quic/core/congestion_control/tcp_cubic_sender_bytes.cc
+++ b/quic/core/congestion_control/tcp_cubic_sender_bytes.cc
@@ -38,9 +38,6 @@
stats_(stats),
reno_(reno),
num_connections_(kDefaultNumConnections),
- largest_sent_packet_number_(kInvalidPacketNumber),
- largest_acked_packet_number_(kInvalidPacketNumber),
- largest_sent_at_last_cutback_(kInvalidPacketNumber),
min4_mode_(false),
last_cutback_exited_slowstart_(false),
slow_start_large_reduction_(false),
@@ -151,8 +148,12 @@
QuicByteCount acked_bytes,
QuicByteCount prior_in_flight,
QuicTime event_time) {
- largest_acked_packet_number_ =
- std::max(acked_packet_number, largest_acked_packet_number_);
+ if (largest_acked_packet_number_.IsInitialized()) {
+ largest_acked_packet_number_ =
+ std::max(acked_packet_number, largest_acked_packet_number_);
+ } else {
+ largest_acked_packet_number_ = acked_packet_number;
+ }
if (InRecovery()) {
if (!no_prr_) {
// PRR is used when in recovery.
@@ -184,7 +185,8 @@
// PRR is used when in recovery.
prr_.OnPacketSent(bytes);
}
- DCHECK_LT(largest_sent_packet_number_, packet_number);
+ DCHECK(!largest_sent_packet_number_.IsInitialized() ||
+ largest_sent_packet_number_ < packet_number);
largest_sent_packet_number_ = packet_number;
hybrid_slow_start_.OnPacketSent(packet_number);
}
@@ -240,8 +242,9 @@
}
bool TcpCubicSenderBytes::InRecovery() const {
- return largest_acked_packet_number_ <= largest_sent_at_last_cutback_ &&
- largest_acked_packet_number_ != kInvalidPacketNumber;
+ return largest_acked_packet_number_.IsInitialized() &&
+ largest_sent_at_last_cutback_.IsInitialized() &&
+ largest_acked_packet_number_ <= largest_sent_at_last_cutback_;
}
bool TcpCubicSenderBytes::ShouldSendProbingPacket() const {
@@ -249,7 +252,7 @@
}
void TcpCubicSenderBytes::OnRetransmissionTimeout(bool packets_retransmitted) {
- largest_sent_at_last_cutback_ = kInvalidPacketNumber;
+ largest_sent_at_last_cutback_.Clear();
if (!packets_retransmitted) {
return;
}
@@ -298,7 +301,8 @@
QuicByteCount prior_in_flight) {
// TCP NewReno (RFC6582) says that once a loss occurs, any losses in packets
// already sent should be treated as a single loss event, since it's expected.
- if (packet_number <= largest_sent_at_last_cutback_) {
+ if (largest_sent_at_last_cutback_.IsInitialized() &&
+ packet_number <= largest_sent_at_last_cutback_) {
if (last_cutback_exited_slowstart_) {
++stats_->slowstart_packets_lost;
stats_->slowstart_bytes_lost += lost_bytes;
@@ -414,9 +418,9 @@
void TcpCubicSenderBytes::OnConnectionMigration() {
hybrid_slow_start_.Restart();
prr_ = PrrSender();
- largest_sent_packet_number_ = kInvalidPacketNumber;
- largest_acked_packet_number_ = kInvalidPacketNumber;
- largest_sent_at_last_cutback_ = kInvalidPacketNumber;
+ largest_sent_packet_number_.Clear();
+ largest_acked_packet_number_.Clear();
+ largest_sent_at_last_cutback_.Clear();
last_cutback_exited_slowstart_ = false;
cubic_.ResetCubicState();
num_acked_packets_ = 0;
diff --git a/quic/core/congestion_control/tcp_cubic_sender_bytes_test.cc b/quic/core/congestion_control/tcp_cubic_sender_bytes_test.cc
index b7234bc..5eb6226 100644
--- a/quic/core/congestion_control/tcp_cubic_sender_bytes_test.cc
+++ b/quic/core/congestion_control/tcp_cubic_sender_bytes_test.cc
@@ -69,8 +69,9 @@
int packets_sent = 0;
bool can_send = sender_->CanSend(bytes_in_flight_);
while (can_send) {
- sender_->OnPacketSent(clock_.Now(), bytes_in_flight_, packet_number_++,
- kDefaultTCPMSS, HAS_RETRANSMITTABLE_DATA);
+ sender_->OnPacketSent(clock_.Now(), bytes_in_flight_,
+ QuicPacketNumber(packet_number_++), kDefaultTCPMSS,
+ HAS_RETRANSMITTABLE_DATA);
++packets_sent;
bytes_in_flight_ += kDefaultTCPMSS;
can_send = sender_->CanSend(bytes_in_flight_);
@@ -87,7 +88,8 @@
for (int i = 0; i < n; ++i) {
++acked_packet_number_;
acked_packets.push_back(
- AckedPacket(acked_packet_number_, kDefaultTCPMSS, QuicTime::Zero()));
+ AckedPacket(QuicPacketNumber(acked_packet_number_), kDefaultTCPMSS,
+ QuicTime::Zero()));
}
sender_->OnCongestionEvent(true, bytes_in_flight_, clock_.Now(),
acked_packets, lost_packets);
@@ -102,7 +104,8 @@
LostPacketVector lost_packets;
for (int i = 0; i < n; ++i) {
++acked_packet_number_;
- lost_packets.push_back(LostPacket(acked_packet_number_, packet_length));
+ lost_packets.push_back(
+ LostPacket(QuicPacketNumber(acked_packet_number_), packet_length));
}
sender_->OnCongestionEvent(false, bytes_in_flight_, clock_.Now(),
acked_packets, lost_packets);
@@ -110,10 +113,11 @@
}
// Does not increment acked_packet_number_.
- void LosePacket(QuicPacketNumber packet_number) {
+ void LosePacket(uint64_t packet_number) {
AckedPacketVector acked_packets;
LostPacketVector lost_packets;
- lost_packets.push_back(LostPacket(packet_number, kDefaultTCPMSS));
+ lost_packets.push_back(
+ LostPacket(QuicPacketNumber(packet_number), kDefaultTCPMSS));
sender_->OnCongestionEvent(false, bytes_in_flight_, clock_.Now(),
acked_packets, lost_packets);
bytes_in_flight_ -= kDefaultTCPMSS;
@@ -122,8 +126,8 @@
const QuicTime::Delta one_ms_;
MockClock clock_;
std::unique_ptr<TcpCubicSenderBytesPeer> sender_;
- QuicPacketNumber packet_number_;
- QuicPacketNumber acked_packet_number_;
+ uint64_t packet_number_;
+ uint64_t acked_packet_number_;
QuicByteCount bytes_in_flight_;
};
@@ -779,7 +783,8 @@
LostPacketVector missing_packets;
for (uint64_t i = 1; i < kDefaultMaxCongestionWindowPackets; ++i) {
acked_packets.clear();
- acked_packets.push_back(AckedPacket(i, 1350, QuicTime::Zero()));
+ acked_packets.push_back(
+ AckedPacket(QuicPacketNumber(i), 1350, QuicTime::Zero()));
sender->OnCongestionEvent(true, sender->GetCongestionWindow(), clock_.Now(),
acked_packets, missing_packets);
}
diff --git a/quic/core/crypto/aead_base_decrypter.cc b/quic/core/crypto/aead_base_decrypter.cc
index f5ec25c..51cfa26 100644
--- a/quic/core/crypto/aead_base_decrypter.cc
+++ b/quic/core/crypto/aead_base_decrypter.cc
@@ -142,7 +142,7 @@
}
bool AeadBaseDecrypter::DecryptPacket(QuicTransportVersion /*version*/,
- QuicPacketNumber packet_number,
+ uint64_t packet_number,
QuicStringPiece associated_data,
QuicStringPiece ciphertext,
char* output,
diff --git a/quic/core/crypto/aead_base_decrypter.h b/quic/core/crypto/aead_base_decrypter.h
index 494d6c2..b4906b8 100644
--- a/quic/core/crypto/aead_base_decrypter.h
+++ b/quic/core/crypto/aead_base_decrypter.h
@@ -36,7 +36,7 @@
bool SetPreliminaryKey(QuicStringPiece key) override;
bool SetDiversificationNonce(const DiversificationNonce& nonce) override;
bool DecryptPacket(QuicTransportVersion version,
- QuicPacketNumber packet_number,
+ uint64_t packet_number,
QuicStringPiece associated_data,
QuicStringPiece ciphertext,
char* output,
diff --git a/quic/core/crypto/aead_base_encrypter.cc b/quic/core/crypto/aead_base_encrypter.cc
index cbe07e3..199851e 100644
--- a/quic/core/crypto/aead_base_encrypter.cc
+++ b/quic/core/crypto/aead_base_encrypter.cc
@@ -124,7 +124,7 @@
}
bool AeadBaseEncrypter::EncryptPacket(QuicTransportVersion /*version*/,
- QuicPacketNumber packet_number,
+ uint64_t packet_number,
QuicStringPiece associated_data,
QuicStringPiece plaintext,
char* output,
diff --git a/quic/core/crypto/aead_base_encrypter.h b/quic/core/crypto/aead_base_encrypter.h
index d3ee016..255bd87 100644
--- a/quic/core/crypto/aead_base_encrypter.h
+++ b/quic/core/crypto/aead_base_encrypter.h
@@ -34,7 +34,7 @@
bool SetNoncePrefix(QuicStringPiece nonce_prefix) override;
bool SetIV(QuicStringPiece iv) override;
bool EncryptPacket(QuicTransportVersion version,
- QuicPacketNumber packet_number,
+ uint64_t packet_number,
QuicStringPiece associated_data,
QuicStringPiece plaintext,
char* output,
diff --git a/quic/core/crypto/aes_128_gcm_12_decrypter_test.cc b/quic/core/crypto/aes_128_gcm_12_decrypter_test.cc
index 7ffbf6e..eb2fa5e 100644
--- a/quic/core/crypto/aes_128_gcm_12_decrypter_test.cc
+++ b/quic/core/crypto/aes_128_gcm_12_decrypter_test.cc
@@ -203,7 +203,7 @@
QuicStringPiece nonce,
QuicStringPiece associated_data,
QuicStringPiece ciphertext) {
- QuicPacketNumber packet_number;
+ uint64_t packet_number;
QuicStringPiece nonce_prefix(nonce.data(),
nonce.size() - sizeof(packet_number));
decrypter->SetNoncePrefix(nonce_prefix);
diff --git a/quic/core/crypto/aes_128_gcm_encrypter_test.cc b/quic/core/crypto/aes_128_gcm_encrypter_test.cc
index 68f56d0..79276ca 100644
--- a/quic/core/crypto/aes_128_gcm_encrypter_test.cc
+++ b/quic/core/crypto/aes_128_gcm_encrypter_test.cc
@@ -220,7 +220,7 @@
TEST_F(Aes128GcmEncrypterTest, EncryptPacket) {
QuicString key = QuicTextUtils::HexDecode("d95a145250826c25a77b6a84fd4d34fc");
QuicString iv = QuicTextUtils::HexDecode("50c4431ebb18283448e276e2");
- QuicPacketNumber packet_num = 0x13278f44;
+ uint64_t packet_num = 0x13278f44;
QuicString aad =
QuicTextUtils::HexDecode("875d49f64a70c9cbe713278f44ff000005");
QuicString pt = QuicTextUtils::HexDecode("aa0003a250bd000000000001");
diff --git a/quic/core/crypto/chacha20_poly1305_decrypter_test.cc b/quic/core/crypto/chacha20_poly1305_decrypter_test.cc
index ba72027..a0c3cbe 100644
--- a/quic/core/crypto/chacha20_poly1305_decrypter_test.cc
+++ b/quic/core/crypto/chacha20_poly1305_decrypter_test.cc
@@ -116,7 +116,7 @@
QuicStringPiece nonce,
QuicStringPiece associated_data,
QuicStringPiece ciphertext) {
- QuicPacketNumber packet_number;
+ uint64_t packet_number;
QuicStringPiece nonce_prefix(nonce.data(),
nonce.size() - sizeof(packet_number));
decrypter->SetNoncePrefix(nonce_prefix);
diff --git a/quic/core/crypto/chacha20_poly1305_encrypter_test.cc b/quic/core/crypto/chacha20_poly1305_encrypter_test.cc
index b5b43fb..8d9a900 100644
--- a/quic/core/crypto/chacha20_poly1305_encrypter_test.cc
+++ b/quic/core/crypto/chacha20_poly1305_encrypter_test.cc
@@ -96,7 +96,7 @@
ASSERT_TRUE(encrypter.SetNoncePrefix("abcd"));
ASSERT_TRUE(decrypter.SetNoncePrefix("abcd"));
- QuicPacketNumber packet_number = UINT64_C(0x123456789ABC);
+ uint64_t packet_number = UINT64_C(0x123456789ABC);
QuicString associated_data = "associated_data";
QuicString plaintext = "plaintext";
char encrypted[1024];
diff --git a/quic/core/crypto/chacha20_poly1305_tls_encrypter_test.cc b/quic/core/crypto/chacha20_poly1305_tls_encrypter_test.cc
index 4a9ecf8..bc7c6c4 100644
--- a/quic/core/crypto/chacha20_poly1305_tls_encrypter_test.cc
+++ b/quic/core/crypto/chacha20_poly1305_tls_encrypter_test.cc
@@ -95,7 +95,7 @@
ASSERT_TRUE(encrypter.SetIV("abcdefghijkl"));
ASSERT_TRUE(decrypter.SetIV("abcdefghijkl"));
- QuicPacketNumber packet_number = UINT64_C(0x123456789ABC);
+ uint64_t packet_number = UINT64_C(0x123456789ABC);
QuicString associated_data = "associated_data";
QuicString plaintext = "plaintext";
char encrypted[1024];
diff --git a/quic/core/crypto/crypto_server_test.cc b/quic/core/crypto/crypto_server_test.cc
index a97b829..c2c4041 100644
--- a/quic/core/crypto/crypto_server_test.cc
+++ b/quic/core/crypto/crypto_server_test.cc
@@ -107,7 +107,7 @@
CryptoServerTest()
: rand_(QuicRandom::GetInstance()),
client_address_(QuicIpAddress::Loopback4(), 1234),
- client_version_(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED),
+ client_version_(UnsupportedQuicVersion()),
config_(QuicCryptoServerConfig::TESTING,
rand_,
crypto_test_utils::ProofSourceForTesting(),
@@ -723,6 +723,26 @@
CheckRejectReasons(kRejectReasons, QUIC_ARRAYSIZE(kRejectReasons));
}
+TEST_P(CryptoServerTest, CorruptSourceAddressTokenIsStillAccepted) {
+ // This tests corrupted source address token.
+ CryptoHandshakeMessage msg = crypto_test_utils::CreateCHLO(
+ {{"PDMD", "X509"},
+ {"AEAD", "AESG"},
+ {"KEXS", "C255"},
+ {"SCID", scid_hex_},
+ {"#004b5453", (QuicString(1, 'X') + srct_hex_)},
+ {"PUBS", pub_hex_},
+ {"NONC", nonce_hex_},
+ {"XLCT", XlctHexString()},
+ {"VER\0", client_version_string_}},
+ kClientHelloMinimumSize);
+
+ config_.set_validate_source_address_token(false);
+
+ ShouldSucceed(msg);
+ EXPECT_EQ(kSHLO, out_.tag());
+}
+
TEST_P(CryptoServerTest, CorruptClientNonceAndSourceAddressToken) {
// This test corrupts client nonce and source address token.
CryptoHandshakeMessage msg = crypto_test_utils::CreateCHLO(
diff --git a/quic/core/crypto/crypto_utils.cc b/quic/core/crypto/crypto_utils.cc
index 72fbdd9..46d172f 100644
--- a/quic/core/crypto/crypto_utils.cc
+++ b/quic/core/crypto/crypto_utils.cc
@@ -95,11 +95,13 @@
// static
void CryptoUtils::CreateTlsInitialCrypters(Perspective perspective,
+ QuicTransportVersion version,
QuicConnectionId connection_id,
CrypterPair* crypters) {
- QUIC_BUG_IF(connection_id.length() != kQuicDefaultConnectionIdLength)
- << "CreateTlsInitialCrypters called with connection ID " << connection_id
- << " of unsupported length " << connection_id.length();
+ QUIC_BUG_IF(!QuicUtils::IsConnectionIdValidForVersion(connection_id, version))
+ << "CreateTlsInitialCrypters: attempted to use connection ID "
+ << connection_id << " which is invalid with version "
+ << QuicVersionToString(version);
const EVP_MD* hash = EVP_sha256();
std::vector<uint8_t> handshake_secret;
diff --git a/quic/core/crypto/crypto_utils.h b/quic/core/crypto/crypto_utils.h
index 713822a..511bae9 100644
--- a/quic/core/crypto/crypto_utils.h
+++ b/quic/core/crypto/crypto_utils.h
@@ -90,6 +90,7 @@
// decrypter (put in |*crypters|) to use for this packet protection, as well
// as setting the key and IV on those crypters.
static void CreateTlsInitialCrypters(Perspective perspective,
+ QuicTransportVersion version,
QuicConnectionId connection_id,
CrypterPair* crypters);
diff --git a/quic/core/crypto/ephemeral_key_source.h b/quic/core/crypto/ephemeral_key_source.h
deleted file mode 100644
index e494310..0000000
--- a/quic/core/crypto/ephemeral_key_source.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef QUICHE_QUIC_CORE_CRYPTO_EPHEMERAL_KEY_SOURCE_H_
-#define QUICHE_QUIC_CORE_CRYPTO_EPHEMERAL_KEY_SOURCE_H_
-
-#include "net/third_party/quiche/src/quic/core/crypto/key_exchange.h"
-#include "net/third_party/quiche/src/quic/core/quic_time.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
-
-namespace quic {
-
-class QuicRandom;
-
-// EphemeralKeySource manages and rotates ephemeral keys as they can be reused
-// for several connections in a short space of time. Since the implementation
-// of this may involve locking or thread-local data, this interface abstracts
-// that away.
-class QUIC_EXPORT_PRIVATE EphemeralKeySource {
- public:
- virtual ~EphemeralKeySource() {}
-
- // CalculateForwardSecureKey generates an ephemeral public/private key pair
- // using the algorithm represented by |key_exchange_factory|, sets
- // |*public_value| to the public key and returns the shared key between
- // |peer_public_value| and the private key. |*public_value| will be sent to
- // the peer to be used with the peer's private key.
- virtual QuicString CalculateForwardSecureKey(
- const KeyExchange::Factory& key_exchange_factory,
- QuicRandom* rand,
- QuicTime now,
- QuicStringPiece peer_public_value,
- QuicString* public_value) = 0;
-};
-
-} // namespace quic
-
-#endif // QUICHE_QUIC_CORE_CRYPTO_EPHEMERAL_KEY_SOURCE_H_
diff --git a/quic/core/crypto/null_decrypter.cc b/quic/core/crypto/null_decrypter.cc
index ba470f5..0c108b6 100644
--- a/quic/core/crypto/null_decrypter.cc
+++ b/quic/core/crypto/null_decrypter.cc
@@ -39,7 +39,7 @@
}
bool NullDecrypter::DecryptPacket(QuicTransportVersion version,
- QuicPacketNumber /*packet_number*/,
+ uint64_t /*packet_number*/,
QuicStringPiece associated_data,
QuicStringPiece ciphertext,
char* output,
diff --git a/quic/core/crypto/null_decrypter.h b/quic/core/crypto/null_decrypter.h
index 275228c..3996eb7 100644
--- a/quic/core/crypto/null_decrypter.h
+++ b/quic/core/crypto/null_decrypter.h
@@ -36,7 +36,7 @@
bool SetPreliminaryKey(QuicStringPiece key) override;
bool SetDiversificationNonce(const DiversificationNonce& nonce) override;
bool DecryptPacket(QuicTransportVersion version,
- QuicPacketNumber packet_number,
+ uint64_t packet_number,
QuicStringPiece associated_data,
QuicStringPiece ciphertext,
char* output,
diff --git a/quic/core/crypto/null_encrypter.cc b/quic/core/crypto/null_encrypter.cc
index 524caef..e4a165f 100644
--- a/quic/core/crypto/null_encrypter.cc
+++ b/quic/core/crypto/null_encrypter.cc
@@ -27,7 +27,7 @@
}
bool NullEncrypter::EncryptPacket(QuicTransportVersion version,
- QuicPacketNumber /*packet_number*/,
+ uint64_t /*packet_number*/,
QuicStringPiece associated_data,
QuicStringPiece plaintext,
char* output,
diff --git a/quic/core/crypto/null_encrypter.h b/quic/core/crypto/null_encrypter.h
index d826202..01ecd45 100644
--- a/quic/core/crypto/null_encrypter.h
+++ b/quic/core/crypto/null_encrypter.h
@@ -30,7 +30,7 @@
bool SetNoncePrefix(QuicStringPiece nonce_prefix) override;
bool SetIV(QuicStringPiece iv) override;
bool EncryptPacket(QuicTransportVersion version,
- QuicPacketNumber packet_number,
+ uint64_t packet_number,
QuicStringPiece associated_data,
QuicStringPiece plaintext,
char* output,
diff --git a/quic/core/crypto/quic_crypto_client_config.cc b/quic/core/crypto/quic_crypto_client_config.cc
index 0a37be8..56447bb 100644
--- a/quic/core/crypto/quic_crypto_client_config.cc
+++ b/quic/core/crypto/quic_crypto_client_config.cc
@@ -13,6 +13,7 @@
#include "net/third_party/quiche/src/quic/core/crypto/channel_id.h"
#include "net/third_party/quiche/src/quic/core/crypto/common_cert_set.h"
#include "net/third_party/quiche/src/quic/core/crypto/crypto_framer.h"
+#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
#include "net/third_party/quiche/src/quic/core/crypto/crypto_utils.h"
#include "net/third_party/quiche/src/quic/core/crypto/curve25519_key_exchange.h"
#include "net/third_party/quiche/src/quic/core/crypto/key_exchange.h"
@@ -88,8 +89,8 @@
const CryptoHandshakeMessage* scfg = GetServerConfig();
if (!scfg) {
- RecordInchoateClientHelloReason(SERVER_CONFIG_CORRUPTED);
// Should be impossible short of cache corruption.
+ RecordInchoateClientHelloReason(SERVER_CONFIG_CORRUPTED);
DCHECK(false);
return false;
}
@@ -441,7 +442,11 @@
CryptoHandshakeMessage* out) const {
out->set_tag(kCHLO);
// TODO(rch): Remove this when we remove quic_use_chlo_packet_size flag.
- out->set_minimum_size(kClientHelloMinimumSize);
+ if (pad_inchoate_hello_) {
+ out->set_minimum_size(kClientHelloMinimumSize);
+ } else {
+ out->set_minimum_size(1);
+ }
// Server name indication. We only send SNI if it's a valid domain name, as
// per the spec.
@@ -517,13 +522,21 @@
CryptoHandshakeMessage* out,
QuicString* error_details) const {
DCHECK(error_details != nullptr);
- QUIC_BUG_IF(connection_id.length() != kQuicDefaultConnectionIdLength)
- << "FillClientHello called with connection ID " << connection_id
- << " of unsupported length " << connection_id.length();
+ QUIC_BUG_IF(!QuicUtils::IsConnectionIdValidForVersion(
+ connection_id, preferred_version.transport_version))
+ << "FillClientHello: attempted to use connection ID " << connection_id
+ << " which is invalid with version "
+ << QuicVersionToString(preferred_version.transport_version);
FillInchoateClientHello(server_id, preferred_version, cached, rand,
/* demand_x509_proof= */ true, out_params, out);
+ if (pad_full_hello_) {
+ out->set_minimum_size(kClientHelloMinimumSize);
+ } else {
+ out->set_minimum_size(1);
+ }
+
const CryptoHandshakeMessage* scfg = cached->GetServerConfig();
if (!scfg) {
// This should never happen as our caller should have checked
@@ -860,10 +873,9 @@
}
connection_id = QuicConnectionId(connection_id_bytes.data(),
connection_id_bytes.length());
- if (connection_id.length() != kQuicDefaultConnectionIdLength) {
+ if (!QuicUtils::IsConnectionIdValidForVersion(connection_id, version)) {
QUIC_PEER_BUG << "Received server-designated connection ID "
- << connection_id << " of bad length "
- << connection_id.length() << " with version "
+ << connection_id << " which is invalid with version "
<< QuicVersionToString(version);
*error_details = "Bad kRCID length";
return QUIC_CRYPTO_INTERNAL_ERROR;
diff --git a/quic/core/crypto/quic_crypto_client_config.h b/quic/core/crypto/quic_crypto_client_config.h
index c7e46a9..32df726 100644
--- a/quic/core/crypto/quic_crypto_client_config.h
+++ b/quic/core/crypto/quic_crypto_client_config.h
@@ -13,6 +13,7 @@
#include "base/macros.h"
#include "third_party/boringssl/src/include/openssl/base.h"
#include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake.h"
+#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/core/quic_server_id.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
@@ -351,6 +352,14 @@
pre_shared_key_ = QuicString(psk);
}
+ bool pad_inchoate_hello() const { return pad_inchoate_hello_; }
+ void set_pad_inchoate_hello(bool new_value) {
+ pad_inchoate_hello_ = new_value;
+ }
+
+ bool pad_full_hello() const { return pad_full_hello_; }
+ void set_pad_full_hello(bool new_value) { pad_full_hello_ = new_value; }
+
private:
// Sets the members to reasonable, default values.
void SetDefaults();
@@ -402,6 +411,20 @@
// If non-empty, the client will operate in the pre-shared key mode by
// incorporating |pre_shared_key_| into the key schedule.
QuicString pre_shared_key_;
+
+ // In QUIC, technically, client hello should be fully padded.
+ // However, fully padding on slow network connection (e.g. 50kbps) can add
+ // 150ms latency to one roundtrip. Therefore, you can disable padding of
+ // individual messages. It is recommend to leave at least one message in
+ // each direction fully padded (e.g. full CHLO and SHLO), but if you know
+ // the lower-bound MTU, you don't need to pad all of them (keep in mind that
+ // it's not OK to do it according to the standard).
+ //
+ // Also, if you disable padding, you must disable (change) the
+ // anti-amplification protection. You should only do so if you have some
+ // other means of verifying the client.
+ bool pad_inchoate_hello_ = true;
+ bool pad_full_hello_ = true;
};
} // namespace quic
diff --git a/quic/core/crypto/quic_crypto_client_config_test.cc b/quic/core/crypto/quic_crypto_client_config_test.cc
index 8cc0420..5e0ca6e 100644
--- a/quic/core/crypto/quic_crypto_client_config_test.cc
+++ b/quic/core/crypto/quic_crypto_client_config_test.cc
@@ -113,9 +113,11 @@
TEST_F(QuicCryptoClientConfigTest, CachedState_ServerIdConsumedBeforeSet) {
QuicCryptoClientConfig::CachedState state;
EXPECT_FALSE(state.has_server_designated_connection_id());
+#if GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
EXPECT_DEBUG_DEATH(state.GetNextServerDesignatedConnectionId(),
"Attempting to consume a connection id "
"that was never designated.");
+#endif // GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
}
TEST_F(QuicCryptoClientConfigTest, CachedState_ServerNonce) {
@@ -152,9 +154,11 @@
TEST_F(QuicCryptoClientConfigTest, CachedState_ServerNonceConsumedBeforeSet) {
QuicCryptoClientConfig::CachedState state;
EXPECT_FALSE(state.has_server_nonce());
+#if GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
EXPECT_DEBUG_DEATH(state.GetNextServerNonce(),
"Attempting to consume a server nonce "
"that was never designated.");
+#endif // GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
}
TEST_F(QuicCryptoClientConfigTest, CachedState_InitializeFrom) {
@@ -197,6 +201,26 @@
QuicStringPiece alpn;
EXPECT_TRUE(msg.GetStringPiece(kALPN, &alpn));
EXPECT_EQ("hq", alpn);
+
+ EXPECT_EQ(msg.minimum_size(), 1024u);
+}
+
+TEST_F(QuicCryptoClientConfigTest, InchoateChloIsNotPadded) {
+ QuicCryptoClientConfig::CachedState state;
+ QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting(),
+ TlsClientHandshaker::CreateSslCtx());
+ config.set_pad_inchoate_hello(false);
+ config.set_user_agent_id("quic-tester");
+ config.set_alpn("hq");
+ QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params(
+ new QuicCryptoNegotiatedParameters);
+ CryptoHandshakeMessage msg;
+ QuicServerId server_id("www.google.com", 443, false);
+ MockRandom rand;
+ config.FillInchoateClientHello(server_id, QuicVersionMax(), &state, &rand,
+ /* demand_x509_proof= */ true, params, &msg);
+
+ EXPECT_EQ(msg.minimum_size(), 1u);
}
// Make sure AES-GCM is the preferred encryption algorithm if it has hardware
@@ -307,6 +331,30 @@
EXPECT_EQ(CreateQuicVersionLabel(QuicVersionMax()), cver);
}
+TEST_F(QuicCryptoClientConfigTest, FillClientHelloNoPadding) {
+ QuicCryptoClientConfig::CachedState state;
+ QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting(),
+ TlsClientHandshaker::CreateSslCtx());
+ config.set_pad_full_hello(false);
+ QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params(
+ new QuicCryptoNegotiatedParameters);
+ QuicConnectionId kConnectionId = TestConnectionId(1234);
+ QuicString error_details;
+ MockRandom rand;
+ CryptoHandshakeMessage chlo;
+ QuicServerId server_id("www.google.com", 443, false);
+ config.FillClientHello(server_id, kConnectionId, QuicVersionMax(), &state,
+ QuicWallTime::Zero(), &rand,
+ nullptr, // channel_id_key
+ params, &chlo, &error_details);
+
+ // Verify that the version label has been set correctly in the CHLO.
+ QuicVersionLabel cver;
+ EXPECT_EQ(QUIC_NO_ERROR, chlo.GetVersionLabel(kVER, &cver));
+ EXPECT_EQ(CreateQuicVersionLabel(QuicVersionMax()), cver);
+ EXPECT_EQ(chlo.minimum_size(), 1u);
+}
+
TEST_F(QuicCryptoClientConfigTest, ProcessServerDowngradeAttack) {
ParsedQuicVersionVector supported_versions = AllSupportedVersions();
if (supported_versions.size() == 1) {
diff --git a/quic/core/crypto/quic_crypto_server_config.cc b/quic/core/crypto/quic_crypto_server_config.cc
index 1004236..851f8e3 100644
--- a/quic/core/crypto/quic_crypto_server_config.cc
+++ b/quic/core/crypto/quic_crypto_server_config.cc
@@ -20,7 +20,6 @@
#include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message.h"
#include "net/third_party/quiche/src/quic/core/crypto/crypto_utils.h"
#include "net/third_party/quiche/src/quic/core/crypto/curve25519_key_exchange.h"
-#include "net/third_party/quiche/src/quic/core/crypto/ephemeral_key_source.h"
#include "net/third_party/quiche/src/quic/core/crypto/key_exchange.h"
#include "net/third_party/quiche/src/quic/core/crypto/p256_key_exchange.h"
#include "net/third_party/quiche/src/quic/core/crypto/proof_source.h"
@@ -35,6 +34,7 @@
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_cert_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_clock.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_endian.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_fallthrough.h"
@@ -220,7 +220,11 @@
source_address_token_future_secs_(3600),
source_address_token_lifetime_secs_(86400),
enable_serving_sct_(false),
- rejection_observer_(nullptr) {
+ rejection_observer_(nullptr),
+ pad_rej_(true),
+ pad_shlo_(true),
+ validate_chlo_size_(true),
+ validate_source_address_token_(true) {
DCHECK(proof_source_.get());
source_address_token_boxer_.SetKeys(
{DeriveSourceAddressTokenKey(source_address_token_secret)});
@@ -507,13 +511,11 @@
QuicReferenceCountedPointer<Config> primary_config;
{
QuicReaderMutexLock locked(&configs_lock_);
-
if (!primary_config_.get()) {
result->error_code = QUIC_CRYPTO_INTERNAL_ERROR;
result->error_details = "No configurations loaded";
} else {
- if (!next_config_promotion_time_.IsZero() &&
- next_config_promotion_time_.IsAfter(now)) {
+ if (IsNextConfigReady(now)) {
configs_lock_.ReaderUnlock();
configs_lock_.WriterLock();
SelectNewPrimaryConfig(now);
@@ -678,6 +680,7 @@
validate_chlo_result,
QuicConnectionId connection_id,
const QuicSocketAddress& client_address,
+ ParsedQuicVersion version,
const ParsedQuicVersionVector& supported_versions,
const QuicClock* clock,
QuicRandom* rand,
@@ -694,6 +697,7 @@
validate_chlo_result_(std::move(validate_chlo_result)),
connection_id_(connection_id),
client_address_(client_address),
+ version_(version),
supported_versions_(supported_versions),
clock_(clock),
rand_(rand),
@@ -707,7 +711,7 @@
config_->ProcessClientHelloAfterCalculateSharedKeys(
!ok, std::move(proof_source_details_), key_exchange_factory_,
std::move(out_), public_value_, *validate_chlo_result_, connection_id_,
- client_address_, supported_versions_, clock_, rand_, params_,
+ client_address_, version_, supported_versions_, clock_, rand_, params_,
signed_config_, requested_config_, primary_config_,
std::move(done_cb_));
}
@@ -722,6 +726,7 @@
validate_chlo_result_;
QuicConnectionId connection_id_;
const QuicSocketAddress client_address_;
+ ParsedQuicVersion version_;
const ParsedQuicVersionVector supported_versions_;
const QuicClock* clock_;
QuicRandom* rand_;
@@ -780,8 +785,7 @@
if (!primary_config_) {
no_primary_config = true;
} else {
- if (!next_config_promotion_time_.IsZero() &&
- next_config_promotion_time_.IsAfter(now)) {
+ if (IsNextConfigReady(now)) {
configs_lock_.ReaderUnlock();
configs_lock_.WriterLock();
SelectNewPrimaryConfig(now);
@@ -867,11 +871,11 @@
const QuicReferenceCountedPointer<Config>& requested_config,
const QuicReferenceCountedPointer<Config>& primary_config,
std::unique_ptr<ProcessClientHelloResultCallback> done_cb) const {
- if (connection_id.length() != kQuicDefaultConnectionIdLength) {
- QUIC_BUG << "ProcessClientHelloAfterGetProof called with connection ID "
- << connection_id << " of unsupported length "
- << connection_id.length();
- }
+ QUIC_BUG_IF(!QuicUtils::IsConnectionIdValidForVersion(
+ connection_id, version.transport_version))
+ << "ProcessClientHelloAfterGetProof: attempted to use connection ID "
+ << connection_id << " which is invalid with version "
+ << QuicVersionToString(version.transport_version);
if (!QuicConnectionIdSupportsVariableLength(Perspective::IS_SERVER)) {
connection_id = QuicConnectionIdFromUInt64(
QuicEndian::HostToNet64(QuicConnectionIdToUInt64(connection_id)));
@@ -965,25 +969,13 @@
// TODO(rch): Would it be better to implement a move operator and just
// std::move(helper) instead of done_cb?
helper.DetachCallback();
- if (GetQuicRestartFlag(quic_use_async_key_exchange)) {
- QUIC_RESTART_FLAG_COUNT(quic_use_async_key_exchange);
- auto cb = QuicMakeUnique<ProcessClientHelloAfterGetProofCallback>(
- this, std::move(proof_source_details), key_exchange->GetFactory(),
- std::move(out), public_value, validate_chlo_result, connection_id,
- client_address, supported_versions, clock, rand, params, signed_config,
- requested_config, primary_config, std::move(done_cb));
- key_exchange->CalculateSharedKey(
- public_value, ¶ms->initial_premaster_secret, std::move(cb));
- } else {
- found_error = !key_exchange->CalculateSharedKey(
- public_value, ¶ms->initial_premaster_secret);
- ProcessClientHelloAfterCalculateSharedKeys(
- found_error, std::move(proof_source_details),
- key_exchange->GetFactory(), std::move(out), public_value,
- *validate_chlo_result, connection_id, client_address,
- supported_versions, clock, rand, params, signed_config,
- requested_config, primary_config, std::move(done_cb));
- }
+ auto cb = QuicMakeUnique<ProcessClientHelloAfterGetProofCallback>(
+ this, std::move(proof_source_details), key_exchange->GetFactory(),
+ std::move(out), public_value, validate_chlo_result, connection_id,
+ client_address, version, supported_versions, clock, rand, params,
+ signed_config, requested_config, primary_config, std::move(done_cb));
+ key_exchange->CalculateSharedKey(
+ public_value, ¶ms->initial_premaster_secret, std::move(cb));
}
void QuicCryptoServerConfig::ProcessClientHelloAfterCalculateSharedKeys(
@@ -995,6 +987,7 @@
const ValidateClientHelloResultCallback::Result& validate_chlo_result,
QuicConnectionId connection_id,
const QuicSocketAddress& client_address,
+ ParsedQuicVersion version,
const ParsedQuicVersionVector& supported_versions,
const QuicClock* clock,
QuicRandom* rand,
@@ -1003,12 +996,12 @@
const QuicReferenceCountedPointer<Config>& requested_config,
const QuicReferenceCountedPointer<Config>& primary_config,
std::unique_ptr<ProcessClientHelloResultCallback> done_cb) const {
- if (connection_id.length() != kQuicDefaultConnectionIdLength) {
- QUIC_BUG << "ProcessClientHelloAfterCalculateSharedKeys called with "
- "connection ID "
- << connection_id << " of unsupported length "
- << connection_id.length();
- }
+ QUIC_BUG_IF(!QuicUtils::IsConnectionIdValidForVersion(
+ connection_id, version.transport_version))
+ << "ProcessClientHelloAfterCalculateSharedKeys:"
+ " attempted to use connection ID "
+ << connection_id << " which is invalid with version "
+ << QuicVersionToString(version.transport_version);
ProcessClientHelloHelper helper(&done_cb);
if (found_error) {
@@ -1140,30 +1133,14 @@
}
QuicString forward_secure_public_value;
- if (GetQuicRestartFlag(quic_no_ephemeral_key_source)) {
- if (ephemeral_key_source_) {
- QUIC_BUG << "quic_no_ephemeral_key_source flag is on, but "
- "ephemeral_key_source is present";
- } else {
- QUIC_RESTART_FLAG_COUNT(quic_no_ephemeral_key_source);
- }
- }
- if (ephemeral_key_source_) {
- params->forward_secure_premaster_secret =
- ephemeral_key_source_->CalculateForwardSecureKey(
- key_exchange_factory, rand, clock->ApproximateNow(), public_value,
- &forward_secure_public_value);
- } else {
- std::unique_ptr<KeyExchange> forward_secure_key_exchange =
- key_exchange_factory.Create(rand);
- forward_secure_public_value =
- QuicString(forward_secure_key_exchange->public_value());
- if (!forward_secure_key_exchange->CalculateSharedKey(
- public_value, ¶ms->forward_secure_premaster_secret)) {
- helper.Fail(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER,
- "Invalid public value");
- return;
- }
+ std::unique_ptr<KeyExchange> forward_secure_key_exchange =
+ key_exchange_factory.Create(rand);
+ forward_secure_public_value =
+ QuicString(forward_secure_key_exchange->public_value());
+ if (!forward_secure_key_exchange->CalculateSharedKey(
+ public_value, ¶ms->forward_secure_premaster_secret)) {
+ helper.Fail(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER, "Invalid public value");
+ return;
}
QuicString forward_secure_hkdf_input;
@@ -1332,7 +1309,6 @@
requested_config,
QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>
primary_config,
- bool use_get_cert_chain,
QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config,
QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
client_hello_state,
@@ -1342,7 +1318,6 @@
version_(version),
requested_config_(std::move(requested_config)),
primary_config_(std::move(primary_config)),
- use_get_cert_chain_(use_get_cert_chain),
signed_config_(signed_config),
client_hello_state_(std::move(client_hello_state)),
done_cb_(std::move(done_cb)) {}
@@ -1357,8 +1332,8 @@
}
config_.EvaluateClientHelloAfterGetProof(
server_ip_, version_, requested_config_, primary_config_,
- signed_config_, std::move(details), use_get_cert_chain_, !ok,
- client_hello_state_, std::move(done_cb_));
+ signed_config_, std::move(details), !ok, client_hello_state_,
+ std::move(done_cb_));
}
private:
@@ -1369,7 +1344,6 @@
requested_config_;
const QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>
primary_config_;
- const bool use_get_cert_chain_;
QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config_;
QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
client_hello_state_;
@@ -1392,7 +1366,7 @@
const CryptoHandshakeMessage& client_hello = client_hello_state->client_hello;
ClientHelloInfo* info = &(client_hello_state->info);
- if (client_hello.size() < kClientHelloMinimumSize) {
+ if (validate_chlo_size_ && client_hello.size() < kClientHelloMinimumSize) {
helper.ValidationComplete(QUIC_CRYPTO_INVALID_VALUE_LENGTH,
"Client hello too small", nullptr);
return;
@@ -1408,22 +1382,27 @@
client_hello.GetStringPiece(kUAID, &info->user_agent_id);
HandshakeFailureReason source_address_token_error = MAX_FAILURE_REASON;
- QuicStringPiece srct;
- if (client_hello.GetStringPiece(kSourceAddressTokenTag, &srct)) {
- Config& config =
- requested_config != nullptr ? *requested_config : *primary_config;
- source_address_token_error =
- ParseSourceAddressToken(config, srct, &info->source_address_tokens);
+ if (validate_source_address_token_) {
+ QuicStringPiece srct;
+ if (client_hello.GetStringPiece(kSourceAddressTokenTag, &srct)) {
+ Config& config =
+ requested_config != nullptr ? *requested_config : *primary_config;
+ source_address_token_error =
+ ParseSourceAddressToken(config, srct, &info->source_address_tokens);
- if (source_address_token_error == HANDSHAKE_OK) {
- source_address_token_error = ValidateSourceAddressTokens(
- info->source_address_tokens, info->client_ip, info->now,
- &client_hello_state->cached_network_params);
+ if (source_address_token_error == HANDSHAKE_OK) {
+ source_address_token_error = ValidateSourceAddressTokens(
+ info->source_address_tokens, info->client_ip, info->now,
+ &client_hello_state->cached_network_params);
+ }
+ info->valid_source_address_token =
+ (source_address_token_error == HANDSHAKE_OK);
+ } else {
+ source_address_token_error = SOURCE_ADDRESS_TOKEN_INVALID_FAILURE;
}
- info->valid_source_address_token =
- (source_address_token_error == HANDSHAKE_OK);
} else {
- source_address_token_error = SOURCE_ADDRESS_TOKEN_INVALID_FAILURE;
+ source_address_token_error = HANDSHAKE_OK;
+ info->valid_source_address_token = true;
}
if (!requested_config.get()) {
@@ -1450,28 +1429,6 @@
// No valid source address token.
}
- const bool use_get_cert_chain =
- GetQuicReloadableFlag(quic_use_get_cert_chain);
- if (!use_get_cert_chain) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_use_get_cert_chain, 1, 2);
- QuicString serialized_config = primary_config->serialized;
- QuicString chlo_hash;
- CryptoUtils::HashHandshakeMessage(client_hello, &chlo_hash,
- Perspective::IS_SERVER);
- // Make an async call to GetProof and setup the callback to trampoline
- // back into EvaluateClientHelloAfterGetProof
- auto cb = QuicMakeUnique<EvaluateClientHelloCallback>(
- *this, server_address.host(), version, requested_config, primary_config,
- use_get_cert_chain, signed_config, client_hello_state,
- std::move(done_cb));
- proof_source_->GetProof(server_address, QuicString(info->sni),
- serialized_config, version, chlo_hash,
- std::move(cb));
- helper.DetachCallback();
- return;
- }
-
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_use_get_cert_chain, 2, 2);
QuicReferenceCountedPointer<ProofSource::Chain> chain =
proof_source_->GetCertChain(server_address, QuicString(info->sni));
if (!chain) {
@@ -1481,7 +1438,7 @@
}
EvaluateClientHelloAfterGetProof(
server_address.host(), version, requested_config, primary_config,
- signed_config, /*proof_source_details=*/nullptr, use_get_cert_chain,
+ signed_config, /*proof_source_details=*/nullptr,
/*get_proof_failed=*/false, client_hello_state, std::move(done_cb));
helper.DetachCallback();
}
@@ -1493,7 +1450,6 @@
QuicReferenceCountedPointer<Config> primary_config,
QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config,
std::unique_ptr<ProofSource::Details> proof_source_details,
- bool use_get_cert_chain,
bool get_proof_failed,
QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
client_hello_state,
@@ -1502,18 +1458,6 @@
const CryptoHandshakeMessage& client_hello = client_hello_state->client_hello;
ClientHelloInfo* info = &(client_hello_state->info);
- if (!use_get_cert_chain) {
- if (get_proof_failed) {
- info->reject_reasons.push_back(SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE);
- }
-
- if (signed_config->chain != nullptr &&
- !ValidateExpectedLeafCertificate(client_hello,
- signed_config->chain->certs)) {
- info->reject_reasons.push_back(INVALID_EXPECTED_LEAF_CERTIFICATE);
- }
- }
-
if (info->client_nonce.size() != kNonceSize) {
info->reject_reasons.push_back(CLIENT_NONCE_INVALID_FAILURE);
// Invalid client nonce.
@@ -1673,12 +1617,11 @@
out->SetValue(kRCID, QuicEndian::HostToNet64(QuicConnectionIdToUInt64(
server_designated_connection_id)));
} else {
- if (server_designated_connection_id.length() !=
- kQuicDefaultConnectionIdLength &&
- version < QUIC_VERSION_99) {
- QUIC_BUG << "Tried to send connection ID "
- << server_designated_connection_id << " of bad length "
- << server_designated_connection_id.length() << " with version "
+ if (!QuicUtils::IsConnectionIdValidForVersion(
+ server_designated_connection_id, version)) {
+ QUIC_BUG << "Tried to send server designated connection ID "
+ << server_designated_connection_id
+ << " which is invalid with version "
<< QuicVersionToString(version);
return;
}
@@ -1754,8 +1697,22 @@
out->SetStringPiece(kPROF, signed_config.proof.signature);
if (should_return_sct) {
if (cert_sct.empty()) {
- QUIC_LOG_EVERY_N_SEC(WARNING, 60)
- << "SCT is expected but it is empty. sni :" << params->sni;
+ if (!GetQuicReloadableFlag(quic_log_cert_name_for_empty_sct)) {
+ QUIC_LOG_EVERY_N_SEC(WARNING, 60)
+ << "SCT is expected but it is empty. sni :" << params->sni;
+ } else {
+ // Log SNI and subject name for the leaf cert if its SCT is empty.
+ // This is for debugging b/28342827.
+ const std::vector<quic::QuicString>& certs =
+ signed_config.chain->certs;
+ QuicStringPiece ca_subject;
+ if (!certs.empty()) {
+ QuicCertUtils::ExtractSubjectNameFromDERCert(certs[0], &ca_subject);
+ }
+ QUIC_LOG_EVERY_N_SEC(WARNING, 60)
+ << "SCT is expected but it is empty. sni: '" << params->sni
+ << "' cert subject: '" << ca_subject << "'";
+ }
} else {
out->SetStringPiece(kCertificateSCTTag, cert_sct);
}
@@ -1855,7 +1812,7 @@
static_assert(sizeof(config->orbit) == kOrbitSize, "incorrect orbit size");
memcpy(config->orbit, orbit.data(), sizeof(config->orbit));
- if (kexs_tags.size() != protobuf->key_size()) {
+ if (kexs_tags.size() != static_cast<size_t>(protobuf->key_size())) {
QUIC_LOG(WARNING) << "Server config has " << kexs_tags.size()
<< " key exchange methods configured, but "
<< protobuf->key_size() << " private keys";
@@ -1878,7 +1835,7 @@
config->kexs.push_back(tag);
- for (size_t j = 0; j < protobuf->key_size(); j++) {
+ for (int j = 0; j < protobuf->key_size(); j++) {
const QuicServerConfigProtobuf::PrivateKey& key = protobuf->key(i);
if (key.tag() == tag) {
private_key = key.private_key();
@@ -1911,11 +1868,6 @@
return config;
}
-void QuicCryptoServerConfig::SetEphemeralKeySource(
- std::unique_ptr<EphemeralKeySource> ephemeral_key_source) {
- ephemeral_key_source_ = std::move(ephemeral_key_source);
-}
-
void QuicCryptoServerConfig::set_replay_protection(bool on) {
replay_protection_ = on;
}
@@ -2124,6 +2076,15 @@
return false;
}
+bool QuicCryptoServerConfig::IsNextConfigReady(QuicWallTime now) const {
+ if (GetQuicReloadableFlag(quic_fix_config_rotation)) {
+ return !next_config_promotion_time_.IsZero() &&
+ !next_config_promotion_time_.IsAfter(now);
+ }
+ return !next_config_promotion_time_.IsZero() &&
+ next_config_promotion_time_.IsAfter(now);
+}
+
QuicCryptoServerConfig::Config::Config()
: channel_id_enabled(false),
is_primary(false),
diff --git a/quic/core/crypto/quic_crypto_server_config.h b/quic/core/crypto/quic_crypto_server_config.h
index b10786d..3561844 100644
--- a/quic/core/crypto/quic_crypto_server_config.h
+++ b/quic/core/crypto/quic_crypto_server_config.h
@@ -34,7 +34,6 @@
namespace quic {
class CryptoHandshakeMessage;
-class EphemeralKeySource;
class ProofSource;
class QuicClock;
class QuicRandom;
@@ -370,12 +369,6 @@
const CachedNetworkParameters* cached_network_params,
std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb) const;
- // SetEphemeralKeySource installs an object that can cache ephemeral keys for
- // a short period of time. If not set, ephemeral keys will be generated
- // per-connection.
- void SetEphemeralKeySource(
- std::unique_ptr<EphemeralKeySource> ephemeral_key_source);
-
// set_replay_protection controls whether replay protection is enabled. If
// replay protection is disabled then no strike registers are needed and
// frontends can share an orbit value without a shared strike-register.
@@ -388,6 +381,19 @@
// valid source-address token.
void set_chlo_multiplier(size_t multiplier);
+ // When sender is allowed to not pad client hello (not standards compliant),
+ // we need to disable the client hello check.
+ void set_validate_chlo_size(bool new_value) {
+ validate_chlo_size_ = new_value;
+ }
+
+ // When QUIC is tunneled through some other mechanism, source token validation
+ // may be disabled. Do not disable it if you are not providing other
+ // protection. (|true| protects against UDP amplification attack.).
+ void set_validate_source_address_token(bool new_value) {
+ validate_source_address_token_ = new_value;
+ }
+
// set_source_address_token_future_secs sets the number of seconds into the
// future that source-address tokens will be accepted from. Since
// source-address tokens are authenticated, this should only happen if
@@ -423,6 +429,12 @@
pre_shared_key_ = QuicString(psk);
}
+ bool pad_rej() const { return pad_rej_; }
+ void set_pad_rej(bool new_value) { pad_rej_ = new_value; }
+
+ bool pad_shlo() const { return pad_shlo_; }
+ void set_pad_shlo(bool new_value) { pad_shlo_ = new_value; }
+
private:
friend class test::QuicCryptoServerConfigPeer;
friend struct QuicSignedServerConfig;
@@ -539,7 +551,6 @@
QuicReferenceCountedPointer<Config> primary_config,
QuicReferenceCountedPointer<QuicSignedServerConfig> crypto_proof,
std::unique_ptr<ProofSource::Details> proof_source_details,
- bool use_get_cert_chain,
bool get_proof_failed,
QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
client_hello_state,
@@ -589,6 +600,7 @@
const ValidateClientHelloResultCallback::Result& validate_chlo_result,
QuicConnectionId connection_id,
const QuicSocketAddress& client_address,
+ ParsedQuicVersion version,
const ParsedQuicVersionVector& supported_versions,
const QuicClock* clock,
QuicRandom* rand,
@@ -754,6 +766,10 @@
CryptoHandshakeMessage message,
std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb) const;
+ // Returns true if the next config promotion should happen now.
+ bool IsNextConfigReady(QuicWallTime now) const
+ SHARED_LOCKS_REQUIRED(configs_lock_);
+
// replay_protection_ controls whether the server enforces that handshakes
// aren't replays.
bool replay_protection_;
@@ -805,10 +821,6 @@
// ssl_ctx_ contains the server configuration for doing TLS handshakes.
bssl::UniquePtr<SSL_CTX> ssl_ctx_;
- // ephemeral_key_source_ contains an object that caches ephemeral keys for a
- // short period of time.
- std::unique_ptr<EphemeralKeySource> ephemeral_key_source_;
-
// These fields store configuration values. See the comments for their
// respective setter functions.
uint32_t source_address_token_future_secs_;
@@ -823,6 +835,23 @@
// If non-empty, the server will operate in the pre-shared key mode by
// incorporating |pre_shared_key_| into the key schedule.
QuicString pre_shared_key_;
+
+ // Whether REJ message should be padded to max packet size.
+ bool pad_rej_;
+
+ // Whether SHLO message should be padded to max packet size.
+ bool pad_shlo_;
+
+ // If client is allowed to send a small client hello (by disabling padding),
+ // server MUST not check for the client hello size.
+ // DO NOT disable this unless you have some other way of validating client.
+ // (e.g. in realtime scenarios, where quic is tunneled through ICE, ICE will
+ // do its own peer validation using STUN pings with ufrag/upass).
+ bool validate_chlo_size_;
+
+ // When source address is validated by some other means (e.g. when using ICE),
+ // source address token validation may be disabled.
+ bool validate_source_address_token_;
};
struct QUIC_EXPORT_PRIVATE QuicSignedServerConfig
diff --git a/quic/core/crypto/quic_crypto_server_config_test.cc b/quic/core/crypto/quic_crypto_server_config_test.cc
index 15de28b..81e6951 100644
--- a/quic/core/crypto/quic_crypto_server_config_test.cc
+++ b/quic/core/crypto/quic_crypto_server_config_test.cc
@@ -258,12 +258,12 @@
NewSourceAddressToken(kPrimary, ip4_, &cached_network_params_input);
CachedNetworkParameters cached_network_params_output;
- EXPECT_NE(cached_network_params_output.DebugString(),
- cached_network_params_input.DebugString());
+ EXPECT_NE(cached_network_params_output.SerializeAsString(),
+ cached_network_params_input.SerializeAsString());
ValidateSourceAddressTokens(kPrimary, token4_with_cached_network_params, ip4_,
&cached_network_params_output);
- EXPECT_EQ(cached_network_params_output.DebugString(),
- cached_network_params_input.DebugString());
+ EXPECT_EQ(cached_network_params_output.SerializeAsString(),
+ cached_network_params_input.SerializeAsString());
}
// Test the ability for a source address token to be valid for multiple
@@ -457,6 +457,33 @@
test_peer_.CheckConfigs({{"a", false}, {"b", true}});
}
+class ValidateCallback : public ValidateClientHelloResultCallback {
+ public:
+ void Run(QuicReferenceCountedPointer<Result> result,
+ std::unique_ptr<ProofSource::Details> /* details */) override {}
+};
+
+TEST_F(CryptoServerConfigsTest, AdvancePrimaryViaValidate) {
+ SetQuicReloadableFlag(quic_fix_config_rotation, true);
+ // Check that a new primary config is enabled at the right time.
+ SetConfigs({{"a", 900, 1}, {"b", 1100, 1}});
+ test_peer_.SelectNewPrimaryConfig(1000);
+ test_peer_.CheckConfigs({{"a", true}, {"b", false}});
+ CryptoHandshakeMessage client_hello;
+ QuicIpAddress client_ip;
+ QuicSocketAddress server_address;
+ QuicTransportVersion version = QUIC_VERSION_99;
+ MockClock clock;
+ QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config(
+ new QuicSignedServerConfig);
+ std::unique_ptr<ValidateClientHelloResultCallback> done_cb(
+ new ValidateCallback);
+ clock.AdvanceTime(QuicTime::Delta::FromSeconds(1100));
+ config_.ValidateClientHello(client_hello, client_ip, server_address, version,
+ &clock, signed_config, std::move(done_cb));
+ test_peer_.CheckConfigs({{"a", false}, {"b", true}});
+}
+
TEST_F(CryptoServerConfigsTest, InvalidConfigs) {
// Ensure that invalid configs don't change anything.
SetConfigs({{"a", 800, 1}, {"b", 900, 1}, {"c", 1100, 1}});
diff --git a/quic/core/crypto/quic_decrypter.h b/quic/core/crypto/quic_decrypter.h
index f61f621..892504c 100644
--- a/quic/core/crypto/quic_decrypter.h
+++ b/quic/core/crypto/quic_decrypter.h
@@ -54,7 +54,7 @@
// TODO(wtc): add a way for DecryptPacket to report decryption failure due
// to non-authentic inputs, as opposed to other reasons for failure.
virtual bool DecryptPacket(QuicTransportVersion version,
- QuicPacketNumber packet_number,
+ uint64_t packet_number,
QuicStringPiece associated_data,
QuicStringPiece ciphertext,
char* output,
diff --git a/quic/core/crypto/quic_encrypter.h b/quic/core/crypto/quic_encrypter.h
index ea1cee8..591021e 100644
--- a/quic/core/crypto/quic_encrypter.h
+++ b/quic/core/crypto/quic_encrypter.h
@@ -35,7 +35,7 @@
// |associated_data|. If |output| overlaps with |plaintext| then
// |plaintext| must be <= |output|.
virtual bool EncryptPacket(QuicTransportVersion version,
- QuicPacketNumber packet_number,
+ uint64_t packet_number,
QuicStringPiece associated_data,
QuicStringPiece plaintext,
char* output,
diff --git a/quic/core/frames/quic_ack_frame.cc b/quic/core/frames/quic_ack_frame.cc
index 3493f97..5f47b3f 100644
--- a/quic/core/frames/quic_ack_frame.cc
+++ b/quic/core/frames/quic_ack_frame.cc
@@ -12,19 +12,29 @@
namespace quic {
namespace {
-const QuicPacketNumber kMaxPrintRange = 128;
+
+const QuicPacketCount kMaxPrintRange = 128;
+
+uint64_t PacketNumberIntervalLength(
+ const QuicInterval<QuicPacketNumber>& interval) {
+ if (interval.Empty()) {
+ return 0u;
+ }
+ return interval.max() - interval.min();
+}
} // namespace
bool IsAwaitingPacket(const QuicAckFrame& ack_frame,
QuicPacketNumber packet_number,
QuicPacketNumber peer_least_packet_awaiting_ack) {
- return packet_number >= peer_least_packet_awaiting_ack &&
+ DCHECK(packet_number.IsInitialized());
+ return (!peer_least_packet_awaiting_ack.IsInitialized() ||
+ packet_number >= peer_least_packet_awaiting_ack) &&
!ack_frame.packets.Contains(packet_number);
}
QuicAckFrame::QuicAckFrame()
- : largest_acked(kInvalidPacketNumber),
- ack_delay_time(QuicTime::Delta::Infinite()),
+ : ack_delay_time(QuicTime::Delta::Infinite()),
ecn_counters_populated(false),
ect_0_count(0),
ect_1_count(0),
@@ -56,7 +66,7 @@
}
void QuicAckFrame::Clear() {
- largest_acked = kInvalidPacketNumber;
+ largest_acked.Clear();
ack_delay_time = QuicTime::Delta::Infinite();
received_packet_times.clear();
packets.Clear();
@@ -73,6 +83,9 @@
default;
void PacketNumberQueue::Add(QuicPacketNumber packet_number) {
+ if (!packet_number.IsInitialized()) {
+ return;
+ }
// Check if the deque is empty
if (packet_number_deque_.empty()) {
packet_number_deque_.push_front(
@@ -148,7 +161,7 @@
void PacketNumberQueue::AddRange(QuicPacketNumber lower,
QuicPacketNumber higher) {
- if (lower >= higher) {
+ if (!lower.IsInitialized() || !higher.IsInitialized() || lower >= higher) {
return;
}
if (packet_number_deque_.empty()) {
@@ -187,7 +200,7 @@
}
bool PacketNumberQueue::RemoveUpTo(QuicPacketNumber higher) {
- if (Empty()) {
+ if (!higher.IsInitialized() || Empty()) {
return false;
}
const QuicPacketNumber old_min = Min();
@@ -221,7 +234,7 @@
}
bool PacketNumberQueue::Contains(QuicPacketNumber packet_number) const {
- if (packet_number_deque_.empty()) {
+ if (!packet_number.IsInitialized() || packet_number_deque_.empty()) {
return false;
}
if (packet_number_deque_.front().min() > packet_number ||
@@ -253,7 +266,7 @@
QuicPacketCount PacketNumberQueue::NumPacketsSlow() const {
QuicPacketCount n_packets = 0;
for (QuicInterval<QuicPacketNumber> interval : packet_number_deque_) {
- n_packets += interval.Length();
+ n_packets += PacketNumberIntervalLength(interval);
}
return n_packets;
}
@@ -278,9 +291,9 @@
return packet_number_deque_.rend();
}
-QuicPacketNumber PacketNumberQueue::LastIntervalLength() const {
+QuicPacketCount PacketNumberQueue::LastIntervalLength() const {
DCHECK(!Empty());
- return packet_number_deque_.back().Length();
+ return PacketNumberIntervalLength(packet_number_deque_.back());
}
// Largest min...max range for packet numbers where we print the numbers
diff --git a/quic/core/frames/quic_ack_frame.h b/quic/core/frames/quic_ack_frame.h
index 29d511e..4dcfc3d 100644
--- a/quic/core/frames/quic_ack_frame.h
+++ b/quic/core/frames/quic_ack_frame.h
@@ -73,7 +73,7 @@
size_t NumIntervals() const;
// Returns the length of last interval.
- QuicPacketNumber LastIntervalLength() const;
+ QuicPacketCount LastIntervalLength() const;
// Returns iterators over the packet number intervals.
const_iterator begin() const;
diff --git a/quic/core/frames/quic_blocked_frame.h b/quic/core/frames/quic_blocked_frame.h
index 3203c67..a4be664 100644
--- a/quic/core/frames/quic_blocked_frame.h
+++ b/quic/core/frames/quic_blocked_frame.h
@@ -37,6 +37,9 @@
// BLOCKED or STREAM_BLOCKED frame is generated.
// If stream_id is 0 then a BLOCKED frame is generated and transmitted,
// if non-0, a STREAM_BLOCKED.
+ // TODO(fkastenholz): This should be converted to use
+ // QuicUtils::GetInvalidStreamId to get the correct invalid stream id value
+ // and not rely on 0.
QuicStreamId stream_id;
// For Google QUIC, the offset is ignored.
diff --git a/quic/core/frames/quic_crypto_frame.cc b/quic/core/frames/quic_crypto_frame.cc
index c7f500a..9d602bc 100644
--- a/quic/core/frames/quic_crypto_frame.cc
+++ b/quic/core/frames/quic_crypto_frame.cc
@@ -8,15 +8,27 @@
namespace quic {
-QuicCryptoFrame::QuicCryptoFrame() : QuicCryptoFrame(0, nullptr, 0) {}
+QuicCryptoFrame::QuicCryptoFrame()
+ : QuicCryptoFrame(ENCRYPTION_NONE, 0, nullptr, 0) {}
-QuicCryptoFrame::QuicCryptoFrame(QuicStreamOffset offset, QuicStringPiece data)
- : QuicCryptoFrame(offset, data.data(), data.length()) {}
+QuicCryptoFrame::QuicCryptoFrame(EncryptionLevel level,
+ QuicStreamOffset offset,
+ QuicPacketLength data_length)
+ : QuicCryptoFrame(level, offset, nullptr, data_length) {}
-QuicCryptoFrame::QuicCryptoFrame(QuicStreamOffset offset,
+QuicCryptoFrame::QuicCryptoFrame(EncryptionLevel level,
+ QuicStreamOffset offset,
+ QuicStringPiece data)
+ : QuicCryptoFrame(level, offset, data.data(), data.length()) {}
+
+QuicCryptoFrame::QuicCryptoFrame(EncryptionLevel level,
+ QuicStreamOffset offset,
const char* data_buffer,
QuicPacketLength data_length)
- : data_length(data_length), data_buffer(data_buffer), offset(offset) {}
+ : level(level),
+ data_length(data_length),
+ data_buffer(data_buffer),
+ offset(offset) {}
QuicCryptoFrame::~QuicCryptoFrame() {}
diff --git a/quic/core/frames/quic_crypto_frame.h b/quic/core/frames/quic_crypto_frame.h
index bbf8ea0..a3968fe 100644
--- a/quic/core/frames/quic_crypto_frame.h
+++ b/quic/core/frames/quic_crypto_frame.h
@@ -17,20 +17,29 @@
struct QUIC_EXPORT_PRIVATE QuicCryptoFrame {
QuicCryptoFrame();
- QuicCryptoFrame(QuicStreamOffset offset, QuicStringPiece data);
+ QuicCryptoFrame(EncryptionLevel level,
+ QuicStreamOffset offset,
+ QuicPacketLength data_length);
+ QuicCryptoFrame(EncryptionLevel level,
+ QuicStreamOffset offset,
+ QuicStringPiece data);
~QuicCryptoFrame();
friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
const QuicCryptoFrame& s);
+ // When writing a crypto frame to a packet, the packet must be encrypted at
+ // |level|. When a crypto frame is read, the encryption level of the packet it
+ // was received in is put in |level|.
+ EncryptionLevel level;
QuicPacketLength data_length;
// When reading, |data_buffer| points to the data that was received in the
- // frame. When writing, |data_buffer| must be a valid pointer for the lifetime
- // of the frame, which may get serialized some time after creation.
+ // frame. |data_buffer| is not used when writing.
const char* data_buffer;
QuicStreamOffset offset; // Location of this data in the stream.
- QuicCryptoFrame(QuicStreamOffset offset,
+ QuicCryptoFrame(EncryptionLevel level,
+ QuicStreamOffset offset,
const char* data_buffer,
QuicPacketLength data_length);
};
diff --git a/quic/core/frames/quic_frame.cc b/quic/core/frames/quic_frame.cc
index a951ce6..2e6a303 100644
--- a/quic/core/frames/quic_frame.cc
+++ b/quic/core/frames/quic_frame.cc
@@ -246,15 +246,15 @@
case PING_FRAME:
copy = QuicFrame(QuicPingFrame(frame.ping_frame.control_frame_id));
break;
+ case STOP_SENDING_FRAME:
+ copy = QuicFrame(new QuicStopSendingFrame(*frame.stop_sending_frame));
+ break;
case STREAM_ID_BLOCKED_FRAME:
copy = QuicFrame(QuicStreamIdBlockedFrame(frame.stream_id_blocked_frame));
break;
case MAX_STREAM_ID_FRAME:
copy = QuicFrame(QuicMaxStreamIdFrame(frame.max_stream_id_frame));
break;
- case STOP_SENDING_FRAME:
- copy = QuicFrame(new QuicStopSendingFrame(*frame.stop_sending_frame));
- break;
default:
QUIC_BUG << "Try to copy a non-retransmittable control frame: " << frame;
copy = QuicFrame(QuicPingFrame(kInvalidControlFrameId));
diff --git a/quic/core/frames/quic_frames_test.cc b/quic/core/frames/quic_frames_test.cc
index 725ce83..af9c40b 100644
--- a/quic/core/frames/quic_frames_test.cc
+++ b/quic/core/frames/quic_frames_test.cc
@@ -27,12 +27,13 @@
TEST_F(QuicFramesTest, AckFrameToString) {
QuicAckFrame frame;
- frame.largest_acked = 5;
+ frame.largest_acked = QuicPacketNumber(5);
frame.ack_delay_time = QuicTime::Delta::FromMicroseconds(3);
- frame.packets.Add(4);
- frame.packets.Add(5);
+ frame.packets.Add(QuicPacketNumber(4));
+ frame.packets.Add(QuicPacketNumber(5));
frame.received_packet_times = {
- {6, QuicTime::Zero() + QuicTime::Delta::FromMicroseconds(7)}};
+ {QuicPacketNumber(6),
+ QuicTime::Zero() + QuicTime::Delta::FromMicroseconds(7)}};
std::ostringstream stream;
stream << frame;
EXPECT_EQ(
@@ -45,11 +46,12 @@
TEST_F(QuicFramesTest, BigAckFrameToString) {
QuicAckFrame frame;
- frame.largest_acked = 500;
+ frame.largest_acked = QuicPacketNumber(500);
frame.ack_delay_time = QuicTime::Delta::FromMicroseconds(3);
- frame.packets.AddRange(4, 501);
+ frame.packets.AddRange(QuicPacketNumber(4), QuicPacketNumber(501));
frame.received_packet_times = {
- {500, QuicTime::Zero() + QuicTime::Delta::FromMicroseconds(7)}};
+ {QuicPacketNumber(500),
+ QuicTime::Zero() + QuicTime::Delta::FromMicroseconds(7)}};
std::ostringstream stream;
stream << frame;
EXPECT_EQ(
@@ -213,7 +215,7 @@
TEST_F(QuicFramesTest, StopWaitingFrameToString) {
QuicStopWaitingFrame frame;
- frame.least_unacked = 2;
+ frame.least_unacked = QuicPacketNumber(2);
std::ostringstream stream;
stream << frame;
EXPECT_EQ("{ least_unacked: 2 }\n", stream.str());
@@ -223,69 +225,84 @@
TEST_F(QuicFramesTest, IsAwaitingPacket) {
QuicAckFrame ack_frame1;
- ack_frame1.largest_acked = 10u;
- ack_frame1.packets.AddRange(1, 11);
- EXPECT_TRUE(IsAwaitingPacket(ack_frame1, 11u, 0u));
- EXPECT_FALSE(IsAwaitingPacket(ack_frame1, 1u, 0u));
+ ack_frame1.largest_acked = QuicPacketNumber(10u);
+ ack_frame1.packets.AddRange(QuicPacketNumber(1), QuicPacketNumber(11));
+ EXPECT_TRUE(
+ IsAwaitingPacket(ack_frame1, QuicPacketNumber(11u), QuicPacketNumber()));
+ EXPECT_FALSE(
+ IsAwaitingPacket(ack_frame1, QuicPacketNumber(1u), QuicPacketNumber()));
- ack_frame1.packets.Add(12);
- EXPECT_TRUE(IsAwaitingPacket(ack_frame1, 11u, 0u));
+ ack_frame1.packets.Add(QuicPacketNumber(12));
+ EXPECT_TRUE(
+ IsAwaitingPacket(ack_frame1, QuicPacketNumber(11u), QuicPacketNumber()));
QuicAckFrame ack_frame2;
- ack_frame2.largest_acked = 100u;
- ack_frame2.packets.AddRange(21, 100);
- EXPECT_FALSE(IsAwaitingPacket(ack_frame2, 11u, 20u));
- EXPECT_FALSE(IsAwaitingPacket(ack_frame2, 80u, 20u));
- EXPECT_TRUE(IsAwaitingPacket(ack_frame2, 101u, 20u));
+ ack_frame2.largest_acked = QuicPacketNumber(100u);
+ ack_frame2.packets.AddRange(QuicPacketNumber(21), QuicPacketNumber(100));
+ EXPECT_FALSE(IsAwaitingPacket(ack_frame2, QuicPacketNumber(11u),
+ QuicPacketNumber(20u)));
+ EXPECT_FALSE(IsAwaitingPacket(ack_frame2, QuicPacketNumber(80u),
+ QuicPacketNumber(20u)));
+ EXPECT_TRUE(IsAwaitingPacket(ack_frame2, QuicPacketNumber(101u),
+ QuicPacketNumber(20u)));
- ack_frame2.packets.AddRange(102, 200);
- EXPECT_TRUE(IsAwaitingPacket(ack_frame2, 101u, 20u));
+ ack_frame2.packets.AddRange(QuicPacketNumber(102), QuicPacketNumber(200));
+ EXPECT_TRUE(IsAwaitingPacket(ack_frame2, QuicPacketNumber(101u),
+ QuicPacketNumber(20u)));
}
TEST_F(QuicFramesTest, AddPacket) {
QuicAckFrame ack_frame1;
- ack_frame1.packets.Add(1);
- ack_frame1.packets.Add(99);
+ ack_frame1.packets.Add(QuicPacketNumber(1));
+ ack_frame1.packets.Add(QuicPacketNumber(99));
EXPECT_EQ(2u, ack_frame1.packets.NumIntervals());
- EXPECT_EQ(1u, ack_frame1.packets.Min());
- EXPECT_EQ(99u, ack_frame1.packets.Max());
+ EXPECT_EQ(QuicPacketNumber(1u), ack_frame1.packets.Min());
+ EXPECT_EQ(QuicPacketNumber(99u), ack_frame1.packets.Max());
std::vector<QuicInterval<QuicPacketNumber>> expected_intervals;
- expected_intervals.emplace_back(QuicInterval<QuicPacketNumber>(1, 2));
- expected_intervals.emplace_back(QuicInterval<QuicPacketNumber>(99, 100));
+ expected_intervals.emplace_back(
+ QuicInterval<QuicPacketNumber>(QuicPacketNumber(1), QuicPacketNumber(2)));
+ expected_intervals.emplace_back(QuicInterval<QuicPacketNumber>(
+ QuicPacketNumber(99), QuicPacketNumber(100)));
const std::vector<QuicInterval<QuicPacketNumber>> actual_intervals(
ack_frame1.packets.begin(), ack_frame1.packets.end());
EXPECT_EQ(expected_intervals, actual_intervals);
- ack_frame1.packets.Add(20);
+ ack_frame1.packets.Add(QuicPacketNumber(20));
const std::vector<QuicInterval<QuicPacketNumber>> actual_intervals2(
ack_frame1.packets.begin(), ack_frame1.packets.end());
std::vector<QuicInterval<QuicPacketNumber>> expected_intervals2;
- expected_intervals2.emplace_back(QuicInterval<QuicPacketNumber>(1, 2));
- expected_intervals2.emplace_back(QuicInterval<QuicPacketNumber>(20, 21));
- expected_intervals2.emplace_back(QuicInterval<QuicPacketNumber>(99, 100));
+ expected_intervals2.emplace_back(
+ QuicInterval<QuicPacketNumber>(QuicPacketNumber(1), QuicPacketNumber(2)));
+ expected_intervals2.emplace_back(QuicInterval<QuicPacketNumber>(
+ QuicPacketNumber(20), QuicPacketNumber(21)));
+ expected_intervals2.emplace_back(QuicInterval<QuicPacketNumber>(
+ QuicPacketNumber(99), QuicPacketNumber(100)));
EXPECT_EQ(3u, ack_frame1.packets.NumIntervals());
EXPECT_EQ(expected_intervals2, actual_intervals2);
- ack_frame1.packets.Add(19);
- ack_frame1.packets.Add(21);
+ ack_frame1.packets.Add(QuicPacketNumber(19));
+ ack_frame1.packets.Add(QuicPacketNumber(21));
const std::vector<QuicInterval<QuicPacketNumber>> actual_intervals3(
ack_frame1.packets.begin(), ack_frame1.packets.end());
std::vector<QuicInterval<QuicPacketNumber>> expected_intervals3;
- expected_intervals3.emplace_back(QuicInterval<QuicPacketNumber>(1, 2));
- expected_intervals3.emplace_back(QuicInterval<QuicPacketNumber>(19, 22));
- expected_intervals3.emplace_back(QuicInterval<QuicPacketNumber>(99, 100));
+ expected_intervals3.emplace_back(
+ QuicInterval<QuicPacketNumber>(QuicPacketNumber(1), QuicPacketNumber(2)));
+ expected_intervals3.emplace_back(QuicInterval<QuicPacketNumber>(
+ QuicPacketNumber(19), QuicPacketNumber(22)));
+ expected_intervals3.emplace_back(QuicInterval<QuicPacketNumber>(
+ QuicPacketNumber(99), QuicPacketNumber(100)));
EXPECT_EQ(expected_intervals3, actual_intervals3);
- ack_frame1.packets.Add(20);
+ ack_frame1.packets.Add(QuicPacketNumber(20));
const std::vector<QuicInterval<QuicPacketNumber>> actual_intervals4(
ack_frame1.packets.begin(), ack_frame1.packets.end());
@@ -293,37 +310,44 @@
EXPECT_EQ(expected_intervals3, actual_intervals4);
QuicAckFrame ack_frame2;
- ack_frame2.packets.Add(20);
- ack_frame2.packets.Add(40);
- ack_frame2.packets.Add(60);
- ack_frame2.packets.Add(10);
- ack_frame2.packets.Add(80);
+ ack_frame2.packets.Add(QuicPacketNumber(20));
+ ack_frame2.packets.Add(QuicPacketNumber(40));
+ ack_frame2.packets.Add(QuicPacketNumber(60));
+ ack_frame2.packets.Add(QuicPacketNumber(10));
+ ack_frame2.packets.Add(QuicPacketNumber(80));
const std::vector<QuicInterval<QuicPacketNumber>> actual_intervals5(
ack_frame2.packets.begin(), ack_frame2.packets.end());
std::vector<QuicInterval<QuicPacketNumber>> expected_intervals5;
- expected_intervals5.emplace_back(QuicInterval<QuicPacketNumber>(10, 11));
- expected_intervals5.emplace_back(QuicInterval<QuicPacketNumber>(20, 21));
- expected_intervals5.emplace_back(QuicInterval<QuicPacketNumber>(40, 41));
- expected_intervals5.emplace_back(QuicInterval<QuicPacketNumber>(60, 61));
- expected_intervals5.emplace_back(QuicInterval<QuicPacketNumber>(80, 81));
+ expected_intervals5.emplace_back(QuicInterval<QuicPacketNumber>(
+ QuicPacketNumber(10), QuicPacketNumber(11)));
+ expected_intervals5.emplace_back(QuicInterval<QuicPacketNumber>(
+ QuicPacketNumber(20), QuicPacketNumber(21)));
+ expected_intervals5.emplace_back(QuicInterval<QuicPacketNumber>(
+ QuicPacketNumber(40), QuicPacketNumber(41)));
+ expected_intervals5.emplace_back(QuicInterval<QuicPacketNumber>(
+ QuicPacketNumber(60), QuicPacketNumber(61)));
+ expected_intervals5.emplace_back(QuicInterval<QuicPacketNumber>(
+ QuicPacketNumber(80), QuicPacketNumber(81)));
EXPECT_EQ(expected_intervals5, actual_intervals5);
}
TEST_F(QuicFramesTest, AddInterval) {
QuicAckFrame ack_frame1;
- ack_frame1.packets.AddRange(1, 10);
- ack_frame1.packets.AddRange(50, 100);
+ ack_frame1.packets.AddRange(QuicPacketNumber(1), QuicPacketNumber(10));
+ ack_frame1.packets.AddRange(QuicPacketNumber(50), QuicPacketNumber(100));
EXPECT_EQ(2u, ack_frame1.packets.NumIntervals());
- EXPECT_EQ(1u, ack_frame1.packets.Min());
- EXPECT_EQ(99u, ack_frame1.packets.Max());
+ EXPECT_EQ(QuicPacketNumber(1u), ack_frame1.packets.Min());
+ EXPECT_EQ(QuicPacketNumber(99u), ack_frame1.packets.Max());
std::vector<QuicInterval<QuicPacketNumber>> expected_intervals;
- expected_intervals.emplace_back(QuicInterval<QuicPacketNumber>(1, 10));
- expected_intervals.emplace_back(QuicInterval<QuicPacketNumber>(50, 100));
+ expected_intervals.emplace_back(QuicInterval<QuicPacketNumber>(
+ QuicPacketNumber(1), QuicPacketNumber(10)));
+ expected_intervals.emplace_back(QuicInterval<QuicPacketNumber>(
+ QuicPacketNumber(50), QuicPacketNumber(100)));
const std::vector<QuicInterval<QuicPacketNumber>> actual_intervals(
ack_frame1.packets.begin(), ack_frame1.packets.end());
@@ -331,48 +355,58 @@
EXPECT_EQ(expected_intervals, actual_intervals);
// Ensure adding a range within the existing ranges fails.
- EXPECT_QUIC_BUG(ack_frame1.packets.AddRange(20, 30), "");
+ EXPECT_QUIC_BUG(
+ ack_frame1.packets.AddRange(QuicPacketNumber(20), QuicPacketNumber(30)),
+ "");
const std::vector<QuicInterval<QuicPacketNumber>> actual_intervals2(
ack_frame1.packets.begin(), ack_frame1.packets.end());
std::vector<QuicInterval<QuicPacketNumber>> expected_intervals2;
- expected_intervals2.emplace_back(QuicInterval<QuicPacketNumber>(1, 10));
- expected_intervals2.emplace_back(QuicInterval<QuicPacketNumber>(50, 100));
+ expected_intervals2.emplace_back(QuicInterval<QuicPacketNumber>(
+ QuicPacketNumber(1), QuicPacketNumber(10)));
+ expected_intervals2.emplace_back(QuicInterval<QuicPacketNumber>(
+ QuicPacketNumber(50), QuicPacketNumber(100)));
EXPECT_EQ(expected_intervals2.size(), ack_frame1.packets.NumIntervals());
EXPECT_EQ(expected_intervals2, actual_intervals2);
// Add ranges at both ends.
QuicAckFrame ack_frame2;
- ack_frame2.packets.AddRange(20, 25);
- ack_frame2.packets.AddRange(40, 45);
- ack_frame2.packets.AddRange(60, 65);
- ack_frame2.packets.AddRange(10, 15);
- ack_frame2.packets.AddRange(80, 85);
+ ack_frame2.packets.AddRange(QuicPacketNumber(20), QuicPacketNumber(25));
+ ack_frame2.packets.AddRange(QuicPacketNumber(40), QuicPacketNumber(45));
+ ack_frame2.packets.AddRange(QuicPacketNumber(60), QuicPacketNumber(65));
+ ack_frame2.packets.AddRange(QuicPacketNumber(10), QuicPacketNumber(15));
+ ack_frame2.packets.AddRange(QuicPacketNumber(80), QuicPacketNumber(85));
const std::vector<QuicInterval<QuicPacketNumber>> actual_intervals8(
ack_frame2.packets.begin(), ack_frame2.packets.end());
std::vector<QuicInterval<QuicPacketNumber>> expected_intervals8;
- expected_intervals8.emplace_back(QuicInterval<QuicPacketNumber>(10, 15));
- expected_intervals8.emplace_back(QuicInterval<QuicPacketNumber>(20, 25));
- expected_intervals8.emplace_back(QuicInterval<QuicPacketNumber>(40, 45));
- expected_intervals8.emplace_back(QuicInterval<QuicPacketNumber>(60, 65));
- expected_intervals8.emplace_back(QuicInterval<QuicPacketNumber>(80, 85));
+ expected_intervals8.emplace_back(QuicInterval<QuicPacketNumber>(
+ QuicPacketNumber(10), QuicPacketNumber(15)));
+ expected_intervals8.emplace_back(QuicInterval<QuicPacketNumber>(
+ QuicPacketNumber(20), QuicPacketNumber(25)));
+ expected_intervals8.emplace_back(QuicInterval<QuicPacketNumber>(
+ QuicPacketNumber(40), QuicPacketNumber(45)));
+ expected_intervals8.emplace_back(QuicInterval<QuicPacketNumber>(
+ QuicPacketNumber(60), QuicPacketNumber(65)));
+ expected_intervals8.emplace_back(QuicInterval<QuicPacketNumber>(
+ QuicPacketNumber(80), QuicPacketNumber(85)));
EXPECT_EQ(expected_intervals8, actual_intervals8);
}
TEST_F(QuicFramesTest, AddAdjacentForward) {
QuicAckFrame ack_frame1;
- ack_frame1.packets.Add(49);
- ack_frame1.packets.AddRange(50, 60);
- ack_frame1.packets.AddRange(60, 70);
- ack_frame1.packets.AddRange(70, 100);
+ ack_frame1.packets.Add(QuicPacketNumber(49));
+ ack_frame1.packets.AddRange(QuicPacketNumber(50), QuicPacketNumber(60));
+ ack_frame1.packets.AddRange(QuicPacketNumber(60), QuicPacketNumber(70));
+ ack_frame1.packets.AddRange(QuicPacketNumber(70), QuicPacketNumber(100));
std::vector<QuicInterval<QuicPacketNumber>> expected_intervals;
- expected_intervals.emplace_back(QuicInterval<QuicPacketNumber>(49, 100));
+ expected_intervals.emplace_back(QuicInterval<QuicPacketNumber>(
+ QuicPacketNumber(49), QuicPacketNumber(100)));
const std::vector<QuicInterval<QuicPacketNumber>> actual_intervals(
ack_frame1.packets.begin(), ack_frame1.packets.end());
@@ -382,13 +416,14 @@
TEST_F(QuicFramesTest, AddAdjacentReverse) {
QuicAckFrame ack_frame1;
- ack_frame1.packets.AddRange(70, 100);
- ack_frame1.packets.AddRange(60, 70);
- ack_frame1.packets.AddRange(50, 60);
- ack_frame1.packets.Add(49);
+ ack_frame1.packets.AddRange(QuicPacketNumber(70), QuicPacketNumber(100));
+ ack_frame1.packets.AddRange(QuicPacketNumber(60), QuicPacketNumber(70));
+ ack_frame1.packets.AddRange(QuicPacketNumber(50), QuicPacketNumber(60));
+ ack_frame1.packets.Add(QuicPacketNumber(49));
std::vector<QuicInterval<QuicPacketNumber>> expected_intervals;
- expected_intervals.emplace_back(QuicInterval<QuicPacketNumber>(49, 100));
+ expected_intervals.emplace_back(QuicInterval<QuicPacketNumber>(
+ QuicPacketNumber(49), QuicPacketNumber(100)));
const std::vector<QuicInterval<QuicPacketNumber>> actual_intervals(
ack_frame1.packets.begin(), ack_frame1.packets.end());
@@ -398,19 +433,19 @@
TEST_F(QuicFramesTest, RemoveSmallestInterval) {
QuicAckFrame ack_frame1;
- ack_frame1.largest_acked = 100u;
- ack_frame1.packets.AddRange(51, 60);
- ack_frame1.packets.AddRange(71, 80);
- ack_frame1.packets.AddRange(91, 100);
+ ack_frame1.largest_acked = QuicPacketNumber(100u);
+ ack_frame1.packets.AddRange(QuicPacketNumber(51), QuicPacketNumber(60));
+ ack_frame1.packets.AddRange(QuicPacketNumber(71), QuicPacketNumber(80));
+ ack_frame1.packets.AddRange(QuicPacketNumber(91), QuicPacketNumber(100));
ack_frame1.packets.RemoveSmallestInterval();
EXPECT_EQ(2u, ack_frame1.packets.NumIntervals());
- EXPECT_EQ(71u, ack_frame1.packets.Min());
- EXPECT_EQ(99u, ack_frame1.packets.Max());
+ EXPECT_EQ(QuicPacketNumber(71u), ack_frame1.packets.Min());
+ EXPECT_EQ(QuicPacketNumber(99u), ack_frame1.packets.Max());
ack_frame1.packets.RemoveSmallestInterval();
EXPECT_EQ(1u, ack_frame1.packets.NumIntervals());
- EXPECT_EQ(91u, ack_frame1.packets.Min());
- EXPECT_EQ(99u, ack_frame1.packets.Max());
+ EXPECT_EQ(QuicPacketNumber(91u), ack_frame1.packets.Min());
+ EXPECT_EQ(QuicPacketNumber(99u), ack_frame1.packets.Max());
}
class PacketNumberQueueTest : public QuicTest {};
@@ -418,85 +453,85 @@
// Tests that a queue contains the expected data after calls to Add().
TEST_F(PacketNumberQueueTest, AddRange) {
PacketNumberQueue queue;
- queue.AddRange(1, 51);
- queue.Add(53);
+ queue.AddRange(QuicPacketNumber(1), QuicPacketNumber(51));
+ queue.Add(QuicPacketNumber(53));
- EXPECT_FALSE(queue.Contains(0));
+ EXPECT_FALSE(queue.Contains(QuicPacketNumber()));
for (int i = 1; i < 51; ++i) {
- EXPECT_TRUE(queue.Contains(i));
+ EXPECT_TRUE(queue.Contains(QuicPacketNumber(i)));
}
- EXPECT_FALSE(queue.Contains(51));
- EXPECT_FALSE(queue.Contains(52));
- EXPECT_TRUE(queue.Contains(53));
- EXPECT_FALSE(queue.Contains(54));
+ EXPECT_FALSE(queue.Contains(QuicPacketNumber(51)));
+ EXPECT_FALSE(queue.Contains(QuicPacketNumber(52)));
+ EXPECT_TRUE(queue.Contains(QuicPacketNumber(53)));
+ EXPECT_FALSE(queue.Contains(QuicPacketNumber(54)));
EXPECT_EQ(51u, queue.NumPacketsSlow());
- EXPECT_EQ(1u, queue.Min());
- EXPECT_EQ(53u, queue.Max());
+ EXPECT_EQ(QuicPacketNumber(1u), queue.Min());
+ EXPECT_EQ(QuicPacketNumber(53u), queue.Max());
- queue.Add(70);
- EXPECT_EQ(70u, queue.Max());
+ queue.Add(QuicPacketNumber(70));
+ EXPECT_EQ(QuicPacketNumber(70u), queue.Max());
}
// Tests Contains function
TEST_F(PacketNumberQueueTest, Contains) {
PacketNumberQueue queue;
- EXPECT_FALSE(queue.Contains(0));
- queue.AddRange(5, 10);
- queue.Add(20);
+ EXPECT_FALSE(queue.Contains(QuicPacketNumber()));
+ queue.AddRange(QuicPacketNumber(5), QuicPacketNumber(10));
+ queue.Add(QuicPacketNumber(20));
for (int i = 1; i < 5; ++i) {
- EXPECT_FALSE(queue.Contains(i));
+ EXPECT_FALSE(queue.Contains(QuicPacketNumber(i)));
}
for (int i = 5; i < 10; ++i) {
- EXPECT_TRUE(queue.Contains(i));
+ EXPECT_TRUE(queue.Contains(QuicPacketNumber(i)));
}
for (int i = 10; i < 20; ++i) {
- EXPECT_FALSE(queue.Contains(i));
+ EXPECT_FALSE(queue.Contains(QuicPacketNumber(i)));
}
- EXPECT_TRUE(queue.Contains(20));
- EXPECT_FALSE(queue.Contains(21));
+ EXPECT_TRUE(queue.Contains(QuicPacketNumber(20)));
+ EXPECT_FALSE(queue.Contains(QuicPacketNumber(21)));
PacketNumberQueue queue2;
- EXPECT_FALSE(queue2.Contains(1));
+ EXPECT_FALSE(queue2.Contains(QuicPacketNumber(1)));
for (int i = 1; i < 51; ++i) {
- queue2.Add(2 * i);
+ queue2.Add(QuicPacketNumber(2 * i));
}
- EXPECT_FALSE(queue2.Contains(0));
+ EXPECT_FALSE(queue2.Contains(QuicPacketNumber()));
for (int i = 1; i < 51; ++i) {
if (i % 2 == 0) {
- EXPECT_TRUE(queue2.Contains(i));
+ EXPECT_TRUE(queue2.Contains(QuicPacketNumber(i)));
} else {
- EXPECT_FALSE(queue2.Contains(i));
+ EXPECT_FALSE(queue2.Contains(QuicPacketNumber(i)));
}
}
- EXPECT_FALSE(queue2.Contains(101));
+ EXPECT_FALSE(queue2.Contains(QuicPacketNumber(101)));
}
// Tests that a queue contains the expected data after calls to RemoveUpTo().
TEST_F(PacketNumberQueueTest, Removal) {
PacketNumberQueue queue;
- EXPECT_FALSE(queue.Contains(51));
- queue.AddRange(0, 100);
+ EXPECT_FALSE(queue.Contains(QuicPacketNumber(51)));
+ queue.AddRange(QuicPacketNumber(1), QuicPacketNumber(100));
- EXPECT_TRUE(queue.RemoveUpTo(51));
- EXPECT_FALSE(queue.RemoveUpTo(51));
+ EXPECT_TRUE(queue.RemoveUpTo(QuicPacketNumber(51)));
+ EXPECT_FALSE(queue.RemoveUpTo(QuicPacketNumber(51)));
- EXPECT_FALSE(queue.Contains(0));
+ EXPECT_FALSE(queue.Contains(QuicPacketNumber()));
for (int i = 1; i < 51; ++i) {
- EXPECT_FALSE(queue.Contains(i));
+ EXPECT_FALSE(queue.Contains(QuicPacketNumber(i)));
}
for (int i = 51; i < 100; ++i) {
- EXPECT_TRUE(queue.Contains(i));
+ EXPECT_TRUE(queue.Contains(QuicPacketNumber(i)));
}
EXPECT_EQ(49u, queue.NumPacketsSlow());
- EXPECT_EQ(51u, queue.Min());
- EXPECT_EQ(99u, queue.Max());
+ EXPECT_EQ(QuicPacketNumber(51u), queue.Min());
+ EXPECT_EQ(QuicPacketNumber(99u), queue.Max());
PacketNumberQueue queue2;
- queue2.AddRange(0, 5);
- EXPECT_TRUE(queue2.RemoveUpTo(3));
- EXPECT_TRUE(queue2.RemoveUpTo(50));
+ queue2.AddRange(QuicPacketNumber(1), QuicPacketNumber(5));
+ EXPECT_TRUE(queue2.RemoveUpTo(QuicPacketNumber(3)));
+ EXPECT_TRUE(queue2.RemoveUpTo(QuicPacketNumber(50)));
EXPECT_TRUE(queue2.Empty());
}
@@ -506,8 +541,8 @@
EXPECT_TRUE(queue.Empty());
EXPECT_EQ(0u, queue.NumPacketsSlow());
- queue.AddRange(1, 100);
- EXPECT_TRUE(queue.RemoveUpTo(100));
+ queue.AddRange(QuicPacketNumber(1), QuicPacketNumber(100));
+ EXPECT_TRUE(queue.RemoveUpTo(QuicPacketNumber(100)));
EXPECT_TRUE(queue.Empty());
EXPECT_EQ(0u, queue.NumPacketsSlow());
}
@@ -518,29 +553,30 @@
PacketNumberQueue queue;
oss << queue;
- queue.Add(1);
- queue.AddRange(50, 100);
+ queue.Add(QuicPacketNumber(1));
+ queue.AddRange(QuicPacketNumber(50), QuicPacketNumber(100));
oss << queue;
}
// Tests that the iterators returned from a packet queue iterate over the queue.
TEST_F(PacketNumberQueueTest, Iterators) {
PacketNumberQueue queue;
- queue.AddRange(1, 100);
+ queue.AddRange(QuicPacketNumber(1), QuicPacketNumber(100));
const std::vector<QuicInterval<QuicPacketNumber>> actual_intervals(
queue.begin(), queue.end());
PacketNumberQueue queue2;
for (int i = 1; i < 100; i++) {
- queue2.AddRange(i, i + 1);
+ queue2.AddRange(QuicPacketNumber(i), QuicPacketNumber(i + 1));
}
const std::vector<QuicInterval<QuicPacketNumber>> actual_intervals2(
queue2.begin(), queue2.end());
std::vector<QuicInterval<QuicPacketNumber>> expected_intervals;
- expected_intervals.emplace_back(QuicInterval<QuicPacketNumber>(1, 100));
+ expected_intervals.emplace_back(QuicInterval<QuicPacketNumber>(
+ QuicPacketNumber(1), QuicPacketNumber(100)));
EXPECT_EQ(expected_intervals, actual_intervals);
EXPECT_EQ(expected_intervals, actual_intervals2);
EXPECT_EQ(actual_intervals, actual_intervals2);
@@ -548,10 +584,10 @@
TEST_F(PacketNumberQueueTest, ReversedIterators) {
PacketNumberQueue queue;
- queue.AddRange(1, 100);
+ queue.AddRange(QuicPacketNumber(1), QuicPacketNumber(100));
PacketNumberQueue queue2;
for (int i = 1; i < 100; i++) {
- queue2.AddRange(i, i + 1);
+ queue2.AddRange(QuicPacketNumber(i), QuicPacketNumber(i + 1));
}
const std::vector<QuicInterval<QuicPacketNumber>> actual_intervals(
queue.rbegin(), queue.rend());
@@ -559,7 +595,8 @@
queue2.rbegin(), queue2.rend());
std::vector<QuicInterval<QuicPacketNumber>> expected_intervals;
- expected_intervals.emplace_back(QuicInterval<QuicPacketNumber>(1, 100));
+ expected_intervals.emplace_back(QuicInterval<QuicPacketNumber>(
+ QuicPacketNumber(1), QuicPacketNumber(100)));
EXPECT_EQ(expected_intervals, actual_intervals);
EXPECT_EQ(expected_intervals, actual_intervals2);
@@ -567,7 +604,7 @@
PacketNumberQueue queue3;
for (int i = 1; i < 20; i++) {
- queue3.Add(2 * i);
+ queue3.Add(QuicPacketNumber(2 * i));
}
auto begin = queue3.begin();
@@ -583,17 +620,17 @@
TEST_F(PacketNumberQueueTest, IntervalLengthAndRemoveInterval) {
PacketNumberQueue queue;
- queue.AddRange(1, 10);
- queue.AddRange(20, 30);
- queue.AddRange(40, 50);
+ queue.AddRange(QuicPacketNumber(1), QuicPacketNumber(10));
+ queue.AddRange(QuicPacketNumber(20), QuicPacketNumber(30));
+ queue.AddRange(QuicPacketNumber(40), QuicPacketNumber(50));
EXPECT_EQ(3u, queue.NumIntervals());
EXPECT_EQ(10u, queue.LastIntervalLength());
- EXPECT_TRUE(queue.RemoveUpTo(25));
+ EXPECT_TRUE(queue.RemoveUpTo(QuicPacketNumber(25)));
EXPECT_EQ(2u, queue.NumIntervals());
EXPECT_EQ(10u, queue.LastIntervalLength());
- EXPECT_EQ(25u, queue.Min());
- EXPECT_EQ(49u, queue.Max());
+ EXPECT_EQ(QuicPacketNumber(25u), queue.Min());
+ EXPECT_EQ(QuicPacketNumber(49u), queue.Max());
}
} // namespace
diff --git a/quic/core/frames/quic_stop_waiting_frame.cc b/quic/core/frames/quic_stop_waiting_frame.cc
index 696bed4..0674e8f 100644
--- a/quic/core/frames/quic_stop_waiting_frame.cc
+++ b/quic/core/frames/quic_stop_waiting_frame.cc
@@ -8,7 +8,7 @@
namespace quic {
-QuicStopWaitingFrame::QuicStopWaitingFrame() : least_unacked(0) {}
+QuicStopWaitingFrame::QuicStopWaitingFrame() {}
QuicStopWaitingFrame::~QuicStopWaitingFrame() {}
diff --git a/quic/core/http/end_to_end_test.cc b/quic/core/http/end_to_end_test.cc
index 55c72ff..132da8e 100644
--- a/quic/core/http/end_to_end_test.cc
+++ b/quic/core/http/end_to_end_test.cc
@@ -22,6 +22,7 @@
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/core/quic_session.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_epoll.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
@@ -62,8 +63,6 @@
#include "net/third_party/quiche/src/quic/tools/quic_simple_client_stream.h"
#include "net/third_party/quiche/src/quic/tools/quic_simple_server_stream.h"
-using gfe2::EpollEvent;
-using gfe2::EpollServer;
using spdy::kV3LowestPriority;
using spdy::SETTINGS_MAX_HEADER_LIST_SIZE;
using spdy::SpdyFramer;
@@ -260,7 +259,7 @@
explicit ClientDelegate(QuicClient* client) : client_(client) {}
~ClientDelegate() override = default;
void OnCanWrite() override {
- EpollEvent event(EPOLLOUT);
+ QuicEpollEvent event(EPOLLOUT);
client_->epoll_network_helper()->OnEvent(client_->GetLatestFD(), &event);
}
@@ -278,10 +277,11 @@
server_hostname_("test.example.com"),
client_writer_(nullptr),
server_writer_(nullptr),
- negotiated_version_(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED),
+ negotiated_version_(UnsupportedQuicVersion()),
chlo_multiplier_(0),
stream_factory_(nullptr),
- support_server_push_(false) {
+ support_server_push_(false),
+ override_connection_id_(nullptr) {
FLAGS_quic_supports_tls_handshake = true;
SetQuicRestartFlag(quic_no_server_conn_ver_negotiation2, true);
SetQuicReloadableFlag(quic_no_client_conn_ver_negotiation, true);
@@ -330,6 +330,9 @@
if (!pre_shared_key_client_.empty()) {
client->client()->SetPreSharedKey(pre_shared_key_client_);
}
+ if (override_connection_id_ != nullptr) {
+ client->UseConnectionId(*override_connection_id_);
+ }
client->Connect();
return client;
}
@@ -419,14 +422,14 @@
}
CreateClientWithWriter();
- static EpollEvent event(EPOLLOUT);
+ static QuicEpollEvent event(EPOLLOUT);
if (client_writer_ != nullptr) {
client_writer_->Initialize(
QuicConnectionPeer::GetHelper(
client_->client()->client_session()->connection()),
QuicConnectionPeer::GetAlarmFactory(
client_->client()->client_session()->connection()),
- absl::make_unique<ClientDelegate>(client_->client()));
+ QuicMakeUnique<ClientDelegate>(client_->client()));
}
initialized_ = true;
return client_->client()->connected();
@@ -470,7 +473,7 @@
server_writer_->Initialize(QuicDispatcherPeer::GetHelper(dispatcher),
QuicDispatcherPeer::GetAlarmFactory(dispatcher),
- absl::make_unique<ServerDelegate>(dispatcher));
+ QuicMakeUnique<ServerDelegate>(dispatcher));
if (stream_factory_ != nullptr) {
down_cast<QuicTestServer*>(server_thread_->server())
->SetSpdyStreamFactory(stream_factory_);
@@ -632,6 +635,7 @@
bool support_server_push_;
QuicString pre_shared_key_client_;
QuicString pre_shared_key_server_;
+ QuicConnectionId* override_connection_id_;
};
// Run all end to end tests with all supported versions.
@@ -724,6 +728,28 @@
client_->client()->GetNumSentClientHellos());
}
+TEST_P(EndToEndTest, SimpleRequestResponseZeroConnectionID) {
+ QuicConnectionId connection_id = QuicUtils::CreateZeroConnectionId(
+ GetParam().negotiated_version.transport_version);
+ override_connection_id_ = &connection_id;
+ ASSERT_TRUE(Initialize());
+
+ EXPECT_EQ(kFooResponseBody, client_->SendSynchronousRequest("/foo"));
+ EXPECT_EQ("200", client_->response_headers()->find(":status")->second);
+ int expected_num_client_hellos = 2;
+ if (ServerSendsVersionNegotiation()) {
+ ++expected_num_client_hellos;
+ if (BothSidesSupportStatelessRejects()) {
+ ++expected_num_client_hellos;
+ }
+ }
+ EXPECT_EQ(expected_num_client_hellos,
+ client_->client()->GetNumSentClientHellos());
+ EXPECT_EQ(client_->client()->client_session()->connection()->connection_id(),
+ QuicUtils::CreateZeroConnectionId(
+ GetParam().negotiated_version.transport_version));
+}
+
// TODO(dschinazi) remove this test once the flags are deprecated
TEST_P(EndToEndTest, SimpleRequestResponseVariableLengthConnectionIDServer) {
SetQuicRestartFlag(quic_variable_length_connection_ids_client, false);
@@ -1870,7 +1896,7 @@
// Register the new FD for epoll events.
int new_fd = client_->client()->GetLatestFD();
- EpollServer* eps = client_->epoll_server();
+ QuicEpollServer* eps = client_->epoll_server();
eps->RegisterFD(new_fd, client_->client()->epoll_network_helper(),
EPOLLIN | EPOLLOUT | EPOLLET);
@@ -3132,13 +3158,13 @@
client->UseWriter(client_writer_);
client->Connect();
client_.reset(client);
- static EpollEvent event(EPOLLOUT);
+ static QuicEpollEvent event(EPOLLOUT);
client_writer_->Initialize(
QuicConnectionPeer::GetHelper(
client_->client()->client_session()->connection()),
QuicConnectionPeer::GetAlarmFactory(
client_->client()->client_session()->connection()),
- absl::make_unique<ClientDelegate>(client_->client()));
+ QuicMakeUnique<ClientDelegate>(client_->client()));
initialized_ = true;
ASSERT_TRUE(client_->client()->connected());
@@ -3695,6 +3721,32 @@
EXPECT_EQ(kStopSendingTestCode, client_stream->last_stop_sending_code());
}
+TEST_P(EndToEndTest, SimpleStopSendingRstStreamTest) {
+ ASSERT_TRUE(Initialize());
+
+ // Send a request without a fin, to keep the stream open
+ SpdyHeaderBlock headers;
+ headers[":method"] = "POST";
+ headers[":path"] = "/foo";
+ headers[":scheme"] = "https";
+ headers[":authority"] = server_hostname_;
+ client_->SendMessage(headers, "", /*fin=*/false);
+ // Stream should be open
+ ASSERT_NE(nullptr, client_->latest_created_stream());
+ EXPECT_FALSE(
+ QuicStreamPeer::write_side_closed(client_->latest_created_stream()));
+ EXPECT_FALSE(
+ QuicStreamPeer::read_side_closed(client_->latest_created_stream()));
+
+ // Send a RST_STREAM+STOP_SENDING on the stream
+ // Code is not important.
+ client_->latest_created_stream()->Reset(QUIC_BAD_APPLICATION_PAYLOAD);
+ client_->WaitForResponse();
+
+ // Stream should be gone.
+ ASSERT_EQ(nullptr, client_->latest_created_stream());
+}
+
} // namespace
} // namespace test
} // namespace quic
diff --git a/quic/core/http/http_decoder.cc b/quic/core/http/http_decoder.cc
index f1d6de0..345f2cb 100644
--- a/quic/core/http/http_decoder.cc
+++ b/quic/core/http/http_decoder.cc
@@ -262,6 +262,24 @@
}
return;
}
+
+ case 0xE: { // DUPLICATE_PUSH
+ BufferFramePayload(reader);
+ if (remaining_frame_length_ != 0) {
+ return;
+ }
+ QuicDataReader reader(buffer_.data(), current_frame_length_,
+ NETWORK_BYTE_ORDER);
+ DuplicatePushFrame frame;
+ if (!reader.ReadVarInt62(&frame.push_id)) {
+ RaiseError(QUIC_INTERNAL_ERROR, "Unable to read push_id");
+ return;
+ }
+ visitor_->OnDuplicatePushFrame(frame);
+ state_ = STATE_READING_FRAME_LENGTH;
+ current_length_field_size_ = 0;
+ return;
+ }
// Reserved frame types.
// TODO(rch): Since these are actually the same behavior as the
// default, we probably don't need to special case them here?
diff --git a/quic/core/http/http_decoder.h b/quic/core/http/http_decoder.h
index 730bbe3..a5f41b5 100644
--- a/quic/core/http/http_decoder.h
+++ b/quic/core/http/http_decoder.h
@@ -58,7 +58,10 @@
// Called when a SETTINGS frame has been successfully parsed.
virtual void OnSettingsFrame(const SettingsFrame& frame) = 0;
- // Called when a DATA frame has been recevied, |frame_lengths| will be
+ // Called when a DUPLICATE_PUSH frame has been successfully parsed.
+ virtual void OnDuplicatePushFrame(const DuplicatePushFrame& frame) = 0;
+
+ // Called when a DATA frame has been received, |frame_lengths| will be
// passed to inform header length and payload length of the frame.
virtual void OnDataFrameStart(Http3FrameLengths frame_length) = 0;
// Called when the payload of a DATA frame has read. May be called
diff --git a/quic/core/http/http_decoder_test.cc b/quic/core/http/http_decoder_test.cc
index 5261d65..c2b303c 100644
--- a/quic/core/http/http_decoder_test.cc
+++ b/quic/core/http/http_decoder_test.cc
@@ -23,6 +23,7 @@
MOCK_METHOD1(OnMaxPushIdFrame, void(const MaxPushIdFrame& frame));
MOCK_METHOD1(OnGoAwayFrame, void(const GoAwayFrame& frame));
MOCK_METHOD1(OnSettingsFrame, void(const SettingsFrame& frame));
+ MOCK_METHOD1(OnDuplicatePushFrame, void(const DuplicatePushFrame& frame));
MOCK_METHOD1(OnDataFrameStart, void(Http3FrameLengths frame_lengths));
MOCK_METHOD1(OnDataFramePayload, void(QuicStringPiece payload));
@@ -134,7 +135,7 @@
// Process the full frame.
InSequence s;
EXPECT_CALL(visitor_, OnPushPromiseFrameStart(1));
- EXPECT_CALL(visitor_, OnPushPromiseFramePayload("Headers"));
+ EXPECT_CALL(visitor_, OnPushPromiseFramePayload(QuicStringPiece("Headers")));
EXPECT_CALL(visitor_, OnPushPromiseFrameEnd());
EXPECT_EQ(QUIC_ARRAYSIZE(input),
decoder_.ProcessInput(input, QUIC_ARRAYSIZE(input)));
@@ -143,13 +144,13 @@
// Process the frame incremently.
EXPECT_CALL(visitor_, OnPushPromiseFrameStart(1));
- EXPECT_CALL(visitor_, OnPushPromiseFramePayload("H"));
- EXPECT_CALL(visitor_, OnPushPromiseFramePayload("e"));
- EXPECT_CALL(visitor_, OnPushPromiseFramePayload("a"));
- EXPECT_CALL(visitor_, OnPushPromiseFramePayload("d"));
- EXPECT_CALL(visitor_, OnPushPromiseFramePayload("e"));
- EXPECT_CALL(visitor_, OnPushPromiseFramePayload("r"));
- EXPECT_CALL(visitor_, OnPushPromiseFramePayload("s"));
+ EXPECT_CALL(visitor_, OnPushPromiseFramePayload(QuicStringPiece("H")));
+ EXPECT_CALL(visitor_, OnPushPromiseFramePayload(QuicStringPiece("e")));
+ EXPECT_CALL(visitor_, OnPushPromiseFramePayload(QuicStringPiece("a")));
+ EXPECT_CALL(visitor_, OnPushPromiseFramePayload(QuicStringPiece("d")));
+ EXPECT_CALL(visitor_, OnPushPromiseFramePayload(QuicStringPiece("e")));
+ EXPECT_CALL(visitor_, OnPushPromiseFramePayload(QuicStringPiece("r")));
+ EXPECT_CALL(visitor_, OnPushPromiseFramePayload(QuicStringPiece("s")));
EXPECT_CALL(visitor_, OnPushPromiseFrameEnd());
for (char c : input) {
EXPECT_EQ(1u, decoder_.ProcessInput(&c, 1));
@@ -182,6 +183,29 @@
EXPECT_EQ("", decoder_.error_detail());
}
+TEST_F(HttpDecoderTest, DuplicatePush) {
+ char input[] = {// length
+ 0x1,
+ // type (DUPLICATE_PUSH)
+ 0x0E,
+ // Push Id
+ 0x01};
+ // Process the full frame.
+ EXPECT_CALL(visitor_, OnDuplicatePushFrame(DuplicatePushFrame({1})));
+ EXPECT_EQ(QUIC_ARRAYSIZE(input),
+ decoder_.ProcessInput(input, QUIC_ARRAYSIZE(input)));
+ EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ EXPECT_EQ("", decoder_.error_detail());
+
+ // Process the frame incremently.
+ EXPECT_CALL(visitor_, OnDuplicatePushFrame(DuplicatePushFrame({1})));
+ for (char c : input) {
+ EXPECT_EQ(1u, decoder_.ProcessInput(&c, 1));
+ }
+ EXPECT_EQ(QUIC_NO_ERROR, decoder_.error());
+ EXPECT_EQ("", decoder_.error_detail());
+}
+
TEST_F(HttpDecoderTest, PriorityFrame) {
char input[] = {// length
0x4,
@@ -273,7 +297,7 @@
// Process the full frame.
InSequence s;
EXPECT_CALL(visitor_, OnDataFrameStart(Http3FrameLengths(2, 5)));
- EXPECT_CALL(visitor_, OnDataFramePayload("Data!"));
+ EXPECT_CALL(visitor_, OnDataFramePayload(QuicStringPiece("Data!")));
EXPECT_CALL(visitor_, OnDataFrameEnd());
EXPECT_EQ(QUIC_ARRAYSIZE(input),
decoder_.ProcessInput(input, QUIC_ARRAYSIZE(input)));
@@ -282,11 +306,11 @@
// Process the frame incremently.
EXPECT_CALL(visitor_, OnDataFrameStart(Http3FrameLengths(2, 5)));
- EXPECT_CALL(visitor_, OnDataFramePayload("D"));
- EXPECT_CALL(visitor_, OnDataFramePayload("a"));
- EXPECT_CALL(visitor_, OnDataFramePayload("t"));
- EXPECT_CALL(visitor_, OnDataFramePayload("a"));
- EXPECT_CALL(visitor_, OnDataFramePayload("!"));
+ EXPECT_CALL(visitor_, OnDataFramePayload(QuicStringPiece("D")));
+ EXPECT_CALL(visitor_, OnDataFramePayload(QuicStringPiece("a")));
+ EXPECT_CALL(visitor_, OnDataFramePayload(QuicStringPiece("t")));
+ EXPECT_CALL(visitor_, OnDataFramePayload(QuicStringPiece("a")));
+ EXPECT_CALL(visitor_, OnDataFramePayload(QuicStringPiece("!")));
EXPECT_CALL(visitor_, OnDataFrameEnd());
for (char c : input) {
EXPECT_EQ(1u, decoder_.ProcessInput(&c, 1));
@@ -358,7 +382,7 @@
// Process the full frame.
InSequence s;
EXPECT_CALL(visitor_, OnHeadersFrameStart());
- EXPECT_CALL(visitor_, OnHeadersFramePayload("Headers"));
+ EXPECT_CALL(visitor_, OnHeadersFramePayload(QuicStringPiece("Headers")));
EXPECT_CALL(visitor_, OnHeadersFrameEnd());
EXPECT_EQ(QUIC_ARRAYSIZE(input),
decoder_.ProcessInput(input, QUIC_ARRAYSIZE(input)));
@@ -367,13 +391,13 @@
// Process the frame incremently.
EXPECT_CALL(visitor_, OnHeadersFrameStart());
- EXPECT_CALL(visitor_, OnHeadersFramePayload("H"));
- EXPECT_CALL(visitor_, OnHeadersFramePayload("e"));
- EXPECT_CALL(visitor_, OnHeadersFramePayload("a"));
- EXPECT_CALL(visitor_, OnHeadersFramePayload("d"));
- EXPECT_CALL(visitor_, OnHeadersFramePayload("e"));
- EXPECT_CALL(visitor_, OnHeadersFramePayload("r"));
- EXPECT_CALL(visitor_, OnHeadersFramePayload("s"));
+ EXPECT_CALL(visitor_, OnHeadersFramePayload(QuicStringPiece("H")));
+ EXPECT_CALL(visitor_, OnHeadersFramePayload(QuicStringPiece("e")));
+ EXPECT_CALL(visitor_, OnHeadersFramePayload(QuicStringPiece("a")));
+ EXPECT_CALL(visitor_, OnHeadersFramePayload(QuicStringPiece("d")));
+ EXPECT_CALL(visitor_, OnHeadersFramePayload(QuicStringPiece("e")));
+ EXPECT_CALL(visitor_, OnHeadersFramePayload(QuicStringPiece("r")));
+ EXPECT_CALL(visitor_, OnHeadersFramePayload(QuicStringPiece("s")));
EXPECT_CALL(visitor_, OnHeadersFrameEnd());
for (char c : input) {
EXPECT_EQ(1u, decoder_.ProcessInput(&c, 1));
diff --git a/quic/core/http/http_encoder.cc b/quic/core/http/http_encoder.cc
index 6e2487b..7c07838 100644
--- a/quic/core/http/http_encoder.cc
+++ b/quic/core/http/http_encoder.cc
@@ -59,33 +59,32 @@
HttpEncoder::~HttpEncoder() {}
QuicByteCount HttpEncoder::SerializeDataFrameHeader(
- QuicByteCount length,
+ QuicByteCount payload_length,
std::unique_ptr<char[]>* output) {
- DCHECK_NE(0u, length);
+ DCHECK_NE(0u, payload_length);
QuicByteCount header_length =
- QuicDataWriter::GetVarInt62Len(length) + kFrameTypeLength;
+ QuicDataWriter::GetVarInt62Len(payload_length) + kFrameTypeLength;
output->reset(new char[header_length]);
QuicDataWriter writer(header_length, output->get(), NETWORK_BYTE_ORDER);
- if (WriteFrameHeader(length, HttpFrameType::DATA, &writer)) {
+ if (WriteFrameHeader(payload_length, HttpFrameType::DATA, &writer)) {
return header_length;
}
return 0;
}
QuicByteCount HttpEncoder::SerializeHeadersFrameHeader(
- const HeadersFrame& headers,
+ QuicByteCount payload_length,
std::unique_ptr<char[]>* output) {
+ DCHECK_NE(0u, payload_length);
QuicByteCount header_length =
- QuicDataWriter::GetVarInt62Len(headers.headers.length()) +
- kFrameTypeLength;
+ QuicDataWriter::GetVarInt62Len(payload_length) + kFrameTypeLength;
output->reset(new char[header_length]);
QuicDataWriter writer(header_length, output->get(), NETWORK_BYTE_ORDER);
- if (WriteFrameHeader(headers.headers.length(), HttpFrameType::HEADERS,
- &writer)) {
+ if (WriteFrameHeader(payload_length, HttpFrameType::HEADERS, &writer)) {
return header_length;
}
return 0;
@@ -225,6 +224,24 @@
return 0;
}
+QuicByteCount HttpEncoder::SerializeDuplicatePushFrame(
+ const DuplicatePushFrame& duplicate_push,
+ std::unique_ptr<char[]>* output) {
+ QuicByteCount payload_length =
+ QuicDataWriter::GetVarInt62Len(duplicate_push.push_id);
+ QuicByteCount total_length = GetTotalLength(payload_length);
+
+ output->reset(new char[total_length]);
+ QuicDataWriter writer(total_length, output->get(), NETWORK_BYTE_ORDER);
+
+ if (WriteFrameHeader(payload_length, HttpFrameType::DUPLICATE_PUSH,
+ &writer) &&
+ writer.WriteVarInt62(duplicate_push.push_id)) {
+ return total_length;
+ }
+ return 0;
+}
+
bool HttpEncoder::WriteFrameHeader(QuicByteCount length,
HttpFrameType type,
QuicDataWriter* writer) {
diff --git a/quic/core/http/http_encoder.h b/quic/core/http/http_encoder.h
index 79b76e9..f04e6e4 100644
--- a/quic/core/http/http_encoder.h
+++ b/quic/core/http/http_encoder.h
@@ -24,14 +24,14 @@
~HttpEncoder();
- // Serializes the header of a DATA frame into a new buffer stored in |output|.
+ // Serializes a DATA frame header into a new buffer stored in |output|.
// Returns the length of the buffer on success, or 0 otherwise.
- QuicByteCount SerializeDataFrameHeader(QuicByteCount length,
+ QuicByteCount SerializeDataFrameHeader(QuicByteCount payload_length,
std::unique_ptr<char[]>* output);
- // Serializes the header of a HEADERS frame into a new buffer stored in
- // |output|. Returns the length of the buffer on success, or 0 otherwise.
- QuicByteCount SerializeHeadersFrameHeader(const HeadersFrame& headers,
+ // Serializes a HEADERS frame header into a new buffer stored in |output|.
+ // Returns the length of the buffer on success, or 0 otherwise.
+ QuicByteCount SerializeHeadersFrameHeader(QuicByteCount payload_length,
std::unique_ptr<char[]>* output);
// Serializes a PRIORITY frame into a new buffer stored in |output|.
@@ -66,6 +66,12 @@
QuicByteCount SerializeMaxPushIdFrame(const MaxPushIdFrame& max_push_id,
std::unique_ptr<char[]>* output);
+ // Serialize a DUPLICATE_PUSH frame into a new buffer stored in |output|.
+ // Returns the length of the buffer on success, or 0 otherwise.
+ QuicByteCount SerializeDuplicatePushFrame(
+ const DuplicatePushFrame& duplicate_push,
+ std::unique_ptr<char[]>* output);
+
private:
bool WriteFrameHeader(QuicByteCount length,
HttpFrameType type,
diff --git a/quic/core/http/http_encoder_test.cc b/quic/core/http/http_encoder_test.cc
index 70cfd6a..a484aed 100644
--- a/quic/core/http/http_encoder_test.cc
+++ b/quic/core/http/http_encoder_test.cc
@@ -18,11 +18,9 @@
};
TEST_F(HttpEncoderTest, SerializeDataFrameHeader) {
- DataFrame data;
- data.data = "Data!";
std::unique_ptr<char[]> buffer;
uint64_t length =
- encoder_.SerializeDataFrameHeader(data.data.length(), &buffer);
+ encoder_.SerializeDataFrameHeader(/* payload_length = */ 5, &buffer);
char output[] = {// length
0x05,
// type (DATA)
@@ -33,10 +31,9 @@
}
TEST_F(HttpEncoderTest, SerializeHeadersFrameHeader) {
- HeadersFrame headers;
- headers.headers = "Headers";
std::unique_ptr<char[]> buffer;
- uint64_t length = encoder_.SerializeHeadersFrameHeader(headers, &buffer);
+ uint64_t length =
+ encoder_.SerializeHeadersFrameHeader(/* payload_length = */ 7, &buffer);
char output[] = {// length
0x07,
// type (HEADERS)
@@ -167,5 +164,22 @@
QUIC_ARRAYSIZE(output));
}
+TEST_F(HttpEncoderTest, SerializeDuplicatePushFrame) {
+ DuplicatePushFrame duplicate_push;
+ duplicate_push.push_id = 0x1;
+ char output[] = {// length
+ 0x1,
+ // type (DUPLICATE_PUSH)
+ 0x0E,
+ // Push Id
+ 0x01};
+ std::unique_ptr<char[]> buffer;
+ uint64_t length =
+ encoder_.SerializeDuplicatePushFrame(duplicate_push, &buffer);
+ EXPECT_EQ(QUIC_ARRAYSIZE(output), length);
+ CompareCharArraysWithHexError("DUPLICATE_PUSH", buffer.get(), length, output,
+ QUIC_ARRAYSIZE(output));
+}
+
} // namespace test
} // namespace quic
diff --git a/quic/core/http/http_frames.h b/quic/core/http/http_frames.h
index 6b6aa41..ea11557 100644
--- a/quic/core/http/http_frames.h
+++ b/quic/core/http/http_frames.h
@@ -21,10 +21,11 @@
SETTINGS = 0x4,
PUSH_PROMISE = 0x5,
GOAWAY = 0x7,
- MAX_PUSH_ID = 0xD
+ MAX_PUSH_ID = 0xD,
+ DUPLICATE_PUSH = 0xE
};
-// 4.2.2. DATA
+// 4.2.1. DATA
//
// DATA frames (type=0x0) convey arbitrary, variable-length sequences of
// octets associated with an HTTP request or response payload.
@@ -32,7 +33,7 @@
QuicStringPiece data;
};
-// 4.2.3. HEADERS
+// 4.2.2. HEADERS
//
// The HEADERS frame (type=0x1) is used to carry a header block,
// compressed using QPACK.
@@ -40,7 +41,7 @@
QuicStringPiece headers;
};
-// 4.2.4. PRIORITY
+// 4.2.3. PRIORITY
//
// The PRIORITY (type=0x02) frame specifies the sender-advised priority
// of a stream
@@ -69,7 +70,7 @@
}
};
-// 4.2.5. CANCEL_PUSH
+// 4.2.4. CANCEL_PUSH
//
// The CANCEL_PUSH frame (type=0x3) is used to request cancellation of
// server push prior to the push stream being created.
@@ -83,7 +84,7 @@
}
};
-// 4.2.6. SETTINGS
+// 4.2.5. SETTINGS
//
// The SETTINGS frame (type=0x4) conveys configuration parameters that
// affect how endpoints communicate, such as preferences and constraints
@@ -100,7 +101,7 @@
}
};
-// 4.2.7. PUSH_PROMISE
+// 4.2.6. PUSH_PROMISE
//
// The PUSH_PROMISE frame (type=0x05) is used to carry a request header
// set from server to client, as in HTTP/2.
@@ -113,7 +114,7 @@
}
};
-// 4.2.8. GOAWAY
+// 4.2.7. GOAWAY
//
// The GOAWAY frame (type=0x7) is used to initiate graceful shutdown of
// a connection by a server.
@@ -125,7 +126,7 @@
}
};
-// 4.2.9. MAX_PUSH_ID
+// 4.2.8. MAX_PUSH_ID
//
// The MAX_PUSH_ID frame (type=0xD) is used by clients to control the
// number of server pushes that the server can initiate.
@@ -137,6 +138,19 @@
}
};
+// 4.2.9. DUPLICATE_PUSH
+//
+// The DUPLICATE_PUSH frame (type=0xE) is used by servers to indicate
+// that an existing pushed resource is related to multiple client
+// requests.
+struct DuplicatePushFrame {
+ PushId push_id;
+
+ bool operator==(const DuplicatePushFrame& rhs) const {
+ return push_id == rhs.push_id;
+ }
+};
+
} // namespace quic
#endif // QUICHE_QUIC_CORE_HTTP_HTTP_FRAMES_H_
diff --git a/quic/core/http/quic_server_session_base.cc b/quic/core/http/quic_server_session_base.cc
index 47e3a27..40b43dc 100644
--- a/quic/core/http/quic_server_session_base.cc
+++ b/quic/core/http/quic_server_session_base.cc
@@ -30,8 +30,7 @@
helper_(helper),
bandwidth_resumption_enabled_(false),
bandwidth_estimate_sent_to_client_(QuicBandwidth::Zero()),
- last_scup_time_(QuicTime::Zero()),
- last_scup_packet_number_(0) {}
+ last_scup_time_(QuicTime::Zero()) {}
QuicServerSessionBase::~QuicServerSessionBase() {}
@@ -112,9 +111,15 @@
int64_t srtt_ms =
sent_packet_manager.GetRttStats()->smoothed_rtt().ToMilliseconds();
int64_t now_ms = (now - last_scup_time_).ToMilliseconds();
- int64_t packets_since_last_scup =
- connection()->sent_packet_manager().GetLargestSentPacket() -
- last_scup_packet_number_;
+ int64_t packets_since_last_scup = 0;
+ const QuicPacketNumber largest_sent_packet =
+ connection()->sent_packet_manager().GetLargestSentPacket();
+ if (largest_sent_packet.IsInitialized()) {
+ packets_since_last_scup =
+ last_scup_packet_number_.IsInitialized()
+ ? largest_sent_packet - last_scup_packet_number_
+ : largest_sent_packet.ToUint64();
+ }
if (now_ms < (kMinIntervalBetweenServerConfigUpdatesRTTs * srtt_ms) ||
now_ms < kMinIntervalBetweenServerConfigUpdatesMs ||
packets_since_last_scup < kMinPacketsBetweenServerConfigUpdates) {
diff --git a/quic/core/http/quic_server_session_base.h b/quic/core/http/quic_server_session_base.h
index 7495253..55a8d60 100644
--- a/quic/core/http/quic_server_session_base.h
+++ b/quic/core/http/quic_server_session_base.h
@@ -126,7 +126,7 @@
QuicTime last_scup_time_;
// Number of packets sent to the peer, at the time we last sent a SCUP.
- int64_t last_scup_packet_number_;
+ QuicPacketNumber last_scup_packet_number_;
// Converts QuicBandwidth to an int32 bytes/second that can be
// stored in CachedNetworkParameters. TODO(jokulik): This function
diff --git a/quic/core/http/quic_server_session_base_test.cc b/quic/core/http/quic_server_session_base_test.cc
index 6a8fb37..9f36e37 100644
--- a/quic/core/http/quic_server_session_base_test.cc
+++ b/quic/core/http/quic_server_session_base_test.cc
@@ -170,6 +170,28 @@
return connection_->transport_version();
}
+ // Create and inject a STOP_SENDING frame. In GOOGLE QUIC, receiving a
+ // RST_STREAM frame causes a two-way close. For IETF QUIC, RST_STREAM causes a
+ // one-way close. This method can be used to inject a STOP_SENDING, which
+ // would cause a close in the opposite direction. This allows tests to do the
+ // extra work to get a two-way (full) close where desired. Also sets up
+ // expects needed to ensure that the STOP_SENDING worked as expected.
+ void InjectStopSendingFrame(QuicStreamId stream_id,
+ QuicRstStreamErrorCode rst_stream_code) {
+ if (transport_version() != QUIC_VERSION_99) {
+ // Only needed for version 99/IETF QUIC. Noop otherwise.
+ return;
+ }
+ QuicStopSendingFrame stop_sending(
+ kInvalidControlFrameId, stream_id,
+ static_cast<QuicApplicationErrorCode>(rst_stream_code));
+ EXPECT_CALL(owner_, OnStopSendingReceived(_)).Times(1);
+ // Expect the RESET_STREAM that is generated in response to receiving a
+ // STOP_SENDING.
+ EXPECT_CALL(*connection_, OnStreamReset(stream_id, rst_stream_code));
+ session_->OnStopSendingFrame(stop_sending);
+ }
+
StrictMock<MockQuicSessionVisitor> owner_;
StrictMock<MockQuicCryptoServerStreamHelper> stream_helper_;
MockQuicConnectionHelper helper_;
@@ -221,6 +243,12 @@
OnStreamReset(GetNthClientInitiatedBidirectionalId(0),
QUIC_RST_ACKNOWLEDGEMENT));
visitor_->OnRstStream(rst1);
+
+ // For version-99 will create and receive a stop-sending, completing
+ // the full-close expected by this test.
+ InjectStopSendingFrame(GetNthClientInitiatedBidirectionalId(0),
+ QUIC_ERROR_PROCESSING_STREAM);
+
EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams());
// Send the same two bytes of payload in a new packet.
@@ -242,6 +270,12 @@
OnStreamReset(GetNthClientInitiatedBidirectionalId(0),
QUIC_RST_ACKNOWLEDGEMENT));
visitor_->OnRstStream(rst1);
+
+ // For version-99 will create and receive a stop-sending, completing
+ // the full-close expected by this test.
+ InjectStopSendingFrame(GetNthClientInitiatedBidirectionalId(0),
+ QUIC_ERROR_PROCESSING_STREAM);
+
EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams());
// Send two bytes of payload.
@@ -275,6 +309,11 @@
QUIC_RST_ACKNOWLEDGEMENT));
visitor_->OnRstStream(rst);
+ // For version-99 will create and receive a stop-sending, completing
+ // the full-close expected by this test.
+ InjectStopSendingFrame(GetNthClientInitiatedBidirectionalId(0),
+ QUIC_ERROR_PROCESSING_STREAM);
+
// If we were tracking, we'd probably want to reject this because it's data
// past the reset point of stream 3. As it's a closed stream we just drop the
// data on the floor, but accept the packet because it has data for stream 5.
@@ -499,10 +538,11 @@
// Bandwidth estimate has now changed sufficiently, enough time has passed,
// and enough packets have been sent.
- SerializedPacket packet(1 + kMinPacketsBetweenServerConfigUpdates,
- PACKET_4BYTE_PACKET_NUMBER, nullptr, 1000, false,
- false);
- sent_packet_manager->OnPacketSent(&packet, 0, now, NOT_RETRANSMISSION,
+ SerializedPacket packet(
+ QuicPacketNumber(1) + kMinPacketsBetweenServerConfigUpdates,
+ PACKET_4BYTE_PACKET_NUMBER, nullptr, 1000, false, false);
+ sent_packet_manager->OnPacketSent(&packet, QuicPacketNumber(), now,
+ NOT_RETRANSMISSION,
HAS_RETRANSMITTABLE_DATA);
// Verify that the proto has exactly the values we expect.
@@ -655,7 +695,7 @@
EXPECT_CALL(stream_helper_, CanAcceptClientHello(_, _, _, _, _))
.WillOnce(testing::Return(true));
- EXPECT_CALL(stream_helper_, GenerateConnectionIdForReject(_))
+ EXPECT_CALL(stream_helper_, GenerateConnectionIdForReject(_, _))
.WillOnce(testing::Return(TestConnectionId(12345)));
// Set the current packet
diff --git a/quic/core/http/quic_spdy_client_session_test.cc b/quic/core/http/quic_spdy_client_session_test.cc
index 579870a..a9d6c62 100644
--- a/quic/core/http/quic_spdy_client_session_test.cc
+++ b/quic/core/http/quic_spdy_client_session_test.cc
@@ -454,7 +454,7 @@
QuicReceivedPacket valid_packet(buf, 2, QuicTime::Zero(), false);
// Close connection shouldn't be called.
EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
- if (connection_->transport_version() == QUIC_VERSION_99) {
+ if (connection_->transport_version() > QUIC_VERSION_46) {
// Illegal fixed bit value.
EXPECT_CALL(*connection_, OnError(_)).Times(1);
}
diff --git a/quic/core/http/quic_spdy_server_stream_base_test.cc b/quic/core/http/quic_spdy_server_stream_base_test.cc
index ab13943..51abf0c 100644
--- a/quic/core/http/quic_spdy_server_stream_base_test.cc
+++ b/quic/core/http/quic_spdy_server_stream_base_test.cc
@@ -62,6 +62,14 @@
QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream_->id(),
QUIC_STREAM_CANCELLED, 1234);
stream_->OnStreamReset(rst_frame);
+ if (session_.connection()->transport_version() == QUIC_VERSION_99) {
+ // Create and inject a STOP SENDING frame to complete the close
+ // of the stream. This is only needed for version 99/IETF QUIC.
+ QuicStopSendingFrame stop_sending(
+ kInvalidControlFrameId, stream_->id(),
+ static_cast<QuicApplicationErrorCode>(QUIC_STREAM_CANCELLED));
+ session_.OnStopSendingFrame(stop_sending);
+ }
EXPECT_TRUE(stream_->reading_stopped());
EXPECT_TRUE(stream_->write_side_closed());
diff --git a/quic/core/http/quic_spdy_session_test.cc b/quic/core/http/quic_spdy_session_test.cc
index 00fb10f..affa07a 100644
--- a/quic/core/http/quic_spdy_session_test.cc
+++ b/quic/core/http/quic_spdy_session_test.cc
@@ -1001,6 +1001,23 @@
GetNthClientInitiatedBidirectionalId(0),
QUIC_ERROR_PROCESSING_STREAM, 0);
session_.OnRstStream(rst1);
+
+ // Create and inject a STOP_SENDING frame. In GOOGLE QUIC, receiving a
+ // RST_STREAM frame causes a two-way close. For IETF QUIC, RST_STREAM causes a
+ // one-way close.
+ if (transport_version() == QUIC_VERSION_99) {
+ // Only needed for version 99/IETF QUIC.
+ QuicStopSendingFrame stop_sending(
+ kInvalidControlFrameId, GetNthClientInitiatedBidirectionalId(0),
+ static_cast<QuicApplicationErrorCode>(QUIC_ERROR_PROCESSING_STREAM));
+ // Expect the RESET_STREAM that is generated in response to receiving a
+ // STOP_SENDING.
+ EXPECT_CALL(*connection_,
+ OnStreamReset(GetNthClientInitiatedBidirectionalId(0),
+ QUIC_ERROR_PROCESSING_STREAM));
+ session_.OnStopSendingFrame(stop_sending);
+ }
+
EXPECT_EQ(0u, session_.GetNumOpenIncomingStreams());
// Connection should remain alive.
EXPECT_TRUE(connection_->connected());
@@ -1219,15 +1236,31 @@
.Times(2)
.WillRepeatedly(Invoke(&session_, &TestSession::ClearControlFrame));
} else {
- // V99 has an additional, STOP_SENDING, frame.
+ // V99 has an additional, STOP_SENDING, frame and an additional RST_STREAM
+ // (the response to the STOP_SENDING) frame.
EXPECT_CALL(*connection_, SendControlFrame(_))
- .Times(3)
+ .Times(4)
.WillRepeatedly(Invoke(&session_, &TestSession::ClearControlFrame));
}
EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream->id(),
QUIC_STREAM_CANCELLED, kByteOffset);
session_.OnRstStream(rst_frame);
+ // Create and inject a STOP_SENDING frame. In GOOGLE QUIC, receiving a
+ // RST_STREAM frame causes a two-way close. For IETF QUIC, RST_STREAM causes a
+ // one-way close.
+ if (transport_version() == QUIC_VERSION_99) {
+ // Only needed for version 99/IETF QUIC.
+ QuicStopSendingFrame stop_sending(
+ kInvalidControlFrameId, stream->id(),
+ static_cast<QuicApplicationErrorCode>(QUIC_STREAM_CANCELLED));
+ // Expect the RESET_STREAM that is generated in response to receiving a
+ // STOP_SENDING.
+ EXPECT_CALL(*connection_,
+ OnStreamReset(stream->id(), QUIC_STREAM_CANCELLED));
+ session_.OnStopSendingFrame(stop_sending);
+ }
+
EXPECT_EQ(kByteOffset, session_.flow_controller()->bytes_consumed());
}
diff --git a/quic/core/http/quic_spdy_stream.cc b/quic/core/http/quic_spdy_stream.cc
index 9a5d024..eb8135a 100644
--- a/quic/core/http/quic_spdy_stream.cc
+++ b/quic/core/http/quic_spdy_stream.cc
@@ -59,6 +59,10 @@
CloseConnectionOnWrongFrame("Settings");
}
+ void OnDuplicatePushFrame(const DuplicatePushFrame& frame) override {
+ CloseConnectionOnWrongFrame("Duplicate Push");
+ }
+
void OnDataFrameStart(Http3FrameLengths frame_lengths) override {
stream_->OnDataFrameStart(frame_lengths);
}
@@ -176,19 +180,23 @@
QuicStringPiece data,
bool fin,
QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
- if (spdy_session_->connection()->transport_version() == QUIC_VERSION_99 &&
- data.length() > 0) {
- std::unique_ptr<char[]> buffer;
- QuicByteCount header_length =
- encoder_.SerializeDataFrameHeader(data.length(), &buffer);
- WriteOrBufferData(QuicStringPiece(buffer.get(), header_length), false,
- nullptr);
- QUIC_DLOG(INFO) << "Stream " << id() << " is writing header of length "
- << header_length;
- total_header_bytes_written_ += header_length;
+ if (spdy_session_->connection()->transport_version() != QUIC_VERSION_99 ||
+ data.length() == 0) {
+ WriteOrBufferData(data, fin, std::move(ack_listener));
+ return;
}
+ QuicConnection::ScopedPacketFlusher flusher(
+ spdy_session_->connection(), QuicConnection::SEND_ACK_IF_PENDING);
+ std::unique_ptr<char[]> buffer;
+ QuicByteCount header_length =
+ encoder_.SerializeDataFrameHeader(data.length(), &buffer);
+ WriteOrBufferData(QuicStringPiece(buffer.get(), header_length), false,
+ nullptr);
+ QUIC_DLOG(INFO) << "Stream " << id() << " is writing header of length "
+ << header_length;
+ total_header_bytes_written_ += header_length;
WriteOrBufferData(data, fin, std::move(ack_listener));
- QUIC_DLOG(INFO) << "Stream" << id() << " is writing body of length "
+ QUIC_DLOG(INFO) << "Stream " << id() << " is writing body of length "
<< data.length();
}
@@ -254,6 +262,8 @@
return {0, false};
}
+ QuicConnection::ScopedPacketFlusher flusher(
+ spdy_session_->connection(), QuicConnection::SEND_ACK_IF_PENDING);
struct iovec header_iov = {static_cast<void*>(buffer.get()), header_length};
QuicMemSliceStorage storage(
&header_iov, 1,
diff --git a/quic/core/http/quic_spdy_stream_body_buffer.h b/quic/core/http/quic_spdy_stream_body_buffer.h
index acd4985..2485aac 100644
--- a/quic/core/http/quic_spdy_stream_body_buffer.h
+++ b/quic/core/http/quic_spdy_stream_body_buffer.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef QUICHE_QUIC_CORE_HTTP_QUIC_SPDY_STREAM_BODY_BUFFER_H
-#define QUICHE_QUIC_CORE_HTTP_QUIC_SPDY_STREAM_BODY_BUFFER_H
+#ifndef QUICHE_QUIC_CORE_HTTP_QUIC_SPDY_STREAM_BODY_BUFFER_H_
+#define QUICHE_QUIC_CORE_HTTP_QUIC_SPDY_STREAM_BODY_BUFFER_H_
#include "net/third_party/quiche/src/quic/core/http/http_decoder.h"
#include "net/third_party/quiche/src/quic/core/quic_stream_sequencer.h"
@@ -72,4 +72,4 @@
} // namespace quic
-#endif // QUICHE_QUIC_CORE_HTTP_QUIC_SPDY_STREAM_BODY_BUFFER_H
+#endif // QUICHE_QUIC_CORE_HTTP_QUIC_SPDY_STREAM_BODY_BUFFER_H_
diff --git a/quic/core/http/spdy_utils_test.cc b/quic/core/http/spdy_utils_test.cc
index b8edf49..6cd2f1d 100644
--- a/quic/core/http/spdy_utils_test.cc
+++ b/quic/core/http/spdy_utils_test.cc
@@ -327,6 +327,24 @@
EXPECT_EQ(SpdyUtils::GetPromisedUrlFromHeaders(headers), "");
}
+TEST_F(GetPromisedUrlFromHeaders, InvalidUserinfo) {
+ SpdyHeaderBlock headers;
+ headers[":method"] = "GET";
+ headers[":authority"] = "user@www.google.com";
+ headers[":scheme"] = "https";
+ headers[":path"] = "/";
+ EXPECT_EQ(SpdyUtils::GetPromisedUrlFromHeaders(headers), "");
+}
+
+TEST_F(GetPromisedUrlFromHeaders, InvalidPath) {
+ SpdyHeaderBlock headers;
+ headers[":method"] = "GET";
+ headers[":authority"] = "www.google.com";
+ headers[":scheme"] = "https";
+ headers[":path"] = "";
+ EXPECT_EQ(SpdyUtils::GetPromisedUrlFromHeaders(headers), "");
+}
+
using GetPromisedHostNameFromHeaders = QuicTest;
TEST_F(GetPromisedHostNameFromHeaders, NormalUsage) {
diff --git a/quic/core/legacy_quic_stream_id_manager.cc b/quic/core/legacy_quic_stream_id_manager.cc
index 000d0cb..6fb662a 100644
--- a/quic/core/legacy_quic_stream_id_manager.cc
+++ b/quic/core/legacy_quic_stream_id_manager.cc
@@ -1,3 +1,6 @@
+// Copyright (c) 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
#include "net/third_party/quiche/src/quic/core/legacy_quic_stream_id_manager.h"
#include "net/third_party/quiche/src/quic/core/quic_session.h"
diff --git a/quic/core/legacy_quic_stream_id_manager.h b/quic/core/legacy_quic_stream_id_manager.h
index 79a4d47..78d4545 100644
--- a/quic/core/legacy_quic_stream_id_manager.h
+++ b/quic/core/legacy_quic_stream_id_manager.h
@@ -1,3 +1,6 @@
+// Copyright (c) 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
#ifndef QUICHE_QUIC_CORE_LEGACY_QUIC_STREAM_ID_MANAGER_H_
#define QUICHE_QUIC_CORE_LEGACY_QUIC_STREAM_ID_MANAGER_H_
diff --git a/quic/core/legacy_quic_stream_id_manager_test.cc b/quic/core/legacy_quic_stream_id_manager_test.cc
index 643ff5b..823cdc0 100644
--- a/quic/core/legacy_quic_stream_id_manager_test.cc
+++ b/quic/core/legacy_quic_stream_id_manager_test.cc
@@ -1,3 +1,6 @@
+// Copyright (c) 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
#include "net/third_party/quiche/src/quic/core/legacy_quic_stream_id_manager.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
diff --git a/quic/core/packet_number_indexed_queue.h b/quic/core/packet_number_indexed_queue.h
index 97d93de..ab2e20b 100644
--- a/quic/core/packet_number_indexed_queue.h
+++ b/quic/core/packet_number_indexed_queue.h
@@ -5,8 +5,9 @@
#ifndef QUICHE_QUIC_CORE_PACKET_NUMBER_INDEXED_QUEUE_H_
#define QUICHE_QUIC_CORE_PACKET_NUMBER_INDEXED_QUEUE_H_
-#include "base/logging.h"
+#include "net/third_party/quiche/src/quic/core/quic_constants.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
namespace quic {
@@ -35,8 +36,7 @@
template <typename T>
class PacketNumberIndexedQueue {
public:
- PacketNumberIndexedQueue()
- : number_of_present_entries_(0), first_packet_(0) {}
+ PacketNumberIndexedQueue() : number_of_present_entries_(0) {}
// Retrieve the entry associated with the packet number. Returns the pointer
// to the entry in case of success, or nullptr if the entry does not exist.
@@ -65,15 +65,15 @@
// proportional to the memory usage of the queue.
size_t entry_slots_used() const { return entries_.size(); }
- // Packet number of the first entry in the queue. Zero if the queue is empty.
- size_t first_packet() const { return first_packet_; }
+ // Packet number of the first entry in the queue.
+ QuicPacketNumber first_packet() const { return first_packet_; }
// Packet number of the last entry ever inserted in the queue. Note that the
// entry in question may have already been removed. Zero if the queue is
// empty.
- size_t last_packet() const {
+ QuicPacketNumber last_packet() const {
if (IsEmpty()) {
- return 0;
+ return QuicPacketNumber();
}
return first_packet_ + entries_.size() - 1;
}
@@ -127,9 +127,14 @@
template <typename... Args>
bool PacketNumberIndexedQueue<T>::Emplace(QuicPacketNumber packet_number,
Args&&... args) {
+ if (!packet_number.IsInitialized()) {
+ QUIC_BUG << "Try to insert an uninitialized packet number";
+ return false;
+ }
+
if (IsEmpty()) {
DCHECK(entries_.empty());
- DCHECK_EQ(0u, first_packet_);
+ DCHECK(!first_packet_.IsInitialized());
entries_.emplace_back(std::forward<Args>(args)...);
number_of_present_entries_ = 1;
@@ -176,18 +181,19 @@
first_packet_++;
}
if (entries_.empty()) {
- first_packet_ = 0;
+ first_packet_.Clear();
}
}
template <typename T>
-auto PacketNumberIndexedQueue<T>::GetEntryWrapper(QuicPacketNumber offset) const
- -> const EntryWrapper* {
- if (offset < first_packet_) {
+auto PacketNumberIndexedQueue<T>::GetEntryWrapper(
+ QuicPacketNumber packet_number) const -> const EntryWrapper* {
+ if (!packet_number.IsInitialized() || IsEmpty() ||
+ packet_number < first_packet_) {
return nullptr;
}
- offset -= first_packet_;
+ uint64_t offset = packet_number - first_packet_;
if (offset >= entries_.size()) {
return nullptr;
}
diff --git a/quic/core/packet_number_indexed_queue_test.cc b/quic/core/packet_number_indexed_queue_test.cc
index 0190df2..294d2a4 100644
--- a/quic/core/packet_number_indexed_queue_test.cc
+++ b/quic/core/packet_number_indexed_queue_test.cc
@@ -23,156 +23,156 @@
TEST_F(PacketNumberIndexedQueueTest, InitialState) {
EXPECT_TRUE(queue_.IsEmpty());
- EXPECT_EQ(0u, queue_.first_packet());
- EXPECT_EQ(0u, queue_.last_packet());
+ EXPECT_FALSE(queue_.first_packet().IsInitialized());
+ EXPECT_FALSE(queue_.last_packet().IsInitialized());
EXPECT_EQ(0u, queue_.number_of_present_entries());
EXPECT_EQ(0u, queue_.entry_slots_used());
}
TEST_F(PacketNumberIndexedQueueTest, InsertingContinuousElements) {
- ASSERT_TRUE(queue_.Emplace(1001, "one"));
- EXPECT_EQ("one", *queue_.GetEntry(1001));
+ ASSERT_TRUE(queue_.Emplace(QuicPacketNumber(1001), "one"));
+ EXPECT_EQ("one", *queue_.GetEntry(QuicPacketNumber(1001)));
- ASSERT_TRUE(queue_.Emplace(1002, "two"));
- EXPECT_EQ("two", *queue_.GetEntry(1002));
+ ASSERT_TRUE(queue_.Emplace(QuicPacketNumber(1002), "two"));
+ EXPECT_EQ("two", *queue_.GetEntry(QuicPacketNumber(1002)));
EXPECT_FALSE(queue_.IsEmpty());
- EXPECT_EQ(1001u, queue_.first_packet());
- EXPECT_EQ(1002u, queue_.last_packet());
+ EXPECT_EQ(QuicPacketNumber(1001u), queue_.first_packet());
+ EXPECT_EQ(QuicPacketNumber(1002u), queue_.last_packet());
EXPECT_EQ(2u, queue_.number_of_present_entries());
EXPECT_EQ(2u, queue_.entry_slots_used());
}
TEST_F(PacketNumberIndexedQueueTest, InsertingOutOfOrder) {
- queue_.Emplace(1001, "one");
+ queue_.Emplace(QuicPacketNumber(1001), "one");
- ASSERT_TRUE(queue_.Emplace(1003, "three"));
- EXPECT_EQ(nullptr, queue_.GetEntry(1002));
- EXPECT_EQ("three", *queue_.GetEntry(1003));
+ ASSERT_TRUE(queue_.Emplace(QuicPacketNumber(1003), "three"));
+ EXPECT_EQ(nullptr, queue_.GetEntry(QuicPacketNumber(1002)));
+ EXPECT_EQ("three", *queue_.GetEntry(QuicPacketNumber(1003)));
- EXPECT_EQ(1001u, queue_.first_packet());
- EXPECT_EQ(1003u, queue_.last_packet());
+ EXPECT_EQ(QuicPacketNumber(1001u), queue_.first_packet());
+ EXPECT_EQ(QuicPacketNumber(1003u), queue_.last_packet());
EXPECT_EQ(2u, queue_.number_of_present_entries());
EXPECT_EQ(3u, queue_.entry_slots_used());
- ASSERT_FALSE(queue_.Emplace(1002, "two"));
+ ASSERT_FALSE(queue_.Emplace(QuicPacketNumber(1002), "two"));
}
TEST_F(PacketNumberIndexedQueueTest, InsertingIntoPast) {
- queue_.Emplace(1001, "one");
- EXPECT_FALSE(queue_.Emplace(1000, "zero"));
+ queue_.Emplace(QuicPacketNumber(1001), "one");
+ EXPECT_FALSE(queue_.Emplace(QuicPacketNumber(1000), "zero"));
}
TEST_F(PacketNumberIndexedQueueTest, InsertingDuplicate) {
- queue_.Emplace(1001, "one");
- EXPECT_FALSE(queue_.Emplace(1001, "one"));
+ queue_.Emplace(QuicPacketNumber(1001), "one");
+ EXPECT_FALSE(queue_.Emplace(QuicPacketNumber(1001), "one"));
}
TEST_F(PacketNumberIndexedQueueTest, RemoveInTheMiddle) {
- queue_.Emplace(1001, "one");
- queue_.Emplace(1002, "two");
- queue_.Emplace(1003, "three");
+ queue_.Emplace(QuicPacketNumber(1001), "one");
+ queue_.Emplace(QuicPacketNumber(1002), "two");
+ queue_.Emplace(QuicPacketNumber(1003), "three");
- ASSERT_TRUE(queue_.Remove(1002));
- EXPECT_EQ(nullptr, queue_.GetEntry(1002));
+ ASSERT_TRUE(queue_.Remove(QuicPacketNumber(1002)));
+ EXPECT_EQ(nullptr, queue_.GetEntry(QuicPacketNumber(1002)));
- EXPECT_EQ(1001u, queue_.first_packet());
- EXPECT_EQ(1003u, queue_.last_packet());
+ EXPECT_EQ(QuicPacketNumber(1001u), queue_.first_packet());
+ EXPECT_EQ(QuicPacketNumber(1003u), queue_.last_packet());
EXPECT_EQ(2u, queue_.number_of_present_entries());
EXPECT_EQ(3u, queue_.entry_slots_used());
- EXPECT_FALSE(queue_.Emplace(1002, "two"));
- EXPECT_TRUE(queue_.Emplace(1004, "four"));
+ EXPECT_FALSE(queue_.Emplace(QuicPacketNumber(1002), "two"));
+ EXPECT_TRUE(queue_.Emplace(QuicPacketNumber(1004), "four"));
}
TEST_F(PacketNumberIndexedQueueTest, RemoveAtImmediateEdges) {
- queue_.Emplace(1001, "one");
- queue_.Emplace(1002, "two");
- queue_.Emplace(1003, "three");
- ASSERT_TRUE(queue_.Remove(1001));
- EXPECT_EQ(nullptr, queue_.GetEntry(1001));
- ASSERT_TRUE(queue_.Remove(1003));
- EXPECT_EQ(nullptr, queue_.GetEntry(1003));
+ queue_.Emplace(QuicPacketNumber(1001), "one");
+ queue_.Emplace(QuicPacketNumber(1002), "two");
+ queue_.Emplace(QuicPacketNumber(1003), "three");
+ ASSERT_TRUE(queue_.Remove(QuicPacketNumber(1001)));
+ EXPECT_EQ(nullptr, queue_.GetEntry(QuicPacketNumber(1001)));
+ ASSERT_TRUE(queue_.Remove(QuicPacketNumber(1003)));
+ EXPECT_EQ(nullptr, queue_.GetEntry(QuicPacketNumber(1003)));
- EXPECT_EQ(1002u, queue_.first_packet());
- EXPECT_EQ(1003u, queue_.last_packet());
+ EXPECT_EQ(QuicPacketNumber(1002u), queue_.first_packet());
+ EXPECT_EQ(QuicPacketNumber(1003u), queue_.last_packet());
EXPECT_EQ(1u, queue_.number_of_present_entries());
EXPECT_EQ(2u, queue_.entry_slots_used());
- EXPECT_TRUE(queue_.Emplace(1004, "four"));
+ EXPECT_TRUE(queue_.Emplace(QuicPacketNumber(1004), "four"));
}
TEST_F(PacketNumberIndexedQueueTest, RemoveAtDistantFront) {
- queue_.Emplace(1001, "one");
- queue_.Emplace(1002, "one (kinda)");
- queue_.Emplace(2001, "two");
+ queue_.Emplace(QuicPacketNumber(1001), "one");
+ queue_.Emplace(QuicPacketNumber(1002), "one (kinda)");
+ queue_.Emplace(QuicPacketNumber(2001), "two");
- EXPECT_EQ(1001u, queue_.first_packet());
- EXPECT_EQ(2001u, queue_.last_packet());
+ EXPECT_EQ(QuicPacketNumber(1001u), queue_.first_packet());
+ EXPECT_EQ(QuicPacketNumber(2001u), queue_.last_packet());
EXPECT_EQ(3u, queue_.number_of_present_entries());
EXPECT_EQ(1001u, queue_.entry_slots_used());
- ASSERT_TRUE(queue_.Remove(1002));
- EXPECT_EQ(1001u, queue_.first_packet());
- EXPECT_EQ(2001u, queue_.last_packet());
+ ASSERT_TRUE(queue_.Remove(QuicPacketNumber(1002)));
+ EXPECT_EQ(QuicPacketNumber(1001u), queue_.first_packet());
+ EXPECT_EQ(QuicPacketNumber(2001u), queue_.last_packet());
EXPECT_EQ(2u, queue_.number_of_present_entries());
EXPECT_EQ(1001u, queue_.entry_slots_used());
- ASSERT_TRUE(queue_.Remove(1001));
- EXPECT_EQ(2001u, queue_.first_packet());
- EXPECT_EQ(2001u, queue_.last_packet());
+ ASSERT_TRUE(queue_.Remove(QuicPacketNumber(1001)));
+ EXPECT_EQ(QuicPacketNumber(2001u), queue_.first_packet());
+ EXPECT_EQ(QuicPacketNumber(2001u), queue_.last_packet());
EXPECT_EQ(1u, queue_.number_of_present_entries());
EXPECT_EQ(1u, queue_.entry_slots_used());
}
TEST_F(PacketNumberIndexedQueueTest, RemoveAtDistantBack) {
- queue_.Emplace(1001, "one");
- queue_.Emplace(2001, "two");
+ queue_.Emplace(QuicPacketNumber(1001), "one");
+ queue_.Emplace(QuicPacketNumber(2001), "two");
- EXPECT_EQ(1001u, queue_.first_packet());
- EXPECT_EQ(2001u, queue_.last_packet());
+ EXPECT_EQ(QuicPacketNumber(1001u), queue_.first_packet());
+ EXPECT_EQ(QuicPacketNumber(2001u), queue_.last_packet());
- ASSERT_TRUE(queue_.Remove(2001));
- EXPECT_EQ(1001u, queue_.first_packet());
- EXPECT_EQ(2001u, queue_.last_packet());
+ ASSERT_TRUE(queue_.Remove(QuicPacketNumber(2001)));
+ EXPECT_EQ(QuicPacketNumber(1001u), queue_.first_packet());
+ EXPECT_EQ(QuicPacketNumber(2001u), queue_.last_packet());
}
TEST_F(PacketNumberIndexedQueueTest, ClearAndRepopulate) {
- queue_.Emplace(1001, "one");
- queue_.Emplace(2001, "two");
+ queue_.Emplace(QuicPacketNumber(1001), "one");
+ queue_.Emplace(QuicPacketNumber(2001), "two");
- ASSERT_TRUE(queue_.Remove(1001));
- ASSERT_TRUE(queue_.Remove(2001));
+ ASSERT_TRUE(queue_.Remove(QuicPacketNumber(1001)));
+ ASSERT_TRUE(queue_.Remove(QuicPacketNumber(2001)));
EXPECT_TRUE(queue_.IsEmpty());
- EXPECT_EQ(0u, queue_.first_packet());
- EXPECT_EQ(0u, queue_.last_packet());
+ EXPECT_FALSE(queue_.first_packet().IsInitialized());
+ EXPECT_FALSE(queue_.last_packet().IsInitialized());
- EXPECT_TRUE(queue_.Emplace(101, "one"));
- EXPECT_TRUE(queue_.Emplace(201, "two"));
- EXPECT_EQ(101u, queue_.first_packet());
- EXPECT_EQ(201u, queue_.last_packet());
+ EXPECT_TRUE(queue_.Emplace(QuicPacketNumber(101), "one"));
+ EXPECT_TRUE(queue_.Emplace(QuicPacketNumber(201), "two"));
+ EXPECT_EQ(QuicPacketNumber(101u), queue_.first_packet());
+ EXPECT_EQ(QuicPacketNumber(201u), queue_.last_packet());
}
TEST_F(PacketNumberIndexedQueueTest, FailToRemoveElementsThatNeverExisted) {
- ASSERT_FALSE(queue_.Remove(1000));
- queue_.Emplace(1001, "one");
- ASSERT_FALSE(queue_.Remove(1000));
- ASSERT_FALSE(queue_.Remove(1002));
+ ASSERT_FALSE(queue_.Remove(QuicPacketNumber(1000)));
+ queue_.Emplace(QuicPacketNumber(1001), "one");
+ ASSERT_FALSE(queue_.Remove(QuicPacketNumber(1000)));
+ ASSERT_FALSE(queue_.Remove(QuicPacketNumber(1002)));
}
TEST_F(PacketNumberIndexedQueueTest, FailToRemoveElementsTwice) {
- queue_.Emplace(1001, "one");
- ASSERT_TRUE(queue_.Remove(1001));
- ASSERT_FALSE(queue_.Remove(1001));
- ASSERT_FALSE(queue_.Remove(1001));
+ queue_.Emplace(QuicPacketNumber(1001), "one");
+ ASSERT_TRUE(queue_.Remove(QuicPacketNumber(1001)));
+ ASSERT_FALSE(queue_.Remove(QuicPacketNumber(1001)));
+ ASSERT_FALSE(queue_.Remove(QuicPacketNumber(1001)));
}
TEST_F(PacketNumberIndexedQueueTest, ConstGetter) {
- queue_.Emplace(1001, "one");
+ queue_.Emplace(QuicPacketNumber(1001), "one");
const auto& const_queue = queue_;
- EXPECT_EQ("one", *const_queue.GetEntry(1001));
- EXPECT_EQ(nullptr, const_queue.GetEntry(1002));
+ EXPECT_EQ("one", *const_queue.GetEntry(QuicPacketNumber(1001)));
+ EXPECT_EQ(nullptr, const_queue.GetEntry(QuicPacketNumber(1002)));
}
} // namespace
diff --git a/quic/core/qpack/fuzzer/qpack_encoder_stream_receiver_fuzzer.cc b/quic/core/qpack/fuzzer/qpack_encoder_stream_receiver_fuzzer.cc
index e61c973..980889d 100644
--- a/quic/core/qpack/fuzzer/qpack_encoder_stream_receiver_fuzzer.cc
+++ b/quic/core/qpack/fuzzer/qpack_encoder_stream_receiver_fuzzer.cc
@@ -28,7 +28,7 @@
void OnInsertWithoutNameReference(QuicStringPiece name,
QuicStringPiece value) override {}
void OnDuplicate(uint64_t index) override {}
- void OnDynamicTableSizeUpdate(uint64_t max_size) override {}
+ void OnSetDynamicTableCapacity(uint64_t capacity) override {}
void OnErrorDetected(QuicStringPiece error_message) override {
error_detected_ = true;
}
diff --git a/quic/core/qpack/fuzzer/qpack_encoder_stream_sender_fuzzer.cc b/quic/core/qpack/fuzzer/qpack_encoder_stream_sender_fuzzer.cc
index f404a76..501a69f 100644
--- a/quic/core/qpack/fuzzer/qpack_encoder_stream_sender_fuzzer.cc
+++ b/quic/core/qpack/fuzzer/qpack_encoder_stream_sender_fuzzer.cc
@@ -8,6 +8,7 @@
#include <cstdint>
#include <limits>
+#include "net/third_party/quiche/src/quic/core/qpack/qpack_encoder_test_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_fuzzed_data_provider.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
@@ -15,22 +16,12 @@
namespace quic {
namespace test {
-// A QpackEncoderStreamSender::Delegate implementation that ignores encoded
-// data.
-class NoOpDelegate : public QpackEncoderStreamSender::Delegate {
- public:
- NoOpDelegate() = default;
- ~NoOpDelegate() override = default;
-
- void Write(QuicStringPiece data) override {}
-};
-
// This fuzzer exercises QpackEncoderStreamSender.
// TODO(bnc): Encoded data could be fed into QpackEncoderStreamReceiver and
// decoded instructions directly compared to input. Figure out how to get gMock
// enabled for cc_fuzz_target target types.
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- NoOpDelegate delegate;
+ NoopEncoderStreamSenderDelegate delegate;
QpackEncoderStreamSender sender(&delegate);
QuicFuzzedDataProvider provider(data, size);
@@ -65,8 +56,8 @@
break;
}
case 3: {
- uint64_t max_size = provider.ConsumeIntegral<uint64_t>();
- sender.SendDynamicTableSizeUpdate(max_size);
+ uint64_t capacity = provider.ConsumeIntegral<uint64_t>();
+ sender.SendSetDynamicTableCapacity(capacity);
break;
}
}
diff --git a/quic/core/qpack/offline/qpack_offline_decoder.cc b/quic/core/qpack/offline/qpack_offline_decoder.cc
index c3ad1f9..2b02edd 100644
--- a/quic/core/qpack/offline/qpack_offline_decoder.cc
+++ b/quic/core/qpack/offline/qpack_offline_decoder.cc
@@ -44,7 +44,7 @@
return true;
}
-void QpackOfflineDecoder::OnError(QuicStringPiece error_message) {
+void QpackOfflineDecoder::OnEncoderStreamError(QuicStringPiece error_message) {
QUIC_LOG(ERROR) << "Encoder stream error: " << error_message;
encoder_stream_error_detected_ = true;
}
diff --git a/quic/core/qpack/offline/qpack_offline_decoder.h b/quic/core/qpack/offline/qpack_offline_decoder.h
index faa64bc..922fd64 100644
--- a/quic/core/qpack/offline/qpack_offline_decoder.h
+++ b/quic/core/qpack/offline/qpack_offline_decoder.h
@@ -5,6 +5,8 @@
#ifndef QUICHE_QUIC_CORE_QPACK_OFFLINE_QPACK_OFFLINE_DECODER_H_
#define QUICHE_QUIC_CORE_QPACK_OFFLINE_QPACK_OFFLINE_DECODER_H_
+#include <list>
+
#include "net/third_party/quiche/src/quic/core/qpack/qpack_decoder.h"
#include "net/third_party/quiche/src/quic/core/qpack/qpack_decoder_test_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
@@ -30,7 +32,7 @@
QuicStringPiece expected_headers_filename);
// QpackDecoder::EncoderStreamErrorDelegate implementation:
- void OnError(QuicStringPiece error_message) override;
+ void OnEncoderStreamError(QuicStringPiece error_message) override;
private:
// Parse decoder parameters from |input_filename| and set up |decoder_|
diff --git a/quic/core/qpack/offline/qpack_offline_decoder_bin.cc b/quic/core/qpack/offline/qpack_offline_decoder_bin.cc
index 2068f52..499c9fd 100644
--- a/quic/core/qpack/offline/qpack_offline_decoder_bin.cc
+++ b/quic/core/qpack/offline/qpack_offline_decoder_bin.cc
@@ -20,7 +20,7 @@
return 1;
}
- size_t i;
+ int i;
for (i = 0; 2 * i + 1 < argc; ++i) {
const quic::QuicStringPiece input_filename(argv[2 * i + 1]);
const quic::QuicStringPiece expected_headers_filename(argv[2 * i + 2]);
diff --git a/quic/core/qpack/qpack_constants.cc b/quic/core/qpack/qpack_constants.cc
index eda1ef4..b9144e0 100644
--- a/quic/core/qpack/qpack_constants.cc
+++ b/quic/core/qpack/qpack_constants.cc
@@ -4,7 +4,6 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_constants.h"
-#include <cstddef>
#include <limits>
#include "base/logging.h"
@@ -17,8 +16,9 @@
// * in each instruction, the bits of |value| that are zero in |mask| are zero;
// * every byte matches exactly one opcode.
void ValidateLangague(const QpackLanguage* language) {
+#ifndef NDEBUG
for (const auto* instruction : *language) {
- DCHECK_EQ(0u, instruction->opcode.value & ~instruction->opcode.mask);
+ DCHECK_EQ(0, instruction->opcode.value & ~instruction->opcode.mask);
}
for (uint8_t byte = 0; byte < std::numeric_limits<uint8_t>::max(); ++byte) {
@@ -30,6 +30,7 @@
}
DCHECK_EQ(1u, match_count) << static_cast<int>(byte);
}
+#endif
}
} // namespace
@@ -68,7 +69,7 @@
return instruction;
}
-const QpackInstruction* DynamicTableSizeUpdateInstruction() {
+const QpackInstruction* SetDynamicTableCapacityInstruction() {
static const QpackInstructionOpcode* const opcode =
new QpackInstructionOpcode{0b00100000, 0b11100000};
static const QpackInstruction* const instruction =
@@ -80,14 +81,12 @@
static const QpackLanguage* const language = new QpackLanguage{
InsertWithNameReferenceInstruction(),
InsertWithoutNameReferenceInstruction(), DuplicateInstruction(),
- DynamicTableSizeUpdateInstruction()};
-#ifndef NDEBUG
+ SetDynamicTableCapacityInstruction()};
ValidateLangague(language);
-#endif
return language;
}
-const QpackInstruction* TableStateSynchronizeInstruction() {
+const QpackInstruction* InsertCountIncrementInstruction() {
static const QpackInstructionOpcode* const opcode =
new QpackInstructionOpcode{0b00000000, 0b11000000};
static const QpackInstruction* const instruction =
@@ -113,11 +112,9 @@
const QpackLanguage* QpackDecoderStreamLanguage() {
static const QpackLanguage* const language = new QpackLanguage{
- TableStateSynchronizeInstruction(), HeaderAcknowledgementInstruction(),
+ InsertCountIncrementInstruction(), HeaderAcknowledgementInstruction(),
StreamCancellationInstruction()};
-#ifndef NDEBUG
ValidateLangague(language);
-#endif
return language;
}
@@ -136,9 +133,7 @@
const QpackLanguage* QpackPrefixLanguage() {
static const QpackLanguage* const language =
new QpackLanguage{QpackPrefixInstruction()};
-#ifndef NDEBUG
ValidateLangague(language);
-#endif
return language;
}
@@ -198,9 +193,7 @@
QpackLiteralHeaderFieldNameReferenceInstruction(),
QpackLiteralHeaderFieldPostBaseInstruction(),
QpackLiteralHeaderFieldInstruction()};
-#ifndef NDEBUG
ValidateLangague(language);
-#endif
return language;
}
diff --git a/quic/core/qpack/qpack_constants.h b/quic/core/qpack/qpack_constants.h
index 4fce3dd..7b7eb47 100644
--- a/quic/core/qpack/qpack_constants.h
+++ b/quic/core/qpack/qpack_constants.h
@@ -30,14 +30,14 @@
// literal consumes all bytes containing the field value.
enum class QpackInstructionFieldType {
// A single bit indicating whether the index refers to the static table, or
- // indicating the sign of Delta Base Index. Called "S" bit because both
- // "static" and "sign" start with the letter "S".
+ // indicating the sign of Delta Base. Called "S" bit because both "static"
+ // and "sign" start with the letter "S".
kSbit,
// An integer encoded with variable length encoding. This could be an index,
- // stream ID, maximum size, or Largest Reference.
+ // stream ID, maximum size, or Encoded Required Insert Count.
kVarint,
// A second integer encoded with variable length encoding. This could be
- // Delta Base Index.
+ // Delta Base.
kVarint2,
// A header name or header value encoded as:
// a bit indicating whether it is Huffman encoded;
@@ -97,15 +97,15 @@
const QpackInstruction* DuplicateInstruction();
// 5.2.4 Dynamic Table Size Update
-const QpackInstruction* DynamicTableSizeUpdateInstruction();
+const QpackInstruction* SetDynamicTableCapacityInstruction();
// Encoder stream language.
const QpackLanguage* QpackEncoderStreamLanguage();
// 5.3 Decoder stream instructions
-// 5.3.1 Table State Synchronize
-const QpackInstruction* TableStateSynchronizeInstruction();
+// 5.3.1 Insert Count Increment
+const QpackInstruction* InsertCountIncrementInstruction();
// 5.3.2 Header Acknowledgement
const QpackInstruction* HeaderAcknowledgementInstruction();
diff --git a/quic/core/qpack/qpack_decoder.cc b/quic/core/qpack/qpack_decoder.cc
index 9ae883f..fd0867a 100644
--- a/quic/core/qpack/qpack_decoder.cc
+++ b/quic/core/qpack/qpack_decoder.cc
@@ -4,6 +4,8 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_decoder.h"
+#include <limits>
+
#include "base/logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
@@ -40,33 +42,36 @@
if (is_static) {
auto entry = header_table_.LookupEntry(/* is_static = */ true, name_index);
if (!entry) {
- encoder_stream_error_delegate_->OnError("Invalid static table entry.");
+ encoder_stream_error_delegate_->OnEncoderStreamError(
+ "Invalid static table entry.");
return;
}
entry = header_table_.InsertEntry(entry->name(), value);
if (!entry) {
- encoder_stream_error_delegate_->OnError(
+ encoder_stream_error_delegate_->OnEncoderStreamError(
"Error inserting entry with name reference.");
}
return;
}
- uint64_t real_index;
- if (!EncoderStreamRelativeIndexToRealIndex(name_index, &real_index)) {
- encoder_stream_error_delegate_->OnError("Invalid relative index.");
+ uint64_t absolute_index;
+ if (!EncoderStreamRelativeIndexToAbsoluteIndex(name_index, &absolute_index)) {
+ encoder_stream_error_delegate_->OnEncoderStreamError(
+ "Invalid relative index.");
return;
}
const QpackEntry* entry =
- header_table_.LookupEntry(/* is_static = */ false, real_index);
+ header_table_.LookupEntry(/* is_static = */ false, absolute_index);
if (!entry) {
- encoder_stream_error_delegate_->OnError("Dynamic table entry not found.");
+ encoder_stream_error_delegate_->OnEncoderStreamError(
+ "Dynamic table entry not found.");
return;
}
entry = header_table_.InsertEntry(entry->name(), value);
if (!entry) {
- encoder_stream_error_delegate_->OnError(
+ encoder_stream_error_delegate_->OnEncoderStreamError(
"Error inserting entry with name reference.");
}
}
@@ -75,50 +80,54 @@
QuicStringPiece value) {
const QpackEntry* entry = header_table_.InsertEntry(name, value);
if (!entry) {
- encoder_stream_error_delegate_->OnError("Error inserting literal entry.");
+ encoder_stream_error_delegate_->OnEncoderStreamError(
+ "Error inserting literal entry.");
}
}
void QpackDecoder::OnDuplicate(uint64_t index) {
- uint64_t real_index;
- if (!EncoderStreamRelativeIndexToRealIndex(index, &real_index)) {
- encoder_stream_error_delegate_->OnError("Invalid relative index.");
+ uint64_t absolute_index;
+ if (!EncoderStreamRelativeIndexToAbsoluteIndex(index, &absolute_index)) {
+ encoder_stream_error_delegate_->OnEncoderStreamError(
+ "Invalid relative index.");
return;
}
const QpackEntry* entry =
- header_table_.LookupEntry(/* is_static = */ false, real_index);
+ header_table_.LookupEntry(/* is_static = */ false, absolute_index);
if (!entry) {
- encoder_stream_error_delegate_->OnError("Dynamic table entry not found.");
+ encoder_stream_error_delegate_->OnEncoderStreamError(
+ "Dynamic table entry not found.");
return;
}
entry = header_table_.InsertEntry(entry->name(), entry->value());
if (!entry) {
- encoder_stream_error_delegate_->OnError("Error inserting duplicate entry.");
+ encoder_stream_error_delegate_->OnEncoderStreamError(
+ "Error inserting duplicate entry.");
}
}
-void QpackDecoder::OnDynamicTableSizeUpdate(uint64_t max_size) {
- if (!header_table_.UpdateTableSize(max_size)) {
- encoder_stream_error_delegate_->OnError(
- "Error updating dynamic table size.");
+void QpackDecoder::OnSetDynamicTableCapacity(uint64_t capacity) {
+ if (!header_table_.SetDynamicTableCapacity(capacity)) {
+ encoder_stream_error_delegate_->OnEncoderStreamError(
+ "Error updating dynamic table capacity.");
}
}
void QpackDecoder::OnErrorDetected(QuicStringPiece error_message) {
- encoder_stream_error_delegate_->OnError(error_message);
+ encoder_stream_error_delegate_->OnEncoderStreamError(error_message);
}
-bool QpackDecoder::EncoderStreamRelativeIndexToRealIndex(
+bool QpackDecoder::EncoderStreamRelativeIndexToAbsoluteIndex(
uint64_t relative_index,
- uint64_t* real_index) const {
+ uint64_t* absolute_index) const {
if (relative_index == std::numeric_limits<uint64_t>::max() ||
relative_index + 1 > std::numeric_limits<uint64_t>::max() -
header_table_.inserted_entry_count()) {
return false;
}
- *real_index = header_table_.inserted_entry_count() - relative_index - 1;
+ *absolute_index = header_table_.inserted_entry_count() - relative_index - 1;
return true;
}
diff --git a/quic/core/qpack/qpack_decoder.h b/quic/core/qpack/qpack_decoder.h
index ffb2e88..c3b28a3 100644
--- a/quic/core/qpack/qpack_decoder.h
+++ b/quic/core/qpack/qpack_decoder.h
@@ -31,7 +31,7 @@
public:
virtual ~EncoderStreamErrorDelegate() {}
- virtual void OnError(QuicStringPiece error_message) = 0;
+ virtual void OnEncoderStreamError(QuicStringPiece error_message) = 0;
};
QpackDecoder(
@@ -79,18 +79,17 @@
void OnInsertWithoutNameReference(QuicStringPiece name,
QuicStringPiece value) override;
void OnDuplicate(uint64_t index) override;
- void OnDynamicTableSizeUpdate(uint64_t max_size) override;
+ void OnSetDynamicTableCapacity(uint64_t capacity) override;
void OnErrorDetected(QuicStringPiece error_message) override;
private:
// The encoder stream uses relative index (but different from the kind of
- // relative index used on a request stream).
- // The spec describes how to convert these into absolute index (one based).
- // QpackHeaderTable uses real index (zero based, one less than the absolute
- // index). This method converts relative index to real index. It returns
- // true on success, or false if conversion fails due to overflow/underflow.
- bool EncoderStreamRelativeIndexToRealIndex(uint64_t relative_index,
- uint64_t* real_index) const;
+ // relative index used on a request stream). This method converts relative
+ // index to absolute index (zero based). It returns true on success, or false
+ // if conversion fails due to overflow/underflow.
+ bool EncoderStreamRelativeIndexToAbsoluteIndex(
+ uint64_t relative_index,
+ uint64_t* absolute_index) const;
EncoderStreamErrorDelegate* const encoder_stream_error_delegate_;
QpackEncoderStreamReceiver encoder_stream_receiver_;
diff --git a/quic/core/qpack/qpack_decoder_stream_receiver.cc b/quic/core/qpack/qpack_decoder_stream_receiver.cc
index b38aedf..559ce43 100644
--- a/quic/core/qpack/qpack_decoder_stream_receiver.cc
+++ b/quic/core/qpack/qpack_decoder_stream_receiver.cc
@@ -27,8 +27,8 @@
bool QpackDecoderStreamReceiver::OnInstructionDecoded(
const QpackInstruction* instruction) {
- if (instruction == TableStateSynchronizeInstruction()) {
- delegate_->OnTableStateSynchronize(instruction_decoder_.varint());
+ if (instruction == InsertCountIncrementInstruction()) {
+ delegate_->OnInsertCountIncrement(instruction_decoder_.varint());
return true;
}
diff --git a/quic/core/qpack/qpack_decoder_stream_receiver.h b/quic/core/qpack/qpack_decoder_stream_receiver.h
index 003be12..61c2773 100644
--- a/quic/core/qpack/qpack_decoder_stream_receiver.h
+++ b/quic/core/qpack/qpack_decoder_stream_receiver.h
@@ -25,8 +25,8 @@
public:
virtual ~Delegate() = default;
- // 5.3.1 Table State Synchronize
- virtual void OnTableStateSynchronize(uint64_t insert_count) = 0;
+ // 5.3.1 Insert Count Increment
+ virtual void OnInsertCountIncrement(uint64_t increment) = 0;
// 5.3.2 Header Acknowledgement
virtual void OnHeaderAcknowledgement(QuicStreamId stream_id) = 0;
// 5.3.3 Stream Cancellation
diff --git a/quic/core/qpack/qpack_decoder_stream_receiver_test.cc b/quic/core/qpack/qpack_decoder_stream_receiver_test.cc
index e9b3124..fc7225f 100644
--- a/quic/core/qpack/qpack_decoder_stream_receiver_test.cc
+++ b/quic/core/qpack/qpack_decoder_stream_receiver_test.cc
@@ -9,6 +9,7 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+using testing::Eq;
using testing::StrictMock;
namespace quic {
@@ -19,7 +20,7 @@
public:
~MockDelegate() override = default;
- MOCK_METHOD1(OnTableStateSynchronize, void(uint64_t insert_count));
+ MOCK_METHOD1(OnInsertCountIncrement, void(uint64_t increment));
MOCK_METHOD1(OnHeaderAcknowledgement, void(QuicStreamId stream_id));
MOCK_METHOD1(OnStreamCancellation, void(QuicStreamId stream_id));
MOCK_METHOD1(OnErrorDetected, void(QuicStringPiece error_message));
@@ -34,20 +35,20 @@
StrictMock<MockDelegate> delegate_;
};
-TEST_F(QpackDecoderStreamReceiverTest, TableStateSynchronize) {
- EXPECT_CALL(delegate_, OnTableStateSynchronize(0));
+TEST_F(QpackDecoderStreamReceiverTest, InsertCountIncrement) {
+ EXPECT_CALL(delegate_, OnInsertCountIncrement(0));
stream_.Decode(QuicTextUtils::HexDecode("00"));
- EXPECT_CALL(delegate_, OnTableStateSynchronize(10));
+ EXPECT_CALL(delegate_, OnInsertCountIncrement(10));
stream_.Decode(QuicTextUtils::HexDecode("0a"));
- EXPECT_CALL(delegate_, OnTableStateSynchronize(63));
+ EXPECT_CALL(delegate_, OnInsertCountIncrement(63));
stream_.Decode(QuicTextUtils::HexDecode("3f00"));
- EXPECT_CALL(delegate_, OnTableStateSynchronize(200));
+ EXPECT_CALL(delegate_, OnInsertCountIncrement(200));
stream_.Decode(QuicTextUtils::HexDecode("3f8901"));
- EXPECT_CALL(delegate_, OnErrorDetected("Encoded integer too large."));
+ EXPECT_CALL(delegate_, OnErrorDetected(Eq("Encoded integer too large.")));
stream_.Decode(QuicTextUtils::HexDecode("3fffffffffffffffffffff"));
}
@@ -64,7 +65,7 @@
EXPECT_CALL(delegate_, OnHeaderAcknowledgement(503));
stream_.Decode(QuicTextUtils::HexDecode("fff802"));
- EXPECT_CALL(delegate_, OnErrorDetected("Encoded integer too large."));
+ EXPECT_CALL(delegate_, OnErrorDetected(Eq("Encoded integer too large.")));
stream_.Decode(QuicTextUtils::HexDecode("ffffffffffffffffffffff"));
}
@@ -81,7 +82,7 @@
EXPECT_CALL(delegate_, OnStreamCancellation(110));
stream_.Decode(QuicTextUtils::HexDecode("7f2f"));
- EXPECT_CALL(delegate_, OnErrorDetected("Encoded integer too large."));
+ EXPECT_CALL(delegate_, OnErrorDetected(Eq("Encoded integer too large.")));
stream_.Decode(QuicTextUtils::HexDecode("7fffffffffffffffffffff"));
}
diff --git a/quic/core/qpack/qpack_decoder_stream_sender.cc b/quic/core/qpack/qpack_decoder_stream_sender.cc
index 48d0e0e..141b64a 100644
--- a/quic/core/qpack/qpack_decoder_stream_sender.cc
+++ b/quic/core/qpack/qpack_decoder_stream_sender.cc
@@ -18,18 +18,17 @@
DCHECK(delegate_);
}
-void QpackDecoderStreamSender::SendTableStateSynchronize(
- uint64_t insert_count) {
- instruction_encoder_.set_varint(insert_count);
+void QpackDecoderStreamSender::SendInsertCountIncrement(uint64_t increment) {
+ instruction_encoder_.set_varint(increment);
- instruction_encoder_.Encode(TableStateSynchronizeInstruction());
+ instruction_encoder_.Encode(InsertCountIncrementInstruction());
QuicString output;
instruction_encoder_.Next(std::numeric_limits<size_t>::max(), &output);
DCHECK(!instruction_encoder_.HasNext());
- delegate_->Write(output);
+ delegate_->WriteDecoderStreamData(output);
}
void QpackDecoderStreamSender::SendHeaderAcknowledgement(
@@ -43,7 +42,7 @@
instruction_encoder_.Next(std::numeric_limits<size_t>::max(), &output);
DCHECK(!instruction_encoder_.HasNext());
- delegate_->Write(output);
+ delegate_->WriteDecoderStreamData(output);
}
void QpackDecoderStreamSender::SendStreamCancellation(QuicStreamId stream_id) {
@@ -56,7 +55,7 @@
instruction_encoder_.Next(std::numeric_limits<size_t>::max(), &output);
DCHECK(!instruction_encoder_.HasNext());
- delegate_->Write(output);
+ delegate_->WriteDecoderStreamData(output);
}
} // namespace quic
diff --git a/quic/core/qpack/qpack_decoder_stream_sender.h b/quic/core/qpack/qpack_decoder_stream_sender.h
index 0522042..a791173 100644
--- a/quic/core/qpack/qpack_decoder_stream_sender.h
+++ b/quic/core/qpack/qpack_decoder_stream_sender.h
@@ -24,9 +24,10 @@
virtual ~Delegate() = default;
// Encoded |data| is ready to be written on the decoder stream.
- // Write() is called exactly once for each instruction, |data| contains the
- // entire encoded instruction and it is guaranteed to be not empty.
- virtual void Write(QuicStringPiece data) = 0;
+ // WriteDecoderStreamData() is called exactly once for each instruction.
+ // |data| contains the entire encoded instruction and it is guaranteed to be
+ // not empty.
+ virtual void WriteDecoderStreamData(QuicStringPiece data) = 0;
};
explicit QpackDecoderStreamSender(Delegate* delegate);
@@ -37,8 +38,8 @@
// Methods for sending instructions, see
// https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#rfc.section.5.3
- // 5.3.1 Table State Synchronize
- void SendTableStateSynchronize(uint64_t insert_count);
+ // 5.3.1 Insert Count Increment
+ void SendInsertCountIncrement(uint64_t increment);
// 5.3.2 Header Acknowledgement
void SendHeaderAcknowledgement(QuicStreamId stream_id);
// 5.3.3 Stream Cancellation
diff --git a/quic/core/qpack/qpack_decoder_stream_sender_test.cc b/quic/core/qpack/qpack_decoder_stream_sender_test.cc
index ab65c8c..cc95759 100644
--- a/quic/core/qpack/qpack_decoder_stream_sender_test.cc
+++ b/quic/core/qpack/qpack_decoder_stream_sender_test.cc
@@ -9,6 +9,7 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+using ::testing::Eq;
using ::testing::StrictMock;
namespace quic {
@@ -19,7 +20,7 @@
public:
~MockSenderDelegate() override = default;
- MOCK_METHOD1(Write, void(QuicStringPiece data));
+ MOCK_METHOD1(WriteDecoderStreamData, void(QuicStringPiece data));
};
class QpackDecoderStreamSenderTest : public QuicTest {
@@ -31,45 +32,57 @@
QpackDecoderStreamSender stream_;
};
-TEST_F(QpackDecoderStreamSenderTest, TableStateSynchronize) {
- EXPECT_CALL(delegate_, Write(QuicTextUtils::HexDecode("00")));
- stream_.SendTableStateSynchronize(0);
+TEST_F(QpackDecoderStreamSenderTest, InsertCountIncrement) {
+ EXPECT_CALL(delegate_,
+ WriteDecoderStreamData(Eq(QuicTextUtils::HexDecode("00"))));
+ stream_.SendInsertCountIncrement(0);
- EXPECT_CALL(delegate_, Write(QuicTextUtils::HexDecode("0a")));
- stream_.SendTableStateSynchronize(10);
+ EXPECT_CALL(delegate_,
+ WriteDecoderStreamData(Eq(QuicTextUtils::HexDecode("0a"))));
+ stream_.SendInsertCountIncrement(10);
- EXPECT_CALL(delegate_, Write(QuicTextUtils::HexDecode("3f00")));
- stream_.SendTableStateSynchronize(63);
+ EXPECT_CALL(delegate_,
+ WriteDecoderStreamData(Eq(QuicTextUtils::HexDecode("3f00"))));
+ stream_.SendInsertCountIncrement(63);
- EXPECT_CALL(delegate_, Write(QuicTextUtils::HexDecode("3f8901")));
- stream_.SendTableStateSynchronize(200);
+ EXPECT_CALL(delegate_,
+ WriteDecoderStreamData(Eq(QuicTextUtils::HexDecode("3f8901"))));
+ stream_.SendInsertCountIncrement(200);
}
TEST_F(QpackDecoderStreamSenderTest, HeaderAcknowledgement) {
- EXPECT_CALL(delegate_, Write(QuicTextUtils::HexDecode("80")));
+ EXPECT_CALL(delegate_,
+ WriteDecoderStreamData(Eq(QuicTextUtils::HexDecode("80"))));
stream_.SendHeaderAcknowledgement(0);
- EXPECT_CALL(delegate_, Write(QuicTextUtils::HexDecode("a5")));
+ EXPECT_CALL(delegate_,
+ WriteDecoderStreamData(Eq(QuicTextUtils::HexDecode("a5"))));
stream_.SendHeaderAcknowledgement(37);
- EXPECT_CALL(delegate_, Write(QuicTextUtils::HexDecode("ff00")));
+ EXPECT_CALL(delegate_,
+ WriteDecoderStreamData(Eq(QuicTextUtils::HexDecode("ff00"))));
stream_.SendHeaderAcknowledgement(127);
- EXPECT_CALL(delegate_, Write(QuicTextUtils::HexDecode("fff802")));
+ EXPECT_CALL(delegate_,
+ WriteDecoderStreamData(Eq(QuicTextUtils::HexDecode("fff802"))));
stream_.SendHeaderAcknowledgement(503);
}
TEST_F(QpackDecoderStreamSenderTest, StreamCancellation) {
- EXPECT_CALL(delegate_, Write(QuicTextUtils::HexDecode("40")));
+ EXPECT_CALL(delegate_,
+ WriteDecoderStreamData(Eq(QuicTextUtils::HexDecode("40"))));
stream_.SendStreamCancellation(0);
- EXPECT_CALL(delegate_, Write(QuicTextUtils::HexDecode("53")));
+ EXPECT_CALL(delegate_,
+ WriteDecoderStreamData(Eq(QuicTextUtils::HexDecode("53"))));
stream_.SendStreamCancellation(19);
- EXPECT_CALL(delegate_, Write(QuicTextUtils::HexDecode("7f00")));
+ EXPECT_CALL(delegate_,
+ WriteDecoderStreamData(Eq(QuicTextUtils::HexDecode("7f00"))));
stream_.SendStreamCancellation(63);
- EXPECT_CALL(delegate_, Write(QuicTextUtils::HexDecode("7f2f")));
+ EXPECT_CALL(delegate_,
+ WriteDecoderStreamData(Eq(QuicTextUtils::HexDecode("7f2f"))));
stream_.SendStreamCancellation(110);
}
diff --git a/quic/core/qpack/qpack_decoder_test.cc b/quic/core/qpack/qpack_decoder_test.cc
index 5f68213..52f739c 100644
--- a/quic/core/qpack/qpack_decoder_test.cc
+++ b/quic/core/qpack/qpack_decoder_test.cc
@@ -4,6 +4,8 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_decoder.h"
+#include <algorithm>
+
#include "base/logging.h"
#include "net/third_party/quiche/src/quic/core/qpack/qpack_decoder_test_utils.h"
#include "net/third_party/quiche/src/quic/core/qpack/qpack_test_utils.h"
@@ -66,8 +68,8 @@
FragmentMode::kOctetByOctet));
TEST_P(QpackDecoderTest, NoPrefix) {
- EXPECT_CALL(handler_, OnDecodingErrorDetected(
- QuicStringPiece("Incomplete header data prefix.")));
+ EXPECT_CALL(handler_,
+ OnDecodingErrorDetected(Eq("Incomplete header data prefix.")));
// Header Data Prefix is at least two bytes long.
DecodeHeaderBlock(QuicTextUtils::HexDecode("00"));
@@ -76,60 +78,54 @@
TEST_P(QpackDecoderTest, EmptyHeaderBlock) {
EXPECT_CALL(handler_, OnDecodingCompleted());
EXPECT_CALL(decoder_stream_sender_delegate_,
- Write(Eq(kHeaderAcknowledgement)));
+ WriteDecoderStreamData(Eq(kHeaderAcknowledgement)));
DecodeHeaderBlock(QuicTextUtils::HexDecode("0000"));
}
TEST_P(QpackDecoderTest, LiteralEntryEmptyName) {
- EXPECT_CALL(handler_,
- OnHeaderDecoded(QuicStringPiece(""), QuicStringPiece("foo")));
+ EXPECT_CALL(handler_, OnHeaderDecoded(Eq(""), Eq("foo")));
EXPECT_CALL(handler_, OnDecodingCompleted());
EXPECT_CALL(decoder_stream_sender_delegate_,
- Write(Eq(kHeaderAcknowledgement)));
+ WriteDecoderStreamData(Eq(kHeaderAcknowledgement)));
DecodeHeaderBlock(QuicTextUtils::HexDecode("00002003666f6f"));
}
TEST_P(QpackDecoderTest, LiteralEntryEmptyValue) {
- EXPECT_CALL(handler_,
- OnHeaderDecoded(QuicStringPiece("foo"), QuicStringPiece("")));
+ EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("")));
EXPECT_CALL(handler_, OnDecodingCompleted());
EXPECT_CALL(decoder_stream_sender_delegate_,
- Write(Eq(kHeaderAcknowledgement)));
+ WriteDecoderStreamData(Eq(kHeaderAcknowledgement)));
DecodeHeaderBlock(QuicTextUtils::HexDecode("000023666f6f00"));
}
TEST_P(QpackDecoderTest, LiteralEntryEmptyNameAndValue) {
- EXPECT_CALL(handler_,
- OnHeaderDecoded(QuicStringPiece(""), QuicStringPiece("")));
+ EXPECT_CALL(handler_, OnHeaderDecoded(Eq(""), Eq("")));
EXPECT_CALL(handler_, OnDecodingCompleted());
EXPECT_CALL(decoder_stream_sender_delegate_,
- Write(Eq(kHeaderAcknowledgement)));
+ WriteDecoderStreamData(Eq(kHeaderAcknowledgement)));
DecodeHeaderBlock(QuicTextUtils::HexDecode("00002000"));
}
TEST_P(QpackDecoderTest, SimpleLiteralEntry) {
- EXPECT_CALL(handler_,
- OnHeaderDecoded(QuicStringPiece("foo"), QuicStringPiece("bar")));
+ EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("bar")));
EXPECT_CALL(handler_, OnDecodingCompleted());
EXPECT_CALL(decoder_stream_sender_delegate_,
- Write(Eq(kHeaderAcknowledgement)));
+ WriteDecoderStreamData(Eq(kHeaderAcknowledgement)));
DecodeHeaderBlock(QuicTextUtils::HexDecode("000023666f6f03626172"));
}
TEST_P(QpackDecoderTest, MultipleLiteralEntries) {
- EXPECT_CALL(handler_,
- OnHeaderDecoded(QuicStringPiece("foo"), QuicStringPiece("bar")));
+ EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("bar")));
QuicString str(127, 'a');
- EXPECT_CALL(handler_, OnHeaderDecoded(QuicStringPiece("foobaar"),
- QuicStringPiece(str)));
+ EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foobaar"), QuicStringPiece(str)));
EXPECT_CALL(handler_, OnDecodingCompleted());
EXPECT_CALL(decoder_stream_sender_delegate_,
- Write(Eq(kHeaderAcknowledgement)));
+ WriteDecoderStreamData(Eq(kHeaderAcknowledgement)));
DecodeHeaderBlock(QuicTextUtils::HexDecode(
"0000" // prefix
@@ -146,24 +142,24 @@
// Name Length value is too large for varint decoder to decode.
TEST_P(QpackDecoderTest, NameLenTooLargeForVarintDecoder) {
- EXPECT_CALL(handler_, OnDecodingErrorDetected(
- QuicStringPiece("Encoded integer too large.")));
+ EXPECT_CALL(handler_,
+ OnDecodingErrorDetected(Eq("Encoded integer too large.")));
DecodeHeaderBlock(QuicTextUtils::HexDecode("000027ffffffffffffffffffff"));
}
// Name Length value can be decoded by varint decoder but exceeds 1 MB limit.
TEST_P(QpackDecoderTest, NameLenExceedsLimit) {
- EXPECT_CALL(handler_, OnDecodingErrorDetected(
- QuicStringPiece("String literal too long.")));
+ EXPECT_CALL(handler_,
+ OnDecodingErrorDetected(Eq("String literal too long.")));
DecodeHeaderBlock(QuicTextUtils::HexDecode("000027ffff7f"));
}
// Value Length value is too large for varint decoder to decode.
TEST_P(QpackDecoderTest, ValueLenTooLargeForVarintDecoder) {
- EXPECT_CALL(handler_, OnDecodingErrorDetected(
- QuicStringPiece("Encoded integer too large.")));
+ EXPECT_CALL(handler_,
+ OnDecodingErrorDetected(Eq("Encoded integer too large.")));
DecodeHeaderBlock(
QuicTextUtils::HexDecode("000023666f6f7fffffffffffffffffffff"));
@@ -171,37 +167,35 @@
// Value Length value can be decoded by varint decoder but exceeds 1 MB limit.
TEST_P(QpackDecoderTest, ValueLenExceedsLimit) {
- EXPECT_CALL(handler_, OnDecodingErrorDetected(
- QuicStringPiece("String literal too long.")));
+ EXPECT_CALL(handler_,
+ OnDecodingErrorDetected(Eq("String literal too long.")));
DecodeHeaderBlock(QuicTextUtils::HexDecode("000023666f6f7fffff7f"));
}
TEST_P(QpackDecoderTest, IncompleteHeaderBlock) {
- EXPECT_CALL(handler_, OnDecodingErrorDetected(
- QuicStringPiece("Incomplete header block.")));
+ EXPECT_CALL(handler_,
+ OnDecodingErrorDetected(Eq("Incomplete header block.")));
DecodeHeaderBlock(QuicTextUtils::HexDecode("00002366"));
}
TEST_P(QpackDecoderTest, HuffmanSimple) {
- EXPECT_CALL(handler_, OnHeaderDecoded(QuicStringPiece("custom-key"),
- QuicStringPiece("custom-value")));
+ EXPECT_CALL(handler_, OnHeaderDecoded(Eq("custom-key"), Eq("custom-value")));
EXPECT_CALL(handler_, OnDecodingCompleted());
EXPECT_CALL(decoder_stream_sender_delegate_,
- Write(Eq(kHeaderAcknowledgement)));
+ WriteDecoderStreamData(Eq(kHeaderAcknowledgement)));
- DecodeHeaderBlock(QuicTextUtils::HexDecode(
- QuicStringPiece("00002f0125a849e95ba97d7f8925a849e95bb8e8b4bf")));
+ DecodeHeaderBlock(
+ QuicTextUtils::HexDecode("00002f0125a849e95ba97d7f8925a849e95bb8e8b4bf"));
}
TEST_P(QpackDecoderTest, AlternatingHuffmanNonHuffman) {
- EXPECT_CALL(handler_, OnHeaderDecoded(QuicStringPiece("custom-key"),
- QuicStringPiece("custom-value")))
+ EXPECT_CALL(handler_, OnHeaderDecoded(Eq("custom-key"), Eq("custom-value")))
.Times(4);
EXPECT_CALL(handler_, OnDecodingCompleted());
EXPECT_CALL(decoder_stream_sender_delegate_,
- Write(Eq(kHeaderAcknowledgement)));
+ WriteDecoderStreamData(Eq(kHeaderAcknowledgement)));
DecodeHeaderBlock(QuicTextUtils::HexDecode(
"0000" // Prefix.
@@ -212,8 +206,7 @@
"2f0125a849e95ba97d7f" // Huffman-encoded name.
"0c637573746f6d2d76616c7565" // Non-Huffman encoded value.
"2703637573746f6d2d6b6579" // Non-Huffman encoded name.
- "8925a849e95bb8e8b4bf" // Huffman-encoded value.
- ));
+ "8925a849e95bb8e8b4bf")); // Huffman-encoded value.
}
TEST_P(QpackDecoderTest, HuffmanNameDoesNotHaveEOSPrefix) {
@@ -260,30 +253,23 @@
TEST_P(QpackDecoderTest, StaticTable) {
// A header name that has multiple entries with different values.
- EXPECT_CALL(handler_, OnHeaderDecoded(QuicStringPiece(":method"),
- QuicStringPiece("GET")));
- EXPECT_CALL(handler_, OnHeaderDecoded(QuicStringPiece(":method"),
- QuicStringPiece("POST")));
- EXPECT_CALL(handler_, OnHeaderDecoded(QuicStringPiece(":method"),
- QuicStringPiece("TRACE")));
+ EXPECT_CALL(handler_, OnHeaderDecoded(Eq(":method"), Eq("GET")));
+ EXPECT_CALL(handler_, OnHeaderDecoded(Eq(":method"), Eq("POST")));
+ EXPECT_CALL(handler_, OnHeaderDecoded(Eq(":method"), Eq("TRACE")));
// A header name that has a single entry with non-empty value.
- EXPECT_CALL(handler_, OnHeaderDecoded(QuicStringPiece("accept-encoding"),
- QuicStringPiece("gzip, deflate, br")));
- EXPECT_CALL(handler_, OnHeaderDecoded(QuicStringPiece("accept-encoding"),
- QuicStringPiece("compress")));
- EXPECT_CALL(handler_, OnHeaderDecoded(QuicStringPiece("accept-encoding"),
- QuicStringPiece("")));
+ EXPECT_CALL(handler_,
+ OnHeaderDecoded(Eq("accept-encoding"), Eq("gzip, deflate, br")));
+ EXPECT_CALL(handler_, OnHeaderDecoded(Eq("accept-encoding"), Eq("compress")));
+ EXPECT_CALL(handler_, OnHeaderDecoded(Eq("accept-encoding"), Eq("")));
// A header name that has a single entry with empty value.
- EXPECT_CALL(handler_, OnHeaderDecoded(QuicStringPiece("location"),
- QuicStringPiece("")));
- EXPECT_CALL(handler_, OnHeaderDecoded(QuicStringPiece("location"),
- QuicStringPiece("foo")));
+ EXPECT_CALL(handler_, OnHeaderDecoded(Eq("location"), Eq("")));
+ EXPECT_CALL(handler_, OnHeaderDecoded(Eq("location"), Eq("foo")));
EXPECT_CALL(handler_, OnDecodingCompleted());
EXPECT_CALL(decoder_stream_sender_delegate_,
- Write(Eq(kHeaderAcknowledgement)));
+ WriteDecoderStreamData(Eq(kHeaderAcknowledgement)));
DecodeHeaderBlock(QuicTextUtils::HexDecode(
"0000d1dfccd45f108621e9aec2a11f5c8294e75f000554524143455f1000"));
@@ -291,12 +277,12 @@
TEST_P(QpackDecoderTest, TooHighStaticTableIndex) {
// This is the last entry in the static table with index 98.
- EXPECT_CALL(handler_, OnHeaderDecoded(QuicStringPiece("x-frame-options"),
- QuicStringPiece("sameorigin")));
+ EXPECT_CALL(handler_,
+ OnHeaderDecoded(Eq("x-frame-options"), Eq("sameorigin")));
// Addressing entry 99 should trigger an error.
- EXPECT_CALL(handler_, OnDecodingErrorDetected(
- QuicStringPiece("Static table entry not found.")));
+ EXPECT_CALL(handler_,
+ OnDecodingErrorDetected(Eq("Static table entry not found.")));
DecodeHeaderBlock(QuicTextUtils::HexDecode("0000ff23ff24"));
}
@@ -311,11 +297,10 @@
"01")); // Duplicate entry with relative index 1.
// Now there are four entries in the dynamic table.
- // Note that absolute indices start with 1.
- // Entry 1: "foo", "bar"
- // Entry 2: "foo", "ZZZ"
- // Entry 3: ":method", "foo"
- // Entry 4: "foo", "ZZZ"
+ // Entry 0: "foo", "bar"
+ // Entry 1: "foo", "ZZZ"
+ // Entry 2: ":method", "foo"
+ // Entry 3: "foo", "ZZZ"
// Use a Sequence to test that mock methods are called in order.
Sequence s;
@@ -327,17 +312,17 @@
EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("ZZZ"))).InSequence(s);
EXPECT_CALL(handler_, OnHeaderDecoded(Eq(":method"), Eq("ZZ"))).InSequence(s);
EXPECT_CALL(decoder_stream_sender_delegate_,
- Write(Eq(kHeaderAcknowledgement)))
+ WriteDecoderStreamData(Eq(kHeaderAcknowledgement)))
.InSequence(s);
EXPECT_CALL(handler_, OnDecodingCompleted()).InSequence(s);
DecodeHeaderBlock(QuicTextUtils::HexDecode(
- "0500" // Largest Reference 4 and Delta Base Index 0.
- // Base Index is 4 + 0 = 4.
- "83" // Dynamic table entry with relative index 3, absolute index 1.
- "82" // Dynamic table entry with relative index 2, absolute index 2.
- "81" // Dynamic table entry with relative index 1, absolute index 3.
- "80" // Dynamic table entry with relative index 0, absolute index 4.
+ "0500" // Required Insert Count 4 and Delta Base 0.
+ // Base is 4 + 0 = 4.
+ "83" // Dynamic table entry with relative index 3, absolute index 0.
+ "82" // Dynamic table entry with relative index 2, absolute index 1.
+ "81" // Dynamic table entry with relative index 1, absolute index 2.
+ "80" // Dynamic table entry with relative index 0, absolute index 3.
"41025a5a")); // Name of entry 1 (relative index) from dynamic table,
// with value "ZZ".
@@ -348,17 +333,17 @@
EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("ZZZ"))).InSequence(s);
EXPECT_CALL(handler_, OnHeaderDecoded(Eq(":method"), Eq("ZZ"))).InSequence(s);
EXPECT_CALL(decoder_stream_sender_delegate_,
- Write(Eq(kHeaderAcknowledgement)))
+ WriteDecoderStreamData(Eq(kHeaderAcknowledgement)))
.InSequence(s);
EXPECT_CALL(handler_, OnDecodingCompleted()).InSequence(s);
DecodeHeaderBlock(QuicTextUtils::HexDecode(
- "0502" // Largest Reference 4 and Delta Base Index 2.
- // Base Index is 4 + 2 = 6.
- "85" // Dynamic table entry with relative index 5, absolute index 1.
- "84" // Dynamic table entry with relative index 4, absolute index 2.
- "83" // Dynamic table entry with relative index 3, absolute index 3.
- "82" // Dynamic table entry with relative index 2, absolute index 4.
+ "0502" // Required Insert Count 4 and Delta Base 2.
+ // Base is 4 + 2 = 6.
+ "85" // Dynamic table entry with relative index 5, absolute index 0.
+ "84" // Dynamic table entry with relative index 4, absolute index 1.
+ "83" // Dynamic table entry with relative index 3, absolute index 2.
+ "82" // Dynamic table entry with relative index 2, absolute index 3.
"43025a5a")); // Name of entry 3 (relative index) from dynamic table,
// with value "ZZ".
@@ -369,17 +354,17 @@
EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("ZZZ"))).InSequence(s);
EXPECT_CALL(handler_, OnHeaderDecoded(Eq(":method"), Eq("ZZ"))).InSequence(s);
EXPECT_CALL(decoder_stream_sender_delegate_,
- Write(Eq(kHeaderAcknowledgement)))
+ WriteDecoderStreamData(Eq(kHeaderAcknowledgement)))
.InSequence(s);
EXPECT_CALL(handler_, OnDecodingCompleted()).InSequence(s);
DecodeHeaderBlock(QuicTextUtils::HexDecode(
- "0582" // Largest Reference 4 and Delta Base Index 2 with sign bit set.
- // Base Index is 4 - 2 - 1 = 1.
- "80" // Dynamic table entry with relative index 0, absolute index 1.
- "10" // Dynamic table entry with post-base index 0, absolute index 2.
- "11" // Dynamic table entry with post-base index 1, absolute index 3.
- "12" // Dynamic table entry with post-base index 2, absolute index 4.
+ "0582" // Required Insert Count 4 and Delta Base 2 with sign bit set.
+ // Base is 4 - 2 - 1 = 1.
+ "80" // Dynamic table entry with relative index 0, absolute index 0.
+ "10" // Dynamic table entry with post-base index 0, absolute index 1.
+ "11" // Dynamic table entry with post-base index 1, absolute index 2.
+ "12" // Dynamic table entry with post-base index 2, absolute index 3.
"01025a5a")); // Name of entry 1 (post-base index) from dynamic table,
// with value "ZZ".
}
@@ -391,12 +376,12 @@
EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("bar")));
EXPECT_CALL(handler_, OnDecodingCompleted());
EXPECT_CALL(decoder_stream_sender_delegate_,
- Write(Eq(kHeaderAcknowledgement)));
+ WriteDecoderStreamData(Eq(kHeaderAcknowledgement)));
DecodeHeaderBlock(QuicTextUtils::HexDecode(
- "0200" // Largest Reference 1 and Delta Base Index 0.
- // Base Index is 1 + 0 = 1.
- "80")); // Dynamic table entry with relative index 0, absolute index 1.
+ "0200" // Required Insert Count 1 and Delta Base 0.
+ // Base is 1 + 0 = 1.
+ "80")); // Dynamic table entry with relative index 0, absolute index 0.
// Change dynamic table capacity to 32 bytes, smaller than the entry.
// This must cause the entry to be evicted.
@@ -406,14 +391,14 @@
OnDecodingErrorDetected(Eq("Dynamic table entry not found.")));
DecodeHeaderBlock(QuicTextUtils::HexDecode(
- "0200" // Largest Reference 1 and Delta Base Index 0.
- // Base Index is 1 + 0 = 1.
- "80")); // Dynamic table entry with relative index 0, absolute index 1.
+ "0200" // Required Insert Count 1 and Delta Base 0.
+ // Base is 1 + 0 = 1.
+ "80")); // Dynamic table entry with relative index 0, absolute index 0.
}
TEST_P(QpackDecoderTest, EncoderStreamErrorEntryTooLarge) {
EXPECT_CALL(encoder_stream_error_delegate_,
- OnError(Eq("Error inserting literal entry.")));
+ OnEncoderStreamError(Eq("Error inserting literal entry.")));
// Set dynamic table capacity to 34.
DecodeEncoderStreamData(QuicTextUtils::HexDecode("3f03"));
@@ -423,7 +408,7 @@
TEST_P(QpackDecoderTest, EncoderStreamErrorInvalidStaticTableEntry) {
EXPECT_CALL(encoder_stream_error_delegate_,
- OnError(Eq("Invalid static table entry.")));
+ OnEncoderStreamError(Eq("Invalid static table entry.")));
// Address invalid static table entry index 99.
DecodeEncoderStreamData(QuicTextUtils::HexDecode("ff2400"));
@@ -431,7 +416,7 @@
TEST_P(QpackDecoderTest, EncoderStreamErrorInvalidDynamicTableEntry) {
EXPECT_CALL(encoder_stream_error_delegate_,
- OnError(Eq("Dynamic table entry not found.")));
+ OnEncoderStreamError(Eq("Dynamic table entry not found.")));
DecodeEncoderStreamData(QuicTextUtils::HexDecode(
"6294e703626172" // Add literal entry with name "foo" and value "bar".
@@ -442,7 +427,7 @@
TEST_P(QpackDecoderTest, EncoderStreamErrorDuplicateInvalidEntry) {
EXPECT_CALL(encoder_stream_error_delegate_,
- OnError(Eq("Dynamic table entry not found.")));
+ OnEncoderStreamError(Eq("Dynamic table entry not found.")));
DecodeEncoderStreamData(QuicTextUtils::HexDecode(
"6294e703626172" // Add literal entry with name "foo" and value "bar".
@@ -453,27 +438,25 @@
TEST_P(QpackDecoderTest, EncoderStreamErrorTooLargeInteger) {
EXPECT_CALL(encoder_stream_error_delegate_,
- OnError(Eq("Encoded integer too large.")));
+ OnEncoderStreamError(Eq("Encoded integer too large.")));
DecodeEncoderStreamData(QuicTextUtils::HexDecode("3fffffffffffffffffffff"));
}
-TEST_P(QpackDecoderTest, InvalidDynamicEntryWhenBaseIndexIsZero) {
+TEST_P(QpackDecoderTest, InvalidDynamicEntryWhenBaseIsZero) {
EXPECT_CALL(handler_, OnDecodingErrorDetected(Eq("Invalid relative index.")));
DecodeHeaderBlock(QuicTextUtils::HexDecode(
- "0280" // Largest Reference is 1. Base Index 1 - 1 - 0 = 0 is explicitly
- // permitted by the spec.
+ "0280" // Required Insert Count is 1. Base 1 - 1 - 0 = 0 is explicitly
+ // permitted by the spec.
"80")); // However, addressing entry with relative index 0 would point to
- // absolute index 0, which is invalid (absolute index is one
- // based).
+ // absolute index -1, which is invalid.
}
-TEST_P(QpackDecoderTest, InvalidNegativeBaseIndex) {
- EXPECT_CALL(handler_,
- OnDecodingErrorDetected(Eq("Error calculating Base Index.")));
+TEST_P(QpackDecoderTest, InvalidNegativeBase) {
+ EXPECT_CALL(handler_, OnDecodingErrorDetected(Eq("Error calculating Base.")));
- // Largest reference 1, Delta Base Index 1 with sign bit set, Base Index would
+ // Required Insert Count 1, Delta Base 1 with sign bit set, Base would
// be 1 - 1 - 1 = -1, but it is not allowed to be negative.
DecodeHeaderBlock(QuicTextUtils::HexDecode("0281"));
}
@@ -486,38 +469,37 @@
OnDecodingErrorDetected(Eq("Dynamic table entry not found.")));
DecodeHeaderBlock(QuicTextUtils::HexDecode(
- "0500" // Largest Reference 4 and Delta Base Index 0.
- // Base Index is 4 + 0 = 4.
+ "0500" // Required Insert Count 4 and Delta Base 0.
+ // Base is 4 + 0 = 4.
"82")); // Indexed Header Field instruction addressing relative index 2.
- // This is absolute index 2. Such entry does not exist.
+ // This is absolute index 1. Such entry does not exist.
EXPECT_CALL(handler_, OnDecodingErrorDetected(Eq("Invalid relative index.")));
DecodeHeaderBlock(QuicTextUtils::HexDecode(
- "0500" // Largest Reference 4 and Delta Base Index 0.
- // Base Index is 4 + 0 = 4.
+ "0500" // Required Insert Count 4 and Delta Base 0.
+ // Base is 4 + 0 = 4.
"84")); // Indexed Header Field instruction addressing relative index 4.
- // This is absolute index 0, which is invalid, because absolute
- // indexing starts from 1.
+ // This is absolute index -1, which is invalid.
EXPECT_CALL(handler_,
OnDecodingErrorDetected(Eq("Dynamic table entry not found.")));
DecodeHeaderBlock(QuicTextUtils::HexDecode(
- "0500" // Largest Reference 4 and Delta Base Index 0.
- // Base Index is 4 + 0 = 4.
+ "0500" // Required Insert Count 4 and Delta Base 0.
+ // Base is 4 + 0 = 4.
"4200")); // Literal Header Field with Name Reference instruction
- // addressing relative index 2. This is absolute index 2. Such
+ // addressing relative index 2. This is absolute index 1. Such
// entry does not exist.
EXPECT_CALL(handler_, OnDecodingErrorDetected(Eq("Invalid relative index.")));
DecodeHeaderBlock(QuicTextUtils::HexDecode(
- "0500" // Largest Reference 4 and Delta Base Index 0.
- // Base Index is 4 + 0 = 4.
+ "0500" // Required Insert Count 4 and Delta Base 0.
+ // Base is 4 + 0 = 4.
"4400")); // Literal Header Field with Name Reference instruction
- // addressing relative index 4. This is absolute index 0,
- // which is invalid, because absolute indexing starts from 1.
+ // addressing relative index 4. This is absolute index -1,
+ // which is invalid.
}
TEST_P(QpackDecoderTest, InvalidDynamicEntryByPostBaseIndex) {
@@ -528,26 +510,27 @@
OnDecodingErrorDetected(Eq("Dynamic table entry not found.")));
DecodeHeaderBlock(QuicTextUtils::HexDecode(
- "0380" // Largest Reference 2 and Delta Base Index 0 with sign bit set.
- // Base Index is 2 - 0 - 1 = 1
+ "0380" // Required Insert Count 2 and Delta Base 0 with sign bit set.
+ // Base is 2 - 0 - 1 = 1
"10")); // Indexed Header Field instruction addressing dynamic table
- // entry with post-base index 0, absolute index 2. Such entry
+ // entry with post-base index 0, absolute index 1. Such entry
// does not exist.
EXPECT_CALL(handler_,
OnDecodingErrorDetected(Eq("Dynamic table entry not found.")));
DecodeHeaderBlock(QuicTextUtils::HexDecode(
- "0380" // Largest Reference 2 and Delta Base Index 0 with sign bit set.
- // Base Index is 2 - 0 - 1 = 1
+ "0380" // Required Insert Count 2 and Delta Base 0 with sign bit set.
+ // Base is 2 - 0 - 1 = 1
"0000")); // Literal Header Field With Name Reference instruction
// addressing dynamic table entry with post-base index 0,
- // absolute index 2. Such entry does not exist.
+ // absolute index 1. Such entry does not exist.
}
TEST_P(QpackDecoderTest, TableCapacityMustNotExceedMaximum) {
- EXPECT_CALL(encoder_stream_error_delegate_,
- OnError(Eq("Error updating dynamic table size.")));
+ EXPECT_CALL(
+ encoder_stream_error_delegate_,
+ OnEncoderStreamError(Eq("Error updating dynamic table capacity.")));
// Try to update dynamic table capacity to 2048, which exceeds the maximum.
DecodeEncoderStreamData(QuicTextUtils::HexDecode("3fe10f"));
@@ -558,17 +541,17 @@
DecodeEncoderStreamData(QuicTextUtils::HexDecode("3f61"));
}
-TEST_P(QpackDecoderTest, LargestReferenceOutOfRange) {
+TEST_P(QpackDecoderTest, InvalidEncodedRequiredInsertCount) {
// Maximum dynamic table capacity is 1024.
// MaxEntries is 1024 / 32 = 32.
- // Largest Reference is decoded modulo 2 * MaxEntries, that is, modulo 64.
+ // Required Insert Count is decoded modulo 2 * MaxEntries, that is, modulo 64.
// A value of 1 cannot be encoded as 65 even though it has the same remainder.
- EXPECT_CALL(handler_,
- OnDecodingErrorDetected(Eq("Error decoding Largest Reference.")));
+ EXPECT_CALL(handler_, OnDecodingErrorDetected(
+ Eq("Error decoding Required Insert Count.")));
DecodeHeaderBlock(QuicTextUtils::HexDecode("4100"));
}
-TEST_P(QpackDecoderTest, WrappedLargestReference) {
+TEST_P(QpackDecoderTest, WrappedRequiredInsertCount) {
// Maximum dynamic table capacity is 1024.
// MaxEntries is 1024 / 32 = 32.
@@ -583,131 +566,136 @@
// Duplicate most recent entry 200 times.
DecodeEncoderStreamData(QuicString(200, '\x00'));
- // Now there is only one entry in the dynamic table, with absolute index 201.
+ // Now there is only one entry in the dynamic table, with absolute index 200.
EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq(header_value)));
EXPECT_CALL(handler_, OnDecodingCompleted());
EXPECT_CALL(decoder_stream_sender_delegate_,
- Write(Eq(kHeaderAcknowledgement)));
+ WriteDecoderStreamData(Eq(kHeaderAcknowledgement)));
- // Send header block with Largest Reference = 201.
+ // Send header block with Required Insert Count = 201.
DecodeHeaderBlock(QuicTextUtils::HexDecode(
- "0a00" // Wire Largest Reference 10, Largest Reference 201,
- // Delta Base Index 0, Base Index 201.
+ "0a00" // Encoded Required Insert Count 10, Required Insert Count 201,
+ // Delta Base 0, Base 201.
"80")); // Emit dynamic table entry with relative index 0.
}
-TEST_P(QpackDecoderTest, NonZeroLargestReferenceButNoDynamicEntries) {
- EXPECT_CALL(handler_, OnHeaderDecoded(QuicStringPiece(":method"),
- QuicStringPiece("GET")));
+TEST_P(QpackDecoderTest, NonZeroRequiredInsertCountButNoDynamicEntries) {
+ EXPECT_CALL(handler_, OnHeaderDecoded(Eq(":method"), Eq("GET")));
EXPECT_CALL(handler_,
- OnDecodingErrorDetected(Eq("Largest Reference too large.")));
+ OnDecodingErrorDetected(Eq("Required Insert Count too large.")));
DecodeHeaderBlock(QuicTextUtils::HexDecode(
- "0200" // Largest Reference is 1.
+ "0200" // Required Insert Count is 1.
"d1")); // But the only instruction references the static table.
}
-TEST_P(QpackDecoderTest, AddressEntryBeyondLargestReference) {
- EXPECT_CALL(handler_, OnDecodingErrorDetected(
- Eq("Index larger than Largest Reference.")));
+TEST_P(QpackDecoderTest, AddressEntryNotAllowedByRequiredInsertCount) {
+ EXPECT_CALL(
+ handler_,
+ OnDecodingErrorDetected(
+ Eq("Absolute Index must be smaller than Required Insert Count.")));
DecodeHeaderBlock(QuicTextUtils::HexDecode(
- "0201" // Largest Reference 1 and Delta Base Index 1.
- // Base Index is 1 + 1 = 2.
+ "0201" // Required Insert Count 1 and Delta Base 1.
+ // Base is 1 + 1 = 2.
"80")); // Indexed Header Field instruction addressing dynamic table
- // entry with relative index 0, absolute index 2. This is beyond
- // Largest Reference.
+ // entry with relative index 0, absolute index 1. This is not
+ // allowed by Required Insert Count.
- EXPECT_CALL(handler_, OnDecodingErrorDetected(
- Eq("Index larger than Largest Reference.")));
+ EXPECT_CALL(
+ handler_,
+ OnDecodingErrorDetected(
+ Eq("Absolute Index must be smaller than Required Insert Count.")));
DecodeHeaderBlock(QuicTextUtils::HexDecode(
- "0201" // Largest Reference 1 and Delta Base Index 1.
- // Base Index is 1 + 1 = 2.
+ "0201" // Required Insert Count 1 and Delta Base 1.
+ // Base is 1 + 1 = 2.
"4000")); // Literal Header Field with Name Reference instruction
// addressing dynamic table entry with relative index 0,
- // absolute index 2. This is beyond Largest Reference.
+ // absolute index 1. This is not allowed by Required Index
+ // Count.
- EXPECT_CALL(handler_, OnDecodingErrorDetected(
- Eq("Index larger than Largest Reference.")));
+ EXPECT_CALL(
+ handler_,
+ OnDecodingErrorDetected(
+ Eq("Absolute Index must be smaller than Required Insert Count.")));
DecodeHeaderBlock(QuicTextUtils::HexDecode(
- "0200" // Largest Reference 1 and Delta Base Index 0.
- // Base Index is 1 + 0 = 1.
+ "0200" // Required Insert Count 1 and Delta Base 0.
+ // Base is 1 + 0 = 1.
"10")); // Indexed Header Field with Post-Base Index instruction
// addressing dynamic table entry with post-base index 0,
- // absolute index 2. This is beyond Largest Reference.
+ // absolute index 1. This is not allowed by Required Insert
+ // Count.
- EXPECT_CALL(handler_, OnDecodingErrorDetected(
- Eq("Index larger than Largest Reference.")));
+ EXPECT_CALL(
+ handler_,
+ OnDecodingErrorDetected(
+ Eq("Absolute Index must be smaller than Required Insert Count.")));
DecodeHeaderBlock(QuicTextUtils::HexDecode(
- "0200" // Largest Reference 1 and Delta Base Index 0.
- // Base Index is 1 + 0 = 1.
+ "0200" // Required Insert Count 1 and Delta Base 0.
+ // Base is 1 + 0 = 1.
"0000")); // Literal Header Field with Post-Base Name Reference
// instruction addressing dynamic table entry with post-base
- // index 0, absolute index 2. This is beyond Largest
- // Reference.
+ // index 0, absolute index 1. This is not allowed by Required
+ // Index Count.
}
-TEST_P(QpackDecoderTest, PromisedLargestReferenceLargerThanLargestActualIndex) {
+TEST_P(QpackDecoderTest, PromisedRequiredInsertCountLargerThanActual) {
// Add literal entry with name "foo" and value "bar".
DecodeEncoderStreamData(QuicTextUtils::HexDecode("6294e703626172"));
// Duplicate entry.
DecodeEncoderStreamData(QuicTextUtils::HexDecode("00"));
+ EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("bar")));
EXPECT_CALL(handler_,
- OnHeaderDecoded(QuicStringPiece("foo"), QuicStringPiece("bar")));
- EXPECT_CALL(handler_,
- OnDecodingErrorDetected(Eq("Largest Reference too large.")));
+ OnDecodingErrorDetected(Eq("Required Insert Count too large.")));
DecodeHeaderBlock(QuicTextUtils::HexDecode(
- "0300" // Largest Reference 2 and Delta Base Index 0.
- // Base Index is 2 + 0 = 2.
+ "0300" // Required Insert Count 2 and Delta Base 0.
+ // Base is 2 + 0 = 2.
"81")); // Indexed Header Field instruction addressing dynamic table
- // entry with relative index 1, absolute index 1. This is the
- // largest reference in this header block, even though Largest
- // Reference is 2.
+ // entry with relative index 1, absolute index 0. Header block
+ // requires insert count of 1, even though Required Insert Count
+ // is 2.
+ EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("")));
EXPECT_CALL(handler_,
- OnHeaderDecoded(QuicStringPiece("foo"), QuicStringPiece("")));
- EXPECT_CALL(handler_,
- OnDecodingErrorDetected(Eq("Largest Reference too large.")));
+ OnDecodingErrorDetected(Eq("Required Insert Count too large.")));
DecodeHeaderBlock(QuicTextUtils::HexDecode(
- "0300" // Largest Reference 2 and Delta Base Index 0.
- // Base Index is 2 + 0 = 2.
+ "0300" // Required Insert Count 2 and Delta Base 0.
+ // Base is 2 + 0 = 2.
"4100")); // Literal Header Field with Name Reference instruction
// addressing dynamic table entry with relative index 1,
- // absolute index 1. This is the largest reference in this
- // header block, even though Largest Reference is 2.
+ // absolute index 0. Header block requires insert count of 1,
+ // even though Required Insert Count is 2.
+ EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("bar")));
EXPECT_CALL(handler_,
- OnHeaderDecoded(QuicStringPiece("foo"), QuicStringPiece("bar")));
- EXPECT_CALL(handler_,
- OnDecodingErrorDetected(Eq("Largest Reference too large.")));
+ OnDecodingErrorDetected(Eq("Required Insert Count too large.")));
DecodeHeaderBlock(QuicTextUtils::HexDecode(
- "0481" // Largest Reference 3 and Delta Base Index 1 with sign bit set.
- // Base Index is 3 - 1 - 1 = 1.
+ "0481" // Required Insert Count 3 and Delta Base 1 with sign bit set.
+ // Base is 3 - 1 - 1 = 1.
"10")); // Indexed Header Field with Post-Base Index instruction
// addressing dynamic table entry with post-base index 0,
- // absolute index 2. This is the largest reference in this
- // header block, even though Largest Reference is 3.
+ // absolute index 1. Header block requires insert count of 2,
+ // even though Required Insert Count is 3.
+ EXPECT_CALL(handler_, OnHeaderDecoded(Eq("foo"), Eq("")));
EXPECT_CALL(handler_,
- OnHeaderDecoded(QuicStringPiece("foo"), QuicStringPiece("")));
- EXPECT_CALL(handler_,
- OnDecodingErrorDetected(Eq("Largest Reference too large.")));
+ OnDecodingErrorDetected(Eq("Required Insert Count too large.")));
DecodeHeaderBlock(QuicTextUtils::HexDecode(
- "0481" // Largest Reference 3 and Delta Base Index 1 with sign bit set.
- // Base Index is 3 - 1 - 1 = 1.
+ "0481" // Required Insert Count 3 and Delta Base 1 with sign bit set.
+ // Base is 3 - 1 - 1 = 1.
"0000")); // Literal Header Field with Post-Base Name Reference
// instruction addressing dynamic table entry with post-base
- // index 0, absolute index 2. This is the largest reference in
- // this header block, even though Largest Reference is 3.
+ // index 0, absolute index 1. Header block requires insert
+ // count of 2, even though Required Insert Count is 3.
}
} // namespace
diff --git a/quic/core/qpack/qpack_decoder_test_utils.cc b/quic/core/qpack/qpack_decoder_test_utils.cc
index 21a4606..e8bbd17 100644
--- a/quic/core/qpack/qpack_decoder_test_utils.cc
+++ b/quic/core/qpack/qpack_decoder_test_utils.cc
@@ -4,16 +4,20 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_decoder_test_utils.h"
+#include <algorithm>
#include <cstddef>
+#include <utility>
#include "testing/gmock/include/gmock/gmock.h"
namespace quic {
namespace test {
-void NoopEncoderStreamErrorDelegate::OnError(QuicStringPiece error_message) {}
+void NoopEncoderStreamErrorDelegate::OnEncoderStreamError(
+ QuicStringPiece error_message) {}
-void NoopDecoderStreamSenderDelegate::Write(QuicStringPiece data) {}
+void NoopDecoderStreamSenderDelegate::WriteDecoderStreamData(
+ QuicStringPiece data) {}
TestHeadersHandler::TestHeadersHandler()
: decoding_completed_(false), decoding_error_detected_(false) {}
diff --git a/quic/core/qpack/qpack_decoder_test_utils.h b/quic/core/qpack/qpack_decoder_test_utils.h
index 4896ce0..937ecfc 100644
--- a/quic/core/qpack/qpack_decoder_test_utils.h
+++ b/quic/core/qpack/qpack_decoder_test_utils.h
@@ -21,7 +21,7 @@
public:
~NoopEncoderStreamErrorDelegate() override = default;
- void OnError(QuicStringPiece error_message) override;
+ void OnEncoderStreamError(QuicStringPiece error_message) override;
};
// Mock QpackDecoder::EncoderStreamErrorDelegate implementation.
@@ -30,7 +30,7 @@
public:
~MockEncoderStreamErrorDelegate() override = default;
- MOCK_METHOD1(OnError, void(QuicStringPiece error_message));
+ MOCK_METHOD1(OnEncoderStreamError, void(QuicStringPiece error_message));
};
// QpackDecoderStreamSender::Delegate implementation that does nothing.
@@ -39,7 +39,7 @@
public:
~NoopDecoderStreamSenderDelegate() override = default;
- void Write(QuicStringPiece data) override;
+ void WriteDecoderStreamData(QuicStringPiece data) override;
};
// Mock QpackDecoderStreamSender::Delegate implementation.
@@ -48,7 +48,7 @@
public:
~MockDecoderStreamSenderDelegate() override = default;
- MOCK_METHOD1(Write, void(QuicStringPiece data));
+ MOCK_METHOD1(WriteDecoderStreamData, void(QuicStringPiece data));
};
// HeadersHandlerInterface implementation that collects decoded headers
diff --git a/quic/core/qpack/qpack_encoder.cc b/quic/core/qpack/qpack_encoder.cc
index 86f1785..6019229 100644
--- a/quic/core/qpack/qpack_encoder.cc
+++ b/quic/core/qpack/qpack_encoder.cc
@@ -35,7 +35,7 @@
decoder_stream_receiver_.Decode(data);
}
-void QpackEncoder::OnTableStateSynchronize(uint64_t insert_count) {
+void QpackEncoder::OnInsertCountIncrement(uint64_t increment) {
// TODO(bnc): Implement dynamic table management for encoding.
}
@@ -48,7 +48,7 @@
}
void QpackEncoder::OnErrorDetected(QuicStringPiece error_message) {
- decoder_stream_error_delegate_->OnError(error_message);
+ decoder_stream_error_delegate_->OnDecoderStreamError(error_message);
}
} // namespace quic
diff --git a/quic/core/qpack/qpack_encoder.h b/quic/core/qpack/qpack_encoder.h
index b7d7f20..4e65532 100644
--- a/quic/core/qpack/qpack_encoder.h
+++ b/quic/core/qpack/qpack_encoder.h
@@ -36,7 +36,7 @@
public:
virtual ~DecoderStreamErrorDelegate() {}
- virtual void OnError(QuicStringPiece error_message) = 0;
+ virtual void OnDecoderStreamError(QuicStringPiece error_message) = 0;
};
QpackEncoder(
@@ -55,7 +55,7 @@
void DecodeDecoderStreamData(QuicStringPiece data);
// QpackDecoderStreamReceiver::Delegate implementation
- void OnTableStateSynchronize(uint64_t insert_count) override;
+ void OnInsertCountIncrement(uint64_t increment) override;
void OnHeaderAcknowledgement(QuicStreamId stream_id) override;
void OnStreamCancellation(QuicStreamId stream_id) override;
void OnErrorDetected(QuicStringPiece error_message) override;
diff --git a/quic/core/qpack/qpack_encoder_stream_receiver.cc b/quic/core/qpack/qpack_encoder_stream_receiver.cc
index 008e357..3f8ef08 100644
--- a/quic/core/qpack/qpack_encoder_stream_receiver.cc
+++ b/quic/core/qpack/qpack_encoder_stream_receiver.cc
@@ -45,8 +45,8 @@
return true;
}
- DCHECK_EQ(instruction, DynamicTableSizeUpdateInstruction());
- delegate_->OnDynamicTableSizeUpdate(instruction_decoder_.varint());
+ DCHECK_EQ(instruction, SetDynamicTableCapacityInstruction());
+ delegate_->OnSetDynamicTableCapacity(instruction_decoder_.varint());
return true;
}
diff --git a/quic/core/qpack/qpack_encoder_stream_receiver.h b/quic/core/qpack/qpack_encoder_stream_receiver.h
index 7ce4f15..66a2985 100644
--- a/quic/core/qpack/qpack_encoder_stream_receiver.h
+++ b/quic/core/qpack/qpack_encoder_stream_receiver.h
@@ -33,8 +33,8 @@
QuicStringPiece value) = 0;
// 5.2.3. Duplicate
virtual void OnDuplicate(uint64_t index) = 0;
- // 5.2.4. Dynamic Table Size Update
- virtual void OnDynamicTableSizeUpdate(uint64_t max_size) = 0;
+ // 5.2.4. Set Dynamic Table Capacity
+ virtual void OnSetDynamicTableCapacity(uint64_t capacity) = 0;
// Decoding error
virtual void OnErrorDetected(QuicStringPiece error_message) = 0;
};
diff --git a/quic/core/qpack/qpack_encoder_stream_receiver_test.cc b/quic/core/qpack/qpack_encoder_stream_receiver_test.cc
index f9fce00..5685981 100644
--- a/quic/core/qpack/qpack_encoder_stream_receiver_test.cc
+++ b/quic/core/qpack/qpack_encoder_stream_receiver_test.cc
@@ -9,6 +9,7 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+using testing::Eq;
using testing::StrictMock;
namespace quic {
@@ -26,7 +27,7 @@
MOCK_METHOD2(OnInsertWithoutNameReference,
void(QuicStringPiece name, QuicStringPiece value));
MOCK_METHOD1(OnDuplicate, void(uint64_t index));
- MOCK_METHOD1(OnDynamicTableSizeUpdate, void(uint64_t max_size));
+ MOCK_METHOD1(OnSetDynamicTableCapacity, void(uint64_t capacity));
MOCK_METHOD1(OnErrorDetected, void(QuicStringPiece error_message));
};
@@ -45,15 +46,15 @@
TEST_F(QpackEncoderStreamReceiverTest, InsertWithNameReference) {
// Static, index fits in prefix, empty value.
- EXPECT_CALL(*delegate(), OnInsertWithNameReference(true, 5, ""));
+ EXPECT_CALL(*delegate(), OnInsertWithNameReference(true, 5, Eq("")));
// Static, index fits in prefix, Huffman encoded value.
- EXPECT_CALL(*delegate(), OnInsertWithNameReference(true, 2, "foo"));
+ EXPECT_CALL(*delegate(), OnInsertWithNameReference(true, 2, Eq("foo")));
// Not static, index does not fit in prefix, not Huffman encoded value.
- EXPECT_CALL(*delegate(), OnInsertWithNameReference(false, 137, "bar"));
+ EXPECT_CALL(*delegate(), OnInsertWithNameReference(false, 137, Eq("bar")));
// Value length does not fit in prefix.
// 'Z' would be Huffman encoded to 8 bits, so no Huffman encoding is used.
EXPECT_CALL(*delegate(),
- OnInsertWithNameReference(false, 42, QuicString(127, 'Z')));
+ OnInsertWithNameReference(false, 42, Eq(QuicString(127, 'Z'))));
Decode(QuicTextUtils::HexDecode(
"c500"
@@ -66,29 +67,29 @@
}
TEST_F(QpackEncoderStreamReceiverTest, InsertWithNameReferenceIndexTooLarge) {
- EXPECT_CALL(*delegate(), OnErrorDetected("Encoded integer too large."));
+ EXPECT_CALL(*delegate(), OnErrorDetected(Eq("Encoded integer too large.")));
Decode(QuicTextUtils::HexDecode("bfffffffffffffffffffffff"));
}
TEST_F(QpackEncoderStreamReceiverTest, InsertWithNameReferenceValueTooLong) {
- EXPECT_CALL(*delegate(),
- OnErrorDetected(QuicStringPiece("Encoded integer too large.")));
+ EXPECT_CALL(*delegate(), OnErrorDetected(Eq("Encoded integer too large.")));
Decode(QuicTextUtils::HexDecode("c57fffffffffffffffffffff"));
}
TEST_F(QpackEncoderStreamReceiverTest, InsertWithoutNameReference) {
// Empty name and value.
- EXPECT_CALL(*delegate(), OnInsertWithoutNameReference("", ""));
+ EXPECT_CALL(*delegate(), OnInsertWithoutNameReference(Eq(""), Eq("")));
// Huffman encoded short strings.
- EXPECT_CALL(*delegate(), OnInsertWithoutNameReference("bar", "bar"));
+ EXPECT_CALL(*delegate(), OnInsertWithoutNameReference(Eq("bar"), Eq("bar")));
// Not Huffman encoded short strings.
- EXPECT_CALL(*delegate(), OnInsertWithoutNameReference("foo", "foo"));
+ EXPECT_CALL(*delegate(), OnInsertWithoutNameReference(Eq("foo"), Eq("foo")));
// Not Huffman encoded long strings; length does not fit on prefix.
// 'Z' would be Huffman encoded to 8 bits, so no Huffman encoding is used.
- EXPECT_CALL(*delegate(), OnInsertWithoutNameReference(QuicString(31, 'Z'),
- QuicString(127, 'Z')));
+ EXPECT_CALL(*delegate(),
+ OnInsertWithoutNameReference(Eq(QuicString(31, 'Z')),
+ Eq(QuicString(127, 'Z'))));
Decode(QuicTextUtils::HexDecode(
"4000"
@@ -104,7 +105,7 @@
// Name Length value is too large for varint decoder to decode.
TEST_F(QpackEncoderStreamReceiverTest,
InsertWithoutNameReferenceNameTooLongForVarintDecoder) {
- EXPECT_CALL(*delegate(), OnErrorDetected("Encoded integer too large."));
+ EXPECT_CALL(*delegate(), OnErrorDetected(Eq("Encoded integer too large.")));
Decode(QuicTextUtils::HexDecode("5fffffffffffffffffffff"));
}
@@ -112,8 +113,7 @@
// Name Length value can be decoded by varint decoder but exceeds 1 MB limit.
TEST_F(QpackEncoderStreamReceiverTest,
InsertWithoutNameReferenceNameExceedsLimit) {
- EXPECT_CALL(*delegate(),
- OnErrorDetected(QuicStringPiece("String literal too long.")));
+ EXPECT_CALL(*delegate(), OnErrorDetected(Eq("String literal too long.")));
Decode(QuicTextUtils::HexDecode("5fffff7f"));
}
@@ -121,7 +121,7 @@
// Value Length value is too large for varint decoder to decode.
TEST_F(QpackEncoderStreamReceiverTest,
InsertWithoutNameReferenceValueTooLongForVarintDecoder) {
- EXPECT_CALL(*delegate(), OnErrorDetected("Encoded integer too large."));
+ EXPECT_CALL(*delegate(), OnErrorDetected(Eq("Encoded integer too large.")));
Decode(QuicTextUtils::HexDecode("436261727fffffffffffffffffffff"));
}
@@ -129,7 +129,7 @@
// Value Length value can be decoded by varint decoder but exceeds 1 MB limit.
TEST_F(QpackEncoderStreamReceiverTest,
InsertWithoutNameReferenceValueExceedsLimit) {
- EXPECT_CALL(*delegate(), OnErrorDetected("String literal too long."));
+ EXPECT_CALL(*delegate(), OnErrorDetected(Eq("String literal too long.")));
Decode(QuicTextUtils::HexDecode("436261727fffff7f"));
}
@@ -144,22 +144,22 @@
}
TEST_F(QpackEncoderStreamReceiverTest, DuplicateIndexTooLarge) {
- EXPECT_CALL(*delegate(), OnErrorDetected("Encoded integer too large."));
+ EXPECT_CALL(*delegate(), OnErrorDetected(Eq("Encoded integer too large.")));
Decode(QuicTextUtils::HexDecode("1fffffffffffffffffffff"));
}
-TEST_F(QpackEncoderStreamReceiverTest, DynamicTableSizeUpdate) {
- // Small max size fits in prefix.
- EXPECT_CALL(*delegate(), OnDynamicTableSizeUpdate(17));
- // Large max size requires two extension bytes.
- EXPECT_CALL(*delegate(), OnDynamicTableSizeUpdate(500));
+TEST_F(QpackEncoderStreamReceiverTest, SetDynamicTableCapacity) {
+ // Small capacity fits in prefix.
+ EXPECT_CALL(*delegate(), OnSetDynamicTableCapacity(17));
+ // Large capacity requires two extension bytes.
+ EXPECT_CALL(*delegate(), OnSetDynamicTableCapacity(500));
Decode(QuicTextUtils::HexDecode("313fd503"));
}
-TEST_F(QpackEncoderStreamReceiverTest, DynamicTableSizeUpdateMaxSizeTooLarge) {
- EXPECT_CALL(*delegate(), OnErrorDetected("Encoded integer too large."));
+TEST_F(QpackEncoderStreamReceiverTest, SetDynamicTableCapacityTooLarge) {
+ EXPECT_CALL(*delegate(), OnErrorDetected(Eq("Encoded integer too large.")));
Decode(QuicTextUtils::HexDecode("3fffffffffffffffffffff"));
}
diff --git a/quic/core/qpack/qpack_encoder_stream_sender.cc b/quic/core/qpack/qpack_encoder_stream_sender.cc
index c7ee503..fb43046 100644
--- a/quic/core/qpack/qpack_encoder_stream_sender.cc
+++ b/quic/core/qpack/qpack_encoder_stream_sender.cc
@@ -33,7 +33,7 @@
instruction_encoder_.Next(std::numeric_limits<size_t>::max(), &output);
DCHECK(!instruction_encoder_.HasNext());
- delegate_->Write(output);
+ delegate_->WriteEncoderStreamData(output);
}
void QpackEncoderStreamSender::SendInsertWithoutNameReference(
@@ -49,7 +49,7 @@
instruction_encoder_.Next(std::numeric_limits<size_t>::max(), &output);
DCHECK(!instruction_encoder_.HasNext());
- delegate_->Write(output);
+ delegate_->WriteEncoderStreamData(output);
}
void QpackEncoderStreamSender::SendDuplicate(uint64_t index) {
@@ -62,20 +62,20 @@
instruction_encoder_.Next(std::numeric_limits<size_t>::max(), &output);
DCHECK(!instruction_encoder_.HasNext());
- delegate_->Write(output);
+ delegate_->WriteEncoderStreamData(output);
}
-void QpackEncoderStreamSender::SendDynamicTableSizeUpdate(uint64_t max_size) {
- instruction_encoder_.set_varint(max_size);
+void QpackEncoderStreamSender::SendSetDynamicTableCapacity(uint64_t capacity) {
+ instruction_encoder_.set_varint(capacity);
- instruction_encoder_.Encode(DynamicTableSizeUpdateInstruction());
+ instruction_encoder_.Encode(SetDynamicTableCapacityInstruction());
QuicString output;
instruction_encoder_.Next(std::numeric_limits<size_t>::max(), &output);
DCHECK(!instruction_encoder_.HasNext());
- delegate_->Write(output);
+ delegate_->WriteEncoderStreamData(output);
}
} // namespace quic
diff --git a/quic/core/qpack/qpack_encoder_stream_sender.h b/quic/core/qpack/qpack_encoder_stream_sender.h
index 0c8d4dd..ad34568 100644
--- a/quic/core/qpack/qpack_encoder_stream_sender.h
+++ b/quic/core/qpack/qpack_encoder_stream_sender.h
@@ -22,9 +22,10 @@
virtual ~Delegate() = default;
// Encoded |data| is ready to be written on the encoder stream.
- // Write() is called exactly once for each instruction, |data| contains the
- // entire encoded instruction and it is guaranteed to be not empty.
- virtual void Write(QuicStringPiece data) = 0;
+ // WriteEncoderStreamData() is called exactly once for each instruction.
+ // |data| contains the entire encoded instruction and it is guaranteed to be
+ // not empty.
+ virtual void WriteEncoderStreamData(QuicStringPiece data) = 0;
};
explicit QpackEncoderStreamSender(Delegate* delegate);
@@ -44,8 +45,8 @@
QuicStringPiece value);
// 5.2.3. Duplicate
void SendDuplicate(uint64_t index);
- // 5.2.4. Dynamic Table Size Update
- void SendDynamicTableSizeUpdate(uint64_t max_size);
+ // 5.2.4. Set Dynamic Table Capacity
+ void SendSetDynamicTableCapacity(uint64_t capacity);
private:
Delegate* const delegate_;
diff --git a/quic/core/qpack/qpack_encoder_stream_sender_test.cc b/quic/core/qpack/qpack_encoder_stream_sender_test.cc
index 46e5c46..a850f18 100644
--- a/quic/core/qpack/qpack_encoder_stream_sender_test.cc
+++ b/quic/core/qpack/qpack_encoder_stream_sender_test.cc
@@ -6,6 +6,7 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "net/third_party/quiche/src/quic/core/qpack/qpack_encoder_test_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
@@ -16,40 +17,36 @@
namespace test {
namespace {
-class MockSenderDelegate : public QpackEncoderStreamSender::Delegate {
- public:
- ~MockSenderDelegate() override = default;
-
- MOCK_METHOD1(Write, void(QuicStringPiece data));
-};
-
class QpackEncoderStreamSenderTest : public QuicTest {
protected:
QpackEncoderStreamSenderTest() : stream_(&delegate_) {}
~QpackEncoderStreamSenderTest() override = default;
- StrictMock<MockSenderDelegate> delegate_;
+ StrictMock<MockEncoderStreamSenderDelegate> delegate_;
QpackEncoderStreamSender stream_;
};
TEST_F(QpackEncoderStreamSenderTest, InsertWithNameReference) {
// Static, index fits in prefix, empty value.
- EXPECT_CALL(delegate_, Write(Eq(QuicTextUtils::HexDecode("c500"))));
+ EXPECT_CALL(delegate_,
+ WriteEncoderStreamData(Eq(QuicTextUtils::HexDecode("c500"))));
stream_.SendInsertWithNameReference(true, 5, "");
// Static, index fits in prefix, Huffman encoded value.
- EXPECT_CALL(delegate_, Write(Eq(QuicTextUtils::HexDecode("c28294e7"))));
+ EXPECT_CALL(delegate_,
+ WriteEncoderStreamData(Eq(QuicTextUtils::HexDecode("c28294e7"))));
stream_.SendInsertWithNameReference(true, 2, "foo");
// Not static, index does not fit in prefix, not Huffman encoded value.
- EXPECT_CALL(delegate_, Write(Eq(QuicTextUtils::HexDecode("bf4a03626172"))));
+ EXPECT_CALL(delegate_, WriteEncoderStreamData(
+ Eq(QuicTextUtils::HexDecode("bf4a03626172"))));
stream_.SendInsertWithNameReference(false, 137, "bar");
// Value length does not fit in prefix.
// 'Z' would be Huffman encoded to 8 bits, so no Huffman encoding is used.
EXPECT_CALL(
delegate_,
- Write(Eq(QuicTextUtils::HexDecode(
+ WriteEncoderStreamData(Eq(QuicTextUtils::HexDecode(
"aa7f005a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a"
"5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a"
"5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a"
@@ -59,23 +56,25 @@
TEST_F(QpackEncoderStreamSenderTest, InsertWithoutNameReference) {
// Empty name and value.
- EXPECT_CALL(delegate_, Write(Eq(QuicTextUtils::HexDecode("4000"))));
+ EXPECT_CALL(delegate_,
+ WriteEncoderStreamData(Eq(QuicTextUtils::HexDecode("4000"))));
stream_.SendInsertWithoutNameReference("", "");
// Huffman encoded short strings.
- EXPECT_CALL(delegate_,
- Write(Eq(QuicTextUtils::HexDecode("4362617203626172"))));
+ EXPECT_CALL(delegate_, WriteEncoderStreamData(
+ Eq(QuicTextUtils::HexDecode("4362617203626172"))));
stream_.SendInsertWithoutNameReference("bar", "bar");
// Not Huffman encoded short strings.
- EXPECT_CALL(delegate_, Write(Eq(QuicTextUtils::HexDecode("6294e78294e7"))));
+ EXPECT_CALL(delegate_, WriteEncoderStreamData(
+ Eq(QuicTextUtils::HexDecode("6294e78294e7"))));
stream_.SendInsertWithoutNameReference("foo", "foo");
// Not Huffman encoded long strings; length does not fit on prefix.
// 'Z' would be Huffman encoded to 8 bits, so no Huffman encoding is used.
EXPECT_CALL(
delegate_,
- Write(Eq(QuicTextUtils::HexDecode(
+ WriteEncoderStreamData(Eq(QuicTextUtils::HexDecode(
"5f005a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a7f"
"005a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a"
"5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a5a"
@@ -87,22 +86,26 @@
TEST_F(QpackEncoderStreamSenderTest, Duplicate) {
// Small index fits in prefix.
- EXPECT_CALL(delegate_, Write(Eq(QuicTextUtils::HexDecode("11"))));
+ EXPECT_CALL(delegate_,
+ WriteEncoderStreamData(Eq(QuicTextUtils::HexDecode("11"))));
stream_.SendDuplicate(17);
// Large index requires two extension bytes.
- EXPECT_CALL(delegate_, Write(Eq(QuicTextUtils::HexDecode("1fd503"))));
+ EXPECT_CALL(delegate_,
+ WriteEncoderStreamData(Eq(QuicTextUtils::HexDecode("1fd503"))));
stream_.SendDuplicate(500);
}
-TEST_F(QpackEncoderStreamSenderTest, DynamicTableSizeUpdate) {
- // Small max size fits in prefix.
- EXPECT_CALL(delegate_, Write(Eq(QuicTextUtils::HexDecode("31"))));
- stream_.SendDynamicTableSizeUpdate(17);
+TEST_F(QpackEncoderStreamSenderTest, SetDynamicTableCapacity) {
+ // Small capacity fits in prefix.
+ EXPECT_CALL(delegate_,
+ WriteEncoderStreamData(Eq(QuicTextUtils::HexDecode("31"))));
+ stream_.SendSetDynamicTableCapacity(17);
- // Large max size requires two extension bytes.
- EXPECT_CALL(delegate_, Write(Eq(QuicTextUtils::HexDecode("3fd503"))));
- stream_.SendDynamicTableSizeUpdate(500);
+ // Large capacity requires two extension bytes.
+ EXPECT_CALL(delegate_,
+ WriteEncoderStreamData(Eq(QuicTextUtils::HexDecode("3fd503"))));
+ stream_.SendSetDynamicTableCapacity(500);
}
} // namespace
diff --git a/quic/core/qpack/qpack_encoder_test.cc b/quic/core/qpack/qpack_encoder_test.cc
index 04e4dd6..e3dba00 100644
--- a/quic/core/qpack/qpack_encoder_test.cc
+++ b/quic/core/qpack/qpack_encoder_test.cc
@@ -11,6 +11,7 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
+using ::testing::Eq;
using ::testing::StrictMock;
using ::testing::Values;
@@ -153,7 +154,7 @@
TEST_P(QpackEncoderTest, DecoderStreamError) {
EXPECT_CALL(decoder_stream_error_delegate_,
- OnError("Encoded integer too large."));
+ OnDecoderStreamError(Eq("Encoded integer too large.")));
QpackEncoder encoder(&decoder_stream_error_delegate_,
&encoder_stream_sender_delegate_);
diff --git a/quic/core/qpack/qpack_encoder_test_utils.cc b/quic/core/qpack/qpack_encoder_test_utils.cc
index 606db4e..b9a3263 100644
--- a/quic/core/qpack/qpack_encoder_test_utils.cc
+++ b/quic/core/qpack/qpack_encoder_test_utils.cc
@@ -9,9 +9,11 @@
namespace quic {
namespace test {
-void NoopDecoderStreamErrorDelegate::OnError(QuicStringPiece error_message) {}
+void NoopDecoderStreamErrorDelegate::OnDecoderStreamError(
+ QuicStringPiece error_message) {}
-void NoopEncoderStreamSenderDelegate::Write(QuicStringPiece data) {}
+void NoopEncoderStreamSenderDelegate::WriteEncoderStreamData(
+ QuicStringPiece data) {}
QuicString QpackEncode(
QpackEncoder::DecoderStreamErrorDelegate* decoder_stream_error_delegate,
diff --git a/quic/core/qpack/qpack_encoder_test_utils.h b/quic/core/qpack/qpack_encoder_test_utils.h
index b000868..03d05cb 100644
--- a/quic/core/qpack/qpack_encoder_test_utils.h
+++ b/quic/core/qpack/qpack_encoder_test_utils.h
@@ -21,7 +21,7 @@
public:
~NoopDecoderStreamErrorDelegate() override = default;
- void OnError(QuicStringPiece error_message) override;
+ void OnDecoderStreamError(QuicStringPiece error_message) override;
};
// Mock QpackEncoder::DecoderStreamErrorDelegate implementation.
@@ -30,7 +30,7 @@
public:
~MockDecoderStreamErrorDelegate() override = default;
- MOCK_METHOD1(OnError, void(QuicStringPiece error_message));
+ MOCK_METHOD1(OnDecoderStreamError, void(QuicStringPiece error_message));
};
// QpackEncoderStreamSender::Delegate implementation that does nothing.
@@ -39,7 +39,16 @@
public:
~NoopEncoderStreamSenderDelegate() override = default;
- void Write(QuicStringPiece data) override;
+ void WriteEncoderStreamData(QuicStringPiece data) override;
+};
+
+// Mock QpackEncoderStreamSender::Delegate implementation.
+class MockEncoderStreamSenderDelegate
+ : public QpackEncoderStreamSender::Delegate {
+ public:
+ ~MockEncoderStreamSenderDelegate() override = default;
+
+ MOCK_METHOD1(WriteEncoderStreamData, void(QuicStringPiece data));
};
QuicString QpackEncode(
diff --git a/quic/core/qpack/qpack_header_table.cc b/quic/core/qpack/qpack_header_table.cc
index 4a4c9fa..4ba3ee3 100644
--- a/quic/core/qpack/qpack_header_table.cc
+++ b/quic/core/qpack/qpack_header_table.cc
@@ -143,12 +143,12 @@
return new_entry;
}
-bool QpackHeaderTable::UpdateTableSize(uint64_t max_size) {
- if (max_size > maximum_dynamic_table_capacity_) {
+bool QpackHeaderTable::SetDynamicTableCapacity(uint64_t capacity) {
+ if (capacity > maximum_dynamic_table_capacity_) {
return false;
}
- dynamic_table_capacity_ = max_size;
+ dynamic_table_capacity_ = capacity;
EvictDownToCurrentCapacity();
DCHECK_LE(dynamic_table_size_, dynamic_table_capacity_);
diff --git a/quic/core/qpack/qpack_header_table.h b/quic/core/qpack/qpack_header_table.h
index b98e7eb..eda7ab5 100644
--- a/quic/core/qpack/qpack_header_table.h
+++ b/quic/core/qpack/qpack_header_table.h
@@ -56,9 +56,9 @@
// is larger than the capacity of the dynamic table.
const QpackEntry* InsertEntry(QuicStringPiece name, QuicStringPiece value);
- // Change dynamic table capacity to |max_size|. Returns true on success.
- // Returns false is |max_size| exceeds maximum dynamic table capacity.
- bool UpdateTableSize(uint64_t max_size);
+ // Change dynamic table capacity to |capacity|. Returns true on success.
+ // Returns false is |capacity| exceeds maximum dynamic table capacity.
+ bool SetDynamicTableCapacity(uint64_t capacity);
// Set |maximum_dynamic_table_capacity_|. The initial value is zero. The
// final value is determined by the decoder and is sent to the encoder as
@@ -68,7 +68,7 @@
// This method must only be called at most once.
void SetMaximumDynamicTableCapacity(uint64_t maximum_dynamic_table_capacity);
- // Used by request streams to decode Largest Reference.
+ // Used on request streams to encode and decode Required Insert Count.
uint64_t max_entries() const { return max_entries_; }
// The number of entries inserted to the dynamic table (including ones that
diff --git a/quic/core/qpack/qpack_header_table_test.cc b/quic/core/qpack/qpack_header_table_test.cc
index 95df41d..f3ac5b5 100644
--- a/quic/core/qpack/qpack_header_table_test.cc
+++ b/quic/core/qpack/qpack_header_table_test.cc
@@ -6,7 +6,6 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "net/third_party/quiche/src/quic/core/qpack/qpack_static_table.h"
-#include "net/third_party/quiche/src/quic/core/qpack/qpack_test_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
#include "net/third_party/quiche/src/spdy/core/hpack/hpack_entry.h"
@@ -76,8 +75,8 @@
EXPECT_FALSE(table_.InsertEntry(name, value));
}
- bool UpdateTableSize(uint64_t max_size) {
- return table_.UpdateTableSize(max_size);
+ bool SetDynamicTableCapacity(uint64_t capacity) {
+ return table_.SetDynamicTableCapacity(capacity);
}
uint64_t max_entries() const { return table_.max_entries(); }
@@ -237,20 +236,21 @@
EXPECT_EQ(15u, table2.max_entries());
}
-TEST_F(QpackHeaderTableTest, UpdateTableSize) {
+TEST_F(QpackHeaderTableTest, SetDynamicTableCapacity) {
// Dynamic table capacity does not affect MaxEntries.
- EXPECT_TRUE(UpdateTableSize(1024));
+ EXPECT_TRUE(SetDynamicTableCapacity(1024));
EXPECT_EQ(32u * 1024, max_entries());
- EXPECT_TRUE(UpdateTableSize(500));
+ EXPECT_TRUE(SetDynamicTableCapacity(500));
EXPECT_EQ(32u * 1024, max_entries());
// Dynamic table capacity cannot exceed maximum dynamic table capacity.
- EXPECT_FALSE(UpdateTableSize(2 * kMaximumDynamicTableCapacityForTesting));
+ EXPECT_FALSE(
+ SetDynamicTableCapacity(2 * kMaximumDynamicTableCapacityForTesting));
}
TEST_F(QpackHeaderTableTest, EvictByInsertion) {
- EXPECT_TRUE(UpdateTableSize(40));
+ EXPECT_TRUE(SetDynamicTableCapacity(40));
// Entry size is 3 + 3 + 32 = 38.
InsertEntry("foo", "bar");
@@ -285,7 +285,7 @@
ExpectMatch("baz", "qux", QpackHeaderTable::MatchType::kNameAndValue,
/* expected_is_static = */ false, 1u);
- EXPECT_TRUE(UpdateTableSize(40));
+ EXPECT_TRUE(SetDynamicTableCapacity(40));
EXPECT_EQ(2u, inserted_entry_count());
EXPECT_EQ(1u, dropped_entry_count());
@@ -293,7 +293,7 @@
ExpectMatch("baz", "qux", QpackHeaderTable::MatchType::kNameAndValue,
/* expected_is_static = */ false, 1u);
- EXPECT_TRUE(UpdateTableSize(20));
+ EXPECT_TRUE(SetDynamicTableCapacity(20));
EXPECT_EQ(2u, inserted_entry_count());
EXPECT_EQ(2u, dropped_entry_count());
@@ -302,7 +302,7 @@
}
TEST_F(QpackHeaderTableTest, EvictOldestOfIdentical) {
- EXPECT_TRUE(UpdateTableSize(80));
+ EXPECT_TRUE(SetDynamicTableCapacity(80));
// Entry size is 3 + 3 + 32 = 38.
// Insert same entry twice.
@@ -327,7 +327,7 @@
}
TEST_F(QpackHeaderTableTest, EvictOldestOfSameName) {
- EXPECT_TRUE(UpdateTableSize(80));
+ EXPECT_TRUE(SetDynamicTableCapacity(80));
// Entry size is 3 + 3 + 32 = 38.
// Insert two entries with same name but different values.
diff --git a/quic/core/qpack/qpack_instruction_decoder.cc b/quic/core/qpack/qpack_instruction_decoder.cc
index 9623dfb..dbb2076 100644
--- a/quic/core/qpack/qpack_instruction_decoder.cc
+++ b/quic/core/qpack/qpack_instruction_decoder.cc
@@ -4,6 +4,9 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_instruction_decoder.h"
+#include <algorithm>
+#include <utility>
+
#include "base/logging.h"
namespace quic {
diff --git a/quic/core/qpack/qpack_instruction_decoder_test.cc b/quic/core/qpack/qpack_instruction_decoder_test.cc
index 99be5a0..d1fe9b5 100644
--- a/quic/core/qpack/qpack_instruction_decoder_test.cc
+++ b/quic/core/qpack/qpack_instruction_decoder_test.cc
@@ -4,6 +4,8 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_instruction_decoder.h"
+#include <algorithm>
+
#include "base/logging.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -13,6 +15,7 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
using ::testing::_;
+using ::testing::Eq;
using ::testing::Expectation;
using ::testing::Return;
using ::testing::StrictMock;
@@ -140,14 +143,12 @@
}
TEST_P(QpackInstructionDecoderTest, InvalidHuffmanEncoding) {
- EXPECT_CALL(delegate_,
- OnError(QuicStringPiece("Error in Huffman-encoded string.")));
+ EXPECT_CALL(delegate_, OnError(Eq("Error in Huffman-encoded string.")));
decoder_.Decode(QuicTextUtils::HexDecode("c1ff"));
}
TEST_P(QpackInstructionDecoderTest, InvalidVarintEncoding) {
- EXPECT_CALL(delegate_,
- OnError(QuicStringPiece("Encoded integer too large.")));
+ EXPECT_CALL(delegate_, OnError(Eq("Encoded integer too large.")));
decoder_.Decode(QuicTextUtils::HexDecode("ffffffffffffffffffffff"));
}
diff --git a/quic/core/qpack/qpack_progressive_decoder.cc b/quic/core/qpack/qpack_progressive_decoder.cc
index 409c910..430e707 100644
--- a/quic/core/qpack/qpack_progressive_decoder.cc
+++ b/quic/core/qpack/qpack_progressive_decoder.cc
@@ -4,6 +4,9 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_progressive_decoder.h"
+#include <algorithm>
+#include <limits>
+
#include "base/logging.h"
#include "net/third_party/quiche/src/quic/core/qpack/qpack_constants.h"
#include "net/third_party/quiche/src/quic/core/qpack/qpack_header_table.h"
@@ -23,21 +26,21 @@
header_table_(header_table),
decoder_stream_sender_(decoder_stream_sender),
handler_(handler),
- largest_reference_(0),
- base_index_(0),
- largest_reference_seen_(0),
+ required_insert_count_(0),
+ base_(0),
+ required_insert_count_so_far_(0),
prefix_decoded_(false),
decoding_(true),
error_detected_(false) {}
// static
-bool QpackProgressiveDecoder::DecodeLargestReference(
- uint64_t wire_largest_reference,
+bool QpackProgressiveDecoder::DecodeRequiredInsertCount(
+ uint64_t encoded_required_insert_count,
uint64_t max_entries,
uint64_t total_number_of_inserts,
- uint64_t* largest_reference) {
- if (wire_largest_reference == 0) {
- *largest_reference = 0;
+ uint64_t* required_insert_count) {
+ if (encoded_required_insert_count == 0) {
+ *required_insert_count = 0;
return true;
}
@@ -45,37 +48,37 @@
// precluding all calculations in this method from overflowing.
DCHECK_LE(max_entries, std::numeric_limits<uint64_t>::max() / 32);
- if (wire_largest_reference > 2 * max_entries) {
+ if (encoded_required_insert_count > 2 * max_entries) {
return false;
}
- *largest_reference = wire_largest_reference - 1;
- DCHECK_LT(*largest_reference, std::numeric_limits<uint64_t>::max() / 16);
+ *required_insert_count = encoded_required_insert_count - 1;
+ DCHECK_LT(*required_insert_count, std::numeric_limits<uint64_t>::max() / 16);
uint64_t current_wrapped = total_number_of_inserts % (2 * max_entries);
DCHECK_LT(current_wrapped, std::numeric_limits<uint64_t>::max() / 16);
- if (current_wrapped >= *largest_reference + max_entries) {
- // Largest Reference wrapped around 1 extra time.
- *largest_reference += 2 * max_entries;
- } else if (current_wrapped + max_entries < *largest_reference) {
+ if (current_wrapped >= *required_insert_count + max_entries) {
+ // Required Insert Count wrapped around 1 extra time.
+ *required_insert_count += 2 * max_entries;
+ } else if (current_wrapped + max_entries < *required_insert_count) {
// Decoder wrapped around 1 extra time.
current_wrapped += 2 * max_entries;
}
- if (*largest_reference >
+ if (*required_insert_count >
std::numeric_limits<uint64_t>::max() - total_number_of_inserts) {
return false;
}
- *largest_reference += total_number_of_inserts;
+ *required_insert_count += total_number_of_inserts;
- // Prevent underflow, but also disallow invalid value 0 for Largest Reference.
- if (current_wrapped >= *largest_reference) {
+ // Prevent underflow, also disallow invalid value 0 for Required Insert Count.
+ if (current_wrapped >= *required_insert_count) {
return false;
}
- *largest_reference -= current_wrapped;
+ *required_insert_count -= current_wrapped;
return true;
}
@@ -118,8 +121,8 @@
return;
}
- if (largest_reference_ != largest_reference_seen_) {
- OnError("Largest Reference too large.");
+ if (required_insert_count_ != required_insert_count_so_far_) {
+ OnError("Required Insert Count too large.");
return;
}
@@ -164,17 +167,17 @@
return false;
}
- if (absolute_index > largest_reference_) {
- OnError("Index larger than Largest Reference.");
+ if (absolute_index >= required_insert_count_) {
+ OnError("Absolute Index must be smaller than Required Insert Count.");
return false;
}
- largest_reference_seen_ = std::max(largest_reference_seen_, absolute_index);
+ DCHECK_LT(absolute_index, std::numeric_limits<uint64_t>::max());
+ required_insert_count_so_far_ =
+ std::max(required_insert_count_so_far_, absolute_index + 1);
- DCHECK_NE(0u, absolute_index);
- const uint64_t real_index = absolute_index - 1;
auto entry =
- header_table_->LookupEntry(/* is_static = */ false, real_index);
+ header_table_->LookupEntry(/* is_static = */ false, absolute_index);
if (!entry) {
OnError("Dynamic table entry not found.");
return false;
@@ -203,16 +206,17 @@
return false;
}
- if (absolute_index > largest_reference_) {
- OnError("Index larger than Largest Reference.");
+ if (absolute_index >= required_insert_count_) {
+ OnError("Absolute Index must be smaller than Required Insert Count.");
return false;
}
- largest_reference_seen_ = std::max(largest_reference_seen_, absolute_index);
+ DCHECK_LT(absolute_index, std::numeric_limits<uint64_t>::max());
+ required_insert_count_so_far_ =
+ std::max(required_insert_count_so_far_, absolute_index + 1);
- DCHECK_NE(0u, absolute_index);
- const uint64_t real_index = absolute_index - 1;
- auto entry = header_table_->LookupEntry(/* is_static = */ false, real_index);
+ auto entry =
+ header_table_->LookupEntry(/* is_static = */ false, absolute_index);
if (!entry) {
OnError("Dynamic table entry not found.");
return false;
@@ -231,17 +235,17 @@
return false;
}
- if (absolute_index > largest_reference_) {
- OnError("Index larger than Largest Reference.");
+ if (absolute_index >= required_insert_count_) {
+ OnError("Absolute Index must be smaller than Required Insert Count.");
return false;
}
- largest_reference_seen_ = std::max(largest_reference_seen_, absolute_index);
+ DCHECK_LT(absolute_index, std::numeric_limits<uint64_t>::max());
+ required_insert_count_so_far_ =
+ std::max(required_insert_count_so_far_, absolute_index + 1);
- DCHECK_NE(0u, absolute_index);
- const uint64_t real_index = absolute_index - 1;
auto entry =
- header_table_->LookupEntry(/* is_static = */ false, real_index);
+ header_table_->LookupEntry(/* is_static = */ false, absolute_index);
if (!entry) {
OnError("Dynamic table entry not found.");
return false;
@@ -270,16 +274,17 @@
return false;
}
- if (absolute_index > largest_reference_) {
- OnError("Index larger than Largest Reference.");
+ if (absolute_index >= required_insert_count_) {
+ OnError("Absolute Index must be smaller than Required Insert Count.");
return false;
}
- largest_reference_seen_ = std::max(largest_reference_seen_, absolute_index);
+ DCHECK_LT(absolute_index, std::numeric_limits<uint64_t>::max());
+ required_insert_count_so_far_ =
+ std::max(required_insert_count_so_far_, absolute_index + 1);
- DCHECK_NE(0u, absolute_index);
- const uint64_t real_index = absolute_index - 1;
- auto entry = header_table_->LookupEntry(/* is_static = */ false, real_index);
+ auto entry =
+ header_table_->LookupEntry(/* is_static = */ false, absolute_index);
if (!entry) {
OnError("Dynamic table entry not found.");
return false;
@@ -299,17 +304,17 @@
bool QpackProgressiveDecoder::DoPrefixInstruction() {
DCHECK(!prefix_decoded_);
- if (!DecodeLargestReference(
+ if (!DecodeRequiredInsertCount(
prefix_decoder_->varint(), header_table_->max_entries(),
- header_table_->inserted_entry_count(), &largest_reference_)) {
- OnError("Error decoding Largest Reference.");
+ header_table_->inserted_entry_count(), &required_insert_count_)) {
+ OnError("Error decoding Required Insert Count.");
return false;
}
const bool sign = prefix_decoder_->s_bit();
- const uint64_t delta_base_index = prefix_decoder_->varint2();
- if (!DeltaBaseIndexToBaseIndex(sign, delta_base_index, &base_index_)) {
- OnError("Error calculating Base Index.");
+ const uint64_t delta_base = prefix_decoder_->varint2();
+ if (!DeltaBaseToBase(sign, delta_base, &base_)) {
+ OnError("Error calculating Base.");
return false;
}
@@ -318,24 +323,23 @@
return true;
}
-bool QpackProgressiveDecoder::DeltaBaseIndexToBaseIndex(
- bool sign,
- uint64_t delta_base_index,
- uint64_t* base_index) {
+bool QpackProgressiveDecoder::DeltaBaseToBase(bool sign,
+ uint64_t delta_base,
+ uint64_t* base) {
if (sign) {
- if (delta_base_index == std::numeric_limits<uint64_t>::max() ||
- largest_reference_ < delta_base_index + 1) {
+ if (delta_base == std::numeric_limits<uint64_t>::max() ||
+ required_insert_count_ < delta_base + 1) {
return false;
}
- *base_index = largest_reference_ - delta_base_index - 1;
+ *base = required_insert_count_ - delta_base - 1;
return true;
}
- if (delta_base_index >
- std::numeric_limits<uint64_t>::max() - largest_reference_) {
+ if (delta_base >
+ std::numeric_limits<uint64_t>::max() - required_insert_count_) {
return false;
}
- *base_index = largest_reference_ + delta_base_index;
+ *base = required_insert_count_ + delta_base;
return true;
}
@@ -343,22 +347,22 @@
uint64_t relative_index,
uint64_t* absolute_index) const {
if (relative_index == std::numeric_limits<uint64_t>::max() ||
- relative_index + 1 > base_index_) {
+ relative_index + 1 > base_) {
return false;
}
- *absolute_index = base_index_ - relative_index;
+ *absolute_index = base_ - 1 - relative_index;
return true;
}
bool QpackProgressiveDecoder::PostBaseIndexToAbsoluteIndex(
uint64_t post_base_index,
uint64_t* absolute_index) const {
- if (post_base_index >= std::numeric_limits<uint64_t>::max() - base_index_) {
+ if (post_base_index >= std::numeric_limits<uint64_t>::max() - base_) {
return false;
}
- *absolute_index = base_index_ + post_base_index + 1;
+ *absolute_index = base_ + post_base_index;
return true;
}
diff --git a/quic/core/qpack/qpack_progressive_decoder.h b/quic/core/qpack/qpack_progressive_decoder.h
index 7524411..7988861 100644
--- a/quic/core/qpack/qpack_progressive_decoder.h
+++ b/quic/core/qpack/qpack_progressive_decoder.h
@@ -56,14 +56,14 @@
QpackProgressiveDecoder& operator=(const QpackProgressiveDecoder&) = delete;
~QpackProgressiveDecoder() override = default;
- // Calculate actual Largest Reference from largest reference value sent on
- // wire, MaxEntries, and total number of dynamic table insertions according to
- // https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#largest-reference
+ // Calculate Required Insert Count from Encoded Required Insert Count,
+ // MaxEntries, and total number of dynamic table insertions according to
+ // https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#ric.
// Returns true on success, false on invalid input or overflow/underflow.
- static bool DecodeLargestReference(uint64_t wire_largest_reference,
- uint64_t max_entries,
- uint64_t total_number_of_inserts,
- uint64_t* largest_reference);
+ static bool DecodeRequiredInsertCount(uint64_t encoded_required_insert_count,
+ uint64_t max_entries,
+ uint64_t total_number_of_inserts,
+ uint64_t* required_insert_count);
// Provide a data fragment to decode.
void Decode(QuicStringPiece data);
@@ -84,19 +84,18 @@
bool DoLiteralHeaderFieldInstruction();
bool DoPrefixInstruction();
- // Calculates Base Index from |largest_reference_|, which must be set before
- // calling this method, and sign bit and Delta Base Index in the Header Data
- // Prefix, which are passed in as arguments. Returns true on success, false
- // on failure due to overflow/underflow.
- bool DeltaBaseIndexToBaseIndex(bool sign,
- uint64_t delta_base_index,
- uint64_t* base_index);
+ // Calculates Base from |required_insert_count_|, which must be set before
+ // calling this method, and sign bit and Delta Base in the Header Data Prefix,
+ // which are passed in as arguments. Returns true on success, false on
+ // failure due to overflow/underflow.
+ bool DeltaBaseToBase(bool sign, uint64_t delta_base, uint64_t* base);
// The request stream can use relative index (but different from the kind of
// relative index used on the encoder stream), and post-base index.
// These methods convert relative index and post-base index to absolute index
// (one based). They return true on success, or false if conversion fails due
- // to overflow/underflow.
+ // to overflow/underflow. On success, |*absolute_index| is guaranteed to be
+ // strictly less than std::numeric_limits<uint64_t>::max().
bool RequestStreamRelativeIndexToAbsoluteIndex(
uint64_t relative_index,
uint64_t* absolute_index) const;
@@ -115,14 +114,16 @@
QpackDecoderStreamSender* const decoder_stream_sender_;
HeadersHandlerInterface* const handler_;
- // Largest Reference and Base Index are parsed from the Header Data Prefix.
- // They are both absolute indices, that is, one based.
- uint64_t largest_reference_;
- uint64_t base_index_;
+ // Required Insert Count and Base are decoded from the Header Data Prefix.
+ uint64_t required_insert_count_;
+ uint64_t base_;
- // Keep track of largest reference seen in this header block.
- // After decoding is completed, this can be compared to |largest_reference_|.
- uint64_t largest_reference_seen_;
+ // Required Insert Count is one larger than the largest absolute index of all
+ // referenced dynamic table entries, or zero if no dynamic table entries are
+ // referenced. |required_insert_count_so_far_| starts out as zero and keeps
+ // track of the Required Insert Count based on entries decoded so far.
+ // After decoding is completed, it is compared to |required_insert_count_|.
+ uint64_t required_insert_count_so_far_;
// False until prefix is fully read and decoded.
bool prefix_decoded_;
diff --git a/quic/core/qpack/qpack_progressive_decoder_test.cc b/quic/core/qpack/qpack_progressive_decoder_test.cc
index c1722e5..b306702 100644
--- a/quic/core/qpack/qpack_progressive_decoder_test.cc
+++ b/quic/core/qpack/qpack_progressive_decoder_test.cc
@@ -11,12 +11,12 @@
namespace test {
namespace {
-// For testing valid decodings, the encoded (wire) largest reference value is
-// calculated for actual Largest Reference values, so that there is an expected
-// value to comparte the decoded value against, and so that intricate
-// inequalities can be documented.
+// For testing valid decodings, the Encoded Required Insert Count is calculated
+// from Required Insert Count, so that there is an expected value to compare
+// the decoded value against, and so that intricate inequalities can be
+// documented.
struct {
- uint64_t largest_reference;
+ uint64_t required_insert_count;
uint64_t max_entries;
uint64_t total_number_of_inserts;
} kTestData[] = {
@@ -25,70 +25,72 @@
// No dynamic entries in header.
{0, 100, 0},
{0, 100, 500},
- // Largest Reference has not wrapped around yet, no entries evicted.
+ // Required Insert Count has not wrapped around yet, no entries evicted.
{15, 100, 25},
{20, 100, 10},
- // Largest Reference has not wrapped around yet, some entries evicted.
+ // Required Insert Count has not wrapped around yet, some entries evicted.
{90, 100, 110},
- // Largest Reference has wrapped around.
+ // Required Insert Count has wrapped around.
{234, 100, 180},
- // Largest Reference has wrapped around many times.
+ // Required Insert Count has wrapped around many times.
{5678, 100, 5701},
- // Lowest and highest possible Largest Reference values
+ // Lowest and highest possible Required Insert Count values
// for given MaxEntries and total number of insertions.
{401, 100, 500},
{600, 100, 500}};
-uint64_t EncodeLargestReference(uint64_t largest_reference,
- uint64_t max_entries) {
- if (largest_reference == 0) {
+uint64_t EncodeRequiredInsertCount(uint64_t required_insert_count,
+ uint64_t max_entries) {
+ if (required_insert_count == 0) {
return 0;
}
- return largest_reference % (2 * max_entries) + 1;
+ return required_insert_count % (2 * max_entries) + 1;
}
-TEST(QpackProgressiveDecoderTest, DecodeLargestReference) {
+TEST(QpackProgressiveDecoderTest, DecodeRequiredInsertCount) {
for (size_t i = 0; i < QUIC_ARRAYSIZE(kTestData); ++i) {
- const uint64_t largest_reference = kTestData[i].largest_reference;
+ const uint64_t required_insert_count = kTestData[i].required_insert_count;
const uint64_t max_entries = kTestData[i].max_entries;
const uint64_t total_number_of_inserts =
kTestData[i].total_number_of_inserts;
- if (largest_reference != 0) {
+ if (required_insert_count != 0) {
// Dynamic entries cannot be referenced if dynamic table capacity is zero.
ASSERT_LT(0u, max_entries) << i;
- // Entry |total_number_of_inserts - max_entries| and earlier entries are
- // evicted. Entry |largest_reference| is referenced. No evicted entry
- // can be referenced.
- ASSERT_LT(total_number_of_inserts, largest_reference + max_entries) << i;
- // Entry |largest_reference - max_entries| and earlier entries are
- // evicted, entry |total_number_of_inserts| is the last acknowledged
+ // Entry |total_number_of_inserts - 1 - max_entries| and earlier entries
+ // are evicted. Entry |required_insert_count - 1| is referenced. No
+ // evicted entry can be referenced.
+ ASSERT_LT(total_number_of_inserts, required_insert_count + max_entries)
+ << i;
+ // Entry |required_insert_count - 1 - max_entries| and earlier entries are
+ // evicted, entry |total_number_of_inserts - 1| is the last acknowledged
// entry. Every evicted entry must be acknowledged.
- ASSERT_LE(largest_reference, total_number_of_inserts + max_entries) << i;
+ ASSERT_LE(required_insert_count, total_number_of_inserts + max_entries)
+ << i;
}
- uint64_t wire_largest_reference =
- EncodeLargestReference(largest_reference, max_entries);
+ uint64_t encoded_required_insert_count =
+ EncodeRequiredInsertCount(required_insert_count, max_entries);
// Initialize to a value different from the expected output to confirm that
- // DecodeLargestReference() modifies the value of
- // |decoded_largest_reference|.
- uint64_t decoded_largest_reference = largest_reference + 1;
- EXPECT_TRUE(QpackProgressiveDecoder::DecodeLargestReference(
- wire_largest_reference, max_entries, total_number_of_inserts,
- &decoded_largest_reference))
+ // DecodeRequiredInsertCount() modifies the value of
+ // |decoded_required_insert_count|.
+ uint64_t decoded_required_insert_count = required_insert_count + 1;
+ EXPECT_TRUE(QpackProgressiveDecoder::DecodeRequiredInsertCount(
+ encoded_required_insert_count, max_entries, total_number_of_inserts,
+ &decoded_required_insert_count))
<< i;
- EXPECT_EQ(decoded_largest_reference, largest_reference) << i;
+ EXPECT_EQ(decoded_required_insert_count, required_insert_count) << i;
}
}
-// Failures are tested with hardcoded values for the on-the-wire largest
-// reference field, to provide test coverage for values that would never be
-// produced by a well behaved encoding function.
+// Failures are tested with hardcoded values for encoded required insert count,
+// to provide test coverage for values that would never be produced by a well
+// behaved encoding function.
struct {
- uint64_t wire_largest_reference;
+ uint64_t encoded_required_insert_count;
uint64_t max_entries;
uint64_t total_number_of_inserts;
} kInvalidTestData[] = {
@@ -100,19 +102,19 @@
// https://github.com/quicwg/base-drafts/issues/2112#issue-389626872.
{1, 10, 2},
{18, 10, 2},
- // Largest Reference value too small or too large
+ // Encoded Required Insert Count value too small or too large
// for given MaxEntries and total number of insertions.
{400, 100, 500},
{601, 100, 500}};
-TEST(QpackProgressiveDecoderTest, DecodeLargestReferenceError) {
+TEST(QpackProgressiveDecoderTest, DecodeRequiredInsertCountError) {
for (size_t i = 0; i < QUIC_ARRAYSIZE(kInvalidTestData); ++i) {
- uint64_t decoded_largest_reference = 0;
- EXPECT_FALSE(QpackProgressiveDecoder::DecodeLargestReference(
- kInvalidTestData[i].wire_largest_reference,
+ uint64_t decoded_required_insert_count = 0;
+ EXPECT_FALSE(QpackProgressiveDecoder::DecodeRequiredInsertCount(
+ kInvalidTestData[i].encoded_required_insert_count,
kInvalidTestData[i].max_entries,
kInvalidTestData[i].total_number_of_inserts,
- &decoded_largest_reference))
+ &decoded_required_insert_count))
<< i;
}
}
diff --git a/quic/core/qpack/qpack_progressive_encoder.cc b/quic/core/qpack/qpack_progressive_encoder.cc
index 4d2a3cf..41433ff 100644
--- a/quic/core/qpack/qpack_progressive_encoder.cc
+++ b/quic/core/qpack/qpack_progressive_encoder.cc
@@ -48,8 +48,8 @@
DCHECK_LT(output->size(), max_length);
if (!prefix_encoded_ && !instruction_encoder_.HasNext()) {
- // TODO(bnc): Implement dynamic entries and set Largest Reference and
- // Delta Base Index accordingly.
+ // TODO(bnc): Implement dynamic entries and set Required Insert Count and
+ // Delta Base accordingly.
instruction_encoder_.set_varint(0);
instruction_encoder_.set_varint2(0);
instruction_encoder_.set_s_bit(false);
diff --git a/quic/core/quic_buffered_packet_store_test.cc b/quic/core/quic_buffered_packet_store_test.cc
index 027a26c..e214ff1 100644
--- a/quic/core/quic_buffered_packet_store_test.cc
+++ b/quic/core/quic_buffered_packet_store_test.cc
@@ -6,6 +6,7 @@
#include <list>
+#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
@@ -53,7 +54,7 @@
packet_content_("some encrypted content"),
packet_time_(QuicTime::Zero() + QuicTime::Delta::FromMicroseconds(42)),
packet_(packet_content_.data(), packet_content_.size(), packet_time_),
- invalid_version_(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED),
+ invalid_version_(UnsupportedQuicVersion()),
valid_version_(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_44) {}
protected:
diff --git a/quic/core/quic_connection.cc b/quic/core/quic_connection.cc
index f3a6767..d4c13c4 100644
--- a/quic/core/quic_connection.cc
+++ b/quic/core/quic_connection.cc
@@ -23,6 +23,7 @@
#include "net/third_party/quiche/src/quic/core/quic_config.h"
#include "net/third_party/quiche/src/quic/core/quic_packet_generator.h"
#include "net/third_party/quiche/src/quic/core/quic_pending_retransmission.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_exported_stats.h"
@@ -42,10 +43,6 @@
namespace {
-// The largest gap in packets we'll accept without closing the connection.
-// This will likely have to be tuned.
-const QuicPacketNumber kMaxPacketGap = 5000;
-
// Maximum number of acks received before sending an ack in response.
// TODO(fayang): Remove this constant when deprecating QUIC_VERSION_35.
const QuicPacketCount kMaxPacketsReceivedBeforeAckSend = 20;
@@ -74,7 +71,7 @@
const int kMinReleaseTimeIntoFutureMs = 1;
bool Near(QuicPacketNumber a, QuicPacketNumber b) {
- QuicPacketNumber delta = (a > b) ? a - b : b - a;
+ QuicPacketCount delta = (a > b) ? a - b : b - a;
return delta <= kMaxPacketGap;
}
@@ -244,15 +241,12 @@
peer_address_(initial_peer_address),
direct_peer_address_(initial_peer_address),
active_effective_peer_migration_type_(NO_CHANGE),
- highest_packet_sent_before_effective_peer_migration_(0),
last_packet_decrypted_(false),
last_size_(0),
current_packet_data_(nullptr),
last_decrypted_packet_level_(ENCRYPTION_NONE),
should_last_packet_instigate_acks_(false),
was_last_packet_missing_(false),
- largest_seen_packet_with_ack_(0),
- largest_seen_packet_with_stop_waiting_(0),
max_undecryptable_packets_(0),
max_tracked_packets_(kMaxTrackedPackets),
pending_version_negotiation_packet_(false),
@@ -344,10 +338,9 @@
processing_ack_frame_(false),
supports_release_time_(false),
release_time_into_future_(QuicTime::Delta::Zero()),
- donot_retransmit_old_window_updates_(false),
no_version_negotiation_(supported_versions.size() == 1),
- decrypt_packets_on_key_change_(
- GetQuicReloadableFlag(quic_decrypt_packets_on_key_change)) {
+ clear_probing_mark_after_packet_processing_(GetQuicReloadableFlag(
+ quic_clear_probing_mark_after_packet_processing)) {
if (ack_mode_ == ACK_DECIMATION) {
QUIC_RELOADABLE_FLAG_COUNT(quic_enable_ack_decimation);
}
@@ -359,10 +352,12 @@
<< "Created connection with connection_id: " << connection_id
<< " and version: "
<< QuicVersionToString(transport_version());
- QUIC_BUG_IF(connection_id.length() != sizeof(uint64_t) &&
- transport_version() < QUIC_VERSION_99)
- << "Cannot use connection ID of length " << connection_id.length()
- << " with version " << QuicVersionToString(transport_version());
+
+ QUIC_BUG_IF(!QuicUtils::IsConnectionIdValidForVersion(connection_id,
+ transport_version()))
+ << "QuicConnection: attempted to use connection ID " << connection_id
+ << " which is invalid with version "
+ << QuicVersionToString(transport_version());
framer_.set_visitor(this);
stats_.connection_creation_time = clock_->ApproximateNow();
@@ -441,16 +436,24 @@
if (config.HasClientSentConnectionOption(kACKD, perspective_)) {
ack_mode_ = ACK_DECIMATION;
}
- if (!GetQuicReloadableFlag(quic_enable_ack_decimation) &&
+ if ((!GetQuicReloadableFlag(quic_enable_ack_decimation) ||
+ GetQuicReloadableFlag(quic_keep_ack_decimation_reordering)) &&
config.HasClientSentConnectionOption(kAKD2, perspective_)) {
+ if (GetQuicReloadableFlag(quic_keep_ack_decimation_reordering)) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_keep_ack_decimation_reordering, 1, 2);
+ }
ack_mode_ = ACK_DECIMATION_WITH_REORDERING;
}
if (config.HasClientSentConnectionOption(kAKD3, perspective_)) {
ack_mode_ = ACK_DECIMATION;
ack_decimation_delay_ = kShortAckDecimationDelay;
}
- if (!GetQuicReloadableFlag(quic_enable_ack_decimation) &&
+ if ((!GetQuicReloadableFlag(quic_enable_ack_decimation) ||
+ GetQuicReloadableFlag(quic_keep_ack_decimation_reordering)) &&
config.HasClientSentConnectionOption(kAKD4, perspective_)) {
+ if (GetQuicReloadableFlag(quic_keep_ack_decimation_reordering)) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_keep_ack_decimation_reordering, 2, 2);
+ }
ack_mode_ = ACK_DECIMATION_WITH_REORDERING;
ack_decimation_delay_ = kShortAckDecimationDelay;
}
@@ -782,7 +785,7 @@
// Packets should have the version flag till version negotiation is
// done.
QuicString error_details =
- QuicStrCat(ENDPOINT, "Packet ", header.packet_number,
+ QuicStrCat(ENDPOINT, "Packet ", header.packet_number.ToUint64(),
" without version flag before version negotiated.");
QUIC_DLOG(WARNING) << error_details;
CloseConnection(QUIC_INVALID_VERSION, error_details,
@@ -840,7 +843,8 @@
current_effective_peer_migration_type_ = NO_CHANGE;
if (perspective_ == Perspective::IS_CLIENT) {
- if (header.packet_number > received_packet_manager_.GetLargestObserved()) {
+ if (!received_packet_manager_.GetLargestObserved().IsInitialized() ||
+ header.packet_number > received_packet_manager_.GetLargestObserved()) {
// Update peer_address_ and effective_peer_address_ immediately for
// client connections.
direct_peer_address_ = last_packet_source_address_;
@@ -944,22 +948,25 @@
QUIC_DVLOG(1) << ENDPOINT
<< "OnAckFrameStart, largest_acked: " << largest_acked;
- if (last_header_.packet_number <= largest_seen_packet_with_ack_) {
+ if (largest_seen_packet_with_ack_.IsInitialized() &&
+ last_header_.packet_number <= largest_seen_packet_with_ack_) {
QUIC_DLOG(INFO) << ENDPOINT << "Received an old ack frame: ignoring";
return true;
}
- if (largest_acked > sent_packet_manager_.GetLargestSentPacket()) {
+ if (!sent_packet_manager_.GetLargestSentPacket().IsInitialized() ||
+ largest_acked > sent_packet_manager_.GetLargestSentPacket()) {
QUIC_DLOG(WARNING) << ENDPOINT
<< "Peer's observed unsent packet:" << largest_acked
<< " vs " << sent_packet_manager_.GetLargestSentPacket();
- // We got an error for data we have not sent.
+ // We got an ack for data we have not sent.
CloseConnection(QUIC_INVALID_ACK_DATA, "Largest observed too high.",
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return false;
}
- if (largest_acked > sent_packet_manager_.GetLargestObserved()) {
+ if (!sent_packet_manager_.GetLargestObserved().IsInitialized() ||
+ largest_acked > sent_packet_manager_.GetLargestObserved()) {
visitor_->OnForwardProgressConfirmed();
} else if (largest_acked < sent_packet_manager_.GetLargestObserved()) {
QUIC_LOG(INFO) << ENDPOINT << "Peer's largest_observed packet decreased:"
@@ -984,7 +991,8 @@
DCHECK(connected_);
QUIC_DVLOG(1) << ENDPOINT << "OnAckRange: [" << start << ", " << end << ")";
- if (last_header_.packet_number <= largest_seen_packet_with_ack_) {
+ if (largest_seen_packet_with_ack_.IsInitialized() &&
+ last_header_.packet_number <= largest_seen_packet_with_ack_) {
QUIC_DLOG(INFO) << ENDPOINT << "Received an old ack frame: ignoring";
return true;
}
@@ -999,7 +1007,8 @@
QUIC_DVLOG(1) << ENDPOINT << "OnAckTimestamp: [" << packet_number << ", "
<< timestamp.ToDebuggingValue() << ")";
- if (last_header_.packet_number <= largest_seen_packet_with_ack_) {
+ if (largest_seen_packet_with_ack_.IsInitialized() &&
+ last_header_.packet_number <= largest_seen_packet_with_ack_) {
QUIC_DLOG(INFO) << ENDPOINT << "Received an old ack frame: ignoring";
return true;
}
@@ -1012,7 +1021,8 @@
DCHECK(connected_);
QUIC_DVLOG(1) << ENDPOINT << "OnAckFrameEnd, start: " << start;
- if (last_header_.packet_number <= largest_seen_packet_with_ack_) {
+ if (largest_seen_packet_with_ack_.IsInitialized() &&
+ last_header_.packet_number <= largest_seen_packet_with_ack_) {
QUIC_DLOG(INFO) << ENDPOINT << "Received an old ack frame: ignoring";
return true;
}
@@ -1051,7 +1061,8 @@
if (no_stop_waiting_frames_) {
return true;
}
- if (last_header_.packet_number <= largest_seen_packet_with_stop_waiting_) {
+ if (largest_seen_packet_with_stop_waiting_.IsInitialized() &&
+ last_header_.packet_number <= largest_seen_packet_with_stop_waiting_) {
QUIC_DLOG(INFO) << ENDPOINT
<< "Received an old stop waiting frame: ignoring";
return true;
@@ -1129,8 +1140,10 @@
const char* QuicConnection::ValidateStopWaitingFrame(
const QuicStopWaitingFrame& stop_waiting) {
- if (stop_waiting.least_unacked <
- received_packet_manager_.peer_least_packet_awaiting_ack()) {
+ if (received_packet_manager_.peer_least_packet_awaiting_ack()
+ .IsInitialized() &&
+ stop_waiting.least_unacked <
+ received_packet_manager_.peer_least_packet_awaiting_ack()) {
QUIC_DLOG(ERROR)
<< ENDPOINT
<< "Peer's sent low least_unacked: " << stop_waiting.least_unacked
@@ -1179,7 +1192,22 @@
}
bool QuicConnection::OnStopSendingFrame(const QuicStopSendingFrame& frame) {
- return visitor_->OnStopSendingFrame(frame);
+ DCHECK(connected_);
+
+ // Since a reset stream frame was received, this is not a connectivity probe.
+ // A probe only contains a PING and full padding.
+ UpdatePacketContent(NOT_PADDED_PING);
+
+ if (debug_visitor_ != nullptr) {
+ debug_visitor_->OnStopSendingFrame(frame);
+ }
+
+ QUIC_DLOG(INFO) << ENDPOINT << "STOP_SENDING frame received for stream: "
+ << frame.stream_id
+ << " with error: " << frame.application_error_code;
+
+ visitor_->OnStopSendingFrame(frame);
+ return connected_;
}
bool QuicConnection::OnPathChallengeFrame(const QuicPathChallengeFrame& frame) {
@@ -1439,8 +1467,10 @@
if (was_missing) {
// Only ack immediately if an ACK frame was sent with a larger
// largest acked than the newly received packet number.
- if (last_header_.packet_number <
- sent_packet_manager_.unacked_packets().largest_sent_largest_acked()) {
+ const QuicPacketNumber largest_sent_largest_acked =
+ sent_packet_manager_.unacked_packets().largest_sent_largest_acked();
+ if (largest_sent_largest_acked.IsInitialized() &&
+ last_header_.packet_number < largest_sent_largest_acked) {
ack_queued_ = true;
}
}
@@ -1448,7 +1478,10 @@
if (should_last_packet_instigate_acks_ && !ack_queued_) {
++num_retransmittable_packets_received_since_last_ack_sent_;
if (ack_mode_ != TCP_ACKING &&
- last_header_.packet_number > min_received_before_ack_decimation_) {
+ // TODO(fayang): Fix this as this check assumes the first received
+ // packet is 1.
+ last_header_.packet_number >
+ QuicPacketNumber(min_received_before_ack_decimation_)) {
// Ack up to 10 packets at once unless ack decimation is unlimited.
if (!unlimited_ack_decimation_ &&
num_retransmittable_packets_received_since_last_ack_sent_ >=
@@ -1497,7 +1530,8 @@
// If there are new missing packets to report, send an ack immediately.
if (received_packet_manager_.HasNewMissingPackets()) {
if (ack_mode_ == ACK_DECIMATION_WITH_REORDERING) {
- DCHECK(!GetQuicReloadableFlag(quic_enable_ack_decimation));
+ DCHECK(!GetQuicReloadableFlag(quic_enable_ack_decimation) ||
+ GetQuicReloadableFlag(quic_keep_ack_decimation_reordering));
// Wait the minimum of an eighth min_rtt and the existing ack time.
QuicTime ack_time =
clock_->ApproximateNow() +
@@ -1527,8 +1561,9 @@
void QuicConnection::CloseIfTooManyOutstandingSentPackets() {
// This occurs if we don't discard old packets we've seen fast enough. It's
// possible largest observed is less than leaset unacked.
- if (sent_packet_manager_.GetLargestObserved() >
- sent_packet_manager_.GetLeastUnacked() + max_tracked_packets_) {
+ if (sent_packet_manager_.GetLargestObserved().IsInitialized() &&
+ sent_packet_manager_.GetLargestObserved() >
+ sent_packet_manager_.GetLeastUnacked() + max_tracked_packets_) {
CloseConnection(
QUIC_TOO_MANY_OUTSTANDING_SENT_PACKETS,
QuicStrCat("More than ", max_tracked_packets_, " outstanding."),
@@ -1602,9 +1637,9 @@
OnWriteError(result.error_code);
return;
}
- if (result.status == WRITE_STATUS_BLOCKED) {
+ if (IsWriteBlockedStatus(result.status)) {
visitor_->OnWriteBlocked();
- if (writer_->IsWriteBlockedDataBuffered()) {
+ if (result.status == WRITE_STATUS_BLOCKED_DATA_BUFFERED) {
pending_version_negotiation_packet_ = false;
}
return;
@@ -1676,6 +1711,8 @@
++packet_iterator;
continue;
}
+ // NOTE THAT RemoveFramesForStream removes only STREAM frames
+ // for the specified stream.
RemoveFramesForStream(retransmittable_frames, id);
if (!retransmittable_frames->empty()) {
++packet_iterator;
@@ -1776,6 +1813,13 @@
<< "Unable to process packet. Last packet processed: "
<< last_header_.packet_number;
current_packet_data_ = nullptr;
+ if (clear_probing_mark_after_packet_processing_) {
+ if (is_current_packet_connectivity_probing_) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(
+ quic_clear_probing_mark_after_packet_processing, 1, 2);
+ }
+ is_current_packet_connectivity_probing_ = false;
+ }
return;
}
@@ -1787,8 +1831,10 @@
<< ", highest_packet_sent_before_effective_peer_migration_ = "
<< highest_packet_sent_before_effective_peer_migration_;
if (active_effective_peer_migration_type_ != NO_CHANGE &&
- sent_packet_manager_.GetLargestObserved() >
- highest_packet_sent_before_effective_peer_migration_) {
+ sent_packet_manager_.GetLargestObserved().IsInitialized() &&
+ (!highest_packet_sent_before_effective_peer_migration_.IsInitialized() ||
+ sent_packet_manager_.GetLargestObserved() >
+ highest_packet_sent_before_effective_peer_migration_)) {
if (perspective_ == Perspective::IS_SERVER) {
OnEffectivePeerMigrationValidated();
}
@@ -1798,6 +1844,13 @@
MaybeSendInResponseToPacket();
SetPingAlarm();
current_packet_data_ = nullptr;
+ if (clear_probing_mark_after_packet_processing_) {
+ if (is_current_packet_connectivity_probing_) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(
+ quic_clear_probing_mark_after_packet_processing, 2, 2);
+ }
+ is_current_packet_connectivity_probing_ = false;
+ }
}
void QuicConnection::OnBlockedWriterCanWrite() {
@@ -1883,7 +1936,7 @@
QUIC_RESTART_FLAG_COUNT_N(quic_enable_accept_random_ipn, 2, 2);
// Configured to accept any packet number in range 1...0x7fffffff
// as initial packet number.
- if (last_header_.packet_number != kInvalidPacketNumber) {
+ if (last_header_.packet_number.IsInitialized()) {
// The last packet's number is not 0. Ensure that this packet
// is reasonably close to where it should be.
if (!Near(header.packet_number, last_header_.packet_number)) {
@@ -1896,10 +1949,9 @@
}
} else {
// The "last packet's number" is 0, meaning that this packet is the first
- // one received. Ensure it is in range 1..kMaxRandomInitialPacketNumber,
+ // one received. Ensure it is in range 1..MaxRandomInitialPacketNumber(),
// inclusive.
- if ((header.packet_number == kInvalidPacketNumber) ||
- (header.packet_number > kMaxRandomInitialPacketNumber)) {
+ if ((header.packet_number > MaxRandomInitialPacketNumber())) {
// packet number is bad.
QUIC_DLOG(INFO) << ENDPOINT << "Initial packet " << header.packet_number
<< " out of bounds. Discarding";
@@ -1913,21 +1965,29 @@
// Count those that would have been accepted if FLAGS..random_ipn
// were true -- to detect/diagnose potential issues prior to
// enabling the flag.
- if ((header.packet_number > 1) &&
- (header.packet_number <= kMaxRandomInitialPacketNumber)) {
+ if ((header.packet_number > QuicPacketNumber(1)) &&
+ (header.packet_number <= MaxRandomInitialPacketNumber())) {
QUIC_CODE_COUNT_N(had_possibly_random_ipn, 2, 2);
}
-
- if (!Near(header.packet_number, last_header_.packet_number)) {
+ bool out_of_bound =
+ last_header_.packet_number.IsInitialized()
+ ? !Near(header.packet_number, last_header_.packet_number)
+ // TODO(fayang): Fix this as this check assume the first received
+ // packet is 1.
+ : header.packet_number > QuicPacketNumber(kMaxPacketGap);
+ if (out_of_bound) {
QUIC_DLOG(INFO) << ENDPOINT << "Packet " << header.packet_number
<< " out of bounds. Discarding";
QuicStringPiece packet_data = GetCurrentPacket();
const size_t kMaxPacketLengthInErrorDetails = 64;
CloseConnection(
QUIC_INVALID_PACKET_HEADER,
- QuicStrCat("Packet number out of bounds. last_pkn=",
- last_header_.packet_number,
- ", current_pkn=", header.packet_number,
+ QuicStrCat("Packet number out of bounds. ",
+ last_header_.packet_number.IsInitialized()
+ ? QuicStrCat("last_pkn=",
+ last_header_.packet_number.ToUint64())
+ : "first received packet",
+ ", current_pkn=", header.packet_number.ToUint64(),
", current_pkt_len=", packet_data.length(),
", current_hdr=",
QuicTextUtils::HexEncode(
@@ -2127,7 +2187,8 @@
++stats_.packets_discarded;
return true;
}
- if (packet->packet_number < sent_packet_manager_.GetLargestSentPacket()) {
+ if (sent_packet_manager_.GetLargestSentPacket().IsInitialized() &&
+ packet->packet_number < sent_packet_manager_.GetLargestSentPacket()) {
QUIC_BUG << "Attempt to write packet:" << packet->packet_number
<< " after:" << sent_packet_manager_.GetLargestSentPacket();
CloseConnection(QUIC_INTERNAL_ERROR, "Packet written out of order.",
@@ -2198,7 +2259,7 @@
WRITE_STATUS_NUM_VALUES,
"Status code returned by writer_->WritePacket() in QuicConnection.");
- if (result.status == WRITE_STATUS_BLOCKED) {
+ if (IsWriteBlockedStatus(result.status)) {
// Ensure the writer is still write blocked, otherwise QUIC may continue
// trying to write when it will not be able to.
DCHECK(writer_->IsWriteBlocked());
@@ -2207,7 +2268,7 @@
// be queued and sent again, which would result in an unnecessary
// duplicate packet being sent. The helper must call OnCanWrite
// when the write completes, and OnWriteError if an error occurs.
- if (!writer_->IsWriteBlockedDataBuffered()) {
+ if (result.status != WRITE_STATUS_BLOCKED_DATA_BUFFERED) {
return false;
}
}
@@ -2314,6 +2375,14 @@
}
WriteResult result = writer_->Flush();
+
+ if (HandleWriteBlocked()) {
+ DCHECK_EQ(WRITE_STATUS_BLOCKED, result.status)
+ << "Unexpected flush result:" << result;
+ QUIC_DLOG(INFO) << ENDPOINT << "Write blocked in FlushPackets.";
+ return;
+ }
+
if (IsWriteError(result.status)) {
OnWriteError(result.error_code);
}
@@ -2402,7 +2471,7 @@
if (transport_version() != QUIC_VERSION_35) {
if (serialized_packet->retransmittable_frames.empty() &&
- serialized_packet->original_packet_number == kInvalidPacketNumber) {
+ !serialized_packet->original_packet_number.IsInitialized()) {
// Increment consecutive_num_packets_with_no_retransmittable_frames_ if
// this packet is a new transmission with no retransmittable frames.
++consecutive_num_packets_with_no_retransmittable_frames_;
@@ -2496,8 +2565,7 @@
}
consecutive_num_packets_with_no_retransmittable_frames_ = 0;
if (packet_generator_.HasRetransmittableFrames() ||
- (donot_retransmit_old_window_updates_ &&
- visitor_->WillingAndAbleToWrite())) {
+ visitor_->WillingAndAbleToWrite()) {
// There are pending retransmittable frames.
return;
}
@@ -2569,11 +2637,7 @@
void QuicConnection::SetDecrypter(EncryptionLevel level,
std::unique_ptr<QuicDecrypter> decrypter) {
framer_.SetDecrypter(level, std::move(decrypter));
- if (!decrypt_packets_on_key_change_) {
- return;
- }
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_decrypt_packets_on_key_change, 1, 3);
if (!undecryptable_packets_.empty() &&
!process_undecryptable_packets_alarm_->IsSet()) {
process_undecryptable_packets_alarm_->Set(clock_->ApproximateNow());
@@ -2585,11 +2649,7 @@
std::unique_ptr<QuicDecrypter> decrypter,
bool latch_once_used) {
framer_.SetAlternativeDecrypter(level, std::move(decrypter), latch_once_used);
- if (!decrypt_packets_on_key_change_) {
- return;
- }
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_decrypt_packets_on_key_change, 2, 3);
if (!undecryptable_packets_.empty() &&
!process_undecryptable_packets_alarm_->IsSet()) {
process_undecryptable_packets_alarm_->Set(clock_->ApproximateNow());
@@ -2611,10 +2671,7 @@
}
void QuicConnection::MaybeProcessUndecryptablePackets() {
- if (decrypt_packets_on_key_change_) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_decrypt_packets_on_key_change, 3, 3);
- process_undecryptable_packets_alarm_->Cancel();
- }
+ process_undecryptable_packets_alarm_->Cancel();
if (undecryptable_packets_.empty() || encryption_level_ == ENCRYPTION_NONE) {
return;
@@ -3071,6 +3128,9 @@
packet_generator_.GenerateMtuDiscoveryPacket(target_mtu);
}
+// TODO(zhongyi): change this method to generate a connectivity probing packet
+// and let the caller to call writer to write the packet and handle write
+// status.
bool QuicConnection::SendConnectivityProbingPacket(
QuicPacketWriter* probing_writer,
const QuicSocketAddress& peer_address) {
@@ -3186,13 +3246,13 @@
packet_send_time, probing_packet->transmission_type,
NO_RETRANSMITTABLE_DATA);
- if (result.status == WRITE_STATUS_BLOCKED) {
+ if (IsWriteBlockedStatus(result.status)) {
if (probing_writer == writer_) {
// Visitor should not be write blocked if the probing writer is not the
// default packet writer.
visitor_->OnWriteBlocked();
}
- if (probing_writer->IsWriteBlockedDataBuffered()) {
+ if (result.status == WRITE_STATUS_BLOCKED_DATA_BUFFERED) {
QUIC_DLOG(INFO) << ENDPOINT << "Write probing packet blocked";
}
}
@@ -3228,7 +3288,7 @@
QUIC_BUG << "No migration underway.";
return;
}
- highest_packet_sent_before_effective_peer_migration_ = 0;
+ highest_packet_sent_before_effective_peer_migration_.Clear();
active_effective_peer_migration_type_ = NO_CHANGE;
}
@@ -3382,8 +3442,9 @@
}
current_packet_content_ = NOT_PADDED_PING;
- if (last_header_.packet_number ==
- received_packet_manager_.GetLargestObserved()) {
+ if (received_packet_manager_.GetLargestObserved().IsInitialized() &&
+ last_header_.packet_number ==
+ received_packet_manager_.GetLargestObserved()) {
direct_peer_address_ = last_packet_source_address_;
if (current_effective_peer_migration_type_ != NO_CHANGE) {
// Start effective peer migration immediately when the current packet is
diff --git a/quic/core/quic_connection.h b/quic/core/quic_connection.h
index 0f50e96..221754f 100644
--- a/quic/core/quic_connection.h
+++ b/quic/core/quic_connection.h
@@ -297,6 +297,9 @@
// Called when RTT may have changed, including when an RTT is read from
// the config.
virtual void OnRttChanged(QuicTime::Delta rtt) const {}
+
+ // Called when a StopSendingFrame has been parsed.
+ virtual void OnStopSendingFrame(const QuicStopSendingFrame& frame) {}
};
class QUIC_EXPORT_PRIVATE QuicConnectionHelperInterface {
@@ -792,6 +795,20 @@
fill_up_link_during_probing_ = new_value;
}
+ // This setting may be changed during the crypto handshake in order to
+ // enable/disable padding of different packets in the crypto handshake.
+ //
+ // This setting should never be set to false in public facing endpoints. It
+ // can only be set to false if there is some other mechanism of preventing
+ // amplification attacks, such as ICE (plus its a non-standard quic).
+ void set_fully_pad_crypto_hadshake_packets(bool new_value) {
+ packet_generator_.set_fully_pad_crypto_hadshake_packets(new_value);
+ }
+
+ bool fully_pad_during_crypto_handshake() const {
+ return packet_generator_.fully_pad_crypto_handshake_packets();
+ }
+
size_t min_received_before_ack_decimation() const {
return min_received_before_ack_decimation_;
}
@@ -803,7 +820,7 @@
return ack_frequency_before_ack_decimation_;
}
void set_ack_frequency_before_ack_decimation(size_t new_value) {
- DCHECK_GT(new_value, 0);
+ DCHECK_GT(new_value, 0u);
ack_frequency_before_ack_decimation_ = new_value;
}
@@ -827,20 +844,9 @@
bool IsPathDegrading() const { return is_path_degrading_; }
- // TODO(wub): Remove this function once
- // quic_donot_retransmit_old_window_update flag is deprecated.
- void set_donot_retransmit_old_window_updates(bool value) {
- donot_retransmit_old_window_updates_ = value;
- }
-
// Attempts to process any queued undecryptable packets.
void MaybeProcessUndecryptablePackets();
- // Whether the handshake is confirmed from this connection's perspective.
- bool IsHandshakeConfirmed() const {
- return sent_packet_manager_.handshake_confirmed();
- }
-
enum PacketContent : uint8_t {
NO_FRAMES_RECEIVED,
// TODO(fkastenholz): Change name when we get rid of padded ping/
@@ -851,6 +857,11 @@
NOT_PADDED_PING, // Set if the packet is not {PING, PADDING}.
};
+ // Whether the handshake is confirmed from this connection's perspective.
+ bool IsHandshakeConfirmed() const {
+ return sent_packet_manager_.handshake_confirmed();
+ }
+
protected:
// Calls cancel() on all the alarms owned by this connection.
void CancelAllAlarms();
@@ -1076,10 +1087,9 @@
// Contents received in the current packet, especially used to identify
// whether the current packet is a padded PING packet.
PacketContent current_packet_content_;
- // True if the packet currently being processed is a connectivity probing
- // packet. Is set to false when a new packet is received, and will be set to
- // true as soon as |current_packet_content_| is set to
- // SECOND_FRAME_IS_PADDING.
+ // Set to true as soon as the packet currently being processed has been
+ // detected as a connectivity probing.
+ // Always false outside the context of ProcessUdpPacket().
bool is_current_packet_connectivity_probing_;
// Caches the current effective peer migration type if a effective peer
@@ -1385,16 +1395,13 @@
// Time this connection can release packets into the future.
QuicTime::Delta release_time_into_future_;
- // Latched value of quic_donot_retransmit_old_window_update flag.
- bool donot_retransmit_old_window_updates_;
-
// Indicates whether server connection does version negotiation. Server
// connection does not support version negotiation if a single version is
// provided in constructor.
const bool no_version_negotiation_;
- // Latched value of quic_decrypt_packets_on_key_change flag.
- const bool decrypt_packets_on_key_change_;
+ // Latched value of --quic_clear_probing_mark_after_packet_processing.
+ const bool clear_probing_mark_after_packet_processing_;
// Payload of most recently transmitted QUIC_VERSION_99 connectivity
// probe packet (the PATH_CHALLENGE payload). This implementation transmits
diff --git a/quic/core/quic_connection_stats.h b/quic/core/quic_connection_stats.h
index 07ca80f..8123fb0 100644
--- a/quic/core/quic_connection_stats.h
+++ b/quic/core/quic_connection_stats.h
@@ -73,7 +73,7 @@
// Number of packets received out of packet number order.
QuicPacketCount packets_reordered;
// Maximum reordering observed in packet number space.
- QuicPacketNumber max_sequence_reordering;
+ QuicPacketCount max_sequence_reordering;
// Maximum reordering observed in microseconds
int64_t max_time_reordering_us;
diff --git a/quic/core/quic_connection_test.cc b/quic/core/quic_connection_test.cc
index 63f4453..fe851fd 100644
--- a/quic/core/quic_connection_test.cc
+++ b/quic/core/quic_connection_test.cc
@@ -17,6 +17,7 @@
#include "net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h"
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/core/quic_simple_buffer_allocator.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
@@ -102,7 +103,7 @@
bool SetIV(QuicStringPiece iv) override { return true; }
bool EncryptPacket(QuicTransportVersion /*version*/,
- QuicPacketNumber packet_number,
+ uint64_t packet_number,
QuicStringPiece associated_data,
QuicStringPiece plaintext,
char* output,
@@ -167,7 +168,7 @@
}
bool DecryptPacket(QuicTransportVersion /*version*/,
- QuicPacketNumber packet_number,
+ uint64_t packet_number,
QuicStringPiece associated_data,
QuicStringPiece ciphertext,
char* output,
@@ -288,6 +289,7 @@
last_packet_size_(0),
write_blocked_(false),
write_should_fail_(false),
+ block_on_next_flush_(false),
block_on_next_write_(false),
next_packet_too_large_(false),
always_get_packet_too_large_(false),
@@ -336,11 +338,14 @@
return WriteResult(WRITE_STATUS_ERROR, EMSGSIZE);
}
if (IsWriteBlocked()) {
- return WriteResult(WRITE_STATUS_BLOCKED, EAGAIN);
+ return WriteResult(is_write_blocked_data_buffered_
+ ? WRITE_STATUS_BLOCKED_DATA_BUFFERED
+ : WRITE_STATUS_BLOCKED,
+ 0);
}
if (ShouldWriteFail()) {
- return WriteResult(WRITE_STATUS_ERROR, EAGAIN);
+ return WriteResult(WRITE_STATUS_ERROR, 0);
}
last_packet_size_ = packet.length();
@@ -380,7 +385,16 @@
return nullptr;
}
- WriteResult Flush() override { return WriteResult(WRITE_STATUS_OK, 0); }
+ WriteResult Flush() override {
+ if (block_on_next_flush_) {
+ block_on_next_flush_ = false;
+ SetWriteBlocked();
+ return WriteResult(WRITE_STATUS_BLOCKED, /*errno*/ -1);
+ }
+ return WriteResult(WRITE_STATUS_OK, 0);
+ }
+
+ void BlockOnNextFlush() { block_on_next_flush_ = true; }
void BlockOnNextWrite() { block_on_next_write_ = true; }
@@ -493,6 +507,8 @@
supports_release_time_ = supports_release_time;
}
+ SimpleQuicFramer* framer() { return &framer_; }
+
private:
ParsedQuicVersion version_;
SimpleQuicFramer framer_;
@@ -500,6 +516,7 @@
QuicPacketHeader last_packet_header_;
bool write_blocked_;
bool write_should_fail_;
+ bool block_on_next_flush_;
bool block_on_next_write_;
bool next_packet_too_large_;
bool always_get_packet_too_large_;
@@ -554,7 +571,7 @@
}
void SendPacket(EncryptionLevel level,
- QuicPacketNumber packet_number,
+ uint64_t packet_number,
std::unique_ptr<QuicPacket> packet,
HasRetransmittableData retransmittable,
bool has_ack,
@@ -562,10 +579,11 @@
char buffer[kMaxPacketSize];
size_t encrypted_length =
QuicConnectionPeer::GetFramer(this)->EncryptPayload(
- ENCRYPTION_NONE, packet_number, *packet, buffer, kMaxPacketSize);
+ ENCRYPTION_NONE, QuicPacketNumber(packet_number), *packet, buffer,
+ kMaxPacketSize);
SerializedPacket serialized_packet(
- packet_number, PACKET_4BYTE_PACKET_NUMBER, buffer, encrypted_length,
- has_ack, has_pending_frames);
+ QuicPacketNumber(packet_number), PACKET_4BYTE_PACKET_NUMBER, buffer,
+ encrypted_length, has_ack, has_pending_frames);
if (retransmittable == HAS_RETRANSMITTABLE_DATA) {
serialized_packet.retransmittable_frames.push_back(
QuicFrame(QuicStreamFrame()));
@@ -580,7 +598,7 @@
QuicStreamOffset offset,
StreamSendingState state) {
ScopedPacketFlusher flusher(this, NO_ACK);
- producer_.SaveStreamData(id, iov, iov_count, 0u, offset, total_length);
+ producer_.SaveStreamData(id, iov, iov_count, 0u, total_length);
if (notifier_ != nullptr) {
return notifier_->WriteOrBufferData(id, total_length, state);
}
@@ -902,14 +920,14 @@
QuicPacketNumber least_unacked() {
if (writer_->stop_waiting_frames().empty()) {
- return 0;
+ return QuicPacketNumber();
}
return writer_->stop_waiting_frames()[0].least_unacked;
}
void use_tagging_decrypter() { writer_->use_tagging_decrypter(); }
- void ProcessPacket(QuicPacketNumber number) {
+ void ProcessPacket(uint64_t number) {
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
ProcessDataPacket(number);
if (connection_.GetSendAlarm()->IsSet()) {
@@ -984,7 +1002,7 @@
QuicReceivedPacket(encrypted_buffer, encrypted_length, clock_.Now()));
}
- size_t ProcessFramePacketAtLevel(QuicPacketNumber number,
+ size_t ProcessFramePacketAtLevel(uint64_t number,
QuicFrame frame,
EncryptionLevel level) {
QuicPacketHeader header;
@@ -995,32 +1013,43 @@
peer_framer_.perspective() == Perspective::IS_SERVER) {
header.destination_connection_id_length = PACKET_0BYTE_CONNECTION_ID;
}
- header.packet_number = number;
+ header.packet_number = QuicPacketNumber(number);
QuicFrames frames;
frames.push_back(frame);
std::unique_ptr<QuicPacket> packet(ConstructPacket(header, frames));
char buffer[kMaxPacketSize];
- size_t encrypted_length =
- framer_.EncryptPayload(level, number, *packet, buffer, kMaxPacketSize);
+ size_t encrypted_length = framer_.EncryptPayload(
+ level, QuicPacketNumber(number), *packet, buffer, kMaxPacketSize);
connection_.ProcessUdpPacket(
kSelfAddress, kPeerAddress,
QuicReceivedPacket(buffer, encrypted_length, QuicTime::Zero(), false));
return encrypted_length;
}
- size_t ProcessDataPacket(QuicPacketNumber number) {
+ size_t ProcessDataPacket(uint64_t number) {
return ProcessDataPacketAtLevel(number, false, ENCRYPTION_NONE);
}
- size_t ProcessDataPacketAtLevel(QuicPacketNumber number,
+ size_t ProcessDataPacket(QuicPacketNumber packet_number) {
+ return ProcessDataPacketAtLevel(packet_number, false, ENCRYPTION_NONE);
+ }
+
+ size_t ProcessDataPacketAtLevel(QuicPacketNumber packet_number,
+ bool has_stop_waiting,
+ EncryptionLevel level) {
+ return ProcessDataPacketAtLevel(packet_number.ToUint64(), has_stop_waiting,
+ level);
+ }
+
+ size_t ProcessDataPacketAtLevel(uint64_t number,
bool has_stop_waiting,
EncryptionLevel level) {
std::unique_ptr<QuicPacket> packet(
ConstructDataPacket(number, has_stop_waiting));
char buffer[kMaxPacketSize];
size_t encrypted_length = peer_framer_.EncryptPayload(
- level, number, *packet, buffer, kMaxPacketSize);
+ level, QuicPacketNumber(number), *packet, buffer, kMaxPacketSize);
connection_.ProcessUdpPacket(
kSelfAddress, kPeerAddress,
QuicReceivedPacket(buffer, encrypted_length, clock_.Now(), false));
@@ -1030,11 +1059,12 @@
return encrypted_length;
}
- void ProcessClosePacket(QuicPacketNumber number) {
+ void ProcessClosePacket(uint64_t number) {
std::unique_ptr<QuicPacket> packet(ConstructClosePacket(number));
char buffer[kMaxPacketSize];
- size_t encrypted_length = peer_framer_.EncryptPayload(
- ENCRYPTION_NONE, number, *packet, buffer, kMaxPacketSize);
+ size_t encrypted_length =
+ peer_framer_.EncryptPayload(ENCRYPTION_NONE, QuicPacketNumber(number),
+ *packet, buffer, kMaxPacketSize);
connection_.ProcessUdpPacket(
kSelfAddress, kPeerAddress,
QuicReceivedPacket(buffer, encrypted_length, QuicTime::Zero(), false));
@@ -1084,8 +1114,12 @@
connection_.OnStreamReset(id, error);
}
- void ProcessAckPacket(QuicPacketNumber packet_number, QuicAckFrame* frame) {
- QuicPacketCreatorPeer::SetPacketNumber(&peer_creator_, packet_number - 1);
+ void ProcessAckPacket(uint64_t packet_number, QuicAckFrame* frame) {
+ if (packet_number > 1) {
+ QuicPacketCreatorPeer::SetPacketNumber(&peer_creator_, packet_number - 1);
+ } else {
+ QuicPacketCreatorPeer::ClearPacketNumber(&peer_creator_);
+ }
ProcessFramePacket(QuicFrame(frame));
}
@@ -1097,7 +1131,7 @@
ProcessFramePacket(QuicFrame(frame));
}
- size_t ProcessStopWaitingPacketAtLevel(QuicPacketNumber number,
+ size_t ProcessStopWaitingPacketAtLevel(uint64_t number,
QuicStopWaitingFrame* frame,
EncryptionLevel level) {
return ProcessFramePacketAtLevel(number, QuicFrame(frame),
@@ -1108,8 +1142,9 @@
ProcessFramePacket(QuicFrame(frame));
}
- bool IsMissing(QuicPacketNumber number) {
- return IsAwaitingPacket(*outgoing_ack(), number, 0);
+ bool IsMissing(uint64_t number) {
+ return IsAwaitingPacket(*outgoing_ack(), QuicPacketNumber(number),
+ QuicPacketNumber());
}
std::unique_ptr<QuicPacket> ConstructPacket(const QuicPacketHeader& header,
@@ -1119,7 +1154,7 @@
return packet;
}
- std::unique_ptr<QuicPacket> ConstructDataPacket(QuicPacketNumber number,
+ std::unique_ptr<QuicPacket> ConstructDataPacket(uint64_t number,
bool has_stop_waiting) {
QuicPacketHeader header;
// Set connection_id to peer's in memory representation as this data packet
@@ -1131,7 +1166,7 @@
peer_framer_.perspective() == Perspective::IS_SERVER) {
header.destination_connection_id_length = PACKET_0BYTE_CONNECTION_ID;
}
- header.packet_number = number;
+ header.packet_number = QuicPacketNumber(number);
QuicFrames frames;
frames.push_back(QuicFrame(frame1_));
@@ -1153,12 +1188,12 @@
&peer_creator_);
}
- std::unique_ptr<QuicPacket> ConstructClosePacket(QuicPacketNumber number) {
+ std::unique_ptr<QuicPacket> ConstructClosePacket(uint64_t number) {
QuicPacketHeader header;
// Set connection_id to peer's in memory representation as this connection
// close packet is created by peer_framer.
header.destination_connection_id = connection_id_;
- header.packet_number = number;
+ header.packet_number = QuicPacketNumber(number);
if (peer_framer_.transport_version() > QUIC_VERSION_43 &&
peer_framer_.perspective() == Perspective::IS_SERVER) {
header.destination_connection_id_length = PACKET_0BYTE_CONNECTION_ID;
@@ -1180,22 +1215,27 @@
return QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs);
}
- const QuicStopWaitingFrame InitStopWaitingFrame(
- QuicPacketNumber least_unacked) {
+ const QuicStopWaitingFrame InitStopWaitingFrame(uint64_t least_unacked) {
QuicStopWaitingFrame frame;
- frame.least_unacked = least_unacked;
+ frame.least_unacked = QuicPacketNumber(least_unacked);
return frame;
}
// Construct a ack_frame that acks all packet numbers between 1 and
// |largest_acked|, except |missing|.
// REQUIRES: 1 <= |missing| < |largest_acked|
+ QuicAckFrame ConstructAckFrame(uint64_t largest_acked, uint64_t missing) {
+ return ConstructAckFrame(QuicPacketNumber(largest_acked),
+ QuicPacketNumber(missing));
+ }
+
QuicAckFrame ConstructAckFrame(QuicPacketNumber largest_acked,
QuicPacketNumber missing) {
- if (missing == 1) {
+ if (missing == QuicPacketNumber(1)) {
return InitAckFrame({{missing + 1, largest_acked + 1}});
}
- return InitAckFrame({{1, missing}, {missing + 1, largest_acked + 1}});
+ return InitAckFrame(
+ {{QuicPacketNumber(1), missing}, {missing + 1, largest_acked + 1}});
}
// Undo nacking a packet within the frame.
@@ -1211,7 +1251,7 @@
// Call ProcessDataPacket rather than ProcessPacket, as we should not get a
// packet call to the visitor.
if (GetQuicRestartFlag(quic_enable_accept_random_ipn)) {
- ProcessDataPacket(kMaxRandomInitialPacketNumber + 6000);
+ ProcessDataPacket(MaxRandomInitialPacketNumber() + 6000);
} else {
ProcessDataPacket(6000);
}
@@ -1256,8 +1296,8 @@
const QuicPacketCount packets_between_probes_base) {
QuicConnectionPeer::SetPacketsBetweenMtuProbes(&connection_,
packets_between_probes_base);
- QuicConnectionPeer::SetNextMtuProbeAt(&connection_,
- packets_between_probes_base);
+ QuicConnectionPeer::SetNextMtuProbeAt(
+ &connection_, QuicPacketNumber(packets_between_probes_base));
}
bool IsDefaultTestConfiguration() {
@@ -1577,9 +1617,15 @@
probing_packet->encrypted_length),
clock_.Now()));
+ uint64_t num_probing_received =
+ connection_.GetStats().num_connectivity_probing_received;
ProcessReceivedPacket(kSelfAddress, kPeerAddress, *received);
- EXPECT_FALSE(connection_.IsCurrentPacketConnectivityProbing());
+ if (!GetQuicReloadableFlag(quic_clear_probing_mark_after_packet_processing)) {
+ EXPECT_FALSE(connection_.IsCurrentPacketConnectivityProbing());
+ }
+ EXPECT_EQ(num_probing_received,
+ connection_.GetStats().num_connectivity_probing_received);
EXPECT_EQ(kPeerAddress, connection_.peer_address());
EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
}
@@ -1673,9 +1719,15 @@
probing_packet->encrypted_length),
clock_.Now()));
+ uint64_t num_probing_received =
+ connection_.GetStats().num_connectivity_probing_received;
ProcessReceivedPacket(kSelfAddress, kNewPeerAddress, *received);
- EXPECT_TRUE(connection_.IsCurrentPacketConnectivityProbing());
+ if (!GetQuicReloadableFlag(quic_clear_probing_mark_after_packet_processing)) {
+ EXPECT_TRUE(connection_.IsCurrentPacketConnectivityProbing());
+ }
+ EXPECT_EQ(num_probing_received + 1,
+ connection_.GetStats().num_connectivity_probing_received);
EXPECT_EQ(kPeerAddress, connection_.peer_address());
EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
@@ -1730,9 +1782,15 @@
probing_packet->encrypted_length),
clock_.Now()));
+ uint64_t num_probing_received =
+ connection_.GetStats().num_connectivity_probing_received;
ProcessReceivedPacket(kSelfAddress, kNewPeerAddress, *received);
- EXPECT_TRUE(connection_.IsCurrentPacketConnectivityProbing());
+ if (!GetQuicReloadableFlag(quic_clear_probing_mark_after_packet_processing)) {
+ EXPECT_TRUE(connection_.IsCurrentPacketConnectivityProbing());
+ }
+ EXPECT_EQ(num_probing_received + 1,
+ connection_.GetStats().num_connectivity_probing_received);
EXPECT_EQ(kPeerAddress, connection_.peer_address());
EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
}
@@ -1819,9 +1877,15 @@
QuicEncryptedPacket(probing_packet->encrypted_buffer,
probing_packet->encrypted_length),
clock_.Now()));
+ uint64_t num_probing_received =
+ connection_.GetStats().num_connectivity_probing_received;
ProcessReceivedPacket(kSelfAddress, kPeerAddress, *received);
- EXPECT_FALSE(connection_.IsCurrentPacketConnectivityProbing());
+ if (!GetQuicReloadableFlag(quic_clear_probing_mark_after_packet_processing)) {
+ EXPECT_FALSE(connection_.IsCurrentPacketConnectivityProbing());
+ }
+ EXPECT_EQ(num_probing_received,
+ connection_.GetStats().num_connectivity_probing_received);
EXPECT_EQ(kPeerAddress, connection_.peer_address());
EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
}
@@ -1861,9 +1925,15 @@
QuicEncryptedPacket(probing_packet->encrypted_buffer,
probing_packet->encrypted_length),
clock_.Now()));
+ uint64_t num_probing_received =
+ connection_.GetStats().num_connectivity_probing_received;
ProcessReceivedPacket(kNewSelfAddress, kPeerAddress, *received);
- EXPECT_TRUE(connection_.IsCurrentPacketConnectivityProbing());
+ if (!GetQuicReloadableFlag(quic_clear_probing_mark_after_packet_processing)) {
+ EXPECT_TRUE(connection_.IsCurrentPacketConnectivityProbing());
+ }
+ EXPECT_EQ(num_probing_received + 1,
+ connection_.GetStats().num_connectivity_probing_received);
EXPECT_EQ(kPeerAddress, connection_.peer_address());
EXPECT_EQ(kPeerAddress, connection_.effective_peer_address());
}
@@ -1923,7 +1993,7 @@
QuicPacketHeader header;
header.destination_connection_id = connection_id_;
header.version_flag = true;
- header.packet_number = 1;
+ header.packet_number = QuicPacketNumber(1);
QuicFrames frames;
QuicPaddingFrame padding;
@@ -1932,7 +2002,7 @@
std::unique_ptr<QuicPacket> packet(ConstructPacket(header, frames));
char buffer[kMaxPacketSize];
size_t encrypted_length = peer_framer_.EncryptPayload(
- ENCRYPTION_NONE, 12, *packet, buffer, kMaxPacketSize);
+ ENCRYPTION_NONE, QuicPacketNumber(12), *packet, buffer, kMaxPacketSize);
EXPECT_EQ(kMaxPacketSize, encrypted_length);
framer_.set_version(version());
@@ -1956,7 +2026,7 @@
QuicPacketHeader header;
header.destination_connection_id = connection_id_;
header.version_flag = true;
- header.packet_number = 1;
+ header.packet_number = QuicPacketNumber(1);
QuicFrames frames;
QuicPaddingFrame padding;
@@ -1965,7 +2035,7 @@
std::unique_ptr<QuicPacket> packet(ConstructPacket(header, frames));
char buffer[kMaxPacketSize];
size_t encrypted_length = peer_framer_.EncryptPayload(
- ENCRYPTION_NONE, 12, *packet, buffer, kMaxPacketSize);
+ ENCRYPTION_NONE, QuicPacketNumber(12), *packet, buffer, kMaxPacketSize);
EXPECT_EQ(kMaxPacketSize, encrypted_length);
framer_.set_version(version());
@@ -2005,15 +2075,15 @@
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
ProcessPacket(1);
- EXPECT_EQ(1u, LargestAcked(*outgoing_ack()));
+ EXPECT_EQ(QuicPacketNumber(1u), LargestAcked(*outgoing_ack()));
EXPECT_EQ(1u, outgoing_ack()->packets.NumIntervals());
ProcessPacket(2);
- EXPECT_EQ(2u, LargestAcked(*outgoing_ack()));
+ EXPECT_EQ(QuicPacketNumber(2u), LargestAcked(*outgoing_ack()));
EXPECT_EQ(1u, outgoing_ack()->packets.NumIntervals());
ProcessPacket(3);
- EXPECT_EQ(3u, LargestAcked(*outgoing_ack()));
+ EXPECT_EQ(QuicPacketNumber(3u), LargestAcked(*outgoing_ack()));
EXPECT_EQ(1u, outgoing_ack()->packets.NumIntervals());
}
@@ -2021,17 +2091,17 @@
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
ProcessPacket(3);
- EXPECT_EQ(3u, LargestAcked(*outgoing_ack()));
+ EXPECT_EQ(QuicPacketNumber(3u), LargestAcked(*outgoing_ack()));
EXPECT_TRUE(IsMissing(2));
EXPECT_TRUE(IsMissing(1));
ProcessPacket(2);
- EXPECT_EQ(3u, LargestAcked(*outgoing_ack()));
+ EXPECT_EQ(QuicPacketNumber(3u), LargestAcked(*outgoing_ack()));
EXPECT_FALSE(IsMissing(2));
EXPECT_TRUE(IsMissing(1));
ProcessPacket(1);
- EXPECT_EQ(3u, LargestAcked(*outgoing_ack()));
+ EXPECT_EQ(QuicPacketNumber(3u), LargestAcked(*outgoing_ack()));
EXPECT_FALSE(IsMissing(2));
EXPECT_FALSE(IsMissing(1));
}
@@ -2040,14 +2110,14 @@
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
ProcessPacket(3);
- EXPECT_EQ(3u, LargestAcked(*outgoing_ack()));
+ EXPECT_EQ(QuicPacketNumber(3u), LargestAcked(*outgoing_ack()));
EXPECT_TRUE(IsMissing(2));
EXPECT_TRUE(IsMissing(1));
// Send packet 3 again, but do not set the expectation that
// the visitor OnStreamFrame() will be called.
ProcessDataPacket(3);
- EXPECT_EQ(3u, LargestAcked(*outgoing_ack()));
+ EXPECT_EQ(QuicPacketNumber(3u), LargestAcked(*outgoing_ack()));
EXPECT_TRUE(IsMissing(2));
EXPECT_TRUE(IsMissing(1));
}
@@ -2056,16 +2126,16 @@
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
ProcessPacket(3);
- EXPECT_EQ(3u, LargestAcked(*outgoing_ack()));
+ EXPECT_EQ(QuicPacketNumber(3u), LargestAcked(*outgoing_ack()));
EXPECT_TRUE(IsMissing(2));
EXPECT_TRUE(IsMissing(1));
ProcessPacket(2);
- EXPECT_EQ(3u, LargestAcked(*outgoing_ack()));
+ EXPECT_EQ(QuicPacketNumber(3u), LargestAcked(*outgoing_ack()));
EXPECT_TRUE(IsMissing(1));
ProcessPacket(5);
- EXPECT_EQ(5u, LargestAcked(*outgoing_ack()));
+ EXPECT_EQ(QuicPacketNumber(5u), LargestAcked(*outgoing_ack()));
EXPECT_TRUE(IsMissing(1));
EXPECT_TRUE(IsMissing(4));
@@ -2089,7 +2159,7 @@
// Call ProcessDataPacket rather than ProcessPacket, as we should not get a
// packet call to the visitor.
if (GetQuicRestartFlag(quic_enable_accept_random_ipn)) {
- ProcessDataPacket(kMaxRandomInitialPacketNumber + 6000);
+ ProcessDataPacket(MaxRandomInitialPacketNumber() + 6000);
} else {
ProcessDataPacket(6000);
}
@@ -2264,7 +2334,8 @@
}
TEST_P(QuicConnectionTest, AckDecimationReducesAcks) {
- if (GetQuicReloadableFlag(quic_enable_ack_decimation)) {
+ if (GetQuicReloadableFlag(quic_enable_ack_decimation) &&
+ !GetQuicReloadableFlag(quic_keep_ack_decimation_reordering)) {
return;
}
@@ -2435,45 +2506,39 @@
ProcessAckPacket(&frame);
}
-TEST_P(QuicConnectionTest, AckAll) {
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- ProcessPacket(1);
-
- QuicPacketCreatorPeer::SetPacketNumber(&peer_creator_, 1);
- QuicAckFrame frame1;
- ProcessAckPacket(&frame1);
-}
-
TEST_P(QuicConnectionTest, BasicSending) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
+ EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
+ ProcessDataPacket(1);
+ QuicPacketCreatorPeer::SetPacketNumber(&peer_creator_, 2);
QuicPacketNumber last_packet;
SendStreamDataToPeer(1, "foo", 0, NO_FIN, &last_packet); // Packet 1
- EXPECT_EQ(1u, last_packet);
+ EXPECT_EQ(QuicPacketNumber(1u), last_packet);
SendAckPacketToPeer(); // Packet 2
if (GetParam().no_stop_waiting) {
// Expect no stop waiting frame is sent.
- EXPECT_EQ(0u, least_unacked());
+ EXPECT_FALSE(least_unacked().IsInitialized());
} else {
- EXPECT_EQ(1u, least_unacked());
+ EXPECT_EQ(QuicPacketNumber(1u), least_unacked());
}
SendAckPacketToPeer(); // Packet 3
if (GetParam().no_stop_waiting) {
// Expect no stop waiting frame is sent.
- EXPECT_EQ(0u, least_unacked());
+ EXPECT_FALSE(least_unacked().IsInitialized());
} else {
- EXPECT_EQ(1u, least_unacked());
+ EXPECT_EQ(QuicPacketNumber(1u), least_unacked());
}
SendStreamDataToPeer(1, "bar", 3, NO_FIN, &last_packet); // Packet 4
- EXPECT_EQ(4u, last_packet);
+ EXPECT_EQ(QuicPacketNumber(4u), last_packet);
SendAckPacketToPeer(); // Packet 5
if (GetParam().no_stop_waiting) {
// Expect no stop waiting frame is sent.
- EXPECT_EQ(0u, least_unacked());
+ EXPECT_FALSE(least_unacked().IsInitialized());
} else {
- EXPECT_EQ(1u, least_unacked());
+ EXPECT_EQ(QuicPacketNumber(1u), least_unacked());
}
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
@@ -2487,9 +2552,9 @@
// ack for 4.
if (GetParam().no_stop_waiting) {
// Expect no stop waiting frame is sent.
- EXPECT_EQ(0u, least_unacked());
+ EXPECT_FALSE(least_unacked().IsInitialized());
} else {
- EXPECT_EQ(4u, least_unacked());
+ EXPECT_EQ(QuicPacketNumber(4u), least_unacked());
}
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
@@ -2499,34 +2564,34 @@
ProcessAckPacket(&frame2); // Acks don't instigate acks.
// Verify that we did not send an ack.
- EXPECT_EQ(6u, writer_->header().packet_number);
+ EXPECT_EQ(QuicPacketNumber(6u), writer_->header().packet_number);
// So the last ack has not changed.
if (GetParam().no_stop_waiting) {
// Expect no stop waiting frame is sent.
- EXPECT_EQ(0u, least_unacked());
+ EXPECT_FALSE(least_unacked().IsInitialized());
} else {
- EXPECT_EQ(4u, least_unacked());
+ EXPECT_EQ(QuicPacketNumber(4u), least_unacked());
}
// If we force an ack, we shouldn't change our retransmit state.
SendAckPacketToPeer(); // Packet 7
if (GetParam().no_stop_waiting) {
// Expect no stop waiting frame is sent.
- EXPECT_EQ(0u, least_unacked());
+ EXPECT_FALSE(least_unacked().IsInitialized());
} else {
- EXPECT_EQ(7u, least_unacked());
+ EXPECT_EQ(QuicPacketNumber(7u), least_unacked());
}
// But if we send more data it should.
SendStreamDataToPeer(1, "eep", 6, NO_FIN, &last_packet); // Packet 8
- EXPECT_EQ(8u, last_packet);
+ EXPECT_EQ(QuicPacketNumber(8u), last_packet);
SendAckPacketToPeer(); // Packet 9
if (GetParam().no_stop_waiting) {
// Expect no stop waiting frame is sent.
- EXPECT_EQ(0u, least_unacked());
+ EXPECT_FALSE(least_unacked().IsInitialized());
} else {
- EXPECT_EQ(7u, least_unacked());
+ EXPECT_EQ(QuicPacketNumber(7u), least_unacked());
}
}
@@ -2643,6 +2708,10 @@
// Process a data packet to queue up a pending ack.
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
ProcessDataPacket(1);
+ QuicPacketNumber last_packet;
+ SendStreamDataToPeer(1, "foo", 0, NO_FIN, &last_packet);
+ // Verify ack is bundled with outging packet.
+ EXPECT_FALSE(writer_->ack_frames().empty());
EXPECT_CALL(visitor_, OnCanWrite())
.WillOnce(DoAll(IgnoreResult(InvokeWithoutArgs(
@@ -2652,9 +2721,9 @@
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
- // Process an ack to cause the visitor's OnCanWrite to be invoked.
- QuicAckFrame ack_one;
- ProcessAckPacket(3, &ack_one);
+ // Process a data packet to cause the visitor's OnCanWrite to be invoked.
+ EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
+ ProcessDataPacket(2);
EXPECT_EQ(0u, connection_.NumQueuedPackets());
EXPECT_FALSE(connection_.HasQueuedData());
@@ -2839,7 +2908,7 @@
// Lose a packet and ensure it triggers retransmission.
QuicAckFrame nack_two = ConstructAckFrame(3, 2);
LostPacketVector lost_packets;
- lost_packets.push_back(LostPacket(2, kMaxPacketSize));
+ lost_packets.push_back(LostPacket(QuicPacketNumber(2), kMaxPacketSize));
EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _, _, _))
.WillOnce(SetArgPointee<5>(lost_packets));
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
@@ -3088,7 +3157,7 @@
BlockOnNextWrite();
LostPacketVector lost_packets;
- lost_packets.push_back(LostPacket(2, kMaxPacketSize));
+ lost_packets.push_back(LostPacket(QuicPacketNumber(2), kMaxPacketSize));
EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _, _, _))
.WillOnce(SetArgPointee<5>(lost_packets));
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
@@ -3103,7 +3172,8 @@
// Unblock the socket and attempt to send the queued packets. We will always
// send the retransmission.
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, 4, _, _)).Times(1);
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(4), _, _))
+ .Times(1);
writer_->SetWritable();
connection_.OnCanWrite();
@@ -3260,14 +3330,15 @@
// Process packet number 1. Can not call ProcessPacket or ProcessDataPacket
// here, because they will fire the alarm after QuicConnection::ProcessPacket
// is returned.
- const QuicPacketNumber received_packet_num = 1;
+ const uint64_t received_packet_num = 1;
const bool has_stop_waiting = false;
const EncryptionLevel level = ENCRYPTION_NONE;
std::unique_ptr<QuicPacket> packet(
ConstructDataPacket(received_packet_num, has_stop_waiting));
char buffer[kMaxPacketSize];
- size_t encrypted_length = peer_framer_.EncryptPayload(
- level, received_packet_num, *packet, buffer, kMaxPacketSize);
+ size_t encrypted_length =
+ peer_framer_.EncryptPayload(level, QuicPacketNumber(received_packet_num),
+ *packet, buffer, kMaxPacketSize);
connection_.ProcessUdpPacket(
kSelfAddress, kPeerAddress,
QuicReceivedPacket(buffer, encrypted_length, clock_.Now(), false));
@@ -3313,6 +3384,19 @@
}
}
+TEST_P(QuicConnectionTest, AddToWriteBlockedListIfBlockedOnFlushPackets) {
+ writer_->SetBatchMode(true);
+ writer_->BlockOnNextFlush();
+
+ EXPECT_CALL(visitor_, OnWriteBlocked()).Times(1);
+ {
+ QuicConnection::ScopedPacketFlusher flusher(&connection_,
+ QuicConnection::NO_ACK);
+ // flusher's destructor will call connection_.FlushPackets, which should add
+ // the connection to the write blocked list.
+ }
+}
+
TEST_P(QuicConnectionTest, NoLimitPacketsPerNack) {
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
int offset = 0;
@@ -3324,12 +3408,13 @@
// Ack 15, nack 1-14.
- QuicAckFrame nack = InitAckFrame({{15, 16}});
+ QuicAckFrame nack =
+ InitAckFrame({{QuicPacketNumber(15), QuicPacketNumber(16)}});
// 14 packets have been NACK'd and lost.
LostPacketVector lost_packets;
for (int i = 1; i < 15; ++i) {
- lost_packets.push_back(LostPacket(i, kMaxPacketSize));
+ lost_packets.push_back(LostPacket(QuicPacketNumber(i), kMaxPacketSize));
}
EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _, _, _))
.WillOnce(SetArgPointee<5>(lost_packets));
@@ -3344,23 +3429,26 @@
// Test sending multiple acks from the connection to the session.
TEST_P(QuicConnectionTest, MultipleAcks) {
+ EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
+ EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
+ ProcessDataPacket(1);
+ QuicPacketCreatorPeer::SetPacketNumber(&peer_creator_, 2);
QuicPacketNumber last_packet;
SendStreamDataToPeer(1, "foo", 0, NO_FIN, &last_packet); // Packet 1
- EXPECT_EQ(1u, last_packet);
+ EXPECT_EQ(QuicPacketNumber(1u), last_packet);
SendStreamDataToPeer(3, "foo", 0, NO_FIN, &last_packet); // Packet 2
- EXPECT_EQ(2u, last_packet);
+ EXPECT_EQ(QuicPacketNumber(2u), last_packet);
SendAckPacketToPeer(); // Packet 3
SendStreamDataToPeer(5, "foo", 0, NO_FIN, &last_packet); // Packet 4
- EXPECT_EQ(4u, last_packet);
+ EXPECT_EQ(QuicPacketNumber(4u), last_packet);
SendStreamDataToPeer(1, "foo", 3, NO_FIN, &last_packet); // Packet 5
- EXPECT_EQ(5u, last_packet);
+ EXPECT_EQ(QuicPacketNumber(5u), last_packet);
SendStreamDataToPeer(3, "foo", 3, NO_FIN, &last_packet); // Packet 6
- EXPECT_EQ(6u, last_packet);
+ EXPECT_EQ(QuicPacketNumber(6u), last_packet);
// Client will ack packets 1, 2, [!3], 4, 5.
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
QuicAckFrame frame1 = ConstructAckFrame(5, 3);
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
ProcessAckPacket(&frame1);
// Now the client implicitly acks 3, and explicitly acks 6.
@@ -3370,11 +3458,14 @@
}
TEST_P(QuicConnectionTest, DontLatchUnackedPacket) {
+ EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
+ EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
+ ProcessDataPacket(1);
+ QuicPacketCreatorPeer::SetPacketNumber(&peer_creator_, 2);
SendStreamDataToPeer(1, "foo", 0, NO_FIN, nullptr); // Packet 1;
// From now on, we send acks, so the send algorithm won't mark them pending.
SendAckPacketToPeer(); // Packet 2
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
QuicAckFrame frame = InitAckFrame(1);
ProcessAckPacket(&frame);
@@ -3382,25 +3473,25 @@
// Verify that our internal state has least-unacked as 2, because we're still
// waiting for a potential ack for 2.
- EXPECT_EQ(2u, stop_waiting()->least_unacked);
+ EXPECT_EQ(QuicPacketNumber(2u), stop_waiting()->least_unacked);
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
frame = InitAckFrame(2);
ProcessAckPacket(&frame);
- EXPECT_EQ(3u, stop_waiting()->least_unacked);
+ EXPECT_EQ(QuicPacketNumber(3u), stop_waiting()->least_unacked);
// When we send an ack, we make sure our least-unacked makes sense. In this
// case since we're not waiting on an ack for 2 and all packets are acked, we
// set it to 3.
SendAckPacketToPeer(); // Packet 3
// Least_unacked remains at 3 until another ack is received.
- EXPECT_EQ(3u, stop_waiting()->least_unacked);
+ EXPECT_EQ(QuicPacketNumber(3u), stop_waiting()->least_unacked);
if (GetParam().no_stop_waiting) {
// Expect no stop waiting frame is sent.
- EXPECT_EQ(0u, least_unacked());
+ EXPECT_FALSE(least_unacked().IsInitialized());
} else {
// Check that the outgoing ack had its packet number as least_unacked.
- EXPECT_EQ(3u, least_unacked());
+ EXPECT_EQ(QuicPacketNumber(3u), least_unacked());
}
// Ack the ack, which updates the rtt and raises the least unacked.
@@ -3409,13 +3500,13 @@
ProcessAckPacket(&frame);
SendStreamDataToPeer(1, "bar", 3, NO_FIN, nullptr); // Packet 4
- EXPECT_EQ(4u, stop_waiting()->least_unacked);
+ EXPECT_EQ(QuicPacketNumber(4u), stop_waiting()->least_unacked);
SendAckPacketToPeer(); // Packet 5
if (GetParam().no_stop_waiting) {
// Expect no stop waiting frame is sent.
- EXPECT_EQ(0u, least_unacked());
+ EXPECT_FALSE(least_unacked().IsInitialized());
} else {
- EXPECT_EQ(4u, least_unacked());
+ EXPECT_EQ(QuicPacketNumber(4u), least_unacked());
}
// Send two data packets at the end, and ensure if the last one is acked,
@@ -3424,30 +3515,31 @@
SendStreamDataToPeer(1, "bar", 9, NO_FIN, nullptr); // Packet 7
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
- frame = InitAckFrame({{1, 5}, {7, 8}});
+ frame = InitAckFrame({{QuicPacketNumber(1), QuicPacketNumber(5)},
+ {QuicPacketNumber(7), QuicPacketNumber(8)}});
ProcessAckPacket(&frame);
- EXPECT_EQ(6u, stop_waiting()->least_unacked);
+ EXPECT_EQ(QuicPacketNumber(6u), stop_waiting()->least_unacked);
}
TEST_P(QuicConnectionTest, TLP) {
connection_.SetMaxTailLossProbes(1);
SendStreamDataToPeer(3, "foo", 0, NO_FIN, nullptr);
- EXPECT_EQ(1u, stop_waiting()->least_unacked);
+ EXPECT_EQ(QuicPacketNumber(1u), stop_waiting()->least_unacked);
QuicTime retransmission_time =
connection_.GetRetransmissionAlarm()->deadline();
EXPECT_NE(QuicTime::Zero(), retransmission_time);
- EXPECT_EQ(1u, writer_->header().packet_number);
+ EXPECT_EQ(QuicPacketNumber(1u), writer_->header().packet_number);
// Simulate the retransmission alarm firing and sending a tlp,
// so send algorithm's OnRetransmissionTimeout is not called.
clock_.AdvanceTime(retransmission_time - clock_.Now());
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, 2u, _, _));
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(2), _, _));
connection_.GetRetransmissionAlarm()->Fire();
- EXPECT_EQ(2u, writer_->header().packet_number);
+ EXPECT_EQ(QuicPacketNumber(2u), writer_->header().packet_number);
// We do not raise the high water mark yet.
- EXPECT_EQ(1u, stop_waiting()->least_unacked);
+ EXPECT_EQ(QuicPacketNumber(1u), stop_waiting()->least_unacked);
}
TEST_P(QuicConnectionTest, RTO) {
@@ -3456,18 +3548,18 @@
QuicTime default_retransmission_time =
clock_.ApproximateNow() + DefaultRetransmissionTime();
SendStreamDataToPeer(3, "foo", 0, NO_FIN, nullptr);
- EXPECT_EQ(1u, stop_waiting()->least_unacked);
+ EXPECT_EQ(QuicPacketNumber(1u), stop_waiting()->least_unacked);
- EXPECT_EQ(1u, writer_->header().packet_number);
+ EXPECT_EQ(QuicPacketNumber(1u), writer_->header().packet_number);
EXPECT_EQ(default_retransmission_time,
connection_.GetRetransmissionAlarm()->deadline());
// Simulate the retransmission alarm firing.
clock_.AdvanceTime(DefaultRetransmissionTime());
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, 2u, _, _));
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(2), _, _));
connection_.GetRetransmissionAlarm()->Fire();
- EXPECT_EQ(2u, writer_->header().packet_number);
+ EXPECT_EQ(QuicPacketNumber(2u), writer_->header().packet_number);
// We do not raise the high water mark yet.
- EXPECT_EQ(1u, stop_waiting()->least_unacked);
+ EXPECT_EQ(QuicPacketNumber(1u), stop_waiting()->least_unacked);
}
TEST_P(QuicConnectionTest, RetransmitWithSameEncryptionLevel) {
@@ -3490,8 +3582,10 @@
{
InSequence s;
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, 3, _, _));
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, 4, _, _));
+ EXPECT_CALL(*send_algorithm_,
+ OnPacketSent(_, _, QuicPacketNumber(3), _, _));
+ EXPECT_CALL(*send_algorithm_,
+ OnPacketSent(_, _, QuicPacketNumber(4), _, _));
}
// Manually mark both packets for retransmission.
@@ -3616,45 +3710,6 @@
ProcessDataPacketAtLevel(3, !kHasStopWaiting, ENCRYPTION_INITIAL);
}
-TEST_P(QuicConnectionTest, Buffer100NonDecryptablePackets) {
- if (GetQuicReloadableFlag(quic_decrypt_packets_on_key_change)) {
- return;
- }
-
- // SetFromConfig is always called after construction from InitializeSession.
- EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
- QuicConfig config;
- config.set_max_undecryptable_packets(100);
- connection_.SetFromConfig(config);
- EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
- use_tagging_decrypter();
-
- const uint8_t tag = 0x07;
- peer_framer_.SetEncrypter(ENCRYPTION_INITIAL,
- QuicMakeUnique<TaggingEncrypter>(tag));
-
- // Process an encrypted packet which can not yet be decrypted which should
- // result in the packet being buffered.
- for (QuicPacketNumber i = 1; i <= 100; ++i) {
- ProcessDataPacketAtLevel(i, !kHasStopWaiting, ENCRYPTION_INITIAL);
- }
-
- // Transition to the new encryption state and process another encrypted packet
- // which should result in the original packets being processed.
- connection_.SetDecrypter(ENCRYPTION_INITIAL,
- QuicMakeUnique<StrictTaggingDecrypter>(tag));
- connection_.SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
- connection_.SetEncrypter(ENCRYPTION_INITIAL,
- QuicMakeUnique<TaggingEncrypter>(tag));
- EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(101);
- ProcessDataPacketAtLevel(101, !kHasStopWaiting, ENCRYPTION_INITIAL);
-
- // Finally, process a third packet and note that we do not reprocess the
- // buffered packet.
- EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
- ProcessDataPacketAtLevel(102, !kHasStopWaiting, ENCRYPTION_INITIAL);
-}
-
TEST_P(QuicConnectionTest, TestRetransmitOrder) {
connection_.SetMaxTailLossProbes(0);
@@ -3688,10 +3743,6 @@
}
TEST_P(QuicConnectionTest, Buffer100NonDecryptablePacketsThenKeyChange) {
- if (!GetQuicReloadableFlag(quic_decrypt_packets_on_key_change)) {
- return;
- }
-
// SetFromConfig is always called after construction from InitializeSession.
EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
QuicConfig config;
@@ -3706,7 +3757,7 @@
// Process an encrypted packet which can not yet be decrypted which should
// result in the packet being buffered.
- for (QuicPacketNumber i = 1; i <= 100; ++i) {
+ for (uint64_t i = 1; i <= 100; ++i) {
ProcessDataPacketAtLevel(i, !kHasStopWaiting, ENCRYPTION_INITIAL);
}
@@ -3848,7 +3899,7 @@
clock_.AdvanceTime(QuicTime::Delta::FromMicroseconds(20));
QuicPacketNumber last_packet;
SendStreamDataToPeer(1, "foo", 0, NO_FIN, &last_packet);
- EXPECT_EQ(1u, last_packet);
+ EXPECT_EQ(QuicPacketNumber(1u), last_packet);
// This will be the updated deadline for the connection to idle time out.
QuicTime new_ddl = clock_.ApproximateNow() +
QuicTime::Delta::FromSeconds(kInitialIdleTimeoutSecs - 1);
@@ -3900,12 +3951,12 @@
// execution until manually adjusted.
QuicPacketNumber last_packet;
SendStreamDataToPeer(1, "foo", 0, NO_FIN, &last_packet);
- EXPECT_EQ(1u, last_packet);
+ EXPECT_EQ(QuicPacketNumber(1u), last_packet);
// Advance the time and send the second packet to the peer.
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(20));
SendStreamDataToPeer(1, "foo", 0, NO_FIN, &last_packet);
- EXPECT_EQ(2u, last_packet);
+ EXPECT_EQ(QuicPacketNumber(2u), last_packet);
if (GetQuicReloadableFlag(
quic_fix_time_of_first_packet_sent_after_receiving)) {
@@ -4092,7 +4143,7 @@
.WillOnce(SaveArg<3>(&mtu_probe_size));
connection_.SendMtuDiscoveryPacket(new_mtu);
EXPECT_EQ(new_mtu, mtu_probe_size);
- EXPECT_EQ(1u, creator_->packet_number());
+ EXPECT_EQ(QuicPacketNumber(1u), creator_->packet_number());
// Send more than MTU worth of data. No acknowledgement was received so far,
// so the MTU should be at its old value.
@@ -4103,7 +4154,7 @@
.WillOnce(SaveArg<3>(&size_before_mtu_change))
.WillOnce(Return());
connection_.SendStreamDataWithString(3, data, 0, FIN);
- EXPECT_EQ(3u, creator_->packet_number());
+ EXPECT_EQ(QuicPacketNumber(3u), creator_->packet_number());
EXPECT_EQ(kDefaultMaxPacketSize, size_before_mtu_change);
// Acknowledge all packets so far.
@@ -4116,7 +4167,7 @@
// Send the same data again. Check that it fits into a single packet now.
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
connection_.SendStreamDataWithString(3, data, 0, FIN);
- EXPECT_EQ(4u, creator_->packet_number());
+ EXPECT_EQ(QuicPacketNumber(4u), creator_->packet_number());
}
// Tests whether MTU discovery does not happen when it is not explicitly enabled
@@ -4161,7 +4212,8 @@
connection_.GetMtuDiscoveryAlarm()->Fire();
EXPECT_EQ(kMtuDiscoveryTargetPacketSizeHigh, probe_size);
- const QuicPacketCount probe_packet_number = packets_between_probes_base + 1;
+ const QuicPacketNumber probe_packet_number =
+ FirstSendingPacketNumber() + packets_between_probes_base;
ASSERT_EQ(probe_packet_number, creator_->packet_number());
// Acknowledge all packets sent so far.
@@ -4223,12 +4275,13 @@
mtu_discovery_packets.end());
QuicPacketNumber max_packet = *max_element(mtu_discovery_packets.begin(),
mtu_discovery_packets.end());
- ack.packets.AddRange(1, min_packet);
- ack.packets.AddRange(max_packet + 1, creator_->packet_number() + 1);
+ ack.packets.AddRange(QuicPacketNumber(1), min_packet);
+ ack.packets.AddRange(QuicPacketNumber(max_packet + 1),
+ creator_->packet_number() + 1);
ack.largest_acked = creator_->packet_number();
} else {
- ack.packets.AddRange(1, creator_->packet_number() + 1);
+ ack.packets.AddRange(QuicPacketNumber(1), creator_->packet_number() + 1);
ack.largest_acked = creator_->packet_number();
}
@@ -4250,11 +4303,12 @@
// Ensure the number of packets between probes grows exponentially by checking
// it against the closed-form expression for the packet number.
ASSERT_EQ(kMtuDiscoveryAttempts, mtu_discovery_packets.size());
- for (QuicPacketNumber i = 0; i < kMtuDiscoveryAttempts; i++) {
+ for (uint64_t i = 0; i < kMtuDiscoveryAttempts; i++) {
// 2^0 + 2^1 + 2^2 + ... + 2^n = 2^(n + 1) - 1
const QuicPacketCount packets_between_probes =
packets_between_probes_base * ((1 << (i + 1)) - 1);
- EXPECT_EQ(packets_between_probes + (i + 1), mtu_discovery_packets[i]);
+ EXPECT_EQ(QuicPacketNumber(packets_between_probes + (i + 1)),
+ mtu_discovery_packets[i]);
}
EXPECT_FALSE(connection_.GetMtuDiscoveryAlarm()->IsSet());
@@ -4290,7 +4344,8 @@
connection_.GetMtuDiscoveryAlarm()->Fire();
EXPECT_EQ(mtu_limit, probe_size);
- const QuicPacketCount probe_sequence_number = packets_between_probes_base + 1;
+ const QuicPacketNumber probe_sequence_number =
+ FirstSendingPacketNumber() + packets_between_probes_base;
ASSERT_EQ(probe_sequence_number, creator_->packet_number());
// Acknowledge all packets sent so far.
@@ -4485,7 +4540,7 @@
const QuicTime final_timeout = rto_time + initial_idle_timeout;
clock_.AdvanceTime(rto_time - clock_.Now());
ASSERT_EQ(rto_time, clock_.Now());
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, 2u, _, _));
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(2u), _, _));
connection_.GetRetransmissionAlarm()->Fire();
// Advance to the original timeout and fire the alarm. The connection should
@@ -4622,7 +4677,7 @@
// Retransmit the packet via tail loss probe.
clock_.AdvanceTime(connection_.GetRetransmissionAlarm()->deadline() -
clock_.Now());
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, 2u, _, _));
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(2u), _, _));
connection_.GetRetransmissionAlarm()->Fire();
// This time, we should time out and send a connection close due to the TLP.
@@ -4839,6 +4894,7 @@
// Test that if we send a packet without delay, it is not queued.
QuicFramerPeer::SetPerspective(&peer_framer_, Perspective::IS_CLIENT);
std::unique_ptr<QuicPacket> packet = ConstructDataPacket(1, !kHasStopWaiting);
+ QuicPacketCreatorPeer::SetPacketNumber(creator_, 1);
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _));
connection_.SendPacket(ENCRYPTION_NONE, 1, std::move(packet),
HAS_RETRANSMITTABLE_DATA, false, false);
@@ -4851,6 +4907,7 @@
QuicFramerPeer::SetPerspective(&peer_framer_, Perspective::IS_CLIENT);
EXPECT_CALL(visitor_, OnConnectionClosed(_, _, _)).Times(1);
std::unique_ptr<QuicPacket> packet = ConstructDataPacket(1, !kHasStopWaiting);
+ QuicPacketCreatorPeer::SetPacketNumber(creator_, 1);
writer_->SetShouldWriteFail();
connection_.SendPacket(ENCRYPTION_NONE, 1, std::move(packet),
HAS_RETRANSMITTABLE_DATA, false, false);
@@ -4859,8 +4916,10 @@
TEST_P(QuicConnectionTest, SendSchedulerEAGAIN) {
QuicFramerPeer::SetPerspective(&peer_framer_, Perspective::IS_CLIENT);
std::unique_ptr<QuicPacket> packet = ConstructDataPacket(1, !kHasStopWaiting);
+ QuicPacketCreatorPeer::SetPacketNumber(creator_, 1);
BlockOnNextWrite();
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, 1, _, _)).Times(0);
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(2u), _, _))
+ .Times(0);
connection_.SendPacket(ENCRYPTION_NONE, 1, std::move(packet),
HAS_RETRANSMITTABLE_DATA, false, false);
EXPECT_EQ(1u, connection_.NumQueuedPackets());
@@ -5112,7 +5171,7 @@
frame1_.stream_id = 3;
// Process all the initial packets in order so there aren't missing packets.
- QuicPacketNumber kFirstDecimatedPacket = 101;
+ uint64_t kFirstDecimatedPacket = 101;
for (unsigned int i = 0; i < kFirstDecimatedPacket - 1; ++i) {
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
ProcessDataPacketAtLevel(1 + i, !kHasStopWaiting, ENCRYPTION_INITIAL);
@@ -5228,7 +5287,7 @@
// default delayed ack time.
ack_time = clock_.ApproximateNow() +
QuicTime::Delta::FromMilliseconds(kMinRttMs / 4);
- QuicPacketNumber kFirstDecimatedPacket = 101;
+ uint64_t kFirstDecimatedPacket = 101;
for (unsigned int i = 0; i < kFirstDecimatedPacket - 4; ++i) {
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
ProcessDataPacketAtLevel(4 + i, !kHasStopWaiting, ENCRYPTION_INITIAL);
@@ -5304,7 +5363,7 @@
frame1_.stream_id = 3;
// Process all the initial packets in order so there aren't missing packets.
- QuicPacketNumber kFirstDecimatedPacket = 101;
+ uint64_t kFirstDecimatedPacket = 101;
for (unsigned int i = 0; i < kFirstDecimatedPacket - 1; ++i) {
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
ProcessDataPacketAtLevel(1 + i, !kHasStopWaiting, ENCRYPTION_INITIAL);
@@ -5357,7 +5416,7 @@
frame1_.stream_id = 3;
// Process all the initial packets in order so there aren't missing packets.
- QuicPacketNumber kFirstDecimatedPacket = 101;
+ uint64_t kFirstDecimatedPacket = 101;
for (unsigned int i = 0; i < kFirstDecimatedPacket - 1; ++i) {
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
ProcessDataPacketAtLevel(1 + i, !kHasStopWaiting, ENCRYPTION_INITIAL);
@@ -5393,7 +5452,8 @@
}
TEST_P(QuicConnectionTest, SendDelayedAckDecimationWithReordering) {
- if (GetQuicReloadableFlag(quic_enable_ack_decimation)) {
+ if (GetQuicReloadableFlag(quic_enable_ack_decimation) &&
+ !GetQuicReloadableFlag(quic_keep_ack_decimation_reordering)) {
return;
}
EXPECT_CALL(visitor_, OnAckNeedsRetransmittableFrame()).Times(AnyNumber());
@@ -5419,7 +5479,7 @@
frame1_.stream_id = 3;
// Process all the initial packets in order so there aren't missing packets.
- QuicPacketNumber kFirstDecimatedPacket = 101;
+ uint64_t kFirstDecimatedPacket = 101;
for (unsigned int i = 0; i < kFirstDecimatedPacket - 1; ++i) {
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
ProcessDataPacketAtLevel(1 + i, !kHasStopWaiting, ENCRYPTION_INITIAL);
@@ -5461,7 +5521,8 @@
}
TEST_P(QuicConnectionTest, SendDelayedAckDecimationWithLargeReordering) {
- if (GetQuicReloadableFlag(quic_enable_ack_decimation)) {
+ if (GetQuicReloadableFlag(quic_enable_ack_decimation) &&
+ !GetQuicReloadableFlag(quic_keep_ack_decimation_reordering)) {
return;
}
EXPECT_CALL(visitor_, OnAckNeedsRetransmittableFrame()).Times(AnyNumber());
@@ -5487,7 +5548,7 @@
frame1_.stream_id = 3;
// Process all the initial packets in order so there aren't missing packets.
- QuicPacketNumber kFirstDecimatedPacket = 101;
+ uint64_t kFirstDecimatedPacket = 101;
for (unsigned int i = 0; i < kFirstDecimatedPacket - 1; ++i) {
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
ProcessDataPacketAtLevel(1 + i, !kHasStopWaiting, ENCRYPTION_INITIAL);
@@ -5548,7 +5609,8 @@
}
TEST_P(QuicConnectionTest, SendDelayedAckDecimationWithReorderingEighthRtt) {
- if (GetQuicReloadableFlag(quic_enable_ack_decimation)) {
+ if (GetQuicReloadableFlag(quic_enable_ack_decimation) &&
+ !GetQuicReloadableFlag(quic_keep_ack_decimation_reordering)) {
return;
}
EXPECT_CALL(visitor_, OnAckNeedsRetransmittableFrame()).Times(AnyNumber());
@@ -5575,7 +5637,7 @@
frame1_.stream_id = 3;
// Process all the initial packets in order so there aren't missing packets.
- QuicPacketNumber kFirstDecimatedPacket = 101;
+ uint64_t kFirstDecimatedPacket = 101;
for (unsigned int i = 0; i < kFirstDecimatedPacket - 1; ++i) {
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
ProcessDataPacketAtLevel(1 + i, !kHasStopWaiting, ENCRYPTION_INITIAL);
@@ -5620,7 +5682,8 @@
TEST_P(QuicConnectionTest,
SendDelayedAckDecimationWithLargeReorderingEighthRtt) {
- if (GetQuicReloadableFlag(quic_enable_ack_decimation)) {
+ if (GetQuicReloadableFlag(quic_enable_ack_decimation) &&
+ !GetQuicReloadableFlag(quic_keep_ack_decimation_reordering)) {
return;
}
EXPECT_CALL(visitor_, OnAckNeedsRetransmittableFrame()).Times(AnyNumber());
@@ -5647,7 +5710,7 @@
frame1_.stream_id = 3;
// Process all the initial packets in order so there aren't missing packets.
- QuicPacketNumber kFirstDecimatedPacket = 101;
+ uint64_t kFirstDecimatedPacket = 101;
for (unsigned int i = 0; i < kFirstDecimatedPacket - 1; ++i) {
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
ProcessDataPacketAtLevel(1 + i, !kHasStopWaiting, ENCRYPTION_INITIAL);
@@ -5844,7 +5907,7 @@
EXPECT_EQ(1u, writer_->stream_frames().size());
EXPECT_EQ(1u, writer_->padding_frames().size());
ASSERT_FALSE(writer_->ack_frames().empty());
- EXPECT_EQ(2u, LargestAcked(writer_->ack_frames().front()));
+ EXPECT_EQ(QuicPacketNumber(2u), LargestAcked(writer_->ack_frames().front()));
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
}
@@ -5873,7 +5936,7 @@
EXPECT_EQ(1u, writer_->stream_frames().size());
EXPECT_EQ(1u, writer_->padding_frames().size());
ASSERT_FALSE(writer_->ack_frames().empty());
- EXPECT_EQ(2u, LargestAcked(writer_->ack_frames().front()));
+ EXPECT_EQ(QuicPacketNumber(2u), LargestAcked(writer_->ack_frames().front()));
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
}
@@ -5888,7 +5951,7 @@
// Ack the second packet, which will retransmit the first packet.
QuicAckFrame ack = ConstructAckFrame(2, 1);
LostPacketVector lost_packets;
- lost_packets.push_back(LostPacket(1, kMaxPacketSize));
+ lost_packets.push_back(LostPacket(QuicPacketNumber(1), kMaxPacketSize));
EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _, _, _))
.WillOnce(SetArgPointee<5>(lost_packets));
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
@@ -5927,7 +5990,7 @@
EXPECT_FALSE(writer_->stop_waiting_frames().empty());
}
EXPECT_FALSE(writer_->ack_frames().empty());
- EXPECT_EQ(3u, LargestAcked(writer_->ack_frames().front()));
+ EXPECT_EQ(QuicPacketNumber(3u), LargestAcked(writer_->ack_frames().front()));
EXPECT_EQ(1u, writer_->stream_frames().size());
EXPECT_FALSE(connection_.GetAckAlarm()->IsSet());
}
@@ -5950,7 +6013,8 @@
EXPECT_FALSE(connection_.connected());
EXPECT_FALSE(connection_.CanWriteStreamData());
std::unique_ptr<QuicPacket> packet = ConstructDataPacket(1, !kHasStopWaiting);
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, 1, _, _)).Times(0);
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(1), _, _))
+ .Times(0);
connection_.SendPacket(ENCRYPTION_NONE, 1, std::move(packet),
HAS_RETRANSMITTABLE_DATA, false, false);
}
@@ -5969,7 +6033,8 @@
EXPECT_FALSE(connection_.connected());
EXPECT_FALSE(connection_.CanWriteStreamData());
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, 1, _, _)).Times(0);
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(1), _, _))
+ .Times(0);
EXPECT_QUIC_BUG(connection_.SendConnectivityProbingPacket(
writer_.get(), connection_.peer_address()),
@@ -5987,7 +6052,8 @@
// affects the probing_writer which is not the default.
EXPECT_CALL(visitor_, OnWriteBlocked()).Times(0);
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, 1, _, _)).Times(1);
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(1), _, _))
+ .Times(1);
connection_.SendConnectivityProbingPacket(&probing_writer,
connection_.peer_address());
}
@@ -6003,7 +6069,8 @@
// writer to send connectivity probes.
EXPECT_CALL(visitor_, OnWriteBlocked()).Times(1);
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, 1, _, _)).Times(1);
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(1), _, _))
+ .Times(1);
connection_.SendConnectivityProbingPacket(writer_.get(),
connection_.peer_address());
}
@@ -6017,7 +6084,8 @@
// sent.
EXPECT_CALL(visitor_, OnConnectionClosed(_, _, _)).Times(0);
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, 1, _, _)).Times(0);
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(1), _, _))
+ .Times(0);
connection_.SendConnectivityProbingPacket(&probing_writer,
connection_.peer_address());
}
@@ -6031,7 +6099,8 @@
// sent.
EXPECT_CALL(visitor_, OnConnectionClosed(_, _, _)).Times(0);
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, 1, _, _)).Times(0);
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, QuicPacketNumber(1), _, _))
+ .Times(0);
connection_.SendConnectivityProbingPacket(writer_.get(),
connection_.peer_address());
}
@@ -6137,21 +6206,20 @@
peer_framer_.set_version_for_tests(
ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_99));
} else {
- peer_framer_.set_version_for_tests(
- ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED));
+ peer_framer_.set_version_for_tests(UnsupportedQuicVersion());
}
QuicPacketHeader header;
header.destination_connection_id = connection_id_;
header.version_flag = true;
- header.packet_number = 12;
+ header.packet_number = QuicPacketNumber(12);
QuicFrames frames;
frames.push_back(QuicFrame(frame1_));
std::unique_ptr<QuicPacket> packet(ConstructPacket(header, frames));
char buffer[kMaxPacketSize];
- size_t encrypted_length = framer_.EncryptPayload(ENCRYPTION_NONE, 12, *packet,
- buffer, kMaxPacketSize);
+ size_t encrypted_length = framer_.EncryptPayload(
+ ENCRYPTION_NONE, QuicPacketNumber(12), *packet, buffer, kMaxPacketSize);
framer_.set_version(version());
// Writer's framer's perspective is client, so that it needs to have the right
@@ -6183,21 +6251,20 @@
peer_framer_.set_version_for_tests(
ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_99));
} else {
- peer_framer_.set_version_for_tests(
- ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED));
+ peer_framer_.set_version_for_tests(UnsupportedQuicVersion());
}
QuicPacketHeader header;
header.destination_connection_id = connection_id_;
header.version_flag = true;
- header.packet_number = 12;
+ header.packet_number = QuicPacketNumber(12);
QuicFrames frames;
frames.push_back(QuicFrame(frame1_));
std::unique_ptr<QuicPacket> packet(ConstructPacket(header, frames));
char buffer[kMaxPacketSize];
- size_t encrypted_length = framer_.EncryptPayload(ENCRYPTION_NONE, 12, *packet,
- buffer, kMaxPacketSize);
+ size_t encrypted_length = framer_.EncryptPayload(
+ ENCRYPTION_NONE, QuicPacketNumber(12), *packet, buffer, kMaxPacketSize);
framer_.set_version(version());
BlockOnNextWrite();
@@ -6236,21 +6303,20 @@
peer_framer_.set_version_for_tests(
ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_99));
} else {
- peer_framer_.set_version_for_tests(
- ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED));
+ peer_framer_.set_version_for_tests(UnsupportedQuicVersion());
}
QuicPacketHeader header;
header.destination_connection_id = connection_id_;
header.version_flag = true;
- header.packet_number = 12;
+ header.packet_number = QuicPacketNumber(12);
QuicFrames frames;
frames.push_back(QuicFrame(frame1_));
std::unique_ptr<QuicPacket> packet(ConstructPacket(header, frames));
char buffer[kMaxPacketSize];
- size_t encryped_length = framer_.EncryptPayload(ENCRYPTION_NONE, 12, *packet,
- buffer, kMaxPacketSize);
+ size_t encryped_length = framer_.EncryptPayload(
+ ENCRYPTION_NONE, QuicPacketNumber(12), *packet, buffer, kMaxPacketSize);
framer_.set_version(version());
set_perspective(Perspective::IS_SERVER);
@@ -6297,14 +6363,14 @@
QuicPacketHeader header;
header.destination_connection_id = connection_id_;
header.destination_connection_id_length = PACKET_0BYTE_CONNECTION_ID;
- header.packet_number = 12;
+ header.packet_number = QuicPacketNumber(12);
header.version_flag = false;
QuicFrames frames;
frames.push_back(QuicFrame(frame1_));
std::unique_ptr<QuicPacket> packet(ConstructPacket(header, frames));
char buffer[kMaxPacketSize];
size_t encrypted_length = peer_framer_.EncryptPayload(
- ENCRYPTION_NONE, 12, *packet, buffer, kMaxPacketSize);
+ ENCRYPTION_NONE, QuicPacketNumber(12), *packet, buffer, kMaxPacketSize);
ASSERT_NE(0u, encrypted_length);
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
@@ -6355,11 +6421,13 @@
connection_.GetRetransmissionAlarm()->Fire();
// Retransmit due to explicit nacks.
- QuicAckFrame nack_three = InitAckFrame({{2, 3}, {4, 5}});
+ QuicAckFrame nack_three =
+ InitAckFrame({{QuicPacketNumber(2), QuicPacketNumber(3)},
+ {QuicPacketNumber(4), QuicPacketNumber(5)}});
LostPacketVector lost_packets;
- lost_packets.push_back(LostPacket(1, kMaxPacketSize));
- lost_packets.push_back(LostPacket(3, kMaxPacketSize));
+ lost_packets.push_back(LostPacket(QuicPacketNumber(1), kMaxPacketSize));
+ lost_packets.push_back(LostPacket(QuicPacketNumber(3), kMaxPacketSize));
EXPECT_CALL(*loss_algorithm_, DetectLosses(_, _, _, _, _, _))
.WillOnce(SetArgPointee<5>(lost_packets));
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
@@ -6395,7 +6463,7 @@
if (peer_framer_.transport_version() > QUIC_VERSION_43) {
header.destination_connection_id_length = PACKET_0BYTE_CONNECTION_ID;
}
- header.packet_number = 1;
+ header.packet_number = QuicPacketNumber(1);
header.version_flag = false;
QuicConnectionCloseFrame qccf;
@@ -6408,7 +6476,7 @@
EXPECT_TRUE(nullptr != packet);
char buffer[kMaxPacketSize];
size_t encrypted_length = peer_framer_.EncryptPayload(
- ENCRYPTION_NONE, 1, *packet, buffer, kMaxPacketSize);
+ ENCRYPTION_NONE, QuicPacketNumber(1), *packet, buffer, kMaxPacketSize);
EXPECT_CALL(visitor_, OnConnectionClosed(QUIC_PEER_GOING_AWAY, _,
ConnectionCloseSource::FROM_PEER));
@@ -6442,8 +6510,7 @@
// Shouldn't be able to find a mutually supported version.
ParsedQuicVersionVector unsupported_version;
- unsupported_version.push_back(
- ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED));
+ unsupported_version.push_back(UnsupportedQuicVersion());
EXPECT_FALSE(connection_.SelectMutualVersion(unsupported_version));
}
@@ -6490,7 +6557,7 @@
TEST_P(QuicConnectionTest, OnPacketHeaderDebugVisitor) {
QuicPacketHeader header;
- header.packet_number = 1;
+ header.packet_number = QuicPacketNumber(1);
if (GetParam().version.transport_version > QUIC_VERSION_43) {
header.form = IETF_QUIC_LONG_HEADER_PACKET;
}
@@ -6594,6 +6661,9 @@
}
TEST_P(QuicConnectionTest, SendAcksImmediately) {
+ EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
+ EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
+ ProcessDataPacket(1);
CongestionBlockWrites();
SendAckPacketToPeer();
}
@@ -6727,7 +6797,8 @@
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
}
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
- QuicAckFrame frame = InitAckFrame({{1u + 2u * i, 2u + 2u * i}});
+ QuicAckFrame frame = InitAckFrame(
+ {{QuicPacketNumber(1u + 2u * i), QuicPacketNumber(2u + 2u * i)}});
ProcessAckPacket(&frame);
EXPECT_TRUE(connection_.GetPathDegradingAlarm()->IsSet());
// Check the deadline of the path degrading alarm.
@@ -6742,7 +6813,7 @@
// degrading alarm.
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
- frame = InitAckFrame({{2, 3}});
+ frame = InitAckFrame({{QuicPacketNumber(2), QuicPacketNumber(3)}});
ProcessAckPacket(&frame);
EXPECT_FALSE(connection_.GetPathDegradingAlarm()->IsSet());
} else {
@@ -6797,7 +6868,8 @@
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
- QuicAckFrame frame = InitAckFrame({{1, 2}});
+ QuicAckFrame frame =
+ InitAckFrame({{QuicPacketNumber(1), QuicPacketNumber(2)}});
ProcessAckPacket(&frame);
// No more retransmittable packets on the wire, so the path degrading alarm
// should be cancelled, and the ping alarm should be set to the
@@ -6860,7 +6932,8 @@
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
- QuicAckFrame frame = InitAckFrame({{1u, 2u}});
+ QuicAckFrame frame =
+ InitAckFrame({{QuicPacketNumber(1u), QuicPacketNumber(2u)}});
ProcessAckPacket(&frame);
EXPECT_TRUE(connection_.GetPathDegradingAlarm()->IsSet());
// Check the deadline of the path degrading alarm.
@@ -6925,7 +6998,8 @@
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
- QuicAckFrame frame = InitAckFrame({{1u, 2u}});
+ QuicAckFrame frame =
+ InitAckFrame({{QuicPacketNumber(1u), QuicPacketNumber(2u)}});
ProcessAckPacket(&frame);
EXPECT_TRUE(connection_.GetPathDegradingAlarm()->IsSet());
// Check the deadline of the path degrading alarm.
@@ -6955,7 +7029,7 @@
// degrading. And will set a timer to detect new path degrading.
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
- frame = InitAckFrame({{2, 3}});
+ frame = InitAckFrame({{QuicPacketNumber(2), QuicPacketNumber(3)}});
ProcessAckPacket(&frame);
EXPECT_FALSE(connection_.IsPathDegrading());
EXPECT_TRUE(connection_.GetPathDegradingAlarm()->IsSet());
@@ -6978,13 +7052,17 @@
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
- QuicAckFrame frame = InitAckFrame({{1u, 2u}});
+ QuicAckFrame frame =
+ InitAckFrame({{QuicPacketNumber(1u), QuicPacketNumber(2u)}});
ProcessAckPacket(&frame);
EXPECT_FALSE(connection_.IsPathDegrading());
EXPECT_FALSE(connection_.GetPathDegradingAlarm()->IsSet());
}
TEST_P(QuicConnectionTest, NoPathDegradingAfterSendingAck) {
+ EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
+ EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(1);
+ ProcessDataPacket(1);
SendAckPacketToPeer();
EXPECT_FALSE(connection_.sent_packet_manager().unacked_packets().empty());
EXPECT_FALSE(connection_.sent_packet_manager().HasInFlightPackets());
@@ -7310,7 +7388,8 @@
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
- QuicAckFrame frame = InitAckFrame({{1, 2}});
+ QuicAckFrame frame =
+ InitAckFrame({{QuicPacketNumber(1), QuicPacketNumber(2)}});
ProcessAckPacket(&frame);
EXPECT_TRUE(connection_.sent_packet_manager().HasInFlightPackets());
// The ping alarm is set for the ping timeout, not the shorter
@@ -7327,7 +7406,7 @@
// the wire.
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
- frame = InitAckFrame({{2, 3}});
+ frame = InitAckFrame({{QuicPacketNumber(2), QuicPacketNumber(3)}});
ProcessAckPacket(&frame);
EXPECT_TRUE(connection_.GetPingAlarm()->IsSet());
EXPECT_EQ(clock_.ApproximateNow() + retransmittable_on_wire_timeout,
@@ -7337,7 +7416,7 @@
// the ping alarm.
QuicTime prev_deadline = connection_.GetPingAlarm()->deadline();
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
- frame = InitAckFrame({{2, 3}});
+ frame = InitAckFrame({{QuicPacketNumber(2), QuicPacketNumber(3)}});
ProcessAckPacket(&frame);
EXPECT_TRUE(connection_.GetPingAlarm()->IsSet());
EXPECT_EQ(prev_deadline, connection_.GetPingAlarm()->deadline());
@@ -7394,7 +7473,8 @@
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
- QuicAckFrame frame = InitAckFrame({{1, 2}});
+ QuicAckFrame frame =
+ InitAckFrame({{QuicPacketNumber(1), QuicPacketNumber(2)}});
ProcessAckPacket(&frame);
EXPECT_TRUE(connection_.GetPingAlarm()->IsSet());
EXPECT_EQ(clock_.ApproximateNow() + retransmittable_on_wire_timeout,
@@ -7412,7 +7492,7 @@
// the wire.
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
- frame = InitAckFrame({{2, 3}});
+ frame = InitAckFrame({{QuicPacketNumber(2), QuicPacketNumber(3)}});
ProcessAckPacket(&frame);
EXPECT_TRUE(connection_.GetPingAlarm()->IsSet());
EXPECT_EQ(clock_.ApproximateNow() + retransmittable_on_wire_timeout,
@@ -7452,13 +7532,14 @@
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
EXPECT_CALL(visitor_, OnForwardProgressConfirmed());
- QuicAckFrame frame = InitAckFrame({{1, 2}});
+ QuicAckFrame frame =
+ InitAckFrame({{QuicPacketNumber(1), QuicPacketNumber(2)}});
ProcessAckPacket(&frame);
// Ack packet 1 again. largest_acked remains at 1, so
// OnForwardProgressConfirmed() should not be called.
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
- frame = InitAckFrame({{1, 2}});
+ frame = InitAckFrame({{QuicPacketNumber(1), QuicPacketNumber(2)}});
ProcessAckPacket(&frame);
// Ack packet 2. This increases the largest_acked to 2, so
@@ -7466,7 +7547,7 @@
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
EXPECT_CALL(*send_algorithm_, OnCongestionEvent(true, _, _, _, _));
EXPECT_CALL(visitor_, OnForwardProgressConfirmed());
- frame = InitAckFrame({{2, 3}});
+ frame = InitAckFrame({{QuicPacketNumber(2), QuicPacketNumber(3)}});
ProcessAckPacket(&frame);
}
@@ -7655,7 +7736,7 @@
std::unique_ptr<QuicPacket> packet(ConstructDataPacket(2, !kHasStopWaiting));
char buffer[kMaxPacketSize];
size_t encrypted_length = peer_framer_.EncryptPayload(
- ENCRYPTION_NONE, 2, *packet, buffer, kMaxPacketSize);
+ ENCRYPTION_NONE, QuicPacketNumber(2), *packet, buffer, kMaxPacketSize);
// Make sure no stream frame is processed.
EXPECT_CALL(visitor_, OnStreamFrame(_)).Times(0);
connection_.ProcessUdpPacket(
@@ -7666,6 +7747,29 @@
EXPECT_EQ(1u, connection_.GetStats().packets_processed);
}
+TEST_P(QuicConnectionTest, AcceptPacketNumberZero) {
+ if (!GetQuicRestartFlag(quic_uint64max_uninitialized_pn) ||
+ version().transport_version != QUIC_VERSION_99) {
+ return;
+ }
+ // Set first_sending_packet_number to be 0 to allow successfully processing
+ // acks which ack packet number 0.
+ QuicFramerPeer::SetFirstSendingPacketNumber(writer_->framer()->framer(), 0);
+ EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
+
+ ProcessPacket(0);
+ EXPECT_EQ(QuicPacketNumber(0), LargestAcked(*outgoing_ack()));
+ EXPECT_EQ(1u, outgoing_ack()->packets.NumIntervals());
+
+ ProcessPacket(1);
+ EXPECT_EQ(QuicPacketNumber(1), LargestAcked(*outgoing_ack()));
+ EXPECT_EQ(1u, outgoing_ack()->packets.NumIntervals());
+
+ ProcessPacket(2);
+ EXPECT_EQ(QuicPacketNumber(2), LargestAcked(*outgoing_ack()));
+ EXPECT_EQ(1u, outgoing_ack()->packets.NumIntervals());
+}
+
} // namespace
} // namespace test
} // namespace quic
diff --git a/quic/core/quic_constants.cc b/quic/core/quic_constants.cc
index 344a94a..8e46f88 100644
--- a/quic/core/quic_constants.cc
+++ b/quic/core/quic_constants.cc
@@ -11,4 +11,15 @@
const char* const kEPIDGoogleFrontEnd = "GFE";
const char* const kEPIDGoogleFrontEnd0 = "GFE0";
+QuicPacketNumber MaxRandomInitialPacketNumber() {
+ static const QuicPacketNumber kMaxRandomInitialPacketNumber =
+ QuicPacketNumber(0x7fffffff);
+ return kMaxRandomInitialPacketNumber;
+}
+
+QuicPacketNumber FirstSendingPacketNumber() {
+ static const QuicPacketNumber kFirstSendingPacketNumber = QuicPacketNumber(1);
+ return kFirstSendingPacketNumber;
+}
+
} // namespace quic
diff --git a/quic/core/quic_constants.h b/quic/core/quic_constants.h
index fa76c21..cf27bef 100644
--- a/quic/core/quic_constants.h
+++ b/quic/core/quic_constants.h
@@ -181,7 +181,7 @@
// The largest gap in packets we'll accept without closing the connection.
// This will likely have to be tuned.
-const QuicPacketNumber kMaxPacketGap = 5000;
+const QuicPacketCount kMaxPacketGap = 5000;
// The maximum number of random padding bytes to add.
const QuicByteCount kMaxNumRandomPaddingBytes = 256;
@@ -193,7 +193,7 @@
// For When using Random Initial Packet Numbers, they can start
// anyplace in the range 1...((2^31)-1) or 0x7fffffff
-const QuicPacketNumber kMaxRandomInitialPacketNumber = 0x7fffffff;
+QUIC_EXPORT_PRIVATE QuicPacketNumber MaxRandomInitialPacketNumber();
// Used to represent an invalid or no control frame id.
const QuicControlFrameId kInvalidControlFrameId = 0;
@@ -224,8 +224,10 @@
// Maximum length allowed for the token in a NEW_TOKEN frame.
const size_t kMaxNewTokenTokenLength = 0xffff;
-// Used to represent an invalid packet number.
-const QuicPacketNumber kInvalidPacketNumber = 0;
+// Packet number of first sending packet of a connection. Please note, this
+// cannot be used as first received packet because peer can choose its starting
+// packet number.
+QUIC_EXPORT_PRIVATE QuicPacketNumber FirstSendingPacketNumber();
// Used by clients to tell if a public reset is sent from a Google frontend.
QUIC_EXPORT_PRIVATE extern const char* const kEPIDGoogleFrontEnd;
diff --git a/quic/core/quic_control_frame_manager.cc b/quic/core/quic_control_frame_manager.cc
index ece6324..c2b5192 100644
--- a/quic/core/quic_control_frame_manager.cc
+++ b/quic/core/quic_control_frame_manager.cc
@@ -17,9 +17,7 @@
: last_control_frame_id_(kInvalidControlFrameId),
least_unacked_(1),
least_unsent_(1),
- session_(session),
- donot_retransmit_old_window_updates_(
- GetQuicReloadableFlag(quic_donot_retransmit_old_window_update2)) {}
+ session_(session) {}
QuicControlFrameManager::~QuicControlFrameManager() {
while (!control_frames_.empty()) {
@@ -129,13 +127,11 @@
<< "Send or retransmit a control frame with invalid control frame id";
return;
}
- if (donot_retransmit_old_window_updates_ &&
- frame.type == WINDOW_UPDATE_FRAME) {
+ if (frame.type == WINDOW_UPDATE_FRAME) {
QuicStreamId stream_id = frame.window_update_frame->stream_id;
if (QuicContainsKey(window_update_frames_, stream_id) &&
id > window_update_frames_[stream_id]) {
// Consider the older window update of the same stream as acked.
- QUIC_RELOADABLE_FLAG_COUNT(quic_donot_retransmit_old_window_update2);
OnControlFrameIdAcked(window_update_frames_[stream_id]);
}
window_update_frames_[stream_id] = id;
@@ -161,8 +157,7 @@
if (!OnControlFrameIdAcked(id)) {
return false;
}
- if (donot_retransmit_old_window_updates_ &&
- frame.type == WINDOW_UPDATE_FRAME) {
+ if (frame.type == WINDOW_UPDATE_FRAME) {
QuicStreamId stream_id = frame.window_update_frame->stream_id;
if (QuicContainsKey(window_update_frames_, stream_id) &&
window_update_frames_[stream_id] == id) {
diff --git a/quic/core/quic_control_frame_manager.h b/quic/core/quic_control_frame_manager.h
index a08d5c3..ace08c6 100644
--- a/quic/core/quic_control_frame_manager.h
+++ b/quic/core/quic_control_frame_manager.h
@@ -102,12 +102,6 @@
// sent.
bool WillingToWrite() const;
- // TODO(wub): Remove this function once
- // quic_donot_retransmit_old_window_update flag is deprecated.
- bool donot_retransmit_old_window_updates() const {
- return donot_retransmit_old_window_updates_;
- }
-
private:
friend class test::QuicControlFrameManagerPeer;
@@ -158,9 +152,6 @@
// Last sent window update frame for each stream.
QuicSmallMap<QuicStreamId, QuicControlFrameId, 10> window_update_frames_;
-
- // Latched value of quic_donot_retransmit_old_window_update2 flag.
- const bool donot_retransmit_old_window_updates_;
};
} // namespace quic
diff --git a/quic/core/quic_control_frame_manager_test.cc b/quic/core/quic_control_frame_manager_test.cc
index a0e0b33..ccddadd 100644
--- a/quic/core/quic_control_frame_manager_test.cc
+++ b/quic/core/quic_control_frame_manager_test.cc
@@ -235,7 +235,6 @@
}
TEST_F(QuicControlFrameManagerTest, DonotRetransmitOldWindowUpdates) {
- SetQuicReloadableFlag(quic_donot_retransmit_old_window_update2, true);
Initialize();
// Send two more window updates of the same stream.
manager_->WriteOrBufferWindowUpdate(kTestStreamId, 200);
@@ -271,7 +270,6 @@
}
TEST_F(QuicControlFrameManagerTest, RetransmitWindowUpdateOfDifferentStreams) {
- SetQuicReloadableFlag(quic_donot_retransmit_old_window_update2, true);
Initialize();
// Send two more window updates of different streams.
manager_->WriteOrBufferWindowUpdate(kTestStreamId + 2, 200);
diff --git a/quic/core/quic_crypto_client_handshaker.cc b/quic/core/quic_crypto_client_handshaker.cc
index 88bfccd..81487df 100644
--- a/quic/core/quic_crypto_client_handshaker.cc
+++ b/quic/core/quic_crypto_client_handshaker.cc
@@ -338,11 +338,10 @@
"CHLO too large");
return;
}
- // TODO(rch): Remove this when we remove quic_use_chlo_packet_size flag.
- out.set_minimum_size(
- static_cast<size_t>(max_packet_size - kFramingOverhead));
next_state_ = STATE_RECV_REJ;
CryptoUtils::HashHandshakeMessage(out, &chlo_hash_, Perspective::IS_CLIENT);
+ session()->connection()->set_fully_pad_crypto_hadshake_packets(
+ crypto_config_->pad_inchoate_hello());
SendHandshakeMessage(out);
return;
}
@@ -377,6 +376,8 @@
*cached->proof_verify_details());
}
next_state_ = STATE_RECV_SHLO;
+ session()->connection()->set_fully_pad_crypto_hadshake_packets(
+ crypto_config_->pad_full_hello());
SendHandshakeMessage(out);
// Be prepared to decrypt with the new server write key.
session()->connection()->SetAlternativeDecrypter(
diff --git a/quic/core/quic_crypto_client_handshaker_test.cc b/quic/core/quic_crypto_client_handshaker_test.cc
new file mode 100644
index 0000000..389be97
--- /dev/null
+++ b/quic/core/quic_crypto_client_handshaker_test.cc
@@ -0,0 +1,213 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/core/quic_crypto_client_handshaker.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "net/third_party/quiche/src/quic/core/proto/crypto_server_config.proto.h"
+#include "net/third_party/quiche/src/quic/core/tls_client_handshaker.h"
+#include "net/third_party/quiche/src/quic/core/tls_server_handshaker.h"
+#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
+
+namespace quic {
+namespace {
+
+using ::testing::Test;
+
+class TestProofHandler : public QuicCryptoClientStream::ProofHandler {
+ public:
+ ~TestProofHandler() override {}
+ void OnProofValid(
+ const QuicCryptoClientConfig::CachedState& cached) override {}
+ void OnProofVerifyDetailsAvailable(
+ const ProofVerifyDetails& verify_details) override {}
+};
+
+class InsecureProofVerifier : public ProofVerifier {
+ public:
+ InsecureProofVerifier() {}
+ ~InsecureProofVerifier() override {}
+
+ // ProofVerifier override.
+ QuicAsyncStatus VerifyProof(
+ const QuicString& hostname,
+ const uint16_t port,
+ const QuicString& server_config,
+ QuicTransportVersion transport_version,
+ QuicStringPiece chlo_hash,
+ const std::vector<QuicString>& certs,
+ const QuicString& cert_sct,
+ const QuicString& signature,
+ const ProofVerifyContext* context,
+ QuicString* error_details,
+ std::unique_ptr<ProofVerifyDetails>* verify_details,
+ std::unique_ptr<ProofVerifierCallback> callback) override {
+ return QUIC_SUCCESS;
+ }
+
+ QuicAsyncStatus VerifyCertChain(
+ const QuicString& hostname,
+ const std::vector<QuicString>& certs,
+ const ProofVerifyContext* context,
+ QuicString* error_details,
+ std::unique_ptr<ProofVerifyDetails>* details,
+ std::unique_ptr<ProofVerifierCallback> callback) override {
+ return QUIC_SUCCESS;
+ }
+
+ std::unique_ptr<ProofVerifyContext> CreateDefaultContext() override {
+ return nullptr;
+ }
+};
+
+class DummyProofSource : public ProofSource {
+ public:
+ DummyProofSource() {}
+ ~DummyProofSource() override {}
+
+ // ProofSource override.
+ void GetProof(const QuicSocketAddress& server_address,
+ const QuicString& hostname,
+ const QuicString& server_config,
+ QuicTransportVersion transport_version,
+ QuicStringPiece chlo_hash,
+ std::unique_ptr<Callback> callback) override {
+ QuicReferenceCountedPointer<ProofSource::Chain> chain =
+ GetCertChain(server_address, hostname);
+ QuicCryptoProof proof;
+ proof.signature = "Dummy signature";
+ proof.leaf_cert_scts = "Dummy timestamp";
+ callback->Run(true, chain, proof, nullptr /* details */);
+ }
+
+ QuicReferenceCountedPointer<Chain> GetCertChain(
+ const QuicSocketAddress& server_address,
+ const QuicString& hostname) override {
+ std::vector<QuicString> certs;
+ certs.push_back("Dummy cert");
+ return QuicReferenceCountedPointer<ProofSource::Chain>(
+ new ProofSource::Chain(certs));
+ }
+
+ void ComputeTlsSignature(
+ const QuicSocketAddress& server_address,
+ const QuicString& hostname,
+ uint16_t signature_algorithm,
+ QuicStringPiece in,
+ std::unique_ptr<SignatureCallback> callback) override {
+ callback->Run(true, "Dummy signature");
+ }
+};
+
+class Handshaker : public QuicCryptoClientHandshaker {
+ public:
+ Handshaker(const QuicServerId& server_id,
+ QuicCryptoClientStream* stream,
+ QuicSession* session,
+ std::unique_ptr<ProofVerifyContext> verify_context,
+ QuicCryptoClientConfig* crypto_config,
+ QuicCryptoClientStream::ProofHandler* proof_handler)
+ : QuicCryptoClientHandshaker(server_id,
+ stream,
+ session,
+ std::move(verify_context),
+ crypto_config,
+ proof_handler) {}
+
+ void DoSendCHLOTest(QuicCryptoClientConfig::CachedState* cached) {
+ QuicCryptoClientHandshaker::DoSendCHLO(cached);
+ }
+};
+
+class QuicCryptoClientHandshakerTest : public Test {
+ protected:
+ QuicCryptoClientHandshakerTest()
+ : proof_handler_(),
+ helper_(),
+ alarm_factory_(),
+ server_id_("host", 123),
+ connection_(new test::MockQuicConnection(&helper_,
+ &alarm_factory_,
+ Perspective::IS_CLIENT)),
+ session_(connection_, false),
+ crypto_client_config_(QuicMakeUnique<InsecureProofVerifier>(),
+ quic::TlsClientHandshaker::CreateSslCtx()),
+ client_stream_(new QuicCryptoClientStream(server_id_,
+ &session_,
+ nullptr,
+ &crypto_client_config_,
+ &proof_handler_)),
+ handshaker_(server_id_,
+ client_stream_,
+ &session_,
+ nullptr,
+ &crypto_client_config_,
+ &proof_handler_),
+ state_() {
+ // Session takes the ownership of the client stream! (but handshaker also
+ // takes a reference to it, but doesn't take the ownership).
+ session_.SetCryptoStream(client_stream_);
+ session_.Initialize();
+ }
+
+ void InitializeServerParametersToEnableFullHello() {
+ QuicCryptoServerConfig::ConfigOptions options;
+ std::unique_ptr<QuicServerConfigProtobuf> config =
+ QuicCryptoServerConfig::GenerateConfig(helper_.GetRandomGenerator(),
+ helper_.GetClock(), options);
+ state_.Initialize(
+ config->config(), "sourcetoken", std::vector<QuicString>{"Dummy cert"},
+ "", "chlo_hash", "signature", helper_.GetClock()->WallNow(),
+ helper_.GetClock()->WallNow().Add(QuicTime::Delta::FromSeconds(30)));
+
+ state_.SetProofValid();
+ }
+
+ TestProofHandler proof_handler_;
+ test::MockQuicConnectionHelper helper_;
+ test::MockAlarmFactory alarm_factory_;
+ QuicServerId server_id_;
+ // Session takes the ownership of the connection.
+ test::MockQuicConnection* connection_;
+ test::MockQuicSession session_;
+ QuicCryptoClientConfig crypto_client_config_;
+ QuicCryptoClientStream* client_stream_;
+ Handshaker handshaker_;
+ QuicCryptoClientConfig::CachedState state_;
+};
+
+TEST_F(QuicCryptoClientHandshakerTest, TestSendFullPaddingInInchoateHello) {
+ handshaker_.DoSendCHLOTest(&state_);
+
+ EXPECT_TRUE(connection_->fully_pad_during_crypto_handshake());
+}
+
+TEST_F(QuicCryptoClientHandshakerTest, TestDisabledPaddingInInchoateHello) {
+ crypto_client_config_.set_pad_inchoate_hello(false);
+ handshaker_.DoSendCHLOTest(&state_);
+ EXPECT_FALSE(connection_->fully_pad_during_crypto_handshake());
+}
+
+TEST_F(QuicCryptoClientHandshakerTest,
+ TestPaddingInFullHelloEvenIfInchoateDisabled) {
+ // Disable inchoate, but full hello should still be padded.
+ crypto_client_config_.set_pad_inchoate_hello(false);
+
+ InitializeServerParametersToEnableFullHello();
+
+ handshaker_.DoSendCHLOTest(&state_);
+ EXPECT_TRUE(connection_->fully_pad_during_crypto_handshake());
+}
+
+TEST_F(QuicCryptoClientHandshakerTest, TestNoPaddingInFullHelloWhenDisabled) {
+ crypto_client_config_.set_pad_full_hello(false);
+
+ InitializeServerParametersToEnableFullHello();
+
+ handshaker_.DoSendCHLOTest(&state_);
+ EXPECT_FALSE(connection_->fully_pad_during_crypto_handshake());
+}
+
+} // namespace
+} // namespace quic
diff --git a/quic/core/quic_crypto_client_stream_test.cc b/quic/core/quic_crypto_client_stream_test.cc
index 14f34a7..d9b344a 100644
--- a/quic/core/quic_crypto_client_stream_test.cc
+++ b/quic/core/quic_crypto_client_stream_test.cc
@@ -329,54 +329,6 @@
EXPECT_FALSE(stream()->WasChannelIDSourceCallbackRun());
}
-TEST_F(QuicCryptoClientStreamTest, TokenBindingNegotiation) {
- server_options_.token_binding_params = QuicTagVector{kTB10, kP256};
- crypto_config_.tb_key_params = QuicTagVector{kTB10};
-
- CompleteCryptoHandshake();
- EXPECT_TRUE(stream()->encryption_established());
- EXPECT_TRUE(stream()->handshake_confirmed());
- EXPECT_EQ(kTB10,
- stream()->crypto_negotiated_params().token_binding_key_param);
-}
-
-TEST_F(QuicCryptoClientStreamTest, NoTokenBindingWithoutServerSupport) {
- crypto_config_.tb_key_params = QuicTagVector{kTB10, kP256};
-
- CompleteCryptoHandshake();
- EXPECT_TRUE(stream()->encryption_established());
- EXPECT_TRUE(stream()->handshake_confirmed());
- EXPECT_EQ(0u, stream()->crypto_negotiated_params().token_binding_key_param);
-}
-
-TEST_F(QuicCryptoClientStreamTest, NoTokenBindingWithoutClientSupport) {
- server_options_.token_binding_params = QuicTagVector{kTB10, kP256};
-
- CompleteCryptoHandshake();
- EXPECT_TRUE(stream()->encryption_established());
- EXPECT_TRUE(stream()->handshake_confirmed());
- EXPECT_EQ(0u, stream()->crypto_negotiated_params().token_binding_key_param);
-}
-
-TEST_F(QuicCryptoClientStreamTest, TokenBindingNotNegotiated) {
- CompleteCryptoHandshake();
- EXPECT_TRUE(stream()->encryption_established());
- EXPECT_TRUE(stream()->handshake_confirmed());
- EXPECT_EQ(0u, stream()->crypto_negotiated_params().token_binding_key_param);
-}
-
-TEST_F(QuicCryptoClientStreamTest, NoTokenBindingInPrivacyMode) {
- server_options_.token_binding_params = QuicTagVector{kTB10};
- crypto_config_.tb_key_params = QuicTagVector{kTB10};
- server_id_ = QuicServerId(kServerHostname, kServerPort, true);
- CreateConnection();
-
- CompleteCryptoHandshake();
- EXPECT_TRUE(stream()->encryption_established());
- EXPECT_TRUE(stream()->handshake_confirmed());
- EXPECT_EQ(0u, stream()->crypto_negotiated_params().token_binding_key_param);
-}
-
TEST_F(QuicCryptoClientStreamTest, PreferredVersion) {
// This mimics the case where client receives version negotiation packet, such
// that, the preferred version is different from the packets' version.
@@ -440,7 +392,7 @@
client_session_->GetMutableCryptoStream()->CryptoConnect();
EXPECT_CALL(*server_session_->helper(), CanAcceptClientHello(_, _, _, _, _))
.Times(testing::AnyNumber());
- EXPECT_CALL(*server_session_->helper(), GenerateConnectionIdForReject(_))
+ EXPECT_CALL(*server_session_->helper(), GenerateConnectionIdForReject(_, _))
.Times(testing::AnyNumber());
crypto_test_utils::AdvanceHandshake(
client_connection_, client_session_->GetMutableCryptoStream(), 0,
diff --git a/quic/core/quic_crypto_server_handshaker.cc b/quic/core/quic_crypto_server_handshaker.cc
index 2b38c4b..e79a60c 100644
--- a/quic/core/quic_crypto_server_handshaker.cc
+++ b/quic/core/quic_crypto_server_handshaker.cc
@@ -184,6 +184,8 @@
// retransmitted.
session()->connection()->EnableSavingCryptoPackets();
}
+ session()->connection()->set_fully_pad_crypto_hadshake_packets(
+ crypto_config_->pad_rej());
SendHandshakeMessage(*reply);
if (reply->tag() == kSREJ) {
@@ -233,6 +235,8 @@
std::move(crypto_negotiated_params_->initial_crypters.decrypter));
session()->connection()->SetDiversificationNonce(*diversification_nonce);
+ session()->connection()->set_fully_pad_crypto_hadshake_packets(
+ crypto_config_->pad_shlo());
SendHandshakeMessage(*reply);
session()->connection()->SetEncrypter(
@@ -463,7 +467,7 @@
return EmptyQuicConnectionId();
}
return helper_->GenerateConnectionIdForReject(
- session()->connection()->connection_id());
+ transport_version(), session()->connection()->connection_id());
}
const QuicSocketAddress QuicCryptoServerHandshaker::GetClientAddress() {
diff --git a/quic/core/quic_crypto_server_stream.h b/quic/core/quic_crypto_server_stream.h
index 63de376..c4de9b0 100644
--- a/quic/core/quic_crypto_server_stream.h
+++ b/quic/core/quic_crypto_server_stream.h
@@ -141,6 +141,7 @@
// Given the current connection_id, generates a new ConnectionId to
// be returned with a stateless reject.
virtual QuicConnectionId GenerateConnectionIdForReject(
+ QuicTransportVersion version,
QuicConnectionId connection_id) const = 0;
// Returns true if |message|, which was received on |self_address| is
diff --git a/quic/core/quic_crypto_server_stream_test.cc b/quic/core/quic_crypto_server_stream_test.cc
index 027e412..33635d8 100644
--- a/quic/core/quic_crypto_server_stream_test.cc
+++ b/quic/core/quic_crypto_server_stream_test.cc
@@ -104,7 +104,7 @@
server_session_.reset(server_session);
EXPECT_CALL(*server_session_->helper(), CanAcceptClientHello(_, _, _, _, _))
.Times(testing::AnyNumber());
- EXPECT_CALL(*server_session_->helper(), GenerateConnectionIdForReject(_))
+ EXPECT_CALL(*server_session_->helper(), GenerateConnectionIdForReject(_, _))
.Times(testing::AnyNumber());
crypto_test_utils::FakeServerOptions options;
options.token_binding_params = QuicTagVector{kTB10};
@@ -489,28 +489,6 @@
QuicCryptoServerStreamPeer::DoesPeerSupportStatelessRejects(message_));
}
-TEST_P(QuicCryptoServerStreamTest, TokenBindingNegotiated) {
- Initialize();
-
- client_options_.token_binding_params = QuicTagVector{kTB10, kP256};
- CompleteCryptoHandshake();
- EXPECT_EQ(
- kTB10,
- server_stream()->crypto_negotiated_params().token_binding_key_param);
- EXPECT_TRUE(server_stream()->encryption_established());
- EXPECT_TRUE(server_stream()->handshake_confirmed());
-}
-
-TEST_P(QuicCryptoServerStreamTest, NoTokenBindingWithoutClientSupport) {
- Initialize();
-
- CompleteCryptoHandshake();
- EXPECT_EQ(
- 0u, server_stream()->crypto_negotiated_params().token_binding_key_param);
- EXPECT_TRUE(server_stream()->encryption_established());
- EXPECT_TRUE(server_stream()->handshake_confirmed());
-}
-
class QuicCryptoServerStreamTestWithFailingProofSource
: public QuicCryptoServerStreamTest {
public:
diff --git a/quic/core/quic_crypto_stream.cc b/quic/core/quic_crypto_stream.cc
index 440a480..8199571 100644
--- a/quic/core/quic_crypto_stream.cc
+++ b/quic/core/quic_crypto_stream.cc
@@ -111,19 +111,6 @@
result);
}
-bool QuicCryptoStream::ExportTokenBindingKeyingMaterial(
- QuicString* result) const {
- if (!encryption_established()) {
- QUIC_BUG << "ExportTokenBindingKeyingMaterial was called before initial"
- << "encryption was established.";
- return false;
- }
- return CryptoUtils::ExportKeyingMaterial(
- crypto_negotiated_params().initial_subkey_secret,
- "EXPORTER-Token-Binding",
- /* context= */ "", 32, result);
-}
-
void QuicCryptoStream::WriteCryptoData(EncryptionLevel level,
QuicStringPiece data) {
// TODO(nharper): This approach to writing data, by setting the encryption
diff --git a/quic/core/quic_crypto_stream.h b/quic/core/quic_crypto_stream.h
index a2cf9fe..0593f44 100644
--- a/quic/core/quic_crypto_stream.h
+++ b/quic/core/quic_crypto_stream.h
@@ -56,16 +56,6 @@
size_t result_len,
QuicString* result) const;
- // Performs key extraction for Token Binding. Unlike ExportKeyingMaterial,
- // this function can be called before forward-secure encryption is
- // established. Returns false if initial encryption has not been established,
- // and true on success.
- //
- // Since this depends only on the initial keys, a signature over it can be
- // repurposed by an attacker who obtains the client's or server's DH private
- // value.
- bool ExportTokenBindingKeyingMaterial(QuicString* result) const;
-
// Writes |data| to the QuicStream at level |level|.
virtual void WriteCryptoData(EncryptionLevel level, QuicStringPiece data);
diff --git a/quic/core/quic_default_packet_writer.cc b/quic/core/quic_default_packet_writer.cc
index 6e8e833..2c162e0 100644
--- a/quic/core/quic_default_packet_writer.cc
+++ b/quic/core/quic_default_packet_writer.cc
@@ -24,7 +24,7 @@
<< "QuicDefaultPacketWriter does not accept any options.";
WriteResult result = QuicSocketUtils::WritePacket(fd_, buffer, buf_len,
self_address, peer_address);
- if (result.status == WRITE_STATUS_BLOCKED) {
+ if (IsWriteBlockedStatus(result.status)) {
write_blocked_ = true;
}
return result;
diff --git a/quic/core/quic_dispatcher.cc b/quic/core/quic_dispatcher.cc
index f476a47..0cb03aa 100644
--- a/quic/core/quic_dispatcher.cc
+++ b/quic/core/quic_dispatcher.cc
@@ -92,6 +92,13 @@
}
return WRITE_FAILED;
}
+ bool WriteCryptoData(EncryptionLevel level,
+ QuicStreamOffset offset,
+ QuicByteCount data_length,
+ QuicDataWriter* writer) override {
+ QUIC_BUG << "PacketCollector::WriteCryptoData is unimplemented.";
+ return false;
+ }
std::vector<std::unique_ptr<QuicEncryptedPacket>>* packets() {
return &packets_;
@@ -235,9 +242,9 @@
if (helper_->CanAcceptClientHello(chlo, client_address_, peer_address_,
self_address_, &error_details_)) {
can_accept_ = true;
- rejector_->OnChlo(version, connection_id,
- helper_->GenerateConnectionIdForReject(connection_id),
- chlo);
+ rejector_->OnChlo(
+ version, connection_id,
+ helper_->GenerateConnectionIdForReject(version, connection_id), chlo);
}
}
@@ -506,27 +513,29 @@
}
// initial packet number of 0 is always invalid.
- if (header.packet_number == kInvalidPacketNumber) {
+ if (!header.packet_number.IsInitialized()) {
return kFateTimeWait;
}
if (GetQuicRestartFlag(quic_enable_accept_random_ipn)) {
QUIC_RESTART_FLAG_COUNT_N(quic_enable_accept_random_ipn, 1, 2);
// Accepting Initial Packet Numbers in 1...((2^31)-1) range... check
// maximum accordingly.
- if (header.packet_number > kMaxRandomInitialPacketNumber) {
+ if (header.packet_number > MaxRandomInitialPacketNumber()) {
return kFateTimeWait;
}
} else {
// Count those that would have been accepted if FLAGS..random_ipn
// were true -- to detect/diagnose potential issues prior to
// enabling the flag.
- if ((header.packet_number > kMaxReasonableInitialPacketNumber) &&
- (header.packet_number <= kMaxRandomInitialPacketNumber)) {
+ if ((header.packet_number >
+ QuicPacketNumber(kMaxReasonableInitialPacketNumber)) &&
+ (header.packet_number <= MaxRandomInitialPacketNumber())) {
QUIC_CODE_COUNT_N(had_possibly_random_ipn, 1, 2);
}
// Check that the sequence number is within the range that the client is
// expected to send before receiving a response from the server.
- if (header.packet_number > kMaxReasonableInitialPacketNumber) {
+ if (header.packet_number >
+ QuicPacketNumber(kMaxReasonableInitialPacketNumber)) {
return kFateTimeWait;
}
}
@@ -552,9 +561,7 @@
// expediency. Stop doing this when removing flag
// quic_always_reset_ietf_connections.
if (!GetQuicReloadableFlag(quic_always_reset_ietf_connections) &&
- (!GetQuicReloadableFlag(
- quic_send_reset_for_post_handshake_connections_without_termination_packets) || // NOLINT
- (source == ConnectionCloseSource::FROM_PEER))) {
+ source == ConnectionCloseSource::FROM_PEER) {
action = QuicTimeWaitListManager::DO_NOTHING;
} else if (!connection->IsHandshakeConfirmed()) {
QUIC_CODE_COUNT(quic_v44_add_to_time_wait_list_with_handshake_failed);
@@ -727,6 +734,8 @@
void QuicDispatcher::OnRstStreamReceived(const QuicRstStreamFrame& frame) {}
+void QuicDispatcher::OnStopSendingReceived(const QuicStopSendingFrame& frame) {}
+
void QuicDispatcher::OnConnectionAddedToTimeWaitList(
QuicConnectionId connection_id) {
QUIC_DLOG(INFO) << "Connection " << connection_id
diff --git a/quic/core/quic_dispatcher.h b/quic/core/quic_dispatcher.h
index 3597a97..d6eb35b 100644
--- a/quic/core/quic_dispatcher.h
+++ b/quic/core/quic_dispatcher.h
@@ -91,6 +91,11 @@
// Collects reset error code received on streams.
void OnRstStreamReceived(const QuicRstStreamFrame& frame) override;
+ // QuicSession::Visitor interface implementation (via inheritance of
+ // QuicTimeWaitListManager::Visitor):
+ // Collects reset error code received on streams.
+ void OnStopSendingReceived(const QuicStopSendingFrame& frame) override;
+
// QuicTimeWaitListManager::Visitor interface implementation
// Called whenever the time wait list manager adds a new connection to the
// time-wait list.
@@ -110,7 +115,7 @@
// send a handshake and then up to 50 or so data packets, and then it may
// resend the handshake packet up to 10 times. (Retransmitted packets are
// sent with unique packet numbers.)
- static const QuicPacketNumber kMaxReasonableInitialPacketNumber = 100;
+ static const uint64_t kMaxReasonableInitialPacketNumber = 100;
static_assert(kMaxReasonableInitialPacketNumber >=
kInitialCongestionWindow + 10,
"kMaxReasonableInitialPacketNumber is unreasonably small "
@@ -348,7 +353,7 @@
// Please do not use this method.
// TODO(fayang): Remove this method when deprecating
- // quic_proxy_use_real_packet_format_when_reject flag.
+ // quic_fix_last_packet_is_ietf_quic flag.
PacketHeaderFormat GetLastPacketFormat() const;
private:
diff --git a/quic/core/quic_dispatcher_test.cc b/quic/core/quic_dispatcher_test.cc
index afc4687..0381cf5 100644
--- a/quic/core/quic_dispatcher_test.cc
+++ b/quic/core/quic_dispatcher_test.cc
@@ -268,7 +268,7 @@
const QuicString& data,
QuicConnectionIdLength connection_id_length,
QuicPacketNumberLength packet_number_length,
- QuicPacketNumber packet_number) {
+ uint64_t packet_number) {
ProcessPacket(peer_address, connection_id, has_version_flag,
CurrentSupportedVersions().front(), data,
connection_id_length, packet_number_length, packet_number);
@@ -282,7 +282,7 @@
const QuicString& data,
QuicConnectionIdLength connection_id_length,
QuicPacketNumberLength packet_number_length,
- QuicPacketNumber packet_number) {
+ uint64_t packet_number) {
ParsedQuicVersionVector versions(SupportedVersions(version));
std::unique_ptr<QuicEncryptedPacket> packet(ConstructEncryptedPacket(
connection_id, EmptyQuicConnectionId(), has_version_flag, false,
@@ -676,18 +676,19 @@
SetQuicRestartFlag(quic_enable_accept_random_ipn, true);
ProcessPacket(client_address, connection_id, true, SerializeCHLO(),
PACKET_8BYTE_CONNECTION_ID, PACKET_4BYTE_PACKET_NUMBER,
- kMaxRandomInitialPacketNumber +
+ MaxRandomInitialPacketNumber().ToUint64() +
QuicDispatcher::kMaxReasonableInitialPacketNumber + 1);
}
TEST_F(QuicDispatcherTest, SupportedTransportVersionsChangeInFlight) {
- static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 7u,
+ static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 8u,
"Supported versions out of sync");
SetQuicReloadableFlag(quic_disable_version_35, false);
SetQuicReloadableFlag(quic_enable_version_43, true);
SetQuicReloadableFlag(quic_enable_version_44, true);
SetQuicReloadableFlag(quic_enable_version_45, true);
SetQuicReloadableFlag(quic_enable_version_46, true);
+ SetQuicReloadableFlag(quic_enable_version_47, true);
SetQuicReloadableFlag(quic_enable_version_99, true);
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
server_address_ = QuicSocketAddress(QuicIpAddress::Any4(), 5);
@@ -741,6 +742,39 @@
SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID,
PACKET_4BYTE_PACKET_NUMBER, 1);
+ // Turn off version 47.
+ SetQuicReloadableFlag(quic_enable_version_47, false);
+ connection_id = TestConnectionId(++conn_id);
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address,
+ QuicStringPiece("hq"), _))
+ .Times(0);
+ ProcessPacket(client_address, connection_id, true,
+ ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_47),
+ SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID,
+ PACKET_4BYTE_PACKET_NUMBER, 1);
+
+ // Turn on version 47.
+ SetQuicReloadableFlag(quic_enable_version_47, true);
+ connection_id = TestConnectionId(++conn_id);
+ EXPECT_CALL(*dispatcher_, CreateQuicSession(connection_id, client_address,
+ QuicStringPiece("hq"), _))
+ .WillOnce(testing::Return(CreateSession(
+ dispatcher_.get(), config_, connection_id, client_address,
+ &mock_helper_, &mock_alarm_factory_, &crypto_config_,
+ QuicDispatcherPeer::GetCache(dispatcher_.get()), &session1_)));
+ EXPECT_CALL(*reinterpret_cast<MockQuicConnection*>(session1_->connection()),
+ ProcessUdpPacket(_, _, _))
+ .WillOnce(WithArg<2>(
+ Invoke([this, connection_id](const QuicEncryptedPacket& packet) {
+ ValidatePacket(connection_id, packet);
+ })));
+ EXPECT_CALL(*dispatcher_,
+ ShouldCreateOrBufferPacketForConnection(connection_id, _));
+ ProcessPacket(client_address, connection_id, true,
+ ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_47),
+ SerializeCHLO(), PACKET_8BYTE_CONNECTION_ID,
+ PACKET_4BYTE_PACKET_NUMBER, 1);
+
// Turn off version 46.
SetQuicReloadableFlag(quic_enable_version_46, false);
connection_id = TestConnectionId(++conn_id);
@@ -1956,7 +1990,7 @@
// Process another |kDefaultMaxUndecryptablePackets| + 1 data packets. The
// last one should be dropped.
- for (QuicPacketNumber packet_number = 2;
+ for (uint64_t packet_number = 2;
packet_number <= kDefaultMaxUndecryptablePackets + 2; ++packet_number) {
ProcessPacket(client_addr_, last_connection_id, true, "data packet");
}
diff --git a/quic/core/quic_epoll_alarm_factory.cc b/quic/core/quic_epoll_alarm_factory.cc
index 550ee13..2ec2f6f 100644
--- a/quic/core/quic_epoll_alarm_factory.cc
+++ b/quic/core/quic_epoll_alarm_factory.cc
@@ -14,7 +14,7 @@
class QuicEpollAlarm : public QuicAlarm {
public:
- QuicEpollAlarm(gfe2::EpollServer* epoll_server,
+ QuicEpollAlarm(QuicEpollServer* epoll_server,
QuicArenaScopedPtr<QuicAlarm::Delegate> delegate)
: QuicAlarm(std::move(delegate)),
epoll_server_(epoll_server),
@@ -44,13 +44,13 @@
}
private:
- class EpollAlarmImpl : public gfe2::EpollAlarm {
+ class EpollAlarmImpl : public QuicEpollAlarmBase {
public:
explicit EpollAlarmImpl(QuicEpollAlarm* alarm) : alarm_(alarm) {}
// Use the same integer type as the base class.
int64 /* allow-non-std-int */ OnAlarm() override {
- EpollAlarm::OnAlarm();
+ QuicEpollAlarmBase::OnAlarm();
alarm_->Fire();
// Fire will take care of registering the alarm, if needed.
return 0;
@@ -60,13 +60,13 @@
QuicEpollAlarm* alarm_;
};
- gfe2::EpollServer* epoll_server_;
+ QuicEpollServer* epoll_server_;
EpollAlarmImpl epoll_alarm_impl_;
};
} // namespace
-QuicEpollAlarmFactory::QuicEpollAlarmFactory(gfe2::EpollServer* epoll_server)
+QuicEpollAlarmFactory::QuicEpollAlarmFactory(QuicEpollServer* epoll_server)
: epoll_server_(epoll_server) {}
QuicEpollAlarmFactory::~QuicEpollAlarmFactory() {}
diff --git a/quic/core/quic_epoll_alarm_factory.h b/quic/core/quic_epoll_alarm_factory.h
index d1ec7ca..fc9b45c 100644
--- a/quic/core/quic_epoll_alarm_factory.h
+++ b/quic/core/quic_epoll_alarm_factory.h
@@ -5,17 +5,17 @@
#ifndef QUICHE_QUIC_CORE_QUIC_EPOLL_ALARM_FACTORY_H_
#define QUICHE_QUIC_CORE_QUIC_EPOLL_ALARM_FACTORY_H_
-#include "gfe/gfe2/base/epoll_server.h"
#include "net/third_party/quiche/src/quic/core/quic_alarm.h"
#include "net/third_party/quiche/src/quic/core/quic_alarm_factory.h"
#include "net/third_party/quiche/src/quic/core/quic_one_block_arena.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_epoll.h"
namespace quic {
// Creates alarms that use the supplied EpollServer for timing and firing.
class QuicEpollAlarmFactory : public QuicAlarmFactory {
public:
- explicit QuicEpollAlarmFactory(gfe2::EpollServer* eps);
+ explicit QuicEpollAlarmFactory(QuicEpollServer* eps);
QuicEpollAlarmFactory(const QuicEpollAlarmFactory&) = delete;
QuicEpollAlarmFactory& operator=(const QuicEpollAlarmFactory&) = delete;
~QuicEpollAlarmFactory() override;
@@ -27,7 +27,7 @@
QuicConnectionArena* arena) override;
private:
- gfe2::EpollServer* epoll_server_; // Not owned.
+ QuicEpollServer* epoll_server_; // Not owned.
};
} // namespace quic
diff --git a/quic/core/quic_epoll_connection_helper.cc b/quic/core/quic_epoll_connection_helper.cc
index 3070c99..49002f6 100644
--- a/quic/core/quic_epoll_connection_helper.cc
+++ b/quic/core/quic_epoll_connection_helper.cc
@@ -16,7 +16,7 @@
namespace quic {
QuicEpollConnectionHelper::QuicEpollConnectionHelper(
- gfe2::EpollServer* epoll_server,
+ QuicEpollServer* epoll_server,
QuicAllocator type)
: clock_(epoll_server),
random_generator_(QuicRandom::GetInstance()),
diff --git a/quic/core/quic_epoll_connection_helper.h b/quic/core/quic_epoll_connection_helper.h
index 858954a..62e030c 100644
--- a/quic/core/quic_epoll_connection_helper.h
+++ b/quic/core/quic_epoll_connection_helper.h
@@ -18,6 +18,7 @@
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/core/quic_simple_buffer_allocator.h"
#include "net/third_party/quiche/src/quic/core/quic_time.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_epoll.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
#include "net/quic/platform/impl/quic_epoll_clock.h"
@@ -43,7 +44,7 @@
class QuicEpollConnectionHelper : public QuicConnectionHelperInterface {
public:
- QuicEpollConnectionHelper(gfe2::EpollServer* eps, QuicAllocator allocator);
+ QuicEpollConnectionHelper(QuicEpollServer* eps, QuicAllocator allocator);
QuicEpollConnectionHelper(const QuicEpollConnectionHelper&) = delete;
QuicEpollConnectionHelper& operator=(const QuicEpollConnectionHelper&) =
delete;
diff --git a/quic/core/quic_framer.cc b/quic/core/quic_framer.cc
index e659b38..1b93074 100644
--- a/quic/core/quic_framer.cc
+++ b/quic/core/quic_framer.cc
@@ -130,7 +130,7 @@
const uint8_t kSourceConnectionIdLengthMask = 0x0F;
// Returns the absolute value of the difference between |a| and |b|.
-QuicPacketNumber Delta(QuicPacketNumber a, QuicPacketNumber b) {
+uint64_t Delta(uint64_t a, uint64_t b) {
// Since these are unsigned numbers, we can't just return abs(a - b)
if (a < b) {
return b - a;
@@ -138,12 +138,18 @@
return a - b;
}
-QuicPacketNumber ClosestTo(QuicPacketNumber target,
- QuicPacketNumber a,
- QuicPacketNumber b) {
+uint64_t ClosestTo(uint64_t target, uint64_t a, uint64_t b) {
return (Delta(target, a) < Delta(target, b)) ? a : b;
}
+uint64_t PacketNumberIntervalLength(
+ const QuicInterval<QuicPacketNumber>& interval) {
+ if (interval.Empty()) {
+ return 0u;
+ }
+ return interval.max() - interval.min();
+}
+
QuicPacketNumberLength ReadSequenceNumberLength(uint8_t flags) {
switch (flags & PACKET_FLAGS_8BYTE_PACKET) {
case PACKET_FLAGS_8BYTE_PACKET:
@@ -180,7 +186,7 @@
uint8_t PacketNumberLengthToOnWireValue(
QuicTransportVersion version,
QuicPacketNumberLength packet_number_length) {
- if (version == QUIC_VERSION_99) {
+ if (version > QUIC_VERSION_46) {
return packet_number_length - 1;
}
switch (packet_number_length) {
@@ -203,7 +209,7 @@
QuicPacketNumberLength* packet_number_length) {
DCHECK(!(type & FLAGS_LONG_HEADER));
const bool two_bits_packet_number_length =
- infer_packet_header_type_from_version ? version == QUIC_VERSION_99
+ infer_packet_header_type_from_version ? version > QUIC_VERSION_46
: (type & FLAGS_FIXED_BIT);
if (two_bits_packet_number_length) {
*packet_number_length =
@@ -231,13 +237,13 @@
QuicLongHeaderType type) {
switch (type) {
case INITIAL:
- return version == QUIC_VERSION_99 ? 0 : 0x7F;
+ return version > QUIC_VERSION_46 ? 0 : 0x7F;
case ZERO_RTT_PROTECTED:
- return version == QUIC_VERSION_99 ? 1 << 4 : 0x7C;
+ return version > QUIC_VERSION_46 ? 1 << 4 : 0x7C;
case HANDSHAKE:
- return version == QUIC_VERSION_99 ? 2 << 4 : 0x7D;
+ return version > QUIC_VERSION_46 ? 2 << 4 : 0x7D;
case RETRY:
- return version == QUIC_VERSION_99 ? 3 << 4 : 0x7E;
+ return version > QUIC_VERSION_46 ? 3 << 4 : 0x7E;
case VERSION_NEGOTIATION:
return 0xF0; // Value does not matter
default:
@@ -250,7 +256,7 @@
uint8_t type,
QuicLongHeaderType* long_header_type) {
DCHECK((type & FLAGS_LONG_HEADER) && version != QUIC_VERSION_UNSUPPORTED);
- if (version == QUIC_VERSION_99) {
+ if (version > QUIC_VERSION_46) {
switch ((type & 0x30) >> 4) {
case 0:
*long_header_type = INITIAL;
@@ -297,7 +303,7 @@
QuicPacketNumberLength GetLongHeaderPacketNumberLength(
QuicTransportVersion version,
uint8_t type) {
- if (version == QUIC_VERSION_99) {
+ if (version > QUIC_VERSION_46) {
return static_cast<QuicPacketNumberLength>((type & 0x03) + 1);
}
return PACKET_4BYTE_PACKET_NUMBER;
@@ -324,6 +330,19 @@
return static_cast<uint8_t>(length - kConnectionIdLengthAdjustment);
}
+bool IsValidPacketNumberLength(QuicPacketNumberLength packet_number_length) {
+ size_t length = packet_number_length;
+ return length == 1 || length == 2 || length == 4 || length == 6 ||
+ length == 8;
+}
+
+bool IsValidFullPacketNumber(uint64_t full_packet_number,
+ QuicTransportVersion version) {
+ return full_packet_number > 0 ||
+ (GetQuicRestartFlag(quic_uint64max_uninitialized_pn) &&
+ version == QUIC_VERSION_99);
+}
+
} // namespace
QuicFramer::QuicFramer(const ParsedQuicVersionVector& supported_versions,
@@ -331,7 +350,6 @@
Perspective perspective)
: visitor_(nullptr),
error_(QUIC_NO_ERROR),
- largest_packet_number_(0),
last_serialized_connection_id_(EmptyQuicConnectionId()),
last_version_label_(0),
last_header_form_(GOOGLE_QUIC_PACKET),
@@ -345,9 +363,8 @@
process_timestamps_(false),
creation_time_(creation_time),
last_timestamp_(QuicTime::Delta::Zero()),
+ first_sending_packet_number_(FirstSendingPacketNumber()),
data_producer_(nullptr),
- process_stateless_reset_at_client_only_(
- GetQuicReloadableFlag(quic_process_stateless_reset_at_client_only)),
infer_packet_header_type_from_version_(perspective ==
Perspective::IS_CLIENT) {
DCHECK(!supported_versions.empty());
@@ -377,6 +394,13 @@
}
// static
+size_t QuicFramer::GetMinCryptoFrameSize(QuicStreamOffset offset,
+ QuicPacketLength data_length) {
+ return kQuicFrameTypeSize + QuicDataWriter::GetVarInt62Len(offset) +
+ QuicDataWriter::GetVarInt62Len(data_length);
+}
+
+// static
size_t QuicFramer::GetMessageFrameSize(QuicTransportVersion version,
bool last_frame_in_packet,
QuicByteCount length) {
@@ -500,6 +524,9 @@
if (version != QUIC_VERSION_99) {
return kQuicFrameTypeSize + kQuicMaxStreamIdSize;
}
+ // TODO(fkastenholz): This should be converted to use
+ // QuicUtils::GetInvalidStreamId to get the correct invalid stream id value
+ // and not rely on 0.
if (frame.stream_id == 0) {
// return size of IETF QUIC Blocked frame
return kQuicFrameTypeSize + QuicDataWriter::GetVarInt62Len(frame.offset);
@@ -869,7 +896,6 @@
set_detailed_error(
"Attempt to append CRYPTO frame and not in version 99.");
return RaiseError(QUIC_INTERNAL_ERROR);
-
default:
RaiseError(QUIC_INVALID_FRAME_DATA);
QUIC_BUG << "QUIC_INVALID_FRAME_DATA";
@@ -1050,10 +1076,30 @@
return writer.length();
}
+size_t QuicFramer::BuildIetfConnectivityProbingPacket(
+ const QuicPacketHeader& header,
+ char* buffer,
+ size_t packet_length) {
+ QuicFrames frames;
+
+ // Write a PING frame, which has no data payload.
+ QuicPingFrame ping_frame;
+ frames.push_back(QuicFrame(ping_frame));
+
+ // Add padding to the rest of the packet.
+ QuicPaddingFrame padding_frame;
+ frames.push_back(QuicFrame(padding_frame));
+
+ return BuildIetfDataPacket(header, frames, buffer, packet_length);
+}
+
size_t QuicFramer::BuildConnectivityProbingPacket(
const QuicPacketHeader& header,
char* buffer,
size_t packet_length) {
+ if (version_.transport_version == QUIC_VERSION_99) {
+ return BuildIetfConnectivityProbingPacket(header, buffer, packet_length);
+ }
QuicDataWriter writer(packet_length, buffer, endianness());
if (!AppendPacketHeader(header, &writer)) {
@@ -1088,47 +1134,25 @@
size_t packet_length,
QuicPathFrameBuffer* payload,
QuicRandom* randomizer) {
- QuicDataWriter writer(packet_length, buffer, endianness());
- DCHECK_EQ(version_.transport_version, QUIC_VERSION_99)
- << "Attempt to build a PATH_CHALLENGE Connectivity Probing packet and "
- "not doing IETF QUIC";
-
- if (!AppendPacketHeader(header, &writer)) {
- QUIC_BUG << "AppendPacketHeader failed";
+ if (version_.transport_version != QUIC_VERSION_99) {
+ QUIC_BUG << "Attempt to build a PATH_CHALLENGE Connectivity Probing "
+ "packet and not doing IETF QUIC";
return 0;
}
+ QuicFrames frames;
// Write a PATH_CHALLENGE frame, which has a random 8-byte payload
randomizer->RandBytes(payload->data(), payload->size());
QuicPathChallengeFrame path_challenge_frame(0, *payload);
- if (!AppendTypeByte(QuicFrame(&path_challenge_frame),
- /* last_frame_in_packet = */ false, &writer)) {
- QUIC_BUG
- << "AppendTypeByte failed for PATH_CHALLENGE frame in probing packet";
- return 0;
- }
-
- if (!AppendPathChallengeFrame(path_challenge_frame, &writer)) {
- QUIC_BUG << "AppendPathChallengeFrame failed for PATH_CHALLENGE frame in "
- "probing packet";
- return 0;
- }
+ frames.push_back(QuicFrame(&path_challenge_frame));
// Add padding to the rest of the packet in order to assess Path MTU
// characteristics.
QuicPaddingFrame padding_frame;
- if (!AppendTypeByte(QuicFrame(padding_frame), true, &writer)) {
- QUIC_BUG << "AppendTypeByte failed for padding frame in probing packet";
- return 0;
- }
- if (!AppendPaddingFrame(padding_frame, &writer)) {
- QUIC_BUG << "AppendPaddingFrame of " << padding_frame.num_padding_bytes
- << " failed";
- return 0;
- }
+ frames.push_back(QuicFrame(padding_frame));
- return writer.length();
+ return BuildIetfDataPacket(header, frames, buffer, packet_length);
}
size_t QuicFramer::BuildPathResponsePacket(
@@ -1142,53 +1166,33 @@
<< "Attempt to generate connectivity response with no request payloads";
return 0;
}
-
- QuicDataWriter writer(packet_length, buffer, endianness());
-
- DCHECK_EQ(version_.transport_version, QUIC_VERSION_99)
- << "Attempt to build a PATH_RESPONSE Connectivity Probing packet and "
- "not doing IETF QUIC";
-
- if (!AppendPacketHeader(header, &writer)) {
- QUIC_BUG << "AppendPacketHeader failed";
+ if (version_.transport_version != QUIC_VERSION_99) {
+ QUIC_BUG << "Attempt to build a PATH_RESPONSE Connectivity Probing "
+ "packet and not doing IETF QUIC";
return 0;
}
- // Write a set of PATH_RESPONSE frames to a single packet, each with the
- // 8-byte payload of the corresponding PATH_REQUEST frame from a single
- // received packet.
+ std::vector<std::unique_ptr<QuicPathResponseFrame>> path_response_frames;
for (const QuicPathFrameBuffer& payload : payloads) {
// Note that the control frame ID can be 0 since this is not retransmitted.
- QuicPathResponseFrame path_response_frame(0, payload);
+ path_response_frames.push_back(
+ QuicMakeUnique<QuicPathResponseFrame>(0, payload));
+ }
- if (!AppendTypeByte(QuicFrame(&path_response_frame), false, &writer)) {
- QUIC_BUG
- << "AppendTypeByte failed for PATH_RESPONSE frame in probing packet";
- return 0;
- }
-
- if (!AppendPathResponseFrame(path_response_frame, &writer)) {
- QUIC_BUG << "AppendPathChallengeFrame failed for PATH_CHALLENGE frame in "
- "probing packet";
- return 0;
- }
+ QuicFrames frames;
+ for (const std::unique_ptr<QuicPathResponseFrame>& path_response_frame :
+ path_response_frames) {
+ frames.push_back(QuicFrame(path_response_frame.get()));
}
if (is_padded) {
// Add padding to the rest of the packet in order to assess Path MTU
// characteristics.
QuicPaddingFrame padding_frame;
- if (!AppendTypeByte(QuicFrame(padding_frame), true, &writer)) {
- QUIC_BUG << "AppendTypeByte failed for padding frame in probing packet";
- return 0;
- }
- if (!AppendPaddingFrame(padding_frame, &writer)) {
- QUIC_BUG << "AppendPaddingFrame of " << padding_frame.num_padding_bytes
- << " failed";
- return 0;
- }
+ frames.push_back(QuicFrame(padding_frame));
}
- return writer.length();
+
+ return BuildIetfDataPacket(header, frames, buffer, packet_length);
}
// static
@@ -1274,7 +1278,7 @@
} else {
// Append an random packet number.
QuicPacketNumber random_packet_number =
- QuicRandom::GetInstance()->RandUint64() % 255 + 1;
+ QuicPacketNumber(QuicRandom::GetInstance()->RandUint64() % 255 + 1);
if (!AppendPacketNumber(PACKET_1BYTE_PACKET_NUMBER, random_packet_number,
&writer)) {
return nullptr;
@@ -1470,35 +1474,17 @@
size_t buffer_length) {
DCHECK_NE(GOOGLE_QUIC_PACKET, header->form);
DCHECK(!header->has_possible_stateless_reset_token);
- if (header->form == IETF_QUIC_SHORT_HEADER_PACKET) {
- if (!process_stateless_reset_at_client_only_) {
- // Peak possible stateless reset token. Will only be used on decryption
- // failure.
- QuicStringPiece remaining = encrypted_reader->PeekRemainingPayload();
- if (remaining.length() >=
- sizeof(header->possible_stateless_reset_token)) {
- remaining.copy(
- reinterpret_cast<char*>(&header->possible_stateless_reset_token),
- sizeof(header->possible_stateless_reset_token),
- remaining.length() -
- sizeof(header->possible_stateless_reset_token));
- }
- } else {
- QUIC_RELOADABLE_FLAG_COUNT(quic_process_stateless_reset_at_client_only);
- if (perspective_ == Perspective::IS_CLIENT) {
- // Peek possible stateless reset token. Will only be used on decryption
- // failure.
- QuicStringPiece remaining = encrypted_reader->PeekRemainingPayload();
- if (remaining.length() >=
- sizeof(header->possible_stateless_reset_token)) {
- header->has_possible_stateless_reset_token = true;
- memcpy(
- &header->possible_stateless_reset_token,
- &remaining.data()[remaining.length() -
- sizeof(header->possible_stateless_reset_token)],
- sizeof(header->possible_stateless_reset_token));
- }
- }
+ if (header->form == IETF_QUIC_SHORT_HEADER_PACKET &&
+ perspective_ == Perspective::IS_CLIENT) {
+ // Peek possible stateless reset token. Will only be used on decryption
+ // failure.
+ QuicStringPiece remaining = encrypted_reader->PeekRemainingPayload();
+ if (remaining.length() >= sizeof(header->possible_stateless_reset_token)) {
+ header->has_possible_stateless_reset_token = true;
+ memcpy(&header->possible_stateless_reset_token,
+ &remaining.data()[remaining.length() -
+ sizeof(header->possible_stateless_reset_token)],
+ sizeof(header->possible_stateless_reset_token));
}
}
@@ -1506,15 +1492,15 @@
header->long_packet_type != VERSION_NEGOTIATION) {
// Process packet number.
QuicPacketNumber base_packet_number = largest_packet_number_;
-
+ uint64_t full_packet_number;
if (!ProcessAndCalculatePacketNumber(
encrypted_reader, header->packet_number_length, base_packet_number,
- &header->packet_number)) {
+ &full_packet_number)) {
set_detailed_error("Unable to read packet number.");
return RaiseError(QUIC_INVALID_PACKET_HEADER);
}
- if (header->packet_number == kInvalidPacketNumber) {
+ if (!IsValidFullPacketNumber(full_packet_number, transport_version())) {
if (IsIetfStatelessResetPacket(*header)) {
// This is a stateless reset packet.
QuicIetfStatelessResetPacket packet(
@@ -1525,6 +1511,7 @@
set_detailed_error("packet numbers cannot be 0.");
return RaiseError(QUIC_INVALID_PACKET_HEADER);
}
+ header->packet_number = QuicPacketNumber(full_packet_number);
}
// A nonce should only present in SHLO from the server to the client when
@@ -1567,8 +1554,12 @@
// Update the largest packet number after we have decrypted the packet
// so we are confident is not attacker controlled.
- largest_packet_number_ =
- std::max(header->packet_number, largest_packet_number_);
+ if (largest_packet_number_.IsInitialized()) {
+ largest_packet_number_ =
+ std::max(header->packet_number, largest_packet_number_);
+ } else {
+ largest_packet_number_ = header->packet_number;
+ }
if (!visitor_->OnPacketHeader(*header)) {
// The visitor suppresses further processing of the packet.
@@ -1629,8 +1620,12 @@
// Update the largest packet number after we have decrypted the packet
// so we are confident is not attacker controlled.
- largest_packet_number_ =
- std::max(header->packet_number, largest_packet_number_);
+ if (largest_packet_number_.IsInitialized()) {
+ largest_packet_number_ =
+ std::max(header->packet_number, largest_packet_number_);
+ } else {
+ largest_packet_number_ = header->packet_number;
+ }
if (!visitor_->OnPacketHeader(*header)) {
// The visitor suppresses further processing of the packet.
@@ -1699,10 +1694,11 @@
bool QuicFramer::IsIetfStatelessResetPacket(
const QuicPacketHeader& header) const {
- return perspective_ == Perspective::IS_CLIENT &&
- header.form == IETF_QUIC_SHORT_HEADER_PACKET &&
- (!process_stateless_reset_at_client_only_ ||
- header.has_possible_stateless_reset_token) &&
+ QUIC_BUG_IF(header.has_possible_stateless_reset_token &&
+ perspective_ != Perspective::IS_CLIENT)
+ << "has_possible_stateless_reset_token can only be true at client side.";
+ return header.form == IETF_QUIC_SHORT_HEADER_PACKET &&
+ header.has_possible_stateless_reset_token &&
visitor_->IsValidStatelessResetToken(
header.possible_stateless_reset_token);
}
@@ -1737,12 +1733,13 @@
}
break;
case PACKET_8BYTE_CONNECTION_ID:
- QUIC_BUG_IF(header.destination_connection_id.length() !=
- kQuicDefaultConnectionIdLength &&
- transport_version() < QUIC_VERSION_99)
- << "Cannot use connection ID of length "
- << header.destination_connection_id.length() << " with version "
+ QUIC_BUG_IF(!QuicUtils::IsConnectionIdValidForVersion(
+ header.destination_connection_id, transport_version()))
+ << "AppendPacketHeader: attempted to use connection ID "
+ << header.destination_connection_id
+ << " which is invalid with version "
<< QuicVersionToString(transport_version());
+
public_flags |= PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID;
if (perspective_ == Perspective::IS_CLIENT) {
public_flags |= PACKET_PUBLIC_FLAGS_8BYTE_CONNECTION_ID_OLD;
@@ -1784,7 +1781,7 @@
bool QuicFramer::AppendIetfHeaderTypeByte(const QuicPacketHeader& header,
QuicDataWriter* writer) {
uint8_t type = 0;
- if (transport_version() == QUIC_VERSION_99) {
+ if (transport_version() > QUIC_VERSION_46) {
if (header.version_flag) {
type = static_cast<uint8_t>(
FLAGS_LONG_HEADER | FLAGS_FIXED_BIT |
@@ -1819,11 +1816,10 @@
bool QuicFramer::AppendIetfPacketHeader(const QuicPacketHeader& header,
QuicDataWriter* writer) {
QUIC_DVLOG(1) << ENDPOINT << "Appending IETF header: " << header;
- QUIC_BUG_IF(header.destination_connection_id.length() !=
- kQuicDefaultConnectionIdLength &&
- transport_version() < QUIC_VERSION_99)
- << "Cannot use connection ID of length "
- << header.destination_connection_id.length() << " with version "
+ QUIC_BUG_IF(!QuicUtils::IsConnectionIdValidForVersion(
+ header.destination_connection_id, transport_version()))
+ << "AppendIetfPacketHeader: attempted to use connection ID "
+ << header.destination_connection_id << " which is invalid with version "
<< QuicVersionToString(transport_version());
if (!AppendIetfHeaderTypeByte(header, writer)) {
return false;
@@ -1892,10 +1888,10 @@
return QuicTime::Delta::FromMicroseconds(time);
}
-QuicPacketNumber QuicFramer::CalculatePacketNumberFromWire(
+uint64_t QuicFramer::CalculatePacketNumberFromWire(
QuicPacketNumberLength packet_number_length,
QuicPacketNumber base_packet_number,
- QuicPacketNumber packet_number) const {
+ uint64_t packet_number) const {
// The new packet number might have wrapped to the next epoch, or
// it might have reverse wrapped to the previous epoch, or it might
// remain in the same epoch. Select the packet number closest to the
@@ -1904,12 +1900,14 @@
// epoch_delta is the delta between epochs the packet number was serialized
// with, so the correct value is likely the same epoch as the last sequence
// number or an adjacent epoch.
- const QuicPacketNumber epoch_delta = UINT64_C(1)
- << (8 * packet_number_length);
- QuicPacketNumber next_packet_number = base_packet_number + 1;
- QuicPacketNumber epoch = base_packet_number & ~(epoch_delta - 1);
- QuicPacketNumber prev_epoch = epoch - epoch_delta;
- QuicPacketNumber next_epoch = epoch + epoch_delta;
+ if (!base_packet_number.IsInitialized()) {
+ return packet_number;
+ }
+ const uint64_t epoch_delta = UINT64_C(1) << (8 * packet_number_length);
+ uint64_t next_packet_number = base_packet_number.ToUint64() + 1;
+ uint64_t epoch = base_packet_number.ToUint64() & ~(epoch_delta - 1);
+ uint64_t prev_epoch = epoch - epoch_delta;
+ uint64_t next_epoch = epoch + epoch_delta;
return ClosestTo(next_packet_number, epoch + packet_number,
ClosestTo(next_packet_number, prev_epoch + packet_number,
@@ -2009,11 +2007,15 @@
QuicPacketNumberLength QuicFramer::GetMinPacketNumberLength(
QuicTransportVersion version,
QuicPacketNumber packet_number) {
- if (packet_number < 1 << (PACKET_1BYTE_PACKET_NUMBER * 8)) {
+ DCHECK(packet_number.IsInitialized());
+ if (packet_number < QuicPacketNumber(1 << (PACKET_1BYTE_PACKET_NUMBER * 8))) {
return PACKET_1BYTE_PACKET_NUMBER;
- } else if (packet_number < 1 << (PACKET_2BYTE_PACKET_NUMBER * 8)) {
+ } else if (packet_number <
+ QuicPacketNumber(1 << (PACKET_2BYTE_PACKET_NUMBER * 8))) {
return PACKET_2BYTE_PACKET_NUMBER;
- } else if (packet_number < UINT64_C(1) << (PACKET_4BYTE_PACKET_NUMBER * 8)) {
+ } else if (packet_number <
+ QuicPacketNumber(UINT64_C(1)
+ << (PACKET_4BYTE_PACKET_NUMBER * 8))) {
return PACKET_4BYTE_PACKET_NUMBER;
} else {
return PACKET_6BYTE_PACKET_NUMBER;
@@ -2051,7 +2053,7 @@
new_ack_info.first_block_length = frame.packets.LastIntervalLength();
auto itr = frame.packets.rbegin();
QuicPacketNumber previous_start = itr->min();
- new_ack_info.max_block_length = itr->Length();
+ new_ack_info.max_block_length = PacketNumberIntervalLength(*itr);
++itr;
// Don't do any more work after getting information for 256 ACK blocks; any
@@ -2060,12 +2062,12 @@
new_ack_info.num_ack_blocks < std::numeric_limits<uint8_t>::max();
previous_start = itr->min(), ++itr) {
const auto& interval = *itr;
- const QuicPacketNumber total_gap = previous_start - interval.max();
+ const QuicPacketCount total_gap = previous_start - interval.max();
new_ack_info.num_ack_blocks +=
(total_gap + std::numeric_limits<uint8_t>::max() - 1) /
std::numeric_limits<uint8_t>::max();
- new_ack_info.max_block_length =
- std::max(new_ack_info.max_block_length, interval.Length());
+ new_ack_info.max_block_length = std::max(
+ new_ack_info.max_block_length, PacketNumberIntervalLength(interval));
}
return new_ack_info;
}
@@ -2073,18 +2075,19 @@
bool QuicFramer::ProcessUnauthenticatedHeader(QuicDataReader* encrypted_reader,
QuicPacketHeader* header) {
QuicPacketNumber base_packet_number = largest_packet_number_;
-
+ uint64_t full_packet_number;
if (!ProcessAndCalculatePacketNumber(
encrypted_reader, header->packet_number_length, base_packet_number,
- &header->packet_number)) {
+ &full_packet_number)) {
set_detailed_error("Unable to read packet number.");
return RaiseError(QUIC_INVALID_PACKET_HEADER);
}
- if (header->packet_number == kInvalidPacketNumber) {
+ if (!IsValidFullPacketNumber(full_packet_number, transport_version())) {
set_detailed_error("packet numbers cannot be 0.");
return RaiseError(QUIC_INVALID_PACKET_HEADER);
}
+ header->packet_number = QuicPacketNumber(full_packet_number);
if (!visitor_->OnUnauthenticatedHeader(*header)) {
set_detailed_error(
@@ -2130,7 +2133,7 @@
} else {
header->version = ParseQuicVersionLabel(version_label);
if (header->version.transport_version != QUIC_VERSION_UNSUPPORTED) {
- if (header->version.transport_version == QUIC_VERSION_99 &&
+ if (header->version.transport_version > QUIC_VERSION_46 &&
!(type & FLAGS_FIXED_BIT)) {
set_detailed_error("Fixed bit is 0 in long header.");
return false;
@@ -2167,7 +2170,7 @@
header->destination_connection_id = last_serialized_connection_id_;
}
if (infer_packet_header_type_from_version_ &&
- transport_version() == QUIC_VERSION_99 && !(type & FLAGS_FIXED_BIT)) {
+ transport_version() > QUIC_VERSION_46 && !(type & FLAGS_FIXED_BIT)) {
set_detailed_error("Fixed bit is 0 in short header.");
return false;
}
@@ -2240,8 +2243,8 @@
QuicDataReader* reader,
QuicPacketNumberLength packet_number_length,
QuicPacketNumber base_packet_number,
- QuicPacketNumber* packet_number) {
- QuicPacketNumber wire_packet_number;
+ uint64_t* packet_number) {
+ uint64_t wire_packet_number;
if (!reader->ReadBytesToUInt64(packet_number_length, &wire_packet_number)) {
return false;
}
@@ -2459,7 +2462,8 @@
encoded_bytes -= reader->BytesRemaining();
// Check that the frame type is minimally encoded.
- if (encoded_bytes != QuicDataWriter::GetVarInt62Len(frame_type)) {
+ if (encoded_bytes !=
+ static_cast<size_t>(QuicDataWriter::GetVarInt62Len(frame_type))) {
// The frame type was not minimally encoded.
set_detailed_error("Frame type not minimally encoded.");
return RaiseError(IETF_QUIC_PROTOCOL_VIOLATION);
@@ -2917,12 +2921,21 @@
ExtractBits(frame_type, kQuicSequenceNumberLengthNumBits,
kLargestAckedOffset));
- QuicPacketNumber largest_acked;
+ uint64_t largest_acked;
if (!reader->ReadBytesToUInt64(largest_acked_length, &largest_acked)) {
set_detailed_error("Unable to read largest acked.");
return false;
}
+ if (GetQuicReloadableFlag(quic_disallow_peer_ack_0) &&
+ largest_acked < first_sending_packet_number_.ToUint64()) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_disallow_peer_ack_0, 1, 3);
+ // Connection always sends packet starting from kFirstSendingPacketNumber >
+ // 0, peer has observed an unsent packet.
+ set_detailed_error("Largest acked is 0.");
+ return false;
+ }
+
uint64_t ack_delay_time_us;
if (!reader->ReadUFloat16(&ack_delay_time_us)) {
set_detailed_error("Unable to read ack delay time.");
@@ -2930,7 +2943,7 @@
}
if (!visitor_->OnAckFrameStart(
- largest_acked,
+ QuicPacketNumber(largest_acked),
ack_delay_time_us == kUFloat16MaxValue
? QuicTime::Delta::Infinite()
: QuicTime::Delta::FromMicroseconds(ack_delay_time_us))) {
@@ -2954,6 +2967,8 @@
if (first_block_length == 0) {
// For non-empty ACKs, the first block length must be non-zero.
+ // TODO(fayang): remove this if and return false directly when deprecating
+ // gfe2_reloadable_flag_quic_disallow_peer_ack_0.
if (largest_acked != 0 || num_ack_blocks != 0) {
set_detailed_error(
QuicStrCat("First block length is zero but ACK is "
@@ -2963,9 +2978,16 @@
.c_str());
return false;
}
+ DCHECK(!GetQuicReloadableFlag(quic_disallow_peer_ack_0));
}
-
- if (first_block_length > largest_acked + 1) {
+ bool first_ack_block_underflow = first_block_length > largest_acked + 1;
+ if (GetQuicReloadableFlag(quic_disallow_peer_ack_0) &&
+ first_block_length + first_sending_packet_number_.ToUint64() >
+ largest_acked + 1) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_disallow_peer_ack_0, 2, 3);
+ first_ack_block_underflow = true;
+ }
+ if (first_ack_block_underflow) {
set_detailed_error(QuicStrCat("Underflow with first ack block length ",
first_block_length, " largest acked is ",
largest_acked, ".")
@@ -2973,8 +2995,9 @@
return false;
}
- QuicPacketNumber first_received = largest_acked + 1 - first_block_length;
- if (!visitor_->OnAckRange(first_received, largest_acked + 1)) {
+ uint64_t first_received = largest_acked + 1 - first_block_length;
+ if (!visitor_->OnAckRange(QuicPacketNumber(first_received),
+ QuicPacketNumber(largest_acked + 1))) {
// The visitor suppresses further processing of the packet. Although
// this is not a parsing error, returns false as this is in middle
// of processing an ack frame,
@@ -2994,7 +3017,14 @@
set_detailed_error("Unable to ack block length.");
return false;
}
- if (first_received < gap + current_block_length) {
+ bool ack_block_underflow = first_received < gap + current_block_length;
+ if (GetQuicReloadableFlag(quic_disallow_peer_ack_0) &&
+ first_received < gap + current_block_length +
+ first_sending_packet_number_.ToUint64()) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_disallow_peer_ack_0, 3, 3);
+ ack_block_underflow = true;
+ }
+ if (ack_block_underflow) {
set_detailed_error(
QuicStrCat("Underflow with ack block length ", current_block_length,
", end of block is ", first_received - gap, ".")
@@ -3004,8 +3034,9 @@
first_received -= (gap + current_block_length);
if (current_block_length > 0) {
- if (!visitor_->OnAckRange(first_received,
- first_received + current_block_length)) {
+ if (!visitor_->OnAckRange(
+ QuicPacketNumber(first_received),
+ QuicPacketNumber(first_received) + current_block_length)) {
// The visitor suppresses further processing of the packet. Although
// this is not a parsing error, returns false as this is in middle
// of processing an ack frame,
@@ -3022,13 +3053,13 @@
return false;
}
- if (!ProcessTimestampsInAckFrame(num_received_packets, largest_acked,
- reader)) {
+ if (!ProcessTimestampsInAckFrame(num_received_packets,
+ QuicPacketNumber(largest_acked), reader)) {
return false;
}
// Done processing the ACK frame.
- return visitor_->OnAckFrameEnd(first_received);
+ return visitor_->OnAckFrameEnd(QuicPacketNumber(first_received));
}
bool QuicFramer::ProcessTimestampsInAckFrame(uint8_t num_received_packets,
@@ -3084,11 +3115,17 @@
bool QuicFramer::ProcessIetfAckFrame(QuicDataReader* reader,
uint64_t frame_type,
QuicAckFrame* ack_frame) {
- QuicPacketNumber largest_acked;
+ uint64_t largest_acked;
if (!reader->ReadVarInt62(&largest_acked)) {
set_detailed_error("Unable to read largest acked.");
return false;
}
+ if (largest_acked < first_sending_packet_number_.ToUint64()) {
+ // Connection always sends packet starting from kFirstSendingPacketNumber >
+ // 0, peer has observed an unsent packet.
+ set_detailed_error("Largest acked is 0.");
+ return false;
+ }
ack_frame->largest_acked = static_cast<QuicPacketNumber>(largest_acked);
uint64_t ack_delay_time_in_us;
if (!reader->ReadVarInt62(&ack_delay_time_in_us)) {
@@ -3125,7 +3162,8 @@
ack_frame->ect_1_count = 0;
ack_frame->ecn_ce_count = 0;
}
- if (!visitor_->OnAckFrameStart(largest_acked, ack_frame->ack_delay_time)) {
+ if (!visitor_->OnAckFrameStart(QuicPacketNumber(largest_acked),
+ ack_frame->ack_delay_time)) {
// The visitor suppresses further processing of the packet. Although this is
// not a parsing error, returns false as this is in middle of processing an
// ACK frame.
@@ -3150,14 +3188,15 @@
}
// Calculate the packets being acked in the first block.
// +1 because AddRange implementation requires [low,high)
- QuicPacketNumber block_high = largest_acked + 1;
- QuicPacketNumber block_low = largest_acked - ack_block_value;
+ uint64_t block_high = largest_acked + 1;
+ uint64_t block_low = largest_acked - ack_block_value;
// ack_block_value is the number of packets preceding the
// largest_acked packet which are in the block being acked. Thus,
// its maximum value is largest_acked-1. Test this, reporting an
// error if the value is wrong.
- if (ack_block_value > largest_acked) {
+ if (ack_block_value + first_sending_packet_number_.ToUint64() >
+ largest_acked) {
set_detailed_error(QuicStrCat("Underflow with first ack block length ",
ack_block_value + 1, " largest acked is ",
largest_acked, ".")
@@ -3165,7 +3204,8 @@
return false;
}
- if (!visitor_->OnAckRange(block_low, block_high)) {
+ if (!visitor_->OnAckRange(QuicPacketNumber(block_low),
+ QuicPacketNumber(block_high))) {
// The visitor suppresses further processing of the packet. Although
// this is not a parsing error, returns false as this is in middle
// of processing an ACK frame.
@@ -3208,7 +3248,8 @@
set_detailed_error("Unable to read ack block value.");
return false;
}
- if (ack_block_value > (block_high - 1)) {
+ if (ack_block_value + first_sending_packet_number_.ToUint64() >
+ (block_high - 1)) {
set_detailed_error(
QuicStrCat("Underflow with ack block length ", ack_block_value + 1,
" latest ack block end is ", block_high - 1, ".")
@@ -3218,7 +3259,8 @@
// Calculate the low end of the new nth ack block. The +1 is
// because the encoded value is the blocksize-1.
block_low = block_high - 1 - ack_block_value;
- if (!visitor_->OnAckRange(block_low, block_high)) {
+ if (!visitor_->OnAckRange(QuicPacketNumber(block_low),
+ QuicPacketNumber(block_high))) {
// The visitor suppresses further processing of the packet. Although
// this is not a parsing error, returns false as this is in middle
// of processing an ACK frame.
@@ -3230,19 +3272,22 @@
ack_block_count--;
}
- return visitor_->OnAckFrameEnd(block_low);
+ return visitor_->OnAckFrameEnd(QuicPacketNumber(block_low));
}
bool QuicFramer::ProcessStopWaitingFrame(QuicDataReader* reader,
const QuicPacketHeader& header,
QuicStopWaitingFrame* stop_waiting) {
- QuicPacketNumber least_unacked_delta;
+ uint64_t least_unacked_delta;
if (!reader->ReadBytesToUInt64(header.packet_number_length,
&least_unacked_delta)) {
set_detailed_error("Unable to read least unacked delta.");
return false;
}
- if (header.packet_number < least_unacked_delta) {
+ if (header.packet_number.ToUint64() < least_unacked_delta ||
+ (GetQuicReloadableFlag(
+ quic_close_connection_with_zero_least_unacked_stop_waiting) &&
+ header.packet_number.ToUint64() == least_unacked_delta)) {
set_detailed_error("Invalid unacked delta.");
return false;
}
@@ -3461,9 +3506,10 @@
size_t total_len,
size_t buffer_len,
char* buffer) {
+ DCHECK(packet_number.IsInitialized());
size_t output_length = 0;
if (!encrypter_[level]->EncryptPacket(
- version_.transport_version, packet_number,
+ version_.transport_version, packet_number.ToUint64(),
QuicStringPiece(buffer, ad_len), // Associated data
QuicStringPiece(buffer + ad_len, total_len - ad_len), // Plaintext
buffer + ad_len, // Destination buffer
@@ -3480,6 +3526,7 @@
const QuicPacket& packet,
char* buffer,
size_t buffer_len) {
+ DCHECK(packet_number.IsInitialized());
DCHECK(encrypter_[level] != nullptr);
QuicStringPiece associated_data =
@@ -3491,7 +3538,7 @@
// Encrypt the plaintext into the buffer.
size_t output_length = 0;
if (!encrypter_[level]->EncryptPacket(
- version_.transport_version, packet_number, associated_data,
+ version_.transport_version, packet_number.ToUint64(), associated_data,
packet.Plaintext(version_.transport_version), buffer + ad_len,
&output_length, buffer_len - ad_len)) {
RaiseError(QUIC_ENCRYPTION_FAILURE);
@@ -3533,8 +3580,9 @@
header.nonce != nullptr, header.packet_number_length);
bool success = decrypter_->DecryptPacket(
- version_.transport_version, header.packet_number, associated_data,
- encrypted, decrypted_buffer, decrypted_length, buffer_length);
+ version_.transport_version, header.packet_number.ToUint64(),
+ associated_data, encrypted, decrypted_buffer, decrypted_length,
+ buffer_length);
if (success) {
visitor_->OnDecryptedPacket(decrypter_level_);
} else if (alternative_decrypter_ != nullptr) {
@@ -3556,8 +3604,9 @@
if (try_alternative_decryption) {
success = alternative_decrypter_->DecryptPacket(
- version_.transport_version, header.packet_number, associated_data,
- encrypted, decrypted_buffer, decrypted_length, buffer_length);
+ version_.transport_version, header.packet_number.ToUint64(),
+ associated_data, encrypted, decrypted_buffer, decrypted_length,
+ buffer_length);
}
if (success) {
visitor_->OnDecryptedPacket(alternative_decrypter_level_);
@@ -3590,7 +3639,7 @@
// Type byte, largest_acked, and delay_time are straight-forward.
size_t ack_frame_size = kQuicFrameTypeSize;
QuicPacketNumber largest_acked = LargestAcked(frame);
- ack_frame_size += QuicDataWriter::GetVarInt62Len(largest_acked);
+ ack_frame_size += QuicDataWriter::GetVarInt62Len(largest_acked.ToUint64());
uint64_t ack_delay_time_us;
ack_delay_time_us = frame.ack_delay_time.ToMicroseconds();
ack_delay_time_us = ack_delay_time_us >> kIetfAckTimestampShift;
@@ -3650,18 +3699,18 @@
size_t ack_block_count_size = QuicDataWriter::GetVarInt62Len(ack_block_count);
ack_frame_size += ack_block_count_size;
- QuicPacketNumber first_ack_block = ack_block_largest - ack_block_smallest;
+ uint64_t first_ack_block = ack_block_largest - ack_block_smallest;
size_t first_ack_block_size = QuicDataWriter::GetVarInt62Len(first_ack_block);
ack_frame_size += first_ack_block_size;
// Account for the remaining Intervals, if any.
while (ack_block_count != 0) {
- QuicPacketNumber gap_size = ack_block_smallest - itr->max();
+ uint64_t gap_size = ack_block_smallest - itr->max();
// Decrement per the protocol specification
size_t size_of_gap_size = QuicDataWriter::GetVarInt62Len(gap_size - 1);
ack_frame_size += size_of_gap_size;
- QuicPacketNumber block_size = itr->max() - itr->min();
+ uint64_t block_size = itr->max() - itr->min();
// Decrement per the protocol specification
size_t size_of_block_size = QuicDataWriter::GetVarInt62Len(block_size - 1);
ack_frame_size += size_of_block_size;
@@ -3677,6 +3726,7 @@
size_t QuicFramer::GetAckFrameSize(
const QuicAckFrame& ack,
QuicPacketNumberLength packet_number_length) {
+ DCHECK(!ack.packets.Empty());
size_t ack_size = 0;
if (version_.transport_version == QUIC_VERSION_99) {
@@ -3686,7 +3736,7 @@
QuicPacketNumberLength largest_acked_length =
GetMinPacketNumberLength(version_.transport_version, LargestAcked(ack));
QuicPacketNumberLength ack_block_length = GetMinPacketNumberLength(
- version_.transport_version, ack_info.max_block_length);
+ version_.transport_version, QuicPacketNumber(ack_info.max_block_length));
ack_size =
GetMinAckFrameSize(version_.transport_version, largest_acked_length);
@@ -3727,7 +3777,10 @@
frame.stream_frame.offset, last_frame_in_packet,
frame.stream_frame.data_length) +
frame.stream_frame.data_length;
- // TODO(nharper): Add a case for CRYPTO_FRAME here?
+ case CRYPTO_FRAME:
+ return GetMinCryptoFrameSize(frame.crypto_frame->offset,
+ frame.crypto_frame->data_length) +
+ frame.crypto_frame->data_length;
case ACK_FRAME: {
return GetAckFrameSize(*frame.ack_frame, packet_number_length);
}
@@ -3913,12 +3966,13 @@
bool QuicFramer::AppendPacketNumber(QuicPacketNumberLength packet_number_length,
QuicPacketNumber packet_number,
QuicDataWriter* writer) {
- size_t length = packet_number_length;
- if (length != 1 && length != 2 && length != 4 && length != 6 && length != 8) {
- QUIC_BUG << "Invalid packet_number_length: " << length;
+ DCHECK(packet_number.IsInitialized());
+ if (!IsValidPacketNumberLength(packet_number_length)) {
+ QUIC_BUG << "Invalid packet_number_length: " << packet_number_length;
return false;
}
- return writer->WriteBytesToUInt64(packet_number_length, packet_number);
+ return writer->WriteBytesToUInt64(packet_number_length,
+ packet_number.ToUint64());
}
// static
@@ -3947,10 +4001,18 @@
// static
bool QuicFramer::AppendAckBlock(uint8_t gap,
QuicPacketNumberLength length_length,
- QuicPacketNumber length,
+ uint64_t length,
QuicDataWriter* writer) {
+ if (length == 0) {
+ if (!IsValidPacketNumberLength(length_length)) {
+ QUIC_BUG << "Invalid packet_number_length: " << length_length;
+ return false;
+ }
+ return writer->WriteUInt8(gap) &&
+ writer->WriteBytesToUInt64(length_length, length);
+ }
return writer->WriteUInt8(gap) &&
- AppendPacketNumber(length_length, length, writer);
+ AppendPacketNumber(length_length, QuicPacketNumber(length), writer);
}
bool QuicFramer::AppendStreamFrame(const QuicStreamFrame& frame,
@@ -4120,8 +4182,20 @@
set_detailed_error("Writing data length failed.");
return false;
}
- // TODO(nharper): Append stream frame contents.
- return false;
+ if (data_producer_ == nullptr) {
+ if (frame.data_buffer == nullptr ||
+ !writer->WriteBytes(frame.data_buffer, frame.data_length)) {
+ set_detailed_error("Writing frame data failed.");
+ return false;
+ }
+ } else {
+ DCHECK_EQ(nullptr, frame.data_buffer);
+ if (!data_producer_->WriteCryptoData(frame.level, frame.offset,
+ frame.data_length, writer)) {
+ return false;
+ }
+ }
+ return true;
}
void QuicFramer::set_version(const ParsedQuicVersion version) {
@@ -4139,8 +4213,9 @@
QuicPacketNumber largest_acked = LargestAcked(frame);
QuicPacketNumberLength largest_acked_length =
GetMinPacketNumberLength(version_.transport_version, largest_acked);
- QuicPacketNumberLength ack_block_length = GetMinPacketNumberLength(
- version_.transport_version, new_ack_info.max_block_length);
+ QuicPacketNumberLength ack_block_length =
+ GetMinPacketNumberLength(version_.transport_version,
+ QuicPacketNumber(new_ack_info.max_block_length));
// Calculate available bytes for timestamps and ack blocks.
int32_t available_timestamp_and_ack_block_bytes =
writer->capacity() - writer->length() - ack_block_length -
@@ -4199,7 +4274,8 @@
}
// First ack block length.
- if (!AppendPacketNumber(ack_block_length, new_ack_info.first_block_length,
+ if (!AppendPacketNumber(ack_block_length,
+ QuicPacketNumber(new_ack_info.first_block_length),
writer)) {
return false;
}
@@ -4223,7 +4299,7 @@
itr != frame.packets.rend() && num_ack_blocks_written < num_ack_blocks;
previous_start = itr->min(), ++itr) {
const auto& interval = *itr;
- const QuicPacketNumber total_gap = previous_start - interval.max();
+ const uint64_t total_gap = previous_start - interval.max();
const size_t num_encoded_gaps =
(total_gap + std::numeric_limits<uint8_t>::max() - 1) /
std::numeric_limits<uint8_t>::max();
@@ -4251,8 +4327,8 @@
total_gap -
(num_encoded_gaps - 1) * std::numeric_limits<uint8_t>::max();
// Append the final ACK block with a non-empty size.
- if (!AppendAckBlock(last_gap, ack_block_length, interval.Length(),
- writer)) {
+ if (!AppendAckBlock(last_gap, ack_block_length,
+ PacketNumberIntervalLength(interval), writer)) {
return false;
}
++num_ack_blocks_written;
@@ -4297,8 +4373,7 @@
auto it = frame.received_packet_times.begin();
QuicPacketNumber packet_number = it->first;
- QuicPacketNumber delta_from_largest_observed =
- LargestAcked(frame) - packet_number;
+ uint64_t delta_from_largest_observed = LargestAcked(frame) - packet_number;
DCHECK_GE(std::numeric_limits<uint8_t>::max(), delta_from_largest_observed);
if (delta_from_largest_observed > std::numeric_limits<uint8_t>::max()) {
@@ -4345,10 +4420,11 @@
const QuicStopWaitingFrame& frame,
QuicDataWriter* writer) {
DCHECK_GE(QUIC_VERSION_43, version_.transport_version);
- DCHECK_GE(header.packet_number, frame.least_unacked);
- const QuicPacketNumber least_unacked_delta =
+ DCHECK(frame.least_unacked.IsInitialized() &&
+ header.packet_number >= frame.least_unacked);
+ const uint64_t least_unacked_delta =
header.packet_number - frame.least_unacked;
- const QuicPacketNumber length_shift = header.packet_number_length * 8;
+ const uint64_t length_shift = header.packet_number_length * 8;
if (least_unacked_delta >> length_shift > 0) {
QUIC_BUG << "packet_number_length " << header.packet_number_length
@@ -4358,8 +4434,12 @@
<< " version:" << version_.transport_version;
return false;
}
- if (!AppendPacketNumber(header.packet_number_length, least_unacked_delta,
- writer)) {
+ if (least_unacked_delta == 0) {
+ return writer->WriteBytesToUInt64(header.packet_number_length,
+ least_unacked_delta);
+ }
+ if (!AppendPacketNumber(header.packet_number_length,
+ QuicPacketNumber(least_unacked_delta), writer)) {
QUIC_BUG << " seq failed: " << header.packet_number_length;
return false;
}
@@ -4382,7 +4462,7 @@
return 0;
}
available_space -= encoded_size;
- uint64_t previous_ack_end = itr->min();
+ QuicPacketNumber previous_ack_end = itr->min();
ack_block_count--;
while (ack_block_count) {
@@ -4426,7 +4506,7 @@
}
QuicPacketNumber largest_acked = LargestAcked(frame);
- if (!writer->WriteVarInt62(largest_acked)) {
+ if (!writer->WriteVarInt62(largest_acked.ToUint64())) {
set_detailed_error("No room for largest-acked in ack frame");
return false;
}
@@ -4480,9 +4560,9 @@
// Case 2 or 3
auto itr = frame.packets.rbegin();
- QuicPacketNumber ack_block_largest = largest_acked;
+ QuicPacketNumber ack_block_largest(largest_acked);
QuicPacketNumber ack_block_smallest;
- if ((itr->max() - 1) == largest_acked) {
+ if ((itr->max() - 1) == QuicPacketNumber(largest_acked)) {
// If largest_acked + 1 is equal to the Max() of the first Interval
// in the QuicAckFrame then the first Interval is the first ack block of the
// frame; remaining Intervals are additional ack blocks. The QuicAckFrame's
@@ -4513,7 +4593,7 @@
return false;
}
- QuicPacketNumber first_ack_block = ack_block_largest - ack_block_smallest;
+ uint64_t first_ack_block = ack_block_largest - ack_block_smallest;
if (!writer->WriteVarInt62(first_ack_block)) {
set_detailed_error("No room for first ack block in ack frame");
return false;
@@ -4521,13 +4601,13 @@
// For the remaining QuicAckFrame Intervals, if any
while (ack_block_count != 0) {
- QuicPacketNumber gap_size = ack_block_smallest - itr->max();
+ uint64_t gap_size = ack_block_smallest - itr->max();
if (!writer->WriteVarInt62(gap_size - 1)) {
set_detailed_error("No room for gap block in ack frame");
return false;
}
- QuicPacketNumber block_size = itr->max() - itr->min();
+ uint64_t block_size = itr->max() - itr->min();
if (!writer->WriteVarInt62(block_size - 1)) {
set_detailed_error("No room for nth ack block in ack frame");
return false;
@@ -4608,6 +4688,9 @@
bool QuicFramer::AppendBlockedFrame(const QuicBlockedFrame& frame,
QuicDataWriter* writer) {
if (version_.transport_version == QUIC_VERSION_99) {
+ // TODO(fkastenholz): This should be converted to use
+ // QuicUtils::GetInvalidStreamId to get the correct invalid stream id value
+ // and not rely on 0.
if (frame.stream_id == 0) {
return AppendIetfBlockedFrame(frame, writer);
}
@@ -4985,6 +5068,9 @@
bool QuicFramer::ProcessIetfBlockedFrame(QuicDataReader* reader,
QuicBlockedFrame* frame) {
// Indicates that it is a BLOCKED frame (as opposed to STREAM_BLOCKED).
+ // TODO(fkastenholz): This should be converted to use
+ // QuicUtils::GetInvalidStreamId to get the correct invalid stream id value
+ // and not rely on 0.
frame->stream_id = 0;
if (!reader->ReadVarInt62(&frame->offset)) {
set_detailed_error("Can not read blocked offset.");
diff --git a/quic/core/quic_framer.h b/quic/core/quic_framer.h
index 828daa0..46280c5 100644
--- a/quic/core/quic_framer.h
+++ b/quic/core/quic_framer.h
@@ -270,6 +270,10 @@
QuicStreamOffset offset,
bool last_frame_in_packet,
QuicPacketLength data_length);
+ // Returns the overhead of framing a CRYPTO frame with the specific offset and
+ // data length provided, but not counting the size of the data payload.
+ static size_t GetMinCryptoFrameSize(QuicStreamOffset offset,
+ QuicPacketLength data_length);
static size_t GetMessageFrameSize(QuicTransportVersion version,
bool last_frame_in_packet,
QuicByteCount length);
@@ -374,6 +378,12 @@
char* buffer,
size_t packet_length);
+ // Serializes an IETF probing packet, which is a padded PING packet.
+ // Returns the length of the packet. Returns 0 if it fails to serialize.
+ size_t BuildIetfConnectivityProbingPacket(const QuicPacketHeader& header,
+ char* buffer,
+ size_t packet_length);
+
// Serialize a probing packet that uses IETF QUIC's PATH CHALLENGE frame. Also
// fills the packet with padding.
size_t BuildPaddedPathChallengePacket(const QuicPacketHeader& header,
@@ -506,7 +516,7 @@
// Returns header wire format of last received packet.
// Please do not use this method.
// TODO(fayang): Remove last_header_form_ when deprecating
- // quic_proxy_use_real_packet_format_when_reject flag.
+ // quic_fix_last_packet_is_ietf_quic flag.
PacketHeaderFormat GetLastPacketFormat() const;
void set_validate_flags(bool value) { validate_flags_ = value; }
@@ -534,6 +544,10 @@
QuicTime creation_time() const { return creation_time_; }
+ QuicPacketNumber first_sending_packet_number() const {
+ return first_sending_packet_number_;
+ }
+
private:
friend class test::QuicFramerPeer;
@@ -545,9 +559,9 @@
~AckFrameInfo();
// The maximum ack block length.
- QuicPacketNumber max_block_length;
+ QuicPacketCount max_block_length;
// Length of first ack block.
- QuicPacketNumber first_block_length;
+ QuicPacketCount first_block_length;
// Number of ACK blocks needed for the ACK frame.
size_t num_ack_blocks;
};
@@ -597,7 +611,7 @@
QuicDataReader* reader,
QuicPacketNumberLength packet_number_length,
QuicPacketNumber base_packet_number,
- QuicPacketNumber* packet_number);
+ uint64_t* packet_number);
bool ProcessFrameData(QuicDataReader* reader, const QuicPacketHeader& header);
bool ProcessIetfFrameData(QuicDataReader* reader,
const QuicPacketHeader& header);
@@ -635,10 +649,10 @@
// Returns the full packet number from the truncated
// wire format version and the last seen packet number.
- QuicPacketNumber CalculatePacketNumberFromWire(
+ uint64_t CalculatePacketNumberFromWire(
QuicPacketNumberLength packet_number_length,
QuicPacketNumber base_packet_number,
- QuicPacketNumber packet_number) const;
+ uint64_t packet_number) const;
// Returns the QuicTime::Delta corresponding to the time from when the framer
// was created.
@@ -675,7 +689,7 @@
// successfully appended.
static bool AppendAckBlock(uint8_t gap,
QuicPacketNumberLength length_length,
- QuicPacketNumber length,
+ uint64_t length,
QuicDataWriter* writer);
static uint8_t GetPacketNumberFlags(
@@ -869,13 +883,15 @@
// The last timestamp received if process_timestamps_ is true.
QuicTime::Delta last_timestamp_;
+ // If this is a framer of a connection, this is the packet number of first
+ // sending packet. If this is a framer of a framer of dispatcher, this is the
+ // packet number of sent packets (for those which have packet number).
+ const QuicPacketNumber first_sending_packet_number_;
+
// If not null, framer asks data_producer_ to write stream frame data. Not
// owned. TODO(fayang): Consider add data producer to framer's constructor.
QuicStreamFrameDataProducer* data_producer_;
- // Latched value of quic_process_stateless_reset_at_client_only flag.
- const bool process_stateless_reset_at_client_only_;
-
// If true, framer infers packet header type (IETF/GQUIC) from version_.
// Otherwise, framer infers packet header type from first byte of a received
// packet.
diff --git a/quic/core/quic_framer_test.cc b/quic/core/quic_framer_test.cc
index a75bceb..888c87e 100644
--- a/quic/core/quic_framer_test.cc
+++ b/quic/core/quic_framer_test.cc
@@ -36,8 +36,8 @@
namespace test {
namespace {
-const QuicPacketNumber kEpoch = UINT64_C(1) << 32;
-const QuicPacketNumber kMask = kEpoch - 1;
+const uint64_t kEpoch = UINT64_C(1) << 32;
+const uint64_t kMask = kEpoch - 1;
const QuicUint128 kTestStatelessResetToken = 1010101; // 0x0F69B5
@@ -51,10 +51,11 @@
return TestConnectionId(UINT64_C(0xFEDCBA9876543211));
}
-const QuicPacketNumber kPacketNumber = UINT64_C(0x12345678);
-const QuicPacketNumber kSmallLargestObserved = UINT16_C(0x1234);
-const QuicPacketNumber kSmallMissingPacket = UINT16_C(0x1233);
-const QuicPacketNumber kLeastUnacked = UINT64_C(0x012345670);
+const QuicPacketNumber kPacketNumber = QuicPacketNumber(UINT64_C(0x12345678));
+const QuicPacketNumber kSmallLargestObserved =
+ QuicPacketNumber(UINT16_C(0x1234));
+const QuicPacketNumber kSmallMissingPacket = QuicPacketNumber(UINT16_C(0x1233));
+const QuicPacketNumber kLeastUnacked = QuicPacketNumber(UINT64_C(0x012345670));
const QuicStreamId kStreamId = UINT64_C(0x01020304);
// Note that the high 4 bits of the stream offset must be less than 0x40
// in order to ensure that the value can be encoded using VarInt62 encoding.
@@ -65,7 +66,7 @@
// This is the largest packet number that can be represented in IETF QUIC
// varint62 format.
const QuicPacketNumber kLargestIetfLargestObserved =
- UINT64_C(0x3fffffffffffffff);
+ QuicPacketNumber(UINT64_C(0x3fffffffffffffff));
// Encodings for the two bits in a VarInt62 that
// describe the length of the VarInt61. For binary packet
// formats in this file, the convention is to code the
@@ -83,14 +84,14 @@
bool SetNoncePrefix(QuicStringPiece nonce_prefix) override { return true; }
bool SetIV(QuicStringPiece iv) override { return true; }
bool EncryptPacket(QuicTransportVersion version,
- QuicPacketNumber packet_number,
+ uint64_t packet_number,
QuicStringPiece associated_data,
QuicStringPiece plaintext,
char* output,
size_t* output_length,
size_t max_output_length) override {
version_ = version;
- packet_number_ = packet_number;
+ packet_number_ = QuicPacketNumber(packet_number);
associated_data_ = QuicString(associated_data);
plaintext_ = QuicString(plaintext);
memcpy(output, plaintext.data(), plaintext.length());
@@ -129,14 +130,14 @@
return true;
}
bool DecryptPacket(QuicTransportVersion version,
- QuicPacketNumber packet_number,
+ uint64_t packet_number,
QuicStringPiece associated_data,
QuicStringPiece ciphertext,
char* output,
size_t* output_length,
size_t max_output_length) override {
version_ = version;
- packet_number_ = packet_number;
+ packet_number_ = QuicPacketNumber(packet_number);
associated_data_ = QuicString(associated_data);
ciphertext_ = QuicString(ciphertext);
memcpy(output, ciphertext.data(), ciphertext.length());
@@ -223,7 +224,13 @@
}
bool OnCryptoFrame(const QuicCryptoFrame& frame) override {
- // TODO(nharper): Implement.
+ ++frame_count_;
+ // Save a copy of the data so it is valid after the packet is processed.
+ QuicString* string_data =
+ new QuicString(frame.data_buffer, frame.data_length);
+ crypto_data_.push_back(QuicWrapUnique(string_data));
+ crypto_frames_.push_back(QuicMakeUnique<QuicCryptoFrame>(
+ ENCRYPTION_NONE, frame.offset, *string_data));
return true;
}
@@ -373,6 +380,7 @@
std::unique_ptr<QuicIetfStatelessResetPacket> stateless_reset_packet_;
std::unique_ptr<QuicVersionNegotiationPacket> version_negotiation_packet_;
std::vector<std::unique_ptr<QuicStreamFrame>> stream_frames_;
+ std::vector<std::unique_ptr<QuicCryptoFrame>> crypto_frames_;
std::vector<std::unique_ptr<QuicAckFrame>> ack_frames_;
std::vector<std::unique_ptr<QuicStopWaitingFrame>> stop_waiting_frames_;
std::vector<std::unique_ptr<QuicPaddingFrame>> padding_frames_;
@@ -393,6 +401,7 @@
QuicRetireConnectionIdFrame retire_connection_id_;
QuicNewTokenFrame new_token_;
std::vector<std::unique_ptr<QuicString>> stream_data_;
+ std::vector<std::unique_ptr<QuicString>> crypto_data_;
};
// Simple struct for defining a packet's content, and associated
@@ -428,6 +437,7 @@
std::unique_ptr<QuicEncrypter>(encrypter_));
framer_.set_visitor(&visitor_);
+ framer_.InferPacketHeaderTypeFromVersion();
}
// Helper function to get unsigned char representation of the handshake
@@ -577,9 +587,9 @@
EXPECT_EQ(str, QuicString(frame->data_buffer, frame->data_length));
}
- void CheckCalculatePacketNumber(QuicPacketNumber expected_packet_number,
+ void CheckCalculatePacketNumber(uint64_t expected_packet_number,
QuicPacketNumber last_packet_number) {
- QuicPacketNumber wire_packet_number = expected_packet_number & kMask;
+ uint64_t wire_packet_number = expected_packet_number & kMask;
EXPECT_EQ(expected_packet_number,
QuicFramerPeer::CalculatePacketNumberFromWire(
&framer_, PACKET_4BYTE_PACKET_NUMBER, last_packet_number,
@@ -623,12 +633,17 @@
TEST_P(QuicFramerTest, CalculatePacketNumberFromWireNearEpochStart) {
// A few quick manual sanity checks.
- CheckCalculatePacketNumber(UINT64_C(1), UINT64_C(0));
- CheckCalculatePacketNumber(kEpoch + 1, kMask);
- CheckCalculatePacketNumber(kEpoch, kMask);
+ CheckCalculatePacketNumber(UINT64_C(1), QuicPacketNumber());
+ CheckCalculatePacketNumber(kEpoch + 1, QuicPacketNumber(kMask));
+ CheckCalculatePacketNumber(kEpoch, QuicPacketNumber(kMask));
+ for (uint64_t j = 0; j < 10; j++) {
+ CheckCalculatePacketNumber(j, QuicPacketNumber());
+ CheckCalculatePacketNumber(kEpoch - 1 - j, QuicPacketNumber());
+ }
// Cases where the last number was close to the start of the range.
- for (uint64_t last = 0; last < 10; last++) {
+ for (QuicPacketNumber last = QuicPacketNumber(1); last < QuicPacketNumber(10);
+ last++) {
// Small numbers should not wrap (even if they're out of order).
for (uint64_t j = 0; j < 10; j++) {
CheckCalculatePacketNumber(j, last);
@@ -644,7 +659,7 @@
TEST_P(QuicFramerTest, CalculatePacketNumberFromWireNearEpochEnd) {
// Cases where the last number was close to the end of the range
for (uint64_t i = 0; i < 10; i++) {
- QuicPacketNumber last = kEpoch - i;
+ QuicPacketNumber last = QuicPacketNumber(kEpoch - i);
// Small numbers should wrap.
for (uint64_t j = 0; j < 10; j++) {
@@ -665,7 +680,7 @@
const uint64_t cur_epoch = 2 * kEpoch;
// Cases where the last number was close to the start of the range
for (uint64_t i = 0; i < 10; i++) {
- uint64_t last = cur_epoch + i;
+ QuicPacketNumber last = QuicPacketNumber(cur_epoch + i);
// Small number should not wrap (even if they're out of order).
for (uint64_t j = 0; j < 10; j++) {
CheckCalculatePacketNumber(cur_epoch + j, last);
@@ -684,7 +699,7 @@
const uint64_t next_epoch = 3 * kEpoch;
// Cases where the last number was close to the end of the range
for (uint64_t i = 0; i < 10; i++) {
- QuicPacketNumber last = next_epoch - 1 - i;
+ QuicPacketNumber last = QuicPacketNumber(next_epoch - 1 - i);
// Small numbers should wrap.
for (uint64_t j = 0; j < 10; j++) {
@@ -707,7 +722,7 @@
for (uint64_t i = 0; i < 10; i++) {
// Subtract 1, because the expected next packet number is 1 more than the
// last packet number.
- QuicPacketNumber last = max_number - i - 1;
+ QuicPacketNumber last = QuicPacketNumber(max_number - i - 1);
// Small numbers should not wrap, because they have nowhere to go.
for (uint64_t j = 0; j < 10; j++) {
@@ -749,10 +764,21 @@
// packet number
0x78, 0x56, 0x34, 0x12,
};
+ unsigned char packet47[kMaxPacketSize + 1] = {
+ // type (short header 4 byte packet number)
+ 0x43,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x78, 0x56, 0x34, 0x12,
+ };
// clang-format on
unsigned char* p = packet;
size_t p_size = QUIC_ARRAYSIZE(packet);
- if (framer_.transport_version() > QUIC_VERSION_43) {
+ if (framer_.transport_version() > QUIC_VERSION_46) {
+ p = packet47;
+ p_size = QUIC_ARRAYSIZE(packet47);
+ } else if (framer_.transport_version() > QUIC_VERSION_43) {
p = packet44;
p_size = QUIC_ARRAYSIZE(packet44);
}
@@ -826,9 +852,9 @@
TEST_P(QuicFramerTest, LongPacketHeader) {
// clang-format off
- PacketFragments packet = {
+ PacketFragments packet44 = {
// type (long header with packet type INITIAL)
- {"Unable to read public flags.",
+ {"Unable to read type.",
{0xFF}},
// version tag
{"Unable to read protocol version.",
@@ -843,14 +869,33 @@
{"Unable to read packet number.",
{0x12, 0x34, 0x56, 0x78}},
};
+ PacketFragments packet47 = {
+ // type (long header with packet type INITIAL)
+ {"Unable to read type.",
+ {0xC3}},
+ // version tag
+ {"Unable to read protocol version.",
+ {QUIC_VERSION_BYTES}},
+ // connection_id length
+ {"Unable to read ConnectionId length.",
+ {0x50}},
+ // connection_id
+ {"Unable to read Destination ConnectionId.",
+ {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
+ // packet number
+ {"Unable to read packet number.",
+ {0x12, 0x34, 0x56, 0x78}},
+ };
// clang-format on
if (framer_.transport_version() <= QUIC_VERSION_43) {
return;
}
+ PacketFragments& fragments =
+ framer_.transport_version() > QUIC_VERSION_46 ? packet47 : packet44;
std::unique_ptr<QuicEncryptedPacket> encrypted(
- AssemblePacketFromFragments(packet));
+ AssemblePacketFromFragments(fragments));
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
EXPECT_EQ(QUIC_MISSING_PAYLOAD, framer_.error());
@@ -861,7 +906,9 @@
EXPECT_TRUE(visitor_.header_->version_flag);
EXPECT_EQ(kPacketNumber, visitor_.header_->packet_number);
- CheckFramingBoundaries(packet, QUIC_INVALID_PACKET_HEADER);
+ CheckFramingBoundaries(
+ framer_.transport_version() > QUIC_VERSION_46 ? packet47 : packet44,
+ QUIC_INVALID_PACKET_HEADER);
}
TEST_P(QuicFramerTest, PacketHeaderWith0ByteConnectionId) {
@@ -900,7 +947,7 @@
{0x12, 0x34, 0x56, 0x78}},
};
- PacketFragments packet99 = {
+ PacketFragments packet47 = {
// type (short header, 4 byte packet number)
{"Unable to read type.",
{0x43}},
@@ -912,8 +959,8 @@
// clang-format on
PacketFragments& fragments =
- framer_.transport_version() == QUIC_VERSION_99
- ? packet99
+ framer_.transport_version() > QUIC_VERSION_46
+ ? packet47
: (framer_.transport_version() > QUIC_VERSION_43
? packet44
: (framer_.transport_version() == QUIC_VERSION_35 ? packet
@@ -966,7 +1013,7 @@
PacketFragments packet44 = {
// type (long header with packet type ZERO_RTT_PROTECTED)
- {"Unable to read public flags.",
+ {"Unable to read type.",
{0xFC}},
// version tag
{"Unable to read protocol version.",
@@ -982,10 +1029,10 @@
{0x12, 0x34, 0x56, 0x78}},
};
- PacketFragments packet99 = {
+ PacketFragments packet47 = {
// type (long header with packet type ZERO_RTT_PROTECTED and 4 bytes
// packet number)
- {"Unable to read public flags.",
+ {"Unable to read type.",
{0xD3}},
// version tag
{"Unable to read protocol version.",
@@ -1003,8 +1050,8 @@
// clang-format on
PacketFragments& fragments =
- framer_.transport_version() == QUIC_VERSION_99
- ? packet99
+ framer_.transport_version() > QUIC_VERSION_46
+ ? packet47
: (framer_.transport_version() > QUIC_VERSION_43
? packet44
: (framer_.transport_version() == QUIC_VERSION_35 ? packet
@@ -1054,7 +1101,7 @@
PacketFragments packet44 = {
// type (short header, 4 byte packet number)
- {"Unable to read public flags.",
+ {"Unable to read type.",
{0x32}},
// connection_id
{"Unable to read Destination ConnectionId.",
@@ -1063,13 +1110,27 @@
{"Unable to read packet number.",
{0x12, 0x34, 0x56, 0x78}},
};
+
+ PacketFragments packet47 = {
+ // type (short header, 4 byte packet number)
+ {"Unable to read type.",
+ {0x43}},
+ // connection_id
+ {"Unable to read Destination ConnectionId.",
+ {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
+ // packet number
+ {"Unable to read packet number.",
+ {0x12, 0x34, 0x56, 0x78}},
+ };
// clang-format on
PacketFragments& fragments =
- framer_.transport_version() > QUIC_VERSION_43
- ? packet44
- : (framer_.transport_version() == QUIC_VERSION_35 ? packet
- : packet39);
+ framer_.transport_version() > QUIC_VERSION_46
+ ? packet47
+ : (framer_.transport_version() > QUIC_VERSION_43
+ ? packet44
+ : (framer_.transport_version() == QUIC_VERSION_35 ? packet
+ : packet39));
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
@@ -1114,7 +1175,7 @@
PacketFragments packet44 = {
// type (short header, 2 byte packet number)
- {"Unable to read public flags.",
+ {"Unable to read type.",
{0x31}},
// connection_id
{"Unable to read Destination ConnectionId.",
@@ -1123,13 +1184,27 @@
{"Unable to read packet number.",
{0x56, 0x78}},
};
+
+ PacketFragments packet47 = {
+ // type (short header, 2 byte packet number)
+ {"Unable to read type.",
+ {0x41}},
+ // connection_id
+ {"Unable to read Destination ConnectionId.",
+ {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
+ // packet number
+ {"Unable to read packet number.",
+ {0x56, 0x78}},
+ };
// clang-format on
PacketFragments& fragments =
- framer_.transport_version() > QUIC_VERSION_43
- ? packet44
- : (framer_.transport_version() == QUIC_VERSION_35 ? packet
- : packet39);
+ framer_.transport_version() > QUIC_VERSION_46
+ ? packet47
+ : (framer_.transport_version() > QUIC_VERSION_43
+ ? packet44
+ : (framer_.transport_version() == QUIC_VERSION_35 ? packet
+ : packet39));
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
@@ -1163,7 +1238,7 @@
PacketFragments packet44 = {
// type (8 byte connection_id and 1 byte packet number)
- {"Unable to read public flags.",
+ {"Unable to read type.",
{0x30}},
// connection_id
{"Unable to read Destination ConnectionId.",
@@ -1173,10 +1248,24 @@
{0x78}},
};
+ PacketFragments packet47 = {
+ // type (8 byte connection_id and 1 byte packet number)
+ {"Unable to read type.",
+ {0x40}},
+ // connection_id
+ {"Unable to read Destination ConnectionId.",
+ {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
+ // packet number
+ {"Unable to read packet number.",
+ {0x78}},
+ };
+
// clang-format on
PacketFragments& fragments =
- framer_.transport_version() > QUIC_VERSION_43 ? packet44 : packet;
+ framer_.transport_version() > QUIC_VERSION_46
+ ? packet47
+ : (framer_.transport_version() > QUIC_VERSION_43 ? packet44 : packet);
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
@@ -1318,7 +1407,7 @@
0x00, 0x00, 0x00, 0x00
};
- unsigned char packet99[] = {
+ unsigned char packet47[] = {
// type: Long header with packet type ZERO_RTT_PROTECTED and 1 byte packet
// number.
0xD0,
@@ -1344,9 +1433,9 @@
unsigned char* p = packet;
size_t p_size = QUIC_ARRAYSIZE(packet);
- if (framer_.transport_version() == QUIC_VERSION_99) {
- p = packet99;
- p_size = QUIC_ARRAYSIZE(packet99);
+ if (framer_.transport_version() > QUIC_VERSION_46) {
+ p = packet47;
+ p_size = QUIC_ARRAYSIZE(packet47);
} else if (framer_.transport_version() > QUIC_VERSION_43) {
p = packet44;
p_size = QUIC_ARRAYSIZE(packet44);
@@ -1571,9 +1660,9 @@
0x00, 0x00,
};
- unsigned char packet99[] = {
+ unsigned char packet47[] = {
// type (short header, 4 byte packet number)
- 0x32,
+ 0x43,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
@@ -1581,8 +1670,35 @@
// paddings
0x00, 0x00,
- // frame type - Stream with FIN, LEN, and OFFSET bits set.
- 0x10 | 0x01 | 0x02 | 0x04,
+ // frame type (stream frame with fin)
+ 0xFF,
+ // stream id
+ 0x01, 0x02, 0x03, 0x04,
+ // offset
+ 0x3A, 0x98, 0xFE, 0xDC,
+ 0x32, 0x10, 0x76, 0x54,
+ // data length
+ 0x00, 0x0c,
+ // data
+ 'h', 'e', 'l', 'l',
+ 'o', ' ', 'w', 'o',
+ 'r', 'l', 'd', '!',
+ // paddings
+ 0x00, 0x00,
+ };
+
+ unsigned char packet99[] = {
+ // type (short header, 4 byte packet number)
+ 0x43,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // paddings
+ 0x00, 0x00,
+ // frame type - IETF_STREAM with FIN, LEN, and OFFSET bits set.
+ 0x08 | 0x01 | 0x02 | 0x04,
// stream id
kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04,
@@ -1608,6 +1724,9 @@
if (framer_.transport_version() == QUIC_VERSION_99) {
p = packet99;
p_size = QUIC_ARRAYSIZE(packet99);
+ } else if (framer_.transport_version() > QUIC_VERSION_46) {
+ p = packet47;
+ p_size = QUIC_ARRAYSIZE(packet47);
} else if (framer_.transport_version() > QUIC_VERSION_43) {
p = packet44;
p_size = QUIC_ARRAYSIZE(packet44);
@@ -1726,6 +1845,36 @@
'r', 'l', 'd', '!'}},
};
+ PacketFragments packet47 = {
+ // type (short header, 4 byte packet number)
+ {"",
+ {0x43}},
+ // connection_id
+ {"",
+ {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
+ // packet number
+ {"",
+ {0x12, 0x34, 0x56, 0x78}},
+ // frame type (stream frame with fin)
+ {"",
+ {0xFF}},
+ // stream id
+ {"Unable to read stream_id.",
+ {0x01, 0x02, 0x03, 0x04}},
+ // offset
+ {"Unable to read offset.",
+ {0x3A, 0x98, 0xFE, 0xDC,
+ 0x32, 0x10, 0x76, 0x54}},
+ {"Unable to read frame data.",
+ {
+ // data length
+ 0x00, 0x0c,
+ // data
+ 'h', 'e', 'l', 'l',
+ 'o', ' ', 'w', 'o',
+ 'r', 'l', 'd', '!'}},
+ };
+
PacketFragments packet99 = {
// type (short header, 4 byte packet number)
{"",
@@ -1736,9 +1885,9 @@
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
- // frame type - Stream with FIN, LEN, and OFFSET bits set.
+ // frame type - IETF_STREAM with FIN, LEN, and OFFSET bits set.
{"",
- { 0x10 | 0x01 | 0x02 | 0x04 }},
+ { 0x08 | 0x01 | 0x02 | 0x04 }},
// stream id
{"Unable to read stream_id.",
{kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04}},
@@ -1760,10 +1909,13 @@
PacketFragments& fragments =
framer_.transport_version() == QUIC_VERSION_99
? packet99
- : (framer_.transport_version() > QUIC_VERSION_43
- ? packet44
- : (framer_.transport_version() != QUIC_VERSION_35 ? packet39
- : packet));
+ : (framer_.transport_version() > QUIC_VERSION_46
+ ? packet47
+ : (framer_.transport_version() > QUIC_VERSION_43
+ ? packet44
+ : (framer_.transport_version() != QUIC_VERSION_35
+ ? packet39
+ : packet)));
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
@@ -1802,9 +1954,9 @@
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
- // frame type - Stream with FIN, LEN, and OFFSET bits set.
+ // frame type - IETF_STREAM with FIN, LEN, and OFFSET bits set.
{"",
- { 0x10 | 0x01 | 0x02 | 0x04 }},
+ { 0x08 | 0x01 | 0x02 | 0x04 }},
// stream id
{"Unable to read stream_id.",
{kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04}},
@@ -2123,6 +2275,36 @@
'r', 'l', 'd', '!'}},
};
+ PacketFragments packet47 = {
+ // type (short header, 4 byte packet number)
+ {"",
+ {0x43}},
+ // connection_id
+ {"",
+ {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
+ // packet number
+ {"",
+ {0x12, 0x34, 0x56, 0x78}},
+ // frame type (stream frame with fin)
+ {"",
+ {0xFD}},
+ // stream id
+ {"Unable to read stream_id.",
+ {0x03, 0x04}},
+ // offset
+ {"Unable to read offset.",
+ {0x3A, 0x98, 0xFE, 0xDC,
+ 0x32, 0x10, 0x76, 0x54}},
+ {"Unable to read frame data.",
+ {
+ // data length
+ 0x00, 0x0c,
+ // data
+ 'h', 'e', 'l', 'l',
+ 'o', ' ', 'w', 'o',
+ 'r', 'l', 'd', '!'}},
+ };
+
PacketFragments packet99 = {
// type (short header, 4 byte packet number)
{"",
@@ -2133,9 +2315,9 @@
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
- // frame type (stream frame with LEN, FIN, and OFFSET bits set)
+ // frame type (IETF_STREAM frame with LEN, FIN, and OFFSET bits set)
{"",
- {0x10 | 0x01 | 0x02 | 0x04}},
+ {0x08 | 0x01 | 0x02 | 0x04}},
// stream id
{"Unable to read stream_id.",
{kVarInt62TwoBytes + 0x03, 0x04}},
@@ -2157,10 +2339,13 @@
PacketFragments& fragments =
framer_.transport_version() == QUIC_VERSION_99
? packet99
- : (framer_.transport_version() > QUIC_VERSION_43
- ? packet44
- : (framer_.transport_version() != QUIC_VERSION_35 ? packet39
- : packet));
+ : (framer_.transport_version() > QUIC_VERSION_46
+ ? packet47
+ : (framer_.transport_version() > QUIC_VERSION_43
+ ? packet44
+ : (framer_.transport_version() != QUIC_VERSION_35
+ ? packet39
+ : packet)));
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
@@ -2274,6 +2459,36 @@
'r', 'l', 'd', '!'}},
};
+ PacketFragments packet47 = {
+ // type (short header, 4 byte packet number)
+ {"",
+ {0x43}},
+ // connection_id
+ {"",
+ {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
+ // packet number
+ {"",
+ {0x12, 0x34, 0x56, 0x78}},
+ // frame type (stream frame with fin)
+ {"",
+ {0xFC}},
+ // stream id
+ {"Unable to read stream_id.",
+ {0x04}},
+ // offset
+ {"Unable to read offset.",
+ {0x3A, 0x98, 0xFE, 0xDC,
+ 0x32, 0x10, 0x76, 0x54}},
+ {"Unable to read frame data.",
+ {
+ // data length
+ 0x00, 0x0c,
+ // data
+ 'h', 'e', 'l', 'l',
+ 'o', ' ', 'w', 'o',
+ 'r', 'l', 'd', '!'}},
+ };
+
PacketFragments packet99 = {
// type (short header, 4 byte packet number)
{"",
@@ -2284,9 +2499,9 @@
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
- // frame type (stream frame with LEN, FIN, and OFFSET bits set)
+ // frame type (IETF_STREAM frame with LEN, FIN, and OFFSET bits set)
{"",
- {0x10 | 0x01 | 0x02 | 0x04}},
+ {0x08 | 0x01 | 0x02 | 0x04}},
// stream id
{"Unable to read stream_id.",
{kVarInt62OneByte + 0x04}},
@@ -2308,10 +2523,13 @@
PacketFragments& fragments =
framer_.transport_version() == QUIC_VERSION_99
? packet99
- : (framer_.transport_version() > QUIC_VERSION_43
- ? packet44
- : (framer_.transport_version() != QUIC_VERSION_35 ? packet39
- : packet));
+ : (framer_.transport_version() > QUIC_VERSION_46
+ ? packet47
+ : (framer_.transport_version() > QUIC_VERSION_43
+ ? packet44
+ : (framer_.transport_version() != QUIC_VERSION_35
+ ? packet39
+ : packet)));
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
@@ -2437,6 +2655,43 @@
'r', 'l', 'd', '!'}},
};
+ PacketFragments packet47 = {
+ // public flags (long header with packet type ZERO_RTT_PROTECTED and
+ // 4-byte packet number)
+ {"",
+ {0xD3}},
+ // version tag
+ {"",
+ {QUIC_VERSION_BYTES}},
+ // connection_id length
+ {"",
+ {0x50}},
+ // connection_id
+ {"",
+ {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
+ // packet number
+ {"",
+ {0x12, 0x34, 0x56, 0x78}},
+ // frame type (stream frame with fin)
+ {"",
+ {0xFE}},
+ // stream id
+ {"Unable to read stream_id.",
+ {0x02, 0x03, 0x04}},
+ // offset
+ {"Unable to read offset.",
+ {0x3A, 0x98, 0xFE, 0xDC,
+ 0x32, 0x10, 0x76, 0x54}},
+ {"Unable to read frame data.",
+ {
+ // data length
+ 0x00, 0x0c,
+ // data
+ 'h', 'e', 'l', 'l',
+ 'o', ' ', 'w', 'o',
+ 'r', 'l', 'd', '!'}},
+ };
+
PacketFragments packet99 = {
// public flags (long header with packet type ZERO_RTT_PROTECTED and
// 4-byte packet number)
@@ -2454,9 +2709,9 @@
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
- // frame type (stream frame with FIN, LEN, and OFFSET bits set)
+ // frame type (IETF_STREAM frame with FIN, LEN, and OFFSET bits set)
{"",
- {0x10 | 0x01 | 0x02 | 0x04}},
+ {0x08 | 0x01 | 0x02 | 0x04}},
// stream id
{"Unable to read stream_id.",
{kVarInt62FourBytes + 0x00, 0x02, 0x03, 0x04}},
@@ -2478,10 +2733,13 @@
PacketFragments& fragments =
framer_.transport_version() == QUIC_VERSION_99
? packet99
- : (framer_.transport_version() > QUIC_VERSION_43
- ? packet44
- : (framer_.transport_version() != QUIC_VERSION_35 ? packet39
- : packet));
+ : (framer_.transport_version() > QUIC_VERSION_46
+ ? packet47
+ : (framer_.transport_version() > QUIC_VERSION_43
+ ? packet44
+ : (framer_.transport_version() != QUIC_VERSION_35
+ ? packet39
+ : packet)));
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
@@ -2575,10 +2833,35 @@
'o', ' ', 'w', 'o',
'r', 'l', 'd', '!',
};
+
+ unsigned char packet47[] = {
+ // type (short header, 4 byte packet number)
+ 0x43,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // frame type (STREAM Frame with FIN, LEN, and OFFSET bits set)
+ 0x10 | 0x01 | 0x02 | 0x04,
+ // stream id
+ kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04,
+ // offset
+ kVarInt62EightBytes + 0x3A, 0x98, 0xFE, 0xDC,
+ 0x32, 0x10, 0x76, 0x54,
+ // data length
+ kVarInt62OneByte + 0x0c,
+ // data
+ 'h', 'e', 'l', 'l',
+ 'o', ' ', 'w', 'o',
+ 'r', 'l', 'd', '!',
+ };
// clang-format on
unsigned char* p = packet;
- if (framer_.transport_version() > QUIC_VERSION_43) {
+ if (framer_.transport_version() > QUIC_VERSION_46) {
+ p = packet47;
+ } else if (framer_.transport_version() > QUIC_VERSION_43) {
p = packet44;
} else if (framer_.transport_version() != QUIC_VERSION_35) {
p = packet39;
@@ -2619,19 +2902,33 @@
// packet number
0x01,
};
+
+ unsigned char packet47[] = {
+ // type (short header, 1 byte packet number)
+ 0x40,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x01,
+ };
// clang-format on
QuicEncryptedPacket encrypted(
- framer_.transport_version() > QUIC_VERSION_43 ? AsChars(packet44)
- : AsChars(packet),
- framer_.transport_version() > QUIC_VERSION_43 ? QUIC_ARRAYSIZE(packet44)
- : QUIC_ARRAYSIZE(packet),
+ framer_.transport_version() > QUIC_VERSION_46
+ ? AsChars(packet47)
+ : (framer_.transport_version() > QUIC_VERSION_43 ? AsChars(packet44)
+ : AsChars(packet)),
+ framer_.transport_version() > QUIC_VERSION_46
+ ? QUIC_ARRAYSIZE(packet47)
+ : (framer_.transport_version() > QUIC_VERSION_43
+ ? QUIC_ARRAYSIZE(packet44)
+ : QUIC_ARRAYSIZE(packet)),
false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
ASSERT_TRUE(visitor_.header_.get());
- EXPECT_EQ(0u, visitor_.header_->packet_number);
+ EXPECT_FALSE(visitor_.header_->packet_number.IsInitialized());
}
TEST_P(QuicFramerTest, AckFrameOneAckBlock) {
@@ -2720,22 +3017,50 @@
{0x00}}
};
- PacketFragments packet99 = {
+ PacketFragments packet47 = {
// type (short packet, 4 byte packet number)
{"",
- {0x32}},
+ {0x43}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
- // frame type (ack frame)
+ // frame type (ack frame)
+ // (one ack block, 2 byte largest observed, 2 byte block length)
+ {"",
+ {0x45}},
+ // largest acked
+ {"Unable to read largest acked.",
+ {0x12, 0x34}},
+ // Zero delta time.
+ {"Unable to read ack delay time.",
+ {0x00, 0x00}},
+ // first ack block length.
+ {"Unable to read first ack block length.",
+ {0x12, 0x34}},
+ // num timestamps.
+ {"Unable to read num received packets.",
+ {0x00}}
+ };
+
+ PacketFragments packet99 = {
+ // type (short packet, 4 byte packet number)
+ {"",
+ {0x43}},
+ // connection_id
+ {"",
+ {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
+ // packet number
+ {"",
+ {0x12, 0x34, 0x56, 0x78}},
+ // frame type (IETF_ACK)
// (one ack block, 2 byte largest observed, 2 byte block length)
// IETF-Quic ignores the bit-fields in the ack type, all of
// that information is encoded elsewhere in the frame.
{"",
- {0x1a}},
+ {0x02}},
// largest acked
{"Unable to read largest acked.",
{kVarInt62TwoBytes + 0x12, 0x34}},
@@ -2759,10 +3084,13 @@
PacketFragments& fragments =
framer_.transport_version() == QUIC_VERSION_99
? packet99
- : (framer_.transport_version() > QUIC_VERSION_43
- ? packet44
- : (framer_.transport_version() != QUIC_VERSION_35 ? packet39
- : packet));
+ : (framer_.transport_version() > QUIC_VERSION_46
+ ? packet47
+ : (framer_.transport_version() > QUIC_VERSION_43
+ ? packet44
+ : (framer_.transport_version() != QUIC_VERSION_35
+ ? packet39
+ : packet)));
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
@@ -2871,6 +3199,34 @@
{0x00}}
};
+ PacketFragments packet47 = {
+ // type (short header, 4 byte packet number)
+ {"",
+ {0x43}},
+ // connection_id
+ {"",
+ {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
+ // packet number
+ {"",
+ {0x12, 0x34, 0x56, 0x78}},
+ // frame type (ack frame)
+ // (one ack block, 2 byte largest observed, 2 byte block length)
+ {"",
+ {0x45}},
+ // largest acked
+ {"Unable to read largest acked.",
+ {0x12, 0x34}},
+ // Zero delta time.
+ {"Unable to read ack delay time.",
+ {0x00, 0x00}},
+ // first ack block length.
+ {"Unable to read first ack block length.",
+ {0x88, 0x88}},
+ // num timestamps.
+ {"Underflow with first ack block length 34952 largest acked is 4660.",
+ {0x00}}
+ };
+
PacketFragments packet99 = {
// type (short header, 4 byte packet number)
{"",
@@ -2881,9 +3237,9 @@
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
- // frame type (ack frame)
+ // frame type (IETF_ACK)
{"",
- {0x1a}},
+ {0x02}},
// largest acked
{"Unable to read largest acked.",
{kVarInt62TwoBytes + 0x12, 0x34}},
@@ -2902,10 +3258,13 @@
PacketFragments& fragments =
framer_.transport_version() == QUIC_VERSION_99
? packet99
- : (framer_.transport_version() > QUIC_VERSION_43
- ? packet44
- : (framer_.transport_version() != QUIC_VERSION_35 ? packet39
- : packet));
+ : (framer_.transport_version() > QUIC_VERSION_46
+ ? packet47
+ : (framer_.transport_version() > QUIC_VERSION_43
+ ? packet44
+ : (framer_.transport_version() != QUIC_VERSION_35
+ ? packet39
+ : packet)));
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
@@ -2931,9 +3290,9 @@
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
- // frame type (ack frame)
+ // frame type (IETF_ACK frame)
{"",
- {0x1a}},
+ {0x02}},
// largest acked
{"Unable to read largest acked.",
{kVarInt62OneByte + 63}},
@@ -2988,9 +3347,9 @@
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
- // frame type (ack frame)
+ // frame type (IETF_ACK frame)
{"",
- {0x1a}},
+ {0x02}},
// largest acked
{"Unable to read largest acked.",
{kVarInt62OneByte + 63}},
@@ -3043,9 +3402,9 @@
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
- // frame type (ack frame)
+ // frame type (IETF_ACK frame)
{"",
- {0x1a}},
+ {0x02}},
// largest acked
{"Unable to read largest acked.",
{kVarInt62OneByte + 10}},
@@ -3092,9 +3451,9 @@
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
- // frame type (ack frame)
+ // frame type (IETF_ACK frame)
{"",
- {0x1a}},
+ {0x02}},
// largest acked
{"Unable to read largest acked.",
{kVarInt62OneByte + 10}},
@@ -3123,7 +3482,7 @@
CheckFramingBoundaries(packet99, QUIC_INVALID_ACK_DATA);
}
-// An ack block that acks the entire range, 0...0x3fffffffffffffff
+// An ack block that acks the entire range, 1...0x3fffffffffffffff
TEST_P(QuicFramerTest, AckBlockAcksEverything) {
if (framer_.transport_version() != QUIC_VERSION_99) {
// for now, only v99
@@ -3140,9 +3499,9 @@
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
- // frame type (ack frame)
+ // frame type (IETF_ACK frame)
{"",
- {0x1a}},
+ {0x02}},
// largest acked
{"Unable to read largest acked.",
{kVarInt62EightBytes + 0x3f, 0xff, 0xff, 0xff,
@@ -3156,7 +3515,7 @@
// first ack block length.
{"Unable to read first ack block length.",
{kVarInt62EightBytes + 0x3f, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff}},
+ 0xff, 0xff, 0xff, 0xfe}},
};
// clang-format on
@@ -3167,8 +3526,8 @@
const QuicAckFrame& frame = *visitor_.ack_frames_[0];
EXPECT_EQ(1u, frame.packets.NumIntervals());
EXPECT_EQ(kLargestIetfLargestObserved, LargestAcked(frame));
- // +1 because it's 0..Largest, inclusive.
- EXPECT_EQ(kLargestIetfLargestObserved + 1, frame.packets.NumPacketsSlow());
+ EXPECT_EQ(kLargestIetfLargestObserved.ToUint64(),
+ frame.packets.NumPacketsSlow());
}
// This test looks for a malformed ack where
@@ -3312,12 +3671,55 @@
{ 0x00 }},
};
+ PacketFragments packet47 = {
+ // type (short header, 4 byte packet number)
+ {"",
+ { 0x43 }},
+ // connection_id
+ {"",
+ { 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 }},
+ // packet number
+ {"",
+ { 0x12, 0x34, 0x56, 0x78 }},
+
+ // frame type (ack frame)
+ // (more than one ack block, 2 byte largest observed, 2 byte block length)
+ {"",
+ { 0x65 }},
+ // largest acked
+ {"Unable to read largest acked.",
+ { 0x12, 0x34 }},
+ // Zero delta time.
+ {"Unable to read ack delay time.",
+ { 0x00, 0x00 }},
+ // num ack blocks ranges.
+ {"Unable to read num of ack blocks.",
+ { 0x01 }},
+ // first ack block length.
+ {"Unable to read first ack block length.",
+ { 0x00, 0x00 }},
+ // gap to next block.
+ { "First block length is zero but ACK is not empty. "
+ "largest acked is 4660, num ack blocks is 1.",
+ { 0x01 }},
+ // ack block length.
+ { "First block length is zero but ACK is not empty. "
+ "largest acked is 4660, num ack blocks is 1.",
+ { 0x0e, 0xaf }},
+ // Number of timestamps.
+ { "First block length is zero but ACK is not empty. "
+ "largest acked is 4660, num ack blocks is 1.",
+ { 0x00 }},
+ };
+
// clang-format on
PacketFragments& fragments =
- framer_.transport_version() > QUIC_VERSION_43
- ? packet44
- : (framer_.transport_version() != QUIC_VERSION_35 ? packet39
- : packet);
+ framer_.transport_version() > QUIC_VERSION_46
+ ? packet47
+ : (framer_.transport_version() > QUIC_VERSION_43
+ ? packet44
+ : (framer_.transport_version() != QUIC_VERSION_35 ? packet39
+ : packet));
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
@@ -3422,6 +3824,34 @@
{0x00}}
};
+ PacketFragments packet47 = {
+ // type (short header, 4 byte packet number)
+ {"",
+ {0x43}},
+ // connection_id
+ {"",
+ {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
+ // packet number
+ {"",
+ {0x56, 0x78, 0x9A, 0xBC}},
+ // frame type (ack frame)
+ // (one ack block, 4 byte largest observed, 2 byte block length)
+ {"",
+ {0x49}},
+ // largest acked
+ {"Unable to read largest acked.",
+ {0x12, 0x34, 0x56, 0x78}},
+ // Zero delta time.
+ {"Unable to read ack delay time.",
+ {0x00, 0x00}},
+ // first ack block length.
+ {"Unable to read first ack block length.",
+ {0x12, 0x34}},
+ // num timestamps.
+ {"Unable to read num received packets.",
+ {0x00}}
+ };
+
PacketFragments packet99 = {
// type (short header, 4 byte packet number)
{"",
@@ -3432,9 +3862,9 @@
// packet number
{"",
{0x56, 0x78, 0x9A, 0xBC}},
- // frame type (ack frame)
+ // frame type (IETF_ACK frame)
{"",
- {0x1a}},
+ {0x02}},
// largest acked
{"Unable to read largest acked.",
{kVarInt62FourBytes + 0x12, 0x34, 0x56, 0x78}},
@@ -3453,10 +3883,13 @@
PacketFragments& fragments =
framer_.transport_version() == QUIC_VERSION_99
? packet99
- : (framer_.transport_version() > QUIC_VERSION_43
- ? packet44
- : (framer_.transport_version() != QUIC_VERSION_35 ? packet39
- : packet));
+ : (framer_.transport_version() > QUIC_VERSION_46
+ ? packet47
+ : (framer_.transport_version() > QUIC_VERSION_43
+ ? packet44
+ : (framer_.transport_version() != QUIC_VERSION_35
+ ? packet39
+ : packet)));
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
@@ -3684,10 +4117,10 @@
{ 0x32, 0x10 }},
};
- PacketFragments packet99 = {
+ PacketFragments packet47 = {
// type (short header, 4 byte packet number)
{"",
- { 0x32 }},
+ { 0x43 }},
// connection_id
{"",
{ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 }},
@@ -3696,8 +4129,76 @@
{ 0x12, 0x34, 0x56, 0x78 }},
// frame type (ack frame)
+ // (more than one ack block, 2 byte largest observed, 2 byte block length)
{"",
- { 0x1a }},
+ { 0x65 }},
+ // largest acked
+ {"Unable to read largest acked.",
+ { 0x12, 0x34 }},
+ // Zero delta time.
+ {"Unable to read ack delay time.",
+ { 0x00, 0x00 }},
+ // num ack blocks ranges.
+ {"Unable to read num of ack blocks.",
+ { 0x04 }},
+ // first ack block length.
+ {"Unable to read first ack block length.",
+ { 0x00, 0x01 }},
+ // gap to next block.
+ { "Unable to read gap to next ack block.",
+ { 0x01 }},
+ // ack block length.
+ { "Unable to ack block length.",
+ { 0x0e, 0xaf }},
+ // gap to next block.
+ { "Unable to read gap to next ack block.",
+ { 0xff }},
+ // ack block length.
+ { "Unable to ack block length.",
+ { 0x00, 0x00 }},
+ // gap to next block.
+ { "Unable to read gap to next ack block.",
+ { 0x91 }},
+ // ack block length.
+ { "Unable to ack block length.",
+ { 0x01, 0xea }},
+ // gap to next block.
+ { "Unable to read gap to next ack block.",
+ { 0x05 }},
+ // ack block length.
+ { "Unable to ack block length.",
+ { 0x00, 0x04 }},
+ // Number of timestamps.
+ { "Unable to read num received packets.",
+ { 0x02 }},
+ // Delta from largest observed.
+ { "Unable to read sequence delta in received packets.",
+ { 0x01 }},
+ // Delta time.
+ { "Unable to read time delta in received packets.",
+ { 0x76, 0x54, 0x32, 0x10 }},
+ // Delta from largest observed.
+ { "Unable to read sequence delta in received packets.",
+ { 0x02 }},
+ // Delta time.
+ { "Unable to read incremental time delta in received packets.",
+ { 0x32, 0x10 }},
+ };
+
+ PacketFragments packet99 = {
+ // type (short header, 4 byte packet number)
+ {"",
+ { 0x43 }},
+ // connection_id
+ {"",
+ { 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 }},
+ // packet number
+ {"",
+ { 0x12, 0x34, 0x56, 0x78 }},
+
+ // frame type (IETF_ACK frame)
+ {"",
+ { 0x02 }},
// largest acked
{"Unable to read largest acked.",
{ kVarInt62TwoBytes + 0x12, 0x34 }}, // = 4660
@@ -3744,10 +4245,13 @@
PacketFragments& fragments =
framer_.transport_version() == QUIC_VERSION_99
? packet99
- : (framer_.transport_version() > QUIC_VERSION_43
- ? packet44
- : (framer_.transport_version() != QUIC_VERSION_35 ? packet39
- : packet));
+ : (framer_.transport_version() > QUIC_VERSION_46
+ ? packet47
+ : (framer_.transport_version() > QUIC_VERSION_43
+ ? packet44
+ : (framer_.transport_version() != QUIC_VERSION_35
+ ? packet39
+ : packet)));
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
@@ -3833,13 +4337,33 @@
{"Unable to read least unacked delta.",
{0x00, 0x00, 0x00, 0x08}}
};
+
+ PacketFragments packet47 = {
+ // type (short header, 4 byte packet number)
+ {"",
+ {0x43}},
+ // connection_id
+ {"",
+ {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
+ // packet number
+ {"",
+ {0x12, 0x34, 0x56, 0x78}},
+ // frame type (stop waiting frame)
+ {"",
+ {0x06}},
+ // least packet number awaiting an ack, delta from packet number.
+ {"Unable to read least unacked delta.",
+ {0x00, 0x00, 0x00, 0x08}}
+ };
// clang-format on
PacketFragments& fragments =
- framer_.transport_version() > QUIC_VERSION_43
- ? packet44
- : (framer_.transport_version() != QUIC_VERSION_35 ? packet39
- : packet);
+ framer_.transport_version() > QUIC_VERSION_46
+ ? packet47
+ : (framer_.transport_version() > QUIC_VERSION_43
+ ? packet44
+ : (framer_.transport_version() != QUIC_VERSION_35 ? packet39
+ : packet));
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
@@ -3903,14 +4427,29 @@
// least packet number awaiting an ack, delta from packet number.
0x57, 0x78, 0x9A, 0xA8,
};
+
+ unsigned char packet47[] = {
+ // type (short header, 4 byte packet number)
+ 0x43,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+ // frame type (stop waiting frame)
+ 0x06,
+ // least packet number awaiting an ack, delta from packet number.
+ 0x57, 0x78, 0x9A, 0xA8,
+ };
// clang-format on
QuicEncryptedPacket encrypted(
- AsChars(framer_.transport_version() > QUIC_VERSION_43
- ? packet44
- : (framer_.transport_version() == QUIC_VERSION_35
- ? packet
- : packet39)),
+ AsChars(framer_.transport_version() > QUIC_VERSION_46
+ ? packet47
+ : (framer_.transport_version() > QUIC_VERSION_43
+ ? packet44
+ : (framer_.transport_version() == QUIC_VERSION_35
+ ? packet
+ : packet39))),
framer_.transport_version() > QUIC_VERSION_43 ? QUIC_ARRAYSIZE(packet44)
: QUIC_ARRAYSIZE(packet),
false);
@@ -3996,7 +4535,7 @@
{0x00, 0x00, 0x00, 0x01}}
};
- PacketFragments packet99 = {
+ PacketFragments packet47 = {
// type (short header, 4 byte packet number)
{"",
{0x43}},
@@ -4010,6 +4549,31 @@
{"",
{0x01}},
// stream id
+ {"Unable to read stream_id.",
+ {0x01, 0x02, 0x03, 0x04}},
+ // sent byte offset
+ {"Unable to read rst stream sent byte offset.",
+ {0x3A, 0x98, 0xFE, 0xDC,
+ 0x32, 0x10, 0x76, 0x54}},
+ // error code
+ {"Unable to read rst stream error code.",
+ {0x00, 0x00, 0x00, 0x01}}
+ };
+
+ PacketFragments packet99 = {
+ // type (short header, 4 byte packet number)
+ {"",
+ {0x43}},
+ // connection_id
+ {"",
+ {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
+ // packet number
+ {"",
+ {0x12, 0x34, 0x56, 0x78}},
+ // frame type (IETF_RST_STREAM frame)
+ {"",
+ {0x04}},
+ // stream id
{"Unable to read rst stream stream id.",
{kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04}},
// application error code
@@ -4024,10 +4588,13 @@
PacketFragments& fragments =
framer_.transport_version() == QUIC_VERSION_99
? packet99
- : (framer_.transport_version() > QUIC_VERSION_43
- ? packet44
- : (framer_.transport_version() != QUIC_VERSION_35 ? packet39
- : packet));
+ : (framer_.transport_version() > QUIC_VERSION_46
+ ? packet47
+ : (framer_.transport_version() > QUIC_VERSION_43
+ ? packet44
+ : (framer_.transport_version() != QUIC_VERSION_35
+ ? packet39
+ : packet)));
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
@@ -4130,7 +4697,7 @@
}
};
- PacketFragments packet99 = {
+ PacketFragments packet47 = {
// type (short header, 4 byte packet number)
{"",
{0x43}},
@@ -4145,6 +4712,34 @@
{0x02}},
// error code
{"Unable to read connection close error code.",
+ {0x00, 0x00, 0x00, 0x11}},
+ {"Unable to read connection close error details.",
+ {
+ // error details length
+ 0x0, 0x0d,
+ // error details
+ 'b', 'e', 'c', 'a',
+ 'u', 's', 'e', ' ',
+ 'I', ' ', 'c', 'a',
+ 'n'}
+ }
+ };
+
+ PacketFragments packet99 = {
+ // type (short header, 4 byte packet number)
+ {"",
+ {0x43}},
+ // connection_id
+ {"",
+ {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
+ // packet number
+ {"",
+ {0x12, 0x34, 0x56, 0x78}},
+ // frame type (IETF_CONNECTION_CLOSE frame)
+ {"",
+ {0x1c}},
+ // error code
+ {"Unable to read connection close error code.",
{0x00, 0x11}},
{"Unable to read connection close frame type.",
{kVarInt62TwoBytes + 0x12, 0x34 }},
@@ -4164,10 +4759,13 @@
PacketFragments& fragments =
framer_.transport_version() == QUIC_VERSION_99
? packet99
- : (framer_.transport_version() > QUIC_VERSION_43
- ? packet44
- : (framer_.transport_version() != QUIC_VERSION_35 ? packet39
- : packet));
+ : (framer_.transport_version() > QUIC_VERSION_46
+ ? packet47
+ : (framer_.transport_version() > QUIC_VERSION_43
+ ? packet44
+ : (framer_.transport_version() != QUIC_VERSION_35
+ ? packet39
+ : packet)));
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
@@ -4208,9 +4806,9 @@
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
- // frame type (application close frame)
+ // frame type (IETF_APPLICATION_CLOSE frame)
{"",
- {0x03}},
+ {0x1d}},
// error code
{"Unable to read application close error code.",
{0x00, 0x11}},
@@ -4347,13 +4945,47 @@
'n'}
}
};
+
+ PacketFragments packet47 = {
+ // type (short header, 4 byte packet number)
+ {"",
+ {0x43}},
+ // connection_id
+ {"",
+ {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
+ // packet number
+ {"",
+ {0x12, 0x34, 0x56, 0x78}},
+ // frame type (go away frame)
+ {"",
+ {0x03}},
+ // error code
+ {"Unable to read go away error code.",
+ {0x00, 0x00, 0x00, 0x09}},
+ // stream id
+ {"Unable to read last good stream id.",
+ {0x01, 0x02, 0x03, 0x04}},
+ // stream id
+ {"Unable to read goaway reason.",
+ {
+ // error details length
+ 0x0, 0x0d,
+ // error details
+ 'b', 'e', 'c', 'a',
+ 'u', 's', 'e', ' ',
+ 'I', ' ', 'c', 'a',
+ 'n'}
+ }
+ };
// clang-format on
PacketFragments& fragments =
- framer_.transport_version() > QUIC_VERSION_43
- ? packet44
- : (framer_.transport_version() != QUIC_VERSION_35 ? packet39
- : packet);
+ framer_.transport_version() > QUIC_VERSION_46
+ ? packet47
+ : (framer_.transport_version() > QUIC_VERSION_43
+ ? packet44
+ : (framer_.transport_version() != QUIC_VERSION_35 ? packet39
+ : packet));
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
@@ -4425,6 +5057,28 @@
PacketFragments packet44 = {
// type (short header, 4 byte packet number)
{"",
+ {0x32}},
+ // connection_id
+ {"",
+ {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
+ // packet number
+ {"",
+ {0x12, 0x34, 0x56, 0x78}},
+ // frame type (window update frame)
+ {"",
+ {0x04}},
+ // stream id
+ {"Unable to read stream_id.",
+ {0x01, 0x02, 0x03, 0x04}},
+ // byte offset
+ {"Unable to read window byte_offset.",
+ {0x3A, 0x98, 0xFE, 0xDC,
+ 0x32, 0x10, 0x76, 0x54}},
+ };
+
+ PacketFragments packet47 = {
+ // type (short header, 4 byte packet number)
+ {"",
{0x43}},
// connection_id
{"",
@@ -4447,10 +5101,12 @@
// clang-format on
PacketFragments& fragments =
- framer_.transport_version() > QUIC_VERSION_43
- ? packet44
- : (framer_.transport_version() != QUIC_VERSION_35 ? packet39
- : packet);
+ framer_.transport_version() > QUIC_VERSION_46
+ ? packet47
+ : (framer_.transport_version() > QUIC_VERSION_43
+ ? packet44
+ : (framer_.transport_version() != QUIC_VERSION_35 ? packet39
+ : packet));
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
@@ -4483,9 +5139,9 @@
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
- // frame type (IETF max data frame)
+ // frame type (IETF_MAX_DATA frame)
{"",
- {0x04}},
+ {0x10}},
// byte offset
{"Can not read MAX_DATA byte-offset",
{kVarInt62EightBytes + 0x3A, 0x98, 0xFE, 0xDC,
@@ -4525,9 +5181,9 @@
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
- // frame type (ietf max stream data frame)
+ // frame type (IETF_MAX_STREAM_DATA frame)
{"",
- {0x05}},
+ {0x11}},
// stream id
{"Can not read MAX_STREAM_DATA stream id",
{kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04}},
@@ -4610,6 +5266,24 @@
{0x01, 0x02, 0x03, 0x04}},
};
+ PacketFragments packet47 = {
+ // type (short header, 4 byte packet number)
+ {"",
+ {0x43}},
+ // connection_id
+ {"",
+ {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
+ // packet number
+ {"",
+ {0x12, 0x34, 0x56, 0x78}},
+ // frame type (blocked frame)
+ {"",
+ {0x05}},
+ // stream id
+ {"Unable to read stream_id.",
+ {0x01, 0x02, 0x03, 0x04}},
+ };
+
PacketFragments packet99 = {
// type (short header, 4 byte packet number)
{"",
@@ -4620,9 +5294,9 @@
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
- // frame type (IETF stream blocked frame)
+ // frame type (IETF_STREAM_BLOCKED frame)
{"",
- {0x09}},
+ {0x15}},
// stream id
{"Can not read stream blocked stream id.",
{kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04}},
@@ -4635,10 +5309,13 @@
PacketFragments& fragments =
framer_.transport_version() == QUIC_VERSION_99
? packet99
- : (framer_.transport_version() > QUIC_VERSION_43
- ? packet44
- : (framer_.transport_version() != QUIC_VERSION_35 ? packet39
- : packet));
+ : (framer_.transport_version() > QUIC_VERSION_46
+ ? packet47
+ : (framer_.transport_version() > QUIC_VERSION_43
+ ? packet44
+ : (framer_.transport_version() != QUIC_VERSION_35
+ ? packet39
+ : packet)));
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
@@ -4700,16 +5377,49 @@
// frame type
0x07,
};
+
+ unsigned char packet47[] = {
+ // type (short header, 4 byte packet number)
+ 0x43,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // frame type
+ 0x07,
+ };
+
+ unsigned char packet99[] = {
+ // type (short header, 4 byte packet number)
+ 0x43,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // frame type (IETF_PING frame)
+ 0x01,
+ };
// clang-format on
QuicEncryptedPacket encrypted(
- AsChars(framer_.transport_version() > QUIC_VERSION_43
- ? packet44
- : (framer_.transport_version() == QUIC_VERSION_35
- ? packet
- : packet39)),
- framer_.transport_version() > QUIC_VERSION_43 ? QUIC_ARRAYSIZE(packet44)
- : QUIC_ARRAYSIZE(packet),
+ AsChars(framer_.transport_version() == QUIC_VERSION_99
+ ? packet99
+ : (framer_.transport_version() > QUIC_VERSION_46
+ ? packet47
+ : framer_.transport_version() > QUIC_VERSION_43
+ ? packet44
+ : (framer_.transport_version() == QUIC_VERSION_35
+ ? packet
+ : packet39))),
+ framer_.transport_version() == QUIC_VERSION_99
+ ? QUIC_ARRAYSIZE(packet99)
+ : (framer_.transport_version() > QUIC_VERSION_46
+ ? QUIC_ARRAYSIZE(packet47)
+ : framer_.transport_version() > QUIC_VERSION_43
+ ? QUIC_ARRAYSIZE(packet44)
+ : QUIC_ARRAYSIZE(packet)),
false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
@@ -4755,10 +5465,37 @@
{{},
{'m', 'e', 's', 's', 'a', 'g', 'e', '2'}},
};
+
+ PacketFragments packet47 = {
+ // type (short header, 4 byte packet number)
+ {"",
+ {0x43}},
+ // connection_id
+ {"",
+ {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
+ // packet number
+ {"",
+ {0x12, 0x34, 0x56, 0x78}},
+ // message frame type.
+ {"",
+ { 0x21 }},
+ // message length
+ {"Unable to read message length",
+ {0x07}},
+ // message data
+ {"Unable to read message data",
+ {'m', 'e', 's', 's', 'a', 'g', 'e'}},
+ // message frame no length.
+ {"",
+ { 0x20 }},
+ // message data
+ {{},
+ {'m', 'e', 's', 's', 'a', 'g', 'e', '2'}},
+ };
// clang-format on
- std::unique_ptr<QuicEncryptedPacket> encrypted(
- AssemblePacketFromFragments(packet45));
+ std::unique_ptr<QuicEncryptedPacket> encrypted(AssemblePacketFromFragments(
+ framer_.transport_version() > QUIC_VERSION_46 ? packet47 : packet45));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
@@ -4771,7 +5508,9 @@
EXPECT_EQ(7u, visitor_.message_frames_[0]->message_data.length());
EXPECT_EQ(8u, visitor_.message_frames_[1]->message_data.length());
- CheckFramingBoundaries(packet45, QUIC_INVALID_MESSAGE_DATA);
+ CheckFramingBoundaries(
+ framer_.transport_version() > QUIC_VERSION_46 ? packet47 : packet45,
+ QUIC_INVALID_MESSAGE_DATA);
}
TEST_P(QuicFramerTest, PublicResetPacketV33) {
@@ -5186,6 +5925,19 @@
0x00, 0x00, 0x00, 0x00
};
+ unsigned char packet47[kMaxPacketSize] = {
+ // type (short header, 4 byte packet number)
+ 0x43,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // frame type (padding frame)
+ 0x00,
+ 0x00, 0x00, 0x00, 0x00
+ };
+
unsigned char packet99[kMaxPacketSize] = {
// type (short header, 4 byte packet number)
0x43,
@@ -5203,6 +5955,8 @@
unsigned char* p = packet;
if (framer_.transport_version() == QUIC_VERSION_99) {
p = packet99;
+ } else if (framer_.transport_version() > QUIC_VERSION_46) {
+ p = packet47;
} else if (framer_.transport_version() > QUIC_VERSION_43) {
p = packet44;
} else if (framer_.transport_version() != QUIC_VERSION_35) {
@@ -5321,6 +6075,33 @@
0x00, 0x00,
};
+ unsigned char packet47[] = {
+ // type (short header, 4 byte packet number)
+ 0x43,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // paddings
+ 0x00, 0x00,
+ // frame type (stream frame with fin)
+ 0xFF,
+ // stream id
+ 0x01, 0x02, 0x03, 0x04,
+ // offset
+ 0x3A, 0x98, 0xFE, 0xDC,
+ 0x32, 0x10, 0x76, 0x54,
+ // data length
+ 0x00, 0x0c,
+ // data
+ 'h', 'e', 'l', 'l',
+ 'o', ' ', 'w', 'o',
+ 'r', 'l', 'd', '!',
+ // paddings
+ 0x00, 0x00,
+ };
+
unsigned char packet99[] = {
// type (short header, 4 byte packet number)
0x43,
@@ -5331,8 +6112,8 @@
// paddings
0x00, 0x00,
- // frame type (stream frame with FIN, LEN, and OFFSET bits set)
- 0x10 | 0x01 | 0x02 | 0x04,
+ // frame type (IETF_STREAM with FIN, LEN, and OFFSET bits set)
+ 0x08 | 0x01 | 0x02 | 0x04,
// stream id
kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04,
// offset
@@ -5357,6 +6138,9 @@
if (framer_.transport_version() == QUIC_VERSION_99) {
p = packet99;
p_size = QUIC_ARRAYSIZE(packet99);
+ } else if (framer_.transport_version() > QUIC_VERSION_46) {
+ p = packet47;
+ p_size = QUIC_ARRAYSIZE(packet47);
} else if (framer_.transport_version() > QUIC_VERSION_43) {
p = packet44;
p_size = QUIC_ARRAYSIZE(packet44);
@@ -5419,6 +6203,19 @@
0x00, 0x00, 0x00, 0x00
};
+ unsigned char packet47[kMaxPacketSize] = {
+ // type (short header, 4 byte packet number)
+ 0x43,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // frame type (padding frame)
+ 0x00,
+ 0x00, 0x00, 0x00, 0x00
+ };
+
unsigned char packet99[kMaxPacketSize] = {
// type (short header, 4 byte packet number)
0x43,
@@ -5436,6 +6233,8 @@
unsigned char* p = packet;
if (framer_.transport_version() == QUIC_VERSION_99) {
p = packet99;
+ } else if (framer_.transport_version() > QUIC_VERSION_46) {
+ p = packet47;
} else if (framer_.transport_version() > QUIC_VERSION_43) {
p = packet44;
} else if (framer_.transport_version() != QUIC_VERSION_35) {
@@ -5507,6 +6306,19 @@
0x00, 0x00, 0x00, 0x00
};
+ unsigned char packet47[kMaxPacketSize] = {
+ // type (short header, 2 byte packet number)
+ 0x41,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x56, 0x78,
+
+ // frame type (padding frame)
+ 0x00,
+ 0x00, 0x00, 0x00, 0x00
+ };
+
unsigned char packet99[kMaxPacketSize] = {
// type (short header, 2 byte packet number)
0x41,
@@ -5524,6 +6336,8 @@
unsigned char* p = packet;
if (framer_.transport_version() == QUIC_VERSION_99) {
p = packet99;
+ } else if (framer_.transport_version() > QUIC_VERSION_46) {
+ p = packet47;
} else if (framer_.transport_version() > QUIC_VERSION_43) {
p = packet44;
} else if (framer_.transport_version() != QUIC_VERSION_35) {
@@ -5582,6 +6396,19 @@
0x00, 0x00, 0x00, 0x00
};
+ unsigned char packet47[kMaxPacketSize] = {
+ // type (short header, 1 byte packet number)
+ 0x40,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x78,
+
+ // frame type (padding frame)
+ 0x00,
+ 0x00, 0x00, 0x00, 0x00
+ };
+
unsigned char packet99[kMaxPacketSize] = {
// type (short header, 1 byte packet number)
0x40,
@@ -5599,6 +6426,8 @@
unsigned char* p = packet;
if (framer_.transport_version() == QUIC_VERSION_99) {
p = packet99;
+ } else if (framer_.transport_version() > QUIC_VERSION_46) {
+ p = packet47;
} else if (framer_.transport_version() > QUIC_VERSION_43) {
p = packet44;
}
@@ -5694,6 +6523,27 @@
'r', 'l', 'd', '!',
};
+ unsigned char packet47[] = {
+ // type (short header, 4 byte packet number)
+ 0x43,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // frame type (stream frame with fin and no length)
+ 0xDF,
+ // stream id
+ 0x01, 0x02, 0x03, 0x04,
+ // offset
+ 0x3A, 0x98, 0xFE, 0xDC,
+ 0x32, 0x10, 0x76, 0x54,
+ // data
+ 'h', 'e', 'l', 'l',
+ 'o', ' ', 'w', 'o',
+ 'r', 'l', 'd', '!',
+ };
+
unsigned char packet99[] = {
// type (short header, 4 byte packet number)
0x43,
@@ -5702,8 +6552,8 @@
// packet number
0x12, 0x34, 0x56, 0x78,
- // frame type (stream frame with FIN and OFFSET, no length)
- 0x10 | 0x01 | 0x04,
+ // frame type (IETF_STREAM frame with FIN and OFFSET, no length)
+ 0x08 | 0x01 | 0x04,
// stream id
kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04,
// offset
@@ -5724,6 +6574,9 @@
if (framer_.transport_version() == QUIC_VERSION_99) {
p = packet99;
p_size = QUIC_ARRAYSIZE(packet99);
+ } else if (framer_.transport_version() > QUIC_VERSION_46) {
+ p = packet47;
+ p_size = QUIC_ARRAYSIZE(packet47);
} else if (framer_.transport_version() > QUIC_VERSION_43) {
p = packet44;
p_size = QUIC_ARRAYSIZE(packet44);
@@ -5811,6 +6664,28 @@
'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '!',
};
+ unsigned char packet47[] = {
+ // type (long header with packet type ZERO_RTT_PROTECTED)
+ 0xD3,
+ // version tag
+ QUIC_VERSION_BYTES,
+ // connection_id length
+ 0x50,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // frame type (stream frame with fin and no length)
+ 0xDF,
+ // stream id
+ 0x01, 0x02, 0x03, 0x04,
+ // offset
+ 0x3A, 0x98, 0xFE, 0xDC, 0x32, 0x10, 0x76, 0x54,
+ // data
+ 'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '!',
+ };
+
unsigned char packet99[] = {
// type (long header with packet type ZERO_RTT_PROTECTED)
0xD3,
@@ -5823,8 +6698,8 @@
// packet number
0x12, 0x34, 0x56, 0x78,
- // frame type (stream frame with fin and offset, no length)
- 0x10 | 0x01 | 0x04,
+ // frame type (IETF_STREAM frame with fin and offset, no length)
+ 0x08 | 0x01 | 0x04,
// stream id
kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04,
// offset
@@ -5843,6 +6718,9 @@
if (framer_.transport_version() == QUIC_VERSION_99) {
p = packet99;
p_size = QUIC_ARRAYSIZE(packet99);
+ } else if (framer_.transport_version() > QUIC_VERSION_46) {
+ p = packet47;
+ p_size = QUIC_ARRAYSIZE(packet47);
} else if (framer_.transport_version() > QUIC_VERSION_43) {
p = packet44;
p_size = QUIC_ARRAYSIZE(packet44);
@@ -5853,6 +6731,112 @@
data->length(), AsChars(p), p_size);
}
+TEST_P(QuicFramerTest, BuildCryptoFramePacket) {
+ if (framer_.transport_version() < QUIC_VERSION_99) {
+ // CRYPTO frames aren't supported prior to v46.
+ return;
+ }
+ QuicPacketHeader header;
+ header.destination_connection_id = FramerTestConnectionId();
+ header.reset_flag = false;
+ header.version_flag = false;
+ header.packet_number = kPacketNumber;
+
+ SimpleDataProducer data_producer;
+ framer_.set_data_producer(&data_producer);
+
+ QuicStringPiece crypto_frame_contents("hello world!");
+ QuicCryptoFrame crypto_frame(ENCRYPTION_NONE, kStreamOffset,
+ crypto_frame_contents.length());
+ data_producer.SaveCryptoData(ENCRYPTION_NONE, kStreamOffset,
+ crypto_frame_contents);
+
+ QuicFrames frames = {QuicFrame(&crypto_frame)};
+
+ // clang-format off
+ unsigned char packet[] = {
+ // type (short header, 4 byte packet number)
+ 0x43,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // frame type (IETF_CRYPTO frame)
+ 0x06,
+ // offset
+ kVarInt62EightBytes + 0x3A, 0x98, 0xFE, 0xDC,
+ 0x32, 0x10, 0x76, 0x54,
+ // length
+ kVarInt62OneByte + 12,
+ // data
+ 'h', 'e', 'l', 'l',
+ 'o', ' ', 'w', 'o',
+ 'r', 'l', 'd', '!',
+ };
+ // clang-format on
+
+ size_t packet_size = QUIC_ARRAYSIZE(packet);
+
+ std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
+ ASSERT_TRUE(data != nullptr);
+ test::CompareCharArraysWithHexError("constructed packet", data->data(),
+ data->length(), AsChars(packet),
+ packet_size);
+}
+
+TEST_P(QuicFramerTest, CryptoFrame) {
+ if (framer_.transport_version() < QUIC_VERSION_99) {
+ // CRYPTO frames aren't supported prior to v46.
+ return;
+ }
+
+ // clang-format off
+ PacketFragments packet = {
+ // type (short header, 4 byte packet number)
+ {"",
+ {0x43}},
+ // connection_id
+ {"",
+ {0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
+ // packet number
+ {"",
+ {0x12, 0x34, 0x56, 0x78}},
+ // frame type (IETF_CRYPTO frame)
+ {"",
+ {0x06}},
+ // offset
+ {"",
+ {kVarInt62EightBytes + 0x3A, 0x98, 0xFE, 0xDC,
+ 0x32, 0x10, 0x76, 0x54}},
+ // data length
+ {"Invalid data length.",
+ {kVarInt62OneByte + 12}},
+ // data
+ {"Unable to read frame data.",
+ {'h', 'e', 'l', 'l',
+ 'o', ' ', 'w', 'o',
+ 'r', 'l', 'd', '!'}},
+ };
+ // clang-format on
+
+ std::unique_ptr<QuicEncryptedPacket> encrypted(
+ AssemblePacketFromFragments(packet));
+ EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
+
+ EXPECT_EQ(QUIC_NO_ERROR, framer_.error());
+ ASSERT_TRUE(visitor_.header_.get());
+ EXPECT_TRUE(CheckDecryption(
+ *encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
+ PACKET_8BYTE_CONNECTION_ID, PACKET_0BYTE_CONNECTION_ID));
+ ASSERT_EQ(1u, visitor_.crypto_frames_.size());
+ QuicCryptoFrame* frame = visitor_.crypto_frames_[0].get();
+ EXPECT_EQ(kStreamOffset, frame->offset);
+ EXPECT_EQ("hello world!", QuicString(frame->data_buffer, frame->data_length));
+
+ CheckFramingBoundaries(packet, QUIC_INVALID_FRAME_DATA);
+}
+
TEST_P(QuicFramerTest, BuildVersionNegotiationPacket) {
// clang-format off
unsigned char packet[] = {
@@ -5969,7 +6953,7 @@
0x00,
};
- unsigned char packet99[] = {
+ unsigned char packet47[] = {
// type (short header, 4 byte packet number)
0x43,
// connection_id
@@ -5978,7 +6962,28 @@
0x12, 0x34, 0x56, 0x78,
// frame type (ack frame)
- 0x1a,
+ // (no ack blocks, 2 byte largest observed, 2 byte block length)
+ 0x45,
+ // largest acked
+ 0x12, 0x34,
+ // Zero delta time.
+ 0x00, 0x00,
+ // first ack block length.
+ 0x12, 0x34,
+ // num timestamps.
+ 0x00,
+ };
+
+ unsigned char packet99[] = {
+ // type (short header, 4 byte packet number)
+ 0x43,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // frame type (IETF_ACK frame)
+ 0x02,
// largest acked
kVarInt62TwoBytes + 0x12, 0x34,
// Zero delta time.
@@ -5994,6 +6999,9 @@
if (framer_.transport_version() == QUIC_VERSION_99) {
p = packet99;
p_size = QUIC_ARRAYSIZE(packet99);
+ } else if (framer_.transport_version() > QUIC_VERSION_46) {
+ p = packet47;
+ p_size = QUIC_ARRAYSIZE(packet47);
} else if (framer_.transport_version() > QUIC_VERSION_43) {
p = packet44;
p_size = QUIC_ARRAYSIZE(packet44);
@@ -6083,6 +7091,27 @@
0x00,
};
+ unsigned char packet47[] = {
+ // type (short header, 4 byte packet number)
+ 0x43,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // frame type (ack frame)
+ // (no ack blocks, 4 byte largest observed, 4 byte block length)
+ 0x4A,
+ // largest acked
+ 0x12, 0x34, 0x56, 0x78,
+ // Zero delta time.
+ 0x00, 0x00,
+ // first ack block length.
+ 0x12, 0x34, 0x56, 0x78,
+ // num timestamps.
+ 0x00,
+ };
+
unsigned char packet99[] = {
// type (short header, 4 byte packet number)
@@ -6092,8 +7121,8 @@
// packet number
0x12, 0x34, 0x56, 0x78,
- // frame type (ack frame)
- 0x1a,
+ // frame type (IETF_ACK frame)
+ 0x02,
// largest acked
kVarInt62FourBytes + 0x12, 0x34, 0x56, 0x78,
// Zero delta time.
@@ -6109,6 +7138,9 @@
if (framer_.transport_version() == QUIC_VERSION_99) {
p = packet99;
p_size = QUIC_ARRAYSIZE(packet99);
+ } else if (framer_.transport_version() > QUIC_VERSION_46) {
+ p = packet47;
+ p_size = QUIC_ARRAYSIZE(packet47);
} else if (framer_.transport_version() > QUIC_VERSION_43) {
p = packet44;
p_size = QUIC_ARRAYSIZE(packet44);
@@ -6131,9 +7163,9 @@
// Use kSmallLargestObserved to make this test finished in a short time.
QuicAckFrame ack_frame =
- InitAckFrame({{1, 5},
- {10, 500},
- {900, kSmallMissingPacket},
+ InitAckFrame({{QuicPacketNumber(1), QuicPacketNumber(5)},
+ {QuicPacketNumber(10), QuicPacketNumber(500)},
+ {QuicPacketNumber(900), kSmallMissingPacket},
{kSmallMissingPacket + 1, kSmallLargestObserved + 1}});
ack_frame.ack_delay_time = QuicTime::Delta::Zero();
@@ -6257,7 +7289,7 @@
0x00,
};
- unsigned char packet99[] = {
+ unsigned char packet47[] = {
// type (short header, 4 byte packet number)
0x43,
// connection_id
@@ -6266,7 +7298,46 @@
0x12, 0x34, 0x56, 0x78,
// frame type (ack frame)
- 0x1a,
+ // (has ack blocks, 2 byte largest observed, 2 byte block length)
+ 0x65,
+ // largest acked
+ 0x12, 0x34,
+ // Zero delta time.
+ 0x00, 0x00,
+ // num ack blocks ranges.
+ 0x04,
+ // first ack block length.
+ 0x00, 0x01,
+ // gap to next block.
+ 0x01,
+ // ack block length.
+ 0x0e, 0xaf,
+ // gap to next block.
+ 0xff,
+ // ack block length.
+ 0x00, 0x00,
+ // gap to next block.
+ 0x91,
+ // ack block length.
+ 0x01, 0xea,
+ // gap to next block.
+ 0x05,
+ // ack block length.
+ 0x00, 0x04,
+ // num timestamps.
+ 0x00,
+ };
+
+ unsigned char packet99[] = {
+ // type (short header, 4 byte packet number)
+ 0x43,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // frame type (IETF_ACK frame)
+ 0x02,
// largest acked
kVarInt62TwoBytes + 0x12, 0x34,
// Zero delta time.
@@ -6297,6 +7368,9 @@
if (framer_.transport_version() == QUIC_VERSION_99) {
p = packet99;
p_size = QUIC_ARRAYSIZE(packet99);
+ } else if (framer_.transport_version() > QUIC_VERSION_46) {
+ p = packet47;
+ p_size = QUIC_ARRAYSIZE(packet47);
} else if (framer_.transport_version() > QUIC_VERSION_43) {
p = packet44;
p_size = QUIC_ARRAYSIZE(packet44);
@@ -6324,9 +7398,9 @@
ack_frame.ack_delay_time = QuicTime::Delta::Zero();
// 300 ack blocks.
for (size_t i = 2; i < 2 * 300; i += 2) {
- ack_frame.packets.Add(i);
+ ack_frame.packets.Add(QuicPacketNumber(i));
}
- ack_frame.packets.AddRange(600, kSmallLargestObserved + 1);
+ ack_frame.packets.AddRange(QuicPacketNumber(600), kSmallLargestObserved + 1);
QuicFrames frames = {QuicFrame(&ack_frame)};
@@ -6610,7 +7684,7 @@
0x00,
};
- unsigned char packet99[] = {
+ unsigned char packet47[] = {
// type (short header, 4 byte packet number)
0x43,
// connection_id
@@ -6618,7 +7692,100 @@
// packet number
0x12, 0x34, 0x56, 0x78,
// frame type (ack frame)
- 0x1a,
+ // (has ack blocks, 2 byte largest observed, 2 byte block length)
+ 0x65,
+ // largest acked
+ 0x12, 0x34,
+ // Zero delta time.
+ 0x00, 0x00,
+ // num ack blocks ranges.
+ 0xff,
+ // first ack block length.
+ 0x0f, 0xdd,
+ // 255 = 4 * 63 + 3
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01,
+ // num timestamps.
+ 0x00,
+ };
+
+ unsigned char packet99[] = {
+ // type (short header, 4 byte packet number)
+ 0x43,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+ // frame type (IETF_ACK frame)
+ 0x02,
// largest acked
kVarInt62TwoBytes + 0x12, 0x34,
// Zero delta time.
@@ -6700,6 +7867,9 @@
if (framer_.transport_version() == QUIC_VERSION_99) {
p = packet99;
p_size = QUIC_ARRAYSIZE(packet99);
+ } else if (framer_.transport_version() > QUIC_VERSION_46) {
+ p = packet47;
+ p_size = QUIC_ARRAYSIZE(packet47);
} else if (framer_.transport_version() > QUIC_VERSION_43) {
p = packet44;
p_size = QUIC_ARRAYSIZE(packet44);
@@ -6848,7 +8018,7 @@
0x05, 0x06, 0x07, 0x08,
};
- unsigned char packet99[] = {
+ unsigned char packet47[] = {
// type (short packet, 4 byte packet number)
0x43,
// connection_id
@@ -6859,6 +8029,25 @@
// frame type (rst stream frame)
0x01,
// stream id
+ 0x01, 0x02, 0x03, 0x04,
+ // sent byte offset
+ 0x08, 0x07, 0x06, 0x05,
+ 0x04, 0x03, 0x02, 0x01,
+ // error code
+ 0x05, 0x06, 0x07, 0x08,
+ };
+
+ unsigned char packet99[] = {
+ // type (short packet, 4 byte packet number)
+ 0x43,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // frame type (IETF_RST_STREAM frame)
+ 0x04,
+ // stream id
kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04,
// error code (not VarInt32 encoded)
0x00, 0x01,
@@ -6877,6 +8066,9 @@
if (framer_.transport_version() == QUIC_VERSION_99) {
p = packet99;
p_size = QUIC_ARRAYSIZE(packet99);
+ } else if (framer_.transport_version() > QUIC_VERSION_46) {
+ p = packet47;
+ p_size = QUIC_ARRAYSIZE(packet47);
} else if (framer_.transport_version() > QUIC_VERSION_43) {
p = packet44;
p_size = QUIC_ARRAYSIZE(packet44);
@@ -6972,7 +8164,7 @@
'n',
};
- unsigned char packet99[] = {
+ unsigned char packet47[] = {
// type (short header, 4 byte packet number)
0x43,
// connection_id
@@ -6983,6 +8175,27 @@
// frame type (connection close frame)
0x02,
// error code
+ 0x05, 0x06, 0x07, 0x08,
+ // error details length
+ 0x00, 0x0d,
+ // error details
+ 'b', 'e', 'c', 'a',
+ 'u', 's', 'e', ' ',
+ 'I', ' ', 'c', 'a',
+ 'n',
+ };
+
+ unsigned char packet99[] = {
+ // type (short header, 4 byte packet number)
+ 0x43,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // frame type (IETF_CONNECTION_CLOSE frame)
+ 0x1c,
+ // error code
0x00, 0x11,
// Frame type within the CONNECTION_CLOSE frame
kVarInt62OneByte + 0x05,
@@ -7001,6 +8214,9 @@
if (framer_.transport_version() == QUIC_VERSION_99) {
p = packet99;
p_size = QUIC_ARRAYSIZE(packet99);
+ } else if (framer_.transport_version() > QUIC_VERSION_46) {
+ p = packet47;
+ p_size = QUIC_ARRAYSIZE(packet47);
} else if (framer_.transport_version() > QUIC_VERSION_43) {
p = packet44;
p_size = QUIC_ARRAYSIZE(packet44);
@@ -7180,7 +8396,7 @@
'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
};
- unsigned char packet99[] = {
+ unsigned char packet47[] = {
// type (short header, 4 byte packet number)
0x43,
// connection_id
@@ -7191,6 +8407,55 @@
// frame type (connection close frame)
0x02,
// error code
+ 0x05, 0x06, 0x07, 0x08,
+ // error details length
+ 0x01, 0x00,
+ // error details (truncated to 256 bytes)
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ };
+
+ unsigned char packet99[] = {
+ // type (short header, 4 byte packet number)
+ 0x43,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // frame type (IETF_CONNECTION_CLOSE frame)
+ 0x1c,
+ // error code
0x00, 0x0a,
// Frame type within the CONNECTION_CLOSE frame
kVarInt62OneByte + 0x00,
@@ -7237,6 +8502,9 @@
if (framer_.transport_version() == QUIC_VERSION_99) {
p = packet99;
p_size = QUIC_ARRAYSIZE(packet99);
+ } else if (framer_.transport_version() > QUIC_VERSION_46) {
+ p = packet47;
+ p_size = QUIC_ARRAYSIZE(packet47);
} else if (framer_.transport_version() > QUIC_VERSION_43) {
p = packet44;
p_size = QUIC_ARRAYSIZE(packet44);
@@ -7278,8 +8546,8 @@
// packet number
0x12, 0x34, 0x56, 0x78,
- // frame type (application close frame)
- 0x03,
+ // frame type (IETF_APPLICATION_CLOSE frame)
+ 0x1d,
// error code
0x00, 0x11,
// error details length
@@ -7326,8 +8594,8 @@
// packet number
0x12, 0x34, 0x56, 0x78,
- // frame type
- 0x03,
+ // frame type (IETF_APPLICATION_CLOSE frame)
+ 0x1d,
// error code
0x00, 0x11,
// error details length
@@ -7464,11 +8732,37 @@
'n',
};
+ unsigned char packet47[] = {
+ // type (short header, 4 byte packet number)
+ 0x43,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // frame type (go away frame)
+ 0x03,
+ // error code
+ 0x05, 0x06, 0x07, 0x08,
+ // stream id
+ 0x01, 0x02, 0x03, 0x04,
+ // error details length
+ 0x00, 0x0d,
+ // error details
+ 'b', 'e', 'c', 'a',
+ 'u', 's', 'e', ' ',
+ 'I', ' ', 'c', 'a',
+ 'n',
+ };
+
// clang-format on
unsigned char* p = packet;
size_t p_size = QUIC_ARRAYSIZE(packet);
- if (framer_.transport_version() > QUIC_VERSION_43) {
+ if (framer_.transport_version() > QUIC_VERSION_46) {
+ p = packet47;
+ p_size = QUIC_ARRAYSIZE(packet47);
+ } else if (framer_.transport_version() > QUIC_VERSION_43) {
p = packet44;
p_size = QUIC_ARRAYSIZE(packet44);
} else if (framer_.transport_version() != QUIC_VERSION_35) {
@@ -7653,11 +8947,65 @@
'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
};
+
+ unsigned char packet47[] = {
+ // type (short header, 4 byte packet number)
+ 0x43,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // frame type (go away frame)
+ 0x03,
+ // error code
+ 0x05, 0x06, 0x07, 0x08,
+ // stream id
+ 0x01, 0x02, 0x03, 0x04,
+ // error details length
+ 0x01, 0x00,
+ // error details (truncated to 256 bytes)
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ };
// clang-format on
unsigned char* p = packet;
size_t p_size = QUIC_ARRAYSIZE(packet);
- if (framer_.transport_version() > QUIC_VERSION_43) {
+ if (framer_.transport_version() > QUIC_VERSION_46) {
+ p = packet47;
+ p_size = QUIC_ARRAYSIZE(packet47);
+ } else if (framer_.transport_version() > QUIC_VERSION_43) {
p = packet44;
p_size = QUIC_ARRAYSIZE(packet44);
} else if (framer_.transport_version() != QUIC_VERSION_35) {
@@ -7736,6 +9084,23 @@
0x55, 0x66, 0x77, 0x88,
};
+ unsigned char packet47[] = {
+ // type (short header, 4 byte packet number)
+ 0x43,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // frame type (window update frame)
+ 0x04,
+ // stream id
+ 0x01, 0x02, 0x03, 0x04,
+ // byte offset
+ 0x11, 0x22, 0x33, 0x44,
+ 0x55, 0x66, 0x77, 0x88,
+ };
+
unsigned char packet99[] = {
// type (short header, 4 byte packet number)
0x43,
@@ -7744,8 +9109,8 @@
// packet number
0x12, 0x34, 0x56, 0x78,
- // frame type (max stream data frame)
- 0x05,
+ // frame type (IETF_MAX_STREAM_DATA frame)
+ 0x11,
// stream id
kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04,
// byte offset
@@ -7762,6 +9127,9 @@
if (framer_.transport_version() == QUIC_VERSION_99) {
p = packet99;
p_size = QUIC_ARRAYSIZE(packet99);
+ } else if (framer_.transport_version() > QUIC_VERSION_46) {
+ p = packet47;
+ p_size = QUIC_ARRAYSIZE(packet47);
} else if (framer_.transport_version() > QUIC_VERSION_43) {
p = packet44;
p_size = QUIC_ARRAYSIZE(packet44);
@@ -7799,8 +9167,8 @@
// packet number
0x12, 0x34, 0x56, 0x78,
- // frame type (max stream data frame)
- 0x05,
+ // frame type (IETF_MAX_STREAM_DATA frame)
+ 0x11,
// stream id
kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04,
// byte offset
@@ -7843,8 +9211,8 @@
// packet number
0x12, 0x34, 0x56, 0x78,
- // frame type (max data frame)
- 0x04,
+ // frame type (IETF_MAX_DATA frame)
+ 0x10,
// byte offset
kVarInt62EightBytes + 0x11, 0x22, 0x33, 0x44,
0x55, 0x66, 0x77, 0x88,
@@ -7867,7 +9235,16 @@
header.packet_number = kPacketNumber;
QuicBlockedFrame blocked_frame;
- blocked_frame.stream_id = kStreamId;
+ if (framer_.transport_version() == QUIC_VERSION_99) {
+ // For V99, the stream ID must be 0 for the frame
+ // to be a BLOCKED frame. if non-0, it will be a
+ // STREAM_BLOCKED frame.
+ // TODO(fkastenholz): This should be converted to use
+ // QuicUtils::GetInvalidStreamId to get the correct invalid stream id value.
+ blocked_frame.stream_id = 0;
+ } else {
+ blocked_frame.stream_id = kStreamId;
+ }
blocked_frame.offset = kStreamOffset;
QuicFrames frames = {QuicFrame(&blocked_frame)};
@@ -7915,6 +9292,20 @@
0x01, 0x02, 0x03, 0x04,
};
+ unsigned char packet47[] = {
+ // type (short packet, 4 byte packet number)
+ 0x43,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // frame type (blocked frame)
+ 0x05,
+ // stream id
+ 0x01, 0x02, 0x03, 0x04,
+ };
+
unsigned char packet99[] = {
// type (short packet, 4 byte packet number)
0x43,
@@ -7923,10 +9314,8 @@
// packet number
0x12, 0x34, 0x56, 0x78,
- // frame type
- 0x09,
- // stream id
- kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04,
+ // frame type (IETF_BLOCKED frame) wahoo
+ 0x14,
// Offset
kVarInt62EightBytes + 0x3a, 0x98, 0xFE, 0xDC, 0x32, 0x10, 0x76, 0x54
};
@@ -7940,6 +9329,9 @@
if (framer_.transport_version() == QUIC_VERSION_99) {
p = packet99;
p_size = QUIC_ARRAYSIZE(packet99);
+ } else if (framer_.transport_version() > QUIC_VERSION_46) {
+ p = packet47;
+ p_size = QUIC_ARRAYSIZE(packet47);
} else if (framer_.transport_version() > QUIC_VERSION_43) {
p = packet44;
p_size = QUIC_ARRAYSIZE(packet44);
@@ -7997,7 +9389,7 @@
0x07,
};
- unsigned char packet99[] = {
+ unsigned char packet47[] = {
// type (short header, 4 byte packet number)
0x43,
// connection_id
@@ -8008,11 +9400,25 @@
// frame type
0x07,
};
+
+ unsigned char packet99[] = {
+ // type (short header, 4 byte packet number)
+ 0x43,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // frame type (IETF_PING frame)
+ 0x01,
+ };
// clang-format on
unsigned char* p = packet;
if (framer_.transport_version() == QUIC_VERSION_99) {
p = packet99;
+ } else if (framer_.transport_version() > QUIC_VERSION_46) {
+ p = packet47;
} else if (framer_.transport_version() > QUIC_VERSION_43) {
p = packet44;
} else if (framer_.transport_version() != QUIC_VERSION_35) {
@@ -8063,7 +9469,7 @@
'm', 'e', 's', 's', 'a', 'g', 'e', '2'
};
- unsigned char packet99[] = {
+ unsigned char packet47[] = {
// type (short header, 4 byte packet number)
0x43,
// connection_id
@@ -8082,11 +9488,33 @@
// Message Data
'm', 'e', 's', 's', 'a', 'g', 'e', '2'
};
+
+ unsigned char packet99[] = {
+ // type (short header, 4 byte packet number)
+ 0x43,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // frame type (IETF_MESSAGE frame)
+ 0x21,
+ // Length
+ 0x07,
+ // Message Data
+ 'm', 'e', 's', 's', 'a', 'g', 'e',
+ // frame type (message frame no length)
+ 0x20,
+ // Message Data
+ 'm', 'e', 's', 's', 'a', 'g', 'e', '2'
+ };
// clang-format on
unsigned char* p = packet45;
if (framer_.transport_version() == QUIC_VERSION_99) {
p = packet99;
+ } else if (framer_.transport_version() > QUIC_VERSION_46) {
+ p = packet47;
}
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
@@ -8152,7 +9580,7 @@
0x00, 0x00, 0x00, 0x00
};
- unsigned char packet99[] = {
+ unsigned char packet47[] = {
// type (short header, 4 byte packet number)
0x43,
// connection_id
@@ -8166,6 +9594,21 @@
0x00,
0x00, 0x00, 0x00, 0x00
};
+
+ unsigned char packet99[] = {
+ // type (short header, 4 byte packet number)
+ 0x43,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // frame type (IETF_PING frame)
+ 0x01,
+ // frame type (padding frame)
+ 0x00,
+ 0x00, 0x00, 0x00, 0x00
+ };
// clang-format on
unsigned char* p = packet;
@@ -8173,6 +9616,9 @@
if (framer_.transport_version() == QUIC_VERSION_99) {
p = packet99;
packet_size = QUIC_ARRAYSIZE(packet99);
+ } else if (framer_.transport_version() > QUIC_VERSION_46) {
+ p = packet47;
+ packet_size = QUIC_ARRAYSIZE(packet47);
} else if (framer_.transport_version() > QUIC_VERSION_43) {
p = packet44;
packet_size = QUIC_ARRAYSIZE(packet44);
@@ -8196,6 +9642,49 @@
data.length(), AsChars(p), packet_size);
}
+// Test that the IETF connectivity probing packet is serialized correctly as a
+// padded PING packet, v99 only.
+TEST_P(QuicFramerTest, BuildIetfConnectivityProbingPacket) {
+ if (framer_.transport_version() != QUIC_VERSION_99) {
+ return;
+ }
+ QuicPacketHeader header;
+ header.destination_connection_id = FramerTestConnectionId();
+ header.reset_flag = false;
+ header.version_flag = false;
+ header.packet_number = kPacketNumber;
+
+ unsigned char packet99[] = {// type (short header, 4 byte packet number)
+ 0x43,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // frame type (IETF_PING frame)
+ 0x01,
+ // frame type (padding frame)
+ 0x00, 0x00, 0x00, 0x00, 0x00};
+ // clang-format on
+
+ unsigned char* p = packet99;
+ size_t packet_size = QUIC_ARRAYSIZE(packet99);
+
+ std::unique_ptr<char[]> buffer(new char[kMaxPacketSize]);
+
+ size_t length = framer_.BuildIetfConnectivityProbingPacket(
+ header, buffer.get(), packet_size);
+
+ EXPECT_NE(0u, length);
+ QuicPacket data(buffer.release(), length, true,
+ header.destination_connection_id_length,
+ header.source_connection_id_length, header.version_flag,
+ header.nonce != nullptr, header.packet_number_length);
+
+ test::CompareCharArraysWithHexError("constructed packet", data.data(),
+ data.length(), AsChars(p), packet_size);
+}
+
// Test that the path challenge connectivity probing packet is serialized
// correctly as a padded PATH CHALLENGE packet.
TEST_P(QuicFramerTest, BuildPaddedPathChallengePacket) {
@@ -8219,8 +9708,8 @@
// packet number
0x12, 0x34, 0x56, 0x78,
- // Path Challenge Frame type
- 0x0e,
+ // Path Challenge Frame type (IETF_PATH_CHALLENGE)
+ 0x1a,
// 8 "random" bytes, MockRandom makes lots of r's
'r', 'r', 'r', 'r', 'r', 'r', 'r', 'r',
// frame type (padding frame)
@@ -8277,8 +9766,8 @@
// packet number
0x12, 0x34, 0x56, 0x78,
- // Path Challenge Frame type
- 0x0f,
+ // Path Response Frame type (IETF_PATH_RESPONSE)
+ 0x1b,
// 8 "random" bytes
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
};
@@ -8323,8 +9812,8 @@
// packet number
0x12, 0x34, 0x56, 0x78,
- // Path Challenge Frame type
- 0x0f,
+ // Path Response Frame type (IETF_PATH_RESPONSE)
+ 0x1b,
// 8 "random" bytes
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
// Padding type and pad
@@ -8375,10 +9864,10 @@
// packet number
0x12, 0x34, 0x56, 0x78,
- // 3 path challenge frames (type byte and payload)
- 0x0f, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
- 0x0f, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
- 0x0f, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
+ // 3 path response frames (IETF_PATH_RESPONSE type byte and payload)
+ 0x1b, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x1b, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+ 0x1b, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
};
// clang-format on
@@ -8428,10 +9917,10 @@
// packet number
0x12, 0x34, 0x56, 0x78,
- // 3 path challenge frames (type byte and payload)
- 0x0f, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
- 0x0f, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
- 0x0f, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
+ // 3 path response frames (IETF_PATH_RESPONSE byte and payload)
+ 0x1b, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+ 0x1b, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
+ 0x1b, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
// Padding
0x00, 0x00, 0x00, 0x00, 0x00
};
@@ -8503,7 +9992,7 @@
0x07,
};
- unsigned char packet99[] = {
+ unsigned char packet47[] = {
// type (short header, 4 byte packet number)
0x43,
// connection_id
@@ -8514,6 +10003,18 @@
// frame type
0x07,
};
+
+ unsigned char packet99[] = {
+ // type (short header, 4 byte packet number)
+ 0x43,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // frame type (IETF_PING frame)
+ 0x01,
+ };
// clang-format on
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
@@ -8522,6 +10023,8 @@
unsigned char* p = packet;
if (framer_.transport_version() == QUIC_VERSION_99) {
p = packet99;
+ } else if (framer_.transport_version() > QUIC_VERSION_46) {
+ p = packet47;
} else if (framer_.transport_version() > QUIC_VERSION_43) {
p = packet44;
} else if (framer_.transport_version() != QUIC_VERSION_35) {
@@ -8784,6 +10287,21 @@
'm', 'n', 'o', 'p',
};
+ unsigned char packet47[] = {
+ // type (short header, 4 byte packet number)
+ 0x43,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // redundancy
+ 'a', 'b', 'c', 'd',
+ 'e', 'f', 'g', 'h',
+ 'i', 'j', 'k', 'l',
+ 'm', 'n', 'o', 'p',
+ };
+
unsigned char packet99[] = {
// type (short header, 4 byte packet number)
0x43,
@@ -8803,6 +10321,8 @@
unsigned char* p = packet;
if (framer_.transport_version() == QUIC_VERSION_99) {
p = packet99;
+ } else if (framer_.transport_version() > QUIC_VERSION_46) {
+ p = packet47;
} else if (framer_.transport_version() > QUIC_VERSION_43) {
p = packet44;
} else if (framer_.transport_version() != QUIC_VERSION_35) {
@@ -8877,6 +10397,25 @@
'm', 'n', 'o', 'p',
};
+ unsigned char packet47[] = {
+ // type (long header with packet type ZERO_RTT_PROTECTED)
+ 0xD3,
+ // version tag
+ 'Q', '.', '1', '0',
+ // connection_id length
+ 0x50,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // redundancy
+ 'a', 'b', 'c', 'd',
+ 'e', 'f', 'g', 'h',
+ 'i', 'j', 'k', 'l',
+ 'm', 'n', 'o', 'p',
+ };
+
unsigned char packet99[] = {
// type (long header with packet type ZERO_RTT_PROTECTED)
0xD3,
@@ -8900,6 +10439,8 @@
unsigned char* p = packet;
if (framer_.transport_version() == QUIC_VERSION_99) {
p = packet99;
+ } else if (framer_.transport_version() > QUIC_VERSION_46) {
+ p = packet47;
} else if (framer_.transport_version() > QUIC_VERSION_43) {
p = packet44;
} else if (framer_.transport_version() != QUIC_VERSION_35) {
@@ -8954,10 +10495,10 @@
QuicEncryptedPacket(buffer, encrypted_length, false)));
ASSERT_EQ(1u, visitor_.ack_frames_.size());
QuicAckFrame& processed_ack_frame = *visitor_.ack_frames_[0];
- EXPECT_EQ(600u, LargestAcked(processed_ack_frame));
+ EXPECT_EQ(QuicPacketNumber(600u), LargestAcked(processed_ack_frame));
ASSERT_EQ(256u, processed_ack_frame.packets.NumPacketsSlow());
- EXPECT_EQ(90u, processed_ack_frame.packets.Min());
- EXPECT_EQ(600u, processed_ack_frame.packets.Max());
+ EXPECT_EQ(QuicPacketNumber(90u), processed_ack_frame.packets.Min());
+ EXPECT_EQ(QuicPacketNumber(600u), processed_ack_frame.packets.Max());
}
TEST_P(QuicFramerTest, AckTruncationSmallPacket) {
@@ -8994,10 +10535,10 @@
QuicEncryptedPacket(buffer, encrypted_length, false)));
ASSERT_EQ(1u, visitor_.ack_frames_.size());
QuicAckFrame& processed_ack_frame = *visitor_.ack_frames_[0];
- EXPECT_EQ(600u, LargestAcked(processed_ack_frame));
+ EXPECT_EQ(QuicPacketNumber(600u), LargestAcked(processed_ack_frame));
ASSERT_EQ(240u, processed_ack_frame.packets.NumPacketsSlow());
- EXPECT_EQ(122u, processed_ack_frame.packets.Min());
- EXPECT_EQ(600u, processed_ack_frame.packets.Max());
+ EXPECT_EQ(QuicPacketNumber(122u), processed_ack_frame.packets.Min());
+ EXPECT_EQ(QuicPacketNumber(600u), processed_ack_frame.packets.Max());
}
TEST_P(QuicFramerTest, CleanTruncation) {
@@ -9158,6 +10699,43 @@
0x9A, 0xBE,
};
+ unsigned char packet47[] = {
+ // type (short header, 4 byte packet number)
+ 0x43,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // frame type (stream frame with fin)
+ 0xFF,
+ // stream id
+ 0x01, 0x02, 0x03, 0x04,
+ // offset
+ 0x3A, 0x98, 0xFE, 0xDC,
+ 0x32, 0x10, 0x76, 0x54,
+ // data length
+ 0x00, 0x0c,
+ // data
+ 'h', 'e', 'l', 'l',
+ 'o', ' ', 'w', 'o',
+ 'r', 'l', 'd', '!',
+
+ // frame type (ack frame)
+ 0x40,
+ // least packet number awaiting an ack
+ 0x12, 0x34, 0x56, 0x78,
+ 0x9A, 0xA0,
+ // largest observed packet number
+ 0x12, 0x34, 0x56, 0x78,
+ 0x9A, 0xBF,
+ // num missing packets
+ 0x01,
+ // missing packet
+ 0x12, 0x34, 0x56, 0x78,
+ 0x9A, 0xBE,
+ };
+
unsigned char packet99[] = {
// type (short header, 4 byte packet number)
0x43,
@@ -9166,8 +10744,8 @@
// packet number
0x12, 0x34, 0x56, 0x78,
- // frame type (stream frame with fin, length, and offset bits set)
- 0x10 | 0x01 | 0x02 | 0x04,
+ // frame type (IETF_STREAM frame with fin, length, and offset bits set)
+ 0x08 | 0x01 | 0x02 | 0x04,
// stream id
kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04,
// offset
@@ -9212,6 +10790,9 @@
if (framer_.transport_version() == QUIC_VERSION_99) {
p = packet99;
p_size = QUIC_ARRAYSIZE(packet99);
+ } else if (framer_.transport_version() > QUIC_VERSION_46) {
+ p = packet47;
+ p_size = QUIC_ARRAYSIZE(packet47);
} else if (framer_.transport_version() > QUIC_VERSION_43) {
p = packet44;
p_size = QUIC_ARRAYSIZE(packet44);
@@ -9411,7 +10992,7 @@
'r', 'l', 'd', '!',
};
- unsigned char packet99[] = {
+ unsigned char packet47[] = {
// type (short header, 4 byte packet number)
0x43,
// packet number
@@ -9431,11 +11012,34 @@
'o', ' ', 'w', 'o',
'r', 'l', 'd', '!',
};
+
+ unsigned char packet99[] = {
+ // type (short header, 4 byte packet number)
+ 0x43,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // frame type (IETF_STREAM frame with fin, length, and offset bits set)
+ 0x08 | 0x01 | 0x02 | 0x04,
+ // stream id
+ 0x01, 0x02, 0x03, 0x04,
+ // offset
+ 0x3A, 0x98, 0xFE, 0xDC,
+ 0x32, 0x10, 0x76, 0x54,
+ // data length
+ 0x00, 0x0c,
+ // data
+ 'h', 'e', 'l', 'l',
+ 'o', ' ', 'w', 'o',
+ 'r', 'l', 'd', '!',
+ };
// clang-format on
unsigned char* p = packet;
if (framer_.transport_version() == QUIC_VERSION_99) {
p = packet99;
+ } else if (framer_.transport_version() > QUIC_VERSION_46) {
+ p = packet47;
} else if (framer_.transport_version() > QUIC_VERSION_43) {
p = packet44;
} else if (framer_.transport_version() != QUIC_VERSION_35) {
@@ -9457,7 +11061,7 @@
iovec.iov_len = data.length();
producer.SaveStreamData(
QuicUtils::GetCryptoStreamId(framer_.transport_version()), &iovec, 1, 0,
- 0, data.length());
+ data.length());
for (size_t offset = 0; offset < 5; ++offset) {
if (offset == 0 || offset == 4) {
EXPECT_TRUE(framer_.StartsWithChlo(
@@ -9486,9 +11090,9 @@
// packet number
{"",
{0x12, 0x34, 0x9A, 0xBC}},
- // frame type (blocked)
+ // frame type (IETF_BLOCKED)
{"",
- {0x08}},
+ {0x14}},
// blocked offset
{"Can not read blocked offset.",
{kVarInt62EightBytes + 0x3a, 0x98, 0xFE, 0xDC, 0x32, 0x10, 0x76, 0x54}},
@@ -9536,8 +11140,8 @@
// packet number
0x12, 0x34, 0x56, 0x78,
- // frame type (blocked)
- 0x08,
+ // frame type (IETF_BLOCKED)
+ 0x14,
// Offset
kVarInt62EightBytes + 0x3a, 0x98, 0xFE, 0xDC, 0x32, 0x10, 0x76, 0x54
};
@@ -9568,9 +11172,9 @@
// packet number
{"",
{0x12, 0x34, 0x9A, 0xBC}},
- // frame type (blocked)
+ // frame type (IETF_STREAM_BLOCKED)
{"",
- {0x09}},
+ {0x15}},
// blocked offset
{"Can not read stream blocked stream id.",
{kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04}},
@@ -9621,8 +11225,8 @@
// packet number
0x12, 0x34, 0x56, 0x78,
- // frame type (blocked)
- 0x09,
+ // frame type (IETF_STREAM_BLOCKED)
+ 0x15,
// Stream ID
kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04,
// Offset
@@ -9655,9 +11259,9 @@
// packet number
{"",
{0x12, 0x34, 0x9A, 0xBC}},
- // frame type (max stream id)
+ // frame type (IETF_MAX_STREAM_ID)
{"",
- {0x06}},
+ {0x12}},
// max. stream id
{"Can not read MAX_STREAM_ID stream id.",
{kVarInt62OneByte + 0x01}},
@@ -9704,8 +11308,8 @@
// packet number
0x12, 0x34, 0x56, 0x78,
- // frame type (max stream id frame)
- 0x06,
+ // frame type (IETF_MAX_STREAM_ID frame)
+ 0x12,
// Max stream id
kVarInt62OneByte + 0x01
};
@@ -9736,9 +11340,9 @@
// packet number
{"",
{0x12, 0x34, 0x9A, 0xBC}},
- // frame type (stream id blocked)
+ // frame type (IETF_STREAM_ID_BLOCKED frame)
{"",
- {0x0a}},
+ {0x16}},
// stream id
{"Can not read STREAM_ID_BLOCKED stream id.",
{kVarInt62OneByte + 0x01}},
@@ -9785,8 +11389,8 @@
// packet number
0x12, 0x34, 0x56, 0x78,
- // frame type (stream id blocked frame)
- 0x0a,
+ // frame type (IETF_STREAM_ID_BLOCKED frame)
+ 0x16,
// Max stream id
kVarInt62OneByte + 0x01
};
@@ -9816,9 +11420,9 @@
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
- // frame type (new connection id frame)
+ // frame type (IETF_NEW_CONNECTION_ID frame)
{"",
- {0x0b}},
+ {0x18}},
// error code
{"Unable to read new connection ID frame sequence number.",
{kVarInt62OneByte + 0x11}},
@@ -9884,8 +11488,8 @@
// packet number
0x12, 0x34, 0x56, 0x78,
- // frame type (new connection id frame)
- 0x0b,
+ // frame type (IETF_NEW_CONNECTION_ID frame)
+ 0x18,
// sequence number
kVarInt62OneByte + 0x11,
// new connection id length
@@ -9922,9 +11526,9 @@
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
- // frame type (new token frame)
+ // frame type (IETF_NEW_TOKEN frame)
{"",
- {0x19}},
+ {0x07}},
// Length
{"Unable to read new token length.",
{kVarInt62OneByte + 0x08}},
@@ -9982,8 +11586,8 @@
// packet number
0x12, 0x34, 0x56, 0x78,
- // frame type (new token frame)
- 0x19,
+ // frame type (IETF_NEW_TOKEN frame)
+ 0x07,
// Length and token
kVarInt62OneByte + 0x08,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
@@ -10015,9 +11619,9 @@
// packet number
{"",
{0x12, 0x34, 0x9A, 0xBC}},
- // frame type (stop sending)
+ // frame type (IETF_STOP_SENDING frame)
{"",
- {0x0c}},
+ {0x05}},
// stream id
{"Unable to read stop sending stream id.",
{kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04}},
@@ -10068,8 +11672,8 @@
// packet number
0x12, 0x34, 0x56, 0x78,
- // frame type (stop sending)
- 0x0c,
+ // frame type (IETF_STOP_SENDING frame)
+ 0x05,
// Stream ID
kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04,
// Application error code
@@ -10102,9 +11706,9 @@
// packet number
{"",
{0x12, 0x34, 0x9A, 0xBC}},
- // frame type (path challenge)
+ // frame type (IETF_PATH_CHALLENGE)
{"",
- {0x0e}},
+ {0x1a}},
// data
{"Can not read path challenge data.",
{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}},
@@ -10152,8 +11756,8 @@
// packet number
0x12, 0x34, 0x56, 0x78,
- // frame type (path challenge)
- 0x0e,
+ // frame type (IETF_PATH_CHALLENGE)
+ 0x1a,
// Data
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
};
@@ -10184,9 +11788,9 @@
// packet number
{"",
{0x12, 0x34, 0x9A, 0xBC}},
- // frame type (path response)
+ // frame type (IETF_PATH_RESPONSE)
{"",
- {0x0f}},
+ {0x1b}},
// data
{"Can not read path response data.",
{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07}},
@@ -10234,8 +11838,8 @@
// packet number
0x12, 0x34, 0x56, 0x78,
- // frame type (path response)
- 0x0f,
+ // frame type (IETF_PATH_RESPONSE)
+ 0x1b,
// Data
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
};
@@ -10978,9 +12582,9 @@
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
- // frame type (retire connection id frame)
+ // frame type (IETF_RETIRE_CONNECTION_ID frame)
{"",
- {0x0d}},
+ {0x19}},
// Sequence number
{"Unable to read retire connection ID frame sequence number.",
{kVarInt62TwoBytes + 0x11, 0x22}}
@@ -11031,8 +12635,8 @@
// packet number
0x12, 0x34, 0x56, 0x78,
- // frame type (retire connection id frame)
- 0x0d,
+ // frame type (IETF_RETIRE_CONNECTION_ID frame)
+ 0x19,
// sequence number
kVarInt62TwoBytes + 0x11, 0x22
};
@@ -11046,6 +12650,444 @@
QUIC_ARRAYSIZE(packet99));
}
+TEST_P(QuicFramerTest, AckFrameWithInvalidLargestObserved) {
+ // clang-format off
+ unsigned char packet[] = {
+ // public flags (8 byte connection_id)
+ 0x2C,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x78, 0x56, 0x34, 0x12,
+
+ // frame type (ack frame)
+ 0x45,
+ // largest observed
+ 0x00, 0x00,
+ // Zero delta time.
+ 0x00, 0x00,
+ // first ack block length.
+ 0x00, 0x00,
+ // num timestamps.
+ 0x00
+ };
+
+ unsigned char packet39[] = {
+ // public flags (8 byte connection_id)
+ 0x2C,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // frame type (ack frame)
+ 0x45,
+ // largest observed
+ 0x00, 0x00,
+ // Zero delta time.
+ 0x00, 0x00,
+ // first ack block length.
+ 0x00, 0x00,
+ // num timestamps.
+ 0x00
+ };
+
+ unsigned char packet44[] = {
+ // type (short header, 4 byte packet number)
+ 0x32,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // frame type (ack frame)
+ 0x45,
+ // largest observed
+ 0x00, 0x00,
+ // Zero delta time.
+ 0x00, 0x00,
+ // first ack block length.
+ 0x00, 0x00,
+ // num timestamps.
+ 0x00
+ };
+
+ unsigned char packet47[] = {
+ // type (short header, 4 byte packet number)
+ 0x43,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // frame type (ack frame)
+ 0x45,
+ // largest observed
+ 0x00, 0x00,
+ // Zero delta time.
+ 0x00, 0x00,
+ // first ack block length.
+ 0x00, 0x00,
+ // num timestamps.
+ 0x00
+ };
+
+ unsigned char packet99[] = {
+ // type (short header, 4 byte packet number)
+ 0x43,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // frame type (IETF_ACK frame)
+ 0x02,
+ // Largest acked
+ kVarInt62OneByte + 0x00,
+ // Zero delta time.
+ kVarInt62OneByte + 0x00,
+ // Ack block count 0
+ kVarInt62OneByte + 0x00,
+ // First ack block length
+ kVarInt62OneByte + 0x00,
+ };
+ // clang-format on
+
+ unsigned char* p = packet;
+ size_t p_size = QUIC_ARRAYSIZE(packet);
+ if (framer_.transport_version() == QUIC_VERSION_99) {
+ p = packet99;
+ p_size = QUIC_ARRAYSIZE(packet99);
+ } else if (framer_.transport_version() > QUIC_VERSION_46) {
+ p = packet47;
+ } else if (framer_.transport_version() > QUIC_VERSION_43) {
+ p = packet44;
+ p_size = QUIC_ARRAYSIZE(packet44);
+ } else if (framer_.transport_version() != QUIC_VERSION_35) {
+ p = packet39;
+ }
+
+ QuicEncryptedPacket encrypted(AsChars(p), p_size, false);
+ if (!GetQuicReloadableFlag(quic_disallow_peer_ack_0) &&
+ framer_.transport_version() != QUIC_VERSION_99) {
+ EXPECT_TRUE(framer_.ProcessPacket(encrypted));
+ return;
+ }
+ EXPECT_FALSE(framer_.ProcessPacket(encrypted));
+ EXPECT_EQ(framer_.detailed_error(), "Largest acked is 0.");
+}
+
+TEST_P(QuicFramerTest, FirstAckBlockJustUnderFlow) {
+ // clang-format off
+ unsigned char packet[] = {
+ // public flags (8 byte connection_id)
+ 0x2C,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x78, 0x56, 0x34, 0x12,
+
+ // frame type (ack frame)
+ 0x45,
+ // largest observed
+ 0x02, 0x00,
+ // Zero delta time.
+ 0x00, 0x00,
+ // first ack block length.
+ 0x03, 0x00,
+ // num timestamps.
+ 0x00
+ };
+
+ unsigned char packet39[] = {
+ // public flags (8 byte connection_id)
+ 0x2C,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // frame type (ack frame)
+ 0x45,
+ // largest observed
+ 0x00, 0x02,
+ // Zero delta time.
+ 0x00, 0x00,
+ // first ack block length.
+ 0x00, 0x03,
+ // num timestamps.
+ 0x00
+ };
+
+ unsigned char packet44[] = {
+ // type (short header, 4 byte packet number)
+ 0x32,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // frame type (ack frame)
+ 0x45,
+ // largest observed
+ 0x00, 0x02,
+ // Zero delta time.
+ 0x00, 0x00,
+ // first ack block length.
+ 0x00, 0x03,
+ // num timestamps.
+ 0x00
+ };
+
+ unsigned char packet47[] = {
+ // type (short header, 4 byte packet number)
+ 0x43,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // frame type (ack frame)
+ 0x45,
+ // largest observed
+ 0x00, 0x02,
+ // Zero delta time.
+ 0x00, 0x00,
+ // first ack block length.
+ 0x00, 0x03,
+ // num timestamps.
+ 0x00
+ };
+
+ unsigned char packet99[] = {
+ // type (short header, 4 byte packet number)
+ 0x43,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // frame type (IETF_ACK frame)
+ 0x02,
+ // Largest acked
+ kVarInt62OneByte + 0x02,
+ // Zero delta time.
+ kVarInt62OneByte + 0x00,
+ // Ack block count 0
+ kVarInt62OneByte + 0x00,
+ // First ack block length
+ kVarInt62OneByte + 0x02,
+ };
+ // clang-format on
+
+ unsigned char* p = packet;
+ size_t p_size = QUIC_ARRAYSIZE(packet);
+ if (framer_.transport_version() == QUIC_VERSION_99) {
+ p = packet99;
+ p_size = QUIC_ARRAYSIZE(packet99);
+ } else if (framer_.transport_version() > QUIC_VERSION_46) {
+ p = packet47;
+ p_size = QUIC_ARRAYSIZE(packet47);
+ } else if (framer_.transport_version() > QUIC_VERSION_43) {
+ p = packet44;
+ p_size = QUIC_ARRAYSIZE(packet44);
+ } else if (framer_.transport_version() != QUIC_VERSION_35) {
+ p = packet39;
+ }
+
+ QuicEncryptedPacket encrypted(AsChars(p), p_size, false);
+ if (!GetQuicReloadableFlag(quic_disallow_peer_ack_0) &&
+ framer_.transport_version() != QUIC_VERSION_99) {
+ EXPECT_TRUE(framer_.ProcessPacket(encrypted));
+ return;
+ }
+ EXPECT_FALSE(framer_.ProcessPacket(encrypted));
+ EXPECT_EQ(framer_.detailed_error(),
+ "Underflow with first ack block length 3 largest acked is 2.");
+}
+
+TEST_P(QuicFramerTest, ThirdAckBlockJustUnderflow) {
+ // clang-format off
+ unsigned char packet[] = {
+ // public flags (8 byte connection_id)
+ 0x2C,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x78, 0x56, 0x34, 0x12,
+
+ // frame type (ack frame)
+ 0x60,
+ // largest observed
+ 0x0A,
+ // Zero delta time.
+ 0x00, 0x00,
+ // Num of ack blocks
+ 0x02,
+ // first ack block length.
+ 0x02,
+ // gap to next block
+ 0x01,
+ // ack block length
+ 0x01,
+ // gap to next block
+ 0x01,
+ // ack block length
+ 0x06,
+ // num timestamps.
+ 0x00
+ };
+
+ unsigned char packet39[] = {
+ // public flags (8 byte connection_id)
+ 0x2C,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // frame type (ack frame)
+ 0x60,
+ // largest observed
+ 0x0A,
+ // Zero delta time.
+ 0x00, 0x00,
+ // Num of ack blocks
+ 0x02,
+ // first ack block length.
+ 0x02,
+ // gap to next block
+ 0x01,
+ // ack block length
+ 0x01,
+ // gap to next block
+ 0x01,
+ // ack block length
+ 0x06,
+ // num timestamps.
+ 0x00
+ };
+
+ unsigned char packet44[] = {
+ // type (short header, 4 byte packet number)
+ 0x32,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // frame type (ack frame)
+ 0x60,
+ // largest observed
+ 0x0A,
+ // Zero delta time.
+ 0x00, 0x00,
+ // Num of ack blocks
+ 0x02,
+ // first ack block length.
+ 0x02,
+ // gap to next block
+ 0x01,
+ // ack block length
+ 0x01,
+ // gap to next block
+ 0x01,
+ // ack block length
+ 0x06,
+ // num timestamps.
+ 0x00
+ };
+
+ unsigned char packet47[] = {
+ // type (short header, 4 byte packet number)
+ 0x43,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // frame type (ack frame)
+ 0x60,
+ // largest observed
+ 0x0A,
+ // Zero delta time.
+ 0x00, 0x00,
+ // Num of ack blocks
+ 0x02,
+ // first ack block length.
+ 0x02,
+ // gap to next block
+ 0x01,
+ // ack block length
+ 0x01,
+ // gap to next block
+ 0x01,
+ // ack block length
+ 0x06,
+ // num timestamps.
+ 0x00
+ };
+
+ unsigned char packet99[] = {
+ // type (short header, 4 byte packet number)
+ 0x43,
+ // connection_id
+ 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
+ // packet number
+ 0x12, 0x34, 0x56, 0x78,
+
+ // frame type (IETF_ACK frame)
+ 0x02,
+ // Largest acked
+ kVarInt62OneByte + 0x0A,
+ // Zero delta time.
+ kVarInt62OneByte + 0x00,
+ // Ack block count 2
+ kVarInt62OneByte + 0x02,
+ // First ack block length
+ kVarInt62OneByte + 0x01,
+ // gap to next block length
+ kVarInt62OneByte + 0x00,
+ // ack block length
+ kVarInt62OneByte + 0x00,
+ // gap to next block length
+ kVarInt62OneByte + 0x00,
+ // ack block length
+ kVarInt62OneByte + 0x05,
+ };
+ // clang-format on
+
+ unsigned char* p = packet;
+ size_t p_size = QUIC_ARRAYSIZE(packet);
+ if (framer_.transport_version() == QUIC_VERSION_99) {
+ p = packet99;
+ p_size = QUIC_ARRAYSIZE(packet99);
+ } else if (framer_.transport_version() > QUIC_VERSION_46) {
+ p = packet47;
+ p_size = QUIC_ARRAYSIZE(packet47);
+ } else if (framer_.transport_version() > QUIC_VERSION_43) {
+ p = packet44;
+ p_size = QUIC_ARRAYSIZE(packet44);
+ } else if (framer_.transport_version() != QUIC_VERSION_35) {
+ p = packet39;
+ }
+
+ QuicEncryptedPacket encrypted(AsChars(p), p_size, false);
+ if (!GetQuicReloadableFlag(quic_disallow_peer_ack_0) &&
+ framer_.transport_version() != QUIC_VERSION_99) {
+ EXPECT_TRUE(framer_.ProcessPacket(encrypted));
+ return;
+ }
+ EXPECT_FALSE(framer_.ProcessPacket(encrypted));
+ if (framer_.transport_version() == QUIC_VERSION_99) {
+ EXPECT_EQ(framer_.detailed_error(),
+ "Underflow with ack block length 6 latest ack block end is 5.");
+ } else {
+ EXPECT_EQ(framer_.detailed_error(),
+ "Underflow with ack block length 6, end of block is 6.");
+ }
+}
+
} // namespace
} // namespace test
} // namespace quic
diff --git a/quic/core/quic_ietf_framer_test.cc b/quic/core/quic_ietf_framer_test.cc
index 2e10b61..d35800a 100644
--- a/quic/core/quic_ietf_framer_test.cc
+++ b/quic/core/quic_ietf_framer_test.cc
@@ -623,6 +623,39 @@
}
}
+TEST_F(QuicIetfFramerTest, CryptoFrame) {
+ SimpleDataProducer data_producer;
+ framer_.set_data_producer(&data_producer);
+ char packet_buffer[kNormalPacketBufferSize];
+
+ QuicStringPiece frame_data("This is a CRYPTO frame.");
+
+ QuicStreamOffset offsets[] = {kOffset8, kOffset4, kOffset2, kOffset1,
+ kOffset0};
+ for (QuicStreamOffset offset : offsets) {
+ QuicCryptoFrame frame(ENCRYPTION_NONE, offset, frame_data.length());
+ data_producer.SaveCryptoData(ENCRYPTION_NONE, offset, frame_data);
+
+ QuicDataWriter writer(QUIC_ARRAYSIZE(packet_buffer), packet_buffer,
+ NETWORK_BYTE_ORDER);
+
+ // Write the frame.
+ EXPECT_TRUE(QuicFramerPeer::AppendCryptoFrame(&framer_, frame, &writer));
+ EXPECT_NE(0u, writer.length());
+ // Read it back.
+ QuicDataReader reader(packet_buffer, writer.length(), NETWORK_BYTE_ORDER);
+ QuicCryptoFrame read_frame;
+ EXPECT_TRUE(
+ QuicFramerPeer::ProcessCryptoFrame(&framer_, &reader, &read_frame));
+
+ // Check that the frames match:
+ QuicStringPiece read_data(read_frame.data_buffer, read_frame.data_length);
+ EXPECT_EQ(read_frame.data_length, frame.data_length);
+ EXPECT_EQ(read_frame.offset, frame.offset);
+ EXPECT_EQ(read_data, frame_data);
+ }
+}
+
TEST_F(QuicIetfFramerTest, ConnectionCloseEmptyString) {
char packet_buffer[kNormalPacketBufferSize];
@@ -695,35 +728,187 @@
// Testing for the IETF ACK framer.
// clang-format off
struct ack_frame ack_frame_variants[] = {
- { 90000, false, 0, 0, 0, {{1000, 2001}}, IETF_ACK },
- { 0, false, 0, 0, 0, {{1000, 2001}}, IETF_ACK },
- { 1, false, 0, 0, 0, {{1, 2}, {5, 6}}, IETF_ACK },
- { 63, false, 0, 0, 0, {{1, 2}, {5, 6}}, IETF_ACK },
- { 64, false, 0, 0, 0, {{1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 10}, {11, 12}},
- IETF_ACK},
- { 10000, false, 0, 0, 0, {{1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 10}, {11, 12}},
- IETF_ACK},
- { 100000000, false, 0, 0, 0,
- {{1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 10}, {11, 12}},
- IETF_ACK},
- { 0, false, 0, 0, 0, {{1, 65}}, IETF_ACK },
- { 9223372036854775807, false, 0, 0, 0, {{1, 11}, {74, 138}}, IETF_ACK },
- // This ack is for packets 60 & 125. There are 64 packets in the gap.
- // The encoded value is gap_size - 1, or 63. Crosses a VarInt62 encoding
- // boundary...
- { 1, false, 0, 0, 0, {{60, 61}, {125, 126}}, IETF_ACK },
- { 2, false, 0, 0, 0, {{ 1, 65}, {129, 130}}, IETF_ACK },
- { 3, false, 0, 0, 0, {{ 1, 65}, {129, 195}}, IETF_ACK },
- { 4, false, 0, 0, 0, {{ 1, 65}, {129, 194}}, IETF_ACK },
- { 5, false, 0, 0, 0, {{ 1, 65}, {129, 193}}, IETF_ACK },
- { 6, false, 0, 0, 0, {{ 1, 65}, {129, 192}}, IETF_ACK },
- // declare some ack_ecn frames to try.
- { 6, false, 100, 200, 300, {{ 1, 65}, {129, 192}}, IETF_ACK },
- { 6, true, 100, 200, 300, {{ 1, 65}, {129, 192}}, IETF_ACK_ECN },
- { 6, true, 100, 0, 0, {{ 1, 65}, {129, 192}}, IETF_ACK_ECN },
- { 6, true, 0, 200, 0, {{ 1, 65}, {129, 192}}, IETF_ACK_ECN },
- { 6, true, 0, 0, 300, {{ 1, 65}, {129, 192}}, IETF_ACK_ECN },
- { 6, true, 0, 0, 0, {{ 1, 65}, {129, 192}}, IETF_ACK },
+ {90000,
+ false,
+ 0,
+ 0,
+ 0,
+ {{QuicPacketNumber(1000), QuicPacketNumber(2001)}},
+ IETF_ACK},
+ {0,
+ false,
+ 0,
+ 0,
+ 0,
+ {{QuicPacketNumber(1000), QuicPacketNumber(2001)}},
+ IETF_ACK},
+ {1,
+ false,
+ 0,
+ 0,
+ 0,
+ {{QuicPacketNumber(1), QuicPacketNumber(2)},
+ {QuicPacketNumber(5), QuicPacketNumber(6)}},
+ IETF_ACK},
+ {63,
+ false,
+ 0,
+ 0,
+ 0,
+ {{QuicPacketNumber(1), QuicPacketNumber(2)},
+ {QuicPacketNumber(5), QuicPacketNumber(6)}},
+ IETF_ACK},
+ {64,
+ false,
+ 0,
+ 0,
+ 0,
+ {{QuicPacketNumber(1), QuicPacketNumber(2)},
+ {QuicPacketNumber(3), QuicPacketNumber(4)},
+ {QuicPacketNumber(5), QuicPacketNumber(6)},
+ {QuicPacketNumber(7), QuicPacketNumber(8)},
+ {QuicPacketNumber(9), QuicPacketNumber(10)},
+ {QuicPacketNumber(11), QuicPacketNumber(12)}},
+ IETF_ACK},
+ {10000,
+ false,
+ 0,
+ 0,
+ 0,
+ {{QuicPacketNumber(1), QuicPacketNumber(2)},
+ {QuicPacketNumber(3), QuicPacketNumber(4)},
+ {QuicPacketNumber(5), QuicPacketNumber(6)},
+ {QuicPacketNumber(7), QuicPacketNumber(8)},
+ {QuicPacketNumber(9), QuicPacketNumber(10)},
+ {QuicPacketNumber(11), QuicPacketNumber(12)}},
+ IETF_ACK},
+ {100000000,
+ false,
+ 0,
+ 0,
+ 0,
+ {{QuicPacketNumber(1), QuicPacketNumber(2)},
+ {QuicPacketNumber(3), QuicPacketNumber(4)},
+ {QuicPacketNumber(5), QuicPacketNumber(6)},
+ {QuicPacketNumber(7), QuicPacketNumber(8)},
+ {QuicPacketNumber(9), QuicPacketNumber(10)},
+ {QuicPacketNumber(11), QuicPacketNumber(12)}},
+ IETF_ACK},
+ {0,
+ false,
+ 0,
+ 0,
+ 0,
+ {{QuicPacketNumber(1), QuicPacketNumber(65)}},
+ IETF_ACK},
+ {9223372036854775807,
+ false,
+ 0,
+ 0,
+ 0,
+ {{QuicPacketNumber(1), QuicPacketNumber(11)},
+ {QuicPacketNumber(74), QuicPacketNumber(138)}},
+ IETF_ACK},
+ // This ack is for packets 60 & 125. There are 64 packets in the gap.
+ // The encoded value is gap_size - 1, or 63. Crosses a VarInt62 encoding
+ // boundary...
+ {1,
+ false,
+ 0,
+ 0,
+ 0,
+ {{QuicPacketNumber(60), QuicPacketNumber(61)},
+ {QuicPacketNumber(125), QuicPacketNumber(126)}},
+ IETF_ACK},
+ {2,
+ false,
+ 0,
+ 0,
+ 0,
+ {{QuicPacketNumber(1), QuicPacketNumber(65)},
+ {QuicPacketNumber(129), QuicPacketNumber(130)}},
+ IETF_ACK},
+ {3,
+ false,
+ 0,
+ 0,
+ 0,
+ {{QuicPacketNumber(1), QuicPacketNumber(65)},
+ {QuicPacketNumber(129), QuicPacketNumber(195)}},
+ IETF_ACK},
+ {4,
+ false,
+ 0,
+ 0,
+ 0,
+ {{QuicPacketNumber(1), QuicPacketNumber(65)},
+ {QuicPacketNumber(129), QuicPacketNumber(194)}},
+ IETF_ACK},
+ {5,
+ false,
+ 0,
+ 0,
+ 0,
+ {{QuicPacketNumber(1), QuicPacketNumber(65)},
+ {QuicPacketNumber(129), QuicPacketNumber(193)}},
+ IETF_ACK},
+ {6,
+ false,
+ 0,
+ 0,
+ 0,
+ {{QuicPacketNumber(1), QuicPacketNumber(65)},
+ {QuicPacketNumber(129), QuicPacketNumber(192)}},
+ IETF_ACK},
+ // declare some ack_ecn frames to try.
+ {6,
+ false,
+ 100,
+ 200,
+ 300,
+ {{QuicPacketNumber(1), QuicPacketNumber(65)},
+ {QuicPacketNumber(129), QuicPacketNumber(192)}},
+ IETF_ACK},
+ {6,
+ true,
+ 100,
+ 200,
+ 300,
+ {{QuicPacketNumber(1), QuicPacketNumber(65)},
+ {QuicPacketNumber(129), QuicPacketNumber(192)}},
+ IETF_ACK_ECN},
+ {6,
+ true,
+ 100,
+ 0,
+ 0,
+ {{QuicPacketNumber(1), QuicPacketNumber(65)},
+ {QuicPacketNumber(129), QuicPacketNumber(192)}},
+ IETF_ACK_ECN},
+ {6,
+ true,
+ 0,
+ 200,
+ 0,
+ {{QuicPacketNumber(1), QuicPacketNumber(65)},
+ {QuicPacketNumber(129), QuicPacketNumber(192)}},
+ IETF_ACK_ECN},
+ {6,
+ true,
+ 0,
+ 0,
+ 300,
+ {{QuicPacketNumber(1), QuicPacketNumber(65)},
+ {QuicPacketNumber(129), QuicPacketNumber(192)}},
+ IETF_ACK_ECN},
+ {6,
+ true,
+ 0,
+ 0,
+ 0,
+ {{QuicPacketNumber(1), QuicPacketNumber(65)},
+ {QuicPacketNumber(129), QuicPacketNumber(192)}},
+ IETF_ACK},
};
// clang-format on
@@ -749,7 +934,7 @@
NETWORK_BYTE_ORDER);
QuicAckFrame transmit_frame;
- transmit_frame.largest_acked = 1;
+ transmit_frame.largest_acked = QuicPacketNumber(1);
transmit_frame.ack_delay_time = QuicTime::Delta::FromMicroseconds(0);
size_t expected_size =
@@ -759,7 +944,7 @@
&framer_, transmit_frame, &writer));
uint8_t packet[] = {
- 0x1a, // type
+ 0x02, // type, IETF_ACK
0x01, // largest_acked,
0x00, // delay
0x00, // count of additional ack blocks
diff --git a/quic/core/quic_lru_cache.h b/quic/core/quic_lru_cache.h
index 12e140b..b8c78c6 100644
--- a/quic/core/quic_lru_cache.h
+++ b/quic/core/quic_lru_cache.h
@@ -10,7 +10,6 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_lru_cache.h"
namespace quic {
@@ -18,13 +17,12 @@
// This cache CANNOT be shared by multiple threads (even with locks) because
// Value* returned by Lookup() can be invalid if the entry is evicted by other
// threads.
-// TODO(vasilvv): rename this class when quic_new_lru_cache flag is deprecated.
template <class K, class V>
-class QuicLRUCacheNew {
+class QuicLRUCache {
public:
- explicit QuicLRUCacheNew(size_t capacity) : capacity_(capacity) {}
- QuicLRUCacheNew(const QuicLRUCacheNew&) = delete;
- QuicLRUCacheNew& operator=(const QuicLRUCacheNew&) = delete;
+ explicit QuicLRUCache(size_t capacity) : capacity_(capacity) {}
+ QuicLRUCache(const QuicLRUCache&) = delete;
+ QuicLRUCache& operator=(const QuicLRUCache&) = delete;
// Inserts one unit of |key|, |value| pair to the cache. Cache takes ownership
// of inserted |value|.
@@ -45,7 +43,6 @@
// value is guaranteed to be valid until Insert or Clear.
// Else return nullptr.
V* Lookup(const K& key) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_new_lru_cache);
auto it = cache_.find(key);
if (it == cache_.end()) {
return nullptr;
@@ -72,63 +69,6 @@
const size_t capacity_;
};
-// TODO(vasilvv): remove this class when quic_new_lru_cache flag is deprecated.
-template <class K, class V>
-class QuicLRUCache {
- public:
- explicit QuicLRUCache(size_t capacity)
- : QuicLRUCache(capacity, GetQuicReloadableFlag(quic_new_lru_cache)) {}
- QuicLRUCache(size_t capacity, bool use_new)
- : new_(capacity), old_(capacity), use_new_(use_new) {}
- QuicLRUCache(const QuicLRUCache&) = delete;
- QuicLRUCache& operator=(const QuicLRUCache&) = delete;
-
- void Insert(const K& key, std::unique_ptr<V> value) {
- if (use_new_) {
- new_.Insert(key, std::move(value));
- } else {
- old_.Insert(key, std::move(value));
- }
- }
-
- V* Lookup(const K& key) {
- if (use_new_) {
- return new_.Lookup(key);
- } else {
- return old_.Lookup(key);
- }
- }
-
- void Clear() {
- if (use_new_) {
- new_.Clear();
- } else {
- old_.Clear();
- }
- }
-
- size_t MaxSize() const {
- if (use_new_) {
- return new_.MaxSize();
- } else {
- return old_.MaxSize();
- }
- }
-
- size_t Size() const {
- if (use_new_) {
- return new_.Size();
- } else {
- return old_.Size();
- }
- }
-
- private:
- QuicLRUCacheNew<K, V> new_;
- QuicLRUCacheOld<K, V> old_;
- bool use_new_;
-};
-
} // namespace quic
#endif // QUICHE_QUIC_CORE_QUIC_LRU_CACHE_H_
diff --git a/quic/core/quic_lru_cache_test.cc b/quic/core/quic_lru_cache_test.cc
index c335d5b..92f788b 100644
--- a/quic/core/quic_lru_cache_test.cc
+++ b/quic/core/quic_lru_cache_test.cc
@@ -16,12 +16,8 @@
uint32_t value;
};
-class QuicLRUCacheTest : public QuicTestWithParam<bool> {};
-
-INSTANTIATE_TEST_CASE_P(QuicLRUCacheTests, QuicLRUCacheTest, testing::Bool());
-
-TEST_P(QuicLRUCacheTest, InsertAndLookup) {
- QuicLRUCache<int, CachedItem> cache(5, GetParam());
+TEST(QuicLRUCacheTest, InsertAndLookup) {
+ QuicLRUCache<int, CachedItem> cache(5);
EXPECT_EQ(nullptr, cache.Lookup(1));
EXPECT_EQ(0u, cache.Size());
EXPECT_EQ(5u, cache.MaxSize());
@@ -48,8 +44,8 @@
EXPECT_EQ(0u, cache.Size());
}
-TEST_P(QuicLRUCacheTest, Eviction) {
- QuicLRUCache<int, CachedItem> cache(3, GetParam());
+TEST(QuicLRUCacheTest, Eviction) {
+ QuicLRUCache<int, CachedItem> cache(3);
for (size_t i = 1; i <= 4; ++i) {
std::unique_ptr<CachedItem> item(new CachedItem(10 + i));
diff --git a/quic/core/quic_packet_creator.cc b/quic/core/quic_packet_creator.cc
index 7f48c74..cc4f50e 100644
--- a/quic/core/quic_packet_creator.cc
+++ b/quic/core/quic_packet_creator.cc
@@ -49,7 +49,12 @@
connection_id_length_(PACKET_8BYTE_CONNECTION_ID),
packet_size_(0),
connection_id_(connection_id),
- packet_(0, PACKET_1BYTE_PACKET_NUMBER, nullptr, 0, false, false),
+ packet_(QuicPacketNumber(),
+ PACKET_1BYTE_PACKET_NUMBER,
+ nullptr,
+ 0,
+ false,
+ false),
long_header_type_(HANDSHAKE),
pending_padding_bytes_(0),
needs_full_padding_(false),
@@ -120,11 +125,11 @@
}
DCHECK_LE(least_packet_awaited_by_peer, packet_.packet_number + 1);
- const QuicPacketNumber current_delta =
+ const uint64_t current_delta =
packet_.packet_number + 1 - least_packet_awaited_by_peer;
const uint64_t delta = std::max(current_delta, max_packets_in_flight);
packet_.packet_number_length = QuicFramer::GetMinPacketNumberLength(
- framer_->transport_version(), delta * 4);
+ framer_->transport_version(), QuicPacketNumber(delta * 4));
}
bool QuicPacketCreator::ConsumeData(QuicStreamId id,
@@ -334,14 +339,14 @@
packet_.has_stop_waiting = false;
packet_.has_crypto_handshake = NOT_HANDSHAKE;
packet_.num_padding_bytes = 0;
- packet_.original_packet_number = kInvalidPacketNumber;
+ packet_.original_packet_number.Clear();
if (!can_set_transmission_type_ || ShouldSetTransmissionTypeForNextFrame()) {
packet_.transmission_type = NOT_RETRANSMISSION;
}
packet_.encrypted_buffer = nullptr;
packet_.encrypted_length = 0;
DCHECK(packet_.retransmittable_frames.empty());
- packet_.largest_acked = kInvalidPacketNumber;
+ packet_.largest_acked.Clear();
needs_full_padding_ = false;
}
@@ -655,8 +660,8 @@
// TODO(b/74062209): Make this a public method of framer?
SerializedPacket QuicPacketCreator::NoPacket() {
- return SerializedPacket(0, PACKET_1BYTE_PACKET_NUMBER, nullptr, 0, false,
- false);
+ return SerializedPacket(QuicPacketNumber(), PACKET_1BYTE_PACKET_NUMBER,
+ nullptr, 0, false, false);
}
QuicConnectionIdLength QuicPacketCreator::GetDestinationConnectionIdLength()
@@ -699,7 +704,12 @@
} else {
header->nonce = nullptr;
}
- header->packet_number = ++packet_.packet_number;
+ if (!packet_.packet_number.IsInitialized()) {
+ packet_.packet_number = framer_->first_sending_packet_number();
+ } else {
+ ++packet_.packet_number;
+ }
+ header->packet_number = packet_.packet_number;
header->packet_number_length = GetPacketNumberLength();
if (!HasIetfLongHeader()) {
return;
diff --git a/quic/core/quic_packet_creator_test.cc b/quic/core/quic_packet_creator_test.cc
index 0ea9b13..5dd4abb 100644
--- a/quic/core/quic_packet_creator_test.cc
+++ b/quic/core/quic_packet_creator_test.cc
@@ -91,8 +91,7 @@
// Save data before data is consumed.
QuicByteCount data_length = total_length - iov_offset;
if (data_length > 0) {
- producer_->SaveStreamData(id, iov, iov_count, iov_offset, offset,
- data_length);
+ producer_->SaveStreamData(id, iov, iov_count, iov_offset, data_length);
}
return QuicPacketCreator::ConsumeData(id, data_length, iov_offset, offset,
fin, needs_full_padding,
@@ -228,9 +227,10 @@
int num_padding_bytes,
EncryptionLevel encryption_level,
QuicPacketNumberLength packet_number_length) {
- return QuicPendingRetransmission(
- 1u, NOT_RETRANSMISSION, retransmittable_frames, has_crypto_handshake,
- num_padding_bytes, encryption_level, packet_number_length);
+ return QuicPendingRetransmission(QuicPacketNumber(1u), NOT_RETRANSMISSION,
+ retransmittable_frames,
+ has_crypto_handshake, num_padding_bytes,
+ encryption_level, packet_number_length);
}
bool IsDefaultTestConfiguration() {
@@ -269,7 +269,7 @@
for (int i = ENCRYPTION_NONE; i < NUM_ENCRYPTION_LEVELS; ++i) {
EncryptionLevel level = static_cast<EncryptionLevel>(i);
creator_.set_encryption_level(level);
- frames_.push_back(QuicFrame(new QuicAckFrame()));
+ frames_.push_back(QuicFrame(new QuicAckFrame(InitAckFrame(1))));
frames_.push_back(QuicFrame(QuicStreamFrame(
QuicUtils::GetCryptoStreamId(client_framer_.transport_version()), false,
0u, QuicStringPiece())));
@@ -290,21 +290,11 @@
EXPECT_CALL(framer_visitor_, OnPacketHeader(_));
EXPECT_CALL(framer_visitor_, OnAckFrameStart(_, _))
.WillOnce(Return(true));
- // This test includes an ack frame with largest_acked == 0 and
- // the size of the first ack-block == 1 (serialized as
- // 0). This is an invalid format for pre-version99, valid
- // for version 99.
- if (client_framer_.transport_version() != QUIC_VERSION_99) {
- // pre-version 99; ensure that the error is gracefully
- // handled.
- EXPECT_CALL(framer_visitor_, OnAckRange(1, 1)).WillOnce(Return(true));
- EXPECT_CALL(framer_visitor_, OnAckFrameEnd(1)).WillOnce(Return(true));
- } else {
- // version 99; ensure that the correct packet is signalled
- // properly.
- EXPECT_CALL(framer_visitor_, OnAckRange(0, 1)).WillOnce(Return(true));
- EXPECT_CALL(framer_visitor_, OnAckFrameEnd(0)).WillOnce(Return(true));
- }
+ EXPECT_CALL(framer_visitor_,
+ OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2)))
+ .WillOnce(Return(true));
+ EXPECT_CALL(framer_visitor_, OnAckFrameEnd(QuicPacketNumber(1)))
+ .WillOnce(Return(true));
EXPECT_CALL(framer_visitor_, OnStreamFrame(_));
EXPECT_CALL(framer_visitor_, OnStreamFrame(_));
EXPECT_CALL(framer_visitor_, OnPacketComplete());
@@ -394,7 +384,7 @@
MakeIOVector("fake handshake message data", &iov_);
producer_.SaveStreamData(
QuicUtils::GetCryptoStreamId(client_framer_.transport_version()), &iov_,
- 1u, 0u, 0u, iov_.iov_len);
+ 1u, 0u, iov_.iov_len);
QuicPacketCreatorPeer::CreateStreamFrame(
&creator_,
QuicUtils::GetCryptoStreamId(client_framer_.transport_version()),
@@ -417,7 +407,7 @@
MakeIOVector("fake message data", &iov_);
producer_.SaveStreamData(
QuicUtils::GetCryptoStreamId(client_framer_.transport_version()), &iov_,
- 1u, 0u, 0u, iov_.iov_len);
+ 1u, 0u, iov_.iov_len);
QuicPacketCreatorPeer::CreateStreamFrame(
&creator_,
QuicUtils::GetCryptoStreamId(client_framer_.transport_version()),
@@ -483,7 +473,7 @@
SimpleDataProducer producer;
producer.SaveStreamData(
QuicUtils::GetCryptoStreamId(client_framer_.transport_version()), &iov_,
- 1u, 0u, 0u, iov_.iov_len);
+ 1u, 0u, iov_.iov_len);
QuicPacketCreatorPeer::framer(&creator_)->set_data_producer(&producer);
QuicPacketCreatorPeer::CreateStreamFrame(
&creator_,
@@ -523,8 +513,8 @@
frames.push_back(QuicFrame(&frame));
SerializedPacket serialized = SerializeAllFrames(frames);
EXPECT_EQ(ENCRYPTION_NONE, serialized.encryption_level);
- ASSERT_EQ(1u, serialized.packet_number);
- ASSERT_EQ(1u, creator_.packet_number());
+ ASSERT_EQ(QuicPacketNumber(1u), serialized.packet_number);
+ ASSERT_EQ(QuicPacketNumber(1u), creator_.packet_number());
InSequence s;
EXPECT_CALL(framer_visitor_, OnPacket());
@@ -1026,28 +1016,33 @@
}
QuicPacketCreatorPeer::SetPacketNumber(&creator_, 64);
- creator_.UpdatePacketNumberLength(2, 10000 / kDefaultMaxPacketSize);
+ creator_.UpdatePacketNumberLength(QuicPacketNumber(2),
+ 10000 / kDefaultMaxPacketSize);
EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER,
QuicPacketCreatorPeer::GetPacketNumberLength(&creator_));
QuicPacketCreatorPeer::SetPacketNumber(&creator_, 64 * 256);
- creator_.UpdatePacketNumberLength(2, 10000 / kDefaultMaxPacketSize);
+ creator_.UpdatePacketNumberLength(QuicPacketNumber(2),
+ 10000 / kDefaultMaxPacketSize);
EXPECT_EQ(PACKET_2BYTE_PACKET_NUMBER,
QuicPacketCreatorPeer::GetPacketNumberLength(&creator_));
QuicPacketCreatorPeer::SetPacketNumber(&creator_, 64 * 256 * 256);
- creator_.UpdatePacketNumberLength(2, 10000 / kDefaultMaxPacketSize);
+ creator_.UpdatePacketNumberLength(QuicPacketNumber(2),
+ 10000 / kDefaultMaxPacketSize);
EXPECT_EQ(PACKET_4BYTE_PACKET_NUMBER,
QuicPacketCreatorPeer::GetPacketNumberLength(&creator_));
QuicPacketCreatorPeer::SetPacketNumber(&creator_,
UINT64_C(64) * 256 * 256 * 256 * 256);
- creator_.UpdatePacketNumberLength(2, 10000 / kDefaultMaxPacketSize);
+ creator_.UpdatePacketNumberLength(QuicPacketNumber(2),
+ 10000 / kDefaultMaxPacketSize);
EXPECT_EQ(PACKET_6BYTE_PACKET_NUMBER,
QuicPacketCreatorPeer::GetPacketNumberLength(&creator_));
}
TEST_P(QuicPacketCreatorTest, UpdatePacketSequenceNumberLengthCwnd) {
+ QuicPacketCreatorPeer::SetPacketNumber(&creator_, 1);
if (GetParam().version.transport_version > QUIC_VERSION_43 &&
GetParam().version.transport_version != QUIC_VERSION_99) {
EXPECT_EQ(PACKET_4BYTE_PACKET_NUMBER,
@@ -1058,21 +1053,24 @@
QuicPacketCreatorPeer::GetPacketNumberLength(&creator_));
}
- creator_.UpdatePacketNumberLength(1, 10000 / kDefaultMaxPacketSize);
+ creator_.UpdatePacketNumberLength(QuicPacketNumber(1),
+ 10000 / kDefaultMaxPacketSize);
EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER,
QuicPacketCreatorPeer::GetPacketNumberLength(&creator_));
- creator_.UpdatePacketNumberLength(1, 10000 * 256 / kDefaultMaxPacketSize);
+ creator_.UpdatePacketNumberLength(QuicPacketNumber(1),
+ 10000 * 256 / kDefaultMaxPacketSize);
EXPECT_EQ(PACKET_2BYTE_PACKET_NUMBER,
QuicPacketCreatorPeer::GetPacketNumberLength(&creator_));
- creator_.UpdatePacketNumberLength(1,
+ creator_.UpdatePacketNumberLength(QuicPacketNumber(1),
10000 * 256 * 256 / kDefaultMaxPacketSize);
EXPECT_EQ(PACKET_4BYTE_PACKET_NUMBER,
QuicPacketCreatorPeer::GetPacketNumberLength(&creator_));
creator_.UpdatePacketNumberLength(
- 1, UINT64_C(1000) * 256 * 256 * 256 * 256 / kDefaultMaxPacketSize);
+ QuicPacketNumber(1),
+ UINT64_C(1000) * 256 * 256 * 256 * 256 / kDefaultMaxPacketSize);
EXPECT_EQ(PACKET_6BYTE_PACKET_NUMBER,
QuicPacketCreatorPeer::GetPacketNumberLength(&creator_));
}
@@ -1191,7 +1189,7 @@
ASSERT_EQ(1u, retransmittable.size());
EXPECT_EQ(STREAM_FRAME, retransmittable[0].type);
EXPECT_TRUE(serialized_packet_.has_ack);
- EXPECT_EQ(10u, serialized_packet_.largest_acked);
+ EXPECT_EQ(QuicPacketNumber(10u), serialized_packet_.largest_acked);
DeleteSerializedPacket();
EXPECT_FALSE(creator_.HasPendingFrames());
@@ -1217,7 +1215,7 @@
MakeIOVector("test", &iov_);
producer_.SaveStreamData(
QuicUtils::GetHeadersStreamId(client_framer_.transport_version()), &iov_,
- 1u, 0u, 0u, iov_.iov_len);
+ 1u, 0u, iov_.iov_len);
EXPECT_CALL(delegate_, OnSerializedPacket(_))
.WillOnce(Invoke(this, &QuicPacketCreatorTest::SaveSerializedPacket));
size_t num_bytes_consumed;
@@ -1357,7 +1355,7 @@
MakeIOVector("fake handshake message data", &iov_);
producer_.SaveStreamData(
QuicUtils::GetCryptoStreamId(client_framer_.transport_version()), &iov_,
- 1u, 0u, 0u, iov_.iov_len);
+ 1u, 0u, iov_.iov_len);
QuicPacketCreatorPeer::CreateStreamFrame(
&creator_,
QuicUtils::GetCryptoStreamId(client_framer_.transport_version()),
@@ -1476,7 +1474,9 @@
// failure. While this test is not applicable to versions other than version 99,
// it should still work. Hence, it is not made version-specific.
TEST_P(QuicPacketCreatorTest, IetfAckGapErrorRegression) {
- QuicAckFrame ack_frame = InitAckFrame({{60, 61}, {125, 126}});
+ QuicAckFrame ack_frame =
+ InitAckFrame({{QuicPacketNumber(60), QuicPacketNumber(61)},
+ {QuicPacketNumber(125), QuicPacketNumber(126)}});
frames_.push_back(QuicFrame(&ack_frame));
SerializeAllFrames(frames_);
}
@@ -1563,7 +1563,7 @@
creator_.set_can_set_transmission_type(true);
creator_.SetTransmissionType(NOT_RETRANSMISSION);
- QuicAckFrame temp_ack_frame;
+ QuicAckFrame temp_ack_frame = InitAckFrame(1);
QuicFrame ack_frame(&temp_ack_frame);
ASSERT_FALSE(QuicUtils::IsRetransmittableFrame(ack_frame.type));
diff --git a/quic/core/quic_packet_generator.cc b/quic/core/quic_packet_generator.cc
index 5c1c330..12978a3 100644
--- a/quic/core/quic_packet_generator.cc
+++ b/quic/core/quic_packet_generator.cc
@@ -26,7 +26,8 @@
flusher_attached_(false),
should_send_ack_(false),
should_send_stop_waiting_(false),
- random_generator_(random_generator) {}
+ random_generator_(random_generator),
+ fully_pad_crypto_handshake_packets_(true) {}
QuicPacketGenerator::~QuicPacketGenerator() {
DeleteFrames(&queued_control_frames_);
@@ -93,10 +94,13 @@
HAS_RETRANSMITTABLE_DATA,
has_handshake ? IS_HANDSHAKE : NOT_HANDSHAKE)) {
QuicFrame frame;
+ bool needs_full_padding =
+ has_handshake && fully_pad_crypto_handshake_packets_;
+
if (!packet_creator_.ConsumeData(id, write_length, total_bytes_consumed,
offset + total_bytes_consumed, fin,
- has_handshake, next_transmission_type_,
- &frame)) {
+ needs_full_padding,
+ next_transmission_type_, &frame)) {
// The creator is always flushed if there's not enough room for a new
// stream frame before ConsumeData, so ConsumeData should always succeed.
QUIC_BUG << "Failed to ConsumeData, stream:" << id;
diff --git a/quic/core/quic_packet_generator.h b/quic/core/quic_packet_generator.h
index 18e102c..572d170 100644
--- a/quic/core/quic_packet_generator.h
+++ b/quic/core/quic_packet_generator.h
@@ -221,6 +221,14 @@
bool should_send_ack() const { return should_send_ack_; }
+ void set_fully_pad_crypto_hadshake_packets(bool new_value) {
+ fully_pad_crypto_handshake_packets_ = new_value;
+ }
+
+ bool fully_pad_crypto_handshake_packets() const {
+ return fully_pad_crypto_handshake_packets_;
+ }
+
private:
friend class test::QuicPacketGeneratorPeer;
@@ -265,6 +273,9 @@
QuicStopWaitingFrame pending_stop_waiting_frame_;
QuicRandom* random_generator_;
+
+ // Whether crypto handshake packets should be fully padded.
+ bool fully_pad_crypto_handshake_packets_;
};
} // namespace quic
diff --git a/quic/core/quic_packet_generator_test.cc b/quic/core/quic_packet_generator_test.cc
index b824a5c..b85a4f7 100644
--- a/quic/core/quic_packet_generator_test.cc
+++ b/quic/core/quic_packet_generator_test.cc
@@ -121,7 +121,7 @@
bool fin) {
// Save data before data is consumed.
if (total_length > 0) {
- producer_->SaveStreamData(id, iov, iov_count, 0, offset, total_length);
+ producer_->SaveStreamData(id, iov, iov_count, 0, total_length);
}
return QuicPacketGenerator::ConsumeDataFastPath(id, total_length, offset,
fin, 0);
@@ -135,7 +135,7 @@
StreamSendingState state) {
// Save data before data is consumed.
if (total_length > 0) {
- producer_->SaveStreamData(id, iov, iov_count, 0, offset, total_length);
+ producer_->SaveStreamData(id, iov, iov_count, 0, total_length);
}
return QuicPacketGenerator::ConsumeData(id, total_length, offset, state);
}
@@ -154,7 +154,8 @@
&random_generator_,
&delegate_,
&producer_),
- creator_(QuicPacketGeneratorPeer::GetPacketCreator(&generator_)) {
+ creator_(QuicPacketGeneratorPeer::GetPacketCreator(&generator_)),
+ ack_frame_(InitAckFrame(1)) {
EXPECT_CALL(delegate_, GetPacketBuffer()).WillRepeatedly(Return(nullptr));
creator_->SetEncrypter(
ENCRYPTION_FORWARD_SECURE,
@@ -470,6 +471,35 @@
EXPECT_EQ(kDefaultMaxPacketSize, packets_[0].encrypted_length);
}
+// Test the behavior of ConsumeData when the data is for the crypto handshake
+// stream, but padding is disabled.
+TEST_F(QuicPacketGeneratorTest, ConsumeData_Handshake_PaddingDisabled) {
+ generator_.set_fully_pad_crypto_hadshake_packets(false);
+
+ delegate_.SetCanWriteAnything();
+
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillOnce(Invoke(this, &QuicPacketGeneratorTest::SavePacket));
+ MakeIOVector("foo", &iov_);
+ QuicConsumedData consumed = generator_.ConsumeData(
+ QuicUtils::GetCryptoStreamId(framer_.transport_version()), &iov_, 1u,
+ iov_.iov_len, 0, NO_FIN);
+ EXPECT_EQ(3u, consumed.bytes_consumed);
+ EXPECT_FALSE(generator_.HasQueuedFrames());
+ EXPECT_FALSE(generator_.HasRetransmittableFrames());
+
+ PacketContents contents;
+ contents.num_stream_frames = 1;
+ contents.num_padding_frames = 0;
+ CheckPacketContains(contents, 0);
+
+ ASSERT_EQ(1u, packets_.size());
+
+ // Packet is not fully padded, but we want to future packets to be larger.
+ ASSERT_EQ(kDefaultMaxPacketSize, generator_.GetCurrentMaxPacketLength());
+ EXPECT_EQ(27, packets_[0].encrypted_length);
+}
+
TEST_F(QuicPacketGeneratorTest, ConsumeData_EmptyData) {
EXPECT_QUIC_BUG(generator_.ConsumeData(QuicUtils::GetHeadersStreamId(
framer_.transport_version()),
@@ -829,7 +859,7 @@
QuicConsumedData consumed =
generator_.ConsumeData(stream1_id, &iov_, 1u, iov_.iov_len, 0, NO_FIN);
EXPECT_EQ(data_len, consumed.bytes_consumed);
- ASSERT_EQ(0, creator_->BytesFree())
+ ASSERT_EQ(0u, creator_->BytesFree())
<< "Test setup failed: Please increase data_len to "
<< data_len + creator_->BytesFree() << " bytes.";
@@ -846,9 +876,9 @@
EXPECT_EQ(data_len, consumed.bytes_consumed);
// Ensure the packet is successfully created.
- ASSERT_EQ(1, packets_.size());
+ ASSERT_EQ(1u, packets_.size());
ASSERT_TRUE(packets_[0].encrypted_buffer);
- ASSERT_EQ(1, packets_[0].retransmittable_frames.size());
+ ASSERT_EQ(1u, packets_[0].retransmittable_frames.size());
EXPECT_EQ(stream1_id,
packets_[0].retransmittable_frames[0].stream_frame.stream_id);
if (GetQuicReloadableFlag(quic_set_transmission_type_for_next_frame)) {
diff --git a/quic/core/quic_packet_number.cc b/quic/core/quic_packet_number.cc
new file mode 100644
index 0000000..f0a497f
--- /dev/null
+++ b/quic/core/quic_packet_number.cc
@@ -0,0 +1,132 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/core/quic_packet_number.h"
+
+namespace quic {
+
+QuicPacketNumber::QuicPacketNumber()
+ : packet_number_(UninitializedPacketNumber()) {}
+
+QuicPacketNumber::QuicPacketNumber(uint64_t packet_number)
+ : packet_number_(packet_number) {
+ DCHECK_NE(UninitializedPacketNumber(), packet_number)
+ << "Use default constructor for uninitialized packet number";
+}
+
+void QuicPacketNumber::Clear() {
+ packet_number_ = UninitializedPacketNumber();
+}
+
+uint64_t QuicPacketNumber::Hash() const {
+ DCHECK(IsInitialized());
+ return packet_number_;
+}
+
+uint64_t QuicPacketNumber::ToUint64() const {
+ DCHECK(IsInitialized());
+ return packet_number_;
+}
+
+bool QuicPacketNumber::IsInitialized() const {
+ return packet_number_ != UninitializedPacketNumber();
+}
+
+QuicPacketNumber& QuicPacketNumber::operator++() {
+#ifndef NDEBUG
+ DCHECK(IsInitialized());
+ if (GetQuicRestartFlag(quic_uint64max_uninitialized_pn)) {
+ DCHECK_LT(ToUint64(), std::numeric_limits<uint64_t>::max() - 1);
+ } else {
+ DCHECK_LT(ToUint64(), std::numeric_limits<uint64_t>::max());
+ }
+#endif
+ packet_number_++;
+ return *this;
+}
+
+QuicPacketNumber QuicPacketNumber::operator++(int) {
+#ifndef NDEBUG
+ DCHECK(IsInitialized());
+ if (GetQuicRestartFlag(quic_uint64max_uninitialized_pn)) {
+ DCHECK_LT(ToUint64(), std::numeric_limits<uint64_t>::max() - 1);
+ } else {
+ DCHECK_LT(ToUint64(), std::numeric_limits<uint64_t>::max());
+ }
+#endif
+ QuicPacketNumber previous(*this);
+ packet_number_++;
+ return previous;
+}
+
+QuicPacketNumber& QuicPacketNumber::operator--() {
+#ifndef NDEBUG
+ DCHECK(IsInitialized());
+ if (GetQuicRestartFlag(quic_uint64max_uninitialized_pn)) {
+ DCHECK_GE(ToUint64(), 1);
+ } else {
+ DCHECK_GT(ToUint64(), 1);
+ }
+#endif
+ packet_number_--;
+ return *this;
+}
+
+QuicPacketNumber QuicPacketNumber::operator--(int) {
+#ifndef NDEBUG
+ DCHECK(IsInitialized());
+ if (GetQuicRestartFlag(quic_uint64max_uninitialized_pn)) {
+ DCHECK_GE(ToUint64(), 1);
+ } else {
+ DCHECK_GT(ToUint64(), 1);
+ }
+#endif
+ QuicPacketNumber previous(*this);
+ packet_number_--;
+ return previous;
+}
+
+QuicPacketNumber& QuicPacketNumber::operator+=(uint64_t delta) {
+#ifndef NDEBUG
+ DCHECK(IsInitialized());
+ if (GetQuicRestartFlag(quic_uint64max_uninitialized_pn)) {
+ DCHECK_GT(std::numeric_limits<uint64_t>::max() - ToUint64(), delta);
+ } else {
+ DCHECK_GE(std::numeric_limits<uint64_t>::max() - ToUint64(), delta);
+ }
+#endif
+ packet_number_ += delta;
+ return *this;
+}
+
+QuicPacketNumber& QuicPacketNumber::operator-=(uint64_t delta) {
+#ifndef NDEBUG
+ DCHECK(IsInitialized());
+ if (GetQuicRestartFlag(quic_uint64max_uninitialized_pn)) {
+ DCHECK_GE(ToUint64(), delta);
+ } else {
+ DCHECK_GT(ToUint64(), delta);
+ }
+#endif
+ packet_number_ -= delta;
+ return *this;
+}
+
+std::ostream& operator<<(std::ostream& os, const QuicPacketNumber& p) {
+ if (p.IsInitialized()) {
+ os << p.packet_number_;
+ } else {
+ os << "uninitialized";
+ }
+ return os;
+}
+
+// static
+uint64_t QuicPacketNumber::UninitializedPacketNumber() {
+ return GetQuicRestartFlag(quic_uint64max_uninitialized_pn)
+ ? std::numeric_limits<uint64_t>::max()
+ : 0;
+}
+
+} // namespace quic
diff --git a/quic/core/quic_packet_number.h b/quic/core/quic_packet_number.h
new file mode 100644
index 0000000..6797e3c
--- /dev/null
+++ b/quic/core/quic_packet_number.h
@@ -0,0 +1,154 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_QUIC_CORE_QUIC_PACKET_NUMBER_H_
+#define QUICHE_QUIC_CORE_QUIC_PACKET_NUMBER_H_
+
+#include <limits>
+#include <ostream>
+
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_string.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_uint128.h"
+
+namespace quic {
+
+// QuicPacketNumber can either initialized or uninitialized. An initialized
+// packet number is simply an ordinal number. A sentinel value is used to
+// represent an uninitialized packet number.
+class QUIC_EXPORT_PRIVATE QuicPacketNumber {
+ public:
+ // Construct an uninitialized packet number.
+ QuicPacketNumber();
+ // Construct a packet number from uint64_t. |packet_number| cannot equal the
+ // sentinel value.
+ explicit QuicPacketNumber(uint64_t packet_number);
+
+ // Packet number becomes uninitialized after calling this function.
+ void Clear();
+
+ // REQUIRES: IsInitialized() == true.
+ uint64_t Hash() const;
+
+ // Converts packet number to uint64_t.
+ // REQUIRES: IsInitialized() == true.
+ uint64_t ToUint64() const;
+
+ // Returns true if packet number is considered initialized.
+ bool IsInitialized() const;
+
+ // REQUIRES: IsInitialized() == true && ToUint64() <
+ // numeric_limits<uint64_t>::max() - 1.
+ QuicPacketNumber& operator++();
+ QuicPacketNumber operator++(int);
+ // REQUIRES: IsInitialized() == true && ToUint64() >= 1.
+ QuicPacketNumber& operator--();
+ QuicPacketNumber operator--(int);
+
+ // REQUIRES: IsInitialized() == true && numeric_limits<uint64_t>::max() -
+ // ToUint64() > |delta|.
+ QuicPacketNumber& operator+=(uint64_t delta);
+ // REQUIRES: IsInitialized() == true && ToUint64() >= |delta|.
+ QuicPacketNumber& operator-=(uint64_t delta);
+
+ QUIC_EXPORT_PRIVATE friend std::ostream& operator<<(
+ std::ostream& os,
+ const QuicPacketNumber& p);
+
+ private:
+ // All following operators REQUIRE operands.Initialized() == true.
+ friend inline bool operator==(QuicPacketNumber lhs, QuicPacketNumber rhs);
+ friend inline bool operator!=(QuicPacketNumber lhs, QuicPacketNumber rhs);
+ friend inline bool operator<(QuicPacketNumber lhs, QuicPacketNumber rhs);
+ friend inline bool operator<=(QuicPacketNumber lhs, QuicPacketNumber rhs);
+ friend inline bool operator>(QuicPacketNumber lhs, QuicPacketNumber rhs);
+ friend inline bool operator>=(QuicPacketNumber lhs, QuicPacketNumber rhs);
+
+ // REQUIRES: numeric_limits<uint64_t>::max() - lhs.ToUint64() > |delta|.
+ friend inline QuicPacketNumber operator+(QuicPacketNumber lhs,
+ uint64_t delta);
+ // REQUIRES: lhs.ToUint64() >= |delta|.
+ friend inline QuicPacketNumber operator-(QuicPacketNumber lhs,
+ uint64_t delta);
+ // REQUIRES: lhs >= rhs.
+ friend inline uint64_t operator-(QuicPacketNumber lhs, QuicPacketNumber rhs);
+
+ // The sentinel value representing an uninitialized packet number.
+ static uint64_t UninitializedPacketNumber();
+
+ uint64_t packet_number_;
+};
+
+class QuicPacketNumberHash {
+ public:
+ uint64_t operator()(QuicPacketNumber packet_number) const noexcept {
+ return packet_number.Hash();
+ }
+};
+
+inline bool operator==(QuicPacketNumber lhs, QuicPacketNumber rhs) {
+ DCHECK(lhs.IsInitialized() && rhs.IsInitialized()) << lhs << " vs. " << rhs;
+ return lhs.packet_number_ == rhs.packet_number_;
+}
+
+inline bool operator!=(QuicPacketNumber lhs, QuicPacketNumber rhs) {
+ DCHECK(lhs.IsInitialized() && rhs.IsInitialized()) << lhs << " vs. " << rhs;
+ return lhs.packet_number_ != rhs.packet_number_;
+}
+
+inline bool operator<(QuicPacketNumber lhs, QuicPacketNumber rhs) {
+ DCHECK(lhs.IsInitialized() && rhs.IsInitialized()) << lhs << " vs. " << rhs;
+ return lhs.packet_number_ < rhs.packet_number_;
+}
+
+inline bool operator<=(QuicPacketNumber lhs, QuicPacketNumber rhs) {
+ DCHECK(lhs.IsInitialized() && rhs.IsInitialized()) << lhs << " vs. " << rhs;
+ return lhs.packet_number_ <= rhs.packet_number_;
+}
+
+inline bool operator>(QuicPacketNumber lhs, QuicPacketNumber rhs) {
+ DCHECK(lhs.IsInitialized() && rhs.IsInitialized()) << lhs << " vs. " << rhs;
+ return lhs.packet_number_ > rhs.packet_number_;
+}
+
+inline bool operator>=(QuicPacketNumber lhs, QuicPacketNumber rhs) {
+ DCHECK(lhs.IsInitialized() && rhs.IsInitialized()) << lhs << " vs. " << rhs;
+ return lhs.packet_number_ >= rhs.packet_number_;
+}
+
+inline QuicPacketNumber operator+(QuicPacketNumber lhs, uint64_t delta) {
+#ifndef NDEBUG
+ DCHECK(lhs.IsInitialized());
+ if (GetQuicRestartFlag(quic_uint64max_uninitialized_pn)) {
+ DCHECK_GT(std::numeric_limits<uint64_t>::max() - lhs.ToUint64(), delta);
+ } else {
+ DCHECK_GE(std::numeric_limits<uint64_t>::max() - lhs.ToUint64(), delta);
+ }
+#endif
+ return QuicPacketNumber(lhs.packet_number_ + delta);
+}
+
+inline QuicPacketNumber operator-(QuicPacketNumber lhs, uint64_t delta) {
+#ifndef NDEBUG
+ DCHECK(lhs.IsInitialized());
+ if (GetQuicRestartFlag(quic_uint64max_uninitialized_pn)) {
+ DCHECK_GE(lhs.ToUint64(), delta);
+ } else {
+ DCHECK_GT(lhs.ToUint64(), delta);
+ }
+#endif
+ return QuicPacketNumber(lhs.packet_number_ - delta);
+}
+
+inline uint64_t operator-(QuicPacketNumber lhs, QuicPacketNumber rhs) {
+ DCHECK(lhs.IsInitialized() && rhs.IsInitialized() && lhs >= rhs)
+ << lhs << " vs. " << rhs;
+ return lhs.packet_number_ - rhs.packet_number_;
+}
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_QUIC_PACKET_NUMBER_H_
diff --git a/quic/core/quic_packet_number_test.cc b/quic/core/quic_packet_number_test.cc
new file mode 100644
index 0000000..5e32b8c
--- /dev/null
+++ b/quic/core/quic_packet_number_test.cc
@@ -0,0 +1,83 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/core/quic_packet_number.h"
+
+#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+
+namespace quic {
+
+namespace test {
+
+namespace {
+
+TEST(QuicPacketNumberTest, BasicTest) {
+ QuicPacketNumber num;
+ EXPECT_FALSE(num.IsInitialized());
+
+ QuicPacketNumber num2(10);
+ EXPECT_TRUE(num2.IsInitialized());
+ EXPECT_EQ(10u, num2.ToUint64());
+ EXPECT_EQ(10u, num2.Hash());
+ num2.Clear();
+ EXPECT_FALSE(num2.IsInitialized());
+
+ if (!GetQuicRestartFlag(quic_uint64max_uninitialized_pn)) {
+ QuicPacketNumber num3(std::numeric_limits<uint64_t>::max());
+ EXPECT_TRUE(num3.IsInitialized());
+ EXPECT_EQ(std::numeric_limits<uint64_t>::max(), num3.ToUint64());
+ EXPECT_EQ(std::numeric_limits<uint64_t>::max(), num3.Hash());
+ num3.Clear();
+ EXPECT_FALSE(num3.IsInitialized());
+ return;
+ }
+
+ QuicPacketNumber num4(0);
+ EXPECT_TRUE(num4.IsInitialized());
+ EXPECT_EQ(0u, num4.ToUint64());
+ EXPECT_EQ(0u, num4.Hash());
+ num4.Clear();
+ EXPECT_FALSE(num4.IsInitialized());
+}
+
+TEST(QuicPacketNumberTest, Operators) {
+ QuicPacketNumber num(100);
+ EXPECT_EQ(QuicPacketNumber(100), num++);
+ EXPECT_EQ(QuicPacketNumber(101), num);
+ EXPECT_EQ(QuicPacketNumber(101), num--);
+ EXPECT_EQ(QuicPacketNumber(100), num);
+
+ EXPECT_EQ(QuicPacketNumber(101), ++num);
+ EXPECT_EQ(QuicPacketNumber(100), --num);
+
+ if (!GetQuicRestartFlag(quic_uint64max_uninitialized_pn)) {
+ QuicPacketNumber num2(std::numeric_limits<uint64_t>::max());
+ EXPECT_EQ(QuicPacketNumber(std::numeric_limits<uint64_t>::max()), num2--);
+ EXPECT_EQ(QuicPacketNumber(std::numeric_limits<uint64_t>::max() - 1), num2);
+ EXPECT_EQ(QuicPacketNumber(std::numeric_limits<uint64_t>::max() - 2),
+ --num2);
+
+ EXPECT_EQ(QuicPacketNumber(std::numeric_limits<uint64_t>::max() - 2),
+ num2++);
+ EXPECT_EQ(QuicPacketNumber(std::numeric_limits<uint64_t>::max() - 1), num2);
+ EXPECT_EQ(QuicPacketNumber(std::numeric_limits<uint64_t>::max()), ++num2);
+ return;
+ }
+
+ QuicPacketNumber num3(0);
+ EXPECT_EQ(QuicPacketNumber(0), num3++);
+ EXPECT_EQ(QuicPacketNumber(1), num3);
+ EXPECT_EQ(QuicPacketNumber(2), ++num3);
+
+ EXPECT_EQ(QuicPacketNumber(2), num3--);
+ EXPECT_EQ(QuicPacketNumber(1), num3);
+ EXPECT_EQ(QuicPacketNumber(0), --num3);
+}
+
+} // namespace
+
+} // namespace test
+
+} // namespace quic
diff --git a/quic/core/quic_packets.cc b/quic/core/quic_packets.cc
index ca0ad6d..5e3ba76 100644
--- a/quic/core/quic_packets.cc
+++ b/quic/core/quic_packets.cc
@@ -33,8 +33,8 @@
// Long header.
return kPacketHeaderTypeSize + kConnectionIdLengthSize +
destination_connection_id_length + source_connection_id_length +
- (version == QUIC_VERSION_99 ? packet_number_length
- : PACKET_4BYTE_PACKET_NUMBER) +
+ (version > QUIC_VERSION_46 ? packet_number_length
+ : PACKET_4BYTE_PACKET_NUMBER) +
kQuicVersionSize +
(include_diversification_nonce ? kDiversificationNonceSize : 0);
}
@@ -74,10 +74,8 @@
version_flag(false),
has_possible_stateless_reset_token(false),
packet_number_length(PACKET_4BYTE_PACKET_NUMBER),
- version(
- ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED)),
+ version(UnsupportedQuicVersion()),
nonce(nullptr),
- packet_number(kInvalidPacketNumber),
form(GOOGLE_QUIC_PACKET),
long_packet_type(INITIAL),
possible_stateless_reset_token(0) {}
@@ -294,9 +292,7 @@
encryption_level(ENCRYPTION_NONE),
has_ack(has_ack),
has_stop_waiting(has_stop_waiting),
- transmission_type(NOT_RETRANSMISSION),
- original_packet_number(kInvalidPacketNumber),
- largest_acked(kInvalidPacketNumber) {}
+ transmission_type(NOT_RETRANSMISSION) {}
SerializedPacket::SerializedPacket(const SerializedPacket& other) = default;
@@ -327,7 +323,7 @@
}
serialized_packet->encrypted_buffer = nullptr;
serialized_packet->encrypted_length = 0;
- serialized_packet->largest_acked = kInvalidPacketNumber;
+ serialized_packet->largest_acked.Clear();
}
char* CopyBuffer(const SerializedPacket& packet) {
diff --git a/quic/core/quic_received_packet_manager.cc b/quic/core/quic_received_packet_manager.cc
index d33c756..8189ff8 100644
--- a/quic/core/quic_received_packet_manager.cc
+++ b/quic/core/quic_received_packet_manager.cc
@@ -25,8 +25,7 @@
} // namespace
QuicReceivedPacketManager::QuicReceivedPacketManager(QuicConnectionStats* stats)
- : peer_least_packet_awaiting_ack_(0),
- ack_frame_updated_(false),
+ : ack_frame_updated_(false),
max_ack_ranges_(0),
time_largest_observed_(QuicTime::Zero()),
save_timestamps_(false),
@@ -44,7 +43,8 @@
}
ack_frame_updated_ = true;
- if (LargestAcked(ack_frame_) > packet_number) {
+ if (LargestAcked(ack_frame_).IsInitialized() &&
+ LargestAcked(ack_frame_) > packet_number) {
// Record how out of order stats.
++stats_->packets_reordered;
stats_->max_sequence_reordering =
@@ -55,7 +55,8 @@
stats_->max_time_reordering_us =
std::max(stats_->max_time_reordering_us, reordering_time_us);
}
- if (packet_number > LargestAcked(ack_frame_)) {
+ if (!LargestAcked(ack_frame_).IsInitialized() ||
+ packet_number > LargestAcked(ack_frame_)) {
ack_frame_.largest_acked = packet_number;
time_largest_observed_ = receipt_time;
}
@@ -77,7 +78,8 @@
}
bool QuicReceivedPacketManager::IsMissing(QuicPacketNumber packet_number) {
- return packet_number < LargestAcked(ack_frame_) &&
+ return LargestAcked(ack_frame_).IsInitialized() &&
+ packet_number < LargestAcked(ack_frame_) &&
!ack_frame_.packets.Contains(packet_number);
}
@@ -120,9 +122,14 @@
void QuicReceivedPacketManager::DontWaitForPacketsBefore(
QuicPacketNumber least_unacked) {
+ if (!least_unacked.IsInitialized()) {
+ return;
+ }
// ValidateAck() should fail if peer_least_packet_awaiting_ack shrinks.
- DCHECK_LE(peer_least_packet_awaiting_ack_, least_unacked);
- if (least_unacked > peer_least_packet_awaiting_ack_) {
+ DCHECK(!peer_least_packet_awaiting_ack_.IsInitialized() ||
+ peer_least_packet_awaiting_ack_ <= least_unacked);
+ if (!peer_least_packet_awaiting_ack_.IsInitialized() ||
+ least_unacked > peer_least_packet_awaiting_ack_) {
peer_least_packet_awaiting_ack_ = least_unacked;
bool packets_updated = ack_frame_.packets.RemoveUpTo(least_unacked);
if (packets_updated) {
@@ -132,14 +139,23 @@
}
}
DCHECK(ack_frame_.packets.Empty() ||
+ !peer_least_packet_awaiting_ack_.IsInitialized() ||
ack_frame_.packets.Min() >= peer_least_packet_awaiting_ack_);
}
bool QuicReceivedPacketManager::HasMissingPackets() const {
- return ack_frame_.packets.NumIntervals() > 1 ||
- (!ack_frame_.packets.Empty() &&
- ack_frame_.packets.Min() >
- std::max(QuicPacketNumber(1), peer_least_packet_awaiting_ack_));
+ if (ack_frame_.packets.Empty()) {
+ return false;
+ }
+ if (ack_frame_.packets.NumIntervals() > 1) {
+ return true;
+ }
+ // TODO(fayang): Fix this as this check assumes first sent packet by peer
+ // is 1.
+ return ack_frame_.packets.Min() >
+ (peer_least_packet_awaiting_ack_.IsInitialized()
+ ? peer_least_packet_awaiting_ack_
+ : QuicPacketNumber(1));
}
bool QuicReceivedPacketManager::HasNewMissingPackets() const {
diff --git a/quic/core/quic_received_packet_manager_test.cc b/quic/core/quic_received_packet_manager_test.cc
index 7d8c811..b8264a5 100644
--- a/quic/core/quic_received_packet_manager_test.cc
+++ b/quic/core/quic_received_packet_manager_test.cc
@@ -42,14 +42,13 @@
received_manager_.set_save_timestamps(true);
}
- void RecordPacketReceipt(QuicPacketNumber packet_number) {
+ void RecordPacketReceipt(uint64_t packet_number) {
RecordPacketReceipt(packet_number, QuicTime::Zero());
}
- void RecordPacketReceipt(QuicPacketNumber packet_number,
- QuicTime receipt_time) {
+ void RecordPacketReceipt(uint64_t packet_number, QuicTime receipt_time) {
QuicPacketHeader header;
- header.packet_number = packet_number;
+ header.packet_number = QuicPacketNumber(packet_number);
received_manager_.RecordPacketReceived(header, receipt_time);
}
@@ -63,20 +62,20 @@
TEST_P(QuicReceivedPacketManagerTest, DontWaitForPacketsBefore) {
QuicPacketHeader header;
- header.packet_number = 2u;
+ header.packet_number = QuicPacketNumber(2u);
received_manager_.RecordPacketReceived(header, QuicTime::Zero());
- header.packet_number = 7u;
+ header.packet_number = QuicPacketNumber(7u);
received_manager_.RecordPacketReceived(header, QuicTime::Zero());
- EXPECT_TRUE(received_manager_.IsAwaitingPacket(3u));
- EXPECT_TRUE(received_manager_.IsAwaitingPacket(6u));
- received_manager_.DontWaitForPacketsBefore(4);
- EXPECT_FALSE(received_manager_.IsAwaitingPacket(3u));
- EXPECT_TRUE(received_manager_.IsAwaitingPacket(6u));
+ EXPECT_TRUE(received_manager_.IsAwaitingPacket(QuicPacketNumber(3u)));
+ EXPECT_TRUE(received_manager_.IsAwaitingPacket(QuicPacketNumber(6u)));
+ received_manager_.DontWaitForPacketsBefore(QuicPacketNumber(4));
+ EXPECT_FALSE(received_manager_.IsAwaitingPacket(QuicPacketNumber(3u)));
+ EXPECT_TRUE(received_manager_.IsAwaitingPacket(QuicPacketNumber(6u)));
}
TEST_P(QuicReceivedPacketManagerTest, GetUpdatedAckFrame) {
QuicPacketHeader header;
- header.packet_number = 2u;
+ header.packet_number = QuicPacketNumber(2u);
QuicTime two_ms = QuicTime::Zero() + QuicTime::Delta::FromMilliseconds(2);
EXPECT_FALSE(received_manager_.ack_frame_updated());
received_manager_.RecordPacketReceived(header, two_ms);
@@ -99,11 +98,11 @@
// And received packet times won't have change.
EXPECT_EQ(1u, ack.ack_frame->received_packet_times.size());
- header.packet_number = 999u;
+ header.packet_number = QuicPacketNumber(999u);
received_manager_.RecordPacketReceived(header, two_ms);
- header.packet_number = 4u;
+ header.packet_number = QuicPacketNumber(4u);
received_manager_.RecordPacketReceived(header, two_ms);
- header.packet_number = 1000u;
+ header.packet_number = QuicPacketNumber(1000u);
received_manager_.RecordPacketReceived(header, two_ms);
EXPECT_TRUE(received_manager_.ack_frame_updated());
ack = received_manager_.GetUpdatedAckFrame(two_ms);
@@ -134,11 +133,16 @@
EXPECT_TRUE(received_manager_.ack_frame_updated());
received_manager_.GetUpdatedAckFrame(QuicTime::Zero());
EXPECT_GE(10u, received_manager_.ack_frame().packets.NumIntervals());
- EXPECT_EQ(1u + 2 * i, received_manager_.ack_frame().packets.Max());
+ EXPECT_EQ(QuicPacketNumber(1u + 2 * i),
+ received_manager_.ack_frame().packets.Max());
for (int j = 0; j < std::min(10, i + 1); ++j) {
- EXPECT_TRUE(
- received_manager_.ack_frame().packets.Contains(1 + (i - j) * 2));
- EXPECT_FALSE(received_manager_.ack_frame().packets.Contains((i - j) * 2));
+ ASSERT_GE(i, j);
+ EXPECT_TRUE(received_manager_.ack_frame().packets.Contains(
+ QuicPacketNumber(1 + (i - j) * 2)));
+ if (i > j) {
+ EXPECT_FALSE(received_manager_.ack_frame().packets.Contains(
+ QuicPacketNumber((i - j) * 2)));
+ }
}
}
}
diff --git a/quic/core/quic_sent_packet_manager.cc b/quic/core/quic_sent_packet_manager.cc
index 783a78c..4bbe070 100644
--- a/quic/core/quic_sent_packet_manager.cc
+++ b/quic/core/quic_sent_packet_manager.cc
@@ -86,7 +86,6 @@
loss_algorithm_(&general_loss_algorithm_),
general_loss_algorithm_(loss_type),
n_connection_simulation_(false),
- first_rto_transmission_(0),
consecutive_rto_count_(0),
consecutive_tlp_count_(0),
consecutive_crypto_retransmission_count_(0),
@@ -103,10 +102,8 @@
QuicTime::Delta::FromMilliseconds(kMinRetransmissionTimeMs)),
ietf_style_tlp_(false),
ietf_style_2x_tlp_(false),
- largest_newly_acked_(0),
largest_mtu_acked_(0),
handshake_confirmed_(false),
- largest_packet_peer_knows_is_acked_(0),
delayed_ack_time_(
QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs)),
rtt_updated_(false),
@@ -452,7 +449,7 @@
} else {
// Clear the recorded first packet sent after loss when version or
// encryption changes.
- transmission_info->retransmission = kInvalidPacketNumber;
+ transmission_info->retransmission.Clear();
}
}
@@ -479,7 +476,7 @@
return;
}
QuicPacketNumber retransmission = info.retransmission;
- while (retransmission != kInvalidPacketNumber) {
+ while (retransmission.IsInitialized()) {
const QuicTransmissionInfo& retransmit_info =
unacked_packets_.GetTransmissionInfo(retransmission);
retransmission = retransmit_info.retransmission;
@@ -529,7 +526,7 @@
return packet_number;
}
QuicPacketNumber retransmission = transmission_info.retransmission;
- while (retransmission != kInvalidPacketNumber) {
+ while (retransmission.IsInitialized()) {
packet_number = retransmission;
retransmission =
unacked_packets_.GetTransmissionInfo(retransmission).retransmission;
@@ -607,12 +604,12 @@
TransmissionType transmission_type,
HasRetransmittableData has_retransmittable_data) {
QuicPacketNumber packet_number = serialized_packet->packet_number;
- DCHECK_LT(0u, packet_number);
+ DCHECK_LE(FirstSendingPacketNumber(), packet_number);
DCHECK(!unacked_packets_.IsUnacked(packet_number));
QUIC_BUG_IF(serialized_packet->encrypted_length == 0)
<< "Cannot send empty packets.";
- if (original_packet_number != kInvalidPacketNumber) {
+ if (original_packet_number.IsInitialized()) {
pending_retransmissions_.erase(original_packet_number);
}
@@ -758,7 +755,7 @@
}
// Abandon non-retransmittable data that's in flight to ensure it doesn't
// fill up the congestion window.
- bool has_retransmissions = it->retransmission != kInvalidPacketNumber;
+ bool has_retransmissions = it->retransmission.IsInitialized();
if (session_decides_what_to_write()) {
has_retransmissions = it->state != OUTSTANDING;
}
@@ -1051,21 +1048,23 @@
DCHECK_LE(largest_acked, unacked_packets_.largest_sent_packet());
rtt_updated_ =
MaybeUpdateRTT(largest_acked, ack_delay_time, ack_receive_time);
- DCHECK_GE(largest_acked, unacked_packets_.largest_acked());
+ DCHECK(!unacked_packets_.largest_acked().IsInitialized() ||
+ largest_acked >= unacked_packets_.largest_acked());
last_ack_frame_.ack_delay_time = ack_delay_time;
acked_packets_iter_ = last_ack_frame_.packets.rbegin();
}
void QuicSentPacketManager::OnAckRange(QuicPacketNumber start,
QuicPacketNumber end) {
- if (end > last_ack_frame_.largest_acked + 1) {
+ if (!last_ack_frame_.largest_acked.IsInitialized() ||
+ end > last_ack_frame_.largest_acked + 1) {
// Largest acked increases.
unacked_packets_.IncreaseLargestAcked(end - 1);
last_ack_frame_.largest_acked = end - 1;
}
// Drop ack ranges which ack packets below least_unacked.
QuicPacketNumber least_unacked = unacked_packets_.GetLeastUnacked();
- if (end <= least_unacked) {
+ if (least_unacked.IsInitialized() && end <= least_unacked) {
return;
}
start = std::max(start, least_unacked);
@@ -1079,6 +1078,9 @@
// Check if end is above the current range. If so add newly acked packets
// in descending order.
packets_acked_.push_back(AckedPacket(acked, 0, QuicTime::Zero()));
+ if (acked == FirstSendingPacketNumber()) {
+ break;
+ }
}
if (acked_packets_iter_ == last_ack_frame_.packets.rend() ||
start > acked_packets_iter_->min()) {
@@ -1125,9 +1127,13 @@
QUIC_DVLOG(1) << ENDPOINT << "Got an ack for packet "
<< acked_packet.packet_number;
last_ack_frame_.packets.Add(acked_packet.packet_number);
- if (info->largest_acked > kInvalidPacketNumber) {
- largest_packet_peer_knows_is_acked_ =
- std::max(largest_packet_peer_knows_is_acked_, info->largest_acked);
+ if (info->largest_acked.IsInitialized()) {
+ if (largest_packet_peer_knows_is_acked_.IsInitialized()) {
+ largest_packet_peer_knows_is_acked_ =
+ std::max(largest_packet_peer_knows_is_acked_, info->largest_acked);
+ } else {
+ largest_packet_peer_knows_is_acked_ = info->largest_acked;
+ }
}
// If data is associated with the most recent transmission of this
// packet, then inform the caller.
diff --git a/quic/core/quic_sent_packet_manager.h b/quic/core/quic_sent_packet_manager.h
index 7b2501a..aad16e2 100644
--- a/quic/core/quic_sent_packet_manager.h
+++ b/quic/core/quic_sent_packet_manager.h
@@ -368,7 +368,9 @@
LOSS_MODE,
};
- typedef QuicLinkedHashMap<QuicPacketNumber, TransmissionType>
+ typedef QuicLinkedHashMap<QuicPacketNumber,
+ TransmissionType,
+ QuicPacketNumberHash>
PendingRetransmissionMap;
// Returns the current retransmission mode.
diff --git a/quic/core/quic_sent_packet_manager_test.cc b/quic/core/quic_sent_packet_manager_test.cc
index 865f181..97e1697 100644
--- a/quic/core/quic_sent_packet_manager_test.cc
+++ b/quic/core/quic_sent_packet_manager_test.cc
@@ -38,7 +38,8 @@
// Matcher to check that the packet number matches the second argument.
MATCHER(PacketNumberEq, "") {
- return ::testing::get<0>(arg).packet_number == ::testing::get<1>(arg);
+ return ::testing::get<0>(arg).packet_number ==
+ QuicPacketNumber(::testing::get<1>(arg));
}
class MockDebugDelegate : public QuicSentPacketManager::DebugDelegate {
@@ -54,25 +55,26 @@
class QuicSentPacketManagerTest : public QuicTestWithParam<bool> {
public:
- void RetransmitCryptoPacket(QuicPacketNumber packet_number) {
- EXPECT_CALL(*send_algorithm_,
- OnPacketSent(_, BytesInFlight(), packet_number, kDefaultLength,
- HAS_RETRANSMITTABLE_DATA));
+ void RetransmitCryptoPacket(uint64_t packet_number) {
+ EXPECT_CALL(
+ *send_algorithm_,
+ OnPacketSent(_, BytesInFlight(), QuicPacketNumber(packet_number),
+ kDefaultLength, HAS_RETRANSMITTABLE_DATA));
SerializedPacket packet(CreatePacket(packet_number, false));
packet.retransmittable_frames.push_back(
QuicFrame(QuicStreamFrame(1, false, 0, QuicStringPiece())));
packet.has_crypto_handshake = IS_HANDSHAKE;
- manager_.OnPacketSent(&packet, 0, clock_.Now(), HANDSHAKE_RETRANSMISSION,
- HAS_RETRANSMITTABLE_DATA);
+ manager_.OnPacketSent(&packet, QuicPacketNumber(), clock_.Now(),
+ HANDSHAKE_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
}
- void RetransmitDataPacket(QuicPacketNumber packet_number,
- TransmissionType type) {
- EXPECT_CALL(*send_algorithm_,
- OnPacketSent(_, BytesInFlight(), packet_number, kDefaultLength,
- HAS_RETRANSMITTABLE_DATA));
+ void RetransmitDataPacket(uint64_t packet_number, TransmissionType type) {
+ EXPECT_CALL(
+ *send_algorithm_,
+ OnPacketSent(_, BytesInFlight(), QuicPacketNumber(packet_number),
+ kDefaultLength, HAS_RETRANSMITTABLE_DATA));
SerializedPacket packet(CreatePacket(packet_number, true));
- manager_.OnPacketSent(&packet, 0, clock_.Now(), type,
+ manager_.OnPacketSent(&packet, QuicPacketNumber(), clock_.Now(), type,
HAS_RETRANSMITTABLE_DATA);
}
@@ -111,7 +113,7 @@
QuicByteCount BytesInFlight() {
return QuicSentPacketManagerPeer::GetBytesInFlight(&manager_);
}
- void VerifyUnackedPackets(QuicPacketNumber* packets, size_t num_packets) {
+ void VerifyUnackedPackets(uint64_t* packets, size_t num_packets) {
if (num_packets == 0) {
EXPECT_TRUE(manager_.unacked_packets().empty());
EXPECT_EQ(0u, QuicSentPacketManagerPeer::GetNumRetransmittablePackets(
@@ -120,15 +122,14 @@
}
EXPECT_FALSE(manager_.unacked_packets().empty());
- EXPECT_EQ(packets[0], manager_.GetLeastUnacked());
+ EXPECT_EQ(QuicPacketNumber(packets[0]), manager_.GetLeastUnacked());
for (size_t i = 0; i < num_packets; ++i) {
EXPECT_TRUE(QuicSentPacketManagerPeer::IsUnacked(&manager_, packets[i]))
<< packets[i];
}
}
- void VerifyRetransmittablePackets(QuicPacketNumber* packets,
- size_t num_packets) {
+ void VerifyRetransmittablePackets(uint64_t* packets, size_t num_packets) {
EXPECT_EQ(
num_packets,
QuicSentPacketManagerPeer::GetNumRetransmittablePackets(&manager_));
@@ -139,7 +140,7 @@
}
}
- void ExpectAck(QuicPacketNumber largest_observed) {
+ void ExpectAck(uint64_t largest_observed) {
EXPECT_CALL(
*send_algorithm_,
// Ensure the AckedPacketVector argument contains largest_observed.
@@ -149,15 +150,15 @@
EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
}
- void ExpectUpdatedRtt(QuicPacketNumber largest_observed) {
+ void ExpectUpdatedRtt(uint64_t largest_observed) {
EXPECT_CALL(*send_algorithm_,
OnCongestionEvent(true, _, _, IsEmpty(), IsEmpty()));
EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
}
void ExpectAckAndLoss(bool rtt_updated,
- QuicPacketNumber largest_observed,
- QuicPacketNumber lost_packet) {
+ uint64_t largest_observed,
+ uint64_t lost_packet) {
EXPECT_CALL(
*send_algorithm_,
OnCongestionEvent(rtt_updated, _, _,
@@ -168,17 +169,17 @@
// |packets_acked| and |packets_lost| should be in packet number order.
void ExpectAcksAndLosses(bool rtt_updated,
- QuicPacketNumber* packets_acked,
+ uint64_t* packets_acked,
size_t num_packets_acked,
- QuicPacketNumber* packets_lost,
+ uint64_t* packets_lost,
size_t num_packets_lost) {
std::vector<QuicPacketNumber> ack_vector;
for (size_t i = 0; i < num_packets_acked; ++i) {
- ack_vector.push_back(packets_acked[i]);
+ ack_vector.push_back(QuicPacketNumber(packets_acked[i]));
}
std::vector<QuicPacketNumber> lost_vector;
for (size_t i = 0; i < num_packets_lost; ++i) {
- lost_vector.push_back(packets_lost[i]);
+ lost_vector.push_back(QuicPacketNumber(packets_lost[i]));
}
EXPECT_CALL(*send_algorithm_,
OnCongestionEvent(rtt_updated, _, _,
@@ -188,14 +189,14 @@
.Times(AnyNumber());
}
- void RetransmitAndSendPacket(QuicPacketNumber old_packet_number,
- QuicPacketNumber new_packet_number) {
+ void RetransmitAndSendPacket(uint64_t old_packet_number,
+ uint64_t new_packet_number) {
RetransmitAndSendPacket(old_packet_number, new_packet_number,
TLP_RETRANSMISSION);
}
- void RetransmitAndSendPacket(QuicPacketNumber old_packet_number,
- QuicPacketNumber new_packet_number,
+ void RetransmitAndSendPacket(uint64_t old_packet_number,
+ uint64_t new_packet_number,
TransmissionType transmission_type) {
bool is_lost = false;
if (manager_.session_decides_what_to_write()) {
@@ -219,38 +220,42 @@
if (!is_lost) {
return;
}
- EXPECT_CALL(*send_algorithm_,
- OnPacketSent(_, BytesInFlight(), new_packet_number,
- kDefaultLength, HAS_RETRANSMITTABLE_DATA));
+ EXPECT_CALL(
+ *send_algorithm_,
+ OnPacketSent(_, BytesInFlight(), QuicPacketNumber(new_packet_number),
+ kDefaultLength, HAS_RETRANSMITTABLE_DATA));
SerializedPacket packet(CreatePacket(new_packet_number, true));
- manager_.OnPacketSent(&packet, 0, clock_.Now(), transmission_type,
- HAS_RETRANSMITTABLE_DATA);
+ manager_.OnPacketSent(&packet, QuicPacketNumber(), clock_.Now(),
+ transmission_type, HAS_RETRANSMITTABLE_DATA);
return;
}
EXPECT_TRUE(manager_.HasPendingRetransmissions());
QuicPendingRetransmission next_retransmission =
manager_.NextPendingRetransmission();
- EXPECT_EQ(old_packet_number, next_retransmission.packet_number);
+ EXPECT_EQ(QuicPacketNumber(old_packet_number),
+ next_retransmission.packet_number);
EXPECT_EQ(transmission_type, next_retransmission.transmission_type);
- EXPECT_CALL(*send_algorithm_,
- OnPacketSent(_, BytesInFlight(), new_packet_number,
- kDefaultLength, HAS_RETRANSMITTABLE_DATA));
+ EXPECT_CALL(
+ *send_algorithm_,
+ OnPacketSent(_, BytesInFlight(), QuicPacketNumber(new_packet_number),
+ kDefaultLength, HAS_RETRANSMITTABLE_DATA));
SerializedPacket packet(CreatePacket(new_packet_number, false));
- manager_.OnPacketSent(&packet, old_packet_number, clock_.Now(),
- transmission_type, HAS_RETRANSMITTABLE_DATA);
+ manager_.OnPacketSent(&packet, QuicPacketNumber(old_packet_number),
+ clock_.Now(), transmission_type,
+ HAS_RETRANSMITTABLE_DATA);
EXPECT_TRUE(QuicSentPacketManagerPeer::IsRetransmission(&manager_,
new_packet_number));
}
- SerializedPacket CreateDataPacket(QuicPacketNumber packet_number) {
+ SerializedPacket CreateDataPacket(uint64_t packet_number) {
return CreatePacket(packet_number, true);
}
- SerializedPacket CreatePacket(QuicPacketNumber packet_number,
- bool retransmittable) {
- SerializedPacket packet(packet_number, PACKET_4BYTE_PACKET_NUMBER, nullptr,
- kDefaultLength, false, false);
+ SerializedPacket CreatePacket(uint64_t packet_number, bool retransmittable) {
+ SerializedPacket packet(QuicPacketNumber(packet_number),
+ PACKET_4BYTE_PACKET_NUMBER, nullptr, kDefaultLength,
+ false, false);
if (retransmittable) {
packet.retransmittable_frames.push_back(
QuicFrame(QuicStreamFrame(kStreamId, false, 0, QuicStringPiece())));
@@ -258,47 +263,50 @@
return packet;
}
- void SendDataPacket(QuicPacketNumber packet_number) {
+ void SendDataPacket(uint64_t packet_number) {
EXPECT_CALL(*send_algorithm_,
- OnPacketSent(_, BytesInFlight(), packet_number, _, _));
+ OnPacketSent(_, BytesInFlight(),
+ QuicPacketNumber(packet_number), _, _));
SerializedPacket packet(CreateDataPacket(packet_number));
- manager_.OnPacketSent(&packet, 0, clock_.Now(), NOT_RETRANSMISSION,
- HAS_RETRANSMITTABLE_DATA);
+ manager_.OnPacketSent(&packet, QuicPacketNumber(), clock_.Now(),
+ NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
}
- void SendCryptoPacket(QuicPacketNumber packet_number) {
- EXPECT_CALL(*send_algorithm_,
- OnPacketSent(_, BytesInFlight(), packet_number, kDefaultLength,
- HAS_RETRANSMITTABLE_DATA));
+ void SendCryptoPacket(uint64_t packet_number) {
+ EXPECT_CALL(
+ *send_algorithm_,
+ OnPacketSent(_, BytesInFlight(), QuicPacketNumber(packet_number),
+ kDefaultLength, HAS_RETRANSMITTABLE_DATA));
SerializedPacket packet(CreatePacket(packet_number, false));
packet.retransmittable_frames.push_back(
QuicFrame(QuicStreamFrame(1, false, 0, QuicStringPiece())));
packet.has_crypto_handshake = IS_HANDSHAKE;
- manager_.OnPacketSent(&packet, 0, clock_.Now(), NOT_RETRANSMISSION,
- HAS_RETRANSMITTABLE_DATA);
+ manager_.OnPacketSent(&packet, QuicPacketNumber(), clock_.Now(),
+ NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
if (manager_.session_decides_what_to_write()) {
EXPECT_CALL(notifier_, HasUnackedCryptoData())
.WillRepeatedly(Return(true));
}
}
- void SendAckPacket(QuicPacketNumber packet_number,
- QuicPacketNumber largest_acked) {
- EXPECT_CALL(*send_algorithm_,
- OnPacketSent(_, BytesInFlight(), packet_number, kDefaultLength,
- NO_RETRANSMITTABLE_DATA));
+ void SendAckPacket(uint64_t packet_number, uint64_t largest_acked) {
+ EXPECT_CALL(
+ *send_algorithm_,
+ OnPacketSent(_, BytesInFlight(), QuicPacketNumber(packet_number),
+ kDefaultLength, NO_RETRANSMITTABLE_DATA));
SerializedPacket packet(CreatePacket(packet_number, false));
- packet.largest_acked = largest_acked;
- manager_.OnPacketSent(&packet, 0, clock_.Now(), NOT_RETRANSMISSION,
- NO_RETRANSMITTABLE_DATA);
+ packet.largest_acked = QuicPacketNumber(largest_acked);
+ manager_.OnPacketSent(&packet, QuicPacketNumber(), clock_.Now(),
+ NOT_RETRANSMISSION, NO_RETRANSMITTABLE_DATA);
}
// Based on QuicConnection's WritePendingRetransmissions.
- void RetransmitNextPacket(QuicPacketNumber retransmission_packet_number) {
+ void RetransmitNextPacket(uint64_t retransmission_packet_number) {
EXPECT_TRUE(manager_.HasPendingRetransmissions());
- EXPECT_CALL(*send_algorithm_,
- OnPacketSent(_, _, retransmission_packet_number, kDefaultLength,
- HAS_RETRANSMITTABLE_DATA));
+ EXPECT_CALL(
+ *send_algorithm_,
+ OnPacketSent(_, _, QuicPacketNumber(retransmission_packet_number),
+ kDefaultLength, HAS_RETRANSMITTABLE_DATA));
const QuicPendingRetransmission pending =
manager_.NextPendingRetransmission();
SerializedPacket packet(CreatePacket(retransmission_packet_number, false));
@@ -320,9 +328,9 @@
VerifyUnackedPackets(nullptr, 0);
SendDataPacket(1);
- QuicPacketNumber unacked[] = {1};
+ uint64_t unacked[] = {1};
VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
- QuicPacketNumber retransmittable[] = {1};
+ uint64_t retransmittable[] = {1};
VerifyRetransmittablePackets(retransmittable,
QUIC_ARRAYSIZE(retransmittable));
}
@@ -332,9 +340,9 @@
RetransmitAndSendPacket(1, 2);
EXPECT_TRUE(QuicSentPacketManagerPeer::IsRetransmission(&manager_, 2));
- QuicPacketNumber unacked[] = {1, 2};
+ uint64_t unacked[] = {1, 2};
VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
- std::vector<QuicPacketNumber> retransmittable;
+ std::vector<uint64_t> retransmittable;
if (manager_.session_decides_what_to_write()) {
retransmittable = {1, 2};
} else {
@@ -349,14 +357,15 @@
// Ack 2 but not 1.
ExpectAck(2);
- manager_.OnAckFrameStart(2, QuicTime::Delta::Infinite(), clock_.Now());
- manager_.OnAckRange(2, 3);
+ manager_.OnAckFrameStart(QuicPacketNumber(2), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(2), QuicPacketNumber(3));
EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
if (manager_.session_decides_what_to_write()) {
EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
}
// Packet 1 is unacked, pending, but not retransmittable.
- QuicPacketNumber unacked[] = {1};
+ uint64_t unacked[] = {1};
VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
EXPECT_TRUE(QuicSentPacketManagerPeer::HasPendingPackets(&manager_));
VerifyRetransmittablePackets(nullptr, 0);
@@ -379,8 +388,9 @@
}
// Ack 1.
ExpectAck(1);
- manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite(), clock_.Now());
- manager_.OnAckRange(1, 2);
+ manager_.OnAckFrameStart(QuicPacketNumber(1), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2));
EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
// There should no longer be a pending retransmission.
@@ -388,7 +398,7 @@
if (manager_.session_decides_what_to_write()) {
EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
- QuicPacketNumber unacked[] = {2};
+ uint64_t unacked[] = {2};
VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
// We do not know packet 2 is a spurious retransmission until it gets acked.
} else {
@@ -418,7 +428,7 @@
// There should no longer be a pending retransmission.
EXPECT_FALSE(manager_.HasPendingRetransmissions());
- QuicPacketNumber unacked[] = {1};
+ uint64_t unacked[] = {1};
VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
VerifyRetransmittablePackets(nullptr, 0);
EXPECT_EQ(0u, stats_.packets_spuriously_retransmitted);
@@ -432,14 +442,15 @@
// Ack 1 but not 2.
ExpectAck(1);
- manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite(), clock_.Now());
- manager_.OnAckRange(1, 2);
+ manager_.OnAckFrameStart(QuicPacketNumber(1), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2));
EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
if (manager_.session_decides_what_to_write()) {
EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
}
// 2 remains unacked, but no packets have retransmittable data.
- QuicPacketNumber unacked[] = {2};
+ uint64_t unacked[] = {2};
VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
EXPECT_TRUE(QuicSentPacketManagerPeer::HasPendingPackets(&manager_));
VerifyRetransmittablePackets(nullptr, 0);
@@ -447,8 +458,9 @@
// Ack 2 causes 2 be considered as spurious retransmission.
EXPECT_CALL(notifier_, OnFrameAcked(_, _)).WillOnce(Return(false));
ExpectAck(2);
- manager_.OnAckFrameStart(2, QuicTime::Delta::Infinite(), clock_.Now());
- manager_.OnAckRange(1, 3);
+ manager_.OnAckFrameStart(QuicPacketNumber(2), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(3));
EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
}
@@ -463,8 +475,9 @@
// First, ACK packet 1 which makes packet 2 non-retransmittable.
ExpectAck(1);
- manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite(), clock_.Now());
- manager_.OnAckRange(1, 2);
+ manager_.OnAckFrameStart(QuicPacketNumber(1), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2));
EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
SendDataPacket(3);
@@ -474,15 +487,17 @@
// Next, NACK packet 2 three times.
ExpectAck(3);
- manager_.OnAckFrameStart(3, QuicTime::Delta::Infinite(), clock_.Now());
- manager_.OnAckRange(3, 4);
- manager_.OnAckRange(1, 2);
+ manager_.OnAckFrameStart(QuicPacketNumber(3), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(3), QuicPacketNumber(4));
+ manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2));
EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
ExpectAck(4);
- manager_.OnAckFrameStart(4, QuicTime::Delta::Infinite(), clock_.Now());
- manager_.OnAckRange(3, 5);
- manager_.OnAckRange(1, 2);
+ manager_.OnAckFrameStart(QuicPacketNumber(4), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(3), QuicPacketNumber(5));
+ manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2));
EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
ExpectAckAndLoss(true, 5, 2);
@@ -495,14 +510,15 @@
EXPECT_CALL(notifier_, OnFrameLost(_)).Times(1);
}
}
- manager_.OnAckFrameStart(5, QuicTime::Delta::Infinite(), clock_.Now());
- manager_.OnAckRange(3, 6);
- manager_.OnAckRange(1, 2);
+ manager_.OnAckFrameStart(QuicPacketNumber(5), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(3), QuicPacketNumber(6));
+ manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2));
EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
if (manager_.session_decides_what_to_write() &&
GetQuicReloadableFlag(quic_fix_mark_for_loss_retransmission)) {
- QuicPacketNumber unacked[] = {2};
+ uint64_t unacked[] = {2};
VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
} else {
// No packets remain unacked.
@@ -532,12 +548,13 @@
// send algorithm is not informed that it has been ACK'd.
ExpectUpdatedRtt(1);
EXPECT_CALL(*send_algorithm_, RevertRetransmissionTimeout());
- manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite(), clock_.Now());
- manager_.OnAckRange(1, 2);
+ manager_.OnAckFrameStart(QuicPacketNumber(1), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2));
EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
// Since 2 was marked for retransmit, when 1 is acked, 2 is kept for RTT.
- QuicPacketNumber unacked[] = {2};
+ uint64_t unacked[] = {2};
VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
EXPECT_FALSE(QuicSentPacketManagerPeer::HasPendingPackets(&manager_));
VerifyRetransmittablePackets(nullptr, 0);
@@ -568,8 +585,9 @@
// Ack 1 but not 2 or 3.
ExpectAck(1);
- manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite(), clock_.Now());
- manager_.OnAckRange(1, 2);
+ manager_.OnAckFrameStart(QuicPacketNumber(1), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2));
EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
if (manager_.session_decides_what_to_write()) {
// Frames in packets 2 and 3 are acked.
@@ -579,7 +597,7 @@
}
// 2 and 3 remain unacked, but no packets have retransmittable data.
- QuicPacketNumber unacked[] = {2, 3};
+ uint64_t unacked[] = {2, 3};
VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
EXPECT_TRUE(QuicSentPacketManagerPeer::HasPendingPackets(&manager_));
VerifyRetransmittablePackets(nullptr, 0);
@@ -592,20 +610,22 @@
.WillOnce(Return(false))
.WillRepeatedly(Return(true));
}
- QuicPacketNumber acked[] = {3, 4};
+ uint64_t acked[] = {3, 4};
ExpectAcksAndLosses(true, acked, QUIC_ARRAYSIZE(acked), nullptr, 0);
- manager_.OnAckFrameStart(4, QuicTime::Delta::Infinite(), clock_.Now());
- manager_.OnAckRange(3, 5);
- manager_.OnAckRange(1, 2);
+ manager_.OnAckFrameStart(QuicPacketNumber(4), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(3), QuicPacketNumber(5));
+ manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2));
EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
- QuicPacketNumber unacked2[] = {2};
+ uint64_t unacked2[] = {2};
VerifyUnackedPackets(unacked2, QUIC_ARRAYSIZE(unacked2));
EXPECT_TRUE(QuicSentPacketManagerPeer::HasPendingPackets(&manager_));
SendDataPacket(5);
ExpectAckAndLoss(true, 5, 2);
- EXPECT_CALL(debug_delegate, OnPacketLoss(2, LOSS_RETRANSMISSION, _));
+ EXPECT_CALL(debug_delegate,
+ OnPacketLoss(QuicPacketNumber(2), LOSS_RETRANSMISSION, _));
if (manager_.session_decides_what_to_write()) {
// Frames in all packets are acked.
EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
@@ -615,14 +635,15 @@
EXPECT_CALL(notifier_, OnFrameLost(_)).Times(1);
}
}
- manager_.OnAckFrameStart(5, QuicTime::Delta::Infinite(), clock_.Now());
- manager_.OnAckRange(3, 6);
- manager_.OnAckRange(1, 2);
+ manager_.OnAckFrameStart(QuicPacketNumber(5), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(3), QuicPacketNumber(6));
+ manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2));
EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
if (manager_.session_decides_what_to_write() &&
GetQuicReloadableFlag(quic_fix_mark_for_loss_retransmission)) {
- QuicPacketNumber unacked[] = {2};
+ uint64_t unacked[] = {2};
VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
} else {
VerifyUnackedPackets(nullptr, 0);
@@ -649,8 +670,9 @@
{
ExpectAck(1);
EXPECT_CALL(*loss_algorithm, DetectLosses(_, _, _, _, _, _));
- manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite(), clock_.Now());
- manager_.OnAckRange(1, 2);
+ manager_.OnAckFrameStart(QuicPacketNumber(1), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2));
EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
}
@@ -660,22 +682,25 @@
{
ExpectAck(4);
EXPECT_CALL(*loss_algorithm, DetectLosses(_, _, _, _, _, _));
- manager_.OnAckFrameStart(4, QuicTime::Delta::Infinite(), clock_.Now());
- manager_.OnAckRange(4, 5);
- manager_.OnAckRange(1, 2);
+ manager_.OnAckFrameStart(QuicPacketNumber(4), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(4), QuicPacketNumber(5));
+ manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2));
EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
RetransmitAndSendPacket(3, 5, LOSS_RETRANSMISSION);
}
// Ack 3, which causes SpuriousRetransmitDetected to be called.
{
- QuicPacketNumber acked[] = {3};
+ uint64_t acked[] = {3};
ExpectAcksAndLosses(false, acked, QUIC_ARRAYSIZE(acked), nullptr, 0);
EXPECT_CALL(*loss_algorithm, DetectLosses(_, _, _, _, _, _));
- EXPECT_CALL(*loss_algorithm, SpuriousRetransmitDetected(_, _, _, 5));
- manager_.OnAckFrameStart(4, QuicTime::Delta::Infinite(), clock_.Now());
- manager_.OnAckRange(3, 5);
- manager_.OnAckRange(1, 2);
+ EXPECT_CALL(*loss_algorithm,
+ SpuriousRetransmitDetected(_, _, _, QuicPacketNumber(5)));
+ manager_.OnAckFrameStart(QuicPacketNumber(4), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(3), QuicPacketNumber(5));
+ manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2));
EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
if (manager_.session_decides_what_to_write()) {
// Ack 3 will not cause 5 be considered as a spurious retransmission. Ack
@@ -684,57 +709,60 @@
ExpectAck(5);
EXPECT_CALL(*loss_algorithm, DetectLosses(_, _, _, _, _, _));
EXPECT_CALL(notifier_, OnFrameAcked(_, _)).WillOnce(Return(false));
- manager_.OnAckFrameStart(5, QuicTime::Delta::Infinite(), clock_.Now());
- manager_.OnAckRange(3, 6);
- manager_.OnAckRange(1, 2);
+ manager_.OnAckFrameStart(QuicPacketNumber(5), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(3), QuicPacketNumber(6));
+ manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2));
EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
}
}
}
TEST_P(QuicSentPacketManagerTest, GetLeastUnacked) {
- EXPECT_EQ(1u, manager_.GetLeastUnacked());
+ EXPECT_EQ(QuicPacketNumber(1u), manager_.GetLeastUnacked());
}
TEST_P(QuicSentPacketManagerTest, GetLeastUnackedUnacked) {
SendDataPacket(1);
- EXPECT_EQ(1u, manager_.GetLeastUnacked());
+ EXPECT_EQ(QuicPacketNumber(1u), manager_.GetLeastUnacked());
}
TEST_P(QuicSentPacketManagerTest, AckAckAndUpdateRtt) {
- EXPECT_EQ(0u, manager_.largest_packet_peer_knows_is_acked());
+ EXPECT_FALSE(manager_.largest_packet_peer_knows_is_acked().IsInitialized());
SendDataPacket(1);
SendAckPacket(2, 1);
// Now ack the ack and expect an RTT update.
- QuicPacketNumber acked[] = {1, 2};
+ uint64_t acked[] = {1, 2};
ExpectAcksAndLosses(true, acked, QUIC_ARRAYSIZE(acked), nullptr, 0);
- manager_.OnAckFrameStart(2, QuicTime::Delta::FromMilliseconds(5),
- clock_.Now());
- manager_.OnAckRange(1, 3);
+ manager_.OnAckFrameStart(QuicPacketNumber(2),
+ QuicTime::Delta::FromMilliseconds(5), clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(3));
EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
- EXPECT_EQ(1u, manager_.largest_packet_peer_knows_is_acked());
+ EXPECT_EQ(QuicPacketNumber(1), manager_.largest_packet_peer_knows_is_acked());
SendAckPacket(3, 3);
// Now ack the ack and expect only an RTT update.
- QuicPacketNumber acked2[] = {3};
+ uint64_t acked2[] = {3};
ExpectAcksAndLosses(true, acked2, QUIC_ARRAYSIZE(acked2), nullptr, 0);
- manager_.OnAckFrameStart(3, QuicTime::Delta::Infinite(), clock_.Now());
- manager_.OnAckRange(1, 4);
+ manager_.OnAckFrameStart(QuicPacketNumber(3), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(4));
EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
- EXPECT_EQ(3u, manager_.largest_packet_peer_knows_is_acked());
+ EXPECT_EQ(QuicPacketNumber(3u),
+ manager_.largest_packet_peer_knows_is_acked());
}
TEST_P(QuicSentPacketManagerTest, Rtt) {
- QuicPacketNumber packet_number = 1;
QuicTime::Delta expected_rtt = QuicTime::Delta::FromMilliseconds(20);
- SendDataPacket(packet_number);
+ SendDataPacket(1);
clock_.AdvanceTime(expected_rtt);
- ExpectAck(packet_number);
- manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite(), clock_.Now());
- manager_.OnAckRange(1, 2);
+ ExpectAck(1);
+ manager_.OnAckFrameStart(QuicPacketNumber(1), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2));
EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
EXPECT_EQ(expected_rtt, manager_.GetRttStats()->latest_rtt());
}
@@ -743,15 +771,14 @@
// Expect that the RTT is equal to the local time elapsed, since the
// ack_delay_time is larger than the local time elapsed
// and is hence invalid.
- QuicPacketNumber packet_number = 1;
QuicTime::Delta expected_rtt = QuicTime::Delta::FromMilliseconds(10);
- SendDataPacket(packet_number);
+ SendDataPacket(1);
clock_.AdvanceTime(expected_rtt);
- ExpectAck(packet_number);
- manager_.OnAckFrameStart(1, QuicTime::Delta::FromMilliseconds(11),
- clock_.Now());
- manager_.OnAckRange(1, 2);
+ ExpectAck(1);
+ manager_.OnAckFrameStart(QuicPacketNumber(1),
+ QuicTime::Delta::FromMilliseconds(11), clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2));
EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
EXPECT_EQ(expected_rtt, manager_.GetRttStats()->latest_rtt());
}
@@ -759,14 +786,14 @@
TEST_P(QuicSentPacketManagerTest, RttWithInfiniteDelta) {
// Expect that the RTT is equal to the local time elapsed, since the
// ack_delay_time is infinite, and is hence invalid.
- QuicPacketNumber packet_number = 1;
QuicTime::Delta expected_rtt = QuicTime::Delta::FromMilliseconds(10);
- SendDataPacket(packet_number);
+ SendDataPacket(1);
clock_.AdvanceTime(expected_rtt);
- ExpectAck(packet_number);
- manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite(), clock_.Now());
- manager_.OnAckRange(1, 2);
+ ExpectAck(1);
+ manager_.OnAckFrameStart(QuicPacketNumber(1), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2));
EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
EXPECT_EQ(expected_rtt, manager_.GetRttStats()->latest_rtt());
}
@@ -774,14 +801,14 @@
TEST_P(QuicSentPacketManagerTest, RttZeroDelta) {
// Expect that the RTT is the time between send and receive since the
// ack_delay_time is zero.
- QuicPacketNumber packet_number = 1;
QuicTime::Delta expected_rtt = QuicTime::Delta::FromMilliseconds(10);
- SendDataPacket(packet_number);
+ SendDataPacket(1);
clock_.AdvanceTime(expected_rtt);
- ExpectAck(packet_number);
- manager_.OnAckFrameStart(1, QuicTime::Delta::Zero(), clock_.Now());
- manager_.OnAckRange(1, 2);
+ ExpectAck(1);
+ manager_.OnAckFrameStart(QuicPacketNumber(1), QuicTime::Delta::Zero(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2));
EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
EXPECT_EQ(expected_rtt, manager_.GetRttStats()->latest_rtt());
}
@@ -790,8 +817,7 @@
QuicSentPacketManagerPeer::SetMaxTailLossProbes(&manager_, 2);
// Send 1 packet.
- QuicPacketNumber packet_number = 1;
- SendDataPacket(packet_number);
+ SendDataPacket(1);
// The first tail loss probe retransmits 1 packet.
manager_.OnRetransmissionTimeout();
@@ -830,8 +856,9 @@
// Ack the third and ensure the first two are still pending.
ExpectAck(3);
- manager_.OnAckFrameStart(3, QuicTime::Delta::Infinite(), clock_.Now());
- manager_.OnAckRange(3, 4);
+ manager_.OnAckFrameStart(QuicPacketNumber(3), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(3), QuicPacketNumber(4));
EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
EXPECT_TRUE(QuicSentPacketManagerPeer::HasPendingPackets(&manager_));
@@ -839,8 +866,8 @@
// Acking two more packets will lose both of them due to nacks.
SendDataPacket(4);
SendDataPacket(5);
- QuicPacketNumber acked[] = {4, 5};
- QuicPacketNumber lost[] = {1, 2};
+ uint64_t acked[] = {4, 5};
+ uint64_t lost[] = {1, 2};
ExpectAcksAndLosses(true, acked, QUIC_ARRAYSIZE(acked), lost,
QUIC_ARRAYSIZE(lost));
if (manager_.session_decides_what_to_write()) {
@@ -852,8 +879,9 @@
EXPECT_CALL(notifier_, OnFrameLost(_)).Times(2);
}
}
- manager_.OnAckFrameStart(5, QuicTime::Delta::Infinite(), clock_.Now());
- manager_.OnAckRange(3, 6);
+ manager_.OnAckFrameStart(QuicPacketNumber(5), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(3), QuicPacketNumber(6));
EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
EXPECT_FALSE(manager_.HasPendingRetransmissions());
@@ -945,7 +973,7 @@
EXPECT_TRUE(manager_.HasPendingRetransmissions());
RetransmitNextPacket(103);
}
- QuicPacketNumber largest_acked = 103;
+ QuicPacketNumber largest_acked = QuicPacketNumber(103);
EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout(true));
EXPECT_CALL(*send_algorithm_,
OnCongestionEvent(
@@ -974,8 +1002,9 @@
EXPECT_CALL(notifier_, OnFrameLost(_)).Times(101);
}
}
- manager_.OnAckFrameStart(103, QuicTime::Delta::Infinite(), clock_.Now());
- manager_.OnAckRange(103, 104);
+ manager_.OnAckFrameStart(QuicPacketNumber(103), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(103), QuicPacketNumber(104));
EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
// All packets before 103 should be lost.
if (manager_.session_decides_what_to_write()) {
@@ -1032,15 +1061,16 @@
// Now ack the two crypto packets and the speculatively encrypted request,
// and ensure the first four crypto packets get abandoned, but not lost.
- QuicPacketNumber acked[] = {3, 4, 5, 8, 9};
+ uint64_t acked[] = {3, 4, 5, 8, 9};
ExpectAcksAndLosses(true, acked, QUIC_ARRAYSIZE(acked), nullptr, 0);
if (manager_.session_decides_what_to_write()) {
EXPECT_CALL(notifier_, HasUnackedCryptoData())
.WillRepeatedly(Return(false));
}
- manager_.OnAckFrameStart(9, QuicTime::Delta::Infinite(), clock_.Now());
- manager_.OnAckRange(8, 10);
- manager_.OnAckRange(3, 6);
+ manager_.OnAckFrameStart(QuicPacketNumber(9), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(8), QuicPacketNumber(10));
+ manager_.OnAckRange(QuicPacketNumber(3), QuicPacketNumber(6));
EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
EXPECT_FALSE(QuicSentPacketManagerPeer::HasUnackedCryptoPackets(&manager_));
@@ -1090,9 +1120,11 @@
RetransmitDataPacket(12, ALL_UNACKED_RETRANSMISSION);
} else {
ASSERT_TRUE(manager_.HasPendingRetransmissions());
- EXPECT_EQ(6u, manager_.NextPendingRetransmission().packet_number);
+ EXPECT_EQ(QuicPacketNumber(6u),
+ manager_.NextPendingRetransmission().packet_number);
RetransmitNextPacket(8);
- EXPECT_EQ(7u, manager_.NextPendingRetransmission().packet_number);
+ EXPECT_EQ(QuicPacketNumber(7u),
+ manager_.NextPendingRetransmission().packet_number);
RetransmitNextPacket(9);
EXPECT_TRUE(manager_.HasPendingRetransmissions());
// Send 3 more data packets and ensure the least unacked is raised.
@@ -1102,19 +1134,20 @@
EXPECT_FALSE(manager_.HasPendingRetransmissions());
}
- EXPECT_EQ(1u, manager_.GetLeastUnacked());
+ EXPECT_EQ(QuicPacketNumber(1u), manager_.GetLeastUnacked());
// Least unacked isn't raised until an ack is received, so ack the
// crypto packets.
- QuicPacketNumber acked[] = {8, 9};
+ uint64_t acked[] = {8, 9};
ExpectAcksAndLosses(true, acked, QUIC_ARRAYSIZE(acked), nullptr, 0);
- manager_.OnAckFrameStart(9, QuicTime::Delta::Infinite(), clock_.Now());
- manager_.OnAckRange(8, 10);
+ manager_.OnAckFrameStart(QuicPacketNumber(9), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(8), QuicPacketNumber(10));
EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
if (manager_.session_decides_what_to_write()) {
EXPECT_CALL(notifier_, HasUnackedCryptoData())
.WillRepeatedly(Return(false));
}
- EXPECT_EQ(10u, manager_.GetLeastUnacked());
+ EXPECT_EQ(QuicPacketNumber(10u), manager_.GetLeastUnacked());
}
TEST_P(QuicSentPacketManagerTest, CryptoHandshakeSpuriousRetransmission) {
@@ -1144,19 +1177,20 @@
// Now ack the second crypto packet, and ensure the first gets removed, but
// the third does not.
- QuicPacketNumber acked[] = {2};
+ uint64_t acked[] = {2};
ExpectAcksAndLosses(true, acked, QUIC_ARRAYSIZE(acked), nullptr, 0);
if (manager_.session_decides_what_to_write()) {
EXPECT_CALL(notifier_, HasUnackedCryptoData())
.WillRepeatedly(Return(false));
EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
}
- manager_.OnAckFrameStart(2, QuicTime::Delta::Infinite(), clock_.Now());
- manager_.OnAckRange(2, 3);
+ manager_.OnAckFrameStart(QuicPacketNumber(2), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(2), QuicPacketNumber(3));
EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
EXPECT_FALSE(QuicSentPacketManagerPeer::HasUnackedCryptoPackets(&manager_));
- QuicPacketNumber unacked[] = {3};
+ uint64_t unacked[] = {3};
VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
}
@@ -1214,7 +1248,7 @@
} else {
// Packet 2 is useful because it does not get retransmitted and still has
// retransmittable frames.
- QuicPacketNumber unacked[] = {1, 2};
+ uint64_t unacked[] = {1, 2};
VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
EXPECT_TRUE(manager_.HasPendingRetransmissions());
}
@@ -1260,7 +1294,7 @@
EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
}
EXPECT_FALSE(QuicSentPacketManagerPeer::HasUnackedCryptoPackets(&manager_));
- QuicPacketNumber unacked[] = {1, 2, 3};
+ uint64_t unacked[] = {1, 2, 3};
VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
VerifyRetransmittablePackets(nullptr, 0);
EXPECT_FALSE(manager_.HasPendingRetransmissions());
@@ -1268,10 +1302,11 @@
EXPECT_FALSE(QuicSentPacketManagerPeer::HasPendingPackets(&manager_));
// Ensure both packets get discarded when packet 2 is acked.
- QuicPacketNumber acked[] = {3};
+ uint64_t acked[] = {3};
ExpectAcksAndLosses(true, acked, QUIC_ARRAYSIZE(acked), nullptr, 0);
- manager_.OnAckFrameStart(3, QuicTime::Delta::Infinite(), clock_.Now());
- manager_.OnAckRange(3, 4);
+ manager_.OnAckFrameStart(QuicPacketNumber(3), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(3), QuicPacketNumber(4));
EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
VerifyUnackedPackets(nullptr, 0);
VerifyRetransmittablePackets(nullptr, 0);
@@ -1314,7 +1349,7 @@
// Ack a retransmission.
// Ensure no packets are lost.
- QuicPacketNumber largest_acked = 102;
+ QuicPacketNumber largest_acked = QuicPacketNumber(102);
EXPECT_CALL(*send_algorithm_,
OnCongestionEvent(true, _, _,
Pointwise(PacketNumberEq(), {largest_acked}),
@@ -1324,7 +1359,8 @@
// RTO's use loss detection instead of immediately declaring retransmitted
// packets lost.
for (int i = 1; i <= 99; ++i) {
- EXPECT_CALL(debug_delegate, OnPacketLoss(i, LOSS_RETRANSMISSION, _));
+ EXPECT_CALL(debug_delegate,
+ OnPacketLoss(QuicPacketNumber(i), LOSS_RETRANSMISSION, _));
}
if (manager_.session_decides_what_to_write()) {
if (GetQuicReloadableFlag(quic_fix_mark_for_loss_retransmission)) {
@@ -1349,8 +1385,9 @@
EXPECT_CALL(notifier_, OnFrameLost(_)).Times(98);
}
}
- manager_.OnAckFrameStart(102, QuicTime::Delta::Zero(), clock_.Now());
- manager_.OnAckRange(102, 103);
+ manager_.OnAckFrameStart(QuicPacketNumber(102), QuicTime::Delta::Zero(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(102), QuicPacketNumber(103));
EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
}
@@ -1448,7 +1485,7 @@
// Ack a retransmission and expect no call to OnRetransmissionTimeout.
// This will include packets in the lost packet map.
- QuicPacketNumber largest_acked = 102;
+ QuicPacketNumber largest_acked = QuicPacketNumber(102);
EXPECT_CALL(*send_algorithm_,
OnCongestionEvent(true, _, _,
Pointwise(PacketNumberEq(), {largest_acked}),
@@ -1477,8 +1514,9 @@
EXPECT_CALL(notifier_, OnFrameLost(_)).Times(98);
}
}
- manager_.OnAckFrameStart(102, QuicTime::Delta::Zero(), clock_.Now());
- manager_.OnAckRange(102, 103);
+ manager_.OnAckFrameStart(QuicPacketNumber(102), QuicTime::Delta::Zero(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(102), QuicPacketNumber(103));
EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
}
@@ -1524,8 +1562,9 @@
// Ack a retransmission and ensure OnRetransmissionTimeout is called.
EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout(true));
ExpectAck(2);
- manager_.OnAckFrameStart(2, QuicTime::Delta::Zero(), clock_.Now());
- manager_.OnAckRange(2, 3);
+ manager_.OnAckFrameStart(QuicPacketNumber(2), QuicTime::Delta::Zero(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(2), QuicPacketNumber(3));
EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
// The original packet and newest should be outstanding.
@@ -1575,8 +1614,9 @@
// Ack a retransmission and ensure OnRetransmissionTimeout is called.
EXPECT_CALL(*send_algorithm_, OnRetransmissionTimeout(true));
ExpectAck(3);
- manager_.OnAckFrameStart(3, QuicTime::Delta::Zero(), clock_.Now());
- manager_.OnAckRange(3, 4);
+ manager_.OnAckFrameStart(QuicPacketNumber(3), QuicTime::Delta::Zero(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(3), QuicPacketNumber(4));
EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
// The first two packets should still be outstanding.
@@ -1776,8 +1816,9 @@
// Ack a packet before the first RTO and ensure the RTO timeout returns to the
// original value and OnRetransmissionTimeout is not called or reverted.
ExpectAck(2);
- manager_.OnAckFrameStart(2, QuicTime::Delta::Infinite(), clock_.Now());
- manager_.OnAckRange(2, 3);
+ manager_.OnAckFrameStart(QuicPacketNumber(2), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(2), QuicPacketNumber(3));
EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
EXPECT_FALSE(manager_.HasPendingRetransmissions());
EXPECT_EQ(5 * kDefaultLength,
@@ -1910,8 +1951,9 @@
// set the loss timeout.
ExpectAck(2);
EXPECT_CALL(*loss_algorithm, DetectLosses(_, _, _, _, _, _));
- manager_.OnAckFrameStart(2, QuicTime::Delta::Infinite(), clock_.Now());
- manager_.OnAckRange(2, 3);
+ manager_.OnAckFrameStart(QuicPacketNumber(2), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(2), QuicPacketNumber(3));
EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
QuicTime timeout(clock_.Now() + QuicTime::Delta::FromMilliseconds(10));
@@ -2416,19 +2458,21 @@
}
TEST_P(QuicSentPacketManagerTest, PathMtuIncreased) {
- EXPECT_CALL(*send_algorithm_, OnPacketSent(_, BytesInFlight(), 1, _, _));
- SerializedPacket packet(1, PACKET_4BYTE_PACKET_NUMBER, nullptr,
- kDefaultLength + 100, false, false);
- manager_.OnPacketSent(&packet, 0, clock_.Now(), NOT_RETRANSMISSION,
- HAS_RETRANSMITTABLE_DATA);
+ EXPECT_CALL(*send_algorithm_,
+ OnPacketSent(_, BytesInFlight(), QuicPacketNumber(1), _, _));
+ SerializedPacket packet(QuicPacketNumber(1), PACKET_4BYTE_PACKET_NUMBER,
+ nullptr, kDefaultLength + 100, false, false);
+ manager_.OnPacketSent(&packet, QuicPacketNumber(), clock_.Now(),
+ NOT_RETRANSMISSION, HAS_RETRANSMITTABLE_DATA);
// Ack the large packet and expect the path MTU to increase.
ExpectAck(1);
EXPECT_CALL(*network_change_visitor_,
OnPathMtuIncreased(kDefaultLength + 100));
QuicAckFrame ack_frame = InitAckFrame(1);
- manager_.OnAckFrameStart(1, QuicTime::Delta::Infinite(), clock_.Now());
- manager_.OnAckRange(1, 2);
+ manager_.OnAckFrameStart(QuicPacketNumber(1), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2));
EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
}
@@ -2438,26 +2482,28 @@
SendDataPacket(i);
}
// Ack [5, 7), [10, 12), [15, 17).
- QuicPacketNumber acked1[] = {5, 6, 10, 11, 15, 16};
- QuicPacketNumber lost1[] = {1, 2, 3, 4, 7, 8, 9, 12, 13};
+ uint64_t acked1[] = {5, 6, 10, 11, 15, 16};
+ uint64_t lost1[] = {1, 2, 3, 4, 7, 8, 9, 12, 13};
ExpectAcksAndLosses(true, acked1, QUIC_ARRAYSIZE(acked1), lost1,
QUIC_ARRAYSIZE(lost1));
EXPECT_CALL(notifier_, OnFrameLost(_)).Times(AnyNumber());
- manager_.OnAckFrameStart(16, QuicTime::Delta::Infinite(), clock_.Now());
- manager_.OnAckRange(15, 17);
- manager_.OnAckRange(10, 12);
- manager_.OnAckRange(5, 7);
+ manager_.OnAckFrameStart(QuicPacketNumber(16), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(15), QuicPacketNumber(17));
+ manager_.OnAckRange(QuicPacketNumber(10), QuicPacketNumber(12));
+ manager_.OnAckRange(QuicPacketNumber(5), QuicPacketNumber(7));
// Make sure empty range does not harm.
- manager_.OnAckRange(4, 4);
+ manager_.OnAckRange(QuicPacketNumber(4), QuicPacketNumber(4));
EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
// Ack [4, 8), [9, 13), [14, 21).
- QuicPacketNumber acked2[] = {4, 7, 9, 12, 14, 17, 18, 19, 20};
+ uint64_t acked2[] = {4, 7, 9, 12, 14, 17, 18, 19, 20};
ExpectAcksAndLosses(true, acked2, QUIC_ARRAYSIZE(acked2), nullptr, 0);
- manager_.OnAckFrameStart(20, QuicTime::Delta::Infinite(), clock_.Now());
- manager_.OnAckRange(14, 21);
- manager_.OnAckRange(9, 13);
- manager_.OnAckRange(4, 8);
+ manager_.OnAckFrameStart(QuicPacketNumber(20), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(14), QuicPacketNumber(21));
+ manager_.OnAckRange(QuicPacketNumber(9), QuicPacketNumber(13));
+ manager_.OnAckRange(QuicPacketNumber(4), QuicPacketNumber(8));
EXPECT_TRUE(manager_.OnAckFrameEnd(clock_.Now()));
}
diff --git a/quic/core/quic_session.cc b/quic/core/quic_session.cc
index 0eae3d4..b5e88ff 100644
--- a/quic/core/quic_session.cc
+++ b/quic/core/quic_session.cc
@@ -88,10 +88,6 @@
connection_->SetDataProducer(this);
connection_->SetFromConfig(config_);
- // Make sure connection and control frame manager latch the same flag values.
- connection_->set_donot_retransmit_old_window_updates(
- control_frame_manager_.donot_retransmit_old_window_updates());
-
DCHECK_EQ(QuicUtils::GetCryptoStreamId(connection_->transport_version()),
GetMutableCryptoStream()->id());
RegisterStaticStream(
@@ -189,6 +185,10 @@
return false;
}
+ if (visitor_) {
+ visitor_->OnStopSendingReceived(frame);
+ }
+
// If stream is closed, ignore the frame
if (IsClosedStream(stream_id)) {
QUIC_DVLOG(1)
@@ -223,8 +223,15 @@
return true;
}
stream->OnStopSending(frame.application_error_code);
- // TODO(fkastenholz): Add in code to start rst-stream in the opposite
- // direction once we add IETF-QUIC semantics for rst-stream.
+
+ stream->set_stream_error(
+ static_cast<QuicRstStreamErrorCode>(frame.application_error_code));
+ SendRstStreamInner(
+ stream->id(),
+ static_cast<quic::QuicRstStreamErrorCode>(frame.application_error_code),
+ stream->stream_bytes_written(),
+ /*close_write_side_only=*/true);
+ stream->set_rst_sent(true);
return true;
}
@@ -561,26 +568,34 @@
void QuicSession::SendRstStream(QuicStreamId id,
QuicRstStreamErrorCode error,
QuicStreamOffset bytes_written) {
- if (QuicContainsKey(static_stream_map_, id)) {
- QUIC_BUG << "Cannot send RST for a static stream with ID " << id;
- return;
- }
+ SendRstStreamInner(id, error, bytes_written, /*close_write_side_only=*/false);
+}
+void QuicSession::SendRstStreamInner(QuicStreamId id,
+ QuicRstStreamErrorCode error,
+ QuicStreamOffset bytes_written,
+ bool close_write_side_only) {
if (connection()->connected()) {
- // Only send a RST_STREAM frame if still connected.
- // Send a RST_STREAM frame. If version 99, will include
- // an IETF-QUIC STOP_SENDING frame in the packet so that
- // the peer also shuts down and sends a RST_STREAM back.
- QuicConnection::ScopedPacketFlusher* flusher =
- (connection_->transport_version() == QUIC_VERSION_99)
- ? new QuicConnection::ScopedPacketFlusher(
- connection(), QuicConnection::SEND_ACK_IF_QUEUED)
- : nullptr;
- control_frame_manager_.WriteOrBufferRstStreamStopSending(id, error,
- bytes_written);
- if (flusher) {
- delete flusher;
- flusher = nullptr;
+ // Only send if still connected.
+ if (close_write_side_only) {
+ DCHECK_EQ(QUIC_VERSION_99, connection_->transport_version());
+ // Send a RST_STREAM frame.
+ control_frame_manager_.WriteOrBufferRstStream(id, error, bytes_written);
+ } else {
+ // Send a RST_STREAM frame plus, if version 99, an IETF
+ // QUIC STOP_SENDING frame. Both sre sent to emulate
+ // the two-way close that Google QUIC's RST_STREAM does.
+ QuicConnection::ScopedPacketFlusher* flusher =
+ (connection_->transport_version() == QUIC_VERSION_99)
+ ? new QuicConnection::ScopedPacketFlusher(
+ connection(), QuicConnection::SEND_ACK_IF_QUEUED)
+ : nullptr;
+ control_frame_manager_.WriteOrBufferRstStreamStopSending(id, error,
+ bytes_written);
+ if (flusher) {
+ delete flusher;
+ flusher = nullptr;
+ }
}
connection_->OnStreamReset(id, error);
}
@@ -588,7 +603,18 @@
OnStreamDoneWaitingForAcks(id);
return;
}
- CloseStreamInner(id, true);
+ if (close_write_side_only) {
+ DCHECK_EQ(QUIC_VERSION_99, connection_->transport_version());
+ DynamicStreamMap::iterator it = dynamic_stream_map_.find(id);
+ if (it != dynamic_stream_map_.end()) {
+ QuicStream* stream = it->second.get();
+ if (stream) {
+ stream->CloseWriteSide();
+ }
+ }
+ } else {
+ CloseStreamInner(id, true);
+ }
}
void QuicSession::SendGoAway(QuicErrorCode error_code,
@@ -671,7 +697,6 @@
InsertLocallyClosedStreamsHighestOffset(
stream_id, stream->flow_controller()->highest_received_byte_offset());
}
-
dynamic_stream_map_.erase(it);
if (IsIncomingStream(stream_id)) {
--num_dynamic_incoming_streams_;
@@ -719,6 +744,7 @@
if (pending_stream_map_.find(stream_id) != pending_stream_map_.end()) {
pending_stream_map_.erase(stream_id);
}
+
--num_dynamic_incoming_streams_;
if (connection_->transport_version() == QUIC_VERSION_99) {
@@ -952,10 +978,7 @@
// Discard originally encrypted packets, since they can't be decrypted by
// the peer.
NeuterUnencryptedData();
- if (GetQuicReloadableFlag(quic_optimize_encryption_established)) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_optimize_encryption_established);
- is_handshake_confirmed_ = true;
- }
+ is_handshake_confirmed_ = true;
break;
default:
@@ -1468,6 +1491,14 @@
return WRITE_FAILED;
}
+bool QuicSession::WriteCryptoData(EncryptionLevel level,
+ QuicStreamOffset offset,
+ QuicByteCount data_length,
+ QuicDataWriter* writer) {
+ QUIC_BUG << "QuicSession::WriteCryptoData is unimplemented";
+ return false;
+}
+
QuicUint128 QuicSession::GetStatelessResetToken() const {
if (!QuicConnectionIdSupportsVariableLength(perspective())) {
return QuicConnectionIdToUInt64(connection_->connection_id());
diff --git a/quic/core/quic_session.h b/quic/core/quic_session.h
index c542977..23778e7 100644
--- a/quic/core/quic_session.h
+++ b/quic/core/quic_session.h
@@ -62,6 +62,10 @@
// Called when the session receives reset on a stream from the peer.
virtual void OnRstStreamReceived(const QuicRstStreamFrame& frame) = 0;
+
+ // Called when the session receives a STOP_SENDING for a stream from the
+ // peer.
+ virtual void OnStopSendingReceived(const QuicStopSendingFrame& frame) = 0;
};
// CryptoHandshakeEvent enumerates the events generated by a QuicCryptoStream.
@@ -130,6 +134,10 @@
QuicStreamOffset offset,
QuicByteCount data_length,
QuicDataWriter* writer) override;
+ bool WriteCryptoData(EncryptionLevel level,
+ QuicStreamOffset offset,
+ QuicByteCount data_length,
+ QuicDataWriter* writer) override;
// SessionNotifierInterface methods:
bool OnFrameAcked(const QuicFrame& frame,
@@ -498,9 +506,6 @@
return stream_id_manager_;
}
- private:
- friend class test::QuicSessionPeer;
-
// A StreamHandler represents an object which can receive a STREAM or
// or RST_STREAM frame.
struct StreamHandler {
@@ -524,6 +529,11 @@
};
};
+ StreamHandler GetOrCreateStreamImpl(QuicStreamId stream_id, bool may_buffer);
+
+ private:
+ friend class test::QuicSessionPeer;
+
// Called in OnConfigNegotiated when we receive a new stream level flow
// control window in a negotiated config. Closes the connection if invalid.
void OnNewStreamFlowControlWindow(QuicStreamOffset new_window);
@@ -551,7 +561,6 @@
// closed.
QuicStream* GetStream(QuicStreamId id) const;
- StreamHandler GetOrCreateStreamImpl(QuicStreamId stream_id, bool may_buffer);
StreamHandler GetOrCreateDynamicStreamImpl(QuicStreamId stream_id,
bool may_buffer);
@@ -562,6 +571,17 @@
// Closes the pending stream |stream_id| before it has been created.
void ClosePendingStream(QuicStreamId stream_id);
+ // Does actual work of sending reset-stream or reset-stream&stop-sending
+ // If the connection is not version 99/IETF QUIC, will always send a
+ // RESET_STREAM and close_write_side_only is ignored. If the connection is
+ // IETF QUIC/Version 99 then will send a RESET_STREAM and STOP_SENDING if
+ // close_write_side_only is false, just a RESET_STREAM if
+ // close_write_side_only is true.
+ void SendRstStreamInner(QuicStreamId id,
+ QuicRstStreamErrorCode error,
+ QuicStreamOffset bytes_written,
+ bool close_write_side_only);
+
// Keep track of highest received byte offset of locally closed streams, while
// waiting for a definitive final highest offset from the peer.
std::map<QuicStreamId, QuicStreamOffset>
diff --git a/quic/core/quic_session_test.cc b/quic/core/quic_session_test.cc
index 3baae32..6bf26ab 100644
--- a/quic/core/quic_session_test.cc
+++ b/quic/core/quic_session_test.cc
@@ -1291,18 +1291,30 @@
1 + kInitialSessionFlowControlWindowForTest / 2;
if (transport_version() == QUIC_VERSION_99) {
+ // Two more control frames than in Google QUIC, one is the STOP_SENDING
+ // frame, the other is the RST_STREAM generated in response.
EXPECT_CALL(*connection_, SendControlFrame(_))
- .Times(3)
+ .Times(4)
.WillRepeatedly(Invoke(&session_, &TestSession::ClearControlFrame));
+ EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _)).Times(2);
} else {
EXPECT_CALL(*connection_, SendControlFrame(_))
.Times(2)
.WillRepeatedly(Invoke(&session_, &TestSession::ClearControlFrame));
+ EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
}
- EXPECT_CALL(*connection_, OnStreamReset(stream->id(), _));
QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream->id(),
QUIC_STREAM_CANCELLED, kByteOffset);
session_.OnRstStream(rst_frame);
+ if (transport_version() == QUIC_VERSION_99) {
+ // The test is predicated on the stream being fully closed. For V99, the
+ // RST_STREAM only does one side (the read side from the perspective of the
+ // node receiving the RST_STREAM). This is needed to fully close the
+ // stream and therefore fulfill all of the expects.
+ QuicStopSendingFrame frame(kInvalidControlFrameId, stream->id(),
+ QUIC_STREAM_CANCELLED);
+ EXPECT_TRUE(session_.OnStopSendingFrame(frame));
+ }
EXPECT_EQ(kByteOffset, session_.flow_controller()->bytes_consumed());
}
@@ -1732,16 +1744,26 @@
if (transport_version() == QUIC_VERSION_99) {
// Once for the RST_STREAM, once for the STOP_SENDING
EXPECT_CALL(*connection_, SendControlFrame(_))
- .Times(2)
+ .Times(3)
.WillRepeatedly(Invoke(&session_, &TestSession::ClearControlFrame));
+ EXPECT_CALL(*connection_, OnStreamReset(stream2->id(), _)).Times(2);
} else {
// Just for the RST_STREAM
EXPECT_CALL(*connection_, SendControlFrame(_))
.WillOnce(Invoke(&session_, &TestSession::ClearControlFrame));
+ EXPECT_CALL(*connection_,
+ OnStreamReset(stream2->id(), QUIC_RST_ACKNOWLEDGEMENT));
}
- EXPECT_CALL(*connection_,
- OnStreamReset(stream2->id(), QUIC_RST_ACKNOWLEDGEMENT));
stream2->OnStreamReset(rst_frame);
+ if (transport_version() == QUIC_VERSION_99) {
+ // The test is predicated on the stream being fully closed. For V99, the
+ // RST_STREAM only does one side (the read side from the perspective of the
+ // node receiving the RST_STREAM). This is needed to fully close the
+ // stream and therefore fulfill all of the expects.
+ QuicStopSendingFrame frame(kInvalidControlFrameId, stream2->id(),
+ QUIC_STREAM_CANCELLED);
+ EXPECT_TRUE(session_.OnStopSendingFrame(frame));
+ }
EXPECT_FALSE(QuicContainsKey(session_.zombie_streams(), stream2->id()));
ASSERT_EQ(1u, session_.closed_streams()->size());
EXPECT_EQ(stream2->id(), session_.closed_streams()->front()->id());
@@ -1759,6 +1781,10 @@
EXPECT_CALL(*connection_,
OnStreamReset(stream4->id(), QUIC_STREAM_CANCELLED));
stream4->WriteOrBufferData(body, false, nullptr);
+ // Note well: Reset() actually closes the stream in both directions. For
+ // GOOGLE QUIC it sends a RST_STREAM (which does a 2-way close), for IETF
+ // QUIC/V99 it sends both a RST_STREAM and a STOP_SENDING (each of which
+ // closes in only one direction).
stream4->Reset(QUIC_STREAM_CANCELLED);
EXPECT_FALSE(QuicContainsKey(session_.zombie_streams(), stream4->id()));
EXPECT_EQ(2u, session_.closed_streams()->size());
@@ -2279,10 +2305,24 @@
}
TestStream* stream = session_.CreateOutgoingBidirectionalStream();
+
+ // Ensure that the stream starts out open in both directions.
+ EXPECT_FALSE(QuicStreamPeer::write_side_closed(stream));
+ EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream));
+
QuicStreamId stream_id = stream->id();
QuicStopSendingFrame frame(1, stream_id, 123);
EXPECT_CALL(*stream, OnStopSending(123));
+ // Expect a reset to come back out.xxxxx
+ EXPECT_CALL(*connection_, SendControlFrame(_));
+ EXPECT_CALL(
+ *connection_,
+ OnStreamReset(stream_id, static_cast<QuicRstStreamErrorCode>(123)));
EXPECT_TRUE(session_.OnStopSendingFrame(frame));
+ // When the STOP_SENDING is received, the node generates a RST_STREAM,
+ // which closes the stream in the write direction. Ensure this.
+ EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream));
+ EXPECT_TRUE(QuicStreamPeer::write_side_closed(stream));
}
} // namespace
diff --git a/quic/core/quic_stream.cc b/quic/core/quic_stream.cc
index 30c02e0..6c8ea8d 100644
--- a/quic/core/quic_stream.cc
+++ b/quic/core/quic_stream.cc
@@ -293,12 +293,15 @@
(kMaxStreamLength - frame.offset < frame.data_length);
if (is_stream_too_long) {
// Close connection if stream becomes too long.
- QUIC_PEER_BUG
- << "Receive stream frame reaches max stream length. frame offset "
- << frame.offset << " length " << frame.data_length;
+ QUIC_PEER_BUG << "Receive stream frame on stream " << id_
+ << " reaches max stream length. frame offset " << frame.offset
+ << " length " << frame.data_length << ". "
+ << sequencer_.DebugString();
CloseConnectionWithDetails(
QUIC_STREAM_LENGTH_OVERFLOW,
- "Peer sends more data than allowed on this stream.");
+ QuicStrCat("Peer sends more data than allowed on stream ", id_,
+ ". frame: offset = ", frame.offset, ", length = ",
+ frame.data_length, ". ", sequencer_.DebugString()));
return;
}
if (frame.fin) {
@@ -364,7 +367,11 @@
}
stream_error_ = frame.error_code;
- CloseWriteSide();
+ // Google QUIC closes both sides of the stream in response to a
+ // RESET_STREAM, IETF QUIC closes only the read side.
+ if (transport_version() != QUIC_VERSION_99) {
+ CloseWriteSide();
+ }
CloseReadSide();
}
diff --git a/quic/core/quic_stream.h b/quic/core/quic_stream.h
index bc440d3..13a6b2c 100644
--- a/quic/core/quic_stream.h
+++ b/quic/core/quic_stream.h
@@ -45,7 +45,8 @@
class QuicStream;
// Buffers frames for a stream until the first byte of that frame arrives.
-class PendingStream : public QuicStreamSequencer::StreamInterface {
+class QUIC_EXPORT_PRIVATE PendingStream
+ : public QuicStreamSequencer::StreamInterface {
public:
PendingStream(QuicStreamId id, QuicSession* session);
PendingStream(const PendingStream&) = delete;
@@ -70,6 +71,9 @@
// If the final offset violates flow control, the connection will be closed.
void OnRstStreamFrame(const QuicRstStreamFrame& frame);
+ // Returns the number of bytes read on this stream.
+ uint64_t stream_bytes_read() { return stream_bytes_read_; }
+
private:
friend class QuicStream;
@@ -341,6 +345,11 @@
// QuicStream class.
virtual void OnStopSending(uint16_t code);
+ // Close the write side of the socket. Further writes will fail.
+ // Can be called by the subclass or internally.
+ // Does not send a FIN. May cause the stream to be closed.
+ virtual void CloseWriteSide();
+
protected:
// Sends as many bytes in the first |count| buffers of |iov| to the connection
// as the connection will consume. If FIN is consumed, the write side is
@@ -358,11 +367,6 @@
QuicStreamOffset offset,
bool fin);
- // Close the write side of the socket. Further writes will fail.
- // Can be called by the subclass or internally.
- // Does not send a FIN. May cause the stream to be closed.
- virtual void CloseWriteSide();
-
// Close the read side of the socket. May cause the stream to be closed.
// Subclasses and consumers should use StopReading to terminate reading early
// if expecting a FIN. Can be used directly by subclasses if not expecting a
diff --git a/quic/core/quic_stream_frame_data_producer.h b/quic/core/quic_stream_frame_data_producer.h
index 56922b1..ab67d54 100644
--- a/quic/core/quic_stream_frame_data_producer.h
+++ b/quic/core/quic_stream_frame_data_producer.h
@@ -24,6 +24,14 @@
QuicStreamOffset offset,
QuicByteCount data_length,
QuicDataWriter* writer) = 0;
+
+ // Writes the data for a CRYPTO frame to |writer| for a frame at encryption
+ // level |level| starting at offset |offset| for |data_length| bytes. Returns
+ // whether writing the data was successful.
+ virtual bool WriteCryptoData(EncryptionLevel level,
+ QuicStreamOffset offset,
+ QuicByteCount data_length,
+ QuicDataWriter* writer) = 0;
};
} // namespace quic
diff --git a/quic/core/quic_stream_id_manager.cc b/quic/core/quic_stream_id_manager.cc
index ede2056..ce08e59 100644
--- a/quic/core/quic_stream_id_manager.cc
+++ b/quic/core/quic_stream_id_manager.cc
@@ -1,3 +1,6 @@
+// Copyright (c) 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
#include "net/third_party/quiche/src/quic/core/quic_stream_id_manager.h"
#include "net/third_party/quiche/src/quic/core/quic_connection.h"
diff --git a/quic/core/quic_stream_id_manager.h b/quic/core/quic_stream_id_manager.h
index d30f5cd..95951c0 100644
--- a/quic/core/quic_stream_id_manager.h
+++ b/quic/core/quic_stream_id_manager.h
@@ -1,3 +1,6 @@
+// Copyright (c) 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
#ifndef QUICHE_QUIC_CORE_QUIC_STREAM_ID_MANAGER_H_
#define QUICHE_QUIC_CORE_QUIC_STREAM_ID_MANAGER_H_
diff --git a/quic/core/quic_stream_id_manager_test.cc b/quic/core/quic_stream_id_manager_test.cc
index 80252c3..5647d75 100644
--- a/quic/core/quic_stream_id_manager_test.cc
+++ b/quic/core/quic_stream_id_manager_test.cc
@@ -1,3 +1,6 @@
+// Copyright (c) 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
#include "net/third_party/quiche/src/quic/core/quic_stream_id_manager.h"
#include <cstdint>
diff --git a/quic/core/quic_stream_sequencer.h b/quic/core/quic_stream_sequencer.h
index 00ead04..dfe5e7d 100644
--- a/quic/core/quic_stream_sequencer.h
+++ b/quic/core/quic_stream_sequencer.h
@@ -20,8 +20,6 @@
class QuicStreamSequencerPeer;
} // namespace test
-class QuicStream;
-
// Buffers frames until we have something which can be passed
// up to the next layer.
class QUIC_EXPORT_PRIVATE QuicStreamSequencer {
diff --git a/quic/core/quic_stream_sequencer_buffer.cc b/quic/core/quic_stream_sequencer_buffer.cc
index 6e720e0..b96a89a 100644
--- a/quic/core/quic_stream_sequencer_buffer.cc
+++ b/quic/core/quic_stream_sequencer_buffer.cc
@@ -91,7 +91,7 @@
// Extend the right edge of last interval.
// TODO(fayang): Encapsulate this into a future version of QuicIntervalSet
// if this is more efficient than Add.
- const_cast<QuicInterval<QuicPacketNumber>*>(&(*bytes_received_.rbegin()))
+ const_cast<QuicInterval<QuicStreamOffset>*>(&(*bytes_received_.rbegin()))
->SetMax(starting_offset + size);
} else {
bytes_received_.Add(starting_offset, starting_offset + size);
diff --git a/quic/core/quic_stream_test.cc b/quic/core/quic_stream_test.cc
index 3b49f72..e8338b3 100644
--- a/quic/core/quic_stream_test.cc
+++ b/quic/core/quic_stream_test.cc
@@ -8,6 +8,7 @@
#include "net/third_party/quiche/src/quic/core/quic_connection.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
+#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/core/quic_write_blocked_list.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_expect_bug.h"
@@ -126,6 +127,18 @@
return true;
}
+ bool ClearResetStreamFrame(const QuicFrame& frame) {
+ EXPECT_EQ(RST_STREAM_FRAME, frame.type);
+ DeleteFrame(&const_cast<QuicFrame&>(frame));
+ return true;
+ }
+
+ bool ClearStopSendingFrame(const QuicFrame& frame) {
+ EXPECT_EQ(STOP_SENDING_FRAME, frame.type);
+ DeleteFrame(&const_cast<QuicFrame&>(frame));
+ return true;
+ }
+
protected:
MockQuicConnectionHelper helper_;
MockAlarmFactory alarm_factory_;
@@ -686,7 +699,8 @@
QuicStreamFrame stream_frame(stream_->id(), false, kMaxStreamLength,
QuicStringPiece("."));
EXPECT_QUIC_PEER_BUG(stream_->OnStreamFrame(stream_frame),
- "Receive stream frame reaches max stream length");
+ QuicStrCat("Receive stream frame on stream ",
+ stream_->id(), " reaches max stream length"));
}
TEST_P(QuicParameterizedStreamTest, SetDrainingIncomingOutgoing) {
@@ -1067,7 +1081,6 @@
QuicConsumedData consumed = stream_->WriteMemSlices(storage.ToSpan(), false);
EXPECT_EQ(data.length(), consumed.bytes_consumed);
struct iovec iov2 = {const_cast<char*>(data.data()), 1u};
- SimpleBufferAllocator allocator2;
QuicMemSliceStorage storage2(
&iov2, 1,
session_->connection()->helper()->GetStreamSendBufferAllocator(), 1024);
@@ -1445,6 +1458,10 @@
TEST_P(QuicParameterizedStreamTest, CheckStopSending) {
Initialize();
const int kStopSendingCode = 123;
+ // These must start as false.
+ EXPECT_FALSE(QuicStreamPeer::write_side_closed(stream_));
+ EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_));
+ // Expect to actually see a stop sending if and only if we are in version 99.
if (connection_->transport_version() == QUIC_VERSION_99) {
EXPECT_CALL(*session_, SendStopSending(kStopSendingCode, stream_->id()))
.Times(1);
@@ -1452,6 +1469,74 @@
EXPECT_CALL(*session_, SendStopSending(_, _)).Times(0);
}
stream_->SendStopSending(kStopSendingCode);
+ // Sending a STOP_SENDING does not actually close the local stream.
+ // Our implementation waits for the responding RESET_STREAM to effect the
+ // closes. Therefore, read- and write-side closes should both be false.
+ EXPECT_FALSE(QuicStreamPeer::write_side_closed(stream_));
+ EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_));
+}
+
+// Test that OnStreamReset does one-way (read) closes if version 99, two way
+// (read and write) if not version 99.
+TEST_P(QuicStreamTest, OnStreamResetReadOrReadWrite) {
+ Initialize();
+ EXPECT_FALSE(QuicStreamPeer::write_side_closed(stream_));
+ EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_));
+
+ QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream_->id(),
+ QUIC_STREAM_CANCELLED, 1234);
+ stream_->OnStreamReset(rst_frame);
+ if (connection_->transport_version() == QUIC_VERSION_99) {
+ // Version 99/IETF QUIC should close just the read side.
+ EXPECT_TRUE(QuicStreamPeer::read_side_closed(stream_));
+ EXPECT_FALSE(QuicStreamPeer::write_side_closed(stream_));
+ } else {
+ // Google QUIC should close both sides of the stream.
+ EXPECT_TRUE(QuicStreamPeer::write_side_closed(stream_));
+ EXPECT_TRUE(QuicStreamPeer::read_side_closed(stream_));
+ }
+}
+
+// Test that receiving a STOP_SENDING just closes the write side of the stream.
+// If not V99, the test is a noop (no STOP_SENDING in Google QUIC).
+TEST_P(QuicStreamTest, OnStopSendingReadOrReadWrite) {
+ Initialize();
+ if (connection_->transport_version() != QUIC_VERSION_99) {
+ return;
+ }
+
+ EXPECT_FALSE(QuicStreamPeer::write_side_closed(stream_));
+ EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_));
+
+ // Simulate receipt of a STOP_SENDING.
+ stream_->OnStopSending(123);
+
+ // Should close just the read side.
+ EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_));
+ EXPECT_TRUE(QuicStreamPeer::write_side_closed(stream_));
+}
+
+// SendOnlyRstStream must only send a RESET_STREAM (no bundled STOP_SENDING).
+TEST_P(QuicStreamTest, SendOnlyRstStream) {
+ Initialize();
+ if (connection_->transport_version() != QUIC_VERSION_99) {
+ return;
+ }
+
+ EXPECT_CALL(*connection_,
+ OnStreamReset(stream_->id(), QUIC_BAD_APPLICATION_PAYLOAD));
+ EXPECT_CALL(*connection_, SendControlFrame(_))
+ .Times(1)
+ .WillOnce(Invoke(this, &QuicStreamTest::ClearResetStreamFrame));
+
+ QuicSessionPeer::SendRstStreamInner(session_.get(), stream_->id(),
+ QUIC_BAD_APPLICATION_PAYLOAD,
+ stream_->stream_bytes_written(),
+ /*close_write_side_only=*/true);
+
+ // ResetStreamOnly should just close the write side.
+ EXPECT_FALSE(QuicStreamPeer::read_side_closed(stream_));
+ EXPECT_TRUE(QuicStreamPeer::write_side_closed(stream_));
}
} // namespace
diff --git a/quic/core/quic_time_wait_list_manager.cc b/quic/core/quic_time_wait_list_manager.cc
index 86be54d..731df3e 100644
--- a/quic/core/quic_time_wait_list_manager.cc
+++ b/quic/core/quic_time_wait_list_manager.cc
@@ -12,6 +12,7 @@
#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_decrypter.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h"
+#include "net/third_party/quiche/src/quic/core/quic_connection_id.h"
#include "net/third_party/quiche/src/quic/core/quic_framer.h"
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
@@ -245,11 +246,11 @@
result = writer_->Flush();
}
- if (result.status == WRITE_STATUS_BLOCKED) {
+ if (IsWriteBlockedStatus(result.status)) {
// If blocked and unbuffered, return false to retry sending.
DCHECK(writer_->IsWriteBlocked());
visitor_->OnWriteBlocked(this);
- return writer_->IsWriteBlockedDataBuffered();
+ return result.status == WRITE_STATUS_BLOCKED_DATA_BUFFERED;
} else if (IsWriteError(result.status)) {
QUIC_LOG_FIRST_N(WARNING, 1)
<< "Received unknown error while sending termination packet to "
diff --git a/quic/core/quic_time_wait_list_manager_test.cc b/quic/core/quic_time_wait_list_manager_test.cc
index 0fced02..0d3244b 100644
--- a/quic/core/quic_time_wait_list_manager_test.cc
+++ b/quic/core/quic_time_wait_list_manager_test.cc
@@ -185,7 +185,7 @@
QuicEncryptedPacket* ConstructEncryptedPacket(
QuicConnectionId destination_connection_id,
QuicConnectionId source_connection_id,
- QuicPacketNumber packet_number) {
+ uint64_t packet_number) {
return quic::test::ConstructEncryptedPacket(destination_connection_id,
source_connection_id, false,
false, packet_number, "data");
@@ -406,9 +406,8 @@
QuicConnectionId connection_id = TestConnectionId(1);
EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(connection_id));
AddConnectionId(connection_id, QuicTimeWaitListManager::SEND_STATELESS_RESET);
- QuicPacketNumber packet_number = 234;
std::unique_ptr<QuicEncryptedPacket> packet(ConstructEncryptedPacket(
- connection_id, EmptyQuicConnectionId(), packet_number));
+ connection_id, EmptyQuicConnectionId(), /*packet_number=*/234));
// Let first write through.
EXPECT_CALL(writer_,
WritePacket(_, _, self_address_.host(), peer_address_, _))
@@ -433,9 +432,8 @@
EXPECT_CALL(visitor_, OnConnectionAddedToTimeWaitList(other_connection_id));
AddConnectionId(other_connection_id,
QuicTimeWaitListManager::SEND_STATELESS_RESET);
- QuicPacketNumber other_packet_number = 23423;
std::unique_ptr<QuicEncryptedPacket> other_packet(ConstructEncryptedPacket(
- other_connection_id, EmptyQuicConnectionId(), other_packet_number));
+ other_connection_id, EmptyQuicConnectionId(), /*packet_number=*/23423));
EXPECT_CALL(writer_, WritePacket(_, _, _, _, _)).Times(0);
EXPECT_CALL(visitor_, OnWriteBlocked(&time_wait_list_manager_));
ProcessPacket(other_connection_id);
diff --git a/quic/core/quic_trace_visitor.cc b/quic/core/quic_trace_visitor.cc
index 08363e2..b0fc8ae 100644
--- a/quic/core/quic_trace_visitor.cc
+++ b/quic/core/quic_trace_visitor.cc
@@ -59,7 +59,7 @@
quic_trace::Event* event = trace_.add_events();
event->set_event_type(quic_trace::PACKET_SENT);
event->set_time_us(ConvertTimestampToRecordedFormat(sent_time));
- event->set_packet_number(serialized_packet.packet_number);
+ event->set_packet_number(serialized_packet.packet_number.ToUint64());
event->set_packet_size(serialized_packet.encrypted_length);
event->set_encryption_level(
EncryptionLevelToProto(serialized_packet.encryption_level));
@@ -140,8 +140,8 @@
quic_trace::AckBlock* block = info->add_acked_packets();
// We record intervals as [a, b], whereas the in-memory representation
// we currently use is [a, b).
- block->set_first_packet(interval.min());
- block->set_last_packet(interval.max() - 1);
+ block->set_first_packet(interval.min().ToUint64());
+ block->set_last_packet(interval.max().ToUint64() - 1);
}
break;
}
@@ -240,7 +240,7 @@
quic_trace::Event* event = trace_.add_events();
event->set_time_us(ConvertTimestampToRecordedFormat(ack_receive_time));
event->set_packet_number(
- connection_->received_packet_manager().GetLargestObserved());
+ connection_->received_packet_manager().GetLargestObserved().ToUint64());
event->set_event_type(quic_trace::PACKET_RECEIVED);
// TODO(vasilvv): consider removing this copy.
@@ -255,7 +255,7 @@
quic_trace::Event* event = trace_.add_events();
event->set_time_us(ConvertTimestampToRecordedFormat(detection_time));
event->set_event_type(quic_trace::PACKET_LOST);
- event->set_packet_number(lost_packet_number);
+ event->set_packet_number(lost_packet_number.ToUint64());
PopulateTransportState(event->mutable_transport_state());
}
@@ -265,7 +265,7 @@
event->set_time_us(ConvertTimestampToRecordedFormat(receive_time));
event->set_event_type(quic_trace::PACKET_RECEIVED);
event->set_packet_number(
- connection_->received_packet_manager().GetLargestObserved());
+ connection_->received_packet_manager().GetLargestObserved().ToUint64());
// TODO(vasilvv): consider removing this copy.
QuicWindowUpdateFrame copy_of_update = frame;
diff --git a/quic/core/quic_trace_visitor_test.cc b/quic/core/quic_trace_visitor_test.cc
index 5d98d55..402fa77 100644
--- a/quic/core/quic_trace_visitor_test.cc
+++ b/quic/core/quic_trace_visitor_test.cc
@@ -135,20 +135,22 @@
const quic_trace::AckInfo& info = frame.ack_info();
for (const auto& block : info.acked_packets()) {
- packets.Add(block.first_packet(), block.last_packet() + 1);
+ packets.Add(QuicPacketNumber(block.first_packet()),
+ QuicPacketNumber(block.last_packet()) + 1);
}
}
}
if (packet.event_type() == quic_trace::PACKET_LOST) {
- packets.Add(packet.packet_number(), packet.packet_number() + 1);
+ packets.Add(QuicPacketNumber(packet.packet_number()),
+ QuicPacketNumber(packet.packet_number()) + 1);
}
}
ASSERT_EQ(1u, packets.Size());
- EXPECT_EQ(1u, packets.begin()->min());
+ EXPECT_EQ(QuicPacketNumber(1u), packets.begin()->min());
// We leave some room (20 packets) for the packets which did not receive
// conclusive status at the end of simulation.
- EXPECT_GT(packets.rbegin()->max(), packets_sent_ - 20);
+ EXPECT_GT(packets.rbegin()->max(), QuicPacketNumber(packets_sent_ - 20));
}
TEST_F(QuicTraceVisitorTest, TransportState) {
diff --git a/quic/core/quic_transmission_info.cc b/quic/core/quic_transmission_info.cc
index 582f939..6e9d02c 100644
--- a/quic/core/quic_transmission_info.cc
+++ b/quic/core/quic_transmission_info.cc
@@ -15,9 +15,7 @@
in_flight(false),
state(OUTSTANDING),
has_crypto_handshake(false),
- num_padding_bytes(0),
- retransmission(kInvalidPacketNumber),
- largest_acked(kInvalidPacketNumber) {}
+ num_padding_bytes(0) {}
QuicTransmissionInfo::QuicTransmissionInfo(
EncryptionLevel level,
@@ -35,9 +33,7 @@
in_flight(false),
state(OUTSTANDING),
has_crypto_handshake(has_crypto_handshake),
- num_padding_bytes(num_padding_bytes),
- retransmission(kInvalidPacketNumber),
- largest_acked(kInvalidPacketNumber) {}
+ num_padding_bytes(num_padding_bytes) {}
QuicTransmissionInfo::QuicTransmissionInfo(const QuicTransmissionInfo& other) =
default;
diff --git a/quic/core/quic_types.h b/quic/core/quic_types.h
index 47811c7..7718468 100644
--- a/quic/core/quic_types.h
+++ b/quic/core/quic_types.h
@@ -12,6 +12,7 @@
#include <vector>
#include "net/third_party/quiche/src/quic/core/quic_connection_id.h"
+#include "net/third_party/quiche/src/quic/core/quic_packet_number.h"
#include "net/third_party/quiche/src/quic/core/quic_time.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
@@ -27,7 +28,6 @@
typedef uint64_t QuicByteCount;
typedef uint64_t QuicPacketCount;
-typedef uint64_t QuicPacketNumber;
typedef uint64_t QuicPublicResetNonceProof;
typedef uint64_t QuicStreamOffset;
typedef std::array<char, 32> DiversificationNonce;
@@ -80,7 +80,10 @@
// TODO(wtc): see if WriteStatus can be replaced by QuicAsyncStatus.
enum WriteStatus {
WRITE_STATUS_OK,
+ // Write is blocked, caller needs to retry.
WRITE_STATUS_BLOCKED,
+ // Write is blocked but the packet data is buffered, caller should not retry.
+ WRITE_STATUS_BLOCKED_DATA_BUFFERED,
// To make the IsWriteError(WriteStatus) function work properly:
// - Non-errors MUST be added before WRITE_STATUS_ERROR.
// - Errors MUST be added after WRITE_STATUS_ERROR.
@@ -89,6 +92,11 @@
WRITE_STATUS_NUM_VALUES,
};
+inline bool IsWriteBlockedStatus(WriteStatus status) {
+ return status == WRITE_STATUS_BLOCKED ||
+ status == WRITE_STATUS_BLOCKED_DATA_BUFFERED;
+}
+
inline bool IsWriteError(WriteStatus status) {
return status >= WRITE_STATUS_ERROR;
}
@@ -107,6 +115,7 @@
case WRITE_STATUS_OK:
return bytes_written == other.bytes_written;
case WRITE_STATUS_BLOCKED:
+ case WRITE_STATUS_BLOCKED_DATA_BUFFERED:
return true;
default:
return error_code == other.error_code;
@@ -208,32 +217,41 @@
// encodings.
enum QuicIetfFrameType : uint8_t {
IETF_PADDING = 0x00,
- IETF_RST_STREAM = 0x01,
- IETF_CONNECTION_CLOSE = 0x02,
- IETF_APPLICATION_CLOSE = 0x03,
- IETF_MAX_DATA = 0x04,
- IETF_MAX_STREAM_DATA = 0x05,
- IETF_MAX_STREAM_ID = 0x06,
- IETF_PING = 0x07,
- IETF_BLOCKED = 0x08,
- IETF_STREAM_BLOCKED = 0x09,
- IETF_STREAM_ID_BLOCKED = 0x0a,
- IETF_NEW_CONNECTION_ID = 0x0b,
- IETF_STOP_SENDING = 0x0c,
- IETF_RETIRE_CONNECTION_ID = 0x0d,
- IETF_PATH_CHALLENGE = 0x0e,
- IETF_PATH_RESPONSE = 0x0f,
+ IETF_PING = 0x01,
+ IETF_ACK = 0x02,
+ IETF_ACK_ECN = 0x03,
+ IETF_RST_STREAM = 0x04,
+ IETF_STOP_SENDING = 0x05,
+ IETF_CRYPTO = 0x06,
+ IETF_NEW_TOKEN = 0x07,
// the low-3 bits of the stream frame type value are actually flags
// declaring what parts of the frame are/are-not present, as well as
// some other control information. The code would then do something
- // along the lines of "if ((frame_type & 0xf8) == 0x10)" to determine
+ // along the lines of "if ((frame_type & 0xf8) == 0x08)" to determine
// whether the frame is a stream frame or not, and then examine each
// bit specifically when/as needed.
- IETF_STREAM = 0x10,
- IETF_CRYPTO = 0x18,
- IETF_NEW_TOKEN = 0x19,
- IETF_ACK = 0x1a,
- IETF_ACK_ECN = 0x1b,
+ IETF_STREAM = 0x08,
+ // 0x09 through 0x0f are various flag settings of the IETF_STREAM frame.
+ IETF_MAX_DATA = 0x10,
+ IETF_MAX_STREAM_DATA = 0x11,
+ IETF_MAX_STREAM_ID = 0x12, // TODO(fkastenholz): Will become IETF_MAX_STREAMS
+ // 0x13 reserved, a flag setting for IETF_MAX_STREAMS.
+ IETF_BLOCKED = 0x14, // TODO(fkastenholz): Should, eventually, be renamed to
+ // IETF_DATA_BLOCKED
+ IETF_STREAM_BLOCKED = 0x15, // TODO(fkastenholz): Should, eventually, be
+ // renamed to IETF_STREAM_DATA_BLOCKED
+ IETF_STREAM_ID_BLOCKED =
+ 0x16, // TODO(fkastenholz): Will become IETF_STREAMS_BLOCKED
+ // 0x17 reserved, a flag setting for IETF_STREAMS_BLOCKED
+ IETF_NEW_CONNECTION_ID = 0x18,
+ IETF_RETIRE_CONNECTION_ID = 0x19,
+ IETF_PATH_CHALLENGE = 0x1a,
+ IETF_PATH_RESPONSE = 0x1b,
+ IETF_CONNECTION_CLOSE = 0x1c,
+ // 0x1d reserved, a flag setting for IETF_CONNECTION_CLOSE
+ // TODO(fkastenholz): IETF_APPLICATION_CLOSE disappears in the next version of
+ // QUIC. It is retained temporarily
+ IETF_APPLICATION_CLOSE = 0x1d,
// MESSAGE frame type is not yet determined, use 0x2x temporarily to give
// stream frame some wiggle room.
@@ -256,7 +274,7 @@
enum QuicPacketNumberLength : uint8_t {
PACKET_1BYTE_PACKET_NUMBER = 1,
PACKET_2BYTE_PACKET_NUMBER = 2,
- PACKET_3BYTE_PACKET_NUMBER = 3, // Only used in v99.
+ PACKET_3BYTE_PACKET_NUMBER = 3, // Used in version > QUIC_VERSION_46.
PACKET_4BYTE_PACKET_NUMBER = 4,
// TODO(rch): Remove this when we remove QUIC_VERSION_39.
PACKET_6BYTE_PACKET_NUMBER = 6,
diff --git a/quic/core/quic_unacked_packet_map.cc b/quic/core/quic_unacked_packet_map.cc
index 3da540e..32fd272 100644
--- a/quic/core/quic_unacked_packet_map.cc
+++ b/quic/core/quic_unacked_packet_map.cc
@@ -25,11 +25,7 @@
} // namespace
QuicUnackedPacketMap::QuicUnackedPacketMap()
- : largest_sent_packet_(0),
- largest_sent_retransmittable_packet_(0),
- largest_sent_largest_acked_(0),
- largest_acked_(0),
- least_unacked_(1),
+ : least_unacked_(FirstSendingPacketNumber()),
bytes_in_flight_(0),
pending_crypto_packet_count_(0),
last_crypto_packet_sent_time_(QuicTime::Zero()),
@@ -49,7 +45,10 @@
bool set_in_flight) {
QuicPacketNumber packet_number = packet->packet_number;
QuicPacketLength bytes_sent = packet->encrypted_length;
- QUIC_BUG_IF(largest_sent_packet_ >= packet_number) << packet_number;
+ QUIC_BUG_IF(largest_sent_packet_.IsInitialized() &&
+ largest_sent_packet_ >= packet_number)
+ << "largest_sent_packet_: " << largest_sent_packet_
+ << ", packet_number: " << packet_number;
DCHECK_GE(packet_number, least_unacked_ + unacked_packets_.size());
while (least_unacked_ + unacked_packets_.size() < packet_number) {
unacked_packets_.push_back(QuicTransmissionInfo());
@@ -62,9 +61,13 @@
packet->encryption_level, packet->packet_number_length, transmission_type,
sent_time, bytes_sent, has_crypto_handshake, packet->num_padding_bytes);
info.largest_acked = packet->largest_acked;
- largest_sent_largest_acked_ =
- std::max(largest_sent_largest_acked_, packet->largest_acked);
- if (old_packet_number > 0) {
+ if (packet->largest_acked.IsInitialized()) {
+ largest_sent_largest_acked_ =
+ largest_sent_largest_acked_.IsInitialized()
+ ? std::max(largest_sent_largest_acked_, packet->largest_acked)
+ : packet->largest_acked;
+ }
+ if (old_packet_number.IsInitialized()) {
TransferRetransmissionInfo(old_packet_number, packet_number,
transmission_type, &info);
}
@@ -78,7 +81,7 @@
unacked_packets_.push_back(info);
// Swap the retransmittable frames to avoid allocations.
// TODO(ianswett): Could use emplace_back when Chromium can.
- if (old_packet_number == kInvalidPacketNumber) {
+ if (!old_packet_number.IsInitialized()) {
if (has_crypto_handshake) {
++pending_crypto_packet_count_;
last_crypto_packet_sent_time_ = sent_time;
@@ -180,12 +183,12 @@
QuicTransmissionInfo* info) {
if (session_decides_what_to_write_) {
DeleteFrames(&info->retransmittable_frames);
- info->retransmission = kInvalidPacketNumber;
+ info->retransmission.Clear();
return;
}
- while (info->retransmission != kInvalidPacketNumber) {
+ while (info->retransmission.IsInitialized()) {
const QuicPacketNumber retransmission = info->retransmission;
- info->retransmission = kInvalidPacketNumber;
+ info->retransmission.Clear();
info = &unacked_packets_[retransmission - least_unacked_];
}
@@ -209,7 +212,7 @@
void QuicUnackedPacketMap::IncreaseLargestAcked(
QuicPacketNumber largest_acked) {
- DCHECK_LE(largest_acked_, largest_acked);
+ DCHECK(!largest_acked_.IsInitialized() || largest_acked_ <= largest_acked);
largest_acked_ = largest_acked;
}
@@ -218,7 +221,8 @@
const QuicTransmissionInfo& info) const {
// Packet can be used for RTT measurement if it may yet be acked as the
// largest observed packet by the receiver.
- return QuicUtils::IsAckable(info.state) && packet_number > largest_acked_;
+ return QuicUtils::IsAckable(info.state) &&
+ (!largest_acked_.IsInitialized() || packet_number > largest_acked_);
}
bool QuicUnackedPacketMap::IsPacketUsefulForCongestionControl(
@@ -233,15 +237,16 @@
// Packet may have retransmittable frames, or the data may have been
// retransmitted with a new packet number.
// Allow for an extra 1 RTT before stopping to track old packets.
- return info.retransmission > largest_acked_ ||
+ return (info.retransmission.IsInitialized() &&
+ (!largest_acked_.IsInitialized() ||
+ info.retransmission > largest_acked_)) ||
HasRetransmittableFrames(info);
}
// Wait for 1 RTT before giving up on the lost packet.
- if (info.retransmission > largest_acked_) {
- return true;
- }
- return false;
+ return info.retransmission.IsInitialized() &&
+ (!largest_acked_.IsInitialized() ||
+ info.retransmission > largest_acked_);
}
bool QuicUnackedPacketMap::IsPacketUseless(
@@ -472,7 +477,7 @@
void QuicUnackedPacketMap::SetSessionDecideWhatToWrite(
bool session_decides_what_to_write) {
- if (largest_sent_packet_ > 0) {
+ if (largest_sent_packet_.IsInitialized()) {
QUIC_BUG << "Cannot change session_decide_what_to_write with packets sent.";
return;
}
diff --git a/quic/core/quic_unacked_packet_map_test.cc b/quic/core/quic_unacked_packet_map_test.cc
index a4d0289..df14321 100644
--- a/quic/core/quic_unacked_packet_map_test.cc
+++ b/quic/core/quic_unacked_packet_map_test.cc
@@ -46,30 +46,31 @@
~QuicUnackedPacketMapTest() override {}
- SerializedPacket CreateRetransmittablePacket(QuicPacketNumber packet_number) {
+ SerializedPacket CreateRetransmittablePacket(uint64_t packet_number) {
return CreateRetransmittablePacketForStream(
packet_number, QuicUtils::GetHeadersStreamId(
CurrentSupportedVersions()[0].transport_version));
}
SerializedPacket CreateRetransmittablePacketForStream(
- QuicPacketNumber packet_number,
+ uint64_t packet_number,
QuicStreamId stream_id) {
- SerializedPacket packet(packet_number, PACKET_1BYTE_PACKET_NUMBER, nullptr,
- kDefaultLength, false, false);
+ SerializedPacket packet(QuicPacketNumber(packet_number),
+ PACKET_1BYTE_PACKET_NUMBER, nullptr, kDefaultLength,
+ false, false);
QuicStreamFrame frame;
frame.stream_id = stream_id;
packet.retransmittable_frames.push_back(QuicFrame(frame));
return packet;
}
- SerializedPacket CreateNonRetransmittablePacket(
- QuicPacketNumber packet_number) {
- return SerializedPacket(packet_number, PACKET_1BYTE_PACKET_NUMBER, nullptr,
- kDefaultLength, false, false);
+ SerializedPacket CreateNonRetransmittablePacket(uint64_t packet_number) {
+ return SerializedPacket(QuicPacketNumber(packet_number),
+ PACKET_1BYTE_PACKET_NUMBER, nullptr, kDefaultLength,
+ false, false);
}
- void VerifyInFlightPackets(QuicPacketNumber* packets, size_t num_packets) {
+ void VerifyInFlightPackets(uint64_t* packets, size_t num_packets) {
unacked_packets_.RemoveObsoletePackets();
if (num_packets == 0) {
EXPECT_FALSE(unacked_packets_.HasInFlightPackets());
@@ -79,12 +80,16 @@
if (num_packets == 1) {
EXPECT_TRUE(unacked_packets_.HasInFlightPackets());
EXPECT_FALSE(unacked_packets_.HasMultipleInFlightPackets());
- ASSERT_TRUE(unacked_packets_.IsUnacked(packets[0]));
- EXPECT_TRUE(unacked_packets_.GetTransmissionInfo(packets[0]).in_flight);
+ ASSERT_TRUE(unacked_packets_.IsUnacked(QuicPacketNumber(packets[0])));
+ EXPECT_TRUE(
+ unacked_packets_.GetTransmissionInfo(QuicPacketNumber(packets[0]))
+ .in_flight);
}
for (size_t i = 0; i < num_packets; ++i) {
- ASSERT_TRUE(unacked_packets_.IsUnacked(packets[i]));
- EXPECT_TRUE(unacked_packets_.GetTransmissionInfo(packets[i]).in_flight);
+ ASSERT_TRUE(unacked_packets_.IsUnacked(QuicPacketNumber(packets[i])));
+ EXPECT_TRUE(
+ unacked_packets_.GetTransmissionInfo(QuicPacketNumber(packets[i]))
+ .in_flight);
}
size_t in_flight_count = 0;
for (QuicUnackedPacketMap::const_iterator it = unacked_packets_.begin();
@@ -96,7 +101,7 @@
EXPECT_EQ(num_packets, in_flight_count);
}
- void VerifyUnackedPackets(QuicPacketNumber* packets, size_t num_packets) {
+ void VerifyUnackedPackets(uint64_t* packets, size_t num_packets) {
unacked_packets_.RemoveObsoletePackets();
if (num_packets == 0) {
EXPECT_TRUE(unacked_packets_.empty());
@@ -107,13 +112,13 @@
}
EXPECT_FALSE(unacked_packets_.empty());
for (size_t i = 0; i < num_packets; ++i) {
- EXPECT_TRUE(unacked_packets_.IsUnacked(packets[i])) << packets[i];
+ EXPECT_TRUE(unacked_packets_.IsUnacked(QuicPacketNumber(packets[i])))
+ << packets[i];
}
EXPECT_EQ(num_packets, unacked_packets_.GetNumUnackedPacketsDebugOnly());
}
- void VerifyRetransmittablePackets(QuicPacketNumber* packets,
- size_t num_packets) {
+ void VerifyRetransmittablePackets(uint64_t* packets, size_t num_packets) {
unacked_packets_.RemoveObsoletePackets();
size_t num_retransmittable_packets = 0;
for (QuicUnackedPacketMap::const_iterator it = unacked_packets_.begin();
@@ -124,29 +129,33 @@
}
EXPECT_EQ(num_packets, num_retransmittable_packets);
for (size_t i = 0; i < num_packets; ++i) {
- EXPECT_TRUE(unacked_packets_.HasRetransmittableFrames(packets[i]))
+ EXPECT_TRUE(unacked_packets_.HasRetransmittableFrames(
+ QuicPacketNumber(packets[i])))
<< " packets[" << i << "]:" << packets[i];
}
}
- void UpdatePacketState(QuicPacketNumber packet_number,
- SentPacketState state) {
- unacked_packets_.GetMutableTransmissionInfo(packet_number)->state = state;
+ void UpdatePacketState(uint64_t packet_number, SentPacketState state) {
+ unacked_packets_
+ .GetMutableTransmissionInfo(QuicPacketNumber(packet_number))
+ ->state = state;
}
- void RetransmitAndSendPacket(QuicPacketNumber old_packet_number,
- QuicPacketNumber new_packet_number,
+ void RetransmitAndSendPacket(uint64_t old_packet_number,
+ uint64_t new_packet_number,
TransmissionType transmission_type) {
- DCHECK(unacked_packets_.HasRetransmittableFrames(old_packet_number));
+ DCHECK(unacked_packets_.HasRetransmittableFrames(
+ QuicPacketNumber(old_packet_number)));
if (!unacked_packets_.session_decides_what_to_write()) {
SerializedPacket packet(
CreateNonRetransmittablePacket(new_packet_number));
- unacked_packets_.AddSentPacket(&packet, old_packet_number,
+ unacked_packets_.AddSentPacket(&packet,
+ QuicPacketNumber(old_packet_number),
transmission_type, now_, true);
return;
}
- QuicTransmissionInfo* info =
- unacked_packets_.GetMutableTransmissionInfo(old_packet_number);
+ QuicTransmissionInfo* info = unacked_packets_.GetMutableTransmissionInfo(
+ QuicPacketNumber(old_packet_number));
QuicStreamId stream_id = QuicUtils::GetHeadersStreamId(
CurrentSupportedVersions()[0].transport_version);
for (const auto& frame : info->retransmittable_frames) {
@@ -158,10 +167,11 @@
UpdatePacketState(
old_packet_number,
QuicUtils::RetransmissionTypeToPacketState(transmission_type));
- info->retransmission = new_packet_number;
+ info->retransmission = QuicPacketNumber(new_packet_number);
SerializedPacket packet(
CreateRetransmittablePacketForStream(new_packet_number, stream_id));
- unacked_packets_.AddSentPacket(&packet, 0, transmission_type, now_, true);
+ unacked_packets_.AddSentPacket(&packet, QuicPacketNumber(),
+ transmission_type, now_, true);
}
QuicUnackedPacketMap unacked_packets_;
QuicTime now_;
@@ -173,14 +183,15 @@
TEST_P(QuicUnackedPacketMapTest, RttOnly) {
// Acks are only tracked for RTT measurement purposes.
SerializedPacket packet(CreateNonRetransmittablePacket(1));
- unacked_packets_.AddSentPacket(&packet, 0, NOT_RETRANSMISSION, now_, false);
+ unacked_packets_.AddSentPacket(&packet, QuicPacketNumber(),
+ NOT_RETRANSMISSION, now_, false);
- QuicPacketNumber unacked[] = {1};
+ uint64_t unacked[] = {1};
VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
VerifyInFlightPackets(nullptr, 0);
VerifyRetransmittablePackets(nullptr, 0);
- unacked_packets_.IncreaseLargestAcked(1);
+ unacked_packets_.IncreaseLargestAcked(QuicPacketNumber(1));
VerifyUnackedPackets(nullptr, 0);
VerifyInFlightPackets(nullptr, 0);
VerifyRetransmittablePackets(nullptr, 0);
@@ -189,24 +200,25 @@
TEST_P(QuicUnackedPacketMapTest, RetransmittableInflightAndRtt) {
// Simulate a retransmittable packet being sent and acked.
SerializedPacket packet(CreateRetransmittablePacket(1));
- unacked_packets_.AddSentPacket(&packet, 0, NOT_RETRANSMISSION, now_, true);
+ unacked_packets_.AddSentPacket(&packet, QuicPacketNumber(),
+ NOT_RETRANSMISSION, now_, true);
- QuicPacketNumber unacked[] = {1};
+ uint64_t unacked[] = {1};
VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
VerifyInFlightPackets(unacked, QUIC_ARRAYSIZE(unacked));
VerifyRetransmittablePackets(unacked, QUIC_ARRAYSIZE(unacked));
- unacked_packets_.RemoveRetransmittability(1);
+ unacked_packets_.RemoveRetransmittability(QuicPacketNumber(1));
VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
VerifyInFlightPackets(unacked, QUIC_ARRAYSIZE(unacked));
VerifyRetransmittablePackets(nullptr, 0);
- unacked_packets_.IncreaseLargestAcked(1);
+ unacked_packets_.IncreaseLargestAcked(QuicPacketNumber(1));
VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
VerifyInFlightPackets(unacked, QUIC_ARRAYSIZE(unacked));
VerifyRetransmittablePackets(nullptr, 0);
- unacked_packets_.RemoveFromInFlight(1);
+ unacked_packets_.RemoveFromInFlight(QuicPacketNumber(1));
VerifyUnackedPackets(nullptr, 0);
VerifyInFlightPackets(nullptr, 0);
VerifyRetransmittablePackets(nullptr, 0);
@@ -215,12 +227,13 @@
TEST_P(QuicUnackedPacketMapTest, StopRetransmission) {
const QuicStreamId stream_id = 2;
SerializedPacket packet(CreateRetransmittablePacketForStream(1, stream_id));
- unacked_packets_.AddSentPacket(&packet, 0, NOT_RETRANSMISSION, now_, true);
+ unacked_packets_.AddSentPacket(&packet, QuicPacketNumber(),
+ NOT_RETRANSMISSION, now_, true);
- QuicPacketNumber unacked[] = {1};
+ uint64_t unacked[] = {1};
VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
VerifyInFlightPackets(unacked, QUIC_ARRAYSIZE(unacked));
- QuicPacketNumber retransmittable[] = {1};
+ uint64_t retransmittable[] = {1};
VerifyRetransmittablePackets(retransmittable,
QUIC_ARRAYSIZE(retransmittable));
@@ -237,12 +250,13 @@
TEST_P(QuicUnackedPacketMapTest, StopRetransmissionOnOtherStream) {
const QuicStreamId stream_id = 2;
SerializedPacket packet(CreateRetransmittablePacketForStream(1, stream_id));
- unacked_packets_.AddSentPacket(&packet, 0, NOT_RETRANSMISSION, now_, true);
+ unacked_packets_.AddSentPacket(&packet, QuicPacketNumber(),
+ NOT_RETRANSMISSION, now_, true);
- QuicPacketNumber unacked[] = {1};
+ uint64_t unacked[] = {1};
VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
VerifyInFlightPackets(unacked, QUIC_ARRAYSIZE(unacked));
- QuicPacketNumber retransmittable[] = {1};
+ uint64_t retransmittable[] = {1};
VerifyRetransmittablePackets(retransmittable,
QUIC_ARRAYSIZE(retransmittable));
@@ -259,13 +273,14 @@
TEST_P(QuicUnackedPacketMapTest, StopRetransmissionAfterRetransmission) {
const QuicStreamId stream_id = 2;
SerializedPacket packet1(CreateRetransmittablePacketForStream(1, stream_id));
- unacked_packets_.AddSentPacket(&packet1, 0, NOT_RETRANSMISSION, now_, true);
+ unacked_packets_.AddSentPacket(&packet1, QuicPacketNumber(),
+ NOT_RETRANSMISSION, now_, true);
RetransmitAndSendPacket(1, 2, LOSS_RETRANSMISSION);
- QuicPacketNumber unacked[] = {1, 2};
+ uint64_t unacked[] = {1, 2};
VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
VerifyInFlightPackets(unacked, QUIC_ARRAYSIZE(unacked));
- std::vector<QuicPacketNumber> retransmittable;
+ std::vector<uint64_t> retransmittable;
if (unacked_packets_.session_decides_what_to_write()) {
retransmittable = {1, 2};
} else {
@@ -287,13 +302,14 @@
// Simulate a retransmittable packet being sent, retransmitted, and the first
// transmission being acked.
SerializedPacket packet1(CreateRetransmittablePacket(1));
- unacked_packets_.AddSentPacket(&packet1, 0, NOT_RETRANSMISSION, now_, true);
+ unacked_packets_.AddSentPacket(&packet1, QuicPacketNumber(),
+ NOT_RETRANSMISSION, now_, true);
RetransmitAndSendPacket(1, 2, LOSS_RETRANSMISSION);
- QuicPacketNumber unacked[] = {1, 2};
+ uint64_t unacked[] = {1, 2};
VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
VerifyInFlightPackets(unacked, QUIC_ARRAYSIZE(unacked));
- std::vector<QuicPacketNumber> retransmittable;
+ std::vector<uint64_t> retransmittable;
if (unacked_packets_.session_decides_what_to_write()) {
retransmittable = {1, 2};
} else {
@@ -302,23 +318,23 @@
VerifyRetransmittablePackets(&retransmittable[0], retransmittable.size());
EXPECT_CALL(notifier_, IsFrameOutstanding(_)).WillRepeatedly(Return(false));
- unacked_packets_.RemoveRetransmittability(1);
+ unacked_packets_.RemoveRetransmittability(QuicPacketNumber(1));
VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
VerifyInFlightPackets(unacked, QUIC_ARRAYSIZE(unacked));
VerifyRetransmittablePackets(nullptr, 0);
- unacked_packets_.IncreaseLargestAcked(2);
+ unacked_packets_.IncreaseLargestAcked(QuicPacketNumber(2));
VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
VerifyInFlightPackets(unacked, QUIC_ARRAYSIZE(unacked));
VerifyRetransmittablePackets(nullptr, 0);
- unacked_packets_.RemoveFromInFlight(2);
- QuicPacketNumber unacked2[] = {1};
+ unacked_packets_.RemoveFromInFlight(QuicPacketNumber(2));
+ uint64_t unacked2[] = {1};
VerifyUnackedPackets(unacked2, QUIC_ARRAYSIZE(unacked2));
VerifyInFlightPackets(unacked2, QUIC_ARRAYSIZE(unacked2));
VerifyRetransmittablePackets(nullptr, 0);
- unacked_packets_.RemoveFromInFlight(1);
+ unacked_packets_.RemoveFromInFlight(QuicPacketNumber(1));
VerifyUnackedPackets(nullptr, 0);
VerifyInFlightPackets(nullptr, 0);
VerifyRetransmittablePackets(nullptr, 0);
@@ -327,31 +343,34 @@
TEST_P(QuicUnackedPacketMapTest, RetransmitThreeTimes) {
// Simulate a retransmittable packet being sent and retransmitted twice.
SerializedPacket packet1(CreateRetransmittablePacket(1));
- unacked_packets_.AddSentPacket(&packet1, 0, NOT_RETRANSMISSION, now_, true);
+ unacked_packets_.AddSentPacket(&packet1, QuicPacketNumber(),
+ NOT_RETRANSMISSION, now_, true);
SerializedPacket packet2(CreateRetransmittablePacket(2));
- unacked_packets_.AddSentPacket(&packet2, 0, NOT_RETRANSMISSION, now_, true);
+ unacked_packets_.AddSentPacket(&packet2, QuicPacketNumber(),
+ NOT_RETRANSMISSION, now_, true);
- QuicPacketNumber unacked[] = {1, 2};
+ uint64_t unacked[] = {1, 2};
VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
VerifyInFlightPackets(unacked, QUIC_ARRAYSIZE(unacked));
- QuicPacketNumber retransmittable[] = {1, 2};
+ uint64_t retransmittable[] = {1, 2};
VerifyRetransmittablePackets(retransmittable,
QUIC_ARRAYSIZE(retransmittable));
// Early retransmit 1 as 3 and send new data as 4.
- unacked_packets_.IncreaseLargestAcked(2);
- unacked_packets_.RemoveFromInFlight(2);
- unacked_packets_.RemoveRetransmittability(2);
- unacked_packets_.RemoveFromInFlight(1);
+ unacked_packets_.IncreaseLargestAcked(QuicPacketNumber(2));
+ unacked_packets_.RemoveFromInFlight(QuicPacketNumber(2));
+ unacked_packets_.RemoveRetransmittability(QuicPacketNumber(2));
+ unacked_packets_.RemoveFromInFlight(QuicPacketNumber(1));
RetransmitAndSendPacket(1, 3, LOSS_RETRANSMISSION);
SerializedPacket packet4(CreateRetransmittablePacket(4));
- unacked_packets_.AddSentPacket(&packet4, 0, NOT_RETRANSMISSION, now_, true);
+ unacked_packets_.AddSentPacket(&packet4, QuicPacketNumber(),
+ NOT_RETRANSMISSION, now_, true);
- QuicPacketNumber unacked2[] = {1, 3, 4};
+ uint64_t unacked2[] = {1, 3, 4};
VerifyUnackedPackets(unacked2, QUIC_ARRAYSIZE(unacked2));
- QuicPacketNumber pending2[] = {3, 4};
+ uint64_t pending2[] = {3, 4};
VerifyInFlightPackets(pending2, QUIC_ARRAYSIZE(pending2));
- std::vector<QuicPacketNumber> retransmittable2;
+ std::vector<uint64_t> retransmittable2;
if (unacked_packets_.session_decides_what_to_write()) {
retransmittable2 = {1, 3, 4};
} else {
@@ -360,15 +379,16 @@
VerifyRetransmittablePackets(&retransmittable2[0], retransmittable2.size());
// Early retransmit 3 (formerly 1) as 5, and remove 1 from unacked.
- unacked_packets_.IncreaseLargestAcked(4);
- unacked_packets_.RemoveFromInFlight(4);
- unacked_packets_.RemoveRetransmittability(4);
+ unacked_packets_.IncreaseLargestAcked(QuicPacketNumber(4));
+ unacked_packets_.RemoveFromInFlight(QuicPacketNumber(4));
+ unacked_packets_.RemoveRetransmittability(QuicPacketNumber(4));
RetransmitAndSendPacket(3, 5, LOSS_RETRANSMISSION);
SerializedPacket packet6(CreateRetransmittablePacket(6));
- unacked_packets_.AddSentPacket(&packet6, 0, NOT_RETRANSMISSION, now_, true);
+ unacked_packets_.AddSentPacket(&packet6, QuicPacketNumber(),
+ NOT_RETRANSMISSION, now_, true);
- std::vector<QuicPacketNumber> unacked3;
- std::vector<QuicPacketNumber> retransmittable3;
+ std::vector<uint64_t> unacked3;
+ std::vector<uint64_t> retransmittable3;
if (unacked_packets_.session_decides_what_to_write()) {
unacked3 = {3, 5, 6};
retransmittable3 = {3, 5, 6};
@@ -378,17 +398,17 @@
}
VerifyUnackedPackets(&unacked3[0], unacked3.size());
VerifyRetransmittablePackets(&retransmittable3[0], retransmittable3.size());
- QuicPacketNumber pending3[] = {3, 5, 6};
+ uint64_t pending3[] = {3, 5, 6};
VerifyInFlightPackets(pending3, QUIC_ARRAYSIZE(pending3));
// Early retransmit 5 as 7 and ensure in flight packet 3 is not removed.
- unacked_packets_.IncreaseLargestAcked(6);
- unacked_packets_.RemoveFromInFlight(6);
- unacked_packets_.RemoveRetransmittability(6);
+ unacked_packets_.IncreaseLargestAcked(QuicPacketNumber(6));
+ unacked_packets_.RemoveFromInFlight(QuicPacketNumber(6));
+ unacked_packets_.RemoveRetransmittability(QuicPacketNumber(6));
RetransmitAndSendPacket(5, 7, LOSS_RETRANSMISSION);
- std::vector<QuicPacketNumber> unacked4;
- std::vector<QuicPacketNumber> retransmittable4;
+ std::vector<uint64_t> unacked4;
+ std::vector<uint64_t> retransmittable4;
if (unacked_packets_.session_decides_what_to_write()) {
unacked4 = {3, 5, 7};
retransmittable4 = {3, 5, 7};
@@ -398,42 +418,44 @@
}
VerifyUnackedPackets(&unacked4[0], unacked4.size());
VerifyRetransmittablePackets(&retransmittable4[0], retransmittable4.size());
- QuicPacketNumber pending4[] = {3, 5, 7};
+ uint64_t pending4[] = {3, 5, 7};
VerifyInFlightPackets(pending4, QUIC_ARRAYSIZE(pending4));
// Remove the older two transmissions from in flight.
- unacked_packets_.RemoveFromInFlight(3);
- unacked_packets_.RemoveFromInFlight(5);
- QuicPacketNumber pending5[] = {7};
+ unacked_packets_.RemoveFromInFlight(QuicPacketNumber(3));
+ unacked_packets_.RemoveFromInFlight(QuicPacketNumber(5));
+ uint64_t pending5[] = {7};
VerifyInFlightPackets(pending5, QUIC_ARRAYSIZE(pending5));
}
TEST_P(QuicUnackedPacketMapTest, RetransmitFourTimes) {
// Simulate a retransmittable packet being sent and retransmitted twice.
SerializedPacket packet1(CreateRetransmittablePacket(1));
- unacked_packets_.AddSentPacket(&packet1, 0, NOT_RETRANSMISSION, now_, true);
+ unacked_packets_.AddSentPacket(&packet1, QuicPacketNumber(),
+ NOT_RETRANSMISSION, now_, true);
SerializedPacket packet2(CreateRetransmittablePacket(2));
- unacked_packets_.AddSentPacket(&packet2, 0, NOT_RETRANSMISSION, now_, true);
+ unacked_packets_.AddSentPacket(&packet2, QuicPacketNumber(),
+ NOT_RETRANSMISSION, now_, true);
- QuicPacketNumber unacked[] = {1, 2};
+ uint64_t unacked[] = {1, 2};
VerifyUnackedPackets(unacked, QUIC_ARRAYSIZE(unacked));
VerifyInFlightPackets(unacked, QUIC_ARRAYSIZE(unacked));
- QuicPacketNumber retransmittable[] = {1, 2};
+ uint64_t retransmittable[] = {1, 2};
VerifyRetransmittablePackets(retransmittable,
QUIC_ARRAYSIZE(retransmittable));
// Early retransmit 1 as 3.
- unacked_packets_.IncreaseLargestAcked(2);
- unacked_packets_.RemoveFromInFlight(2);
- unacked_packets_.RemoveRetransmittability(2);
- unacked_packets_.RemoveFromInFlight(1);
+ unacked_packets_.IncreaseLargestAcked(QuicPacketNumber(2));
+ unacked_packets_.RemoveFromInFlight(QuicPacketNumber(2));
+ unacked_packets_.RemoveRetransmittability(QuicPacketNumber(2));
+ unacked_packets_.RemoveFromInFlight(QuicPacketNumber(1));
RetransmitAndSendPacket(1, 3, LOSS_RETRANSMISSION);
- QuicPacketNumber unacked2[] = {1, 3};
+ uint64_t unacked2[] = {1, 3};
VerifyUnackedPackets(unacked2, QUIC_ARRAYSIZE(unacked2));
- QuicPacketNumber pending2[] = {3};
+ uint64_t pending2[] = {3};
VerifyInFlightPackets(pending2, QUIC_ARRAYSIZE(pending2));
- std::vector<QuicPacketNumber> retransmittable2;
+ std::vector<uint64_t> retransmittable2;
if (unacked_packets_.session_decides_what_to_write()) {
retransmittable2 = {1, 3};
} else {
@@ -444,13 +466,14 @@
// TLP 3 (formerly 1) as 4, and don't remove 1 from unacked.
RetransmitAndSendPacket(3, 4, TLP_RETRANSMISSION);
SerializedPacket packet5(CreateRetransmittablePacket(5));
- unacked_packets_.AddSentPacket(&packet5, 0, NOT_RETRANSMISSION, now_, true);
+ unacked_packets_.AddSentPacket(&packet5, QuicPacketNumber(),
+ NOT_RETRANSMISSION, now_, true);
- QuicPacketNumber unacked3[] = {1, 3, 4, 5};
+ uint64_t unacked3[] = {1, 3, 4, 5};
VerifyUnackedPackets(unacked3, QUIC_ARRAYSIZE(unacked3));
- QuicPacketNumber pending3[] = {3, 4, 5};
+ uint64_t pending3[] = {3, 4, 5};
VerifyInFlightPackets(pending3, QUIC_ARRAYSIZE(pending3));
- std::vector<QuicPacketNumber> retransmittable3;
+ std::vector<uint64_t> retransmittable3;
if (unacked_packets_.session_decides_what_to_write()) {
retransmittable3 = {1, 3, 4, 5};
} else {
@@ -459,23 +482,23 @@
VerifyRetransmittablePackets(&retransmittable3[0], retransmittable3.size());
// Early retransmit 4 as 6 and ensure in flight packet 3 is removed.
- unacked_packets_.IncreaseLargestAcked(5);
- unacked_packets_.RemoveFromInFlight(5);
- unacked_packets_.RemoveRetransmittability(5);
- unacked_packets_.RemoveFromInFlight(3);
- unacked_packets_.RemoveFromInFlight(4);
+ unacked_packets_.IncreaseLargestAcked(QuicPacketNumber(5));
+ unacked_packets_.RemoveFromInFlight(QuicPacketNumber(5));
+ unacked_packets_.RemoveRetransmittability(QuicPacketNumber(5));
+ unacked_packets_.RemoveFromInFlight(QuicPacketNumber(3));
+ unacked_packets_.RemoveFromInFlight(QuicPacketNumber(4));
RetransmitAndSendPacket(4, 6, LOSS_RETRANSMISSION);
- std::vector<QuicPacketNumber> unacked4;
+ std::vector<uint64_t> unacked4;
if (unacked_packets_.session_decides_what_to_write()) {
unacked4 = {4, 6};
} else {
unacked4 = {4, 6};
}
VerifyUnackedPackets(&unacked4[0], unacked4.size());
- QuicPacketNumber pending4[] = {6};
+ uint64_t pending4[] = {6};
VerifyInFlightPackets(pending4, QUIC_ARRAYSIZE(pending4));
- std::vector<QuicPacketNumber> retransmittable4;
+ std::vector<uint64_t> retransmittable4;
if (unacked_packets_.session_decides_what_to_write()) {
retransmittable4 = {4, 6};
} else {
@@ -488,18 +511,20 @@
// Simulate a retransmittable packet being sent, retransmitted, and the first
// transmission being acked.
SerializedPacket packet1(CreateRetransmittablePacket(1));
- unacked_packets_.AddSentPacket(&packet1, 0, NOT_RETRANSMISSION, now_, true);
+ unacked_packets_.AddSentPacket(&packet1, QuicPacketNumber(),
+ NOT_RETRANSMISSION, now_, true);
SerializedPacket packet3(CreateRetransmittablePacket(3));
- unacked_packets_.AddSentPacket(&packet3, 0, NOT_RETRANSMISSION, now_, true);
+ unacked_packets_.AddSentPacket(&packet3, QuicPacketNumber(),
+ NOT_RETRANSMISSION, now_, true);
RetransmitAndSendPacket(3, 5, LOSS_RETRANSMISSION);
- EXPECT_EQ(1u, unacked_packets_.GetLeastUnacked());
- EXPECT_TRUE(unacked_packets_.IsUnacked(1));
- EXPECT_FALSE(unacked_packets_.IsUnacked(2));
- EXPECT_TRUE(unacked_packets_.IsUnacked(3));
- EXPECT_FALSE(unacked_packets_.IsUnacked(4));
- EXPECT_TRUE(unacked_packets_.IsUnacked(5));
- EXPECT_EQ(5u, unacked_packets_.largest_sent_packet());
+ EXPECT_EQ(QuicPacketNumber(1u), unacked_packets_.GetLeastUnacked());
+ EXPECT_TRUE(unacked_packets_.IsUnacked(QuicPacketNumber(1)));
+ EXPECT_FALSE(unacked_packets_.IsUnacked(QuicPacketNumber(2)));
+ EXPECT_TRUE(unacked_packets_.IsUnacked(QuicPacketNumber(3)));
+ EXPECT_FALSE(unacked_packets_.IsUnacked(QuicPacketNumber(4)));
+ EXPECT_TRUE(unacked_packets_.IsUnacked(QuicPacketNumber(5)));
+ EXPECT_EQ(QuicPacketNumber(5u), unacked_packets_.largest_sent_packet());
}
TEST_P(QuicUnackedPacketMapTest, AggregateContiguousAckedStreamFrames) {
diff --git a/quic/core/quic_utils.cc b/quic/core/quic_utils.cc
index a08328c..be6eeea 100644
--- a/quic/core/quic_utils.cc
+++ b/quic/core/quic_utils.cc
@@ -443,6 +443,37 @@
QUIC_ARRAYSIZE(connection_id_bytes));
}
+// static
+bool QuicUtils::VariableLengthConnectionIdAllowedForVersion(
+ QuicTransportVersion version) {
+ // TODO(dschinazi): Allow in appropriate version when supported.
+ return false;
+}
+
+// static
+QuicConnectionId QuicUtils::CreateZeroConnectionId(
+ QuicTransportVersion version) {
+ if (!QuicConnectionIdSupportsVariableLength(Perspective::IS_SERVER) ||
+ !QuicConnectionIdSupportsVariableLength(Perspective::IS_CLIENT)) {
+ return QuicConnectionIdFromUInt64(0);
+ }
+ if (!VariableLengthConnectionIdAllowedForVersion(version)) {
+ char connection_id_bytes[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+ return QuicConnectionId(static_cast<char*>(connection_id_bytes),
+ QUIC_ARRAYSIZE(connection_id_bytes));
+ }
+ return EmptyQuicConnectionId();
+}
+
+// static
+bool QuicUtils::IsConnectionIdValidForVersion(QuicConnectionId connection_id,
+ QuicTransportVersion version) {
+ if (VariableLengthConnectionIdAllowedForVersion(version)) {
+ return true;
+ }
+ return connection_id.length() == kQuicDefaultConnectionIdLength;
+}
+
QuicUint128 QuicUtils::GenerateStatelessResetToken(
QuicConnectionId connection_id) {
if (!QuicConnectionIdUseNetworkByteOrder()) {
diff --git a/quic/core/quic_utils.h b/quic/core/quic_utils.h
index 114465e..111080a 100644
--- a/quic/core/quic_utils.h
+++ b/quic/core/quic_utils.h
@@ -151,6 +151,19 @@
static QuicConnectionId CreateRandomConnectionId(QuicRandom* random,
Perspective perspective);
+ // Returns true if the QUIC version allows variable length connection IDs.
+ static bool VariableLengthConnectionIdAllowedForVersion(
+ QuicTransportVersion version);
+
+ // Returns true if the connection ID is valid for this QUIC version.
+ static bool IsConnectionIdValidForVersion(QuicConnectionId connection_id,
+ QuicTransportVersion version);
+
+ // Returns a connection ID suitable for QUIC use-cases that do not need the
+ // connection ID for multiplexing. If the version allows variable lengths,
+ // a connection of length zero is returned, otherwise 64bits set to zero.
+ static QuicConnectionId CreateZeroConnectionId(QuicTransportVersion version);
+
// Generates a 128bit stateless reset token based on a connection ID.
static QuicUint128 GenerateStatelessResetToken(
QuicConnectionId connection_id);
diff --git a/quic/core/quic_utils_test.cc b/quic/core/quic_utils_test.cc
index d725e72..d1b5268 100644
--- a/quic/core/quic_utils_test.cc
+++ b/quic/core/quic_utils_test.cc
@@ -183,6 +183,23 @@
EXPECT_NE(connection_id, TestConnectionId(1));
}
+TEST_F(QuicUtilsTest, VariableLengthConnectionId) {
+ EXPECT_FALSE(
+ QuicUtils::VariableLengthConnectionIdAllowedForVersion(QUIC_VERSION_35));
+ EXPECT_TRUE(QuicUtils::IsConnectionIdValidForVersion(
+ QuicUtils::CreateZeroConnectionId(QUIC_VERSION_35), QUIC_VERSION_35));
+ EXPECT_TRUE(QuicUtils::IsConnectionIdValidForVersion(
+ QuicUtils::CreateZeroConnectionId(QUIC_VERSION_99), QUIC_VERSION_99));
+ if (!QuicConnectionIdSupportsVariableLength(quic::Perspective::IS_SERVER) ||
+ !QuicConnectionIdSupportsVariableLength(quic::Perspective::IS_CLIENT)) {
+ return;
+ }
+ EXPECT_NE(QuicUtils::CreateZeroConnectionId(QUIC_VERSION_35),
+ EmptyQuicConnectionId());
+ EXPECT_FALSE(QuicUtils::IsConnectionIdValidForVersion(EmptyQuicConnectionId(),
+ QUIC_VERSION_35));
+}
+
TEST_F(QuicUtilsTest, StatelessResetToken) {
QuicConnectionId connection_id1a = test::TestConnectionId(1);
QuicConnectionId connection_id1b = test::TestConnectionId(1);
diff --git a/quic/core/quic_version_manager.cc b/quic/core/quic_version_manager.cc
index 7d5e3f3..064e932 100644
--- a/quic/core/quic_version_manager.cc
+++ b/quic/core/quic_version_manager.cc
@@ -15,6 +15,7 @@
QuicVersionManager::QuicVersionManager(
ParsedQuicVersionVector supported_versions)
: enable_version_99_(GetQuicReloadableFlag(quic_enable_version_99)),
+ enable_version_47_(GetQuicReloadableFlag(quic_enable_version_47)),
enable_version_46_(GetQuicReloadableFlag(quic_enable_version_46)),
enable_version_45_(GetQuicReloadableFlag(quic_enable_version_45)),
enable_version_44_(GetQuicReloadableFlag(quic_enable_version_44)),
@@ -39,12 +40,14 @@
void QuicVersionManager::MaybeRefilterSupportedVersions() {
if (enable_version_99_ != GetQuicReloadableFlag(quic_enable_version_99) ||
+ enable_version_47_ != GetQuicReloadableFlag(quic_enable_version_47) ||
enable_version_46_ != GetQuicReloadableFlag(quic_enable_version_46) ||
enable_version_45_ != GetQuicReloadableFlag(quic_enable_version_45) ||
enable_version_44_ != GetQuicReloadableFlag(quic_enable_version_44) ||
enable_version_43_ != GetQuicReloadableFlag(quic_enable_version_43) ||
disable_version_35_ != GetQuicReloadableFlag(quic_disable_version_35)) {
enable_version_99_ = GetQuicReloadableFlag(quic_enable_version_99);
+ enable_version_47_ = GetQuicReloadableFlag(quic_enable_version_47);
enable_version_46_ = GetQuicReloadableFlag(quic_enable_version_46);
enable_version_45_ = GetQuicReloadableFlag(quic_enable_version_45);
enable_version_44_ = GetQuicReloadableFlag(quic_enable_version_44);
diff --git a/quic/core/quic_version_manager.h b/quic/core/quic_version_manager.h
index d3b18fe..1196c31 100644
--- a/quic/core/quic_version_manager.h
+++ b/quic/core/quic_version_manager.h
@@ -37,6 +37,8 @@
private:
// quic_enable_version_99 flag
bool enable_version_99_;
+ // quic_enable_version_47 flag
+ bool enable_version_47_;
// quic_enable_version_46 flag
bool enable_version_46_;
// quic_enable_version_45 flag
diff --git a/quic/core/quic_version_manager_test.cc b/quic/core/quic_version_manager_test.cc
index d70b852..b734b89 100644
--- a/quic/core/quic_version_manager_test.cc
+++ b/quic/core/quic_version_manager_test.cc
@@ -16,9 +16,10 @@
class QuicVersionManagerTest : public QuicTest {};
TEST_F(QuicVersionManagerTest, QuicVersionManager) {
- static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 7u,
+ static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 8u,
"Supported versions out of sync");
SetQuicReloadableFlag(quic_enable_version_99, false);
+ SetQuicReloadableFlag(quic_enable_version_47, false);
SetQuicReloadableFlag(quic_enable_version_46, false);
SetQuicReloadableFlag(quic_enable_version_45, false);
SetQuicReloadableFlag(quic_enable_version_44, false);
@@ -58,11 +59,18 @@
QUIC_VERSION_39, QUIC_VERSION_35}),
manager.GetSupportedTransportVersions());
+ SetQuicReloadableFlag(quic_enable_version_47, true);
+ EXPECT_EQ(
+ QuicTransportVersionVector(
+ {QUIC_VERSION_47, QUIC_VERSION_46, QUIC_VERSION_45, QUIC_VERSION_44,
+ QUIC_VERSION_43, QUIC_VERSION_39, QUIC_VERSION_35}),
+ manager.GetSupportedTransportVersions());
+
SetQuicReloadableFlag(quic_enable_version_99, true);
EXPECT_EQ(
QuicTransportVersionVector(
- {QUIC_VERSION_99, QUIC_VERSION_46, QUIC_VERSION_45, QUIC_VERSION_44,
- QUIC_VERSION_43, QUIC_VERSION_39, QUIC_VERSION_35}),
+ {QUIC_VERSION_99, QUIC_VERSION_47, QUIC_VERSION_46, QUIC_VERSION_45,
+ QUIC_VERSION_44, QUIC_VERSION_43, QUIC_VERSION_39, QUIC_VERSION_35}),
manager.GetSupportedTransportVersions());
// Ensure that all versions are now supported.
diff --git a/quic/core/quic_versions.cc b/quic/core/quic_versions.cc
index 7db4254..6f050dd 100644
--- a/quic/core/quic_versions.cc
+++ b/quic/core/quic_versions.cc
@@ -66,6 +66,8 @@
return MakeVersionLabel(proto, '0', '4', '5');
case QUIC_VERSION_46:
return MakeVersionLabel(proto, '0', '4', '6');
+ case QUIC_VERSION_47:
+ return MakeVersionLabel(proto, '0', '4', '7');
case QUIC_VERSION_99:
return MakeVersionLabel(proto, '0', '9', '9');
default:
@@ -103,7 +105,7 @@
// Reading from the client so this should not be considered an ERROR.
QUIC_DLOG(INFO) << "Unsupported QuicVersionLabel version: "
<< QuicVersionLabelToString(version_label);
- return ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED);
+ return UnsupportedQuicVersion();
}
QuicTransportVersionVector AllSupportedTransportVersions() {
@@ -159,6 +161,15 @@
for (ParsedQuicVersion version : versions) {
if (version.transport_version == QUIC_VERSION_99) {
if (GetQuicReloadableFlag(quic_enable_version_99) &&
+ GetQuicReloadableFlag(quic_enable_version_47) &&
+ GetQuicReloadableFlag(quic_enable_version_46) &&
+ GetQuicReloadableFlag(quic_enable_version_45) &&
+ GetQuicReloadableFlag(quic_enable_version_44) &&
+ GetQuicReloadableFlag(quic_enable_version_43)) {
+ filtered_versions.push_back(version);
+ }
+ } else if (version.transport_version == QUIC_VERSION_47) {
+ if (GetQuicReloadableFlag(quic_enable_version_47) &&
GetQuicReloadableFlag(quic_enable_version_46) &&
GetQuicReloadableFlag(quic_enable_version_45) &&
GetQuicReloadableFlag(quic_enable_version_44) &&
@@ -219,8 +230,7 @@
if (index >= 0 && index < version_count) {
version.push_back(versions[index]);
} else {
- version.push_back(
- ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED));
+ version.push_back(UnsupportedQuicVersion());
}
return version;
}
@@ -286,6 +296,7 @@
RETURN_STRING_LITERAL(QUIC_VERSION_44);
RETURN_STRING_LITERAL(QUIC_VERSION_45);
RETURN_STRING_LITERAL(QUIC_VERSION_46);
+ RETURN_STRING_LITERAL(QUIC_VERSION_47);
RETURN_STRING_LITERAL(QUIC_VERSION_99);
default:
return "QUIC_VERSION_UNSUPPORTED";
@@ -327,9 +338,7 @@
}
ParsedQuicVersion UnsupportedQuicVersion() {
- static const ParsedQuicVersion kUnsupportedQuicVersion(
- PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED);
- return kUnsupportedQuicVersion;
+ return ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED);
}
#undef RETURN_STRING_LITERAL // undef for jumbo builds
diff --git a/quic/core/quic_versions.h b/quic/core/quic_versions.h
index 2f780ab..2c3ba1f 100644
--- a/quic/core/quic_versions.h
+++ b/quic/core/quic_versions.h
@@ -102,6 +102,8 @@
QUIC_VERSION_44 = 44, // Use IETF header format.
QUIC_VERSION_45 = 45, // Added MESSAGE frame.
QUIC_VERSION_46 = 46, // Use CRYPTO frames for QuicCryptoStreams.
+ QUIC_VERSION_47 = 47, // Use IETF draft-17 header format with demultiplexing
+ // bit.
QUIC_VERSION_99 = 99, // Dumping ground for IETF QUIC changes which are not
// yet ready for production.
};
@@ -164,8 +166,8 @@
//
// See go/new-quic-version for more details on how to roll out new versions.
static const QuicTransportVersion kSupportedTransportVersions[] = {
- QUIC_VERSION_99, QUIC_VERSION_46, QUIC_VERSION_45, QUIC_VERSION_44,
- QUIC_VERSION_43, QUIC_VERSION_39, QUIC_VERSION_35};
+ QUIC_VERSION_99, QUIC_VERSION_47, QUIC_VERSION_46, QUIC_VERSION_45,
+ QUIC_VERSION_44, QUIC_VERSION_43, QUIC_VERSION_39, QUIC_VERSION_35};
// This vector contains all crypto handshake protocols that are supported.
static const HandshakeProtocol kSupportedHandshakeProtocols[] = {
@@ -206,8 +208,7 @@
VersionOfIndex(const QuicTransportVersionVector& versions, int index);
// Returns QUIC version of |index| in result of |versions|. Returns
-// ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED) if |index|
-// is out of bounds.
+// UnsupportedQuicVersion() if |index| is out of bounds.
QUIC_EXPORT_PRIVATE ParsedQuicVersionVector
ParsedVersionOfIndex(const ParsedQuicVersionVector& versions, int index);
diff --git a/quic/core/quic_versions_test.cc b/quic/core/quic_versions_test.cc
index e9e1854..a0f664e 100644
--- a/quic/core/quic_versions_test.cc
+++ b/quic/core/quic_versions_test.cc
@@ -53,8 +53,10 @@
CREATE_QUIC_MOCK_LOG(log);
log.StartCapturingLogs();
- EXPECT_QUIC_LOG_CALL_CONTAINS(log, ERROR,
- "Unsupported QuicTransportVersion: 0");
+ if (QUIC_LOG_ERROR_IS_ON()) {
+ EXPECT_QUIC_LOG_CALL_CONTAINS(log, ERROR,
+ "Unsupported QuicTransportVersion: 0");
+ }
EXPECT_EQ(0u, QuicVersionToQuicVersionLabel(QUIC_VERSION_UNSUPPORTED));
}
@@ -90,11 +92,11 @@
TEST_F(QuicVersionsTest, QuicVersionLabelToQuicVersionUnsupported) {
CREATE_QUIC_MOCK_LOG(log);
-#if QUIC_DLOG_INFO_IS_ON
- EXPECT_QUIC_LOG_CALL_CONTAINS(log, INFO,
- "Unsupported QuicVersionLabel version: EKAF")
- .Times(1);
-#endif
+ if (QUIC_DLOG_INFO_IS_ON()) {
+ EXPECT_QUIC_LOG_CALL_CONTAINS(log, INFO,
+ "Unsupported QuicVersionLabel version: EKAF")
+ .Times(1);
+ }
log.StartCapturingLogs();
EXPECT_EQ(QUIC_VERSION_UNSUPPORTED,
@@ -119,11 +121,11 @@
EXPECT_EQ(PROTOCOL_TLS1_3, QuicVersionLabelToHandshakeProtocol(tls_tag));
FLAGS_quic_supports_tls_handshake = false;
-#if QUIC_DLOG_INFO_IS_ON
- EXPECT_QUIC_LOG_CALL_CONTAINS(log, INFO,
- "Unsupported QuicVersionLabel version: T043")
- .Times(1);
-#endif
+ if (QUIC_DLOG_INFO_IS_ON()) {
+ EXPECT_QUIC_LOG_CALL_CONTAINS(log, INFO,
+ "Unsupported QuicVersionLabel version: T043")
+ .Times(1);
+ }
EXPECT_EQ(PROTOCOL_UNSUPPORTED, QuicVersionLabelToHandshakeProtocol(tls_tag));
}
@@ -140,6 +142,8 @@
ParseQuicVersionLabel(MakeVersionLabel('Q', '0', '4', '5')));
EXPECT_EQ(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_46),
ParseQuicVersionLabel(MakeVersionLabel('Q', '0', '4', '6')));
+ EXPECT_EQ(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_47),
+ ParseQuicVersionLabel(MakeVersionLabel('Q', '0', '4', '7')));
// Test a TLS version:
FLAGS_quic_supports_tls_handshake = true;
@@ -155,20 +159,24 @@
ParseQuicVersionLabel(MakeVersionLabel('T', '0', '4', '5')));
EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_46),
ParseQuicVersionLabel(MakeVersionLabel('T', '0', '4', '6')));
+ EXPECT_EQ(ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_47),
+ ParseQuicVersionLabel(MakeVersionLabel('T', '0', '4', '7')));
FLAGS_quic_supports_tls_handshake = false;
- EXPECT_EQ(ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED),
+ EXPECT_EQ(UnsupportedQuicVersion(),
ParseQuicVersionLabel(MakeVersionLabel('T', '0', '3', '5')));
- EXPECT_EQ(ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED),
+ EXPECT_EQ(UnsupportedQuicVersion(),
ParseQuicVersionLabel(MakeVersionLabel('T', '0', '3', '9')));
- EXPECT_EQ(ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED),
+ EXPECT_EQ(UnsupportedQuicVersion(),
ParseQuicVersionLabel(MakeVersionLabel('T', '0', '4', '3')));
- EXPECT_EQ(ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED),
+ EXPECT_EQ(UnsupportedQuicVersion(),
ParseQuicVersionLabel(MakeVersionLabel('T', '0', '4', '4')));
- EXPECT_EQ(ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED),
+ EXPECT_EQ(UnsupportedQuicVersion(),
ParseQuicVersionLabel(MakeVersionLabel('T', '0', '4', '5')));
- EXPECT_EQ(ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED),
+ EXPECT_EQ(UnsupportedQuicVersion(),
ParseQuicVersionLabel(MakeVersionLabel('T', '0', '4', '6')));
+ EXPECT_EQ(UnsupportedQuicVersion(),
+ ParseQuicVersionLabel(MakeVersionLabel('T', '0', '4', '7')));
}
TEST_F(QuicVersionsTest, CreateQuicVersionLabel) {
@@ -190,6 +198,9 @@
EXPECT_EQ(MakeVersionLabel('Q', '0', '4', '6'),
CreateQuicVersionLabel(
ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_46)));
+ EXPECT_EQ(MakeVersionLabel('Q', '0', '4', '7'),
+ CreateQuicVersionLabel(
+ ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_47)));
// Test a TLS version:
FLAGS_quic_supports_tls_handshake = true;
@@ -211,20 +222,25 @@
EXPECT_EQ(MakeVersionLabel('T', '0', '4', '6'),
CreateQuicVersionLabel(
ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_46)));
+ EXPECT_EQ(MakeVersionLabel('T', '0', '4', '7'),
+ CreateQuicVersionLabel(
+ ParsedQuicVersion(PROTOCOL_TLS1_3, QUIC_VERSION_47)));
FLAGS_quic_supports_tls_handshake = false;
- EXPECT_EQ(ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED),
+ EXPECT_EQ(UnsupportedQuicVersion(),
ParseQuicVersionLabel(MakeVersionLabel('T', '0', '3', '5')));
- EXPECT_EQ(ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED),
+ EXPECT_EQ(UnsupportedQuicVersion(),
ParseQuicVersionLabel(MakeVersionLabel('T', '0', '3', '9')));
- EXPECT_EQ(ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED),
+ EXPECT_EQ(UnsupportedQuicVersion(),
ParseQuicVersionLabel(MakeVersionLabel('T', '0', '4', '3')));
- EXPECT_EQ(ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED),
+ EXPECT_EQ(UnsupportedQuicVersion(),
ParseQuicVersionLabel(MakeVersionLabel('T', '0', '4', '4')));
- EXPECT_EQ(ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED),
+ EXPECT_EQ(UnsupportedQuicVersion(),
ParseQuicVersionLabel(MakeVersionLabel('T', '0', '4', '5')));
- EXPECT_EQ(ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED),
+ EXPECT_EQ(UnsupportedQuicVersion(),
ParseQuicVersionLabel(MakeVersionLabel('T', '0', '4', '6')));
+ EXPECT_EQ(UnsupportedQuicVersion(),
+ ParseQuicVersionLabel(MakeVersionLabel('T', '0', '4', '7')));
}
TEST_F(QuicVersionsTest, QuicVersionLabelToString) {
@@ -274,7 +290,7 @@
}
TEST_F(QuicVersionsTest, ParsedQuicVersionToString) {
- ParsedQuicVersion unsupported(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED);
+ ParsedQuicVersion unsupported = UnsupportedQuicVersion();
ParsedQuicVersion version35(PROTOCOL_QUIC_CRYPTO, QUIC_VERSION_35);
EXPECT_EQ("Q035", ParsedQuicVersionToString(version35));
EXPECT_EQ("0", ParsedQuicVersionToString(unsupported));
@@ -313,14 +329,15 @@
SetQuicReloadableFlag(quic_enable_version_44, true);
SetQuicReloadableFlag(quic_enable_version_45, true);
SetQuicReloadableFlag(quic_enable_version_46, true);
+ SetQuicReloadableFlag(quic_enable_version_47, true);
SetQuicReloadableFlag(quic_enable_version_99, true);
ParsedQuicVersionVector parsed_versions;
for (QuicTransportVersion version : all_versions) {
parsed_versions.push_back(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, version));
}
QuicTransportVersionVector expected_versions = {
- QUIC_VERSION_99, QUIC_VERSION_46, QUIC_VERSION_45, QUIC_VERSION_44,
- QUIC_VERSION_43, QUIC_VERSION_39, QUIC_VERSION_35};
+ QUIC_VERSION_99, QUIC_VERSION_47, QUIC_VERSION_46, QUIC_VERSION_45,
+ QUIC_VERSION_44, QUIC_VERSION_43, QUIC_VERSION_39, QUIC_VERSION_35};
ParsedQuicVersionVector expected_parsed_versions;
for (QuicTransportVersion version : expected_versions) {
expected_parsed_versions.push_back(
@@ -338,6 +355,33 @@
SetQuicReloadableFlag(quic_enable_version_44, true);
SetQuicReloadableFlag(quic_enable_version_45, true);
SetQuicReloadableFlag(quic_enable_version_46, true);
+ SetQuicReloadableFlag(quic_enable_version_47, true);
+ SetQuicReloadableFlag(quic_enable_version_99, false);
+ ParsedQuicVersionVector parsed_versions;
+ for (QuicTransportVersion version : all_versions) {
+ parsed_versions.push_back(ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, version));
+ }
+ QuicTransportVersionVector expected_versions = {
+ QUIC_VERSION_47, QUIC_VERSION_46, QUIC_VERSION_45, QUIC_VERSION_44,
+ QUIC_VERSION_43, QUIC_VERSION_39, QUIC_VERSION_35};
+ ParsedQuicVersionVector expected_parsed_versions;
+ for (QuicTransportVersion version : expected_versions) {
+ expected_parsed_versions.push_back(
+ ParsedQuicVersion(PROTOCOL_QUIC_CRYPTO, version));
+ }
+
+ ASSERT_EQ(expected_versions, FilterSupportedTransportVersions(all_versions));
+ ASSERT_EQ(expected_parsed_versions, FilterSupportedVersions(parsed_versions));
+}
+
+TEST_F(QuicVersionsTest, FilterSupportedTransportVersionsNo47) {
+ QuicTransportVersionVector all_versions = AllSupportedTransportVersions();
+ SetQuicReloadableFlag(quic_disable_version_35, false);
+ SetQuicReloadableFlag(quic_enable_version_43, true);
+ SetQuicReloadableFlag(quic_enable_version_44, true);
+ SetQuicReloadableFlag(quic_enable_version_45, true);
+ SetQuicReloadableFlag(quic_enable_version_46, true);
+ SetQuicReloadableFlag(quic_enable_version_47, false);
SetQuicReloadableFlag(quic_enable_version_99, false);
ParsedQuicVersionVector parsed_versions;
for (QuicTransportVersion version : all_versions) {
@@ -363,6 +407,7 @@
SetQuicReloadableFlag(quic_enable_version_44, true);
SetQuicReloadableFlag(quic_enable_version_45, true);
SetQuicReloadableFlag(quic_enable_version_46, false);
+ SetQuicReloadableFlag(quic_enable_version_47, false);
SetQuicReloadableFlag(quic_enable_version_99, false);
ParsedQuicVersionVector parsed_versions;
for (QuicTransportVersion version : all_versions) {
@@ -388,6 +433,7 @@
SetQuicReloadableFlag(quic_enable_version_44, true);
SetQuicReloadableFlag(quic_enable_version_45, false);
SetQuicReloadableFlag(quic_enable_version_46, false);
+ SetQuicReloadableFlag(quic_enable_version_47, false);
SetQuicReloadableFlag(quic_enable_version_99, false);
ParsedQuicVersionVector parsed_versions;
for (QuicTransportVersion version : all_versions) {
@@ -412,6 +458,7 @@
SetQuicReloadableFlag(quic_enable_version_44, false);
SetQuicReloadableFlag(quic_enable_version_45, false);
SetQuicReloadableFlag(quic_enable_version_46, false);
+ SetQuicReloadableFlag(quic_enable_version_47, false);
SetQuicReloadableFlag(quic_enable_version_99, false);
ParsedQuicVersionVector parsed_versions;
for (QuicTransportVersion version : all_versions) {
@@ -436,6 +483,7 @@
SetQuicReloadableFlag(quic_enable_version_44, false);
SetQuicReloadableFlag(quic_enable_version_45, false);
SetQuicReloadableFlag(quic_enable_version_46, false);
+ SetQuicReloadableFlag(quic_enable_version_47, false);
SetQuicReloadableFlag(quic_enable_version_99, false);
ParsedQuicVersionVector parsed_versions;
for (QuicTransportVersion version : all_versions) {
@@ -460,6 +508,7 @@
SetQuicReloadableFlag(quic_enable_version_44, false);
SetQuicReloadableFlag(quic_enable_version_45, false);
SetQuicReloadableFlag(quic_enable_version_46, false);
+ SetQuicReloadableFlag(quic_enable_version_47, false);
SetQuicReloadableFlag(quic_enable_version_99, false);
ParsedQuicVersionVector parsed_versions;
for (QuicTransportVersion version : all_versions) {
@@ -495,9 +544,8 @@
if (i >= 0 && i < version_count) {
EXPECT_EQ(all_versions[i], ParsedVersionOfIndex(all_versions, i)[0]);
} else {
- EXPECT_EQ(
- ParsedQuicVersion(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED),
- ParsedVersionOfIndex(all_versions, i)[0]);
+ EXPECT_EQ(UnsupportedQuicVersion(),
+ ParsedVersionOfIndex(all_versions, i)[0]);
}
}
}
@@ -516,7 +564,7 @@
// yet a typo was made in doing the #defines and it was caught
// only in some test far removed from here... Better safe than sorry.
TEST_F(QuicVersionsTest, CheckVersionNumbersForTypos) {
- static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 7u,
+ static_assert(QUIC_ARRAYSIZE(kSupportedTransportVersions) == 8u,
"Supported versions out of sync");
EXPECT_EQ(QUIC_VERSION_35, 35);
EXPECT_EQ(QUIC_VERSION_39, 39);
@@ -524,6 +572,7 @@
EXPECT_EQ(QUIC_VERSION_44, 44);
EXPECT_EQ(QUIC_VERSION_45, 45);
EXPECT_EQ(QUIC_VERSION_46, 46);
+ EXPECT_EQ(QUIC_VERSION_47, 47);
EXPECT_EQ(QUIC_VERSION_99, 99);
}
} // namespace
diff --git a/quic/core/stateless_rejector_test.cc b/quic/core/stateless_rejector_test.cc
index 609c6a0..497fe54 100644
--- a/quic/core/stateless_rejector_test.cc
+++ b/quic/core/stateless_rejector_test.cc
@@ -52,8 +52,7 @@
// Test various combinations of QUIC version and flag state.
struct TestParams {
- ParsedQuicVersion version =
- ParsedQuicVersion{PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED};
+ ParsedQuicVersion version = UnsupportedQuicVersion();
FlagsMode flags;
};
diff --git a/quic/core/tls_client_handshaker.cc b/quic/core/tls_client_handshaker.cc
index dd52515..5edce8a 100644
--- a/quic/core/tls_client_handshaker.cc
+++ b/quic/core/tls_client_handshaker.cc
@@ -65,8 +65,9 @@
bool TlsClientHandshaker::CryptoConnect() {
CrypterPair crypters;
- CryptoUtils::CreateTlsInitialCrypters(Perspective::IS_CLIENT,
- session()->connection_id(), &crypters);
+ CryptoUtils::CreateTlsInitialCrypters(
+ Perspective::IS_CLIENT, session()->connection()->transport_version(),
+ session()->connection_id(), &crypters);
session()->connection()->SetEncrypter(ENCRYPTION_NONE,
std::move(crypters.encrypter));
session()->connection()->SetDecrypter(ENCRYPTION_NONE,
diff --git a/quic/core/tls_server_handshaker.cc b/quic/core/tls_server_handshaker.cc
index f7a3242..a96e406 100644
--- a/quic/core/tls_server_handshaker.cc
+++ b/quic/core/tls_server_handshaker.cc
@@ -62,8 +62,9 @@
proof_source_(proof_source),
crypto_negotiated_params_(new QuicCryptoNegotiatedParameters) {
CrypterPair crypters;
- CryptoUtils::CreateTlsInitialCrypters(Perspective::IS_SERVER,
- session->connection_id(), &crypters);
+ CryptoUtils::CreateTlsInitialCrypters(
+ Perspective::IS_SERVER, session->connection()->transport_version(),
+ session->connection_id(), &crypters);
session->connection()->SetEncrypter(ENCRYPTION_NONE,
std::move(crypters.encrypter));
session->connection()->SetDecrypter(ENCRYPTION_NONE,
diff --git a/quic/core/uber_quic_stream_id_manager.cc b/quic/core/uber_quic_stream_id_manager.cc
index 7531952..51ea994 100644
--- a/quic/core/uber_quic_stream_id_manager.cc
+++ b/quic/core/uber_quic_stream_id_manager.cc
@@ -1,3 +1,7 @@
+// Copyright (c) 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
#include "net/third_party/quiche/src/quic/core/uber_quic_stream_id_manager.h"
#include "net/third_party/quiche/src/quic/core/quic_session.h"
diff --git a/quic/core/uber_quic_stream_id_manager.h b/quic/core/uber_quic_stream_id_manager.h
index f07694a..bf5a588 100644
--- a/quic/core/uber_quic_stream_id_manager.h
+++ b/quic/core/uber_quic_stream_id_manager.h
@@ -1,3 +1,7 @@
+// Copyright (c) 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
#ifndef QUICHE_QUIC_CORE_UBER_QUIC_STREAM_ID_MANAGER_H_
#define QUICHE_QUIC_CORE_UBER_QUIC_STREAM_ID_MANAGER_H_
diff --git a/quic/core/uber_quic_stream_id_manager_test.cc b/quic/core/uber_quic_stream_id_manager_test.cc
index 258b157..a413a0b 100644
--- a/quic/core/uber_quic_stream_id_manager_test.cc
+++ b/quic/core/uber_quic_stream_id_manager_test.cc
@@ -1,3 +1,7 @@
+// Copyright (c) 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
#include "net/third_party/quiche/src/quic/core/uber_quic_stream_id_manager.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
diff --git a/quic/platform/api/quic_cert_utils.h b/quic/platform/api/quic_cert_utils.h
new file mode 100644
index 0000000..1c660b5
--- /dev/null
+++ b/quic/platform/api/quic_cert_utils.h
@@ -0,0 +1,23 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file._
+
+#ifndef QUICHE_QUIC_PLATFORM_API_QUIC_CERT_UTILS_H_
+#define QUICHE_QUIC_PLATFORM_API_QUIC_CERT_UTILS_H_
+
+#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+#include "net/quic/platform/impl/quic_cert_utils_impl.h"
+
+namespace quic {
+
+class QuicCertUtils {
+ public:
+ static bool ExtractSubjectNameFromDERCert(QuicStringPiece cert,
+ QuicStringPiece* subject_out) {
+ return QuicCertUtilsImpl::ExtractSubjectNameFromDERCert(cert, subject_out);
+ }
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_PLATFORM_API_QUIC_CERT_UTILS_H_
diff --git a/quic/platform/api/quic_client_stats.h b/quic/platform/api/quic_client_stats.h
index d1a3154..b780ba6 100644
--- a/quic/platform/api/quic_client_stats.h
+++ b/quic/platform/api/quic_client_stats.h
@@ -1,3 +1,7 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
#ifndef QUICHE_QUIC_PLATFORM_API_QUIC_CLIENT_STATS_H_
#define QUICHE_QUIC_PLATFORM_API_QUIC_CLIENT_STATS_H_
diff --git a/quic/platform/api/quic_epoll.h b/quic/platform/api/quic_epoll.h
new file mode 100644
index 0000000..c289ef4
--- /dev/null
+++ b/quic/platform/api/quic_epoll.h
@@ -0,0 +1,15 @@
+#ifndef QUICHE_QUIC_PLATFORM_API_QUIC_EPOLL_H_
+#define QUICHE_QUIC_PLATFORM_API_QUIC_EPOLL_H_
+
+#include "net/quic/platform/impl/quic_epoll_impl.h"
+
+namespace quic {
+
+using QuicEpollServer = QuicEpollServerImpl;
+using QuicEpollEvent = QuicEpollEventImpl;
+using QuicEpollAlarmBase = QuicEpollAlarmBaseImpl;
+using QuicEpollCallbackInterface = QuicEpollCallbackInterfaceImpl;
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_PLATFORM_API_QUIC_EPOLL_H_
diff --git a/quic/platform/api/quic_file_utils.cc b/quic/platform/api/quic_file_utils.cc
new file mode 100644
index 0000000..5492b83
--- /dev/null
+++ b/quic/platform/api/quic_file_utils.cc
@@ -0,0 +1,22 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/platform/api/quic_file_utils.h"
+
+#include "net/quic/platform/impl/quic_file_utils_impl.h"
+
+namespace quic {
+
+// Traverses the directory |dirname| and retuns all of the files
+// it contains.
+std::vector<QuicString> ReadFileContents(const QuicString& dirname) {
+ return ReadFileContentsImpl(dirname);
+}
+
+// Reads the contents of |filename| as a string into |contents|.
+void ReadFileContents(QuicStringPiece filename, QuicString* contents) {
+ ReadFileContentsImpl(filename, contents);
+}
+
+} // namespace quic
diff --git a/quic/platform/api/quic_file_utils.h b/quic/platform/api/quic_file_utils.h
index 463af0d..0f270ef 100644
--- a/quic/platform/api/quic_file_utils.h
+++ b/quic/platform/api/quic_file_utils.h
@@ -7,22 +7,20 @@
#include <vector>
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
-#include "net/quic/platform/impl/quic_file_utils_impl.h"
namespace quic {
// Traverses the directory |dirname| and retuns all of the files
// it contains.
-std::vector<QuicString> ReadFileContents(const QuicString& dirname) {
- return ReadFileContentsImpl(dirname);
-}
+QUIC_EXPORT_PRIVATE std::vector<QuicString> ReadFileContents(
+ const QuicString& dirname);
// Reads the contents of |filename| as a string into |contents|.
-void ReadFileContents(QuicStringPiece filename, QuicString* contents) {
- ReadFileContentsImpl(filename, contents);
-}
+QUIC_EXPORT_PRIVATE void ReadFileContents(QuicStringPiece filename,
+ QuicString* contents);
} // namespace quic
diff --git a/quic/platform/api/quic_goog_cc_sender.h b/quic/platform/api/quic_goog_cc_sender.h
deleted file mode 100644
index ba08cb3..0000000
--- a/quic/platform/api/quic_goog_cc_sender.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (c) 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef QUICHE_QUIC_PLATFORM_API_QUIC_GOOG_CC_SENDER_H_
-#define QUICHE_QUIC_PLATFORM_API_QUIC_GOOG_CC_SENDER_H_
-
-#include "net/third_party/quiche/src/quic/core/congestion_control/rtt_stats.h"
-#include "net/third_party/quiche/src/quic/core/congestion_control/send_algorithm_interface.h"
-#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
-#include "net/third_party/quiche/src/quic/core/quic_connection_stats.h"
-#include "net/third_party/quiche/src/quic/core/quic_types.h"
-#include "net/third_party/quiche/src/quic/core/quic_unacked_packet_map.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_clock.h"
-#include "net/quic/platform/impl/quic_goog_cc_sender_impl.h"
-
-namespace quic {
-
-// Interface for creating a GoogCC SendAlgorithmInterface.
-// TODO(b/122312335): Remove this file.
-SendAlgorithmInterface* CreateGoogCcSender(
- const QuicClock* clock,
- const RttStats* rtt_stats,
- const QuicUnackedPacketMap* unacked_packets,
- QuicRandom* random,
- QuicConnectionStats* stats,
- QuicPacketCount initial_congestion_window,
- QuicPacketCount max_congestion_window) {
- return CreateGoogCcSenderImpl(clock, rtt_stats, unacked_packets, random,
- stats, initial_congestion_window,
- max_congestion_window);
-}
-
-} // namespace quic
-
-#endif // QUICHE_QUIC_PLATFORM_API_QUIC_GOOG_CC_SENDER_H_
diff --git a/quic/platform/api/quic_hostname_utils.h b/quic/platform/api/quic_hostname_utils.h
index 61958c2..7f2b98a 100644
--- a/quic/platform/api/quic_hostname_utils.h
+++ b/quic/platform/api/quic_hostname_utils.h
@@ -5,7 +5,6 @@
#ifndef QUICHE_QUIC_PLATFORM_API_QUIC_HOSTNAME_UTILS_H_
#define QUICHE_QUIC_PLATFORM_API_QUIC_HOSTNAME_UTILS_H_
-#include "base/macros.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
diff --git a/quic/platform/api/quic_logging.h b/quic/platform/api/quic_logging.h
index d8dc682..ba48dc1 100644
--- a/quic/platform/api/quic_logging.h
+++ b/quic/platform/api/quic_logging.h
@@ -31,8 +31,9 @@
#define QUIC_PLOG(severity) QUIC_PLOG_IMPL(severity)
-#define QUIC_DLOG_INFO_IS_ON QUIC_DLOG_INFO_IS_ON_IMPL
-#define QUIC_LOG_INFO_IS_ON QUIC_LOG_INFO_IS_ON_IMPL
-#define QUIC_LOG_WARNING_IS_ON QUIC_LOG_WARNING_IS_ON_IMPL
+#define QUIC_DLOG_INFO_IS_ON() QUIC_DLOG_INFO_IS_ON_IMPL()
+#define QUIC_LOG_INFO_IS_ON() QUIC_LOG_INFO_IS_ON_IMPL()
+#define QUIC_LOG_WARNING_IS_ON() QUIC_LOG_WARNING_IS_ON_IMPL()
+#define QUIC_LOG_ERROR_IS_ON() QUIC_LOG_ERROR_IS_ON_IMPL()
#endif // QUICHE_QUIC_PLATFORM_API_QUIC_LOGGING_H_
diff --git a/quic/platform/api/quic_lru_cache.h b/quic/platform/api/quic_lru_cache.h
deleted file mode 100644
index 7789670..0000000
--- a/quic/platform/api/quic_lru_cache.h
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright (c) 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef QUICHE_QUIC_PLATFORM_API_QUIC_LRU_CACHE_H_
-#define QUICHE_QUIC_PLATFORM_API_QUIC_LRU_CACHE_H_
-
-#include <memory>
-
-#include "net/quic/platform/impl/quic_lru_cache_impl.h"
-
-namespace quic {
-
-// A LRU cache that maps from type Key to Value* in QUIC.
-// This cache CANNOT be shared by multiple threads (even with locks) because
-// Value* returned by Lookup() can be invalid if the entry is evicted by other
-// threads.
-template <class K, class V>
-class QuicLRUCacheOld {
- public:
- explicit QuicLRUCacheOld(int64_t total_units) : impl_(total_units) {}
- QuicLRUCacheOld(const QuicLRUCacheOld&) = delete;
- QuicLRUCacheOld& operator=(const QuicLRUCacheOld&) = delete;
-
- // Inserts one unit of |key|, |value| pair to the cache. Cache takes ownership
- // of inserted |value|.
- void Insert(const K& key, std::unique_ptr<V> value) {
- impl_.Insert(key, std::move(value));
- }
-
- // If cache contains an entry for |key|, return a pointer to it. This returned
- // value is guaranteed to be valid until Insert or Clear.
- // Else return nullptr.
- V* Lookup(const K& key) { return impl_.Lookup(key); }
-
- // Removes all entries from the cache. This method MUST be called before
- // destruction.
- void Clear() { impl_.Clear(); }
-
- // Returns maximum size of the cache.
- int64_t MaxSize() const { return impl_.MaxSize(); }
-
- // Returns current size of the cache.
- int64_t Size() const { return impl_.Size(); }
-
- private:
- QuicLRUCacheImpl<K, V> impl_;
-};
-
-} // namespace quic
-
-#endif // QUICHE_QUIC_PLATFORM_API_QUIC_LRU_CACHE_H_
diff --git a/quic/platform/api/quic_mem_slice_span.h b/quic/platform/api/quic_mem_slice_span.h
index 890556b..39436be 100644
--- a/quic/platform/api/quic_mem_slice_span.h
+++ b/quic/platform/api/quic_mem_slice_span.h
@@ -6,7 +6,6 @@
#define QUICHE_QUIC_PLATFORM_API_QUIC_MEM_SLICE_SPAN_H_
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
-#include "net/third_party/quiche/src/quic/platform/api/quic_mem_slice.h"
#include "net/quic/platform/impl/quic_mem_slice_span_impl.h"
namespace quic {
diff --git a/quic/platform/api/quic_mutex.h b/quic/platform/api/quic_mutex.h
index c57a937..162863a 100644
--- a/quic/platform/api/quic_mutex.h
+++ b/quic/platform/api/quic_mutex.h
@@ -5,7 +5,6 @@
#ifndef QUICHE_QUIC_PLATFORM_API_QUIC_MUTEX_H_
#define QUICHE_QUIC_PLATFORM_API_QUIC_MUTEX_H_
-#include "base/macros.h"
#include "net/quic/platform/impl/quic_mutex_impl.h"
namespace quic {
diff --git a/quic/platform/api/quic_server_stats.h b/quic/platform/api/quic_server_stats.h
index d3b49ee..5364844 100644
--- a/quic/platform/api/quic_server_stats.h
+++ b/quic/platform/api/quic_server_stats.h
@@ -1,3 +1,7 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
#ifndef QUICHE_QUIC_PLATFORM_API_QUIC_SERVER_STATS_H_
#define QUICHE_QUIC_PLATFORM_API_QUIC_SERVER_STATS_H_
diff --git a/quic/quartc/quartc_factory.cc b/quic/quartc/quartc_factory.cc
index bff445f..ee637e5 100644
--- a/quic/quartc/quartc_factory.cc
+++ b/quic/quartc/quartc_factory.cc
@@ -35,7 +35,10 @@
SetQuicReloadableFlag(quic_fix_spurious_ack_alarm, true);
// Enable version 45+ to enable SendMessage API.
+ // Enable version 47+ to enable 'quic bit' per draft 17.
SetQuicReloadableFlag(quic_enable_version_45, true);
+ SetQuicReloadableFlag(quic_enable_version_46, true);
+ SetQuicReloadableFlag(quic_enable_version_47, true);
// Fix for inconsistent reporting of crypto handshake.
SetQuicReloadableFlag(quic_fix_has_pending_crypto_data, true);
diff --git a/quic/quartc/quartc_interval_counter.h b/quic/quartc/quartc_interval_counter.h
index 0597f76..a9b827c 100644
--- a/quic/quartc/quartc_interval_counter.h
+++ b/quic/quartc/quartc_interval_counter.h
@@ -1,3 +1,7 @@
+// Copyright (c) 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
#ifndef QUICHE_QUIC_QUARTC_QUARTC_INTERVAL_COUNTER_H_
#define QUICHE_QUIC_QUARTC_QUARTC_INTERVAL_COUNTER_H_
diff --git a/quic/quartc/quartc_interval_counter_test.cc b/quic/quartc/quartc_interval_counter_test.cc
index c0edccb..9ba14b2 100644
--- a/quic/quartc/quartc_interval_counter_test.cc
+++ b/quic/quartc/quartc_interval_counter_test.cc
@@ -1,3 +1,7 @@
+// Copyright (c) 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
#include "net/third_party/quiche/src/quic/quartc/quartc_interval_counter.h"
#include "testing/gmock/include/gmock/gmock.h"
diff --git a/quic/quartc/quartc_session.cc b/quic/quartc/quartc_session.cc
index ebd7a7d..37d2cbe 100644
--- a/quic/quartc/quartc_session.cc
+++ b/quic/quartc/quartc_session.cc
@@ -4,6 +4,7 @@
#include "net/third_party/quiche/src/quic/quartc/quartc_session.h"
+#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/core/tls_client_handshaker.h"
#include "net/third_party/quiche/src/quic/core/tls_server_handshaker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
@@ -104,8 +105,9 @@
} // namespace
QuicConnectionId QuartcCryptoServerStreamHelper::GenerateConnectionIdForReject(
+ QuicTransportVersion version,
QuicConnectionId connection_id) const {
- return EmptyQuicConnectionId();
+ return QuicUtils::CreateZeroConnectionId(version);
}
bool QuartcCryptoServerStreamHelper::CanAcceptClientHello(
@@ -142,6 +144,8 @@
std::unique_ptr<ProofVerifier> proof_verifier(new InsecureProofVerifier);
quic_crypto_client_config_ = QuicMakeUnique<QuicCryptoClientConfig>(
std::move(proof_verifier), TlsClientHandshaker::CreateSslCtx());
+ quic_crypto_client_config_->set_pad_inchoate_hello(false);
+ quic_crypto_client_config_->set_pad_full_hello(false);
} else {
std::unique_ptr<ProofSource> proof_source(new DummyProofSource);
// Generate a random source address token secret. For long-running servers
@@ -154,6 +158,29 @@
QuicString(source_address_token_secret, kInputKeyingMaterialLength),
helper_->GetRandomGenerator(), std::move(proof_source),
KeyExchangeSource::Default(), TlsServerHandshaker::CreateSslCtx());
+
+ // Effectively disables the anti-amplification measures (we don't need
+ // them because we use ICE, and we need to disable them because we disable
+ // padding of crypto packets).
+ // This multiplier must be large enough so that the crypto handshake packet
+ // (approx. 300 bytes) multiplied by this multiplier is larger than a fully
+ // sized packet (currently 1200 bytes).
+ // 1500 is a bit extreme: if you can imagine sending a 1 byte packet, and
+ // your largest MTU would be below 1500 bytes, 1500*1 >=
+ // any_packet_that_you_can_imagine_sending.
+ // (again, we hardcode packet size to 1200, so we are not dealing with jumbo
+ // frames).
+ quic_crypto_server_config_->set_chlo_multiplier(1500);
+
+ // We are sending small client hello, we must not validate its size.
+ quic_crypto_server_config_->set_validate_chlo_size(false);
+
+ // We run QUIC over ICE, and ICE is verifying remote side with STUN pings.
+ // We disable source address token validation in order to allow for 0-rtt
+ // setup (plus source ip addresses are changing even during the connection
+ // when ICE is used).
+ quic_crypto_server_config_->set_validate_source_address_token(false);
+
// Provide server with serialized config string to prove ownership.
QuicCryptoServerConfig::ConfigOptions options;
// The |message| is used to handle the return value of AddDefaultConfig
@@ -161,6 +188,8 @@
std::unique_ptr<CryptoHandshakeMessage> message(
quic_crypto_server_config_->AddDefaultConfig(
helper_->GetRandomGenerator(), helper_->GetClock(), options));
+ quic_crypto_server_config_->set_pad_rej(false);
+ quic_crypto_server_config_->set_pad_shlo(false);
}
}
@@ -257,12 +286,25 @@
void QuartcSession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) {
QuicSession::OnCryptoHandshakeEvent(event);
- if (event == HANDSHAKE_CONFIRMED) {
- DCHECK(IsEncryptionEstablished());
- DCHECK(IsCryptoHandshakeConfirmed());
+ switch (event) {
+ case ENCRYPTION_FIRST_ESTABLISHED:
+ case ENCRYPTION_REESTABLISHED:
+ // 1-rtt setup triggers 'ENCRYPTION_REESTABLISHED' (after REJ, when the
+ // CHLO is sent).
+ DCHECK(IsEncryptionEstablished());
+ DCHECK(session_delegate_);
+ session_delegate_->OnConnectionWritable();
+ break;
+ case HANDSHAKE_CONFIRMED:
+ // On the server, handshake confirmed is the first time when you can start
+ // writing packets.
+ DCHECK(IsEncryptionEstablished());
+ DCHECK(IsCryptoHandshakeConfirmed());
- DCHECK(session_delegate_);
- session_delegate_->OnCryptoHandshakeComplete();
+ DCHECK(session_delegate_);
+ session_delegate_->OnConnectionWritable();
+ session_delegate_->OnCryptoHandshakeComplete();
+ break;
}
}
diff --git a/quic/quartc/quartc_session.h b/quic/quartc/quartc_session.h
index fbbf111..411c94c 100644
--- a/quic/quartc/quartc_session.h
+++ b/quic/quartc/quartc_session.h
@@ -24,6 +24,7 @@
class QuartcCryptoServerStreamHelper : public QuicCryptoServerStream::Helper {
public:
QuicConnectionId GenerateConnectionIdForReject(
+ QuicTransportVersion version,
QuicConnectionId connection_id) const override;
bool CanAcceptClientHello(const CryptoHandshakeMessage& message,
@@ -126,9 +127,18 @@
public:
virtual ~Delegate() {}
- // Called when the crypto handshake is complete.
+ // Called when the crypto handshake is complete. Crypto handshake on the
+ // client is only completed _after_ SHLO is received, but we can actually
+ // start sending media data right after CHLO is sent.
virtual void OnCryptoHandshakeComplete() = 0;
+ // Connection can be writable even before crypto handshake is complete.
+ // In particular, on the client, we can start sending data after sending
+ // full CHLO, without waiting for SHLO. This reduces a send delay by 1-rtt.
+ //
+ // This may be called multiple times.
+ virtual void OnConnectionWritable() = 0;
+
// Called when a new stream is received from the remote endpoint.
virtual void OnIncomingStream(QuartcStream* stream) = 0;
diff --git a/quic/quartc/quartc_session_test.cc b/quic/quartc/quartc_session_test.cc
index f3e4978..78efa9e 100644
--- a/quic/quartc/quartc_session_test.cc
+++ b/quic/quartc/quartc_session_test.cc
@@ -6,11 +6,11 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "net/third_party/quiche/src/quic/core/proto/crypto_server_config.proto.h"
#include "net/third_party/quiche/src/quic/core/quic_simple_buffer_allocator.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/tls_client_handshaker.h"
#include "net/third_party/quiche/src/quic/core/tls_server_handshaker.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_clock.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
@@ -31,18 +31,30 @@
class FakeQuartcSessionDelegate : public QuartcSession::Delegate {
public:
- explicit FakeQuartcSessionDelegate(QuartcStream::Delegate* stream_delegate)
- : stream_delegate_(stream_delegate) {}
+ explicit FakeQuartcSessionDelegate(QuartcStream::Delegate* stream_delegate,
+ const QuicClock* clock)
+ : stream_delegate_(stream_delegate), clock_(clock) {}
+
+ void OnConnectionWritable() override {
+ LOG(INFO) << "Connection writable!";
+ if (!writable_time_.IsInitialized()) {
+ writable_time_ = clock_->Now();
+ }
+ }
+
// Called when peers have established forward-secure encryption
void OnCryptoHandshakeComplete() override {
LOG(INFO) << "Crypto handshake complete!";
+ crypto_handshake_time_ = clock_->Now();
}
+
// Called when connection closes locally, or remotely by peer.
void OnConnectionClosed(QuicErrorCode error_code,
const QuicString& error_details,
ConnectionCloseSource source) override {
connected_ = false;
}
+
// Called when an incoming QUIC stream is created.
void OnIncomingStream(QuartcStream* quartc_stream) override {
last_incoming_stream_ = quartc_stream;
@@ -65,12 +77,17 @@
}
bool connected() { return connected_; }
+ QuicTime writable_time() const { return writable_time_; }
+ QuicTime crypto_handshake_time() const { return crypto_handshake_time_; }
private:
QuartcStream* last_incoming_stream_;
std::vector<QuicString> incoming_messages_;
bool connected_ = true;
QuartcStream::Delegate* stream_delegate_;
+ QuicTime writable_time_ = QuicTime::Zero();
+ QuicTime crypto_handshake_time_ = QuicTime::Zero();
+ const QuicClock* clock_;
};
class FakeQuartcStreamDelegate : public QuartcStream::Delegate {
@@ -128,11 +145,11 @@
client_stream_delegate_ = QuicMakeUnique<FakeQuartcStreamDelegate>();
client_session_delegate_ = QuicMakeUnique<FakeQuartcSessionDelegate>(
- client_stream_delegate_.get());
+ client_stream_delegate_.get(), simulator_.GetClock());
server_stream_delegate_ = QuicMakeUnique<FakeQuartcStreamDelegate>();
server_session_delegate_ = QuicMakeUnique<FakeQuartcSessionDelegate>(
- server_stream_delegate_.get());
+ server_stream_delegate_.get(), simulator_.GetClock());
QuartcFactoryConfig factory_config;
factory_config.alarm_factory = simulator_.GetAlarmFactory();
@@ -358,6 +375,29 @@
TestSendLongMessage();
}
+TEST_F(QuartcSessionTest, TestCryptoHandshakeCanWriteTriggers) {
+ CreateClientAndServerSessions(QuartcSessionConfig());
+
+ StartHandshake();
+
+ RunTasks();
+
+ ASSERT_TRUE(client_session_delegate_->writable_time().IsInitialized());
+ ASSERT_TRUE(
+ client_session_delegate_->crypto_handshake_time().IsInitialized());
+ // On client, we are writable 1-rtt before crypto handshake is complete.
+ ASSERT_LT(client_session_delegate_->writable_time(),
+ client_session_delegate_->crypto_handshake_time());
+
+ ASSERT_TRUE(server_session_delegate_->writable_time().IsInitialized());
+ ASSERT_TRUE(
+ server_session_delegate_->crypto_handshake_time().IsInitialized());
+ // On server, the writable time and crypto handshake are the same. (when SHLO
+ // is sent).
+ ASSERT_EQ(server_session_delegate_->writable_time(),
+ server_session_delegate_->crypto_handshake_time());
+}
+
TEST_F(QuartcSessionTest, PreSharedKeyHandshake) {
CreateClientAndServerSessions(QuartcSessionConfig());
client_peer_->SetPreSharedKey("foo");
diff --git a/quic/quartc/quartc_stream_test.cc b/quic/quartc/quartc_stream_test.cc
index f560185..075aca1 100644
--- a/quic/quartc/quartc_stream_test.cc
+++ b/quic/quartc/quartc_stream_test.cc
@@ -24,6 +24,7 @@
#include "net/third_party/quiche/src/quic/core/quic_simple_buffer_allocator.h"
#include "net/third_party/quiche/src/quic/core/quic_time.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/core/quic_write_blocked_list.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_clock.h"
@@ -225,9 +226,10 @@
alarm_factory_ = QuicMakeUnique<test::MockAlarmFactory>();
connection_ = QuicMakeUnique<QuicConnection>(
- EmptyQuicConnectionId(), QuicSocketAddress(ip, 0),
- this /*QuicConnectionHelperInterface*/, alarm_factory_.get(),
- new DummyPacketWriter(), owns_writer, perspective,
+ QuicUtils::CreateZeroConnectionId(
+ CurrentSupportedVersions()[0].transport_version),
+ QuicSocketAddress(ip, 0), this /*QuicConnectionHelperInterface*/,
+ alarm_factory_.get(), new DummyPacketWriter(), owns_writer, perspective,
ParsedVersionOfIndex(CurrentSupportedVersions(), 0));
clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1));
session_ = QuicMakeUnique<MockQuicSession>(connection_.get(), QuicConfig(),
@@ -589,16 +591,16 @@
EXPECT_EQ("Foo bar", write_buffer_);
stream_->OnStreamFrameLost(0, 4, false);
- EXPECT_EQ(stream_->BytesPendingRetransmission(), 4);
- EXPECT_EQ(mock_stream_delegate_->last_bytes_pending_retransmission(), 4);
+ EXPECT_EQ(stream_->BytesPendingRetransmission(), 4u);
+ EXPECT_EQ(mock_stream_delegate_->last_bytes_pending_retransmission(), 4u);
stream_->OnStreamFrameLost(4, 3, false);
- EXPECT_EQ(stream_->BytesPendingRetransmission(), 7);
- EXPECT_EQ(mock_stream_delegate_->last_bytes_pending_retransmission(), 7);
+ EXPECT_EQ(stream_->BytesPendingRetransmission(), 7u);
+ EXPECT_EQ(mock_stream_delegate_->last_bytes_pending_retransmission(), 7u);
stream_->OnCanWrite();
- EXPECT_EQ(stream_->BytesPendingRetransmission(), 0);
- EXPECT_EQ(mock_stream_delegate_->last_bytes_pending_retransmission(), 0);
+ EXPECT_EQ(stream_->BytesPendingRetransmission(), 0u);
+ EXPECT_EQ(mock_stream_delegate_->last_bytes_pending_retransmission(), 0u);
EXPECT_EQ("Foo barFoo bar", write_buffer_);
EXPECT_EQ(stream_->stream_error(), QUIC_STREAM_NO_ERROR);
@@ -615,16 +617,16 @@
EXPECT_EQ("Foo bar", write_buffer_);
stream_->OnStreamFrameLost(0, 4, false);
- EXPECT_EQ(stream_->BytesPendingRetransmission(), 0);
- EXPECT_EQ(mock_stream_delegate_->last_bytes_pending_retransmission(), 0);
+ EXPECT_EQ(stream_->BytesPendingRetransmission(), 0u);
+ EXPECT_EQ(mock_stream_delegate_->last_bytes_pending_retransmission(), 0u);
stream_->OnStreamFrameLost(4, 3, false);
- EXPECT_EQ(stream_->BytesPendingRetransmission(), 0);
- EXPECT_EQ(mock_stream_delegate_->last_bytes_pending_retransmission(), 0);
+ EXPECT_EQ(stream_->BytesPendingRetransmission(), 0u);
+ EXPECT_EQ(mock_stream_delegate_->last_bytes_pending_retransmission(), 0u);
stream_->OnCanWrite();
- EXPECT_EQ(stream_->BytesPendingRetransmission(), 0);
- EXPECT_EQ(mock_stream_delegate_->last_bytes_pending_retransmission(), 0);
+ EXPECT_EQ(stream_->BytesPendingRetransmission(), 0u);
+ EXPECT_EQ(mock_stream_delegate_->last_bytes_pending_retransmission(), 0u);
EXPECT_EQ("Foo bar", write_buffer_);
EXPECT_EQ(stream_->stream_error(), QUIC_STREAM_CANCELLED);
diff --git a/quic/test_tools/crypto_test_utils.cc b/quic/test_tools/crypto_test_utils.cc
index 1f14306..fd270c3 100644
--- a/quic/test_tools/crypto_test_utils.cc
+++ b/quic/test_tools/crypto_test_utils.cc
@@ -407,7 +407,7 @@
testing::_, testing::_))
.Times(testing::AnyNumber());
EXPECT_CALL(*server_session.helper(),
- GenerateConnectionIdForReject(testing::_))
+ GenerateConnectionIdForReject(testing::_, testing::_))
.Times(testing::AnyNumber());
EXPECT_CALL(*server_conn, OnCanWrite()).Times(testing::AnyNumber());
EXPECT_CALL(*client_conn, OnCanWrite()).Times(testing::AnyNumber());
@@ -783,8 +783,6 @@
EXPECT_TRUE(server->ExportKeyingMaterial(kSampleLabel, kSampleContext,
kSampleOutputLength,
&server_key_extraction));
- EXPECT_TRUE(client->ExportTokenBindingKeyingMaterial(&client_tb_ekm));
- EXPECT_TRUE(server->ExportTokenBindingKeyingMaterial(&server_tb_ekm));
CompareCharArraysWithHexError("client write key", client_encrypter_key.data(),
client_encrypter_key.length(),
@@ -1002,11 +1000,8 @@
QuicStringPiece orbit;
CHECK(msg->GetStringPiece(kORBT, &orbit));
QuicString nonce;
- CryptoUtils::GenerateNonce(
- clock->WallNow(), QuicRandom::GetInstance(),
- QuicStringPiece(reinterpret_cast<const char*>(orbit.data()),
- sizeof(static_cast<int64>(orbit.size()))),
- &nonce);
+ CryptoUtils::GenerateNonce(clock->WallNow(), QuicRandom::GetInstance(), orbit,
+ &nonce);
return ("#" + QuicTextUtils::HexEncode(nonce));
}
diff --git a/quic/test_tools/crypto_test_utils_test.cc b/quic/test_tools/crypto_test_utils_test.cc
index c6be73a..601103c 100644
--- a/quic/test_tools/crypto_test_utils_test.cc
+++ b/quic/test_tools/crypto_test_utils_test.cc
@@ -135,11 +135,8 @@
QuicStringPiece orbit;
ASSERT_TRUE(msg->GetStringPiece(kORBT, &orbit));
QuicString nonce;
- CryptoUtils::GenerateNonce(
- clock.WallNow(), QuicRandom::GetInstance(),
- QuicStringPiece(reinterpret_cast<const char*>(orbit.data()),
- sizeof(static_cast<int64>(orbit.size()))),
- &nonce);
+ CryptoUtils::GenerateNonce(clock.WallNow(), QuicRandom::GetInstance(), orbit,
+ &nonce);
QuicString nonce_hex = "#" + QuicTextUtils::HexEncode(nonce);
char public_value[32];
diff --git a/quic/test_tools/limited_mtu_test_writer.cc b/quic/test_tools/limited_mtu_test_writer.cc
index cd9be17..bc71c7c 100644
--- a/quic/test_tools/limited_mtu_test_writer.cc
+++ b/quic/test_tools/limited_mtu_test_writer.cc
@@ -9,7 +9,7 @@
LimitedMtuTestWriter::LimitedMtuTestWriter(QuicByteCount mtu) : mtu_(mtu) {}
-LimitedMtuTestWriter::~LimitedMtuTestWriter() {}
+LimitedMtuTestWriter::~LimitedMtuTestWriter() = default;
WriteResult LimitedMtuTestWriter::WritePacket(
const char* buffer,
diff --git a/quic/test_tools/mock_quic_session_visitor.cc b/quic/test_tools/mock_quic_session_visitor.cc
index e8d2b66..fea8414 100644
--- a/quic/test_tools/mock_quic_session_visitor.cc
+++ b/quic/test_tools/mock_quic_session_visitor.cc
@@ -7,13 +7,13 @@
namespace quic {
namespace test {
-MockQuicSessionVisitor::MockQuicSessionVisitor() {}
+MockQuicSessionVisitor::MockQuicSessionVisitor() = default;
-MockQuicSessionVisitor::~MockQuicSessionVisitor() {}
+MockQuicSessionVisitor::~MockQuicSessionVisitor() = default;
-MockQuicCryptoServerStreamHelper::MockQuicCryptoServerStreamHelper() {}
+MockQuicCryptoServerStreamHelper::MockQuicCryptoServerStreamHelper() = default;
-MockQuicCryptoServerStreamHelper::~MockQuicCryptoServerStreamHelper() {}
+MockQuicCryptoServerStreamHelper::~MockQuicCryptoServerStreamHelper() = default;
} // namespace test
} // namespace quic
diff --git a/quic/test_tools/mock_quic_session_visitor.h b/quic/test_tools/mock_quic_session_visitor.h
index a75a852..fb01da6 100644
--- a/quic/test_tools/mock_quic_session_visitor.h
+++ b/quic/test_tools/mock_quic_session_visitor.h
@@ -27,6 +27,7 @@
MOCK_METHOD1(OnWriteBlocked,
void(QuicBlockedWriterInterface* blocked_writer));
MOCK_METHOD1(OnRstStreamReceived, void(const QuicRstStreamFrame& frame));
+ MOCK_METHOD1(OnStopSendingReceived, void(const QuicStopSendingFrame& frame));
MOCK_METHOD1(OnConnectionAddedToTimeWaitList,
void(QuicConnectionId connection_id));
};
@@ -39,8 +40,9 @@
MockQuicCryptoServerStreamHelper& operator=(
const MockQuicCryptoServerStreamHelper&) = delete;
~MockQuicCryptoServerStreamHelper() override;
- MOCK_CONST_METHOD1(GenerateConnectionIdForReject,
- QuicConnectionId(QuicConnectionId connection_id));
+ MOCK_CONST_METHOD2(GenerateConnectionIdForReject,
+ QuicConnectionId(QuicTransportVersion version,
+ QuicConnectionId connection_id));
MOCK_CONST_METHOD5(CanAcceptClientHello,
bool(const CryptoHandshakeMessage& message,
const QuicSocketAddress& client_address,
diff --git a/quic/test_tools/mock_quic_time_wait_list_manager.cc b/quic/test_tools/mock_quic_time_wait_list_manager.cc
index bf3d075..ec63558 100644
--- a/quic/test_tools/mock_quic_time_wait_list_manager.cc
+++ b/quic/test_tools/mock_quic_time_wait_list_manager.cc
@@ -26,7 +26,7 @@
QuicTimeWaitListManager_AddConnectionIdToTimeWait));
}
-MockTimeWaitListManager::~MockTimeWaitListManager() {}
+MockTimeWaitListManager::~MockTimeWaitListManager() = default;
} // namespace test
} // namespace quic
diff --git a/quic/test_tools/mock_random.cc b/quic/test_tools/mock_random.cc
index 683e504..a01a5a7 100644
--- a/quic/test_tools/mock_random.cc
+++ b/quic/test_tools/mock_random.cc
@@ -4,6 +4,8 @@
#include "net/third_party/quiche/src/quic/test_tools/mock_random.h"
+#include <string.h>
+
namespace quic {
namespace test {
diff --git a/quic/test_tools/packet_dropping_test_writer.cc b/quic/test_tools/packet_dropping_test_writer.cc
index 51d8fed..d296367 100644
--- a/quic/test_tools/packet_dropping_test_writer.cc
+++ b/quic/test_tools/packet_dropping_test_writer.cc
@@ -15,7 +15,7 @@
// An alarm that is scheduled if a blocked socket is simulated to indicate
// it's writable again.
-class WriteUnblockedAlarm : public quic::QuicAlarm::Delegate {
+class WriteUnblockedAlarm : public QuicAlarm::Delegate {
public:
explicit WriteUnblockedAlarm(PacketDroppingTestWriter* writer)
: writer_(writer) {}
@@ -31,7 +31,7 @@
// An alarm that is scheduled every time a new packet is to be written at a
// later point.
-class DelayAlarm : public quic::QuicAlarm::Delegate {
+class DelayAlarm : public QuicAlarm::Delegate {
public:
explicit DelayAlarm(PacketDroppingTestWriter* writer) : writer_(writer) {}
@@ -58,12 +58,12 @@
fake_bandwidth_(QuicBandwidth::Zero()),
buffer_size_(0),
num_consecutive_packet_lost_(0) {
- uint32_t seed = RandomBase::WeakSeed32();
+ uint64_t seed = QuicRandom::GetInstance()->RandUint64();
QUIC_LOG(INFO) << "Seeding packet loss with " << seed;
simple_random_.set_seed(seed);
}
-PacketDroppingTestWriter::~PacketDroppingTestWriter() {}
+PacketDroppingTestWriter::~PacketDroppingTestWriter() = default;
void PacketDroppingTestWriter::Initialize(
QuicConnectionHelperInterface* helper,
diff --git a/quic/test_tools/packet_dropping_test_writer.h b/quic/test_tools/packet_dropping_test_writer.h
index ae1df42..404be81 100644
--- a/quic/test_tools/packet_dropping_test_writer.h
+++ b/quic/test_tools/packet_dropping_test_writer.h
@@ -16,7 +16,6 @@
#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
namespace quic {
-
namespace test {
// Simulates a connection that drops packets a configured percentage of the time
@@ -143,17 +142,17 @@
~DelayedWrite();
QuicString buffer;
- const QuicIpAddress self_address;
- const QuicSocketAddress peer_address;
+ QuicIpAddress self_address;
+ QuicSocketAddress peer_address;
std::unique_ptr<PerPacketOptions> options;
QuicTime send_time;
};
typedef std::list<DelayedWrite> DelayedPacketList;
- const quic::QuicClock* clock_;
- std::unique_ptr<quic::QuicAlarm> write_unblocked_alarm_;
- std::unique_ptr<quic::QuicAlarm> delay_alarm_;
+ const QuicClock* clock_;
+ std::unique_ptr<QuicAlarm> write_unblocked_alarm_;
+ std::unique_ptr<QuicAlarm> delay_alarm_;
std::unique_ptr<Delegate> on_can_write_;
SimpleRandom simple_random_;
// Stored packets delayed by fake packet delay or bandwidth restrictions.
diff --git a/quic/test_tools/quic_client_peer.h b/quic/test_tools/quic_client_peer.h
index 934495a..66987e4 100644
--- a/quic/test_tools/quic_client_peer.h
+++ b/quic/test_tools/quic_client_peer.h
@@ -10,7 +10,6 @@
namespace quic {
class QuicClient;
-class QuicCryptoClientConfig;
class QuicPacketWriter;
namespace test {
diff --git a/quic/test_tools/quic_connection_peer.cc b/quic/test_tools/quic_connection_peer.cc
index dde870b..e813c1e 100644
--- a/quic/test_tools/quic_connection_peer.cc
+++ b/quic/test_tools/quic_connection_peer.cc
@@ -275,9 +275,8 @@
}
// static
-bool QuicConnectionPeer::HasRetransmittableFrames(
- QuicConnection* connection,
- QuicPacketNumber packet_number) {
+bool QuicConnectionPeer::HasRetransmittableFrames(QuicConnection* connection,
+ uint64_t packet_number) {
return QuicSentPacketManagerPeer::HasRetransmittableFrames(
GetSentPacketManager(connection), packet_number);
}
diff --git a/quic/test_tools/quic_connection_peer.h b/quic/test_tools/quic_connection_peer.h
index 58bdec9..d58d1d7 100644
--- a/quic/test_tools/quic_connection_peer.h
+++ b/quic/test_tools/quic_connection_peer.h
@@ -123,7 +123,7 @@
static void SetAckDecimationDelay(QuicConnection* connection,
float ack_decimation_delay);
static bool HasRetransmittableFrames(QuicConnection* connection,
- QuicPacketNumber packet_number);
+ uint64_t packet_number);
static bool GetNoStopWaitingFrames(QuicConnection* connection);
static void SetNoStopWaitingFrames(QuicConnection* connection,
bool no_stop_waiting_frames);
diff --git a/quic/test_tools/quic_framer_peer.cc b/quic/test_tools/quic_framer_peer.cc
index 6202669..20cbc49 100644
--- a/quic/test_tools/quic_framer_peer.cc
+++ b/quic/test_tools/quic_framer_peer.cc
@@ -12,11 +12,11 @@
namespace test {
// static
-QuicPacketNumber QuicFramerPeer::CalculatePacketNumberFromWire(
+uint64_t QuicFramerPeer::CalculatePacketNumberFromWire(
QuicFramer* framer,
QuicPacketNumberLength packet_number_length,
QuicPacketNumber last_packet_number,
- QuicPacketNumber packet_number) {
+ uint64_t packet_number) {
return framer->CalculatePacketNumberFromWire(
packet_number_length, last_packet_number, packet_number);
}
@@ -338,5 +338,12 @@
packet_number_length);
}
+// static
+void QuicFramerPeer::SetFirstSendingPacketNumber(QuicFramer* framer,
+ uint64_t packet_number) {
+ *const_cast<QuicPacketNumber*>(&framer->first_sending_packet_number_) =
+ QuicPacketNumber(packet_number);
+}
+
} // namespace test
} // namespace quic
diff --git a/quic/test_tools/quic_framer_peer.h b/quic/test_tools/quic_framer_peer.h
index 57a05aa..1fa7351 100644
--- a/quic/test_tools/quic_framer_peer.h
+++ b/quic/test_tools/quic_framer_peer.h
@@ -18,11 +18,11 @@
public:
QuicFramerPeer() = delete;
- static QuicPacketNumber CalculatePacketNumberFromWire(
+ static uint64_t CalculatePacketNumberFromWire(
QuicFramer* framer,
QuicPacketNumberLength packet_number_length,
QuicPacketNumber last_packet_number,
- QuicPacketNumber packet_number);
+ uint64_t packet_number);
static void SetLastSerializedConnectionId(QuicFramer* framer,
QuicConnectionId connection_id);
static void SetLargestPacketNumber(QuicFramer* framer,
@@ -161,6 +161,8 @@
const QuicFrame& frame,
bool last_frame_in_packet,
QuicPacketNumberLength packet_number_length);
+ static void SetFirstSendingPacketNumber(QuicFramer* framer,
+ uint64_t packet_number);
};
} // namespace test
diff --git a/quic/test_tools/quic_packet_creator_peer.cc b/quic/test_tools/quic_packet_creator_peer.cc
index 5168688..efcda92 100644
--- a/quic/test_tools/quic_packet_creator_peer.cc
+++ b/quic/test_tools/quic_packet_creator_peer.cc
@@ -44,8 +44,14 @@
}
void QuicPacketCreatorPeer::SetPacketNumber(QuicPacketCreator* creator,
- QuicPacketNumber s) {
- creator->packet_.packet_number = s;
+ uint64_t s) {
+ DCHECK_NE(0u, s);
+ creator->packet_.packet_number = QuicPacketNumber(s);
+}
+
+// static
+void QuicPacketCreatorPeer::ClearPacketNumber(QuicPacketCreator* creator) {
+ creator->packet_.packet_number.Clear();
}
// static
diff --git a/quic/test_tools/quic_packet_creator_peer.h b/quic/test_tools/quic_packet_creator_peer.h
index add0712..94c461a 100644
--- a/quic/test_tools/quic_packet_creator_peer.h
+++ b/quic/test_tools/quic_packet_creator_peer.h
@@ -27,7 +27,8 @@
QuicPacketNumberLength packet_number_length);
static QuicPacketNumberLength GetPacketNumberLength(
QuicPacketCreator* creator);
- static void SetPacketNumber(QuicPacketCreator* creator, QuicPacketNumber s);
+ static void SetPacketNumber(QuicPacketCreator* creator, uint64_t s);
+ static void ClearPacketNumber(QuicPacketCreator* creator);
static void FillPacketHeader(QuicPacketCreator* creator,
QuicPacketHeader* header);
static void CreateStreamFrame(QuicPacketCreator* creator,
diff --git a/quic/test_tools/quic_sent_packet_manager_peer.cc b/quic/test_tools/quic_sent_packet_manager_peer.cc
index 7699520..469fa40 100644
--- a/quic/test_tools/quic_sent_packet_manager_peer.cc
+++ b/quic/test_tools/quic_sent_packet_manager_peer.cc
@@ -85,18 +85,19 @@
// static
bool QuicSentPacketManagerPeer::IsRetransmission(
QuicSentPacketManager* sent_packet_manager,
- QuicPacketNumber packet_number) {
+ uint64_t packet_number) {
DCHECK(HasRetransmittableFrames(sent_packet_manager, packet_number));
if (!HasRetransmittableFrames(sent_packet_manager, packet_number)) {
return false;
}
if (sent_packet_manager->session_decides_what_to_write()) {
return sent_packet_manager->unacked_packets_
- .GetTransmissionInfo(packet_number)
+ .GetTransmissionInfo(QuicPacketNumber(packet_number))
.transmission_type != NOT_RETRANSMISSION;
}
for (auto transmission_info : sent_packet_manager->unacked_packets_) {
- if (transmission_info.retransmission == packet_number) {
+ if (transmission_info.retransmission.IsInitialized() &&
+ transmission_info.retransmission == QuicPacketNumber(packet_number)) {
return true;
}
}
@@ -106,9 +107,10 @@
// static
void QuicSentPacketManagerPeer::MarkForRetransmission(
QuicSentPacketManager* sent_packet_manager,
- QuicPacketNumber packet_number,
+ uint64_t packet_number,
TransmissionType transmission_type) {
- sent_packet_manager->MarkForRetransmission(packet_number, transmission_type);
+ sent_packet_manager->MarkForRetransmission(QuicPacketNumber(packet_number),
+ transmission_type);
}
// static
@@ -198,16 +200,17 @@
// static
bool QuicSentPacketManagerPeer::IsUnacked(
QuicSentPacketManager* sent_packet_manager,
- QuicPacketNumber packet_number) {
- return sent_packet_manager->unacked_packets_.IsUnacked(packet_number);
+ uint64_t packet_number) {
+ return sent_packet_manager->unacked_packets_.IsUnacked(
+ QuicPacketNumber(packet_number));
}
// static
bool QuicSentPacketManagerPeer::HasRetransmittableFrames(
QuicSentPacketManager* sent_packet_manager,
- QuicPacketNumber packet_number) {
+ uint64_t packet_number) {
return sent_packet_manager->unacked_packets_.HasRetransmittableFrames(
- packet_number);
+ QuicPacketNumber(packet_number));
}
// static
diff --git a/quic/test_tools/quic_sent_packet_manager_peer.h b/quic/test_tools/quic_sent_packet_manager_peer.h
index 9f9f6a1..b8ec1d3 100644
--- a/quic/test_tools/quic_sent_packet_manager_peer.h
+++ b/quic/test_tools/quic_sent_packet_manager_peer.h
@@ -52,10 +52,10 @@
// Returns true if |packet_number| is a retransmission of a packet.
static bool IsRetransmission(QuicSentPacketManager* sent_packet_manager,
- QuicPacketNumber packet_number);
+ uint64_t packet_number);
static void MarkForRetransmission(QuicSentPacketManager* sent_packet_manager,
- QuicPacketNumber packet_number,
+ uint64_t packet_number,
TransmissionType transmission_type);
static QuicTime::Delta GetRetransmissionDelay(
@@ -93,11 +93,11 @@
static bool UsingPacing(const QuicSentPacketManager* sent_packet_manager);
static bool IsUnacked(QuicSentPacketManager* sent_packet_manager,
- QuicPacketNumber packet_number);
+ uint64_t packet_number);
static bool HasRetransmittableFrames(
QuicSentPacketManager* sent_packet_manager,
- QuicPacketNumber packet_number);
+ uint64_t packet_number);
static QuicUnackedPacketMap* GetUnackedPacketMap(
QuicSentPacketManager* sent_packet_manager);
diff --git a/quic/test_tools/quic_session_peer.cc b/quic/test_tools/quic_session_peer.cc
index 6bacca9..37e5013 100644
--- a/quic/test_tools/quic_session_peer.cc
+++ b/quic/test_tools/quic_session_peer.cc
@@ -184,5 +184,14 @@
return &session->v99_streamid_manager_.unidirectional_stream_id_manager_;
}
+// static
+void QuicSessionPeer::SendRstStreamInner(QuicSession* session,
+ QuicStreamId id,
+ QuicRstStreamErrorCode error,
+ QuicStreamOffset bytes_written,
+ bool close_write_side_only) {
+ session->SendRstStreamInner(id, error, bytes_written, close_write_side_only);
+}
+
} // namespace test
} // namespace quic
diff --git a/quic/test_tools/quic_session_peer.h b/quic/test_tools/quic_session_peer.h
index 917d203..8c2e72c 100644
--- a/quic/test_tools/quic_session_peer.h
+++ b/quic/test_tools/quic_session_peer.h
@@ -67,6 +67,11 @@
QuicSession* session);
static QuicStreamIdManager* v99_unidirectional_stream_id_manager(
QuicSession* session);
+ static void SendRstStreamInner(QuicSession* session,
+ QuicStreamId id,
+ QuicRstStreamErrorCode error,
+ QuicStreamOffset bytes_written,
+ bool close_write_side_only);
};
} // namespace test
diff --git a/quic/test_tools/quic_stream_id_manager_peer.cc b/quic/test_tools/quic_stream_id_manager_peer.cc
index 8bdfd16..705ee27 100644
--- a/quic/test_tools/quic_stream_id_manager_peer.cc
+++ b/quic/test_tools/quic_stream_id_manager_peer.cc
@@ -1,3 +1,6 @@
+// Copyright (c) 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
#include "net/third_party/quiche/src/quic/test_tools/quic_stream_id_manager_peer.h"
#include "net/third_party/quiche/src/quic/core/quic_stream_id_manager.h"
diff --git a/quic/test_tools/quic_stream_id_manager_peer.h b/quic/test_tools/quic_stream_id_manager_peer.h
index 7b42888..2ec07b1 100644
--- a/quic/test_tools/quic_stream_id_manager_peer.h
+++ b/quic/test_tools/quic_stream_id_manager_peer.h
@@ -1,7 +1,10 @@
+// Copyright (c) 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
#ifndef QUICHE_QUIC_TEST_TOOLS_QUIC_STREAM_ID_MANAGER_PEER_H_
#define QUICHE_QUIC_TEST_TOOLS_QUIC_STREAM_ID_MANAGER_PEER_H_
-#include "base/macros.h"
+#include <stddef.h>
namespace quic {
diff --git a/quic/test_tools/quic_stream_peer.cc b/quic/test_tools/quic_stream_peer.cc
index d5ac1e4..e512ba4 100644
--- a/quic/test_tools/quic_stream_peer.cc
+++ b/quic/test_tools/quic_stream_peer.cc
@@ -33,6 +33,11 @@
}
// static
+bool QuicStreamPeer::write_side_closed(QuicStream* stream) {
+ return stream->write_side_closed();
+}
+
+// static
void QuicStreamPeer::CloseReadSide(QuicStream* stream) {
stream->CloseReadSide();
}
diff --git a/quic/test_tools/quic_stream_peer.h b/quic/test_tools/quic_stream_peer.h
index fbbbbb6..e1ba33a 100644
--- a/quic/test_tools/quic_stream_peer.h
+++ b/quic/test_tools/quic_stream_peer.h
@@ -27,6 +27,7 @@
static void SetWriteSideClosed(bool value, QuicStream* stream);
static void SetStreamBytesWritten(QuicStreamOffset stream_bytes_written,
QuicStream* stream);
+ static bool write_side_closed(QuicStream* stream);
static bool read_side_closed(QuicStream* stream);
static void CloseReadSide(QuicStream* stream);
diff --git a/quic/test_tools/quic_test_client.cc b/quic/test_tools/quic_test_client.cc
index 878ac83..a6298a6 100644
--- a/quic/test_tools/quic_test_client.cc
+++ b/quic/test_tools/quic_test_client.cc
@@ -120,7 +120,7 @@
: public QuicClientEpollNetworkHelper {
public:
using QuicClientEpollNetworkHelper::QuicClientEpollNetworkHelper;
- ~MockableQuicClientEpollNetworkHelper() override {}
+ ~MockableQuicClientEpollNetworkHelper() override = default;
void ProcessPacket(const QuicSocketAddress& self_address,
const QuicSocketAddress& peer_address,
@@ -172,7 +172,7 @@
QuicSocketAddress server_address,
const QuicServerId& server_id,
const ParsedQuicVersionVector& supported_versions,
- gfe2::EpollServer* epoll_server)
+ QuicEpollServer* epoll_server)
: MockableQuicClient(server_address,
server_id,
QuicConfig(),
@@ -184,7 +184,7 @@
const QuicServerId& server_id,
const QuicConfig& config,
const ParsedQuicVersionVector& supported_versions,
- gfe2::EpollServer* epoll_server)
+ QuicEpollServer* epoll_server)
: MockableQuicClient(server_address,
server_id,
config,
@@ -197,7 +197,7 @@
const QuicServerId& server_id,
const QuicConfig& config,
const ParsedQuicVersionVector& supported_versions,
- gfe2::EpollServer* epoll_server,
+ QuicEpollServer* epoll_server,
std::unique_ptr<ProofVerifier> proof_verifier)
: QuicClient(
server_address,
@@ -209,7 +209,8 @@
this),
QuicWrapUnique(
new RecordingProofVerifier(std::move(proof_verifier)))),
- override_connection_id_(EmptyQuicConnectionId()) {}
+ override_connection_id_(EmptyQuicConnectionId()),
+ connection_id_overridden_(false) {}
MockableQuicClient::~MockableQuicClient() {
if (connected()) {
@@ -230,12 +231,12 @@
}
QuicConnectionId MockableQuicClient::GenerateNewConnectionId() {
- return !override_connection_id_.IsEmpty()
- ? override_connection_id_
- : QuicClient::GenerateNewConnectionId();
+ return connection_id_overridden_ ? override_connection_id_
+ : QuicClient::GenerateNewConnectionId();
}
void MockableQuicClient::UseConnectionId(QuicConnectionId connection_id) {
+ connection_id_overridden_ = true;
override_connection_id_ = connection_id;
}
@@ -294,7 +295,7 @@
Initialize();
}
-QuicTestClient::QuicTestClient() {}
+QuicTestClient::QuicTestClient() = default;
QuicTestClient::~QuicTestClient() {
for (std::pair<QuicStreamId, QuicSpdyClientStream*> stream : open_streams_) {
@@ -805,7 +806,7 @@
test_client_(test_client),
ack_listener_(std::move(ack_listener)) {}
-QuicTestClient::TestClientDataToResend::~TestClientDataToResend() {}
+QuicTestClient::TestClientDataToResend::~TestClientDataToResend() = default;
void QuicTestClient::TestClientDataToResend::Resend() {
test_client_->GetOrCreateStreamAndSendRequest(headers_.get(), body_, fin_,
@@ -847,7 +848,7 @@
bytes_written(bytes_written),
response_body_size(response_body_size) {}
-QuicTestClient::PerStreamState::~PerStreamState() {}
+QuicTestClient::PerStreamState::~PerStreamState() = default;
bool QuicTestClient::PopulateHeaderBlockFromUrl(
const QuicString& uri,
diff --git a/quic/test_tools/quic_test_client.h b/quic/test_tools/quic_test_client.h
index 08f8808..9142fd9 100644
--- a/quic/test_tools/quic_test_client.h
+++ b/quic/test_tools/quic_test_client.h
@@ -15,6 +15,7 @@
#include "net/third_party/quiche/src/quic/core/quic_packet_creator.h"
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_epoll.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_map_util.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/tools/quic_client.h"
@@ -34,19 +35,19 @@
MockableQuicClient(QuicSocketAddress server_address,
const QuicServerId& server_id,
const ParsedQuicVersionVector& supported_versions,
- gfe2::EpollServer* epoll_server);
+ QuicEpollServer* epoll_server);
MockableQuicClient(QuicSocketAddress server_address,
const QuicServerId& server_id,
const QuicConfig& config,
const ParsedQuicVersionVector& supported_versions,
- gfe2::EpollServer* epoll_server);
+ QuicEpollServer* epoll_server);
MockableQuicClient(QuicSocketAddress server_address,
const QuicServerId& server_id,
const QuicConfig& config,
const ParsedQuicVersionVector& supported_versions,
- gfe2::EpollServer* epoll_server,
+ QuicEpollServer* epoll_server,
std::unique_ptr<ProofVerifier> proof_verifier);
MockableQuicClient(const MockableQuicClient&) = delete;
MockableQuicClient& operator=(const MockableQuicClient&) = delete;
@@ -68,7 +69,9 @@
const MockableQuicClientEpollNetworkHelper* mockable_network_helper() const;
private:
- QuicConnectionId override_connection_id_; // ConnectionId to use, if nonzero
+ // ConnectionId to use, if connection_id_overridden_
+ QuicConnectionId override_connection_id_;
+ bool connection_id_overridden_;
CachedNetworkParameters cached_network_paramaters_;
};
@@ -253,7 +256,7 @@
void WaitForWriteToFlush();
- gfe2::EpollServer* epoll_server() { return &epoll_server_; }
+ QuicEpollServer* epoll_server() { return &epoll_server_; }
size_t num_requests() const { return num_requests_; }
@@ -356,7 +359,7 @@
// tracking its state.
void SetLatestCreatedStream(QuicSpdyClientStream* stream);
- gfe2::EpollServer epoll_server_;
+ QuicEpollServer epoll_server_;
std::unique_ptr<MockableQuicClient> client_; // The actual client
QuicSpdyClientStream* latest_created_stream_;
std::map<QuicStreamId, QuicSpdyClientStream*> open_streams_;
diff --git a/quic/test_tools/quic_test_utils.cc b/quic/test_tools/quic_test_utils.cc
index 49b871d..da76b33 100644
--- a/quic/test_tools/quic_test_utils.cc
+++ b/quic/test_tools/quic_test_utils.cc
@@ -66,7 +66,7 @@
DCHECK_GT(ack_blocks.size(), 0u);
QuicAckFrame ack;
- QuicPacketNumber end_of_previous_block = 1;
+ QuicPacketNumber end_of_previous_block(1);
for (const QuicAckBlock& block : ack_blocks) {
DCHECK_GE(block.start, end_of_previous_block);
DCHECK_GT(block.limit, block.start);
@@ -79,17 +79,22 @@
return ack;
}
+QuicAckFrame InitAckFrame(uint64_t largest_acked) {
+ return InitAckFrame(QuicPacketNumber(largest_acked));
+}
+
QuicAckFrame InitAckFrame(QuicPacketNumber largest_acked) {
- return InitAckFrame({{1, largest_acked + 1}});
+ return InitAckFrame({{QuicPacketNumber(1), largest_acked + 1}});
}
QuicAckFrame MakeAckFrameWithAckBlocks(size_t num_ack_blocks,
- QuicPacketNumber least_unacked) {
+ uint64_t least_unacked) {
QuicAckFrame ack;
- ack.largest_acked = 2 * num_ack_blocks + least_unacked;
+ ack.largest_acked = QuicPacketNumber(2 * num_ack_blocks + least_unacked);
// Add enough received packets to get num_ack_blocks ack blocks.
- for (QuicPacketNumber i = 2; i < 2 * num_ack_blocks + 1; i += 2) {
- ack.packets.Add(least_unacked + i);
+ for (QuicPacketNumber i = QuicPacketNumber(2);
+ i < QuicPacketNumber(2 * num_ack_blocks + 1); i += 2) {
+ ack.packets.Add(i + least_unacked);
}
return ack;
}
@@ -464,7 +469,7 @@
// Transfer ownership of the packet to the SentPacketManager and the
// ack notifier to the AckNotifierManager.
QuicConnectionPeer::GetSentPacketManager(this)->OnPacketSent(
- packet, 0, QuicTime::Zero(), NOT_RETRANSMISSION,
+ packet, QuicPacketNumber(), QuicTime::Zero(), NOT_RETRANSMISSION,
HAS_RETRANSMITTABLE_DATA);
}
@@ -600,7 +605,7 @@
crypto_config,
compressed_certs_cache) {
Initialize();
- ON_CALL(helper_, GenerateConnectionIdForReject(_))
+ ON_CALL(helper_, GenerateConnectionIdForReject(_, _))
.WillByDefault(testing::Return(
QuicUtils::CreateRandomConnectionId(connection->random_generator())));
ON_CALL(helper_, CanAcceptClientHello(_, _, _, _, _))
@@ -786,7 +791,7 @@
QuicConnectionId source_connection_id,
bool version_flag,
bool reset_flag,
- QuicPacketNumber packet_number,
+ uint64_t packet_number,
const QuicString& data) {
return ConstructEncryptedPacket(
destination_connection_id, source_connection_id, version_flag, reset_flag,
@@ -799,7 +804,7 @@
QuicConnectionId source_connection_id,
bool version_flag,
bool reset_flag,
- QuicPacketNumber packet_number,
+ uint64_t packet_number,
const QuicString& data,
QuicConnectionIdLength destination_connection_id_length,
QuicConnectionIdLength source_connection_id_length,
@@ -815,7 +820,7 @@
QuicConnectionId source_connection_id,
bool version_flag,
bool reset_flag,
- QuicPacketNumber packet_number,
+ uint64_t packet_number,
const QuicString& data,
QuicConnectionIdLength destination_connection_id_length,
QuicConnectionIdLength source_connection_id_length,
@@ -832,7 +837,7 @@
QuicConnectionId source_connection_id,
bool version_flag,
bool reset_flag,
- QuicPacketNumber packet_number,
+ uint64_t packet_number,
const QuicString& data,
QuicConnectionIdLength destination_connection_id_length,
QuicConnectionIdLength source_connection_id_length,
@@ -847,7 +852,7 @@
header.version_flag = version_flag;
header.reset_flag = reset_flag;
header.packet_number_length = packet_number_length;
- header.packet_number = packet_number;
+ header.packet_number = QuicPacketNumber(packet_number);
QuicFrame frame(QuicStreamFrame(
QuicUtils::GetCryptoStreamId(
versions != nullptr
@@ -864,8 +869,9 @@
BuildUnsizedDataPacket(&framer, header, frames));
EXPECT_TRUE(packet != nullptr);
char* buffer = new char[kMaxPacketSize];
- size_t encrypted_length = framer.EncryptPayload(
- ENCRYPTION_NONE, packet_number, *packet, buffer, kMaxPacketSize);
+ size_t encrypted_length =
+ framer.EncryptPayload(ENCRYPTION_NONE, QuicPacketNumber(packet_number),
+ *packet, buffer, kMaxPacketSize);
EXPECT_NE(0u, encrypted_length);
return new QuicEncryptedPacket(buffer, encrypted_length, true);
}
@@ -884,7 +890,7 @@
QuicConnectionId source_connection_id,
bool version_flag,
bool reset_flag,
- QuicPacketNumber packet_number,
+ uint64_t packet_number,
const QuicString& data,
QuicConnectionIdLength destination_connection_id_length,
QuicConnectionIdLength source_connection_id_length,
@@ -899,7 +905,7 @@
header.version_flag = version_flag;
header.reset_flag = reset_flag;
header.packet_number_length = packet_number_length;
- header.packet_number = packet_number;
+ header.packet_number = QuicPacketNumber(packet_number);
QuicFrame frame(QuicStreamFrame(1, false, 0, QuicStringPiece(data)));
QuicFrames frames;
frames.push_back(frame);
@@ -918,8 +924,9 @@
false /* no diversification nonce */, packet_number_length)] = 0x1F;
char* buffer = new char[kMaxPacketSize];
- size_t encrypted_length = framer.EncryptPayload(
- ENCRYPTION_NONE, packet_number, *packet, buffer, kMaxPacketSize);
+ size_t encrypted_length =
+ framer.EncryptPayload(ENCRYPTION_NONE, QuicPacketNumber(packet_number),
+ *packet, buffer, kMaxPacketSize);
EXPECT_NE(0u, encrypted_length);
return new QuicEncryptedPacket(buffer, encrypted_length, true);
}
diff --git a/quic/test_tools/quic_test_utils.h b/quic/test_tools/quic_test_utils.h
index 61b60e4..8b52d4f 100644
--- a/quic/test_tools/quic_test_utils.h
+++ b/quic/test_tools/quic_test_utils.h
@@ -77,7 +77,7 @@
QuicConnectionId source_connection_id,
bool version_flag,
bool reset_flag,
- QuicPacketNumber packet_number,
+ uint64_t packet_number,
const QuicString& data,
QuicConnectionIdLength destination_connection_id_length,
QuicConnectionIdLength source_connection_id_length,
@@ -94,7 +94,7 @@
QuicConnectionId source_connection_id,
bool version_flag,
bool reset_flag,
- QuicPacketNumber packet_number,
+ uint64_t packet_number,
const QuicString& data,
QuicConnectionIdLength destination_connection_id_length,
QuicConnectionIdLength source_connection_id_length,
@@ -107,7 +107,7 @@
QuicConnectionId source_connection_id,
bool version_flag,
bool reset_flag,
- QuicPacketNumber packet_number,
+ uint64_t packet_number,
const QuicString& data,
QuicConnectionIdLength destination_connection_id_length,
QuicConnectionIdLength source_connection_id_length,
@@ -121,7 +121,7 @@
QuicConnectionId source_connection_id,
bool version_flag,
bool reset_flag,
- QuicPacketNumber packet_number,
+ uint64_t packet_number,
const QuicString& data);
// Constructs a received packet for testing. The caller must take ownership of
@@ -140,7 +140,7 @@
QuicConnectionId source_connection_id,
bool version_flag,
bool reset_flag,
- QuicPacketNumber packet_number,
+ uint64_t packet_number,
const QuicString& data,
QuicConnectionIdLength destination_connection_id_length,
QuicConnectionIdLength source_connection_id_length,
@@ -195,12 +195,13 @@
// Testing convenience method to construct a QuicAckFrame with 1 ack block which
// covers packet number range [1, |largest_acked| + 1).
// Equivalent to InitAckFrame({{1, largest_acked + 1}})
+QuicAckFrame InitAckFrame(uint64_t largest_acked);
QuicAckFrame InitAckFrame(QuicPacketNumber largest_acked);
// Testing convenience method to construct a QuicAckFrame with |num_ack_blocks|
// ack blocks of width 1 packet, starting from |least_unacked| + 2.
QuicAckFrame MakeAckFrameWithAckBlocks(size_t num_ack_blocks,
- QuicPacketNumber least_unacked);
+ uint64_t least_unacked);
// Returns a QuicPacket that is owned by the caller, and
// is populated with the fields in |header| and |frames|, or is nullptr if the
@@ -553,6 +554,7 @@
QuicConnection::SendConnectivityProbingResponsePacket(peer_address);
}
MOCK_METHOD1(OnPathResponseFrame, bool(const QuicPathResponseFrame&));
+ MOCK_METHOD1(OnStopSendingFrame, bool(const QuicStopSendingFrame& frame));
};
class PacketSavingConnection : public MockQuicConnection {
diff --git a/quic/test_tools/quic_test_utils_test.cc b/quic/test_tools/quic_test_utils_test.cc
index c9627c2..01791e0 100644
--- a/quic/test_tools/quic_test_utils_test.cc
+++ b/quic/test_tools/quic_test_utils_test.cc
@@ -18,8 +18,8 @@
EXPECT_EQ(TestConnectionId(), TestConnectionId());
EXPECT_EQ(TestConnectionId(33), TestConnectionId(33));
EXPECT_NE(TestConnectionId(0xdead), TestConnectionId(0xbeef));
- EXPECT_EQ(0x1337, TestConnectionIdToUInt64(TestConnectionId(0x1337)));
- EXPECT_NE(0xdead, TestConnectionIdToUInt64(TestConnectionId(0xbeef)));
+ EXPECT_EQ(0x1337u, TestConnectionIdToUInt64(TestConnectionId(0x1337)));
+ EXPECT_NE(0xdeadu, TestConnectionIdToUInt64(TestConnectionId(0xbeef)));
}
TEST_F(QuicTestUtilsTest, BasicApproxEq) {
diff --git a/quic/test_tools/simple_data_producer.cc b/quic/test_tools/simple_data_producer.cc
index 1b010eb..ab98fd1 100644
--- a/quic/test_tools/simple_data_producer.cc
+++ b/quic/test_tools/simple_data_producer.cc
@@ -4,6 +4,8 @@
#include "net/third_party/quiche/src/quic/test_tools/simple_data_producer.h"
+#include "net/third_party/quiche/src/quic/core/quic_data_writer.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_map_util.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
@@ -13,13 +15,13 @@
namespace test {
SimpleDataProducer::SimpleDataProducer() {}
+
SimpleDataProducer::~SimpleDataProducer() {}
void SimpleDataProducer::SaveStreamData(QuicStreamId id,
const struct iovec* iov,
int iov_count,
size_t iov_offset,
- QuicStreamOffset offset,
QuicByteCount data_length) {
if (data_length == 0) {
return;
@@ -30,6 +32,13 @@
send_buffer_map_[id]->SaveStreamData(iov, iov_count, iov_offset, data_length);
}
+void SimpleDataProducer::SaveCryptoData(EncryptionLevel level,
+ QuicStreamOffset offset,
+ QuicStringPiece data) {
+ auto key = std::make_pair(level, offset);
+ crypto_buffer_map_[key] = data;
+}
+
WriteStreamDataResult SimpleDataProducer::WriteStreamData(
QuicStreamId id,
QuicStreamOffset offset,
@@ -45,6 +54,17 @@
return WRITE_FAILED;
}
+bool SimpleDataProducer::WriteCryptoData(EncryptionLevel level,
+ QuicStreamOffset offset,
+ QuicByteCount data_length,
+ QuicDataWriter* writer) {
+ auto it = crypto_buffer_map_.find(std::make_pair(level, offset));
+ if (it == crypto_buffer_map_.end() || it->second.length() != data_length) {
+ return false;
+ }
+ return writer->WriteStringPiece(it->second);
+}
+
} // namespace test
} // namespace quic
diff --git a/quic/test_tools/simple_data_producer.h b/quic/test_tools/simple_data_producer.h
index 88622c1..d51ec69 100644
--- a/quic/test_tools/simple_data_producer.h
+++ b/quic/test_tools/simple_data_producer.h
@@ -21,26 +21,67 @@
SimpleDataProducer();
~SimpleDataProducer() override;
+ // Saves data to be provided when WriteStreamData is called. Data of length
+ // |data_length| is buffered to be provided for stream |id|. Multiple calls to
+ // SaveStreamData for the same stream ID append to the buffer for that stream.
+ // The data to be buffered is provided in |iov_count| iovec structs, with
+ // |iov| pointing to the first, and |iov_offset| indicating how many bytes
+ // into the iovec structs the data starts.
void SaveStreamData(QuicStreamId id,
const struct iovec* iov,
int iov_count,
size_t iov_offset,
- QuicStreamOffset offset,
QuicByteCount data_length);
+ void SaveCryptoData(EncryptionLevel level,
+ QuicStreamOffset offset,
+ QuicStringPiece data);
+
// QuicStreamFrameDataProducer
WriteStreamDataResult WriteStreamData(QuicStreamId id,
QuicStreamOffset offset,
QuicByteCount data_length,
QuicDataWriter* writer) override;
+ bool WriteCryptoData(EncryptionLevel level,
+ QuicStreamOffset offset,
+ QuicByteCount data_length,
+ QuicDataWriter* writer) override;
+
+ // TODO(wub): Allow QuicDefaultHasher to accept a pair. Then remove this.
+ class PairHash {
+ public:
+ template <class T1, class T2>
+ size_t operator()(const std::pair<T1, T2>& pair) const {
+ return std::hash<T1>()(pair.first) ^ std::hash<T2>()(pair.second);
+ }
+ };
private:
using SendBufferMap =
QuicUnorderedMap<QuicStreamId, std::unique_ptr<QuicStreamSendBuffer>>;
+ using CryptoBufferMap =
+ QuicUnorderedMap<std::pair<EncryptionLevel, QuicStreamOffset>,
+ QuicStringPiece,
+ PairHash>;
+
SimpleBufferAllocator allocator_;
SendBufferMap send_buffer_map_;
+
+ // |crypto_buffer_map_| stores data provided by SaveCryptoData to later write
+ // in WriteCryptoData. The level and data passed into SaveCryptoData are used
+ // as the key to identify the data when WriteCryptoData is called.
+ // WriteCryptoData will only succeed if there is data in the map for the
+ // provided level and offset, and the data in the map matches the data_length
+ // passed into WriteCryptoData.
+ //
+ // Unlike SaveStreamData/WriteStreamData which uses a map of
+ // QuicStreamSendBuffers (for each stream ID), this map provides data for
+ // specific offsets. Using a QuicStreamSendBuffer requires that all data
+ // before an offset exist, whereas this allows providing data that exists at
+ // arbitrary offsets for testing.
+ CryptoBufferMap crypto_buffer_map_;
};
} // namespace test
diff --git a/quic/test_tools/simulator/quic_endpoint.cc b/quic/test_tools/simulator/quic_endpoint.cc
index 4cf236b..2867d82 100644
--- a/quic/test_tools/simulator/quic_endpoint.cc
+++ b/quic/test_tools/simulator/quic_endpoint.cc
@@ -222,6 +222,7 @@
// Sanity check against very pathological connections.
DCHECK_LE(offsets_received_.Size(), 1000u);
}
+
void QuicEndpoint::OnCanWrite() {
if (notifier_ != nullptr) {
notifier_->OnCanWrite();
@@ -354,6 +355,14 @@
return WRITE_SUCCESS;
}
+bool QuicEndpoint::DataProducer::WriteCryptoData(EncryptionLevel leve,
+ QuicStreamOffset offset,
+ QuicByteCount data_length,
+ QuicDataWriter* writer) {
+ QUIC_BUG << "QuicEndpoint::DataProducer::WriteCryptoData is unimplemented";
+ return false;
+}
+
void QuicEndpoint::WriteStreamData() {
// Instantiate a flusher which would normally be here due to QuicSession.
QuicConnection::ScopedPacketFlusher flusher(
diff --git a/quic/test_tools/simulator/quic_endpoint.h b/quic/test_tools/simulator/quic_endpoint.h
index 1a31ab2..600a1d1 100644
--- a/quic/test_tools/simulator/quic_endpoint.h
+++ b/quic/test_tools/simulator/quic_endpoint.h
@@ -166,6 +166,10 @@
QuicStreamOffset offset,
QuicByteCount data_length,
QuicDataWriter* writer) override;
+ bool WriteCryptoData(EncryptionLevel level,
+ QuicStreamOffset offset,
+ QuicByteCount data_length,
+ QuicDataWriter* writer) override;
};
// Write stream data until |bytes_to_transfer_| is zero or the connection is
diff --git a/quic/test_tools/simulator/simulator_test.cc b/quic/test_tools/simulator/simulator_test.cc
index cb0c3a6..b2221c7 100644
--- a/quic/test_tools/simulator/simulator_test.cc
+++ b/quic/test_tools/simulator/simulator_test.cc
@@ -310,10 +310,9 @@
saturator.SetTxPort(&local_link);
queue.set_tx_port(&bottleneck_link);
- const QuicPacketCount packets_received = 1000;
- simulator.RunUntil([&counter, packets_received]() {
- return counter.packets() == packets_received;
- });
+ static const QuicPacketCount packets_received = 1000;
+ simulator.RunUntil(
+ [&counter]() { return counter.packets() == packets_received; });
const double loss_ratio = 1 - static_cast<double>(packets_received) /
saturator.packets_transmitted();
EXPECT_NEAR(loss_ratio, 0.9, 0.001);
diff --git a/quic/tools/quic_client.cc b/quic/tools/quic_client.cc
index 84e1844..7705907 100644
--- a/quic/tools/quic_client.cc
+++ b/quic/tools/quic_client.cc
@@ -35,7 +35,7 @@
QuicClient::QuicClient(QuicSocketAddress server_address,
const QuicServerId& server_id,
const ParsedQuicVersionVector& supported_versions,
- gfe2::EpollServer* epoll_server,
+ QuicEpollServer* epoll_server,
std::unique_ptr<ProofVerifier> proof_verifier)
: QuicClient(
server_address,
@@ -50,7 +50,7 @@
QuicSocketAddress server_address,
const QuicServerId& server_id,
const ParsedQuicVersionVector& supported_versions,
- gfe2::EpollServer* epoll_server,
+ QuicEpollServer* epoll_server,
std::unique_ptr<QuicClientEpollNetworkHelper> network_helper,
std::unique_ptr<ProofVerifier> proof_verifier)
: QuicClient(server_address,
@@ -66,7 +66,7 @@
const QuicServerId& server_id,
const ParsedQuicVersionVector& supported_versions,
const QuicConfig& config,
- gfe2::EpollServer* epoll_server,
+ QuicEpollServer* epoll_server,
std::unique_ptr<QuicClientEpollNetworkHelper> network_helper,
std::unique_ptr<ProofVerifier> proof_verifier)
: QuicSpdyClientBase(
@@ -80,7 +80,7 @@
set_server_address(server_address);
}
-QuicClient::~QuicClient() {}
+QuicClient::~QuicClient() = default;
std::unique_ptr<QuicSession> QuicClient::CreateQuicClientSession(
const ParsedQuicVersionVector& supported_versions,
diff --git a/quic/tools/quic_client.h b/quic/tools/quic_client.h
index 71ff7f4..03a029d 100644
--- a/quic/tools/quic_client.h
+++ b/quic/tools/quic_client.h
@@ -21,6 +21,7 @@
#include "net/third_party/quiche/src/quic/core/quic_packet_reader.h"
#include "net/third_party/quiche/src/quic/core/quic_process_packet_interface.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_epoll.h"
#include "net/third_party/quiche/src/quic/tools/quic_client_epoll_network_helper.h"
#include "net/third_party/quiche/src/quic/tools/quic_spdy_client_base.h"
@@ -38,20 +39,20 @@
QuicClient(QuicSocketAddress server_address,
const QuicServerId& server_id,
const ParsedQuicVersionVector& supported_versions,
- gfe2::EpollServer* epoll_server,
+ QuicEpollServer* epoll_server,
std::unique_ptr<ProofVerifier> proof_verifier);
// This will take ownership of a passed in network primitive.
QuicClient(QuicSocketAddress server_address,
const QuicServerId& server_id,
const ParsedQuicVersionVector& supported_versions,
- gfe2::EpollServer* epoll_server,
+ QuicEpollServer* epoll_server,
std::unique_ptr<QuicClientEpollNetworkHelper> network_helper,
std::unique_ptr<ProofVerifier> proof_verifier);
QuicClient(QuicSocketAddress server_address,
const QuicServerId& server_id,
const ParsedQuicVersionVector& supported_versions,
const QuicConfig& config,
- gfe2::EpollServer* epoll_server,
+ QuicEpollServer* epoll_server,
std::unique_ptr<QuicClientEpollNetworkHelper> network_helper,
std::unique_ptr<ProofVerifier> proof_verifier);
QuicClient(const QuicClient&) = delete;
diff --git a/quic/tools/quic_client_base.cc b/quic/tools/quic_client_base.cc
index 8a469a6..f824811 100644
--- a/quic/tools/quic_client_base.cc
+++ b/quic/tools/quic_client_base.cc
@@ -86,7 +86,7 @@
// Resend any previously queued data.
ResendSavedData();
}
- ParsedQuicVersion version(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED);
+ ParsedQuicVersion version = UnsupportedQuicVersion();
if (session() != nullptr &&
session()->error() != QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT &&
!CanReconnectWithDifferentVersion(&version)) {
@@ -110,8 +110,7 @@
DCHECK(initialized_);
DCHECK(!connected());
QuicPacketWriter* writer = network_helper_->CreateQuicPacketWriter();
- ParsedQuicVersion mutual_version(PROTOCOL_UNSUPPORTED,
- QUIC_VERSION_UNSUPPORTED);
+ ParsedQuicVersion mutual_version = UnsupportedQuicVersion();
const bool can_reconnect_with_different_version =
CanReconnectWithDifferentVersion(&mutual_version);
if (connected_or_attempting_connect()) {
@@ -180,7 +179,7 @@
network_helper_->RunEventLoop();
DCHECK(session() != nullptr);
- ParsedQuicVersion version(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED);
+ ParsedQuicVersion version = UnsupportedQuicVersion();
if (!connected() &&
(session()->error() == QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT ||
CanReconnectWithDifferentVersion(&version))) {
diff --git a/quic/tools/quic_client_base.h b/quic/tools/quic_client_base.h
index 8257cef..c751bfd 100644
--- a/quic/tools/quic_client_base.h
+++ b/quic/tools/quic_client_base.h
@@ -136,17 +136,6 @@
crypto_config_.SetChannelIDSource(source);
}
- // UseTokenBinding enables token binding negotiation in the client. This
- // should only be called before the initial Connect(). The client will still
- // need to check that token binding is negotiated with the server, and add
- // token binding headers to requests if so. server, and add token binding
- // headers to requests if so. The negotiated token binding parameters can be
- // found on the QuicCryptoNegotiatedParameters object in
- // token_binding_key_param.
- void UseTokenBinding() {
- crypto_config_.tb_key_params = QuicTagVector{kTB10};
- }
-
const ParsedQuicVersionVector& supported_versions() const {
return supported_versions_;
}
diff --git a/quic/tools/quic_client_bin.cc b/quic/tools/quic_client_bin.cc
index dc82b0f..629b980 100644
--- a/quic/tools/quic_client_bin.cc
+++ b/quic/tools/quic_client_bin.cc
@@ -124,9 +124,13 @@
"for_connecting_to_google/roots.pem",
"Path to the root certificate which the server's certificate is "
"required to chain to.");
-ABSL_FLAG(bool, disable_certificate_verification, false,
+ABSL_FLAG(bool,
+ disable_certificate_verification,
+ false,
"If true, don't verify the server certificate.");
-ABSL_FLAG(bool, drop_response_body, false,
+ABSL_FLAG(bool,
+ drop_response_body,
+ false,
"If true, drop response body immediately after it is received.");
using quic::QuicStringPiece;
@@ -169,7 +173,7 @@
cout << "Resolved " << host << " to " << host_port << endl;
// Build the client, and try to connect.
- gfe2::EpollServer epoll_server;
+ quic::QuicEpollServer epoll_server;
quic::QuicServerId server_id(url.host(), port, false);
quic::ParsedQuicVersionVector versions = quic::CurrentSupportedVersions();
if (FLAGS_quic_version != -1) {
diff --git a/quic/tools/quic_client_epoll_network_helper.cc b/quic/tools/quic_client_epoll_network_helper.cc
index b12148c..6a48ad3 100644
--- a/quic/tools/quic_client_epoll_network_helper.cc
+++ b/quic/tools/quic_client_epoll_network_helper.cc
@@ -36,7 +36,7 @@
} // namespace
QuicClientEpollNetworkHelper::QuicClientEpollNetworkHelper(
- gfe2::EpollServer* epoll_server,
+ QuicEpollServer* epoll_server,
QuicClientBase* client)
: epoll_server_(epoll_server),
packets_dropped_(0),
@@ -120,14 +120,14 @@
epoll_server_->WaitForEventsAndExecuteCallbacks();
}
-void QuicClientEpollNetworkHelper::OnRegistration(gfe2::EpollServer* eps,
+void QuicClientEpollNetworkHelper::OnRegistration(QuicEpollServer* eps,
int fd,
int event_mask) {}
void QuicClientEpollNetworkHelper::OnModification(int fd, int event_mask) {}
void QuicClientEpollNetworkHelper::OnUnregistration(int fd, bool replaced) {}
-void QuicClientEpollNetworkHelper::OnShutdown(gfe2::EpollServer* eps, int fd) {}
+void QuicClientEpollNetworkHelper::OnShutdown(QuicEpollServer* eps, int fd) {}
-void QuicClientEpollNetworkHelper::OnEvent(int fd, gfe2::EpollEvent* event) {
+void QuicClientEpollNetworkHelper::OnEvent(int fd, QuicEpollEvent* event) {
DCHECK_EQ(fd, GetLatestFD());
if (event->in_events & EPOLLIN) {
diff --git a/quic/tools/quic_client_epoll_network_helper.h b/quic/tools/quic_client_epoll_network_helper.h
index 23a1c91..5871cd0 100644
--- a/quic/tools/quic_client_epoll_network_helper.h
+++ b/quic/tools/quic_client_epoll_network_helper.h
@@ -21,6 +21,7 @@
#include "net/third_party/quiche/src/quic/core/quic_packet_reader.h"
#include "net/third_party/quiche/src/quic/core/quic_process_packet_interface.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_containers.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_epoll.h"
#include "net/third_party/quiche/src/quic/tools/quic_spdy_client_base.h"
namespace quic {
@@ -32,12 +33,12 @@
// An implementation of the QuicClientBase::NetworkHelper based off
// the epoll server.
class QuicClientEpollNetworkHelper : public QuicClientBase::NetworkHelper,
- public gfe2::EpollCallbackInterface,
+ public QuicEpollCallbackInterface,
public ProcessPacketInterface {
public:
// Create a quic client, which will have events managed by an externally owned
// EpollServer.
- QuicClientEpollNetworkHelper(gfe2::EpollServer* epoll_server,
+ QuicClientEpollNetworkHelper(QuicEpollServer* epoll_server,
QuicClientBase* client);
QuicClientEpollNetworkHelper(const QuicClientEpollNetworkHelper&) = delete;
QuicClientEpollNetworkHelper& operator=(const QuicClientEpollNetworkHelper&) =
@@ -49,14 +50,14 @@
QuicString Name() const override;
// From EpollCallbackInterface
- void OnRegistration(gfe2::EpollServer* eps, int fd, int event_mask) override;
+ void OnRegistration(QuicEpollServer* eps, int fd, int event_mask) override;
void OnModification(int fd, int event_mask) override;
- void OnEvent(int fd, gfe2::EpollEvent* event) override;
+ void OnEvent(int fd, QuicEpollEvent* event) override;
// |fd_| can be unregistered without the client being disconnected. This
// happens in b3m QuicProber where we unregister |fd_| to feed in events to
// the client from the SelectServer.
void OnUnregistration(int fd, bool replaced) override;
- void OnShutdown(gfe2::EpollServer* eps, int fd) override;
+ void OnShutdown(QuicEpollServer* eps, int fd) override;
// From ProcessPacketInterface. This will be called for each received
// packet.
@@ -75,7 +76,7 @@
// Accessors provided for convenience, not part of any interface.
- gfe2::EpollServer* epoll_server() { return epoll_server_; }
+ QuicEpollServer* epoll_server() { return epoll_server_; }
const QuicLinkedHashMap<int, QuicSocketAddress>& fd_address_map() const {
return fd_address_map_;
@@ -110,7 +111,7 @@
void CleanUpUDPSocketImpl(int fd);
// Listens for events on the client socket.
- gfe2::EpollServer* epoll_server_;
+ QuicEpollServer* epoll_server_;
// Map mapping created UDP sockets to their addresses. By using linked hash
// map, the order of socket creation can be recorded.
diff --git a/quic/tools/quic_client_test.cc b/quic/tools/quic_client_test.cc
index 1c8c7ad..4f139b3 100644
--- a/quic/tools/quic_client_test.cc
+++ b/quic/tools/quic_client_test.cc
@@ -17,8 +17,6 @@
#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
#include "net/third_party/quiche/src/quic/test_tools/quic_client_peer.h"
-using gfe2::EpollServer;
-
namespace quic {
namespace test {
namespace {
@@ -51,7 +49,7 @@
// Creates a new QuicClient and Initializes it. Caller is responsible for
// deletion.
-QuicClient* CreateAndInitializeQuicClient(EpollServer* eps, uint16_t port) {
+QuicClient* CreateAndInitializeQuicClient(QuicEpollServer* eps, uint16_t port) {
QuicSocketAddress server_address(QuicSocketAddress(TestLoopback(), port));
QuicServerId server_id("hostname", server_address.port(), false);
ParsedQuicVersionVector versions = AllSupportedVersions();
@@ -69,7 +67,7 @@
// port exhaustion in long running processes which repeatedly create clients.
// Record initial number of FDs, after creation of EpollServer.
- EpollServer eps;
+ QuicEpollServer eps;
size_t number_of_open_fds = NumOpenSocketFDs();
// Create a number of clients, initialize them, and verify this has resulted
@@ -88,7 +86,7 @@
}
TEST_F(QuicClientTest, CreateAndCleanUpUDPSockets) {
- EpollServer eps;
+ QuicEpollServer eps;
size_t number_of_open_fds = NumOpenSocketFDs();
std::unique_ptr<QuicClient> client(
diff --git a/quic/tools/quic_memory_cache_backend.cc b/quic/tools/quic_memory_cache_backend.cc
index 94d795a..fa80e7e 100644
--- a/quic/tools/quic_memory_cache_backend.cc
+++ b/quic/tools/quic_memory_cache_backend.cc
@@ -107,9 +107,9 @@
host_ = base.substr(0, path_start);
size_t query_start = base.find_first_of(',');
if (query_start > 0) {
- path_ = absl::ClippedSubstr(base, path_start, query_start - 1);
+ path_ = base.substr(path_start, query_start - 1);
} else {
- path_ = absl::ClippedSubstr(base, path_start);
+ path_ = base.substr(path_start);
}
}
diff --git a/quic/tools/quic_server.cc b/quic/tools/quic_server.cc
index 7e8dc95..eaec5d4 100644
--- a/quic/tools/quic_server.cc
+++ b/quic/tools/quic_server.cc
@@ -182,7 +182,7 @@
fd_ = -1;
}
-void QuicServer::OnEvent(int fd, gfe2::EpollEvent* event) {
+void QuicServer::OnEvent(int fd, QuicEpollEvent* event) {
DCHECK_EQ(fd, fd_);
event->out_ready_mask = 0;
diff --git a/quic/tools/quic_server.h b/quic/tools/quic_server.h
index 712eceb..af60f95 100644
--- a/quic/tools/quic_server.h
+++ b/quic/tools/quic_server.h
@@ -21,6 +21,7 @@
#include "net/third_party/quiche/src/quic/core/quic_framer.h"
#include "net/third_party/quiche/src/quic/core/quic_packet_writer.h"
#include "net/third_party/quiche/src/quic/core/quic_version_manager.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_epoll.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
#include "net/third_party/quiche/src/quic/tools/quic_simple_server_backend.h"
@@ -33,7 +34,7 @@
class QuicDispatcher;
class QuicPacketReader;
-class QuicServer : public gfe2::EpollCallbackInterface {
+class QuicServer : public QuicEpollCallbackInterface {
public:
QuicServer(std::unique_ptr<ProofSource> proof_source,
QuicSimpleServerBackend* quic_simple_server_backend);
@@ -62,13 +63,12 @@
virtual void Shutdown();
// From EpollCallbackInterface
- void OnRegistration(gfe2::EpollServer* eps, int fd, int event_mask) override {
- }
+ void OnRegistration(QuicEpollServer* eps, int fd, int event_mask) override {}
void OnModification(int fd, int event_mask) override {}
- void OnEvent(int fd, gfe2::EpollEvent* event) override;
+ void OnEvent(int fd, QuicEpollEvent* event) override;
void OnUnregistration(int fd, bool replaced) override {}
- void OnShutdown(gfe2::EpollServer* eps, int fd) override {}
+ void OnShutdown(QuicEpollServer* eps, int fd) override {}
void SetChloMultiplier(size_t multiplier) {
crypto_config_.set_chlo_multiplier(multiplier);
@@ -91,7 +91,7 @@
const QuicConfig& config() const { return config_; }
const QuicCryptoServerConfig& crypto_config() const { return crypto_config_; }
- gfe2::EpollServer* epoll_server() { return &epoll_server_; }
+ QuicEpollServer* epoll_server() { return &epoll_server_; }
QuicDispatcher* dispatcher() { return dispatcher_.get(); }
@@ -112,7 +112,7 @@
// Accepts data from the framer and demuxes clients to sessions.
std::unique_ptr<QuicDispatcher> dispatcher_;
// Frames incoming packets and hands them to the dispatcher.
- gfe2::EpollServer epoll_server_;
+ QuicEpollServer epoll_server_;
// The port the server is listening on.
int port_;
diff --git a/quic/tools/quic_server_test.cc b/quic/tools/quic_server_test.cc
index a3c0fb0..f549ad4 100644
--- a/quic/tools/quic_server_test.cc
+++ b/quic/tools/quic_server_test.cc
@@ -28,7 +28,6 @@
namespace quic {
namespace test {
-using gfe2::EpollServer;
using ::testing::_;
namespace {
@@ -228,7 +227,7 @@
QuicConfig config_;
QuicCryptoServerConfig crypto_config_;
QuicVersionManager version_manager_;
- EpollServer eps_;
+ QuicEpollServer eps_;
QuicMemoryCacheBackend quic_simple_server_backend_;
MockQuicDispatcher dispatcher_;
};
diff --git a/quic/tools/quic_simple_crypto_server_stream_helper.cc b/quic/tools/quic_simple_crypto_server_stream_helper.cc
index af4e152..567c670 100644
--- a/quic/tools/quic_simple_crypto_server_stream_helper.cc
+++ b/quic/tools/quic_simple_crypto_server_stream_helper.cc
@@ -17,6 +17,7 @@
QuicConnectionId
QuicSimpleCryptoServerStreamHelper::GenerateConnectionIdForReject(
+ QuicTransportVersion /*version*/,
QuicConnectionId /*connection_id*/) const {
return QuicUtils::CreateRandomConnectionId(random_, Perspective::IS_SERVER);
}
diff --git a/quic/tools/quic_simple_crypto_server_stream_helper.h b/quic/tools/quic_simple_crypto_server_stream_helper.h
index 2c1e19a..c058f1a 100644
--- a/quic/tools/quic_simple_crypto_server_stream_helper.h
+++ b/quic/tools/quic_simple_crypto_server_stream_helper.h
@@ -20,13 +20,14 @@
~QuicSimpleCryptoServerStreamHelper() override;
QuicConnectionId GenerateConnectionIdForReject(
+ QuicTransportVersion /*version*/,
QuicConnectionId /*connection_id*/) const override;
bool CanAcceptClientHello(const CryptoHandshakeMessage& message,
const QuicSocketAddress& client_address,
const QuicSocketAddress& peer_address,
const QuicSocketAddress& self_address,
- string* error_details) const override;
+ QuicString* error_details) const override;
private:
QuicRandom* random_; // Unowned.
diff --git a/quic/tools/quic_simple_crypto_server_stream_helper_test.cc b/quic/tools/quic_simple_crypto_server_stream_helper_test.cc
index e64ba69..652f282 100644
--- a/quic/tools/quic_simple_crypto_server_stream_helper_test.cc
+++ b/quic/tools/quic_simple_crypto_server_stream_helper_test.cc
@@ -14,7 +14,12 @@
QuicSimpleCryptoServerStreamHelper helper(&random);
EXPECT_EQ(QuicUtils::CreateRandomConnectionId(&random),
- helper.GenerateConnectionIdForReject(test::TestConnectionId()));
+ helper.GenerateConnectionIdForReject(QUIC_VERSION_35,
+ test::TestConnectionId()));
+
+ EXPECT_EQ(QuicUtils::CreateRandomConnectionId(&random),
+ helper.GenerateConnectionIdForReject(QUIC_VERSION_99,
+ test::TestConnectionId()));
}
} // namespace quic
diff --git a/quic/tools/quic_simple_server_session.cc b/quic/tools/quic_simple_server_session.cc
index 685d9f5..a3e8208 100644
--- a/quic/tools/quic_simple_server_session.cc
+++ b/quic/tools/quic_simple_server_session.cc
@@ -13,8 +13,6 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
#include "net/third_party/quiche/src/quic/tools/quic_simple_server_stream.h"
-using spdy::SpdyHeaderBlock;
-
namespace quic {
QuicSimpleServerSession::QuicSimpleServerSession(
diff --git a/quic/tools/quic_simple_server_session_test.cc b/quic/tools/quic_simple_server_session_test.cc
index a76facd..1ba330d 100644
--- a/quic/tools/quic_simple_server_session_test.cc
+++ b/quic/tools/quic_simple_server_session_test.cc
@@ -251,6 +251,25 @@
*session_, n);
}
+ void InjectStopSending(QuicStreamId stream_id,
+ QuicRstStreamErrorCode rst_stream_code) {
+ // Create and inject a STOP_SENDING frame. In GOOGLE QUIC, receiving a
+ // RST_STREAM frame causes a two-way close. For IETF QUIC, RST_STREAM causes
+ // a one-way close.
+ if (connection_->transport_version() != QUIC_VERSION_99) {
+ // Only needed for version 99/IETF QUIC.
+ return;
+ }
+ EXPECT_CALL(owner_, OnStopSendingReceived(_)).Times(1);
+ QuicStopSendingFrame stop_sending(
+ kInvalidControlFrameId, stream_id,
+ static_cast<QuicApplicationErrorCode>(rst_stream_code));
+ // Expect the RESET_STREAM that is generated in response to receiving a
+ // STOP_SENDING.
+ EXPECT_CALL(*connection_, OnStreamReset(stream_id, rst_stream_code));
+ session_->OnStopSendingFrame(stop_sending);
+ }
+
StrictMock<MockQuicSessionVisitor> owner_;
StrictMock<MockQuicCryptoServerStreamHelper> stream_helper_;
MockQuicConnectionHelper helper_;
@@ -287,6 +306,11 @@
OnStreamReset(GetNthClientInitiatedBidirectionalId(0),
QUIC_RST_ACKNOWLEDGEMENT));
visitor_->OnRstStream(rst1);
+ // Create and inject a STOP_SENDING frame. In GOOGLE QUIC, receiving a
+ // RST_STREAM frame causes a two-way close. For IETF QUIC, RST_STREAM causes
+ // a one-way close.
+ InjectStopSending(GetNthClientInitiatedBidirectionalId(0),
+ QUIC_ERROR_PROCESSING_STREAM);
EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams());
// Send the same two bytes of payload in a new packet.
@@ -310,6 +334,12 @@
OnStreamReset(GetNthClientInitiatedBidirectionalId(0),
QUIC_RST_ACKNOWLEDGEMENT));
visitor_->OnRstStream(rst1);
+ // Create and inject a STOP_SENDING frame. In GOOGLE QUIC, receiving a
+ // RST_STREAM frame causes a two-way close. For IETF QUIC, RST_STREAM causes
+ // a one-way close.
+ InjectStopSending(GetNthClientInitiatedBidirectionalId(0),
+ QUIC_ERROR_PROCESSING_STREAM);
+
EXPECT_EQ(0u, session_->GetNumOpenIncomingStreams());
// Send two bytes of payload.
@@ -344,6 +374,11 @@
OnStreamReset(GetNthClientInitiatedBidirectionalId(0),
QUIC_RST_ACKNOWLEDGEMENT));
visitor_->OnRstStream(rst);
+ // Create and inject a STOP_SENDING frame. In GOOGLE QUIC, receiving a
+ // RST_STREAM frame causes a two-way close. For IETF QUIC, RST_STREAM causes
+ // a one-way close.
+ InjectStopSending(GetNthClientInitiatedBidirectionalId(0),
+ QUIC_ERROR_PROCESSING_STREAM);
// If we were tracking, we'd probably want to reject this because it's data
// past the reset point of stream 3. As it's a closed stream we just drop the
@@ -794,6 +829,10 @@
QuicMaxStreamIdFrame(0, GetNthServerInitiatedUnidirectionalId(10)));
}
visitor_->OnRstStream(rst);
+ // Create and inject a STOP_SENDING frame. In GOOGLE QUIC, receiving a
+ // RST_STREAM frame causes a two-way close. For IETF QUIC, RST_STREAM causes
+ // a one-way close.
+ InjectStopSending(stream_got_reset, QUIC_STREAM_CANCELLED);
}
} // namespace
diff --git a/quic/tools/quic_simple_server_stream_test.cc b/quic/tools/quic_simple_server_stream_test.cc
index 3916bd8..4e9e68d 100644
--- a/quic/tools/quic_simple_server_stream_test.cc
+++ b/quic/tools/quic_simple_server_stream_test.cc
@@ -170,6 +170,8 @@
using QuicSession::ActivateStream;
+ MOCK_METHOD1(OnStopSendingReceived, void(const QuicStopSendingFrame& frame));
+
spdy::SpdyHeaderBlock original_request_headers_;
};
@@ -197,7 +199,8 @@
&memory_cache_backend_),
quic_response_(new QuicBackendResponse),
body_("hello world"),
- is_verion_99_(connection_->transport_version() == QUIC_VERSION_99) {
+ is_version_99_(connection_->transport_version() == QUIC_VERSION_99) {
+ connection_->set_visitor(&session_);
header_list_.OnHeaderBlockStart();
header_list_.OnHeader(":authority", "www.google.com");
header_list_.OnHeader(":path", "/");
@@ -245,7 +248,7 @@
QuicString body_;
QuicHeaderList header_list_;
HttpEncoder encoder_;
- bool is_verion_99_;
+ bool is_version_99_;
};
INSTANTIATE_TEST_CASE_P(Tests,
@@ -261,7 +264,7 @@
QuicByteCount header_length =
encoder_.SerializeDataFrameHeader(body_.length(), &buffer);
QuicString header = QuicString(buffer.get(), header_length);
- QuicString data = is_verion_99_ ? header + body_ : body_;
+ QuicString data = is_version_99_ ? header + body_ : body_;
stream_->OnStreamFrame(
QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, data));
EXPECT_EQ("11", StreamHeadersValue("content-length"));
@@ -280,7 +283,7 @@
QuicByteCount header_length =
encoder_.SerializeDataFrameHeader(body_.length(), &buffer);
QuicString header = QuicString(buffer.get(), header_length);
- QuicString data = is_verion_99_ ? header + body_ : body_;
+ QuicString data = is_version_99_ ? header + body_ : body_;
stream_->OnStreamFrame(
QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, data));
EXPECT_EQ("11", StreamHeadersValue("content-length"));
@@ -310,7 +313,7 @@
// We'll automatically write out an error (headers + body)
EXPECT_CALL(session_, WriteHeadersMock(_, _, _, _, _));
- if (is_verion_99_) {
+ if (is_version_99_) {
EXPECT_CALL(session_, WritevData(_, _, _, _, _))
.WillOnce(Invoke(MockQuicSession::ConsumeData));
}
@@ -324,7 +327,7 @@
QuicByteCount header_length =
encoder_.SerializeDataFrameHeader(body_.length(), &buffer);
QuicString header = QuicString(buffer.get(), header_length);
- QuicString data = is_verion_99_ ? header + body_ : body_;
+ QuicString data = is_version_99_ ? header + body_ : body_;
stream_->OnStreamFrame(
QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, data));
@@ -333,7 +336,7 @@
header_length =
encoder_.SerializeDataFrameHeader(large_body.length(), &buffer);
header = QuicString(buffer.get(), header_length);
- QuicString data2 = is_verion_99_ ? header + large_body : large_body;
+ QuicString data2 = is_version_99_ ? header + large_body : large_body;
stream_->OnStreamFrame(
QuicStreamFrame(stream_->id(), /*fin=*/true, data.size(), data2));
EXPECT_EQ("11", StreamHeadersValue("content-length"));
@@ -365,7 +368,7 @@
InSequence s;
EXPECT_CALL(session_, WriteHeadersMock(stream_->id(), _, false, _, _));
- if (is_verion_99_) {
+ if (is_version_99_) {
EXPECT_CALL(session_, WritevData(_, _, _, _, _))
.Times(1)
.WillOnce(Return(QuicConsumedData(header_length, false)));
@@ -405,7 +408,7 @@
InSequence s;
EXPECT_CALL(session_, WriteHeadersMock(stream_->id(), _, false, _, _));
- if (is_verion_99_) {
+ if (is_version_99_) {
EXPECT_CALL(session_, WritevData(_, _, _, _, _))
.Times(1)
.WillOnce(Return(QuicConsumedData(header_length, false)));
@@ -474,7 +477,7 @@
InSequence s;
EXPECT_CALL(session_, WriteHeadersMock(stream_->id(), _, false, _, _));
- if (is_verion_99_) {
+ if (is_version_99_) {
EXPECT_CALL(session_, WritevData(_, _, _, _, _))
.Times(1)
.WillOnce(Return(QuicConsumedData(header_length, false)));
@@ -523,7 +526,7 @@
session_, 0),
_));
EXPECT_CALL(session_, WriteHeadersMock(stream_->id(), _, false, _, _));
- if (is_verion_99_) {
+ if (is_version_99_) {
EXPECT_CALL(session_, WritevData(_, _, _, _, _))
.Times(1)
.WillOnce(Return(QuicConsumedData(header_length, false)));
@@ -588,7 +591,7 @@
server_initiated_stream->priority(), _));
InSequence s;
- if (is_verion_99_) {
+ if (is_version_99_) {
EXPECT_CALL(session_, WritevData(_, kServerInitiatedStreamId, _, _, _))
.Times(1)
.WillOnce(Return(QuicConsumedData(header_length, false)));
@@ -612,7 +615,7 @@
InSequence s;
EXPECT_CALL(session_, WriteHeadersMock(_, _, _, _, _));
- if (is_verion_99_) {
+ if (is_version_99_) {
EXPECT_CALL(session_, WritevData(_, _, _, _, _))
.Times(1)
.WillOnce(Return(QuicConsumedData(2, false)));
@@ -685,7 +688,12 @@
QuicRstStreamFrame rst_frame(kInvalidControlFrameId, stream_->id(),
QUIC_STREAM_CANCELLED, 1234);
stream_->OnStreamReset(rst_frame);
-
+ if (connection_->transport_version() == QUIC_VERSION_99) {
+ // For V99 receiving a RST_STREAM causes a 1-way close; the test requires
+ // a full close. A CloseWriteSide closes the other half of the stream.
+ // Everything should then work properly.
+ stream_->CloseWriteSide();
+ }
EXPECT_TRUE(stream_->reading_stopped());
EXPECT_TRUE(stream_->write_side_closed());
}
diff --git a/quic/tools/quic_spdy_client_base.cc b/quic/tools/quic_spdy_client_base.cc
index 22db8df..f03b678 100644
--- a/quic/tools/quic_spdy_client_base.cc
+++ b/quic/tools/quic_spdy_client_base.cc
@@ -27,7 +27,7 @@
bool fin)
: headers_(std::move(headers)), body_(body), fin_(fin) {}
-QuicSpdyClientBase::QuicDataToResend::~QuicDataToResend() {}
+QuicSpdyClientBase::QuicDataToResend::~QuicDataToResend() = default;
QuicSpdyClientBase::QuicSpdyClientBase(
const QuicServerId& server_id,
diff --git a/spdy/core/hpack/hpack_constants.cc b/spdy/core/hpack/hpack_constants.cc
index da41c0e..9c1498a 100644
--- a/spdy/core/hpack/hpack_constants.cc
+++ b/spdy/core/hpack/hpack_constants.cc
@@ -6,13 +6,12 @@
#include <cstddef>
#include <memory>
+#include <vector>
#include "base/logging.h"
-#include "base/once.h"
#include "net/third_party/quiche/src/spdy/core/hpack/hpack_huffman_table.h"
#include "net/third_party/quiche/src/spdy/core/hpack/hpack_static_table.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_arraysize.h"
-#include "net/third_party/quiche/src/spdy/platform/api/spdy_ptr_util.h"
namespace spdy {
@@ -26,7 +25,7 @@
// HpackHuffmanSymbol entries are initialized as {code, length, id}.
// Codes are specified in the |length| most-significant bits of |code|.
const std::vector<HpackHuffmanSymbol>& HpackHuffmanCodeVector() {
- static const std::vector<HpackHuffmanSymbol> kHpackHuffmanCode = {
+ static const auto* kHpackHuffmanCode = new std::vector<HpackHuffmanSymbol>{
{0xffc00000ul, 13, 0}, // 11111111|11000
{0xffffb000ul, 23, 1}, // 11111111|11111111|1011000
{0xfffffe20ul, 28, 2}, // 11111111|11111111|11111110|0010
@@ -285,7 +284,7 @@
{0xfffffb80ul, 26, 255}, // 11111111|11111111|11111011|10
{0xfffffffcul, 30, 256}, // EOS 11111111|11111111|11111111|111111
};
- return kHpackHuffmanCode;
+ return *kHpackHuffmanCode;
}
// The "constructor" for a HpackStaticEntry that computes the lengths at
@@ -294,7 +293,7 @@
{ name, SPDY_ARRAYSIZE(name) - 1, value, SPDY_ARRAYSIZE(value) - 1 }
const std::vector<HpackStaticEntry>& HpackStaticTableVector() {
- static const std::vector<HpackStaticEntry> kHpackStaticTable = {
+ static const auto* kHpackStaticTable = new std::vector<HpackStaticEntry>{
STATIC_ENTRY(":authority", ""), // 1
STATIC_ENTRY(":method", "GET"), // 2
STATIC_ENTRY(":method", "POST"), // 3
@@ -357,7 +356,7 @@
STATIC_ENTRY("via", ""), // 60
STATIC_ENTRY("www-authenticate", ""), // 61
};
- return kHpackStaticTable;
+ return *kHpackStaticTable;
}
#undef STATIC_ENTRY
diff --git a/spdy/core/hpack/hpack_decoder_adapter.cc b/spdy/core/hpack/hpack_decoder_adapter.cc
index 77ff703..309af39 100644
--- a/spdy/core/hpack/hpack_decoder_adapter.cc
+++ b/spdy/core/hpack/hpack_decoder_adapter.cc
@@ -7,6 +7,7 @@
#include "base/logging.h"
#include "net/third_party/quiche/src/http2/decoder/decode_buffer.h"
#include "net/third_party/quiche/src/http2/decoder/decode_status.h"
+#include "net/third_party/quiche/src/spdy/platform/api/spdy_estimate_memory_usage.h"
using ::http2::DecodeBuffer;
using ::http2::HpackEntryType;
@@ -107,6 +108,10 @@
hpack_decoder_.set_max_string_size_bytes(max_decode_buffer_size_bytes);
}
+size_t HpackDecoderAdapter::EstimateMemoryUsage() const {
+ return SpdyEstimateMemoryUsage(hpack_decoder_);
+}
+
HpackDecoderAdapter::ListenerAdapter::ListenerAdapter() : handler_(nullptr) {}
HpackDecoderAdapter::ListenerAdapter::~ListenerAdapter() = default;
diff --git a/spdy/core/hpack/hpack_decoder_adapter.h b/spdy/core/hpack/hpack_decoder_adapter.h
index 3f2ba88..b497fe7 100644
--- a/spdy/core/hpack/hpack_decoder_adapter.h
+++ b/spdy/core/hpack/hpack_decoder_adapter.h
@@ -80,6 +80,8 @@
// of individual transport buffers.
void set_max_decode_buffer_size_bytes(size_t max_decode_buffer_size_bytes);
+ size_t EstimateMemoryUsage() const;
+
private:
class SPDY_EXPORT_PRIVATE ListenerAdapter
: public http2::HpackDecoderListener,
diff --git a/spdy/core/hpack/hpack_decoder_adapter_test.cc b/spdy/core/hpack/hpack_decoder_adapter_test.cc
index bef5c65..765c2ea 100644
--- a/spdy/core/hpack/hpack_decoder_adapter_test.cc
+++ b/spdy/core/hpack/hpack_decoder_adapter_test.cc
@@ -6,16 +6,19 @@
// Tests of HpackDecoderAdapter.
+#include <stdint.h>
+
+#include <tuple>
#include <utility>
#include <vector>
#include "base/logging.h"
#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/base/public/googletest.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_state.h"
#include "net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_tables.h"
#include "net/third_party/quiche/src/http2/hpack/tools/hpack_block_builder.h"
+#include "net/third_party/quiche/src/http2/test_tools/http2_random.h"
#include "net/third_party/quiche/src/spdy/core/hpack/hpack_constants.h"
#include "net/third_party/quiche/src/spdy/core/hpack/hpack_encoder.h"
#include "net/third_party/quiche/src/spdy/core/hpack/hpack_output_stream.h"
@@ -23,12 +26,12 @@
#include "net/third_party/quiche/src/spdy/platform/api/spdy_arraysize.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_string.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_string_utils.h"
-#include "util/random/mt_random.h"
using ::http2::HpackEntryType;
using ::http2::HpackString;
using ::http2::HpackStringPair;
using ::http2::test::HpackBlockBuilder;
+using ::http2::test::HpackDecoderPeer;
using ::testing::ElementsAre;
using ::testing::Pair;
@@ -58,8 +61,6 @@
namespace spdy {
namespace test {
-using ::http2::test::HpackDecoderPeer;
-
class HpackDecoderAdapterPeer {
public:
explicit HpackDecoderAdapterPeer(HpackDecoderAdapter* decoder)
@@ -112,14 +113,8 @@
class HpackDecoderAdapterTest
: public ::testing::TestWithParam<std::tuple<StartChoice, bool>> {
- public:
- static void SetUpTestCase() {
- LOG(INFO) << "Flag --test_random_seed=" << FLAGS_test_random_seed;
- }
-
protected:
- HpackDecoderAdapterTest()
- : random_(FLAGS_test_random_seed), decoder_(), decoder_peer_(&decoder_) {}
+ HpackDecoderAdapterTest() : decoder_(), decoder_peer_(&decoder_) {}
void SetUp() override {
std::tie(start_choice_, randomly_split_input_buffer_) = GetParam();
@@ -254,7 +249,7 @@
return result;
}
- MTRandom random_;
+ http2::test::Http2Random random_;
HpackDecoderAdapter decoder_;
test::HpackDecoderAdapterPeer decoder_peer_;
TestHeadersHandler handler_;
@@ -407,13 +402,14 @@
decoder_.HandleControlFrameHeadersComplete(nullptr);
// Resulting decoded headers are in the same order as the inputs.
- EXPECT_THAT(decoded_block(),
- ElementsAre(Pair("cookie", " part 1; part 2 ; part3; fin!"),
- Pair("passed-through", SpdyString("foo\0baz", 7)),
- Pair("joined", "not joined"),
- Pair("joineD", SpdyString("value 1\0value 2", 15)),
- Pair("empty", ""),
- Pair("empty-joined", SpdyString("\0foo\0\0", 6))));
+ EXPECT_THAT(
+ decoded_block(),
+ ElementsAre(Pair("cookie", " part 1; part 2 ; part3; fin!"),
+ Pair("passed-through", SpdyStringPiece("foo\0baz", 7)),
+ Pair("joined", "not joined"),
+ Pair("joineD", SpdyStringPiece("value 1\0value 2", 15)),
+ Pair("empty", ""),
+ Pair("empty-joined", SpdyStringPiece("\0foo\0\0", 6))));
}
// Decoding indexed static table field should work.
@@ -678,8 +674,7 @@
SpdyString first = SpdyHexDecode("418cf1e3c2e5f23a6ba0ab90f4ff");
EXPECT_TRUE(DecodeHeaderBlock(first));
- first[1] = 0x8d;
- first.push_back(0xff);
+ first = SpdyHexDecode("418df1e3c2e5f23a6ba0ab90f4ffff");
EXPECT_FALSE(DecodeHeaderBlock(first));
}
@@ -705,8 +700,9 @@
// RFC 7541, Section C.4: Request Examples with Huffman Coding
// http://httpwg.org/specs/rfc7541.html#rfc.section.C.4
TEST_P(HpackDecoderAdapterTest, SectionC4RequestHuffmanExamples) {
- // TODO(jamessynge): Use gfe/http2/hpack/tools/hpack_example.h to parse the
+ // TODO(jamessynge): Use http2/hpack/tools/hpack_example.h to parse the
// example directly, instead of having it as a comment.
+ //
// 82 | == Indexed - Add ==
// | idx = 2
// | -> :method: GET
diff --git a/spdy/core/hpack/hpack_encoder.cc b/spdy/core/hpack/hpack_encoder.cc
index 7608b06..a9981b9 100644
--- a/spdy/core/hpack/hpack_encoder.cc
+++ b/spdy/core/hpack/hpack_encoder.cc
@@ -12,6 +12,7 @@
#include "net/third_party/quiche/src/spdy/core/hpack/hpack_header_table.h"
#include "net/third_party/quiche/src/spdy/core/hpack/hpack_huffman_table.h"
#include "net/third_party/quiche/src/spdy/core/hpack/hpack_output_stream.h"
+#include "net/third_party/quiche/src/spdy/platform/api/spdy_estimate_memory_usage.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_ptr_util.h"
namespace spdy {
@@ -123,6 +124,12 @@
should_emit_table_size_ = true;
}
+size_t HpackEncoder::EstimateMemoryUsage() const {
+ // |huffman_table_| is a singleton. It's accounted for in spdy_session_pool.cc
+ return SpdyEstimateMemoryUsage(header_table_) +
+ SpdyEstimateMemoryUsage(output_stream_);
+}
+
void HpackEncoder::EncodeRepresentations(RepresentationIterator* iter,
SpdyString* output) {
MaybeEmitTableSize();
@@ -228,18 +235,17 @@
if (first == SpdyStringPiece::npos) {
cookie_value = SpdyStringPiece();
} else {
- cookie_value = absl::ClippedSubstr(cookie_value, first, (last - first) + 1);
+ cookie_value = cookie_value.substr(first, (last - first) + 1);
}
for (size_t pos = 0;;) {
size_t end = cookie_value.find(";", pos);
if (end == SpdyStringPiece::npos) {
- out->push_back(
- std::make_pair(cookie.first, absl::ClippedSubstr(cookie_value, pos)));
+ out->push_back(std::make_pair(cookie.first, cookie_value.substr(pos)));
break;
}
- out->push_back(std::make_pair(
- cookie.first, absl::ClippedSubstr(cookie_value, pos, end - pos)));
+ out->push_back(
+ std::make_pair(cookie.first, cookie_value.substr(pos, end - pos)));
// Consume next space if present.
pos = end + 1;
@@ -258,8 +264,8 @@
end = header_field.second.find('\0', pos);
out->push_back(std::make_pair(
header_field.first,
- absl::ClippedSubstr(header_field.second, pos,
- end == SpdyStringPiece::npos ? end : end - pos)));
+ header_field.second.substr(
+ pos, end == SpdyStringPiece::npos ? end : end - pos)));
pos = end + 1;
}
}
diff --git a/spdy/core/hpack/hpack_encoder.h b/spdy/core/hpack/hpack_encoder.h
index 22bed4e..486d536 100644
--- a/spdy/core/hpack/hpack_encoder.h
+++ b/spdy/core/hpack/hpack_encoder.h
@@ -97,6 +97,9 @@
void DisableCompression() { enable_compression_ = false; }
+ // Returns the estimate of dynamically allocated memory in bytes.
+ size_t EstimateMemoryUsage() const;
+
private:
friend class test::HpackEncoderPeer;
diff --git a/spdy/core/hpack/hpack_encoder_test.cc b/spdy/core/hpack/hpack_encoder_test.cc
index e639650..8ead1c2 100644
--- a/spdy/core/hpack/hpack_encoder_test.cc
+++ b/spdy/core/hpack/hpack_encoder_test.cc
@@ -7,12 +7,11 @@
#include <cstdint>
#include <map>
-#include "base/arena.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/absl/random/random.h"
+#include "net/third_party/quiche/src/http2/test_tools/http2_random.h"
#include "net/third_party/quiche/src/spdy/core/hpack/hpack_huffman_table.h"
-#include "util/random/acmrandom.h"
+#include "net/third_party/quiche/src/spdy/platform/api/spdy_unsafe_arena.h"
namespace spdy {
@@ -86,11 +85,11 @@
std::unique_ptr<HpackEncoder::ProgressiveEncoder> encoderator =
encoder->EncodeHeaderSet(header_set);
SpdyString output_buffer;
- ACMRandom random(FLAGS_test_random_seed);
- encoderator->Next(absl::Uniform<uint32_t>(random, 0, 16), &output_buffer);
+ http2::test::Http2Random random;
+ encoderator->Next(random.UniformInRange(0, 16), &output_buffer);
while (encoderator->HasNext()) {
SpdyString second_buffer;
- encoderator->Next(absl::Uniform<uint32_t>(random, 0, 16), &second_buffer);
+ encoderator->Next(random.UniformInRange(0, 16), &second_buffer);
output_buffer.append(second_buffer);
}
*output = std::move(output_buffer);
@@ -201,7 +200,7 @@
const HpackEntry* cookie_a_;
const HpackEntry* cookie_c_;
- UnsafeArena headers_storage_;
+ SpdyUnsafeArena headers_storage_;
std::vector<std::pair<SpdyStringPiece, SpdyStringPiece>> headers_observed_;
HpackOutputStream expected_;
diff --git a/spdy/core/hpack/hpack_entry.h b/spdy/core/hpack/hpack_entry.h
index 2b4c427..28dee47 100644
--- a/spdy/core/hpack/hpack_entry.h
+++ b/spdy/core/hpack/hpack_entry.h
@@ -5,6 +5,7 @@
#ifndef QUICHE_SPDY_CORE_HPACK_HPACK_ENTRY_H_
#define QUICHE_SPDY_CORE_HPACK_HPACK_ENTRY_H_
+#include <cstddef>
#include <cstdint>
#include "base/macros.h"
diff --git a/spdy/core/hpack/hpack_header_table.cc b/spdy/core/hpack/hpack_header_table.cc
index e08ca8f..dbe565f 100644
--- a/spdy/core/hpack/hpack_header_table.cc
+++ b/spdy/core/hpack/hpack_header_table.cc
@@ -9,15 +9,14 @@
#include "base/logging.h"
#include "net/third_party/quiche/src/spdy/core/hpack/hpack_constants.h"
#include "net/third_party/quiche/src/spdy/core/hpack/hpack_static_table.h"
+#include "net/third_party/quiche/src/spdy/platform/api/spdy_containers.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_estimate_memory_usage.h"
-#include "util/hash/hash.h"
namespace spdy {
size_t HpackHeaderTable::EntryHasher::operator()(
const HpackEntry* entry) const {
- return GoodFastHash<std::pair<SpdyStringPiece, SpdyStringPiece>>()(
- std::make_pair(entry->name(), entry->value()));
+ return SpdyHashStringPair(entry->name(), entry->value());
}
bool HpackHeaderTable::EntriesEq::operator()(const HpackEntry* lhs,
diff --git a/spdy/core/hpack/hpack_header_table.h b/spdy/core/hpack/hpack_header_table.h
index 2529551..e85edb7 100644
--- a/spdy/core/hpack/hpack_header_table.h
+++ b/spdy/core/hpack/hpack_header_table.h
@@ -14,8 +14,8 @@
#include "net/third_party/quiche/src/spdy/core/hpack/hpack_entry.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_containers.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_export.h"
+#include "net/third_party/quiche/src/spdy/platform/api/spdy_macros.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_string_piece.h"
-#include "util/hash/hash.h"
// All section references below are to http://tools.ietf.org/html/rfc7541.
@@ -54,10 +54,12 @@
// HpackHeaderTable takes advantage of the deque property that references
// remain valid, so long as insertions & deletions are at the head & tail.
- // If this changes (eg we start to drop entries from the middle of the table),
- // this needs to be a std::list, in which case |*_index_| can be trivially
- // extended to map to list iterators.
- typedef std::deque<HpackEntry> EntryTable;
+ // This precludes the use of base::circular_deque.
+ //
+ // If this changes (we want to change to circular_deque or we start to drop
+ // entries from the middle of the table), this should to be a std::list, in
+ // which case |*_index_| can be trivially extended to map to list iterators.
+ using EntryTable = std::deque<HpackEntry>;
struct SPDY_EXPORT_PRIVATE EntryHasher {
size_t operator()(const HpackEntry* entry) const;
@@ -66,7 +68,8 @@
bool operator()(const HpackEntry* lhs, const HpackEntry* rhs) const;
};
using UnorderedEntrySet = SpdyHashSet<HpackEntry*, EntryHasher, EntriesEq>;
- using NameToEntryMap = SpdyHashMap<SpdyStringPiece, const HpackEntry*>;
+ using NameToEntryMap =
+ SpdyHashMap<SpdyStringPiece, const HpackEntry*, SpdyStringPieceHash>;
HpackHeaderTable();
HpackHeaderTable(const HpackHeaderTable&) = delete;
@@ -117,7 +120,7 @@
// evicted and the empty table is of insufficent size for the representation.
const HpackEntry* TryAddEntry(SpdyStringPiece name, SpdyStringPiece value);
- void DebugLogTableState() const ABSL_ATTRIBUTE_UNUSED;
+ void DebugLogTableState() const SPDY_UNUSED;
void set_debug_visitor(std::unique_ptr<DebugVisitorInterface> visitor) {
debug_visitor_ = std::move(visitor);
diff --git a/spdy/core/hpack/hpack_huffman_table.cc b/spdy/core/hpack/hpack_huffman_table.cc
index 2ff2101..c917767 100644
--- a/spdy/core/hpack/hpack_huffman_table.cc
+++ b/spdy/core/hpack/hpack_huffman_table.cc
@@ -6,10 +6,12 @@
#include <algorithm>
#include <cmath>
+#include <limits>
#include <memory>
#include "base/logging.h"
#include "net/third_party/quiche/src/spdy/core/hpack/hpack_output_stream.h"
+#include "net/third_party/quiche/src/spdy/platform/api/spdy_estimate_memory_usage.h"
namespace spdy {
@@ -35,6 +37,7 @@
bool HpackHuffmanTable::Initialize(const HpackHuffmanSymbol* input_symbols,
size_t symbol_count) {
CHECK(!IsInitialized());
+ DCHECK_LE(symbol_count, std::numeric_limits<uint16_t>::max());
std::vector<Symbol> symbols(symbol_count);
// Validate symbol id sequence, and copy into |symbols|.
@@ -140,4 +143,9 @@
return bit_count / 8;
}
+size_t HpackHuffmanTable::EstimateMemoryUsage() const {
+ return SpdyEstimateMemoryUsage(code_by_id_) +
+ SpdyEstimateMemoryUsage(length_by_id_);
+}
+
} // namespace spdy
diff --git a/spdy/core/hpack/hpack_huffman_table.h b/spdy/core/hpack/hpack_huffman_table.h
index efa5e2d..80d9e52 100644
--- a/spdy/core/hpack/hpack_huffman_table.h
+++ b/spdy/core/hpack/hpack_huffman_table.h
@@ -51,6 +51,9 @@
// Returns the encoded size of the input string.
size_t EncodedSize(SpdyStringPiece in) const;
+ // Returns the estimate of dynamically allocated memory in bytes.
+ size_t EstimateMemoryUsage() const;
+
private:
// Expects symbols ordered on ID ascending.
void BuildEncodeTable(const std::vector<Symbol>& symbols);
diff --git a/spdy/core/hpack/hpack_output_stream.cc b/spdy/core/hpack/hpack_output_stream.cc
index 77fea53..30b5662 100644
--- a/spdy/core/hpack/hpack_output_stream.cc
+++ b/spdy/core/hpack/hpack_output_stream.cc
@@ -7,6 +7,7 @@
#include <utility>
#include "base/logging.h"
+#include "net/third_party/quiche/src/spdy/platform/api/spdy_estimate_memory_usage.h"
namespace spdy {
@@ -89,4 +90,8 @@
}
}
+size_t HpackOutputStream::EstimateMemoryUsage() const {
+ return SpdyEstimateMemoryUsage(buffer_);
+}
+
} // namespace spdy
diff --git a/spdy/core/hpack/hpack_output_stream.h b/spdy/core/hpack/hpack_output_stream.h
index d2a0804..450803f 100644
--- a/spdy/core/hpack/hpack_output_stream.h
+++ b/spdy/core/hpack/hpack_output_stream.h
@@ -59,6 +59,9 @@
// Size in bytes of stream's internal buffer.
size_t size() const { return buffer_.size(); }
+ // Returns the estimate of dynamically allocated memory in bytes.
+ size_t EstimateMemoryUsage() const;
+
private:
// The internal bit buffer.
SpdyString buffer_;
diff --git a/spdy/core/hpack/hpack_round_trip_test.cc b/spdy/core/hpack/hpack_round_trip_test.cc
index 105566a..4b3a848 100644
--- a/spdy/core/hpack/hpack_round_trip_test.cc
+++ b/spdy/core/hpack/hpack_round_trip_test.cc
@@ -8,16 +8,16 @@
#include <vector>
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/absl/random/random.h"
+#include "net/third_party/quiche/src/http2/test_tools/http2_random.h"
#include "net/third_party/quiche/src/spdy/core/hpack/hpack_constants.h"
#include "net/third_party/quiche/src/spdy/core/hpack/hpack_decoder_adapter.h"
#include "net/third_party/quiche/src/spdy/core/hpack/hpack_encoder.h"
#include "net/third_party/quiche/src/spdy/core/spdy_test_utils.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_string.h"
-#include "util/random/mt_random.h"
namespace spdy {
namespace test {
+
namespace {
// Supports testing with the input split at every byte boundary.
@@ -73,7 +73,7 @@
sanity_bound);
}
- MTRandom random_;
+ http2::test::Http2Random random_;
HpackEncoder encoder_;
HpackDecoderAdapter decoder_;
};
@@ -170,10 +170,6 @@
values.push_back("baz=bing; foo=bar; garbage");
values.push_back("baz=bing; fizzle=fazzle; garbage");
- uint32_t seed = absl::Uniform<uint32_t>(random_);
- LOG(INFO) << "Seeding with " << seed << "";
- random_.Reset(seed);
-
for (size_t i = 0; i != 2000; ++i) {
SpdyHeaderBlock headers;
diff --git a/spdy/core/hpack/hpack_static_table.cc b/spdy/core/hpack/hpack_static_table.cc
index f462fa4..14e282e 100644
--- a/spdy/core/hpack/hpack_static_table.cc
+++ b/spdy/core/hpack/hpack_static_table.cc
@@ -7,6 +7,7 @@
#include "base/logging.h"
#include "net/third_party/quiche/src/spdy/core/hpack/hpack_constants.h"
#include "net/third_party/quiche/src/spdy/core/hpack/hpack_entry.h"
+#include "net/third_party/quiche/src/spdy/platform/api/spdy_estimate_memory_usage.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_string_piece.h"
namespace spdy {
@@ -40,4 +41,10 @@
return !static_entries_.empty();
}
+size_t HpackStaticTable::EstimateMemoryUsage() const {
+ return SpdyEstimateMemoryUsage(static_entries_) +
+ SpdyEstimateMemoryUsage(static_index_) +
+ SpdyEstimateMemoryUsage(static_name_index_);
+}
+
} // namespace spdy
diff --git a/spdy/core/hpack/hpack_static_table.h b/spdy/core/hpack/hpack_static_table.h
index 2f2a6dd..f354a12 100644
--- a/spdy/core/hpack/hpack_static_table.h
+++ b/spdy/core/hpack/hpack_static_table.h
@@ -40,6 +40,9 @@
return static_name_index_;
}
+ // Returns the estimate of dynamically allocated memory in bytes.
+ size_t EstimateMemoryUsage() const;
+
private:
HpackHeaderTable::EntryTable static_entries_;
HpackHeaderTable::UnorderedEntrySet static_index_;
diff --git a/spdy/core/hpack/hpack_static_table_test.cc b/spdy/core/hpack/hpack_static_table_test.cc
index c5f8403..4550be0 100644
--- a/spdy/core/hpack/hpack_static_table_test.cc
+++ b/spdy/core/hpack/hpack_static_table_test.cc
@@ -9,7 +9,6 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "net/third_party/quiche/src/spdy/core/hpack/hpack_constants.h"
-#include "net/third_party/quiche/src/spdy/platform/api/spdy_arraysize.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_string_piece.h"
namespace spdy {
diff --git a/spdy/core/http2_frame_decoder_adapter.cc b/spdy/core/http2_frame_decoder_adapter.cc
index 5c05fd1..c4e728d 100644
--- a/spdy/core/http2_frame_decoder_adapter.cc
+++ b/spdy/core/http2_frame_decoder_adapter.cc
@@ -16,7 +16,6 @@
#include <utility>
#include "base/logging.h"
-#include "strings/escaping.h"
#include "net/third_party/quiche/src/http2/decoder/decode_buffer.h"
#include "net/third_party/quiche/src/http2/decoder/decode_status.h"
#include "net/third_party/quiche/src/http2/decoder/http2_frame_decoder.h"
@@ -27,17 +26,16 @@
#include "net/third_party/quiche/src/spdy/core/hpack/hpack_decoder_adapter.h"
#include "net/third_party/quiche/src/spdy/core/hpack/hpack_header_table.h"
#include "net/third_party/quiche/src/spdy/core/spdy_alt_svc_wire_format.h"
-#include "net/third_party/quiche/src/spdy/core/spdy_bug_tracker.h"
#include "net/third_party/quiche/src/spdy/core/spdy_header_block.h"
#include "net/third_party/quiche/src/spdy/core/spdy_headers_handler_interface.h"
#include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"
+#include "net/third_party/quiche/src/spdy/platform/api/spdy_bug_tracker.h"
+#include "net/third_party/quiche/src/spdy/platform/api/spdy_endianness_util.h"
+#include "net/third_party/quiche/src/spdy/platform/api/spdy_estimate_memory_usage.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_flags.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_ptr_util.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_string_utils.h"
-#include "util/endian/endian.h"
-#include "util/gtl/labs/optional.h"
-using absl::nullopt;
using ::spdy::ExtensionVisitorInterface;
using ::spdy::HpackDecoderAdapter;
using ::spdy::HpackHeaderTable;
@@ -45,6 +43,7 @@
using ::spdy::ParseFrameType;
using ::spdy::SpdyAltSvcWireFormat;
using ::spdy::SpdyErrorCode;
+using ::spdy::SpdyEstimateMemoryUsage;
using ::spdy::SpdyFramerDebugVisitorInterface;
using ::spdy::SpdyFramerVisitorInterface;
using ::spdy::SpdyFrameType;
@@ -71,7 +70,7 @@
uint64_t ToSpdyPingId(const Http2PingFields& ping) {
uint64_t v;
std::memcpy(&v, ping.opaque_bytes, Http2PingFields::EncodedSize());
- return gntohll(v);
+ return spdy::SpdyNetToHost64(v);
}
// Overwrites the fields of the header with invalid values, for the purpose
@@ -248,6 +247,13 @@
return latched_probable_http_response_;
}
+size_t Http2DecoderAdapter::EstimateMemoryUsage() const {
+ // Skip |frame_decoder_|, |frame_header_| and |hpack_first_frame_header_| as
+ // they don't allocate.
+ return SpdyEstimateMemoryUsage(alt_svc_origin_) +
+ SpdyEstimateMemoryUsage(alt_svc_value_);
+}
+
// ===========================================================================
// Implementations of the methods declared by Http2FrameDecoderListener.
@@ -354,7 +360,7 @@
if (frame_header().IsEndStream()) {
visitor()->OnStreamEnd(frame_header().stream_id);
}
- opt_pad_length_ = nullopt;
+ opt_pad_length_.reset();
}
void Http2DecoderAdapter::OnHeadersStart(const Http2FrameHeader& header) {
@@ -407,7 +413,7 @@
void Http2DecoderAdapter::OnHeadersEnd() {
DVLOG(1) << "OnHeadersEnd";
CommonHpackFragmentEnd();
- opt_pad_length_ = nullopt;
+ opt_pad_length_.reset();
}
void Http2DecoderAdapter::OnPriorityFrame(const Http2FrameHeader& header,
@@ -521,7 +527,7 @@
void Http2DecoderAdapter::OnPushPromiseEnd() {
DVLOG(1) << "OnPushPromiseEnd";
CommonHpackFragmentEnd();
- opt_pad_length_ = nullopt;
+ opt_pad_length_.reset();
}
void Http2DecoderAdapter::OnPing(const Http2FrameHeader& header,
diff --git a/spdy/core/http2_frame_decoder_adapter.h b/spdy/core/http2_frame_decoder_adapter.h
index b2bf31a..02deafd 100644
--- a/spdy/core/http2_frame_decoder_adapter.h
+++ b/spdy/core/http2_frame_decoder_adapter.h
@@ -11,13 +11,13 @@
#include <memory>
#include "net/third_party/quiche/src/http2/decoder/http2_frame_decoder.h"
+#include "net/third_party/quiche/src/http2/platform/api/http2_optional.h"
#include "net/third_party/quiche/src/spdy/core/hpack/hpack_decoder_adapter.h"
#include "net/third_party/quiche/src/spdy/core/hpack/hpack_header_table.h"
#include "net/third_party/quiche/src/spdy/core/spdy_alt_svc_wire_format.h"
#include "net/third_party/quiche/src/spdy/core/spdy_headers_handler_interface.h"
#include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_string_piece.h"
-#include "util/gtl/labs/optional.h"
namespace spdy {
@@ -137,6 +137,9 @@
// has responded with an HTTP/1.1 (or earlier) response.
bool probable_http_response() const;
+ // Returns the estimate of dynamically allocated memory in bytes.
+ size_t EstimateMemoryUsage() const;
+
spdy::HpackDecoderAdapter* GetHpackDecoder();
bool HasError() const;
@@ -242,7 +245,7 @@
// Amount of trailing padding. Currently used just as an indicator of whether
// OnPadLength has been called.
- absl::optional<size_t> opt_pad_length_;
+ Http2Optional<size_t> opt_pad_length_;
// Temporary buffers for the AltSvc fields.
Http2String alt_svc_origin_;
diff --git a/spdy/core/priority_write_scheduler.h b/spdy/core/priority_write_scheduler.h
index 25f8b49..d5c3c44 100644
--- a/spdy/core/priority_write_scheduler.h
+++ b/spdy/core/priority_write_scheduler.h
@@ -6,16 +6,19 @@
#define QUICHE_SPDY_CORE_PRIORITY_WRITE_SCHEDULER_H_
#include <algorithm>
+#include <cstddef>
#include <cstdint>
-#include <deque>
#include <tuple>
#include <unordered_map>
#include <utility>
+#include <vector>
#include "base/logging.h"
-#include "net/third_party/quiche/src/spdy/core/spdy_bug_tracker.h"
+#include "net/third_party/quiche/src/http2/platform/api/http2_containers.h"
#include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"
#include "net/third_party/quiche/src/spdy/core/write_scheduler.h"
+#include "net/third_party/quiche/src/spdy/platform/api/spdy_bug_tracker.h"
+#include "net/third_party/quiche/src/spdy/platform/api/spdy_macros.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_string.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_string_utils.h"
@@ -52,7 +55,8 @@
// parent_id not used here, but may as well validate it. However,
// parent_id may legitimately not be registered yet--see b/15676312.
StreamIdType parent_id = precedence.parent_id();
- VLOG_IF(1, parent_id != kHttp2RootStreamId && !StreamRegistered(parent_id))
+ SPDY_DVLOG_IF(
+ 1, parent_id != kHttp2RootStreamId && !StreamRegistered(parent_id))
<< "Parent stream " << parent_id << " not registered";
if (stream_id == kHttp2RootStreamId) {
@@ -88,7 +92,7 @@
StreamIdType stream_id) const override {
auto it = stream_infos_.find(stream_id);
if (it == stream_infos_.end()) {
- VLOG(1) << "Stream " << stream_id << " not registered";
+ DVLOG(1) << "Stream " << stream_id << " not registered";
return StreamPrecedenceType(kV3LowestPriority);
}
return StreamPrecedenceType(it->second.priority);
@@ -102,13 +106,14 @@
// parent_id not used here, but may as well validate it. However,
// parent_id may legitimately not be registered yet--see b/15676312.
StreamIdType parent_id = precedence.parent_id();
- VLOG_IF(1, parent_id != kHttp2RootStreamId && !StreamRegistered(parent_id))
+ SPDY_DVLOG_IF(
+ 1, parent_id != kHttp2RootStreamId && !StreamRegistered(parent_id))
<< "Parent stream " << parent_id << " not registered";
auto it = stream_infos_.find(stream_id);
if (it == stream_infos_.end()) {
// TODO(mpw): add to stream_infos_ on demand--see b/15676312.
- VLOG(1) << "Stream " << stream_id << " not registered";
+ DVLOG(1) << "Stream " << stream_id << " not registered";
return;
}
StreamInfo& stream_info = it->second;
@@ -278,8 +283,8 @@
bool ready;
};
- // 0(1) size lookup, 0(1) insert at front or back.
- typedef std::deque<StreamInfo*> ReadyList;
+ // O(1) size lookup, O(1) insert at front or back (amortized).
+ using ReadyList = http2::Http2Deque<StreamInfo*>;
// State kept for each priority level.
struct PriorityInfo {
diff --git a/spdy/core/priority_write_scheduler_test.cc b/spdy/core/priority_write_scheduler_test.cc
index 127ab17..a285cb2 100644
--- a/spdy/core/priority_write_scheduler_test.cc
+++ b/spdy/core/priority_write_scheduler_test.cc
@@ -4,9 +4,7 @@
#include "net/third_party/quiche/src/spdy/core/priority_write_scheduler.h"
-#include "testing/base/public/benchmark.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/base/public/test_utils.h"
#include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"
#include "net/third_party/quiche/src/spdy/core/spdy_test_utils.h"
@@ -203,7 +201,7 @@
EXPECT_SPDY_BUG(scheduler_.MarkStreamReady(1, false),
"Stream 1 not registered");
EXPECT_FALSE(scheduler_.HasReadyStreams());
- EXPECT_SPDY_BUG(EXPECT_EQ(0, scheduler_.PopNextReadyStream()),
+ EXPECT_SPDY_BUG(EXPECT_EQ(0u, scheduler_.PopNextReadyStream()),
"No ready streams available");
// Add a bunch of ready streams to tail of per-priority lists.
diff --git a/spdy/core/spdy_alt_svc_wire_format.h b/spdy/core/spdy_alt_svc_wire_format.h
index 5e12ead..ac834bc 100644
--- a/spdy/core/spdy_alt_svc_wire_format.h
+++ b/spdy/core/spdy_alt_svc_wire_format.h
@@ -13,11 +13,10 @@
#include <cstdint>
#include <vector>
-#include "third_party/absl/container/inlined_vector.h"
+#include "net/third_party/quiche/src/spdy/platform/api/spdy_containers.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_export.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_string.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_string_piece.h"
-#include "util/gtl/inlined_vector.h"
namespace spdy {
@@ -27,11 +26,12 @@
class SPDY_EXPORT_PRIVATE SpdyAltSvcWireFormat {
public:
- using VersionVector = absl::InlinedVector<uint32_t, 8>;
+ using VersionVector = SpdyInlinedVector<uint32_t, 8>;
struct SPDY_EXPORT_PRIVATE AlternativeService {
SpdyString protocol_id;
SpdyString host;
+
// Default is 0: invalid port.
uint16_t port = 0;
// Default is one day.
diff --git a/spdy/core/spdy_alt_svc_wire_format_test.cc b/spdy/core/spdy_alt_svc_wire_format_test.cc
index e145b83..c2595f0 100644
--- a/spdy/core/spdy_alt_svc_wire_format_test.cc
+++ b/spdy/core/spdy_alt_svc_wire_format_test.cc
@@ -6,7 +6,7 @@
#include "base/logging.h"
#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/base/public/test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
namespace spdy {
diff --git a/spdy/core/spdy_bug_tracker.h b/spdy/core/spdy_bug_tracker.h
deleted file mode 100644
index 06e3204..0000000
--- a/spdy/core/spdy_bug_tracker.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright (c) 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef QUICHE_SPDY_CORE_SPDY_BUG_TRACKER_H_
-#define QUICHE_SPDY_CORE_SPDY_BUG_TRACKER_H_
-
-// Defined in Blaze when targetting non-production platforms (iOS, Android, etc)
-// The fallback implimentation is the same as in Chromium which simply delegates
-// to LOG(DFATAL) which is part of PG3.
-#if SPDY_GENERIC_BUG
-
-#define SPDY_BUG LOG(DFATAL)
-#define SPDY_BUG_IF(condition) LOG_IF(DFATAL, condition)
-#define FLAGS_spdy_always_log_bugs_for_tests true
-
-#else
-
-#include "gfe/gfe2/base/bug_utils.h"
-
-// For external SPDY, SPDY_BUG should be #defined to LOG(DFATAL) and
-// SPDY_BUG_IF(condition) to LOG_IF(DFATAL, condition) as client-side log rate
-// limiting is less important and chrome doesn't LOG_FIRST_N anyway.
-//
-// This file should change infrequently if ever, so update cost should be
-// minimal. Meanwhile we do want different macros so we can rate limit server
-// side, so the google3 shared code increments GFE varz, and chrome can have its
-// own custom hooks.
-#define SPDY_BUG GFE_BUG
-#define SPDY_BUG_IF GFE_BUG_IF
-#define FLAGS_spdy_always_log_bugs_for_tests FLAGS_gfe_always_log_bug_for_tests
-
-#endif // __ANDROID__
-
-#endif // QUICHE_SPDY_CORE_SPDY_BUG_TRACKER_H_
diff --git a/spdy/core/spdy_deframer_visitor.cc b/spdy/core/spdy_deframer_visitor.cc
index 8a30f79..76188e9 100644
--- a/spdy/core/spdy_deframer_visitor.cc
+++ b/spdy/core/spdy_deframer_visitor.cc
@@ -7,13 +7,13 @@
#include <stdlib.h>
#include <algorithm>
+#include <cstdint>
#include <limits>
#include <memory>
-#include "base/log_severity.h"
#include "base/logging.h"
-#include "strings/cord.h"
#include "testing/gmock/include/gmock/gmock.h"
+#include "net/third_party/quiche/src/http2/platform/api/http2_macros.h"
#include "net/third_party/quiche/src/spdy/core/hpack/hpack_constants.h"
#include "net/third_party/quiche/src/spdy/core/mock_spdy_framer_visitor.h"
#include "net/third_party/quiche/src/spdy/core/spdy_frame_reader.h"
@@ -35,7 +35,7 @@
enum class HeaderDirection { REQUEST, RESPONSE };
// Types of HTTP/2 frames, per RFC 7540.
-// TODO(jamessynge): Switch to using //gfe/http2/http2_constants.h when ready.
+// TODO(jamessynge): Switch to using http2/http2_constants.h when ready.
enum Http2FrameType {
DATA = 0,
HEADERS = 1,
@@ -54,7 +54,7 @@
UNKNOWN = -2,
};
-// TODO(jamessynge): Switch to using //gfe/http2/http2_constants.h when ready.
+// TODO(jamessynge): Switch to using http2/http2_constants.h when ready.
const char* Http2FrameTypeToString(Http2FrameType v) {
switch (v) {
case DATA:
@@ -88,7 +88,7 @@
}
}
-// TODO(jamessynge): Switch to using //gfe/http2/http2_constants.h when ready.
+// TODO(jamessynge): Switch to using http2/http2_constants.h when ready.
inline std::ostream& operator<<(std::ostream& out, Http2FrameType v) {
return out << Http2FrameTypeToString(v);
}
@@ -97,7 +97,7 @@
// (see https://httpwg.github.io/specs/rfc7540.html#FrameHeader for details on
// the fixed 9-octet header structure shared by all frames).
// Flag bits are only valid for specified frame types.
-// TODO(jamessynge): Switch to using //gfe/http2/http2_constants.h when ready.
+// TODO(jamessynge): Switch to using http2/http2_constants.h when ready.
enum Http2HeaderFlag {
NO_FLAGS = 0,
@@ -109,7 +109,7 @@
};
// Returns name of frame type.
-// TODO(jamessynge): Switch to using //gfe/http2/http2_constants.h when ready.
+// TODO(jamessynge): Switch to using http2/http2_constants.h when ready.
const char* Http2FrameTypeToString(Http2FrameType v);
void SpdyDeframerVisitorInterface::OnPingAck(
@@ -268,7 +268,7 @@
void SpdyTestDeframerImpl::AtGoAwayEnd() {
DVLOG(1) << "AtDataEnd";
CHECK_EQ(frame_type_, GOAWAY);
- if (ABSL_DIE_IF_NULL(goaway_description_)->empty()) {
+ if (HTTP2_DIE_IF_NULL(goaway_description_)->empty()) {
listener_->OnGoAway(std::move(goaway_ir_));
} else {
listener_->OnGoAway(SpdyMakeUnique<SpdyGoAwayIR>(
@@ -751,7 +751,7 @@
CHECK(frame_type_ == HEADERS || frame_type_ == PUSH_PROMISE)
<< " frame_type_=" << Http2FrameTypeToString(frame_type_);
CHECK(headers_ != nullptr);
- CHECK_EQ(headers_->size(), 0u);
+ CHECK_EQ(0u, headers_->size());
got_hpack_end_ = false;
}
@@ -761,8 +761,8 @@
frame_type_ == PUSH_PROMISE)
<< " frame_type_=" << Http2FrameTypeToString(frame_type_);
CHECK(!got_hpack_end_);
- ABSL_DIE_IF_NULL(headers_)->emplace_back(SpdyString(key), SpdyString(value));
- ABSL_DIE_IF_NULL(headers_handler_)->OnHeader(key, value);
+ HTTP2_DIE_IF_NULL(headers_)->emplace_back(SpdyString(key), SpdyString(value));
+ HTTP2_DIE_IF_NULL(headers_handler_)->OnHeader(key, value);
}
void SpdyTestDeframerImpl::OnHeaderBlockEnd(
@@ -896,11 +896,11 @@
return *this;
}
-::testing::AssertionResult CollectedFrame::VerifyHasHeaders(
+AssertionResult CollectedFrame::VerifyHasHeaders(
const StringPairVector& expected_headers) const {
VERIFY_NE(headers.get(), nullptr);
VERIFY_THAT(*headers, ::testing::ContainerEq(expected_headers));
- return ::testing::AssertionSuccess();
+ return AssertionSuccess();
}
AssertionResult CollectedFrame::VerifyHasSettings(
@@ -912,7 +912,7 @@
DeframerCallbackCollector::DeframerCallbackCollector(
std::vector<CollectedFrame>* collected_frames)
- : collected_frames_(ABSL_DIE_IF_NULL(collected_frames)) {}
+ : collected_frames_(HTTP2_DIE_IF_NULL(collected_frames)) {}
void DeframerCallbackCollector::OnAltSvc(
std::unique_ptr<SpdyAltSvcIR> frame_ir) {
diff --git a/spdy/core/spdy_deframer_visitor.h b/spdy/core/spdy_deframer_visitor.h
index 6d57ffd..50d9987 100644
--- a/spdy/core/spdy_deframer_visitor.h
+++ b/spdy/core/spdy_deframer_visitor.h
@@ -111,7 +111,7 @@
virtual ~SpdyDeframerVisitorInterface() {}
// Wrap a visitor in another SpdyDeframerVisitorInterface that will
- // VLOG each call, and will then forward the calls to the wrapped visitor
+ // DVLOG each call, and will then forward the calls to the wrapped visitor
// (if provided; nullptr is OK). Takes ownership of the wrapped visitor.
static std::unique_ptr<SpdyDeframerVisitorInterface> LogBeforeVisiting(
std::unique_ptr<SpdyDeframerVisitorInterface> wrapped_visitor);
@@ -195,8 +195,7 @@
typename X =
typename std::enable_if<std::is_base_of<SpdyFrameIR, T>::value>>
::testing::AssertionResult VerifyHasFrame(const T& expected_ir) const {
- VERIFY_SUCCESS(VerifySpdyFrameIREquals(expected_ir, frame_ir.get()));
- return ::testing::AssertionSuccess();
+ return VerifySpdyFrameIREquals(expected_ir, frame_ir.get());
}
// Compare the collected headers against a StringPairVector. Ignores
diff --git a/spdy/core/spdy_deframer_visitor_test.cc b/spdy/core/spdy_deframer_visitor_test.cc
index e1accec..ede1a20 100644
--- a/spdy/core/spdy_deframer_visitor_test.cc
+++ b/spdy/core/spdy_deframer_visitor_test.cc
@@ -8,14 +8,10 @@
#include <algorithm>
#include <limits>
-#include <memory>
-#include <utility>
-#include "base/log_severity.h"
#include "base/logging.h"
-#include "strings/cord.h"
-#include "testing/base/public/googletest.h" // for FLAGS_test_random_seed
#include "testing/gtest/include/gtest/gtest.h"
+#include "net/third_party/quiche/src/http2/test_tools/http2_random.h"
#include "net/third_party/quiche/src/spdy/core/hpack/hpack_constants.h"
#include "net/third_party/quiche/src/spdy/core/mock_spdy_framer_visitor.h"
#include "net/third_party/quiche/src/spdy/core/spdy_frame_builder.h"
@@ -25,7 +21,6 @@
#include "net/third_party/quiche/src/spdy/core/spdy_protocol_test_utils.h"
#include "net/third_party/quiche/src/spdy/core/spdy_test_utils.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_ptr_util.h"
-#include "util/random/mt_random.h"
namespace spdy {
namespace test {
@@ -33,11 +28,7 @@
class SpdyDeframerVisitorTest : public ::testing::Test {
protected:
- SpdyDeframerVisitorTest()
- : encoder_(SpdyFramer::ENABLE_COMPRESSION),
- random_(FLAGS_test_random_seed) {
- DLOG(INFO) << "Random seed (--test_random_seed): "
- << FLAGS_test_random_seed;
+ SpdyDeframerVisitorTest() : encoder_(SpdyFramer::ENABLE_COMPRESSION) {
decoder_.set_process_single_input_frame(true);
auto collector =
SpdyMakeUnique<DeframerCallbackCollector>(&collected_frames_);
@@ -77,7 +68,7 @@
std::unique_ptr<SpdyTestDeframer> deframer_;
private:
- MTRandom random_;
+ http2::test::Http2Random random_;
};
TEST_F(SpdyDeframerVisitorTest, DataFrame) {
@@ -161,12 +152,12 @@
TEST_F(SpdyDeframerVisitorTest, PriorityFrame) {
const char kFrameData[] = {
- 0x00, 0x00, 0x05, // Length: 5
- 0x02, // Type: PRIORITY
- 0x00, // Flags: none
- 0x00, 0x00, 0x00, 0x65, // Stream: 101
- 0x80, 0x00, 0x00, 0x01, // Parent: 1 (Exclusive)
- 0x10, // Weight: 17
+ 0x00, 0x00, 0x05, // Length: 5
+ 0x02, // Type: PRIORITY
+ 0x00, // Flags: none
+ 0x00, 0x00, 0x00, 0x65, // Stream: 101
+ '\x80', 0x00, 0x00, 0x01, // Parent: 1 (Exclusive)
+ 0x10, // Weight: 17
};
EXPECT_TRUE(DeframeInput(kFrameData, sizeof kFrameData));
@@ -194,14 +185,14 @@
// values. The last one will be in the decoded SpdySettingsIR, but the vector
// of settings will have both, in the same order.
const char kFrameData[] = {
- 0x00, 0x00, 0x0c, // Length
- 0x04, // Type (SETTINGS)
- 0x00, // Flags
- 0x00, 0x00, 0x00, 0x00, // Stream id (must be zero)
- 0x00, 0x04, // Setting id (SETTINGS_INITIAL_WINDOW_SIZE)
- 0x0a, 0x0b, 0x0c, 0x0d, // Setting value
- 0x00, 0x04, // Setting id (SETTINGS_INITIAL_WINDOW_SIZE)
- 0x00, 0x00, 0x00, 0xff, // Setting value
+ 0x00, 0x00, 0x0c, // Length
+ 0x04, // Type (SETTINGS)
+ 0x00, // Flags
+ 0x00, 0x00, 0x00, 0x00, // Stream id (must be zero)
+ 0x00, 0x04, // Setting id (SETTINGS_INITIAL_WINDOW_SIZE)
+ 0x0a, 0x0b, 0x0c, 0x0d, // Setting value
+ 0x00, 0x04, // Setting id (SETTINGS_INITIAL_WINDOW_SIZE)
+ 0x00, 0x00, 0x00, '\xff', // Setting value
};
EXPECT_TRUE(DeframeInput(kFrameData, sizeof kFrameData));
diff --git a/spdy/core/spdy_frame_builder.cc b/spdy/core/spdy_frame_builder.cc
index 4a3753b..a056b70 100644
--- a/spdy/core/spdy_frame_builder.cc
+++ b/spdy/core/spdy_frame_builder.cc
@@ -10,9 +10,9 @@
#include <new>
#include "base/logging.h"
-#include "net/third_party/quiche/src/spdy/core/spdy_bug_tracker.h"
#include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"
#include "net/third_party/quiche/src/spdy/core/zero_copy_output_buffer.h"
+#include "net/third_party/quiche/src/spdy/platform/api/spdy_bug_tracker.h"
namespace spdy {
@@ -90,7 +90,7 @@
uint8_t raw_frame_type = SerializeFrameType(type);
DCHECK(IsDefinedFrameType(raw_frame_type));
DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
- SPDY_BUG_IF(length > spdy::kHttp2DefaultFramePayloadLimit)
+ SPDY_BUG_IF(length > kHttp2DefaultFramePayloadLimit)
<< "Frame length " << length_ << " is longer than frame size limit.";
return BeginNewFrameInternal(raw_frame_type, flags, stream_id, length);
}
diff --git a/spdy/core/spdy_frame_builder.h b/spdy/core/spdy_frame_builder.h
index e0a853c..c569c8c 100644
--- a/spdy/core/spdy_frame_builder.h
+++ b/spdy/core/spdy_frame_builder.h
@@ -5,17 +5,17 @@
#ifndef QUICHE_SPDY_CORE_SPDY_FRAME_BUILDER_H_
#define QUICHE_SPDY_CORE_SPDY_FRAME_BUILDER_H_
+#include <cstddef>
#include <cstdint>
#include <memory>
-#include "base/logging.h"
-#include "testing/production_stub/public/gunit_prod.h"
-#include "net/third_party/quiche/src/spdy/core/spdy_bug_tracker.h"
#include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"
#include "net/third_party/quiche/src/spdy/core/zero_copy_output_buffer.h"
+#include "net/third_party/quiche/src/spdy/platform/api/spdy_bug_tracker.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_endianness_util.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_export.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_string_piece.h"
+#include "net/third_party/quiche/src/spdy/platform/api/spdy_test_utils_prod.h"
namespace spdy {
@@ -88,23 +88,22 @@
return WriteBytes(reinterpret_cast<char*>(&value) + 1, sizeof(value) - 1);
}
bool WriteUInt32(uint32_t value) {
- value = htonl(value);
+ value = SpdyHostToNet32(value);
return WriteBytes(&value, sizeof(value));
}
bool WriteUInt64(uint64_t value) {
- uint32_t upper = htonl(value >> 32);
- uint32_t lower = htonl(static_cast<uint32_t>(value));
+ uint32_t upper = SpdyHostToNet32(static_cast<uint32_t>(value >> 32));
+ uint32_t lower = SpdyHostToNet32(static_cast<uint32_t>(value));
return (WriteBytes(&upper, sizeof(upper)) &&
WriteBytes(&lower, sizeof(lower)));
}
bool WriteStringPiece32(const SpdyStringPiece value);
-
bool WriteBytes(const void* data, uint32_t data_len);
private:
- FRIEND_TEST(SpdyFrameBuilderTest, GetWritableBuffer);
- FRIEND_TEST(SpdyFrameBuilderTest, GetWritableOutput);
- FRIEND_TEST(SpdyFrameBuilderTest, GetWritableOutputNegative);
+ SPDY_FRIEND_TEST(SpdyFrameBuilderTest, GetWritableBuffer);
+ SPDY_FRIEND_TEST(SpdyFrameBuilderTest, GetWritableOutput);
+ SPDY_FRIEND_TEST(SpdyFrameBuilderTest, GetWritableOutputNegative);
// Populates this frame with a HTTP2 frame prefix with type and length
// information.
diff --git a/spdy/core/spdy_frame_reader.h b/spdy/core/spdy_frame_reader.h
index 3ef69ea..dc6c064 100644
--- a/spdy/core/spdy_frame_reader.h
+++ b/spdy/core/spdy_frame_reader.h
@@ -7,7 +7,6 @@
#include <cstdint>
-#include "base/basictypes.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_export.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_string_piece.h"
diff --git a/spdy/core/spdy_frame_reader_test.cc b/spdy/core/spdy_frame_reader_test.cc
index ad8c824..8caf60f 100644
--- a/spdy/core/spdy_frame_reader_test.cc
+++ b/spdy/core/spdy_frame_reader_test.cc
@@ -3,9 +3,9 @@
// found in the LICENSE file.
#include "net/third_party/quiche/src/spdy/core/spdy_frame_reader.h"
+
#include <cstdint>
-#include "base/macros.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_arraysize.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_endianness_util.h"
@@ -37,7 +37,7 @@
// Frame data in network byte order.
const uint32_t kFrameData[] = {
SpdyHostToNet32(1),
- SpdyHostToNet32(static_cast<uint32_t>(1) << 31),
+ SpdyHostToNet32(0x80000000),
};
SpdyFrameReader frame_reader(reinterpret_cast<const char*>(kFrameData),
diff --git a/spdy/core/spdy_framer.cc b/spdy/core/spdy_framer.cc
index 7d60d84..fc9cc2e 100644
--- a/spdy/core/spdy_framer.cc
+++ b/spdy/core/spdy_framer.cc
@@ -10,21 +10,16 @@
#include <list>
#include <new>
-#include "base/casts.h"
-#include "base/commandlineflags.h"
#include "base/logging.h"
-#include "base/macros.h"
-#include "gfe/gfe2/base/flag_utils.h"
-#include "strings/ascii_ctype.h"
-#include "third_party/absl/strings/case.h"
+#include "net/third_party/quiche/src/http2/platform/api/http2_macros.h"
#include "net/third_party/quiche/src/spdy/core/hpack/hpack_constants.h"
#include "net/third_party/quiche/src/spdy/core/spdy_bitmasks.h"
-#include "net/third_party/quiche/src/spdy/core/spdy_bug_tracker.h"
#include "net/third_party/quiche/src/spdy/core/spdy_frame_builder.h"
#include "net/third_party/quiche/src/spdy/core/spdy_frame_reader.h"
+#include "net/third_party/quiche/src/spdy/platform/api/spdy_bug_tracker.h"
+#include "net/third_party/quiche/src/spdy/platform/api/spdy_estimate_memory_usage.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_ptr_util.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_string_utils.h"
-#include "util/gtl/lazy_static_ptr.h"
namespace spdy {
@@ -134,7 +129,7 @@
}
if (!ret) {
- DLOG(INFO) << "Failed to build HEADERS. Not enough space in output";
+ DLOG(WARNING) << "Failed to build HEADERS. Not enough space in output";
}
return ret;
}
@@ -427,7 +422,7 @@
}
case SpdyFrameType::DATA: {
DVLOG(1) << "Serialize a stream end DATA frame for VTL";
- ABSL_FALLTHROUGH_INTENDED;
+ HTTP2_FALLTHROUGH;
}
default: {
return SpdyMakeUnique<SpdyControlFrameIterator>(framer,
@@ -1293,4 +1288,8 @@
GetHpackEncoder()->SetHeaderTableDebugVisitor(std::move(visitor));
}
+size_t SpdyFramer::EstimateMemoryUsage() const {
+ return SpdyEstimateMemoryUsage(hpack_encoder_);
+}
+
} // namespace spdy
diff --git a/spdy/core/spdy_framer.h b/spdy/core/spdy_framer.h
index 9c59642..e268994 100644
--- a/spdy/core/spdy_framer.h
+++ b/spdy/core/spdy_framer.h
@@ -220,6 +220,9 @@
// Get (and lazily initialize) the HPACK encoder state.
HpackEncoder* GetHpackEncoder();
+ // Returns the estimate of dynamically allocated memory in bytes.
+ size_t EstimateMemoryUsage() const;
+
protected:
friend class test::SpdyFramerPeer;
friend class test::SpdyFramerTest_MultipleContinuationFramesWithIterator_Test;
diff --git a/spdy/core/spdy_framer_test.cc b/spdy/core/spdy_framer_test.cc
index 163a769..a08d7d7 100644
--- a/spdy/core/spdy_framer_test.cc
+++ b/spdy/core/spdy_framer_test.cc
@@ -12,14 +12,10 @@
#include <tuple>
#include <vector>
-#include "base/log_severity.h"
#include "base/logging.h"
#include "base/macros.h"
-#include "strings/cord.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/base/public/mock-log.h"
-#include "testing/base/public/test_utils.h"
#include "net/third_party/quiche/src/spdy/core/array_output_buffer.h"
#include "net/third_party/quiche/src/spdy/core/hpack/hpack_constants.h"
#include "net/third_party/quiche/src/spdy/core/mock_spdy_framer_visitor.h"
@@ -51,8 +47,6 @@
char frame_list_char[buffer_size] = "";
} // namespace
-using ::spdy::operator==;
-
class MockDebugVisitor : public SpdyFramerDebugVisitorInterface {
public:
MOCK_METHOD4(OnSendCompressedFrame,
@@ -120,7 +114,7 @@
SpdyFramer::SpdyHeaderFrameIterator it(framer, CloneSpdyHeadersIR(headers));
while (it.HasNextFrame()) {
size_t size_before = frame_list_buffer.Size();
- EXPECT_GT(it.NextFrame(&frame_list_buffer), 0);
+ EXPECT_GT(it.NextFrame(&frame_list_buffer), 0u);
frame_list.emplace_back(
SpdySerializedFrame(frame_list_buffer.Begin() + size_before,
frame_list_buffer.Size() - size_before, false));
@@ -150,7 +144,7 @@
SpdyFramer::SpdyHeaderFrameIterator it(framer, CloneSpdyHeadersIR(headers));
while (it.HasNextFrame()) {
size_t size_before = frame_list_buffer.Size();
- EXPECT_GT(it.NextFrame(&frame_list_buffer), 0);
+ EXPECT_GT(it.NextFrame(&frame_list_buffer), 0u);
frame_list.emplace_back(
SpdySerializedFrame(frame_list_buffer.Begin() + size_before,
frame_list_buffer.Size() - size_before, false));
@@ -189,7 +183,7 @@
framer, CloneSpdyPushPromiseIR(push_promise));
while (it.HasNextFrame()) {
size_t size_before = frame_list_buffer.Size();
- EXPECT_GT(it.NextFrame(&frame_list_buffer), 0);
+ EXPECT_GT(it.NextFrame(&frame_list_buffer), 0u);
frame_list.emplace_back(
SpdySerializedFrame(frame_list_buffer.Begin() + size_before,
frame_list_buffer.Size() - size_before, false));
@@ -222,7 +216,7 @@
framer, CloneSpdyPushPromiseIR(push_promise));
while (it.HasNextFrame()) {
size_t size_before = frame_list_buffer.Size();
- EXPECT_GT(it.NextFrame(&frame_list_buffer), 0);
+ EXPECT_GT(it.NextFrame(&frame_list_buffer), 0u);
frame_list.emplace_back(
SpdySerializedFrame(frame_list_buffer.Begin() + size_before,
frame_list_buffer.Size() - size_before, false));
@@ -579,8 +573,8 @@
// Exposes SpdyUnknownIR::set_length() for testing purposes.
class TestSpdyUnknownIR : public SpdyUnknownIR {
public:
- using SpdyUnknownIR::SpdyUnknownIR;
using SpdyUnknownIR::set_length;
+ using SpdyUnknownIR::SpdyUnknownIR;
};
enum Output { USE, NOT_USE };
@@ -1130,8 +1124,24 @@
reinterpret_cast<unsigned char*>(control_frame.data()),
control_frame.size());
- EXPECT_THAT(visitor.headers_,
- testing::ElementsAre(testing::Pair("name", value)));
+ EXPECT_THAT(visitor.headers_, testing::ElementsAre(testing::Pair(
+ "name", SpdyStringPiece(value))));
+}
+
+TEST_P(SpdyFramerTest, CompressEmptyHeaders) {
+ // See https://crbug.com/172383/
+ SpdyHeadersIR headers(1);
+ headers.SetHeader("server", "SpdyServer 1.0");
+ headers.SetHeader("date", "Mon 12 Jan 2009 12:12:12 PST");
+ headers.SetHeader("status", "200");
+ headers.SetHeader("version", "HTTP/1.1");
+ headers.SetHeader("content-type", "text/html");
+ headers.SetHeader("content-length", "12");
+ headers.SetHeader("x-empty-header", "");
+
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
+ SpdySerializedFrame frame1(
+ SpdyFramerPeer::SerializeHeaders(&framer, headers, &output_));
}
TEST_P(SpdyFramerTest, Basic) {
@@ -1539,11 +1549,15 @@
SpdySerializedFrame frame(framer_.SerializeData(data_ir));
CompareFrame(kDescription, frame, kH2FrameData,
SPDY_ARRAYSIZE(kH2FrameData));
+
+ frame = framer_.SerializeDataFrameHeaderWithPaddingLengthField(data_ir);
+ CompareCharArraysWithHexError(
+ kDescription, reinterpret_cast<const unsigned char*>(frame.data()),
+ kDataFrameMinimumSize, kH2FrameData, kDataFrameMinimumSize);
}
{
const char kDescription[] = "Data frame with max stream ID";
- // clang-format on
const unsigned char kH2FrameData[] = {
0x00, 0x00, 0x05, // Length: 5
0x00, // Type: DATA
@@ -1582,7 +1596,6 @@
{
const char kDescription[] = "RST_STREAM frame with max stream ID";
- // clang-format off
const unsigned char kH2FrameData[] = {
0x00, 0x00, 0x04, // Length: 4
0x03, // Type: RST_STREAM
@@ -1764,8 +1777,8 @@
0x00, 0x00, 0x00, 0x00, // Error: NO_ERROR
0x47, 0x41, // Description
};
- SpdyGoAwayIR goaway_ir(/* last_good_stream_id = */ 0,
- ERROR_CODE_NO_ERROR, "GA");
+ SpdyGoAwayIR goaway_ir(/* last_good_stream_id = */ 0, ERROR_CODE_NO_ERROR,
+ "GA");
SpdySerializedFrame frame(framer_.SerializeGoAway(goaway_ir));
if (use_output_) {
ASSERT_TRUE(framer_.SerializeGoAway(goaway_ir, &output_));
@@ -2068,8 +2081,7 @@
if (use_output_) {
output_.Reset();
ASSERT_TRUE(framer_.SerializeWindowUpdate(
- SpdyWindowUpdateIR(/* stream_id = */ 1, /* delta = */ 1),
- &output_));
+ SpdyWindowUpdateIR(/* stream_id = */ 1, /* delta = */ 1), &output_));
frame = SpdySerializedFrame(output_.Begin(), output_.Size(), false);
}
CompareFrame(kDescription, frame, kH2FrameData,
@@ -2094,8 +2106,8 @@
&output_));
frame = SpdySerializedFrame(output_.Begin(), output_.Size(), false);
}
- CompareFrame(
- kDescription, frame, kH2FrameData, SPDY_ARRAYSIZE(kH2FrameData));
+ CompareFrame(kDescription, frame, kH2FrameData,
+ SPDY_ARRAYSIZE(kH2FrameData));
}
{
@@ -2116,8 +2128,8 @@
&output_));
frame = SpdySerializedFrame(output_.Begin(), output_.Size(), false);
}
- CompareFrame(
- kDescription, frame, kH2FrameData, SPDY_ARRAYSIZE(kH2FrameData));
+ CompareFrame(kDescription, frame, kH2FrameData,
+ SPDY_ARRAYSIZE(kH2FrameData));
}
}
@@ -3699,8 +3711,8 @@
EXPECT_EQ(11u, kGetAltSvcFrameMinimumSize);
EXPECT_EQ(9u, kFrameMinimumSize);
- EXPECT_EQ(16384u, spdy::kHttp2DefaultFramePayloadLimit);
- EXPECT_EQ(16393u, spdy::kHttp2DefaultFrameSizeLimit);
+ EXPECT_EQ(16384u, kHttp2DefaultFramePayloadLimit);
+ EXPECT_EQ(16393u, kHttp2DefaultFrameSizeLimit);
}
TEST_P(SpdyFramerTest, StateToStringTest) {
@@ -4145,7 +4157,7 @@
headers_ir.SetHeader("foo", "bar");
SpdySerializedFrame frame0;
if (use_output_) {
- EXPECT_GT(framer.SerializeHeaders(headers_ir, &output_), 0);
+ EXPECT_TRUE(framer.SerializeHeaders(headers_ir, &output_));
frame0 = SpdySerializedFrame(output_.Begin(), output_.Size(), false);
} else {
frame0 = framer.SerializeHeaders(headers_ir);
@@ -4156,7 +4168,7 @@
SpdySerializedFrame frame1;
if (use_output_) {
char* begin = output_.Begin() + output_.Size();
- EXPECT_GT(framer.SerializeContinuation(continuation, &output_), 0);
+ ASSERT_TRUE(framer.SerializeContinuation(continuation, &output_));
frame1 =
SpdySerializedFrame(begin, output_.Size() - frame0.size(), false);
} else {
@@ -4283,7 +4295,8 @@
SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector;
altsvc_vector.push_back(altsvc1);
altsvc_vector.push_back(altsvc2);
- EXPECT_CALL(visitor, OnAltSvc(kStreamId, "o_r|g!n", altsvc_vector));
+ EXPECT_CALL(visitor,
+ OnAltSvc(kStreamId, SpdyStringPiece("o_r|g!n"), altsvc_vector));
SpdyAltSvcIR altsvc_ir(kStreamId);
altsvc_ir.set_origin("o_r|g!n");
@@ -4317,7 +4330,7 @@
SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector;
altsvc_vector.push_back(altsvc1);
altsvc_vector.push_back(altsvc2);
- EXPECT_CALL(visitor, OnAltSvc(kStreamId, "", altsvc_vector));
+ EXPECT_CALL(visitor, OnAltSvc(kStreamId, SpdyStringPiece(""), altsvc_vector));
SpdyAltSvcIR altsvc_ir(kStreamId);
altsvc_ir.add_altsvc(altsvc1);
@@ -4374,6 +4387,7 @@
deframer_.set_visitor(&visitor);
visitor.SimulateInFramer(kFrameDataOriginLenLargerThanFrame,
sizeof(kFrameDataOriginLenLargerThanFrame));
+
EXPECT_EQ(1, visitor.error_count_);
EXPECT_EQ(Http2DecoderAdapter::SPDY_INVALID_CONTROL_FRAME,
visitor.deframer_.spdy_framer_error());
diff --git a/spdy/core/spdy_header_block.cc b/spdy/core/spdy_header_block.cc
index a6f49b9..dcf84b9 100644
--- a/spdy/core/spdy_header_block.cc
+++ b/spdy/core/spdy_header_block.cc
@@ -9,12 +9,12 @@
#include <algorithm>
#include <utility>
-#include "base/arena.h"
#include "base/logging.h"
#include "base/macros.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_estimate_memory_usage.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_ptr_util.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_string_utils.h"
+#include "net/third_party/quiche/src/spdy/platform/api/spdy_unsafe_arena.h"
namespace spdy {
namespace {
@@ -90,8 +90,13 @@
size_t bytes_allocated() const { return arena_.status().bytes_allocated(); }
+ // TODO(xunjieli): https://crbug.com/669108. Merge this with bytes_allocated()
+ size_t EstimateMemoryUsage() const {
+ return arena_.status().bytes_allocated();
+ }
+
private:
- UnsafeArena arena_;
+ SpdyUnsafeArena arena_;
};
SpdyHeaderBlock::HeaderValue::HeaderValue(Storage* storage,
diff --git a/spdy/core/spdy_header_block.h b/spdy/core/spdy_header_block.h
index a63c52e..f453246 100644
--- a/spdy/core/spdy_header_block.h
+++ b/spdy/core/spdy_header_block.h
@@ -10,13 +10,14 @@
#include <list>
#include <memory>
#include <utility>
+#include <vector>
#include "base/macros.h"
-#include "base/port.h"
+#include "net/third_party/quiche/src/spdy/platform/api/spdy_containers.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_export.h"
+#include "net/third_party/quiche/src/spdy/platform/api/spdy_macros.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_string.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_string_piece.h"
-#include "util/gtl/linked_hash_map.h"
namespace spdy {
@@ -81,7 +82,8 @@
size_t separator_size_ = 0;
};
- typedef gtl::linked_hash_map<SpdyStringPiece, HeaderValue> MapType;
+ typedef SpdyLinkedHashMap<SpdyStringPiece, HeaderValue, SpdyStringPieceHash>
+ MapType;
public:
typedef std::pair<SpdyStringPiece, SpdyStringPiece> value_type;
@@ -179,10 +181,10 @@
const SpdyStringPiece value);
// Allows either lookup or mutation of the value associated with a key.
- ValueProxy operator[](const SpdyStringPiece key) ABSL_MUST_USE_RESULT;
+ ValueProxy operator[](const SpdyStringPiece key) SPDY_MUST_USE_RESULT;
// This object provides automatic conversions that allow SpdyHeaderBlock to be
- // nearly a drop-in replacement for linked_hash_map<SpdyString, SpdyString>.
+ // nearly a drop-in replacement for SpdyLinkedHashMap<SpdyString, SpdyString>.
// It reads data from or writes data to a SpdyHeaderBlock::Storage.
class SPDY_EXPORT_PRIVATE ValueProxy {
public:
diff --git a/spdy/core/spdy_protocol.cc b/spdy/core/spdy_protocol.cc
index b9af3fe..f51dc6e 100644
--- a/spdy/core/spdy_protocol.cc
+++ b/spdy/core/spdy_protocol.cc
@@ -6,7 +6,7 @@
#include <ostream>
-#include "net/third_party/quiche/src/spdy/core/spdy_bug_tracker.h"
+#include "net/third_party/quiche/src/spdy/platform/api/spdy_bug_tracker.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_ptr_util.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_string_utils.h"
diff --git a/spdy/core/spdy_protocol.h b/spdy/core/spdy_protocol.h
index c384f2e..d300d10 100644
--- a/spdy/core/spdy_protocol.h
+++ b/spdy/core/spdy_protocol.h
@@ -9,24 +9,25 @@
#ifndef QUICHE_SPDY_CORE_SPDY_PROTOCOL_H_
#define QUICHE_SPDY_CORE_SPDY_PROTOCOL_H_
+#include <cstddef>
#include <cstdint>
#include <iosfwd>
#include <limits>
#include <map>
#include <memory>
+#include <new>
#include <utility>
#include "base/logging.h"
#include "base/macros.h"
#include "net/third_party/quiche/src/spdy/core/spdy_alt_svc_wire_format.h"
#include "net/third_party/quiche/src/spdy/core/spdy_bitmasks.h"
-#include "net/third_party/quiche/src/spdy/core/spdy_bug_tracker.h"
#include "net/third_party/quiche/src/spdy/core/spdy_header_block.h"
+#include "net/third_party/quiche/src/spdy/platform/api/spdy_bug_tracker.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_export.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_ptr_util.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_string.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_string_piece.h"
-#include "util/gtl/linked_hash_map.h"
namespace spdy {
@@ -230,7 +231,7 @@
// Reserved ID for root stream of HTTP/2 stream dependency tree, as specified
// in RFC 7540 section 5.3.1.
-const int kHttp2RootStreamId = 0;
+const unsigned int kHttp2RootStreamId = 0;
typedef uint64_t SpdyPingId;
@@ -668,7 +669,6 @@
SpdyStreamId last_good_stream_id() const { return last_good_stream_id_; }
void set_last_good_stream_id(SpdyStreamId last_good_stream_id) {
- DCHECK_LE(0u, last_good_stream_id);
DCHECK_EQ(0u, last_good_stream_id & ~kStreamIdMask);
last_good_stream_id_ = last_good_stream_id;
}
@@ -986,6 +986,9 @@
return buffer;
}
+ // Returns the estimate of dynamically allocated memory in bytes.
+ size_t EstimateMemoryUsage() const { return owns_buffer_ ? size_ : 0; }
+
protected:
char* frame_;
diff --git a/spdy/core/spdy_protocol_test.cc b/spdy/core/spdy_protocol_test.cc
index b1f999e..09a56cb 100644
--- a/spdy/core/spdy_protocol_test.cc
+++ b/spdy/core/spdy_protocol_test.cc
@@ -9,7 +9,6 @@
#include <memory>
#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/base/public/test_utils.h"
#include "net/third_party/quiche/src/spdy/core/spdy_bitmasks.h"
#include "net/third_party/quiche/src/spdy/core/spdy_test_utils.h"
diff --git a/spdy/core/spdy_test_utils.cc b/spdy/core/spdy_test_utils.cc
index 7318e62..dd6c417 100644
--- a/spdy/core/spdy_test_utils.cc
+++ b/spdy/core/spdy_test_utils.cc
@@ -7,10 +7,11 @@
#include <algorithm>
#include <cstring>
#include <memory>
+#include <new>
#include <utility>
+#include <vector>
#include "base/logging.h"
-#include "strings/strcat.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_endianness_util.h"
@@ -32,7 +33,7 @@
}
SpdyString hex;
- for (const unsigned char *row = data; length > 0;
+ for (const unsigned char* row = data; length > 0;
row += kColumns, length -= kColumns) {
for (const unsigned char* p = row; p < row + 4; ++p) {
if (p < row + length) {
diff --git a/spdy/core/spdy_test_utils.h b/spdy/core/spdy_test_utils.h
index a7375aa..bf62eeb 100644
--- a/spdy/core/spdy_test_utils.h
+++ b/spdy/core/spdy_test_utils.h
@@ -5,21 +5,17 @@
#ifndef QUICHE_SPDY_CORE_SPDY_TEST_UTILS_H_
#define QUICHE_SPDY_CORE_SPDY_TEST_UTILS_H_
+#include <cstddef>
#include <cstdint>
-#include "gfe/gfe2/test_tools/failure.h"
-#include "net/third_party/quiche/src/spdy/core/spdy_bug_tracker.h"
+#include "net/third_party/quiche/src/http2/platform/api/http2_test_helpers.h"
#include "net/third_party/quiche/src/spdy/core/spdy_header_block.h"
#include "net/third_party/quiche/src/spdy/core/spdy_headers_handler_interface.h"
#include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"
+#include "net/third_party/quiche/src/spdy/platform/api/spdy_bug_tracker.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_string.h"
#include "net/third_party/quiche/src/spdy/platform/api/spdy_string_piece.h"
-
-// EXPECT_SPDY_BUG is like EXPECT_DFATAL, except it ensures that no DFATAL
-// logging is skipped due to exponential backoff.
-//
-// For external SPDY, EXPECT_SPDY_BUG should be #defined to EXPECT_DFATAL.
-#define EXPECT_SPDY_BUG EXPECT_GFE_BUG
+#include "net/third_party/quiche/src/spdy/platform/api/spdy_test_helpers.h"
namespace spdy {
diff --git a/spdy/platform/api/spdy_bug_tracker.h b/spdy/platform/api/spdy_bug_tracker.h
new file mode 100644
index 0000000..d750a21
--- /dev/null
+++ b/spdy/platform/api/spdy_bug_tracker.h
@@ -0,0 +1,15 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_SPDY_PLATFORM_API_SPDY_BUG_TRACKER_H_
+#define QUICHE_SPDY_PLATFORM_API_SPDY_BUG_TRACKER_H_
+
+#include "net/spdy/platform/impl/spdy_bug_tracker_impl.h"
+
+#define SPDY_BUG SPDY_BUG_IMPL
+#define SPDY_BUG_IF(condition) SPDY_BUG_IF_IMPL(condition)
+#define FLAGS_spdy_always_log_bugs_for_tests \
+ FLAGS_spdy_always_log_bugs_for_tests_impl
+
+#endif // QUICHE_SPDY_PLATFORM_API_SPDY_BUG_TRACKER_H_
diff --git a/spdy/platform/api/spdy_containers.h b/spdy/platform/api/spdy_containers.h
index 71a20de..e4f4c49 100644
--- a/spdy/platform/api/spdy_containers.h
+++ b/spdy/platform/api/spdy_containers.h
@@ -5,6 +5,7 @@
#ifndef QUICHE_SPDY_PLATFORM_API_SPDY_CONTAINERS_H_
#define QUICHE_SPDY_PLATFORM_API_SPDY_CONTAINERS_H_
+#include "net/third_party/quiche/src/spdy/platform/api/spdy_string_piece.h"
#include "net/spdy/platform/impl/spdy_containers_impl.h"
namespace spdy {
@@ -22,6 +23,20 @@
template <typename ElementType, typename Hasher, typename Eq>
using SpdyHashSet = SpdyHashSetImpl<ElementType, Hasher, Eq>;
+// A map which offers insertion-ordered iteration.
+template <typename Key, typename Value, typename Hash = SpdyHash<Key>>
+using SpdyLinkedHashMap = SpdyLinkedHashMapImpl<Key, Value, Hash>;
+
+// A vector optimized for small sizes. Provides the same APIs as a std::vector.
+template <typename T, size_t N, typename A = std::allocator<T>>
+using SpdyInlinedVector = SpdyInlinedVectorImpl<T, N, A>;
+
+using SpdyStringPieceHash = SpdyStringPieceHashImpl;
+
+inline size_t SpdyHashStringPair(SpdyStringPiece a, SpdyStringPiece b) {
+ return SpdyHashStringPairImpl(a, b);
+}
+
} // namespace spdy
#endif // QUICHE_SPDY_PLATFORM_API_SPDY_CONTAINERS_H_
diff --git a/spdy/platform/api/spdy_endianness_util.h b/spdy/platform/api/spdy_endianness_util.h
index 313a075..e4074d7 100644
--- a/spdy/platform/api/spdy_endianness_util.h
+++ b/spdy/platform/api/spdy_endianness_util.h
@@ -1,3 +1,7 @@
+// Copyright (c) 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
#ifndef QUICHE_SPDY_PLATFORM_API_SPDY_ENDIANNESS_UTIL_H_
#define QUICHE_SPDY_PLATFORM_API_SPDY_ENDIANNESS_UTIL_H_
diff --git a/spdy/platform/api/spdy_macros.h b/spdy/platform/api/spdy_macros.h
new file mode 100644
index 0000000..a75c957
--- /dev/null
+++ b/spdy/platform/api/spdy_macros.h
@@ -0,0 +1,15 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_SPDY_PLATFORM_API_SPDY_MACROS_H_
+#define QUICHE_SPDY_PLATFORM_API_SPDY_MACROS_H_
+
+#include "net/spdy/platform/impl/spdy_macros_impl.h"
+
+#define SPDY_MUST_USE_RESULT SPDY_MUST_USE_RESULT_IMPL
+#define SPDY_UNUSED SPDY_UNUSED_IMPL
+
+#define SPDY_DVLOG_IF SPDY_DVLOG_IF_IMPL
+
+#endif // QUICHE_SPDY_PLATFORM_API_SPDY_MACROS_H_
diff --git a/spdy/platform/api/spdy_test_helpers.h b/spdy/platform/api/spdy_test_helpers.h
new file mode 100644
index 0000000..367d330
--- /dev/null
+++ b/spdy/platform/api/spdy_test_helpers.h
@@ -0,0 +1,12 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_SPDY_PLATFORM_API_SPDY_TEST_HELPERS_H_
+#define QUICHE_SPDY_PLATFORM_API_SPDY_TEST_HELPERS_H_
+
+#include "net/spdy/platform/impl/spdy_test_helpers_impl.h"
+
+#define EXPECT_SPDY_BUG EXPECT_SPDY_BUG_IMPL
+
+#endif // QUICHE_SPDY_PLATFORM_API_SPDY_TEST_HELPERS_H_
diff --git a/spdy/platform/api/spdy_test_utils_prod.h b/spdy/platform/api/spdy_test_utils_prod.h
new file mode 100644
index 0000000..1466770
--- /dev/null
+++ b/spdy/platform/api/spdy_test_utils_prod.h
@@ -0,0 +1,12 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_SPDY_PLATFORM_API_SPDY_TEST_UTILS_PROD_H_
+#define QUICHE_SPDY_PLATFORM_API_SPDY_TEST_UTILS_PROD_H_
+
+#include "net/spdy/platform/impl/spdy_test_utils_prod_impl.h"
+
+#define SPDY_FRIEND_TEST SPDY_FRIEND_TEST_IMPL
+
+#endif // QUICHE_SPDY_PLATFORM_API_SPDY_TEST_UTILS_PROD_H_
diff --git a/spdy/platform/api/spdy_unsafe_arena.h b/spdy/platform/api/spdy_unsafe_arena.h
new file mode 100644
index 0000000..77185e1
--- /dev/null
+++ b/spdy/platform/api/spdy_unsafe_arena.h
@@ -0,0 +1,16 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_SPDY_PLATFORM_API_SPDY_UNSAFE_ARENA_H_
+#define QUICHE_SPDY_PLATFORM_API_SPDY_UNSAFE_ARENA_H_
+
+#include "net/spdy/platform/impl/spdy_unsafe_arena_impl.h"
+
+namespace spdy {
+
+using SpdyUnsafeArena = SpdyUnsafeArenaImpl;
+
+} // namespace spdy
+
+#endif // QUICHE_SPDY_PLATFORM_API_SPDY_UNSAFE_ARENA_H_