Commit 97a69515 authored by Bence Béky's avatar Bence Béky Committed by Commit Bot

Update ever-changing QPACK terminology.

https://github.com/quicwg/base-drafts/pull/2111 changed a whole bunch of
terminology without changing the wire format.  This CL updates the
implementation with the name changes:

s/Largest Reference/Insert Count/
s/Base Index/Base/
s/Delta Base Index/Delta Base/
s/Table State Synchronize/Insert Count Increment/

Also, decrement absolute index to make it zero-based.  Internally a
zero-based "real index" was used, there is no more need for that.

Also rename Dynamic Table Size Update to Set Dynamic Table Capacity
according to https://github.com/quicwg/base-drafts/pull/2115.  Dynamic
table size, dynamic table capacity, and maximum dynamic table capacity
is already in the code base.

This CL lands server change 230923988 by bnc.

BUG=488484

Change-Id: I36ffe38a0caa22615434cbe996a20b86af47ee05
Reviewed-on: https://chromium-review.googlesource.com/c/1441496
Commit-Queue: Bence Béky <bnc@chromium.org>
Reviewed-by: default avatarZhongyi Shi <zhongyi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#626999}
parent c8adc846
......@@ -28,7 +28,7 @@ class NoOpDelegate : public QpackEncoderStreamReceiver::Delegate {
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;
}
......
......@@ -65,8 +65,8 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
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;
}
}
......
......@@ -69,7 +69,7 @@ const QpackInstruction* DuplicateInstruction() {
return instruction;
}
const QpackInstruction* DynamicTableSizeUpdateInstruction() {
const QpackInstruction* SetDynamicTableCapacityInstruction() {
static const QpackInstructionOpcode* const opcode =
new QpackInstructionOpcode{0b00100000, 0b11100000};
static const QpackInstruction* const instruction =
......@@ -81,12 +81,12 @@ const QpackLanguage* QpackEncoderStreamLanguage() {
static const QpackLanguage* const language = new QpackLanguage{
InsertWithNameReferenceInstruction(),
InsertWithoutNameReferenceInstruction(), DuplicateInstruction(),
DynamicTableSizeUpdateInstruction()};
SetDynamicTableCapacityInstruction()};
ValidateLangague(language);
return language;
}
const QpackInstruction* TableStateSynchronizeInstruction() {
const QpackInstruction* InsertCountIncrementInstruction() {
static const QpackInstructionOpcode* const opcode =
new QpackInstructionOpcode{0b00000000, 0b11000000};
static const QpackInstruction* const instruction =
......@@ -112,7 +112,7 @@ const QpackInstruction* StreamCancellationInstruction() {
const QpackLanguage* QpackDecoderStreamLanguage() {
static const QpackLanguage* const language = new QpackLanguage{
TableStateSynchronizeInstruction(), HeaderAcknowledgementInstruction(),
InsertCountIncrementInstruction(), HeaderAcknowledgementInstruction(),
StreamCancellationInstruction()};
ValidateLangague(language);
return language;
......
......@@ -30,14 +30,14 @@ bool operator==(const QpackInstructionOpcode& a,
// 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* InsertWithoutNameReferenceInstruction();
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();
......
......@@ -55,14 +55,14 @@ void QpackDecoder::OnInsertWithNameReference(bool is_static,
return;
}
uint64_t real_index;
if (!EncoderStreamRelativeIndexToRealIndex(name_index, &real_index)) {
uint64_t absolute_index;
if (!EncoderStreamRelativeIndexToAbsoluteIndex(name_index, &absolute_index)) {
encoder_stream_error_delegate_->OnError("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.");
return;
......@@ -83,14 +83,14 @@ void QpackDecoder::OnInsertWithoutNameReference(QuicStringPiece name,
}
void QpackDecoder::OnDuplicate(uint64_t index) {
uint64_t real_index;
if (!EncoderStreamRelativeIndexToRealIndex(index, &real_index)) {
uint64_t absolute_index;
if (!EncoderStreamRelativeIndexToAbsoluteIndex(index, &absolute_index)) {
encoder_stream_error_delegate_->OnError("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.");
return;
......@@ -101,10 +101,10 @@ void QpackDecoder::OnDuplicate(uint64_t index) {
}
}
void QpackDecoder::OnDynamicTableSizeUpdate(uint64_t max_size) {
if (!header_table_.UpdateTableSize(max_size)) {
void QpackDecoder::OnSetDynamicTableCapacity(uint64_t capacity) {
if (!header_table_.SetDynamicTableCapacity(capacity)) {
encoder_stream_error_delegate_->OnError(
"Error updating dynamic table size.");
"Error updating dynamic table capacity.");
}
}
......@@ -112,16 +112,16 @@ void QpackDecoder::OnErrorDetected(QuicStringPiece error_message) {
encoder_stream_error_delegate_->OnError(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;
}
......
......@@ -79,18 +79,17 @@ class QUIC_EXPORT_PRIVATE QpackDecoder
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_;
......
......@@ -27,8 +27,8 @@ void QpackDecoderStreamReceiver::Decode(QuicStringPiece data) {
bool QpackDecoderStreamReceiver::OnInstructionDecoded(
const QpackInstruction* instruction) {
if (instruction == TableStateSynchronizeInstruction()) {
delegate_->OnTableStateSynchronize(instruction_decoder_.varint());
if (instruction == InsertCountIncrementInstruction()) {
delegate_->OnInsertCountIncrement(instruction_decoder_.varint());
return true;
}
......
......@@ -25,8 +25,8 @@ class QUIC_EXPORT_PRIVATE QpackDecoderStreamReceiver
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
......
......@@ -20,7 +20,7 @@ class MockDelegate : public QpackDecoderStreamReceiver::Delegate {
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));
......@@ -35,17 +35,17 @@ class QpackDecoderStreamReceiverTest : public QuicTest {
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(Eq("Encoded integer too large.")));
......
......@@ -18,11 +18,10 @@ QpackDecoderStreamSender::QpackDecoderStreamSender(Delegate* delegate)
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;
......
......@@ -37,8 +37,8 @@ class QUIC_EXPORT_PRIVATE QpackDecoderStreamSender {
// 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
......
......@@ -32,18 +32,18 @@ class QpackDecoderStreamSenderTest : public QuicTest {
QpackDecoderStreamSender stream_;
};
TEST_F(QpackDecoderStreamSenderTest, TableStateSynchronize) {
TEST_F(QpackDecoderStreamSenderTest, InsertCountIncrement) {
EXPECT_CALL(delegate_, Write(Eq(QuicTextUtils::HexDecode("00"))));
stream_.SendTableStateSynchronize(0);
stream_.SendInsertCountIncrement(0);
EXPECT_CALL(delegate_, Write(Eq(QuicTextUtils::HexDecode("0a"))));
stream_.SendTableStateSynchronize(10);
stream_.SendInsertCountIncrement(10);
EXPECT_CALL(delegate_, Write(Eq(QuicTextUtils::HexDecode("3f00"))));
stream_.SendTableStateSynchronize(63);
stream_.SendInsertCountIncrement(63);
EXPECT_CALL(delegate_, Write(Eq(QuicTextUtils::HexDecode("3f8901"))));
stream_.SendTableStateSynchronize(200);
stream_.SendInsertCountIncrement(200);
}
TEST_F(QpackDecoderStreamSenderTest, HeaderAcknowledgement) {
......
......@@ -35,7 +35,7 @@ void QpackEncoder::DecodeDecoderStreamData(QuicStringPiece data) {
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.
}
......
......@@ -55,7 +55,7 @@ class QUIC_EXPORT_PRIVATE QpackEncoder
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;
......
......@@ -45,8 +45,8 @@ bool QpackEncoderStreamReceiver::OnInstructionDecoded(
return true;
}
DCHECK_EQ(instruction, DynamicTableSizeUpdateInstruction());
delegate_->OnDynamicTableSizeUpdate(instruction_decoder_.varint());
DCHECK_EQ(instruction, SetDynamicTableCapacityInstruction());
delegate_->OnSetDynamicTableCapacity(instruction_decoder_.varint());
return true;
}
......
......@@ -33,8 +33,8 @@ class QUIC_EXPORT_PRIVATE QpackEncoderStreamReceiver
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;
};
......
......@@ -27,7 +27,7 @@ class MockDelegate : public QpackEncoderStreamReceiver::Delegate {
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));
};
......@@ -149,16 +149,16 @@ TEST_F(QpackEncoderStreamReceiverTest, DuplicateIndexTooLarge) {
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) {
TEST_F(QpackEncoderStreamReceiverTest, SetDynamicTableCapacityTooLarge) {
EXPECT_CALL(*delegate(), OnErrorDetected(Eq("Encoded integer too large.")));
Decode(QuicTextUtils::HexDecode("3fffffffffffffffffffff"));
......
......@@ -65,10 +65,10 @@ void QpackEncoderStreamSender::SendDuplicate(uint64_t index) {
delegate_->Write(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;
......
......@@ -44,8 +44,8 @@ class QUIC_EXPORT_PRIVATE QpackEncoderStreamSender {
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_;
......
......@@ -95,14 +95,14 @@ TEST_F(QpackEncoderStreamSenderTest, Duplicate) {
stream_.SendDuplicate(500);
}
TEST_F(QpackEncoderStreamSenderTest, DynamicTableSizeUpdate) {
// Small max size fits in prefix.
TEST_F(QpackEncoderStreamSenderTest, SetDynamicTableCapacity) {
// Small capacity fits in prefix.
EXPECT_CALL(delegate_, Write(Eq(QuicTextUtils::HexDecode("31"))));
stream_.SendDynamicTableSizeUpdate(17);
stream_.SendSetDynamicTableCapacity(17);
// Large max size requires two extension bytes.
// Large capacity requires two extension bytes.
EXPECT_CALL(delegate_, Write(Eq(QuicTextUtils::HexDecode("3fd503"))));
stream_.SendDynamicTableSizeUpdate(500);
stream_.SendSetDynamicTableCapacity(500);
}
} // namespace
......
......@@ -143,12 +143,12 @@ const QpackEntry* QpackHeaderTable::InsertEntry(QuicStringPiece name,
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_);
......
......@@ -56,9 +56,9 @@ class QUIC_EXPORT_PRIVATE QpackHeaderTable {
// 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 @@ class QUIC_EXPORT_PRIVATE QpackHeaderTable {
// 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
......
......@@ -76,8 +76,8 @@ class QpackHeaderTableTest : public QuicTest {
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 +237,21 @@ TEST_F(QpackHeaderTableTest, MaxEntries) {
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 +286,7 @@ TEST_F(QpackHeaderTableTest, EvictByUpdateTableSize) {
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 +294,7 @@ TEST_F(QpackHeaderTableTest, EvictByUpdateTableSize) {
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 +303,7 @@ TEST_F(QpackHeaderTableTest, EvictByUpdateTableSize) {
}
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 +328,7 @@ TEST_F(QpackHeaderTableTest, EvictOldestOfIdentical) {
}
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.
......
......@@ -56,14 +56,14 @@ class QUIC_EXPORT_PRIVATE QpackProgressiveDecoder
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 @@ class QUIC_EXPORT_PRIVATE QpackProgressiveDecoder
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 @@ class QUIC_EXPORT_PRIVATE QpackProgressiveDecoder
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_;
......
......@@ -11,12 +11,12 @@ namespace quic {
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 @@ struct {
// 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 @@ struct {
// 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;
}
}
......
......@@ -48,8 +48,8 @@ void QpackProgressiveEncoder::Next(size_t max_encoded_bytes,
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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment