Commit dbb8f5c1 authored by Michael Warres's avatar Michael Warres Committed by Commit Bot

Implement QpackDecoderStreamSender.

Merge internal change: 222419106

R=zhongyi@chromium.org

Change-Id: I78b6a3cc500b4e9b72a135f1c346373d89faf33d
Reviewed-on: https://chromium-review.googlesource.com/c/1394007Reviewed-by: default avatarZhongyi Shi <zhongyi@chromium.org>
Commit-Queue: Zhongyi Shi <zhongyi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#619769}
parent 7194f0ed
......@@ -1315,6 +1315,8 @@ component("net") {
"third_party/quic/core/qpack/qpack_constants.h",
"third_party/quic/core/qpack/qpack_decoder.cc",
"third_party/quic/core/qpack/qpack_decoder.h",
"third_party/quic/core/qpack/qpack_decoder_stream_sender.cc",
"third_party/quic/core/qpack/qpack_decoder_stream_sender.h",
"third_party/quic/core/qpack/qpack_encoder.cc",
"third_party/quic/core/qpack/qpack_encoder.h",
"third_party/quic/core/qpack/qpack_encoder_stream_receiver.cc",
......@@ -5089,6 +5091,7 @@ test("net_unittests") {
"third_party/quic/core/http/spdy_utils_test.cc",
"third_party/quic/core/legacy_quic_stream_id_manager_test.cc",
"third_party/quic/core/packet_number_indexed_queue_test.cc",
"third_party/quic/core/qpack/qpack_decoder_stream_sender_test.cc",
"third_party/quic/core/qpack/qpack_decoder_test.cc",
"third_party/quic/core/qpack/qpack_encoder_stream_receiver_test.cc",
"third_party/quic/core/qpack/qpack_encoder_stream_sender_test.cc",
......
......@@ -56,6 +56,37 @@ const QpackLanguage* QpackEncoderStreamLanguage() {
return language;
}
const QpackInstruction* TableStateSynchronizeInstruction() {
static const QpackInstructionOpcode* const opcode =
new QpackInstructionOpcode{0b00000000, 0b11000000};
static const QpackInstruction* const instruction =
new QpackInstruction{*opcode, {{QpackInstructionFieldType::kVarint, 6}}};
return instruction;
}
const QpackInstruction* HeaderAcknowledgementInstruction() {
static const QpackInstructionOpcode* const opcode =
new QpackInstructionOpcode{0b10000000, 0b10000000};
static const QpackInstruction* const instruction =
new QpackInstruction{*opcode, {{QpackInstructionFieldType::kVarint, 7}}};
return instruction;
}
const QpackInstruction* StreamCancellationInstruction() {
static const QpackInstructionOpcode* const opcode =
new QpackInstructionOpcode{0b01000000, 0b11000000};
static const QpackInstruction* const instruction =
new QpackInstruction{*opcode, {{QpackInstructionFieldType::kVarint, 6}}};
return instruction;
}
const QpackLanguage* QpackDecoderStreamLanguage() {
static const QpackLanguage* const language = new QpackLanguage{
TableStateSynchronizeInstruction(), HeaderAcknowledgementInstruction(),
StreamCancellationInstruction()};
return language;
}
const QpackInstruction* QpackPrefixInstruction() {
// This opcode matches every input.
static const QpackInstructionOpcode* const opcode =
......
......@@ -102,6 +102,20 @@ const QpackInstruction* DynamicTableSizeUpdateInstruction();
// Encoder stream language.
const QpackLanguage* QpackEncoderStreamLanguage();
// 5.3 Decoder stream instructions
// 5.3.1 Table State Synchronize
const QpackInstruction* TableStateSynchronizeInstruction();
// 5.3.2 Header Acknowledgement
const QpackInstruction* HeaderAcknowledgementInstruction();
// 5.3.3 Stream Cancellation
const QpackInstruction* StreamCancellationInstruction();
// Decoder stream language.
const QpackLanguage* QpackDecoderStreamLanguage();
// 5.4.1. Header data prefix instructions
const QpackInstruction* QpackPrefixInstruction();
......
// 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/quic/core/qpack/qpack_decoder_stream_sender.h"
#include <limits>
#include "net/third_party/quic/core/qpack/qpack_constants.h"
#include "net/third_party/quic/platform/api/quic_logging.h"
#include "net/third_party/quic/platform/api/quic_string.h"
namespace quic {
QpackDecoderStreamSender::QpackDecoderStreamSender(Delegate* delegate)
: delegate_(delegate) {
DCHECK(delegate_);
}
void QpackDecoderStreamSender::SendTableStateSynchronize(
uint64_t insert_count) {
instruction_encoder_.set_varint(insert_count);
instruction_encoder_.Encode(TableStateSynchronizeInstruction());
QuicString output;
instruction_encoder_.Next(std::numeric_limits<size_t>::max(), &output);
DCHECK(!instruction_encoder_.HasNext());
delegate_->Write(output);
}
void QpackDecoderStreamSender::SendHeaderAcknowledgement(uint64_t stream_id) {
instruction_encoder_.set_varint(stream_id);
instruction_encoder_.Encode(HeaderAcknowledgementInstruction());
QuicString output;
instruction_encoder_.Next(std::numeric_limits<size_t>::max(), &output);
DCHECK(!instruction_encoder_.HasNext());
delegate_->Write(output);
}
void QpackDecoderStreamSender::SendStreamCancellation(uint64_t stream_id) {
instruction_encoder_.set_varint(stream_id);
instruction_encoder_.Encode(StreamCancellationInstruction());
QuicString output;
instruction_encoder_.Next(std::numeric_limits<size_t>::max(), &output);
DCHECK(!instruction_encoder_.HasNext());
delegate_->Write(output);
}
} // namespace quic
// 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 NET_THIRD_PARTY_QUIC_CORE_QPACK_QPACK_DECODER_STREAM_SENDER_H_
#define NET_THIRD_PARTY_QUIC_CORE_QPACK_QPACK_DECODER_STREAM_SENDER_H_
#include <cstdint>
#include "net/third_party/quic/core/qpack/qpack_instruction_encoder.h"
#include "net/third_party/quic/platform/api/quic_export.h"
#include "net/third_party/quic/platform/api/quic_string_piece.h"
namespace quic {
// This class serializes (encodes) instructions for transmission on the decoder
// stream.
class QUIC_EXPORT_PRIVATE QpackDecoderStreamSender {
public:
// An interface for handling encoded data.
class Delegate {
public:
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;
};
explicit QpackDecoderStreamSender(Delegate* delegate);
QpackDecoderStreamSender() = delete;
QpackDecoderStreamSender(const QpackDecoderStreamSender&) = delete;
QpackDecoderStreamSender& operator=(const QpackDecoderStreamSender&) = delete;
// 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.2 Header Acknowledgement
void SendHeaderAcknowledgement(uint64_t stream_id);
// 5.3.3 Stream Cancellation
void SendStreamCancellation(uint64_t stream_id);
private:
Delegate* const delegate_;
QpackInstructionEncoder instruction_encoder_;
};
} // namespace quic
#endif // NET_THIRD_PARTY_QUIC_CORE_QPACK_QPACK_DECODER_STREAM_SENDER_H_
// 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/quic/core/qpack/qpack_decoder_stream_sender.h"
#include "net/third_party/quic/platform/api/quic_test.h"
#include "net/third_party/quic/platform/api/quic_text_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using ::testing::Eq;
using ::testing::StrictMock;
namespace quic {
namespace test {
namespace {
class MockSenderDelegate : public QpackDecoderStreamSender::Delegate {
public:
~MockSenderDelegate() override = default;
MOCK_METHOD1(Write, void(QuicStringPiece));
};
class QpackDecoderStreamSenderTest : public QuicTest {
protected:
QpackDecoderStreamSenderTest() : stream_(&delegate_) {}
StrictMock<MockSenderDelegate> delegate_;
QpackDecoderStreamSender stream_;
};
TEST_F(QpackDecoderStreamSenderTest, TableStateSynchronize) {
EXPECT_CALL(delegate_, Write(Eq(QuicTextUtils::HexDecode("00"))));
stream_.SendTableStateSynchronize(0);
EXPECT_CALL(delegate_, Write(Eq(QuicTextUtils::HexDecode("0a"))));
stream_.SendTableStateSynchronize(10);
EXPECT_CALL(delegate_, Write(Eq(QuicTextUtils::HexDecode("3f00"))));
stream_.SendTableStateSynchronize(63);
EXPECT_CALL(delegate_, Write(Eq(QuicTextUtils::HexDecode("3f8901"))));
stream_.SendTableStateSynchronize(200);
}
TEST_F(QpackDecoderStreamSenderTest, HeaderAcknowledgement) {
EXPECT_CALL(delegate_, Write(Eq(QuicTextUtils::HexDecode("80"))));
stream_.SendHeaderAcknowledgement(0);
EXPECT_CALL(delegate_, Write(Eq(QuicTextUtils::HexDecode("a5"))));
stream_.SendHeaderAcknowledgement(37);
EXPECT_CALL(delegate_, Write(Eq(QuicTextUtils::HexDecode("ff00"))));
stream_.SendHeaderAcknowledgement(127);
EXPECT_CALL(delegate_, Write(Eq(QuicTextUtils::HexDecode("fff802"))));
stream_.SendHeaderAcknowledgement(503);
}
TEST_F(QpackDecoderStreamSenderTest, StreamCancellation) {
EXPECT_CALL(delegate_, Write(Eq(QuicTextUtils::HexDecode("40"))));
stream_.SendStreamCancellation(0);
EXPECT_CALL(delegate_, Write(Eq(QuicTextUtils::HexDecode("53"))));
stream_.SendStreamCancellation(19);
EXPECT_CALL(delegate_, Write(Eq(QuicTextUtils::HexDecode("7f00"))));
stream_.SendStreamCancellation(63);
EXPECT_CALL(delegate_, Write(Eq(QuicTextUtils::HexDecode("7f2f"))));
stream_.SendStreamCancellation(110);
}
} // namespace
} // namespace test
} // namespace quic
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