Add QpackEncoder::SetMaximumDynamicTableCapacity() and SetMaximumBlockedStreams() and call them when corresponding settings are received. gfe-relnote: n/a, change to QUIC v99-only code. Protected by existing disabled gfe2_reloadable_flag_quic_enable_version_99. PiperOrigin-RevId: 261579634 Change-Id: Ice97e1d26210c622fbbf6c6894901ed6b44c01ca
diff --git a/quic/core/http/quic_spdy_session.cc b/quic/core/http/quic_spdy_session.cc index 3c00c2b..2a83d24 100644 --- a/quic/core/http/quic_spdy_session.cc +++ b/quic/core/http/quic_spdy_session.cc
@@ -647,7 +647,7 @@ QUIC_DVLOG(1) << "SETTINGS_QPACK_MAX_TABLE_CAPACITY received with value " << value; - // TODO(b/112770235): implement. + qpack_encoder_->SetMaximumDynamicTableCapacity(value); break; case SETTINGS_MAX_HEADER_LIST_SIZE: QUIC_DVLOG(1) << "SETTINGS_MAX_HEADER_LIST_SIZE received with value " @@ -657,7 +657,7 @@ case SETTINGS_QPACK_BLOCKED_STREAMS: QUIC_DVLOG(1) << "SETTINGS_QPACK_BLOCKED_STREAMS received with value " << value; - // TODO(b/112770235): implement. + qpack_encoder_->SetMaximumBlockedStreams(value); break; case SETTINGS_NUM_PLACEHOLDERS: QUIC_DVLOG(1) << "SETTINGS_NUM_PLACEHOLDERS received with value "
diff --git a/quic/core/http/quic_spdy_session_test.cc b/quic/core/http/quic_spdy_session_test.cc index a2b4846..6a0b96e 100644 --- a/quic/core/http/quic_spdy_session_test.cc +++ b/quic/core/http/quic_spdy_session_test.cc
@@ -25,6 +25,8 @@ #include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.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" +#include "net/third_party/quiche/src/quic/test_tools/qpack_encoder_peer.h" +#include "net/third_party/quiche/src/quic/test_tools/qpack_header_table_peer.h" #include "net/third_party/quiche/src/quic/test_tools/quic_config_peer.h" #include "net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h" #include "net/third_party/quiche/src/quic/test_tools/quic_flow_controller_peer.h" @@ -2119,7 +2121,7 @@ if (!VersionHasStreamType(transport_version())) { return; } - // Use a arbitrary stream id. + // Use an arbitrary stream id. QuicStreamId stream_id = GetNthClientInitiatedUnidirectionalStreamId(transport_version(), 3); char type[] = {kControlStream}; @@ -2130,14 +2132,27 @@ QuicSpdySessionPeer::GetReceiveControlStream(&session_)->id()); SettingsFrame settings; - settings.values[3] = 2; + settings.values[SETTINGS_QPACK_MAX_TABLE_CAPACITY] = 512; settings.values[SETTINGS_MAX_HEADER_LIST_SIZE] = 5; + settings.values[SETTINGS_QPACK_BLOCKED_STREAMS] = 42; std::string data = EncodeSettings(settings); QuicStreamFrame frame(stream_id, false, 1, QuicStringPiece(data)); + QpackEncoder* qpack_encoder = session_.qpack_encoder(); + QpackHeaderTable* header_table = + QpackEncoderPeer::header_table(qpack_encoder); + + EXPECT_NE(512u, + QpackHeaderTablePeer::maximum_dynamic_table_capacity(header_table)); EXPECT_NE(5u, session_.max_outbound_header_list_size()); + EXPECT_NE(42u, QpackEncoderPeer::maximum_blocked_streams(qpack_encoder)); + session_.OnStreamFrame(frame); + + EXPECT_EQ(512u, + QpackHeaderTablePeer::maximum_dynamic_table_capacity(header_table)); EXPECT_EQ(5u, session_.max_outbound_header_list_size()); + EXPECT_EQ(42u, QpackEncoderPeer::maximum_blocked_streams(qpack_encoder)); } TEST_P(QuicSpdySessionTestServer, ReceiveControlStreamOutOfOrderDelivery) {
diff --git a/quic/core/qpack/qpack_encoder.cc b/quic/core/qpack/qpack_encoder.cc index 4759e42..1daa572 100644 --- a/quic/core/qpack/qpack_encoder.cc +++ b/quic/core/qpack/qpack_encoder.cc
@@ -20,7 +20,8 @@ QpackStreamSenderDelegate* encoder_stream_sender_delegate) : decoder_stream_error_delegate_(decoder_stream_error_delegate), decoder_stream_receiver_(this), - encoder_stream_sender_(encoder_stream_sender_delegate) { + encoder_stream_sender_(encoder_stream_sender_delegate), + maximum_blocked_streams_(0) { DCHECK(decoder_stream_error_delegate_); DCHECK(encoder_stream_sender_delegate); } @@ -103,6 +104,15 @@ decoder_stream_receiver_.Decode(data); } +void QpackEncoder::SetMaximumDynamicTableCapacity( + uint64_t maximum_dynamic_table_capacity) { + header_table_.SetMaximumDynamicTableCapacity(maximum_dynamic_table_capacity); +} + +void QpackEncoder::SetMaximumBlockedStreams(uint64_t maximum_blocked_streams) { + maximum_blocked_streams_ = maximum_blocked_streams; +} + void QpackEncoder::OnInsertCountIncrement(uint64_t /*increment*/) { // TODO(bnc): Implement dynamic table management for encoding. }
diff --git a/quic/core/qpack/qpack_encoder.h b/quic/core/qpack/qpack_encoder.h index 39600e8..e0bd8d4 100644 --- a/quic/core/qpack/qpack_encoder.h +++ b/quic/core/qpack/qpack_encoder.h
@@ -20,10 +20,16 @@ class SpdyHeaderBlock; -} +} // namespace spdy namespace quic { +namespace test { + +class QpackEncoderPeer; + +} // namespace test + // QPACK encoder class. Exactly one instance should exist per QUIC connection. class QUIC_EXPORT_PRIVATE QpackEncoder : public QpackDecoderStreamReceiver::Delegate { @@ -49,6 +55,14 @@ // Decode data received on the decoder stream. void DecodeDecoderStreamData(QuicStringPiece data); + // Set maximum capacity of dynamic table, measured in bytes. + // Called when SETTINGS_QPACK_MAX_TABLE_CAPACITY is received. + void SetMaximumDynamicTableCapacity(uint64_t maximum_dynamic_table_capacity); + + // Set maximum number of blocked streams. + // Called when SETTINGS_QPACK_BLOCKED_STREAMS is received. + void SetMaximumBlockedStreams(uint64_t maximum_blocked_streams); + // QpackDecoderStreamReceiver::Delegate implementation void OnInsertCountIncrement(uint64_t increment) override; void OnHeaderAcknowledgement(QuicStreamId stream_id) override; @@ -56,6 +70,8 @@ void OnErrorDetected(QuicStringPiece error_message) override; private: + friend class test::QpackEncoderPeer; + // TODO(bnc): Consider moving this class to QpackInstructionEncoder or // qpack_constants, adding factory methods, one for each instruction, and // changing QpackInstructionEncoder::Encoder() to take an @@ -71,6 +87,7 @@ QpackDecoderStreamReceiver decoder_stream_receiver_; QpackEncoderStreamSender encoder_stream_sender_; QpackHeaderTable header_table_; + uint64_t maximum_blocked_streams_; }; } // namespace quic
diff --git a/quic/core/qpack/qpack_header_table.h b/quic/core/qpack/qpack_header_table.h index 4e3b77c..f251894 100644 --- a/quic/core/qpack/qpack_header_table.h +++ b/quic/core/qpack/qpack_header_table.h
@@ -17,6 +17,12 @@ namespace quic { +namespace test { + +class QpackHeaderTablePeer; + +} // namespace test + using QpackEntry = spdy::HpackEntry; // This class manages the QPACK static and dynamic tables. For dynamic entries, @@ -114,6 +120,8 @@ uint64_t draining_index(float draining_fraction) const; private: + friend class test::QpackHeaderTablePeer; + // Evict entries from the dynamic table until table size is less than or equal // to current value of |dynamic_table_capacity_|. void EvictDownToCurrentCapacity();
diff --git a/quic/test_tools/qpack_encoder_peer.cc b/quic/test_tools/qpack_encoder_peer.cc new file mode 100644 index 0000000..4e4bb52 --- /dev/null +++ b/quic/test_tools/qpack_encoder_peer.cc
@@ -0,0 +1,24 @@ +// 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/test_tools/qpack_encoder_peer.h" + +#include "net/third_party/quiche/src/quic/core/qpack/qpack_encoder.h" + +namespace quic { +namespace test { + +// static +QpackHeaderTable* QpackEncoderPeer::header_table(QpackEncoder* encoder) { + return &encoder->header_table_; +} + +// static +uint64_t QpackEncoderPeer::maximum_blocked_streams( + const QpackEncoder* encoder) { + return encoder->maximum_blocked_streams_; +} + +} // namespace test +} // namespace quic
diff --git a/quic/test_tools/qpack_encoder_peer.h b/quic/test_tools/qpack_encoder_peer.h new file mode 100644 index 0000000..b8a8cc7 --- /dev/null +++ b/quic/test_tools/qpack_encoder_peer.h
@@ -0,0 +1,29 @@ +// 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_TEST_TOOLS_QPACK_ENCODER_PEER_H_ +#define QUICHE_QUIC_TEST_TOOLS_QPACK_ENCODER_PEER_H_ + +#include <cstdint> + +namespace quic { + +class QpackEncoder; +class QpackHeaderTable; + +namespace test { + +class QpackEncoderPeer { + public: + QpackEncoderPeer() = delete; + + static QpackHeaderTable* header_table(QpackEncoder* encoder); + static uint64_t maximum_blocked_streams(const QpackEncoder* encoder); +}; + +} // namespace test + +} // namespace quic + +#endif // QUICHE_QUIC_TEST_TOOLS_QPACK_ENCODER_PEER_H_
diff --git a/quic/test_tools/qpack_header_table_peer.cc b/quic/test_tools/qpack_header_table_peer.cc new file mode 100644 index 0000000..37c2961 --- /dev/null +++ b/quic/test_tools/qpack_header_table_peer.cc
@@ -0,0 +1,19 @@ +// 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/test_tools/qpack_header_table_peer.h" + +#include "net/third_party/quiche/src/quic/core/qpack/qpack_header_table.h" + +namespace quic { +namespace test { + +// static +uint64_t QpackHeaderTablePeer::maximum_dynamic_table_capacity( + const QpackHeaderTable* header_table) { + return header_table->maximum_dynamic_table_capacity_; +} + +} // namespace test +} // namespace quic
diff --git a/quic/test_tools/qpack_header_table_peer.h b/quic/test_tools/qpack_header_table_peer.h new file mode 100644 index 0000000..a73859c --- /dev/null +++ b/quic/test_tools/qpack_header_table_peer.h
@@ -0,0 +1,28 @@ +// 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_TEST_TOOLS_QPACK_HEADER_TABLE_PEER_H_ +#define QUICHE_QUIC_TEST_TOOLS_QPACK_HEADER_TABLE_PEER_H_ + +#include <cstdint> + +namespace quic { + +class QpackHeaderTable; + +namespace test { + +class QpackHeaderTablePeer { + public: + QpackHeaderTablePeer() = delete; + + static uint64_t maximum_dynamic_table_capacity( + const QpackHeaderTable* header_table); +}; + +} // namespace test + +} // namespace quic + +#endif // QUICHE_QUIC_TEST_TOOLS_QPACK_HEADER_TABLE_PEER_H_