grpc 1.55.0 → 1.55.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1f9a054ee1af1ffadd4c0b60c94967408914e245cdbdafe0675789f512b1bade
4
- data.tar.gz: 7df2f0faa6118ae884499d6ef572e1999e204ac13ca0075933ec1bfa68f99dbb
3
+ metadata.gz: 0ae21f1a2c098f42e02627a2f42d31f3ff20ab095fd29e842122418a6ef9a205
4
+ data.tar.gz: 16f30ea02d89e66f113bf4ecb28d34f4507418726acf9ff0f4f371636db2427d
5
5
  SHA512:
6
- metadata.gz: d717d94acde42cbc0fcacb390643e16baa9fc75194f2f2182a4298509d05659c6dd22c81b8425e655a0b59009bd9514be53e637aa1d565bad988bc2d77e54257
7
- data.tar.gz: 6550089a28af60f28c5f07d08626c555c6bf7835de24f92854d7bb137ae1104c651ac410e51856576db4658371bd2d8587037a48933e8a2dd4c589a4aa66c357
6
+ metadata.gz: bc74a95bfe12838c5c28cd47a95e0d8a9abec0634522292831709ddd3e394dfc0ea1a255348f14e32dbf757013043be1d1248dd6c4d51a26f5549a8b9bee1ed6
7
+ data.tar.gz: 68f68a12ef092eebd3333c16eda5b5337378b4615448f25a6da8551b253acba54093ce373e66bbf5eb5304b5be6f243328c0cdf941e57510010e8919c9b93de9
data/Makefile CHANGED
@@ -411,8 +411,8 @@ Q = @
411
411
  endif
412
412
 
413
413
  CORE_VERSION = 32.0.0
414
- CPP_VERSION = 1.55.0
415
- CSHARP_VERSION = 2.55.0
414
+ CPP_VERSION = 1.55.3
415
+ CSHARP_VERSION = 2.55.3
416
416
 
417
417
  CPPFLAGS_NO_ARCH += $(addprefix -I, $(INCLUDES)) $(addprefix -D, $(DEFINES))
418
418
  CPPFLAGS += $(CPPFLAGS_NO_ARCH) $(ARCH_FLAGS)
@@ -1057,6 +1057,7 @@ LIBGRPC_SRC = \
1057
1057
  src/core/ext/transport/chttp2/transport/frame_window_update.cc \
1058
1058
  src/core/ext/transport/chttp2/transport/hpack_encoder.cc \
1059
1059
  src/core/ext/transport/chttp2/transport/hpack_encoder_table.cc \
1060
+ src/core/ext/transport/chttp2/transport/hpack_parse_result.cc \
1060
1061
  src/core/ext/transport/chttp2/transport/hpack_parser.cc \
1061
1062
  src/core/ext/transport/chttp2/transport/hpack_parser_table.cc \
1062
1063
  src/core/ext/transport/chttp2/transport/http2_settings.cc \
@@ -1919,6 +1920,7 @@ LIBGRPC_UNSECURE_SRC = \
1919
1920
  src/core/ext/transport/chttp2/transport/frame_window_update.cc \
1920
1921
  src/core/ext/transport/chttp2/transport/hpack_encoder.cc \
1921
1922
  src/core/ext/transport/chttp2/transport/hpack_encoder_table.cc \
1923
+ src/core/ext/transport/chttp2/transport/hpack_parse_result.cc \
1922
1924
  src/core/ext/transport/chttp2/transport/hpack_parser.cc \
1923
1925
  src/core/ext/transport/chttp2/transport/hpack_parser_table.cc \
1924
1926
  src/core/ext/transport/chttp2/transport/http2_settings.cc \
@@ -3033,6 +3033,8 @@ void ClientChannel::FilterBasedLoadBalancedCall::RecvInitialMetadataReady(
3033
3033
  // recv_initial_metadata_flags is not populated for clients
3034
3034
  self->call_attempt_tracer()->RecordReceivedInitialMetadata(
3035
3035
  self->recv_initial_metadata_);
3036
+ auto* peer_string = self->recv_initial_metadata_->get_pointer(PeerString());
3037
+ if (peer_string != nullptr) self->peer_string_ = peer_string->Ref();
3036
3038
  }
3037
3039
  Closure::Run(DEBUG_LOCATION, self->original_recv_initial_metadata_ready_,
3038
3040
  error);
@@ -3076,12 +3078,8 @@ void ClientChannel::FilterBasedLoadBalancedCall::RecvTrailingMetadataReady(
3076
3078
  }
3077
3079
  }
3078
3080
  absl::string_view peer_string;
3079
- if (self->recv_initial_metadata_ != nullptr) {
3080
- Slice* peer_string_slice =
3081
- self->recv_initial_metadata_->get_pointer(PeerString());
3082
- if (peer_string_slice != nullptr) {
3083
- peer_string = peer_string_slice->as_string_view();
3084
- }
3081
+ if (self->peer_string_.has_value()) {
3082
+ peer_string = self->peer_string_->as_string_view();
3085
3083
  }
3086
3084
  self->RecordCallCompletion(status, self->recv_trailing_metadata_,
3087
3085
  self->transport_stream_stats_, peer_string);
@@ -65,6 +65,7 @@
65
65
  #include "src/core/lib/resolver/resolver.h"
66
66
  #include "src/core/lib/resource_quota/arena.h"
67
67
  #include "src/core/lib/service_config/service_config.h"
68
+ #include "src/core/lib/slice/slice.h"
68
69
  #include "src/core/lib/surface/channel.h"
69
70
  #include "src/core/lib/transport/connectivity_state.h"
70
71
  #include "src/core/lib/transport/metadata_batch.h"
@@ -552,6 +553,7 @@ class ClientChannel::FilterBasedLoadBalancedCall
552
553
  CallCombiner* call_combiner_;
553
554
  grpc_polling_entity* pollent_;
554
555
  grpc_closure* on_call_destruction_complete_;
556
+ absl::optional<Slice> peer_string_;
555
557
 
556
558
  // Set when we get a cancel_stream op.
557
559
  grpc_error_handle cancel_error_;
@@ -0,0 +1,176 @@
1
+ // Copyright 2023 gRPC authors.
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ #include <grpc/support/port_platform.h>
16
+
17
+ #include "src/core/ext/transport/chttp2/transport/hpack_parse_result.h"
18
+
19
+ #include <stddef.h>
20
+
21
+ #include <initializer_list>
22
+
23
+ #include "absl/strings/str_format.h"
24
+
25
+ #include "src/core/ext/transport/chttp2/transport/hpack_constants.h"
26
+ #include "src/core/lib/gprpp/status_helper.h"
27
+ #include "src/core/lib/iomgr/error.h"
28
+ #include "src/core/lib/slice/slice.h"
29
+
30
+ namespace grpc_core {
31
+
32
+ namespace {
33
+ class MetadataSizeLimitExceededEncoder {
34
+ public:
35
+ explicit MetadataSizeLimitExceededEncoder(std::string& summary)
36
+ : summary_(summary) {}
37
+
38
+ void Encode(const Slice& key, const Slice& value) {
39
+ AddToSummary(key.as_string_view(), value.size());
40
+ }
41
+
42
+ template <typename Key, typename Value>
43
+ void Encode(Key, const Value& value) {
44
+ AddToSummary(Key::key(), EncodedSizeOfKey(Key(), value));
45
+ }
46
+
47
+ private:
48
+ void AddToSummary(absl::string_view key,
49
+ size_t value_length) GPR_ATTRIBUTE_NOINLINE {
50
+ absl::StrAppend(&summary_, " ", key, ":",
51
+ hpack_constants::SizeForEntry(key.size(), value_length),
52
+ "B");
53
+ }
54
+ std::string& summary_;
55
+ };
56
+
57
+ absl::Status MakeStreamError(absl::Status error) {
58
+ GPR_DEBUG_ASSERT(!error.ok());
59
+ return grpc_error_set_int(std::move(error), StatusIntProperty::kStreamId, 0);
60
+ }
61
+ } // namespace
62
+
63
+ absl::Status HpackParseResult::Materialize() const {
64
+ if (materialized_status_.has_value()) return *materialized_status_;
65
+ materialized_status_ = BuildMaterialized();
66
+ return *materialized_status_;
67
+ }
68
+
69
+ absl::Status HpackParseResult::BuildMaterialized() const {
70
+ switch (status_.get()) {
71
+ case HpackParseStatus::kOk:
72
+ return absl::OkStatus();
73
+ case HpackParseStatus::kEof:
74
+ Crash("Materialize() called on EOF");
75
+ break;
76
+ case HpackParseStatus::kMovedFrom:
77
+ Crash("Materialize() called on moved-from object");
78
+ break;
79
+ case HpackParseStatus::kInvalidMetadata:
80
+ if (key_.empty()) {
81
+ return MakeStreamError(absl::InternalError(
82
+ ValidateMetadataResultToString(validate_metadata_result_)));
83
+ } else {
84
+ return MakeStreamError(absl::InternalError(absl::StrCat(
85
+ ValidateMetadataResultToString(validate_metadata_result_), ": ",
86
+ key_)));
87
+ }
88
+ case HpackParseStatus::kSoftMetadataLimitExceeded:
89
+ case HpackParseStatus::kHardMetadataLimitExceeded: {
90
+ const auto& e = metadata_limit_exceeded_;
91
+ // Collect a summary of sizes so far for debugging
92
+ // Do not collect contents, for fear of exposing PII.
93
+ std::string summary;
94
+ if (e.prior != nullptr) {
95
+ MetadataSizeLimitExceededEncoder encoder(summary);
96
+ e.prior->Encode(&encoder);
97
+ }
98
+ return MakeStreamError(absl::ResourceExhaustedError(absl::StrCat(
99
+ "received metadata size exceeds ",
100
+ status_.get() == HpackParseStatus::kSoftMetadataLimitExceeded
101
+ ? "soft"
102
+ : "hard",
103
+ " limit (", e.frame_length, " vs. ", e.limit, ")",
104
+ summary.empty() ? "" : "; ", summary)));
105
+ }
106
+ case HpackParseStatus::kHardMetadataLimitExceededByKey: {
107
+ const auto& e = metadata_limit_exceeded_by_atom_;
108
+ return MakeStreamError(absl::ResourceExhaustedError(
109
+ absl::StrCat("received metadata size exceeds hard limit (key length ",
110
+ e.atom_length, " vs. ", e.limit, ")")));
111
+ }
112
+ case HpackParseStatus::kHardMetadataLimitExceededByValue: {
113
+ const auto& e = metadata_limit_exceeded_by_atom_;
114
+ return MakeStreamError(absl::ResourceExhaustedError(absl::StrCat(
115
+ "received metadata size exceeds hard limit (value length ",
116
+ e.atom_length, " vs. ", e.limit, ")")));
117
+ }
118
+ case HpackParseStatus::kMetadataParseError:
119
+ if (!key_.empty()) {
120
+ return MakeStreamError(absl::InternalError(
121
+ absl::StrCat("Error parsing '", key_, "' metadata")));
122
+ } else {
123
+ return MakeStreamError(absl::InternalError("Error parsing metadata"));
124
+ }
125
+ case HpackParseStatus::kUnbase64Failed:
126
+ if (!key_.empty()) {
127
+ return MakeStreamError(absl::InternalError(absl::StrCat(
128
+ "Error parsing '", key_, "' metadata: illegal base64 encoding")));
129
+ } else {
130
+ return MakeStreamError(absl::InternalError(
131
+ absl::StrCat("Failed base64 decoding metadata")));
132
+ }
133
+ case HpackParseStatus::kIncompleteHeaderAtBoundary:
134
+ return absl::InternalError(
135
+ "Incomplete header at the end of a header/continuation sequence");
136
+ case HpackParseStatus::kVarintOutOfRange:
137
+ return absl::InternalError(absl::StrFormat(
138
+ "integer overflow in hpack integer decoding: have 0x%08x, "
139
+ "got byte 0x%02x",
140
+ varint_out_of_range_.value, varint_out_of_range_.last_byte));
141
+ case HpackParseStatus::kIllegalTableSizeChange:
142
+ return absl::InternalError(absl::StrCat(
143
+ "Attempt to make hpack table ", illegal_table_size_change_.new_size,
144
+ " bytes when max is ", illegal_table_size_change_.max_size,
145
+ " bytes"));
146
+ case HpackParseStatus::kAddBeforeTableSizeUpdated:
147
+ return absl::InternalError(
148
+ absl::StrCat("HPACK max table size reduced to ",
149
+ illegal_table_size_change_.new_size,
150
+ " but not reflected by hpack stream (still at ",
151
+ illegal_table_size_change_.max_size, ")"));
152
+ case HpackParseStatus::kParseHuffFailed:
153
+ if (!key_.empty()) {
154
+ return absl::InternalError(
155
+ absl::StrCat("Failed huffman decoding '", key_, "' metadata"));
156
+ } else {
157
+ return absl::InternalError(
158
+ absl::StrCat("Failed huffman decoding metadata"));
159
+ }
160
+ break;
161
+ case HpackParseStatus::kTooManyDynamicTableSizeChanges:
162
+ return absl::InternalError(
163
+ "More than two max table size changes in a single frame");
164
+ case HpackParseStatus::kMaliciousVarintEncoding:
165
+ return absl::InternalError(
166
+ "Malicious varint encoding detected in HPACK stream");
167
+ case HpackParseStatus::kInvalidHpackIndex:
168
+ return absl::InternalError(absl::StrFormat(
169
+ "Invalid HPACK index received (%d)", invalid_hpack_index_));
170
+ case HpackParseStatus::kIllegalHpackOpCode:
171
+ return absl::InternalError("Illegal hpack op code");
172
+ }
173
+ GPR_UNREACHABLE_CODE(return absl::UnknownError("Should never reach here"));
174
+ }
175
+
176
+ } // namespace grpc_core
@@ -0,0 +1,325 @@
1
+ // Copyright 2023 gRPC authors.
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ #ifndef GRPC_SRC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HPACK_PARSE_RESULT_H
16
+ #define GRPC_SRC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HPACK_PARSE_RESULT_H
17
+
18
+ #include <grpc/support/port_platform.h>
19
+
20
+ #include <stdint.h>
21
+
22
+ #include <string>
23
+ #include <utility>
24
+
25
+ #include "absl/status/status.h"
26
+ #include "absl/strings/str_cat.h"
27
+ #include "absl/strings/string_view.h"
28
+ #include "absl/types/optional.h"
29
+
30
+ #include <grpc/support/log.h>
31
+
32
+ #include "src/core/lib/gprpp/crash.h"
33
+ #include "src/core/lib/surface/validate_metadata.h"
34
+ #include "src/core/lib/transport/metadata_batch.h"
35
+
36
+ namespace grpc_core {
37
+
38
+ // Result of parsing
39
+ // Makes it trivial to identify stream vs connection errors (via a range check)
40
+ enum class HpackParseStatus : uint8_t {
41
+ ///////////////////////////////////////////////////////
42
+ // Non-Errors
43
+
44
+ // Parsed OK
45
+ kOk,
46
+ // Parse reached end of the current frame
47
+ kEof,
48
+ // Moved from - used to denote a HpackParseResult that has been moved into a
49
+ // different object, and so the original should be deemed invalid.
50
+ kMovedFrom,
51
+
52
+ ///////////////////////////////////////////////////////////////////
53
+ // Stream Errors - result in a stream cancellation
54
+
55
+ // Sentinel value used to denote the first error that is a stream error.
56
+ // All stream errors are hence >= kFirstStreamError and <
57
+ // kFirstConnectionError.
58
+ // Should not be used in switch statements, instead the first error message
59
+ // after this one should be assigned the same value.
60
+ kFirstStreamError,
61
+ kInvalidMetadata = kFirstStreamError,
62
+ // Hard metadata limit exceeded by the total set of metadata
63
+ kHardMetadataLimitExceeded,
64
+ kSoftMetadataLimitExceeded,
65
+ // Hard metadata limit exceeded by a single key string
66
+ kHardMetadataLimitExceededByKey,
67
+ // Hard metadata limit exceeded by a single value string
68
+ kHardMetadataLimitExceededByValue,
69
+ kMetadataParseError,
70
+ // Parse failed due to a base64 decode error
71
+ kUnbase64Failed,
72
+
73
+ ///////////////////////////////////////////////////////////////////
74
+ // Connection Errors - result in the tcp connection closing
75
+
76
+ // Sentinel value used to denote the first error that is a connection error.
77
+ // All connection errors are hence >= kFirstConnectionError.
78
+ // Should not be used in switch statements, instead the first error message
79
+ // after this one should be assigned the same value.
80
+ kFirstConnectionError,
81
+ // Incomplete header at end of header boundary
82
+ kIncompleteHeaderAtBoundary = kFirstConnectionError,
83
+ // Varint out of range
84
+ kVarintOutOfRange,
85
+ // Invalid HPACK index
86
+ kInvalidHpackIndex,
87
+ // Illegal HPACK table size change
88
+ kIllegalTableSizeChange,
89
+ // Trying to add to the hpack table prior to reducing after a settings change
90
+ kAddBeforeTableSizeUpdated,
91
+ // Parse failed due to a huffman decode error
92
+ kParseHuffFailed,
93
+ // Too many dynamic table size changes in one frame
94
+ kTooManyDynamicTableSizeChanges,
95
+ // Maliciously long varint encoding
96
+ // We don't read past 16 repeated 0x80 prefixes on a varint (all zeros)
97
+ // because no reasonable varint encoder would emit that (16 is already quite
98
+ // generous!)
99
+ // Because we stop reading we don't parse the rest of the bytes and so we
100
+ // can't recover parsing and would end up with a hpack table desync if we
101
+ // tried, so this is a connection error.
102
+ kMaliciousVarintEncoding,
103
+ // Illegal hpack op code
104
+ kIllegalHpackOpCode,
105
+ };
106
+
107
+ inline bool IsStreamError(HpackParseStatus status) {
108
+ return status >= HpackParseStatus::kFirstStreamError &&
109
+ status < HpackParseStatus::kFirstConnectionError;
110
+ }
111
+
112
+ inline bool IsConnectionError(HpackParseStatus status) {
113
+ return status >= HpackParseStatus::kFirstConnectionError;
114
+ }
115
+
116
+ inline bool IsEphemeralError(HpackParseStatus status) {
117
+ switch (status) {
118
+ case HpackParseStatus::kSoftMetadataLimitExceeded:
119
+ case HpackParseStatus::kHardMetadataLimitExceeded:
120
+ return true;
121
+ default:
122
+ return false;
123
+ }
124
+ }
125
+
126
+ class HpackParseResult {
127
+ public:
128
+ HpackParseResult() : HpackParseResult{HpackParseStatus::kOk} {}
129
+
130
+ bool ok() const { return status_.get() == HpackParseStatus::kOk; }
131
+ bool stream_error() const { return IsStreamError(status_.get()); }
132
+ bool connection_error() const { return IsConnectionError(status_.get()); }
133
+ bool ephemeral() const { return IsEphemeralError(status_.get()); }
134
+
135
+ HpackParseResult PersistentStreamErrorOrOk() const {
136
+ if (connection_error() || ephemeral()) return HpackParseResult();
137
+ return *this;
138
+ }
139
+
140
+ static HpackParseResult FromStatus(HpackParseStatus status) {
141
+ // Most statuses need some payloads, and we only need this functionality
142
+ // rarely - so allow list the statuses that we can include here.
143
+ switch (status) {
144
+ case HpackParseStatus::kUnbase64Failed:
145
+ case HpackParseStatus::kParseHuffFailed:
146
+ return HpackParseResult{status};
147
+ default:
148
+ Crash(
149
+ absl::StrCat("Invalid HpackParseStatus for FromStatus: ", status));
150
+ }
151
+ }
152
+
153
+ static HpackParseResult FromStatusWithKey(HpackParseStatus status,
154
+ absl::string_view key) {
155
+ auto r = FromStatus(status);
156
+ r.key_ = std::string(key);
157
+ return r;
158
+ }
159
+
160
+ static HpackParseResult MetadataParseError(absl::string_view key) {
161
+ HpackParseResult r{HpackParseStatus::kMetadataParseError};
162
+ r.key_ = std::string(key);
163
+ return r;
164
+ }
165
+
166
+ static HpackParseResult AddBeforeTableSizeUpdated(uint32_t current_size,
167
+ uint32_t max_size) {
168
+ HpackParseResult p{HpackParseStatus::kAddBeforeTableSizeUpdated};
169
+ p.illegal_table_size_change_ =
170
+ IllegalTableSizeChange{current_size, max_size};
171
+ return p;
172
+ }
173
+
174
+ static HpackParseResult MaliciousVarintEncodingError() {
175
+ return HpackParseResult{HpackParseStatus::kMaliciousVarintEncoding};
176
+ }
177
+
178
+ static HpackParseResult IllegalHpackOpCode() {
179
+ return HpackParseResult{HpackParseStatus::kIllegalHpackOpCode};
180
+ }
181
+
182
+ static HpackParseResult InvalidMetadataError(ValidateMetadataResult result,
183
+ absl::string_view key) {
184
+ GPR_DEBUG_ASSERT(result != ValidateMetadataResult::kOk);
185
+ HpackParseResult p{HpackParseStatus::kInvalidMetadata};
186
+ p.key_ = std::string(key);
187
+ p.validate_metadata_result_ = result;
188
+ return p;
189
+ }
190
+
191
+ static HpackParseResult IncompleteHeaderAtBoundaryError() {
192
+ return HpackParseResult{HpackParseStatus::kIncompleteHeaderAtBoundary};
193
+ }
194
+
195
+ static HpackParseResult VarintOutOfRangeError(uint32_t value,
196
+ uint8_t last_byte) {
197
+ HpackParseResult p{HpackParseStatus::kVarintOutOfRange};
198
+ p.varint_out_of_range_ = VarintOutOfRange{last_byte, value};
199
+ return p;
200
+ }
201
+
202
+ static HpackParseResult InvalidHpackIndexError(uint32_t index) {
203
+ HpackParseResult p{HpackParseStatus::kInvalidHpackIndex};
204
+ p.invalid_hpack_index_ = index;
205
+ return p;
206
+ }
207
+
208
+ static HpackParseResult IllegalTableSizeChangeError(uint32_t new_size,
209
+ uint32_t max_size) {
210
+ HpackParseResult p{HpackParseStatus::kIllegalTableSizeChange};
211
+ p.illegal_table_size_change_ = IllegalTableSizeChange{new_size, max_size};
212
+ return p;
213
+ }
214
+
215
+ static HpackParseResult TooManyDynamicTableSizeChangesError() {
216
+ return HpackParseResult{HpackParseStatus::kTooManyDynamicTableSizeChanges};
217
+ }
218
+
219
+ static HpackParseResult SoftMetadataLimitExceededError(
220
+ grpc_metadata_batch* metadata, uint32_t frame_length, uint32_t limit) {
221
+ HpackParseResult p{HpackParseStatus::kSoftMetadataLimitExceeded};
222
+ p.metadata_limit_exceeded_ =
223
+ MetadataLimitExceeded{frame_length, limit, metadata};
224
+ return p;
225
+ }
226
+
227
+ static HpackParseResult HardMetadataLimitExceededError(
228
+ grpc_metadata_batch* metadata, uint32_t frame_length, uint32_t limit) {
229
+ HpackParseResult p{HpackParseStatus::kHardMetadataLimitExceeded};
230
+ p.metadata_limit_exceeded_ =
231
+ MetadataLimitExceeded{frame_length, limit, metadata};
232
+ return p;
233
+ }
234
+
235
+ static HpackParseResult HardMetadataLimitExceededByKeyError(
236
+ uint32_t key_length, uint32_t limit) {
237
+ HpackParseResult p{HpackParseStatus::kHardMetadataLimitExceededByKey};
238
+ p.metadata_limit_exceeded_by_atom_ =
239
+ MetadataLimitExceededByAtom{key_length, limit};
240
+ return p;
241
+ }
242
+
243
+ static HpackParseResult HardMetadataLimitExceededByValueError(
244
+ absl::string_view key, uint32_t value_length, uint32_t limit) {
245
+ HpackParseResult p{HpackParseStatus::kHardMetadataLimitExceededByValue};
246
+ p.metadata_limit_exceeded_by_atom_ =
247
+ MetadataLimitExceededByAtom{value_length, limit};
248
+ p.key_ = std::string(key);
249
+ return p;
250
+ }
251
+
252
+ // Compute the absl::Status that goes along with this HpackParseResult.
253
+ // (may be cached, so this is not thread safe)
254
+ absl::Status Materialize() const;
255
+
256
+ private:
257
+ explicit HpackParseResult(HpackParseStatus status) : status_(status) {}
258
+ absl::Status BuildMaterialized() const;
259
+
260
+ struct VarintOutOfRange {
261
+ uint8_t last_byte;
262
+ uint32_t value;
263
+ };
264
+
265
+ struct MetadataLimitExceeded {
266
+ uint32_t frame_length;
267
+ uint32_t limit;
268
+ grpc_metadata_batch* prior;
269
+ };
270
+
271
+ // atom here means one of either a key or a value - so this is used for when a
272
+ // metadata limit is consumed by either of these.
273
+ struct MetadataLimitExceededByAtom {
274
+ uint32_t atom_length;
275
+ uint32_t limit;
276
+ };
277
+
278
+ struct IllegalTableSizeChange {
279
+ uint32_t new_size;
280
+ uint32_t max_size;
281
+ };
282
+
283
+ class StatusWrapper {
284
+ public:
285
+ explicit StatusWrapper(HpackParseStatus status) : status_(status) {}
286
+
287
+ StatusWrapper(const StatusWrapper&) = default;
288
+ StatusWrapper& operator=(const StatusWrapper&) = default;
289
+ StatusWrapper(StatusWrapper&& other) noexcept
290
+ : status_(std::exchange(other.status_, HpackParseStatus::kMovedFrom)) {}
291
+ StatusWrapper& operator=(StatusWrapper&& other) noexcept {
292
+ status_ = std::exchange(other.status_, HpackParseStatus::kMovedFrom);
293
+ return *this;
294
+ }
295
+
296
+ HpackParseStatus get() const { return status_; }
297
+
298
+ private:
299
+ HpackParseStatus status_;
300
+ };
301
+
302
+ StatusWrapper status_;
303
+ union {
304
+ // Set if status == kInvalidMetadata
305
+ ValidateMetadataResult validate_metadata_result_;
306
+ // Set if status == kVarintOutOfRange
307
+ VarintOutOfRange varint_out_of_range_;
308
+ // Set if status == kInvalidHpackIndex
309
+ uint32_t invalid_hpack_index_;
310
+ // Set if status == kHardMetadataLimitExceeded or
311
+ // kSoftMetadataLimitExceeded
312
+ MetadataLimitExceeded metadata_limit_exceeded_;
313
+ // Set if status == kHardMetadataLimitExceededByKey or
314
+ // kHardMetadataLimitExceededByValue
315
+ MetadataLimitExceededByAtom metadata_limit_exceeded_by_atom_;
316
+ // Set if status == kIllegalTableSizeChange
317
+ IllegalTableSizeChange illegal_table_size_change_;
318
+ };
319
+ std::string key_;
320
+ mutable absl::optional<absl::Status> materialized_status_;
321
+ };
322
+
323
+ } // namespace grpc_core
324
+
325
+ #endif // GRPC_SRC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_HPACK_PARSE_RESULT_H