grpc 1.56.0.pre3 → 1.56.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +4 -2
  3. data/include/grpc/grpc_security.h +19 -0
  4. data/src/core/ext/filters/client_channel/lb_policy/outlier_detection/outlier_detection.cc +1 -1
  5. data/src/core/ext/filters/client_channel/lb_policy/weighted_round_robin/weighted_round_robin.cc +10 -1
  6. data/src/core/ext/transport/chttp2/transport/hpack_parse_result.cc +176 -0
  7. data/src/core/ext/transport/chttp2/transport/hpack_parse_result.h +325 -0
  8. data/src/core/ext/transport/chttp2/transport/hpack_parser.cc +567 -543
  9. data/src/core/ext/transport/chttp2/transport/hpack_parser.h +150 -9
  10. data/src/core/ext/transport/chttp2/transport/hpack_parser_table.cc +46 -32
  11. data/src/core/ext/transport/chttp2/transport/hpack_parser_table.h +18 -5
  12. data/src/core/ext/transport/chttp2/transport/parsing.cc +12 -12
  13. data/src/core/lib/backoff/random_early_detection.h +5 -0
  14. data/src/core/lib/event_engine/posix_engine/posix_engine.h +1 -0
  15. data/src/core/lib/event_engine/posix_engine/posix_engine_listener.cc +29 -0
  16. data/src/core/lib/event_engine/posix_engine/posix_engine_listener.h +3 -0
  17. data/src/core/lib/iomgr/tcp_server_posix.cc +34 -12
  18. data/src/core/lib/iomgr/tcp_server_utils_posix.h +12 -0
  19. data/src/core/lib/iomgr/tcp_server_utils_posix_common.cc +21 -0
  20. data/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc +8 -0
  21. data/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h +5 -1
  22. data/src/core/lib/security/security_connector/ssl_utils.cc +2 -1
  23. data/src/core/lib/security/security_connector/ssl_utils.h +1 -1
  24. data/src/core/lib/security/security_connector/tls/tls_security_connector.cc +1 -1
  25. data/src/core/lib/surface/validate_metadata.cc +37 -22
  26. data/src/core/lib/surface/validate_metadata.h +13 -3
  27. data/src/core/tsi/ssl_transport_security.cc +5 -2
  28. data/src/core/tsi/ssl_transport_security.h +13 -1
  29. data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +2 -0
  30. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +3 -0
  31. data/src/ruby/lib/grpc/version.rb +1 -1
  32. metadata +7 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 82eb96446f478b61dff7f478ccd62182999f29b69cc834cfcb730fcebd3daf7d
4
- data.tar.gz: 8be8ef333de3ebac5750b7e90932c8fdfee6f207ff0c2fa405210749390f0e93
3
+ metadata.gz: 3481eedf57501bb8ae2f09cd0c0a3ad03300047a9e47bee671a6899f1794e4ba
4
+ data.tar.gz: 62506671a0935ef989fe57777830f658c70e0d9393f01c9a4a2d572448d0f975
5
5
  SHA512:
6
- metadata.gz: 50143535fc2dc6cdd48d5e03f9776dc9afab5a1dd5597c17111a0ba344caf479fbc133c785c8bfa3a3d81ee4db6532f64d89c094e351d2a2f4e8e41f971a37f0
7
- data.tar.gz: ee5b69ace3899823ea7bbf51a50b839ec03c6a1480406337ca4f926b33345551b87db6d28eedaaf2888a35af004af356bf74c0a257740b126f5de2a4b511aa15
6
+ metadata.gz: d349ee4daea9488acb1467cb2decc7acbf9d0944a264d1ccb1418fbe2f76e68a5dfbc6f5b38617aa89254a11650fed7988ccbbdf08617c1d491ab5bd2b7756a3
7
+ data.tar.gz: 985dce4d0fa51fa2a2b38449185bdb4959cd43f3dacb70deeab16615974fabb09330288ca71837372978a3a6131c3bebaf7ab1a3d4c6f0a2da9d9dfef61c2fa0
data/Makefile CHANGED
@@ -411,8 +411,8 @@ Q = @
411
411
  endif
412
412
 
413
413
  CORE_VERSION = 33.0.0
414
- CPP_VERSION = 1.56.0-pre3
415
- CSHARP_VERSION = 2.56.0-pre3
414
+ CPP_VERSION = 1.56.2
415
+ CSHARP_VERSION = 2.56.2
416
416
 
417
417
  CPPFLAGS_NO_ARCH += $(addprefix -I, $(INCLUDES)) $(addprefix -D, $(DEFINES))
418
418
  CPPFLAGS += $(CPPFLAGS_NO_ARCH) $(ARCH_FLAGS)
@@ -1058,6 +1058,7 @@ LIBGRPC_SRC = \
1058
1058
  src/core/ext/transport/chttp2/transport/frame_window_update.cc \
1059
1059
  src/core/ext/transport/chttp2/transport/hpack_encoder.cc \
1060
1060
  src/core/ext/transport/chttp2/transport/hpack_encoder_table.cc \
1061
+ src/core/ext/transport/chttp2/transport/hpack_parse_result.cc \
1061
1062
  src/core/ext/transport/chttp2/transport/hpack_parser.cc \
1062
1063
  src/core/ext/transport/chttp2/transport/hpack_parser_table.cc \
1063
1064
  src/core/ext/transport/chttp2/transport/http2_settings.cc \
@@ -1931,6 +1932,7 @@ LIBGRPC_UNSECURE_SRC = \
1931
1932
  src/core/ext/transport/chttp2/transport/frame_window_update.cc \
1932
1933
  src/core/ext/transport/chttp2/transport/hpack_encoder.cc \
1933
1934
  src/core/ext/transport/chttp2/transport/hpack_encoder_table.cc \
1935
+ src/core/ext/transport/chttp2/transport/hpack_parse_result.cc \
1934
1936
  src/core/ext/transport/chttp2/transport/hpack_parser.cc \
1935
1937
  src/core/ext/transport/chttp2/transport/hpack_parser_table.cc \
1936
1938
  src/core/ext/transport/chttp2/transport/http2_settings.cc \
@@ -21,6 +21,8 @@
21
21
 
22
22
  #include <grpc/support/port_platform.h>
23
23
 
24
+ #include <stdbool.h>
25
+
24
26
  #include <grpc/grpc.h>
25
27
  #include <grpc/grpc_security_constants.h>
26
28
  #include <grpc/status.h>
@@ -896,6 +898,23 @@ GRPCAPI void grpc_tls_credentials_options_set_crl_directory(
896
898
  GRPCAPI void grpc_tls_credentials_options_set_verify_server_cert(
897
899
  grpc_tls_credentials_options* options, int verify_server_cert);
898
900
 
901
+ /**
902
+ * EXPERIMENTAL API - Subject to change
903
+ *
904
+ * Sets whether or not a TLS server should send a list of CA names in the
905
+ * ServerHello. This list of CA names is read from the server's trust bundle, so
906
+ * that the client can use this list as a hint to know which certificate it
907
+ * should send to the server.
908
+ *
909
+ * WARNING: This API is extremely dangerous and should not be used. If the
910
+ * server's trust bundle is too large, then the TLS server will be unable to
911
+ * form a ServerHello, and hence will be unusable. The definition of "too large"
912
+ * depends on the underlying SSL library being used and on the size of the CN
913
+ * fields of the certificates in the trust bundle.
914
+ */
915
+ GRPCAPI void grpc_tls_credentials_options_set_send_client_ca_list(
916
+ grpc_tls_credentials_options* options, bool send_client_ca_list);
917
+
899
918
  /**
900
919
  * EXPERIMENTAL API - Subject to change
901
920
  *
@@ -299,7 +299,7 @@ class OutlierDetectionLb : public LoadBalancingPolicy {
299
299
  }
300
300
 
301
301
  void DisableEjection() {
302
- Uneject();
302
+ if (ejection_time_.has_value()) Uneject();
303
303
  multiplier_ = 0;
304
304
  }
305
305
 
@@ -909,12 +909,21 @@ void WeightedRoundRobin::WeightedRoundRobinSubchannelData::
909
909
  subchannel()->RequestConnection();
910
910
  } else if (new_state == GRPC_CHANNEL_READY) {
911
911
  // If we transition back to READY state, restart the blackout period.
912
+ // Skip this if this is the initial notification for this
913
+ // subchannel (which happens whenever we get updated addresses and
914
+ // create a new endpoint list). Also skip it if the previous state
915
+ // was READY (which should never happen in practice, but we've seen
916
+ // at least one bug that caused this in the outlier_detection
917
+ // policy, so let's be defensive here).
918
+ //
912
919
  // Note that we cannot guarantee that we will never receive
913
920
  // lingering callbacks for backend metric reports from the previous
914
921
  // connection after the new connection has been established, but they
915
922
  // should be masked by new backend metric reports from the new
916
923
  // connection by the time the blackout period ends.
917
- weight_->ResetNonEmptySince();
924
+ if (old_state.has_value() && old_state != GRPC_CHANNEL_READY) {
925
+ weight_->ResetNonEmptySince();
926
+ }
918
927
  }
919
928
  // Update logical connectivity state.
920
929
  UpdateLogicalConnectivityStateLocked(new_state);
@@ -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