diff options
Diffstat (limited to 'src/core/ext/transport/chttp2/transport/hpack_parse_result.h')
-rw-r--r-- | src/core/ext/transport/chttp2/transport/hpack_parse_result.h | 97 |
1 files changed, 61 insertions, 36 deletions
diff --git a/src/core/ext/transport/chttp2/transport/hpack_parse_result.h b/src/core/ext/transport/chttp2/transport/hpack_parse_result.h index 188b1563b4..4a551e9447 100644 --- a/src/core/ext/transport/chttp2/transport/hpack_parse_result.h +++ b/src/core/ext/transport/chttp2/transport/hpack_parse_result.h @@ -31,6 +31,8 @@ #include <grpc/support/log.h> #include "src/core/lib/gprpp/crash.h" +#include "src/core/lib/gprpp/ref_counted.h" +#include "src/core/lib/gprpp/ref_counted_ptr.h" #include "src/core/lib/surface/validate_metadata.h" #include "src/core/lib/transport/metadata_batch.h" @@ -128,10 +130,18 @@ class HpackParseResult { public: HpackParseResult() : HpackParseResult{HpackParseStatus::kOk} {} - bool ok() const { return status_.get() == HpackParseStatus::kOk; } - bool stream_error() const { return IsStreamError(status_.get()); } - bool connection_error() const { return IsConnectionError(status_.get()); } - bool ephemeral() const { return IsEphemeralError(status_.get()); } + bool ok() const { + return state_ == nullptr || state_->status.get() == HpackParseStatus::kOk; + } + bool stream_error() const { + return state_ != nullptr && IsStreamError(state_->status.get()); + } + bool connection_error() const { + return state_ != nullptr && IsConnectionError(state_->status.get()); + } + bool ephemeral() const { + return state_ != nullptr && IsEphemeralError(state_->status.get()); + } std::unique_ptr<HpackParseResult> PersistentStreamErrorOrNullptr() const { if (ok() || connection_error() || ephemeral()) return nullptr; @@ -154,20 +164,22 @@ class HpackParseResult { static HpackParseResult FromStatusWithKey(HpackParseStatus status, absl::string_view key) { auto r = FromStatus(status); - r.key_ = std::string(key); + if (r.state_ != nullptr) { + r.state_->key = std::string(key); + } return r; } static HpackParseResult MetadataParseError(absl::string_view key) { HpackParseResult r{HpackParseStatus::kMetadataParseError}; - r.key_ = std::string(key); + r.state_->key = std::string(key); return r; } static HpackParseResult AddBeforeTableSizeUpdated(uint32_t current_size, uint32_t max_size) { HpackParseResult p{HpackParseStatus::kAddBeforeTableSizeUpdated}; - p.illegal_table_size_change_ = + p.state_->illegal_table_size_change = IllegalTableSizeChange{current_size, max_size}; return p; } @@ -184,8 +196,8 @@ class HpackParseResult { absl::string_view key) { GPR_DEBUG_ASSERT(result != ValidateMetadataResult::kOk); HpackParseResult p{HpackParseStatus::kInvalidMetadata}; - p.key_ = std::string(key); - p.validate_metadata_result_ = result; + p.state_->key = std::string(key); + p.state_->validate_metadata_result = result; return p; } @@ -196,20 +208,21 @@ class HpackParseResult { static HpackParseResult VarintOutOfRangeError(uint32_t value, uint8_t last_byte) { HpackParseResult p{HpackParseStatus::kVarintOutOfRange}; - p.varint_out_of_range_ = VarintOutOfRange{last_byte, value}; + p.state_->varint_out_of_range = VarintOutOfRange{last_byte, value}; return p; } static HpackParseResult InvalidHpackIndexError(uint32_t index) { HpackParseResult p{HpackParseStatus::kInvalidHpackIndex}; - p.invalid_hpack_index_ = index; + p.state_->invalid_hpack_index = index; return p; } static HpackParseResult IllegalTableSizeChangeError(uint32_t new_size, uint32_t max_size) { HpackParseResult p{HpackParseStatus::kIllegalTableSizeChange}; - p.illegal_table_size_change_ = IllegalTableSizeChange{new_size, max_size}; + p.state_->illegal_table_size_change = + IllegalTableSizeChange{new_size, max_size}; return p; } @@ -220,7 +233,7 @@ class HpackParseResult { static HpackParseResult SoftMetadataLimitExceededError( grpc_metadata_batch* metadata, uint32_t frame_length, uint32_t limit) { HpackParseResult p{HpackParseStatus::kSoftMetadataLimitExceeded}; - p.metadata_limit_exceeded_ = + p.state_->metadata_limit_exceeded = MetadataLimitExceeded{frame_length, limit, metadata}; return p; } @@ -228,7 +241,7 @@ class HpackParseResult { static HpackParseResult HardMetadataLimitExceededError( grpc_metadata_batch* metadata, uint32_t frame_length, uint32_t limit) { HpackParseResult p{HpackParseStatus::kHardMetadataLimitExceeded}; - p.metadata_limit_exceeded_ = + p.state_->metadata_limit_exceeded = MetadataLimitExceeded{frame_length, limit, metadata}; return p; } @@ -236,7 +249,7 @@ class HpackParseResult { static HpackParseResult HardMetadataLimitExceededByKeyError( uint32_t key_length, uint32_t limit) { HpackParseResult p{HpackParseStatus::kHardMetadataLimitExceededByKey}; - p.metadata_limit_exceeded_by_atom_ = + p.state_->metadata_limit_exceeded_by_atom = MetadataLimitExceededByAtom{key_length, limit}; return p; } @@ -244,9 +257,9 @@ class HpackParseResult { static HpackParseResult HardMetadataLimitExceededByValueError( absl::string_view key, uint32_t value_length, uint32_t limit) { HpackParseResult p{HpackParseStatus::kHardMetadataLimitExceededByValue}; - p.metadata_limit_exceeded_by_atom_ = + p.state_->metadata_limit_exceeded_by_atom = MetadataLimitExceededByAtom{value_length, limit}; - p.key_ = std::string(key); + p.state_->key = std::string(key); return p; } @@ -255,7 +268,13 @@ class HpackParseResult { absl::Status Materialize() const; private: - explicit HpackParseResult(HpackParseStatus status) : status_(status) {} + explicit HpackParseResult(HpackParseStatus status) { + // Dynamically allocate state if status is not ok. + if (status != HpackParseStatus::kOk) { + state_ = MakeRefCounted<HpackParseResultState>(status); + } + } + absl::Status BuildMaterialized() const; struct VarintOutOfRange { @@ -300,25 +319,31 @@ class HpackParseResult { HpackParseStatus status_; }; - StatusWrapper status_; - union { - // Set if status == kInvalidMetadata - ValidateMetadataResult validate_metadata_result_; - // Set if status == kVarintOutOfRange - VarintOutOfRange varint_out_of_range_; - // Set if status == kInvalidHpackIndex - uint32_t invalid_hpack_index_; - // Set if status == kHardMetadataLimitExceeded or - // kSoftMetadataLimitExceeded - MetadataLimitExceeded metadata_limit_exceeded_; - // Set if status == kHardMetadataLimitExceededByKey or - // kHardMetadataLimitExceededByValue - MetadataLimitExceededByAtom metadata_limit_exceeded_by_atom_; - // Set if status == kIllegalTableSizeChange - IllegalTableSizeChange illegal_table_size_change_; + struct HpackParseResultState : public RefCounted<HpackParseResultState> { + explicit HpackParseResultState(HpackParseStatus incoming_status) + : status(incoming_status) {} + StatusWrapper status; + union { + // Set if status == kInvalidMetadata + ValidateMetadataResult validate_metadata_result; + // Set if status == kVarintOutOfRange + VarintOutOfRange varint_out_of_range; + // Set if status == kInvalidHpackIndex + uint32_t invalid_hpack_index; + // Set if status == kHardMetadataLimitExceeded or + // kSoftMetadataLimitExceeded + MetadataLimitExceeded metadata_limit_exceeded; + // Set if status == kHardMetadataLimitExceededByKey or + // kHardMetadataLimitExceededByValue + MetadataLimitExceededByAtom metadata_limit_exceeded_by_atom; + // Set if status == kIllegalTableSizeChange + IllegalTableSizeChange illegal_table_size_change; + }; + std::string key; + mutable absl::optional<absl::Status> materialized_status; }; - std::string key_; - mutable absl::optional<absl::Status> materialized_status_; + + RefCountedPtr<HpackParseResultState> state_ = nullptr; }; } // namespace grpc_core |