Factor out QPACK absolute, relative, and post-base index conversion functions, and add new ones.
gfe-relnote: n/a, change to QUIC v99-only code. Protected by existing disabled gfe2_reloadable_flag_quic_enable_version_99.
PiperOrigin-RevId: 263421099
Change-Id: I762c3105da671f9d01ba5971c57a2f89f130ebbf
diff --git a/quic/core/qpack/qpack_decoder.cc b/quic/core/qpack/qpack_decoder.cc
index 8e3103c..7fac1f2 100644
--- a/quic/core/qpack/qpack_decoder.cc
+++ b/quic/core/qpack/qpack_decoder.cc
@@ -4,6 +4,7 @@
#include "net/third_party/quiche/src/quic/core/qpack/qpack_decoder.h"
+#include "net/third_party/quiche/src/quic/core/qpack/qpack_index_conversions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
@@ -48,7 +49,8 @@
}
uint64_t absolute_index;
- if (!EncoderStreamRelativeIndexToAbsoluteIndex(name_index, &absolute_index)) {
+ if (!QpackEncoderStreamRelativeIndexToAbsoluteIndex(
+ name_index, header_table_.inserted_entry_count(), &absolute_index)) {
encoder_stream_error_delegate_->OnEncoderStreamError(
"Invalid relative index.");
return;
@@ -79,7 +81,8 @@
void QpackDecoder::OnDuplicate(uint64_t index) {
uint64_t absolute_index;
- if (!EncoderStreamRelativeIndexToAbsoluteIndex(index, &absolute_index)) {
+ if (!QpackEncoderStreamRelativeIndexToAbsoluteIndex(
+ index, header_table_.inserted_entry_count(), &absolute_index)) {
encoder_stream_error_delegate_->OnEncoderStreamError(
"Invalid relative index.");
return;
@@ -110,17 +113,6 @@
encoder_stream_error_delegate_->OnEncoderStreamError(error_message);
}
-bool QpackDecoder::EncoderStreamRelativeIndexToAbsoluteIndex(
- uint64_t relative_index,
- uint64_t* absolute_index) const {
- if (relative_index >= header_table_.inserted_entry_count()) {
- return false;
- }
-
- *absolute_index = header_table_.inserted_entry_count() - relative_index - 1;
- return true;
-}
-
std::unique_ptr<QpackProgressiveDecoder> QpackDecoder::CreateProgressiveDecoder(
QuicStreamId stream_id,
QpackProgressiveDecoder::HeadersHandlerInterface* handler) {
diff --git a/quic/core/qpack/qpack_decoder.h b/quic/core/qpack/qpack_decoder.h
index c00d777..1ec2d39 100644
--- a/quic/core/qpack/qpack_decoder.h
+++ b/quic/core/qpack/qpack_decoder.h
@@ -85,14 +85,6 @@
}
private:
- // The encoder stream uses relative index (but different from the kind of
- // 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_;
QpackDecoderStreamSender decoder_stream_sender_;
diff --git a/quic/core/qpack/qpack_index_conversions.cc b/quic/core/qpack/qpack_index_conversions.cc
new file mode 100644
index 0000000..8f1d52f
--- /dev/null
+++ b/quic/core/qpack/qpack_index_conversions.cc
@@ -0,0 +1,62 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/core/qpack/qpack_index_conversions.h"
+
+#include <limits>
+
+#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
+
+namespace quic {
+
+uint64_t QpackAbsoluteIndexToEncoderStreamRelativeIndex(
+ uint64_t absolute_index,
+ uint64_t inserted_entry_count) {
+ DCHECK_LT(absolute_index, inserted_entry_count);
+
+ return inserted_entry_count - absolute_index - 1;
+}
+
+uint64_t QpackAbsoluteIndexToRequestStreamRelativeIndex(uint64_t absolute_index,
+ uint64_t base) {
+ DCHECK_LT(absolute_index, base);
+
+ return base - absolute_index - 1;
+}
+
+bool QpackEncoderStreamRelativeIndexToAbsoluteIndex(
+ uint64_t relative_index,
+ uint64_t inserted_entry_count,
+ uint64_t* absolute_index) {
+ if (relative_index >= inserted_entry_count) {
+ return false;
+ }
+
+ *absolute_index = inserted_entry_count - relative_index - 1;
+ return true;
+}
+
+bool QpackRequestStreamRelativeIndexToAbsoluteIndex(uint64_t relative_index,
+ uint64_t base,
+ uint64_t* absolute_index) {
+ if (relative_index >= base) {
+ return false;
+ }
+
+ *absolute_index = base - relative_index - 1;
+ return true;
+}
+
+bool QpackPostBaseIndexToAbsoluteIndex(uint64_t post_base_index,
+ uint64_t base,
+ uint64_t* absolute_index) {
+ if (post_base_index >= std::numeric_limits<uint64_t>::max() - base) {
+ return false;
+ }
+
+ *absolute_index = base + post_base_index;
+ return true;
+}
+
+} // namespace quic
diff --git a/quic/core/qpack/qpack_index_conversions.h b/quic/core/qpack/qpack_index_conversions.h
new file mode 100644
index 0000000..f05a477
--- /dev/null
+++ b/quic/core/qpack/qpack_index_conversions.h
@@ -0,0 +1,65 @@
+// 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.
+
+// Utility methods to convert between absolute indexing (used in the dynamic
+// table), relative indexing used on the encoder stream, and relative indexing
+// and post-base indexing used on request streams (in header blocks). See:
+// https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#indexing
+// https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#relative-indexing
+// https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#post-base
+
+#ifndef QUICHE_QUIC_CORE_QPACK_QPACK_INDEX_CONVERSIONS_H_
+#define QUICHE_QUIC_CORE_QPACK_QPACK_INDEX_CONVERSIONS_H_
+
+#include <cstdint>
+
+namespace quic {
+
+// Conversion functions used in the encoder do not check for overflow/underflow.
+// Since the maximum index is limited by maximum dynamic table capacity
+// (represented on uint64_t) divided by minimum header field size (defined to be
+// 32 bytes), overflow is not possible. The caller is responsible for providing
+// input that does not underflow.
+
+uint64_t QpackAbsoluteIndexToEncoderStreamRelativeIndex(
+ uint64_t absolute_index,
+ uint64_t inserted_entry_count);
+
+uint64_t QpackAbsoluteIndexToRequestStreamRelativeIndex(uint64_t absolute_index,
+ uint64_t base);
+
+// Conversion functions used in the decoder operate on input received from the
+// network. These functions return false on overflow or underflow.
+
+// TODO The encoder stream uses relative index (but different from the kind of
+// 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 QpackEncoderStreamRelativeIndexToAbsoluteIndex(
+ uint64_t relative_index,
+ uint64_t inserted_entry_count,
+ uint64_t* absolute_index);
+
+// TODO 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.
+
+// On success, |*absolute_index| is guaranteed to be strictly less than
+// std::numeric_limits<uint64_t>::max().
+bool QpackRequestStreamRelativeIndexToAbsoluteIndex(uint64_t relative_index,
+ uint64_t base,
+ uint64_t* absolute_index);
+
+// On success, |*absolute_index| is guaranteed to be strictly less than
+// std::numeric_limits<uint64_t>::max().
+bool QpackPostBaseIndexToAbsoluteIndex(uint64_t post_base_index,
+ uint64_t base,
+ uint64_t* absolute_index);
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_QPACK_QPACK_INDEX_CONVERSIONS_H_
diff --git a/quic/core/qpack/qpack_index_conversions_test.cc b/quic/core/qpack/qpack_index_conversions_test.cc
new file mode 100644
index 0000000..214dff5
--- /dev/null
+++ b/quic/core/qpack/qpack_index_conversions_test.cc
@@ -0,0 +1,99 @@
+// Copyright (c) 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/third_party/quiche/src/quic/core/qpack/qpack_index_conversions.h"
+
+#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
+
+namespace quic {
+namespace test {
+namespace {
+
+struct {
+ uint64_t relative_index;
+ uint64_t inserted_entry_count;
+ uint64_t expected_absolute_index;
+} kEncoderStreamRelativeIndexTestData[] = {{0, 1, 0}, {0, 2, 1}, {1, 2, 0},
+ {0, 10, 9}, {5, 10, 4}, {9, 10, 0}};
+
+TEST(QpackIndexConversions, EncoderStreamRelativeIndex) {
+ for (const auto& test_data : kEncoderStreamRelativeIndexTestData) {
+ uint64_t absolute_index = 42;
+ EXPECT_TRUE(QpackEncoderStreamRelativeIndexToAbsoluteIndex(
+ test_data.relative_index, test_data.inserted_entry_count,
+ &absolute_index));
+ EXPECT_EQ(test_data.expected_absolute_index, absolute_index);
+
+ EXPECT_EQ(test_data.relative_index,
+ QpackAbsoluteIndexToEncoderStreamRelativeIndex(
+ absolute_index, test_data.inserted_entry_count));
+ }
+}
+
+struct {
+ uint64_t relative_index;
+ uint64_t base;
+ uint64_t expected_absolute_index;
+} kRequestStreamRelativeIndexTestData[] = {{0, 1, 0}, {0, 2, 1}, {1, 2, 0},
+ {0, 10, 9}, {5, 10, 4}, {9, 10, 0}};
+
+TEST(QpackIndexConversions, RequestStreamRelativeIndex) {
+ for (const auto& test_data : kRequestStreamRelativeIndexTestData) {
+ uint64_t absolute_index = 42;
+ EXPECT_TRUE(QpackRequestStreamRelativeIndexToAbsoluteIndex(
+ test_data.relative_index, test_data.base, &absolute_index));
+ EXPECT_EQ(test_data.expected_absolute_index, absolute_index);
+
+ EXPECT_EQ(test_data.relative_index,
+ QpackAbsoluteIndexToRequestStreamRelativeIndex(absolute_index,
+ test_data.base));
+ }
+}
+
+struct {
+ uint64_t post_base_index;
+ uint64_t base;
+ uint64_t expected_absolute_index;
+} kPostBaseIndexTestData[] = {{0, 1, 1}, {1, 0, 1}, {2, 0, 2},
+ {1, 1, 2}, {0, 2, 2}, {1, 2, 3}};
+
+TEST(QpackIndexConversions, PostBaseIndex) {
+ for (const auto& test_data : kPostBaseIndexTestData) {
+ uint64_t absolute_index = 42;
+ EXPECT_TRUE(QpackPostBaseIndexToAbsoluteIndex(
+ test_data.post_base_index, test_data.base, &absolute_index));
+ EXPECT_EQ(test_data.expected_absolute_index, absolute_index);
+ }
+}
+
+TEST(QpackIndexConversions, EncoderStreamRelativeIndexUnderflow) {
+ uint64_t absolute_index;
+ EXPECT_FALSE(QpackEncoderStreamRelativeIndexToAbsoluteIndex(
+ /* relative_index = */ 10,
+ /* inserted_entry_count = */ 10, &absolute_index));
+ EXPECT_FALSE(QpackEncoderStreamRelativeIndexToAbsoluteIndex(
+ /* relative_index = */ 12,
+ /* inserted_entry_count = */ 10, &absolute_index));
+}
+
+TEST(QpackIndexConversions, RequestStreamRelativeIndexUnderflow) {
+ uint64_t absolute_index;
+ EXPECT_FALSE(QpackRequestStreamRelativeIndexToAbsoluteIndex(
+ /* relative_index = */ 10,
+ /* base = */ 10, &absolute_index));
+ EXPECT_FALSE(QpackRequestStreamRelativeIndexToAbsoluteIndex(
+ /* relative_index = */ 12,
+ /* base = */ 10, &absolute_index));
+}
+
+TEST(QpackIndexConversions, QpackPostBaseIndexToAbsoluteIndexOverflow) {
+ uint64_t absolute_index;
+ EXPECT_FALSE(QpackPostBaseIndexToAbsoluteIndex(
+ /* post_base_index = */ 20,
+ /* base = */ std::numeric_limits<uint64_t>::max() - 10, &absolute_index));
+}
+
+} // namespace
+} // namespace test
+} // namespace quic
diff --git a/quic/core/qpack/qpack_progressive_decoder.cc b/quic/core/qpack/qpack_progressive_decoder.cc
index d9449e3..e5f7f09 100644
--- a/quic/core/qpack/qpack_progressive_decoder.cc
+++ b/quic/core/qpack/qpack_progressive_decoder.cc
@@ -8,6 +8,7 @@
#include <limits>
#include "net/third_party/quiche/src/quic/core/qpack/qpack_constants.h"
+#include "net/third_party/quiche/src/quic/core/qpack/qpack_index_conversions.h"
#include "net/third_party/quiche/src/quic/core/qpack/qpack_required_insert_count.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
@@ -125,8 +126,8 @@
bool QpackProgressiveDecoder::DoIndexedHeaderFieldInstruction() {
if (!instruction_decoder_.s_bit()) {
uint64_t absolute_index;
- if (!RequestStreamRelativeIndexToAbsoluteIndex(
- instruction_decoder_.varint(), &absolute_index)) {
+ if (!QpackRequestStreamRelativeIndexToAbsoluteIndex(
+ instruction_decoder_.varint(), base_, &absolute_index)) {
OnError("Invalid relative index.");
return false;
}
@@ -164,8 +165,8 @@
bool QpackProgressiveDecoder::DoIndexedHeaderFieldPostBaseInstruction() {
uint64_t absolute_index;
- if (!PostBaseIndexToAbsoluteIndex(instruction_decoder_.varint(),
- &absolute_index)) {
+ if (!QpackPostBaseIndexToAbsoluteIndex(instruction_decoder_.varint(), base_,
+ &absolute_index)) {
OnError("Invalid post-base index.");
return false;
}
@@ -193,8 +194,8 @@
bool QpackProgressiveDecoder::DoLiteralHeaderFieldNameReferenceInstruction() {
if (!instruction_decoder_.s_bit()) {
uint64_t absolute_index;
- if (!RequestStreamRelativeIndexToAbsoluteIndex(
- instruction_decoder_.varint(), &absolute_index)) {
+ if (!QpackRequestStreamRelativeIndexToAbsoluteIndex(
+ instruction_decoder_.varint(), base_, &absolute_index)) {
OnError("Invalid relative index.");
return false;
}
@@ -232,8 +233,8 @@
bool QpackProgressiveDecoder::DoLiteralHeaderFieldPostBaseInstruction() {
uint64_t absolute_index;
- if (!PostBaseIndexToAbsoluteIndex(instruction_decoder_.varint(),
- &absolute_index)) {
+ if (!QpackPostBaseIndexToAbsoluteIndex(instruction_decoder_.varint(), base_,
+ &absolute_index)) {
OnError("Invalid post-base index.");
return false;
}
@@ -343,26 +344,4 @@
return true;
}
-bool QpackProgressiveDecoder::RequestStreamRelativeIndexToAbsoluteIndex(
- uint64_t relative_index,
- uint64_t* absolute_index) const {
- if (relative_index >= base_) {
- return false;
- }
-
- *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_) {
- return false;
- }
-
- *absolute_index = base_ + post_base_index;
- return true;
-}
-
} // namespace quic
diff --git a/quic/core/qpack/qpack_progressive_decoder.h b/quic/core/qpack/qpack_progressive_decoder.h
index 3abf427..6d2e992 100644
--- a/quic/core/qpack/qpack_progressive_decoder.h
+++ b/quic/core/qpack/qpack_progressive_decoder.h
@@ -89,18 +89,6 @@
// 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. 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;
- bool PostBaseIndexToAbsoluteIndex(uint64_t post_base_index,
- uint64_t* absolute_index) const;
-
const QuicStreamId stream_id_;
// |prefix_decoder_| only decodes a handful of bytes then it can be