blob: ab808748a4b3fedfed0d98090a537015b0c0d827 [file] [log] [blame]
// 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_QPACK_QPACK_INSTRUCTIONS_H_
#define QUICHE_QUIC_CORE_QPACK_QPACK_INSTRUCTIONS_H_
#include <cstdint>
#include <string>
#include <tuple>
#include <vector>
#include "absl/strings/string_view.h"
#include "quiche/quic/platform/api/quic_export.h"
namespace quic {
namespace test {
class QpackInstructionWithValuesPeer;
} // namespace test
// Each instruction is identified with an opcode in the first byte.
// |mask| determines which bits are part of the opcode.
// |value| is the value of these bits. (Other bits in value must be zero.)
struct QUICHE_EXPORT QpackInstructionOpcode {
uint8_t value;
uint8_t mask;
};
bool operator==(const QpackInstructionOpcode& a,
const QpackInstructionOpcode& b);
// Possible types of an instruction field. Decoding a static bit does not
// consume the current byte. Decoding an integer or a length-prefixed string
// 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. 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 Encoded Required Insert Count.
kVarint,
// A second integer encoded with variable length encoding. This could be
// Delta Base.
kVarint2,
// A header name or header value encoded as:
// a bit indicating whether it is Huffman encoded;
// the encoded length of the string;
// the header name or value optionally Huffman encoded.
kName,
kValue
};
// Each instruction field has a type and a parameter.
// The meaning of the parameter depends on the field type.
struct QUICHE_EXPORT QpackInstructionField {
QpackInstructionFieldType type;
// For a kSbit field, |param| is a mask with exactly one bit set.
// For kVarint fields, |param| is the prefix length of the integer encoding.
// For kName and kValue fields, |param| is the prefix length of the length of
// the string, and the bit immediately preceding the prefix is interpreted as
// the Huffman bit.
uint8_t param;
};
using QpackInstructionFields = std::vector<QpackInstructionField>;
// A QPACK instruction consists of an opcode identifying the instruction,
// followed by a non-empty list of fields. The last field must be integer or
// string literal type to guarantee that all bytes of the instruction are
// consumed.
struct QUICHE_EXPORT QpackInstruction {
QpackInstruction(QpackInstructionOpcode opcode, QpackInstructionFields fields)
: opcode(std::move(opcode)), fields(std::move(fields)) {}
QpackInstruction(const QpackInstruction&) = delete;
const QpackInstruction& operator=(const QpackInstruction&) = delete;
QpackInstructionOpcode opcode;
QpackInstructionFields fields;
};
// A language is a collection of instructions. The order does not matter.
// Every possible input must match exactly one instruction.
using QpackLanguage = std::vector<const QpackInstruction*>;
// Wire format defined in
// https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#rfc.section.5
// 5.2 Encoder stream instructions
// 5.2.1 Insert With Name Reference
const QpackInstruction* InsertWithNameReferenceInstruction();
// 5.2.2 Insert Without Name Reference
const QpackInstruction* InsertWithoutNameReferenceInstruction();
// 5.2.3 Duplicate
const QpackInstruction* DuplicateInstruction();
// 5.2.4 Dynamic Table Size Update
const QpackInstruction* SetDynamicTableCapacityInstruction();
// Encoder stream language.
const QpackLanguage* QpackEncoderStreamLanguage();
// 5.3 Decoder stream instructions
// 5.3.1 Insert Count Increment
const QpackInstruction* InsertCountIncrementInstruction();
// 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();
const QpackLanguage* QpackPrefixLanguage();
// 5.4.2. Request and push stream instructions
// 5.4.2.1. Indexed Header Field
const QpackInstruction* QpackIndexedHeaderFieldInstruction();
// 5.4.2.2. Indexed Header Field With Post-Base Index
const QpackInstruction* QpackIndexedHeaderFieldPostBaseInstruction();
// 5.4.2.3. Literal Header Field With Name Reference
const QpackInstruction* QpackLiteralHeaderFieldNameReferenceInstruction();
// 5.4.2.4. Literal Header Field With Post-Base Name Reference
const QpackInstruction* QpackLiteralHeaderFieldPostBaseInstruction();
// 5.4.2.5. Literal Header Field Without Name Reference
const QpackInstruction* QpackLiteralHeaderFieldInstruction();
// Request and push stream language.
const QpackLanguage* QpackRequestStreamLanguage();
// Storage for instruction and field values to be encoded.
// This class can only be instantiated using factory methods that take exactly
// the arguments that the corresponding instruction needs.
class QUICHE_EXPORT QpackInstructionWithValues {
public:
// 5.2 Encoder stream instructions
static QpackInstructionWithValues InsertWithNameReference(
bool is_static, uint64_t name_index, absl::string_view value);
static QpackInstructionWithValues InsertWithoutNameReference(
absl::string_view name, absl::string_view value);
static QpackInstructionWithValues Duplicate(uint64_t index);
static QpackInstructionWithValues SetDynamicTableCapacity(uint64_t capacity);
// 5.3 Decoder stream instructions
static QpackInstructionWithValues InsertCountIncrement(uint64_t increment);
static QpackInstructionWithValues HeaderAcknowledgement(uint64_t stream_id);
static QpackInstructionWithValues StreamCancellation(uint64_t stream_id);
// 5.4.1. Header data prefix. Delta Base is hardcoded to be zero.
static QpackInstructionWithValues Prefix(uint64_t required_insert_count);
// 5.4.2. Request and push stream instructions
static QpackInstructionWithValues IndexedHeaderField(bool is_static,
uint64_t index);
static QpackInstructionWithValues LiteralHeaderFieldNameReference(
bool is_static, uint64_t index, absl::string_view value);
static QpackInstructionWithValues LiteralHeaderField(absl::string_view name,
absl::string_view value);
const QpackInstruction* instruction() const { return instruction_; }
bool s_bit() const { return s_bit_; }
uint64_t varint() const { return varint_; }
uint64_t varint2() const { return varint2_; }
absl::string_view name() const { return name_; }
absl::string_view value() const { return value_; }
// Used by QpackEncoder, because in the first pass it stores absolute indices,
// which are converted into relative indices in the second pass after base is
// determined.
void set_varint(uint64_t varint) { varint_ = varint; }
private:
friend test::QpackInstructionWithValuesPeer;
QpackInstructionWithValues() = default;
// |*instruction| is not owned.
const QpackInstruction* instruction_ = nullptr;
bool s_bit_ = false;
uint64_t varint_ = 0;
uint64_t varint2_ = 0;
absl::string_view name_;
absl::string_view value_;
};
} // namespace quic
#endif // QUICHE_QUIC_CORE_QPACK_QPACK_INSTRUCTIONS_H_