aboutsummaryrefslogtreecommitdiff
path: root/src/core/ext/transport/chttp2/transport/hpack_parse_result.h
diff options
context:
space:
mode:
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.h97
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