grpc 1.83.0.pre1 → 1.83.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d9d4fc83c3f58cf1edbbbd20d851c69c661d50e3f01a011215bfa8c852acf99e
4
- data.tar.gz: 8bac1533c21612e978093963232793392c5d8f7c9bebcf9778a4684a42d3c11a
3
+ metadata.gz: b7cad78eb1a239fccff217f8dfda9db31f92a3f0f32b713a55cf26ebc782c5e3
4
+ data.tar.gz: '039647b8a259b5e5c561efd5e23c0831d2caa17184ad92f4da26b8de00fe2594'
5
5
  SHA512:
6
- metadata.gz: ec25876a53fcccba31939ecda4a9f4cb4a59d4849a2f9de3b0533d0d7426d3f5b4ebb95f9c2ec3b9108e9f2b9d9c0dedf28b6fbd5db7b66f5ce25a5a5f0eaa7a
7
- data.tar.gz: af3aca7939347829f5ab735f79451b14101c3109168f5892f0290aabb44fa0e9e5177215c31abaacc1e0b49e459ce86320ea1ab1b4d8e6280a5f7fab6829ae45
6
+ metadata.gz: a442ff623a15321dc764714d9389c6cf58db45b8d7f5a73d40161d9277f7ff34ea6796a8e07cc9eece2443a1f37f406bea2b6b19804311545c2ebb444fc1c8e2
7
+ data.tar.gz: cc1c384f869bee5ff9336804619580ef647f0f9d3ce643a7b1494d41fa6da73511b8d74b30eabbb39f0a9baaa1ed3f806a51f44c42332395b2a3643d2963b7e6
data/Makefile CHANGED
@@ -368,7 +368,7 @@ Q = @
368
368
  endif
369
369
 
370
370
  CORE_VERSION = 56.0.0
371
- CPP_VERSION = 1.83.0-pre1
371
+ CPP_VERSION = 1.83.1
372
372
 
373
373
  CPPFLAGS_NO_ARCH += $(addprefix -I, $(INCLUDES)) $(addprefix -D, $(DEFINES))
374
374
  CPPFLAGS += $(CPPFLAGS_NO_ARCH) $(ARCH_FLAGS)
@@ -21,6 +21,7 @@
21
21
  #include <grpc/support/port_platform.h>
22
22
  #include <inttypes.h>
23
23
 
24
+ #include <cstdint>
24
25
  #include <functional>
25
26
  #include <memory>
26
27
  #include <optional>
@@ -44,6 +45,7 @@
44
45
  #include "src/core/lib/surface/call.h"
45
46
  #include "src/core/lib/transport/transport.h"
46
47
  #include "src/core/telemetry/call_tracer.h"
48
+ #include "src/core/transport/message_size_service_config.h"
47
49
  #include "src/core/util/grpc_check.h"
48
50
  #include "src/core/util/latent_see.h"
49
51
  #include "absl/status/status.h"
@@ -75,8 +77,6 @@ ServerCompressionFilter::Create(const ChannelArgs& args, ChannelFilter::Args) {
75
77
 
76
78
  ChannelCompression::ChannelCompression(const ChannelArgs& args)
77
79
  : max_recv_size_(GetMaxRecvSizeFromChannelArgs(args)),
78
- message_size_service_config_parser_index_(
79
- MessageSizeParser::ParserIndex()),
80
80
  default_compression_algorithm_(
81
81
  DefaultCompressionAlgorithmFromChannelArgs(args).value_or(
82
82
  GRPC_COMPRESS_NONE)),
@@ -118,26 +118,25 @@ MessageHandle ChannelCompression::CompressMessage(
118
118
  return message;
119
119
  }
120
120
  // Try to compress the payload.
121
- SliceBuffer tmp;
122
- SliceBuffer* payload = message->payload();
123
- bool did_compress = grpc_msg_compress(algorithm, payload->c_slice_buffer(),
124
- tmp.c_slice_buffer());
121
+ std::optional<SliceBuffer> compressed =
122
+ MessageCompress(algorithm, *message->payload());
123
+
125
124
  // If we achieved compression send it as compressed, otherwise send it as (to
126
125
  // avoid spending cycles on the receiver decompressing).
127
- if (did_compress) {
126
+ if (compressed.has_value()) {
128
127
  if (GRPC_TRACE_FLAG_ENABLED(compression)) {
129
128
  const char* algo_name;
130
- const size_t before_size = payload->Length();
131
- const size_t after_size = tmp.Length();
129
+ GRPC_CHECK(grpc_compression_algorithm_name(algorithm, &algo_name));
130
+ const size_t before_size = message->payload()->Length();
131
+ const size_t after_size = compressed->Length();
132
132
  const float savings_ratio = 1.0f - (static_cast<float>(after_size) /
133
133
  static_cast<float>(before_size));
134
- GRPC_CHECK(grpc_compression_algorithm_name(algorithm, &algo_name));
135
134
  LOG(INFO) << absl::StrFormat(
136
135
  "Compressed[%s] %" PRIuPTR " bytes vs. %" PRIuPTR
137
136
  " bytes (%.2f%% savings)",
138
137
  algo_name, before_size, after_size, 100 * savings_ratio);
139
138
  }
140
- tmp.Swap(payload);
139
+ *message->payload() = std::move(*compressed);
141
140
  flags |= GRPC_WRITE_INTERNAL_COMPRESS;
142
141
  if (call_tracer != nullptr) {
143
142
  call_tracer->RecordSendCompressedMessage(*message);
@@ -148,7 +147,7 @@ MessageHandle ChannelCompression::CompressMessage(
148
147
  GRPC_CHECK(grpc_compression_algorithm_name(algorithm, &algo_name));
149
148
  LOG(INFO) << "Algorithm '" << algo_name
150
149
  << "' enabled but decided not to compress. Input size: "
151
- << payload->Length();
150
+ << message->payload()->Length();
152
151
  }
153
152
  }
154
153
  return message;
@@ -180,15 +179,17 @@ absl::StatusOr<MessageHandle> ChannelCompression::DecompressMessage(
180
179
  return std::move(message);
181
180
  }
182
181
  // Try to decompress the payload.
183
- SliceBuffer decompressed_slices;
184
- if (grpc_msg_decompress(args.algorithm, message->payload()->c_slice_buffer(),
185
- decompressed_slices.c_slice_buffer()) == 0) {
186
- return absl::InternalError(
187
- absl::StrCat("Unexpected error decompressing data for algorithm ",
188
- CompressionAlgorithmAsString(args.algorithm)));
182
+ std::optional<uint32_t> max_output_size = IsMessageSizeRefactoringEnabled()
183
+ ? args.max_recv_message_length
184
+ : std::nullopt;
185
+ absl::StatusOr<SliceBuffer> decompressed_slices =
186
+ MessageDecompress(args.algorithm, *message->payload(), max_output_size);
187
+ if (!decompressed_slices.ok()) {
188
+ return decompressed_slices.status();
189
189
  }
190
- // Swap the decompressed slices into the message.
191
- message->payload()->Swap(&decompressed_slices);
190
+
191
+ // Move the decompressed slices into the message.
192
+ *message->payload() = std::move(*decompressed_slices);
192
193
  message->mutable_flags() &= ~GRPC_WRITE_INTERNAL_COMPRESS;
193
194
  message->mutable_flags() |= GRPC_WRITE_INTERNAL_TEST_ONLY_WAS_COMPRESSED;
194
195
  if (call_tracer != nullptr) {
@@ -213,18 +214,10 @@ grpc_compression_algorithm ChannelCompression::HandleOutgoingMetadata(
213
214
  ChannelCompression::DecompressArgs ChannelCompression::HandleIncomingMetadata(
214
215
  const grpc_metadata_batch& incoming_metadata) {
215
216
  // Configure max receive size.
216
- auto max_recv_message_length = max_recv_size_;
217
- const MessageSizeParsedConfig* limits =
218
- MessageSizeParsedConfig::GetFromCallContext(
219
- GetContext<Arena>(), message_size_service_config_parser_index_);
220
- if (limits != nullptr && limits->max_recv_size().has_value() &&
221
- (!max_recv_message_length.has_value() ||
222
- *limits->max_recv_size() < *max_recv_message_length)) {
223
- max_recv_message_length = limits->max_recv_size();
224
- }
225
- return DecompressArgs{incoming_metadata.get(GrpcEncodingMetadata())
226
- .value_or(GRPC_COMPRESS_NONE),
227
- max_recv_message_length};
217
+ return DecompressArgs{
218
+ incoming_metadata.get(GrpcEncodingMetadata())
219
+ .value_or(GRPC_COMPRESS_NONE),
220
+ GetMaxRecvSizeFromCallContext(GetContext<Arena>(), max_recv_size_)};
228
221
  }
229
222
 
230
223
  void ClientCompressionFilter::Call::OnClientInitialMetadata(
@@ -107,7 +107,6 @@ class ChannelCompression {
107
107
  private:
108
108
  // Max receive message length, if set.
109
109
  std::optional<uint32_t> max_recv_size_;
110
- size_t message_size_service_config_parser_index_;
111
110
  // The default, channel-level, compression algorithm.
112
111
  grpc_compression_algorithm default_compression_algorithm_;
113
112
  // Enabled compression algorithms.
@@ -106,6 +106,7 @@
106
106
  #include "src/core/telemetry/stats_data.h"
107
107
  #include "src/core/telemetry/tcp_tracer.h"
108
108
  #include "src/core/transport/auth_context.h"
109
+ #include "src/core/transport/message_size_service_config.h"
109
110
  #include "src/core/util/bitset.h"
110
111
  #include "src/core/util/crash.h"
111
112
  #include "src/core/util/debug_location.h"
@@ -816,6 +817,7 @@ grpc_chttp2_transport::grpc_chttp2_transport(
816
817
  Ref(), &init_keepalive_ping_locked),
817
818
  absl::OkStatus());
818
819
 
820
+ // TODO(tjagtap) : [PH2][P0] : Do this for PH2.
819
821
  if (flow_control.bdp_probe()) {
820
822
  bdp_ping_blocked = true;
821
823
  grpc_chttp2_act_on_flowctl_action(flow_control.PeriodicUpdate(), this,
@@ -859,6 +861,9 @@ grpc_chttp2_transport::grpc_chttp2_transport(
859
861
  epte->SetSocketNode(channelz_socket);
860
862
  }
861
863
  }
864
+
865
+ max_recv_message_length =
866
+ grpc_core::GetMaxRecvSizeFromChannelArgs(channel_args);
862
867
  }
863
868
 
864
869
  static void destroy_transport_locked(void* tp, grpc_error_handle /*error*/) {
@@ -879,6 +884,10 @@ static void close_transport_locked(grpc_chttp2_transport* t,
879
884
  grpc_error_handle error) {
880
885
  end_all_the_calls(t, error);
881
886
  cancel_pings(t, error);
887
+ if (t->transport_framing_endpoint_extension != nullptr) {
888
+ t->transport_framing_endpoint_extension->SetSendFrameCallback(nullptr);
889
+ t->transport_framing_endpoint_extension = nullptr;
890
+ }
882
891
  if (t->closed_with_error.ok()) {
883
892
  if (!grpc_error_has_clear_grpc_status(error)) {
884
893
  error =
@@ -1507,7 +1516,8 @@ static grpc_closure* add_closure_barrier(grpc_closure* closure) {
1507
1516
  return closure;
1508
1517
  }
1509
1518
 
1510
- static void null_then_sched_closure(grpc_closure** closure) {
1519
+ static void null_then_sched_closure_with_error(grpc_closure** closure,
1520
+ grpc_error_handle error) {
1511
1521
  grpc_closure* c = *closure;
1512
1522
  *closure = nullptr;
1513
1523
  // null_then_schedule_closure might be run during a start_batch which might
@@ -1516,7 +1526,11 @@ static void null_then_sched_closure(grpc_closure** closure) {
1516
1526
  // completion, have the application see it, and make a new operation on the
1517
1527
  // call which recycles the batch BEFORE the call to start_batch completes,
1518
1528
  // forcing a race.
1519
- grpc_core::ExecCtx::Run(DEBUG_LOCATION, c, absl::OkStatus());
1529
+ grpc_core::ExecCtx::Run(DEBUG_LOCATION, c, error);
1530
+ }
1531
+
1532
+ static void null_then_sched_closure(grpc_closure** closure) {
1533
+ null_then_sched_closure_with_error(closure, absl::OkStatus());
1520
1534
  }
1521
1535
 
1522
1536
  void grpc_chttp2_complete_closure_step(grpc_chttp2_transport* t,
@@ -2343,6 +2357,8 @@ void grpc_chttp2_maybe_complete_recv_initial_metadata(grpc_chttp2_transport* t,
2343
2357
  t->registered_method_matcher_cb(t->accept_stream_cb_user_data,
2344
2358
  s->recv_initial_metadata);
2345
2359
  }
2360
+ s->max_recv_message_length =
2361
+ GetMaxRecvSizeFromCallContext(s->arena, t->max_recv_message_length);
2346
2362
  null_then_sched_closure(&s->recv_initial_metadata_ready);
2347
2363
  }
2348
2364
  }
@@ -2415,7 +2431,36 @@ void grpc_chttp2_maybe_complete_recv_message(grpc_chttp2_transport* t,
2415
2431
  *s->call_failed_before_recv_message =
2416
2432
  (s->published_metadata[1] != GRPC_METADATA_PUBLISHED_AT_CLOSE);
2417
2433
  }
2418
- null_then_sched_closure(&s->recv_message_ready);
2434
+ if (s->seen_error && s->message_size_limit_exceeded) {
2435
+ null_then_sched_closure_with_error(&s->recv_message_ready, error);
2436
+ } else {
2437
+ null_then_sched_closure(&s->recv_message_ready);
2438
+ }
2439
+ } else if (s->seen_error && s->message_size_limit_exceeded) {
2440
+ null_then_sched_closure_with_error(&s->recv_message_ready, error);
2441
+ }
2442
+
2443
+ if (grpc_core::IsMessageSizeRefactoringEnabled() && s->seen_error &&
2444
+ s->message_size_limit_exceeded) {
2445
+ s->message_size_limit_exceeded = false;
2446
+ // Explicitly cancel the stream to fail the RPC immediately.
2447
+ // We delay the cancellation until the recv_message_ready closure is
2448
+ // executed to prevent re-entrancy issues. When the HTTP/2 frame deframer
2449
+ // in `grpc_deframe_unprocessed_incoming_frames`
2450
+ // returns a size violation error, invoking `grpc_chttp2_cancel_stream`
2451
+ // immediately triggers `grpc_chttp2_mark_stream_closed`. This in turn
2452
+ // synchronously re-enters `grpc_chttp2_maybe_complete_recv_message` while
2453
+ // the original deframing loop is still active on the call stack.
2454
+ //
2455
+ // Because the re-entrant invocation observes that the incoming frame
2456
+ // storage has been cleared but `s->recv_message_ready` is still non-null,
2457
+ // it preemptively schedules the closure as a standard/non-error stream
2458
+ // termination (i.e., via `null_then_sched_closure(...,
2459
+ // absl::OkStatus())`). By the time control returns to the initial (outer)
2460
+ // deframing loop to execute `null_then_sched_closure_with_error`, the
2461
+ // closure pointer is already null, causing the original error context to
2462
+ // be discarded.
2463
+ grpc_chttp2_cancel_stream(t, s, error, true, nullptr);
2419
2464
  }
2420
2465
  }();
2421
2466
 
@@ -48,6 +48,7 @@ absl::Status grpc_chttp2_data_parser_begin_frame(uint8_t flags,
48
48
  } else {
49
49
  s->received_last_frame = false;
50
50
  }
51
+ ++s->num_frames;
51
52
 
52
53
  return absl::OkStatus();
53
54
  }
@@ -123,6 +124,24 @@ grpc_core::Poll<grpc_error_handle> grpc_deframe_unprocessed_incoming_frames(
123
124
  (static_cast<uint32_t>(header[3]) << 8) |
124
125
  static_cast<uint32_t>(header[4]);
125
126
 
127
+ if (grpc_core::IsMessageSizeRefactoringEnabled()) {
128
+ if (s->max_recv_message_length.has_value() &&
129
+ length > *(s->max_recv_message_length)) {
130
+ error = GRPC_ERROR_CREATE(
131
+ absl::StrFormat("%s: Received message larger than max (%d vs. %u)",
132
+ s->t->is_client ? "CLIENT" : "SERVER", length,
133
+ *(s->max_recv_message_length)));
134
+ error = grpc_error_set_int(error, grpc_core::StatusIntProperty::kStreamId,
135
+ static_cast<intptr_t>(s->id));
136
+ // Attach the explicit gRPC status code to fail the RPC correctly.
137
+ error =
138
+ grpc_error_set_int(error, grpc_core::StatusIntProperty::kRpcStatus,
139
+ GRPC_STATUS_RESOURCE_EXHAUSTED);
140
+ s->message_size_limit_exceeded = true;
141
+ return error;
142
+ }
143
+ }
144
+
126
145
  if (slices->length < length + GRPC_HEADER_SIZE_IN_BYTES) {
127
146
  if (min_progress_size != nullptr) {
128
147
  *min_progress_size = length + GRPC_HEADER_SIZE_IN_BYTES - slices->length;
@@ -138,6 +157,7 @@ grpc_core::Poll<grpc_error_handle> grpc_deframe_unprocessed_incoming_frames(
138
157
  grpc_slice_buffer_move_first_into_buffer(slices, GRPC_HEADER_SIZE_IN_BYTES,
139
158
  header);
140
159
  grpc_slice_buffer_move_first(slices, length, stream_out->c_slice_buffer());
160
+ s->num_frames = 0;
141
161
  }
142
162
 
143
163
  return absl::OkStatus();
@@ -148,8 +168,20 @@ grpc_error_handle grpc_chttp2_data_parser_parse(void* /*parser*/,
148
168
  grpc_chttp2_stream* s,
149
169
  const grpc_slice& slice,
150
170
  int is_last) {
151
- grpc_core::CSliceRef(slice);
152
- grpc_slice_buffer_add(&s->frame_storage, slice);
171
+ const size_t slice_len = GRPC_SLICE_LENGTH(slice);
172
+ bool is_small_frame = 0 < slice_len && slice_len < GRPC_SLICE_INLINED_SIZE;
173
+ bool multiple_small_frames =
174
+ (s->num_frames >= 64) &&
175
+ ((s->frame_storage.length / s->num_frames) < GRPC_SLICE_INLINED_SIZE);
176
+ if (GPR_UNLIKELY(multiple_small_frames && is_small_frame &&
177
+ grpc_core::IsHeaderDataFrameEnabled())) {
178
+ uint8_t* append_ptr =
179
+ grpc_slice_buffer_tiny_add(&s->frame_storage, slice_len);
180
+ memcpy(append_ptr, GRPC_SLICE_START_PTR(slice), slice_len);
181
+ } else {
182
+ grpc_core::CSliceRef(slice);
183
+ grpc_slice_buffer_add(&s->frame_storage, slice);
184
+ }
153
185
  grpc_chttp2_maybe_complete_recv_message(t, s);
154
186
 
155
187
  if (is_last) {
@@ -31,11 +31,15 @@
31
31
  #include "absl/strings/string_view.h"
32
32
 
33
33
  void grpc_chttp2_goaway_parser_init(grpc_chttp2_goaway_parser* p) {
34
- p->debug_data = nullptr;
34
+ if (!grpc_core::IsPh2Perf01Enabled()) {
35
+ p->debug_data = nullptr;
36
+ }
35
37
  }
36
38
 
37
39
  void grpc_chttp2_goaway_parser_destroy(grpc_chttp2_goaway_parser* p) {
38
- gpr_free(p->debug_data);
40
+ if (!grpc_core::IsPh2Perf01Enabled()) {
41
+ gpr_free(p->debug_data);
42
+ }
39
43
  }
40
44
 
41
45
  grpc_error_handle grpc_chttp2_goaway_parser_begin_frame(
@@ -45,10 +49,14 @@ grpc_error_handle grpc_chttp2_goaway_parser_begin_frame(
45
49
  absl::StrFormat("goaway frame too short (%d bytes)", length));
46
50
  }
47
51
 
48
- gpr_free(p->debug_data);
49
52
  p->debug_length = length - 8;
50
- p->debug_data = static_cast<char*>(gpr_malloc(p->debug_length));
51
- p->debug_pos = 0;
53
+ if (grpc_core::IsPh2Perf01Enabled()) {
54
+ p->debug_slice_buffer.Clear();
55
+ } else {
56
+ gpr_free(p->debug_data);
57
+ p->debug_data = static_cast<char*>(gpr_malloc(p->debug_length));
58
+ p->debug_pos = 0;
59
+ }
52
60
  p->state = GRPC_CHTTP2_GOAWAY_LSI0;
53
61
  return absl::OkStatus();
54
62
  }
@@ -130,24 +138,48 @@ grpc_error_handle grpc_chttp2_goaway_parser_parse(void* parser,
130
138
  ++cur;
131
139
  [[fallthrough]];
132
140
  case GRPC_CHTTP2_GOAWAY_DEBUG:
133
- if (end != cur) {
134
- memcpy(p->debug_data + p->debug_pos, cur,
135
- static_cast<size_t>(end - cur));
136
- }
137
- GRPC_CHECK((size_t)(end - cur) < UINT32_MAX - p->debug_pos);
138
- p->debug_pos += static_cast<uint32_t>(end - cur);
139
- p->state = GRPC_CHTTP2_GOAWAY_DEBUG;
140
- if (is_last) {
141
- t->http2_ztrace_collector.Append([p]() {
142
- return grpc_core::H2GoAwayTrace<true>{
143
- p->last_stream_id, p->error_code,
144
- std::string(absl::string_view(p->debug_data, p->debug_length))};
145
- });
146
- grpc_chttp2_add_incoming_goaway(
147
- t, p->error_code, p->last_stream_id,
148
- absl::string_view(p->debug_data, p->debug_length));
149
- gpr_free(p->debug_data);
150
- p->debug_data = nullptr;
141
+ if (grpc_core::IsPh2Perf01Enabled()) {
142
+ if (end != cur) {
143
+ p->debug_slice_buffer.AppendIndexed(
144
+ grpc_core::Slice::FromCopiedBuffer(
145
+ cur, static_cast<size_t>(end - cur)));
146
+ }
147
+ GRPC_CHECK(p->debug_slice_buffer.Length() <= p->debug_length);
148
+ p->state = GRPC_CHTTP2_GOAWAY_DEBUG;
149
+ if (is_last) {
150
+ std::string debug_str = p->debug_slice_buffer.JoinIntoString();
151
+
152
+ grpc_chttp2_add_incoming_goaway(t, p->error_code, p->last_stream_id,
153
+ absl::string_view(debug_str));
154
+
155
+ t->http2_ztrace_collector.Append(
156
+ [last_stream_id = p->last_stream_id, error_code = p->error_code,
157
+ debug_str = std::move(debug_str)]() mutable {
158
+ return grpc_core::H2GoAwayTrace<true>{
159
+ last_stream_id, error_code, std::move(debug_str)};
160
+ });
161
+ p->debug_slice_buffer.Clear();
162
+ }
163
+ } else {
164
+ if (end != cur) {
165
+ memcpy(p->debug_data + p->debug_pos, cur,
166
+ static_cast<size_t>(end - cur));
167
+ }
168
+ GRPC_CHECK((size_t)(end - cur) < UINT32_MAX - p->debug_pos);
169
+ p->debug_pos += static_cast<uint32_t>(end - cur);
170
+ p->state = GRPC_CHTTP2_GOAWAY_DEBUG;
171
+ if (is_last) {
172
+ t->http2_ztrace_collector.Append([p]() {
173
+ return grpc_core::H2GoAwayTrace<true>{
174
+ p->last_stream_id, p->error_code,
175
+ std::string(absl::string_view(p->debug_data, p->debug_length))};
176
+ });
177
+ grpc_chttp2_add_incoming_goaway(
178
+ t, p->error_code, p->last_stream_id,
179
+ absl::string_view(p->debug_data, p->debug_length));
180
+ gpr_free(p->debug_data);
181
+ p->debug_data = nullptr;
182
+ }
151
183
  }
152
184
  return absl::OkStatus();
153
185
  }
@@ -44,6 +44,7 @@ struct grpc_chttp2_goaway_parser {
44
44
  uint32_t last_stream_id;
45
45
  uint32_t error_code;
46
46
  char* debug_data;
47
+ grpc_core::SliceBuffer debug_slice_buffer;
47
48
  uint32_t debug_length;
48
49
  uint32_t debug_pos;
49
50
  };
@@ -629,6 +629,8 @@ struct grpc_chttp2_transport final : public grpc_core::FilterStackTransport,
629
629
 
630
630
  GPR_NO_UNIQUE_ADDRESS grpc_core::latent_see::Flow write_flow;
631
631
 
632
+ std::optional<uint32_t> max_recv_message_length;
633
+
632
634
  // Current mitigation engine, retrieved once per connection.
633
635
  grpc_core::RefCountedPtr<grpc_core::MitigationEngine> mitigation_engine;
634
636
  };
@@ -718,6 +720,7 @@ struct grpc_chttp2_stream {
718
720
  grpc_metadata_batch trailing_metadata_buffer;
719
721
 
720
722
  grpc_slice_buffer frame_storage; // protected by t combiner
723
+ size_t num_frames = 0; // protected by t combiner
721
724
 
722
725
  grpc_core::Timestamp deadline = grpc_core::Timestamp::InfFuture();
723
726
 
@@ -777,6 +780,9 @@ struct grpc_chttp2_stream {
777
780
  // The last time a stream window update was received.
778
781
  grpc_core::Timestamp last_window_update_time =
779
782
  grpc_core::Timestamp::InfPast();
783
+
784
+ bool message_size_limit_exceeded = false;
785
+ std::optional<uint32_t> max_recv_message_length;
780
786
  };
781
787
 
782
788
  /// Transport writing call flow:
@@ -430,6 +430,14 @@ static grpc_error_handle init_frame_parser(grpc_chttp2_transport* t,
430
430
  t->incoming_frame_type));
431
431
  }
432
432
  t->is_first_frame = false;
433
+
434
+ if (grpc_core::IsPh2Perf01Enabled() &&
435
+ t->incoming_frame_size > t->settings.acked().max_frame_size()) {
436
+ return GRPC_ERROR_CREATE(absl::StrFormat(
437
+ "Frame size %d is larger than max frame size %d",
438
+ t->incoming_frame_size, t->settings.acked().max_frame_size()));
439
+ }
440
+
433
441
  if (t->expect_continuation_stream_id != 0) {
434
442
  if (t->incoming_frame_type != GRPC_CHTTP2_FRAME_CONTINUATION) {
435
443
  return GRPC_ERROR_CREATE(
@@ -25,168 +25,203 @@
25
25
  #include <zconf.h>
26
26
  #include <zlib.h>
27
27
 
28
+ #include <algorithm>
29
+ #include <cstdint>
30
+ #include <optional>
31
+
28
32
  #include "src/core/lib/slice/slice.h"
29
33
  #include "src/core/util/grpc_check.h"
34
+ #include "src/core/util/status_helper.h"
30
35
  #include "absl/log/log.h"
36
+ #include "absl/status/status.h"
37
+ #include "absl/status/statusor.h"
31
38
 
32
39
  #define OUTPUT_BLOCK_SIZE 1024
33
40
 
34
- static int zlib_body(z_stream* zs, grpc_slice_buffer* input,
35
- grpc_slice_buffer* output,
36
- int (*flate)(z_stream* zs, int flush)) {
41
+ namespace grpc_core {
42
+ namespace {
43
+
44
+ absl::StatusOr<SliceBuffer> ZlibBody(z_stream* zs, const SliceBuffer& input,
45
+ int (*flate)(z_stream* zs, int flush),
46
+ std::optional<uint32_t> max_output_size) {
37
47
  int r = Z_STREAM_END; // Do not fail on an empty input.
38
48
  int flush;
39
49
  size_t i;
40
- grpc_slice outbuf = GRPC_SLICE_MALLOC(OUTPUT_BLOCK_SIZE);
50
+ uint32_t remaining_output_size = max_output_size.value_or(UINT32_MAX);
51
+ SliceBuffer output_sb;
41
52
  const uInt uint_max = ~uInt{0};
53
+ auto outbuf = MutableSlice::CreateUninitialized(
54
+ std::min<uint32_t>(remaining_output_size, OUTPUT_BLOCK_SIZE));
42
55
 
43
- GRPC_CHECK(GRPC_SLICE_LENGTH(outbuf) <= uint_max);
44
- zs->avail_out = static_cast<uInt> GRPC_SLICE_LENGTH(outbuf);
45
- zs->next_out = GRPC_SLICE_START_PTR(outbuf);
56
+ GRPC_CHECK(outbuf.length() <= uint_max);
57
+ zs->avail_out = static_cast<uInt>(outbuf.length());
58
+ zs->next_out = const_cast<uint8_t*>(outbuf.begin());
46
59
  flush = Z_NO_FLUSH;
47
- for (i = 0; i < input->count; i++) {
48
- if (i == input->count - 1) flush = Z_FINISH;
49
- GRPC_CHECK(GRPC_SLICE_LENGTH(input->slices[i]) <= uint_max);
50
- zs->avail_in = static_cast<uInt> GRPC_SLICE_LENGTH(input->slices[i]);
51
- zs->next_in = GRPC_SLICE_START_PTR(input->slices[i]);
60
+ for (i = 0; i < input.Count(); i++) {
61
+ if (i == input.Count() - 1) {
62
+ flush = Z_FINISH;
63
+ }
64
+ GRPC_CHECK(input[i].length() <= uint_max);
65
+ zs->avail_in = static_cast<uInt>(input[i].length());
66
+ zs->next_in = const_cast<uint8_t*>(input[i].begin());
52
67
  do {
53
68
  if (zs->avail_out == 0) {
54
- grpc_slice_buffer_add_indexed(output, outbuf);
55
- outbuf = GRPC_SLICE_MALLOC(OUTPUT_BLOCK_SIZE);
56
- GRPC_CHECK(GRPC_SLICE_LENGTH(outbuf) <= uint_max);
57
- zs->avail_out = static_cast<uInt> GRPC_SLICE_LENGTH(outbuf);
58
- zs->next_out = GRPC_SLICE_START_PTR(outbuf);
69
+ if (max_output_size.has_value() && remaining_output_size == 0) {
70
+ VLOG(2) << "zlib: max provided output size exceeded";
71
+ return absl::ResourceExhaustedError(
72
+ "Decompressed message larger than max");
73
+ }
74
+ output_sb.AppendIndexed(Slice(std::move(outbuf)));
75
+ outbuf = MutableSlice::CreateUninitialized(
76
+ std::min<uint32_t>(remaining_output_size, OUTPUT_BLOCK_SIZE));
77
+ // Update remaining output size to reflect the size of the slice we just
78
+ // filled with compressed / decompressed data.
79
+ if (max_output_size.has_value()) {
80
+ remaining_output_size -= outbuf.length();
81
+ }
82
+ GRPC_CHECK(outbuf.length() <= uint_max);
83
+ zs->avail_out = static_cast<uInt>(outbuf.length());
84
+ zs->next_out = const_cast<uint8_t*>(outbuf.begin());
59
85
  }
60
86
  r = flate(zs, flush);
61
87
  if (r < 0 && r != Z_BUF_ERROR /* not fatal */) {
62
88
  VLOG(2) << "zlib error (" << r << ")";
63
- goto error;
89
+ return absl::InternalError("Decompression failed due to zlib error");
64
90
  }
65
91
  } while (zs->avail_out == 0);
66
92
  if (zs->avail_in) {
67
93
  VLOG(2) << "zlib: not all input consumed";
68
- goto error;
94
+ return absl::InternalError(
95
+ "Decompression failed due to not all input "
96
+ "consumed");
69
97
  }
70
98
  }
71
99
  if (r != Z_STREAM_END) {
72
100
  VLOG(2) << "zlib: Data error";
73
- goto error;
101
+ return absl::InternalError("Decompression failed due to data error");
74
102
  }
75
103
 
76
- GRPC_CHECK(outbuf.refcount);
77
- outbuf.data.refcounted.length -= zs->avail_out;
78
- grpc_slice_buffer_add_indexed(output, outbuf);
79
-
80
- return 1;
81
-
82
- error:
83
- grpc_core::CSliceUnref(outbuf);
84
- return 0;
104
+ // TODO(vigneshbabu): Add a Truncate() method to the Slice type to avoid using
105
+ // the underlying C type here.
106
+ grpc_slice slice = outbuf.TakeCSlice();
107
+ if (slice.refcount) {
108
+ slice.data.refcounted.length -= zs->avail_out;
109
+ } else {
110
+ slice.data.inlined.length -= zs->avail_out;
111
+ }
112
+ output_sb.AppendIndexed(Slice(slice));
113
+ return output_sb;
85
114
  }
86
115
 
87
- static void* zalloc_gpr(void* /*opaque*/, unsigned int items,
88
- unsigned int size) {
116
+ void* ZallocGpr(void* /*opaque*/, unsigned int items, unsigned int size) {
89
117
  return gpr_malloc(items * size);
90
118
  }
91
119
 
92
- static void zfree_gpr(void* /*opaque*/, void* address) { gpr_free(address); }
120
+ void ZFreeGpr(void* /*opaque*/, void* address) { gpr_free(address); }
93
121
 
94
- static int zlib_compress(grpc_slice_buffer* input, grpc_slice_buffer* output,
95
- int gzip) {
122
+ std::optional<SliceBuffer> ZlibCompress(const SliceBuffer& input, int gzip) {
96
123
  z_stream zs;
97
- int r;
98
- size_t i;
99
- size_t count_before = output->count;
100
- size_t length_before = output->length;
124
+ absl::StatusOr<SliceBuffer> compression_result;
101
125
  memset(&zs, 0, sizeof(zs));
102
- zs.zalloc = zalloc_gpr;
103
- zs.zfree = zfree_gpr;
104
- r = deflateInit2(&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 15 | (gzip ? 16 : 0),
105
- 8, Z_DEFAULT_STRATEGY);
126
+ zs.zalloc = ZallocGpr;
127
+ zs.zfree = ZFreeGpr;
128
+ bool r = deflateInit2(&zs, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
129
+ 15 | (gzip ? 16 : 0), 8, Z_DEFAULT_STRATEGY);
106
130
  GRPC_CHECK(r == Z_OK);
107
- r = zlib_body(&zs, input, output, deflate) && output->length < input->length;
108
- if (!r) {
109
- for (i = count_before; i < output->count; i++) {
110
- grpc_core::CSliceUnref(output->slices[i]);
111
- }
112
- output->count = count_before;
113
- output->length = length_before;
114
- }
131
+ compression_result = ZlibBody(&zs, input, deflate, input.Length());
115
132
  deflateEnd(&zs);
116
- return r;
133
+ if (compression_result.ok() &&
134
+ compression_result->Length() < input.Length()) {
135
+ return std::move(*compression_result);
136
+ }
137
+ return std::nullopt;
117
138
  }
118
139
 
119
- static int zlib_decompress(grpc_slice_buffer* input, grpc_slice_buffer* output,
120
- int gzip) {
140
+ absl::StatusOr<SliceBuffer> ZlibDecompress(
141
+ const SliceBuffer& input, int gzip,
142
+ std::optional<uint32_t> max_output_size) {
121
143
  z_stream zs;
122
- int r;
123
- size_t i;
124
- size_t count_before = output->count;
125
- size_t length_before = output->length;
144
+ absl::StatusOr<SliceBuffer> decompression_result;
126
145
  memset(&zs, 0, sizeof(zs));
127
- zs.zalloc = zalloc_gpr;
128
- zs.zfree = zfree_gpr;
129
- r = inflateInit2(&zs, 15 | (gzip ? 16 : 0));
146
+ zs.zalloc = ZallocGpr;
147
+ zs.zfree = ZFreeGpr;
148
+ bool r = inflateInit2(&zs, 15 | (gzip ? 16 : 0));
130
149
  GRPC_CHECK(r == Z_OK);
131
- r = zlib_body(&zs, input, output, inflate);
132
- if (!r) {
133
- for (i = count_before; i < output->count; i++) {
134
- grpc_core::CSliceUnref(output->slices[i]);
135
- }
136
- output->count = count_before;
137
- output->length = length_before;
138
- }
150
+ decompression_result = ZlibBody(&zs, input, inflate, max_output_size);
139
151
  inflateEnd(&zs);
140
- return r;
152
+ return decompression_result;
141
153
  }
142
154
 
143
- static int copy(grpc_slice_buffer* input, grpc_slice_buffer* output) {
144
- size_t i;
145
- for (i = 0; i < input->count; i++) {
146
- grpc_slice_buffer_add(output, grpc_core::CSliceRef(input->slices[i]));
147
- }
148
- return 1;
149
- }
155
+ } // namespace
150
156
 
151
- static int compress_inner(grpc_compression_algorithm algorithm,
152
- grpc_slice_buffer* input, grpc_slice_buffer* output) {
157
+ std::optional<SliceBuffer> MessageCompress(grpc_compression_algorithm algorithm,
158
+ const SliceBuffer& input) {
153
159
  switch (algorithm) {
154
160
  case GRPC_COMPRESS_NONE:
155
161
  // the fallback path always needs to be send uncompressed: we simply
156
162
  // rely on that here
157
- return 0;
163
+ return std::nullopt;
158
164
  case GRPC_COMPRESS_DEFLATE:
159
- return zlib_compress(input, output, 0);
165
+ return ZlibCompress(input, 0);
160
166
  case GRPC_COMPRESS_GZIP:
161
- return zlib_compress(input, output, 1);
167
+ return ZlibCompress(input, 1);
162
168
  case GRPC_COMPRESS_ALGORITHMS_COUNT:
163
169
  break;
164
170
  }
165
171
  LOG(ERROR) << "invalid compression algorithm " << algorithm;
166
- return 0;
172
+ return std::nullopt;
167
173
  }
168
174
 
175
+ absl::StatusOr<SliceBuffer> MessageDecompress(
176
+ grpc_compression_algorithm algorithm, const SliceBuffer& input,
177
+ std::optional<uint32_t> max_output_size) {
178
+ switch (algorithm) {
179
+ case GRPC_COMPRESS_NONE: {
180
+ SliceBuffer output;
181
+ output.Append(input);
182
+ return output;
183
+ }
184
+ case GRPC_COMPRESS_DEFLATE:
185
+ return ZlibDecompress(input, 0, max_output_size);
186
+ case GRPC_COMPRESS_GZIP:
187
+ return ZlibDecompress(input, 1, max_output_size);
188
+ case GRPC_COMPRESS_ALGORITHMS_COUNT:
189
+ break;
190
+ }
191
+ LOG(ERROR) << "invalid compression algorithm " << algorithm;
192
+ return absl::InternalError("Invalid compression algorithm");
193
+ }
194
+
195
+ } // namespace grpc_core
196
+
169
197
  int grpc_msg_compress(grpc_compression_algorithm algorithm,
170
198
  grpc_slice_buffer* input, grpc_slice_buffer* output) {
171
- if (!compress_inner(algorithm, input, output)) {
172
- copy(input, output);
173
- return 0;
199
+ int retval = 1;
200
+ grpc_core::SliceBuffer input_sb;
201
+ grpc_slice_buffer_swap(input, input_sb.c_slice_buffer());
202
+ std::optional<grpc_core::SliceBuffer> output_sb =
203
+ grpc_core::MessageCompress(algorithm, input_sb);
204
+ if (!output_sb.has_value()) {
205
+ output_sb.emplace();
206
+ output_sb->Append(input_sb);
207
+ retval = 0;
174
208
  }
175
- return 1;
209
+ grpc_slice_buffer_swap(input, input_sb.c_slice_buffer());
210
+ grpc_slice_buffer_swap(output, output_sb->c_slice_buffer());
211
+ return retval;
176
212
  }
177
213
 
178
214
  int grpc_msg_decompress(grpc_compression_algorithm algorithm,
179
215
  grpc_slice_buffer* input, grpc_slice_buffer* output) {
180
- switch (algorithm) {
181
- case GRPC_COMPRESS_NONE:
182
- return copy(input, output);
183
- case GRPC_COMPRESS_DEFLATE:
184
- return zlib_decompress(input, output, 0);
185
- case GRPC_COMPRESS_GZIP:
186
- return zlib_decompress(input, output, 1);
187
- case GRPC_COMPRESS_ALGORITHMS_COUNT:
188
- break;
216
+ grpc_core::SliceBuffer input_sb;
217
+ grpc_slice_buffer_swap(input, input_sb.c_slice_buffer());
218
+
219
+ absl::StatusOr<grpc_core::SliceBuffer> output_sb =
220
+ grpc_core::MessageDecompress(algorithm, input_sb, std::nullopt);
221
+ if (!output_sb.ok()) {
222
+ return 0;
189
223
  }
190
- LOG(ERROR) << "invalid compression algorithm " << algorithm;
191
- return 0;
224
+ grpc_slice_buffer_swap(input, input_sb.c_slice_buffer());
225
+ grpc_slice_buffer_swap(output, output_sb->c_slice_buffer());
226
+ return 1;
192
227
  }
@@ -23,6 +23,13 @@
23
23
  #include <grpc/slice.h>
24
24
  #include <grpc/support/port_platform.h>
25
25
 
26
+ #include <cstdint>
27
+ #include <optional>
28
+
29
+ #include "src/core/lib/slice/slice_buffer.h"
30
+ #include "absl/status/status.h"
31
+ #include "absl/status/statusor.h"
32
+
26
33
  // compress 'input' to 'output' using 'algorithm'.
27
34
  // On success, appends compressed slices to output and returns 1.
28
35
  // On failure, appends uncompressed slices to output and returns 0.
@@ -35,4 +42,21 @@ int grpc_msg_compress(grpc_compression_algorithm algorithm,
35
42
  int grpc_msg_decompress(grpc_compression_algorithm algorithm,
36
43
  grpc_slice_buffer* input, grpc_slice_buffer* output);
37
44
 
45
+ namespace grpc_core {
46
+
47
+ // Compresses 'input' using 'algorithm'.
48
+ // On success, returns a SliceBuffer containing the compressed data.
49
+ // On failure, returns nullopt.
50
+ std::optional<SliceBuffer> MessageCompress(grpc_compression_algorithm algorithm,
51
+ const SliceBuffer& input);
52
+ // Decompresses 'input'.
53
+ // On success, returns a SliceBuffer containing the decompressed data.
54
+ // On failure, returns a non-OK status.
55
+ // Fails if the decompressed data would be larger than max_output_size.
56
+ absl::StatusOr<SliceBuffer> MessageDecompress(
57
+ grpc_compression_algorithm algorithm, const SliceBuffer& input,
58
+ std::optional<uint32_t> max_output_size);
59
+
60
+ } // namespace grpc_core
61
+
38
62
  #endif // GRPC_SRC_CORE_LIB_COMPRESSION_MESSAGE_COMPRESS_H
@@ -103,6 +103,9 @@ const char* const description_h2_max_deallocating_streams_headroom =
103
103
  "Separate allocated max concurrent streams.";
104
104
  const char* const additional_constraints_h2_max_deallocating_streams_headroom =
105
105
  "{}";
106
+ const char* const description_header_data_frame =
107
+ "Managing header and data memory better";
108
+ const char* const additional_constraints_header_data_frame = "{}";
106
109
  const char* const description_inproc_cancel_stream =
107
110
  "If set, cancel inproc stream inside the transport mutex.";
108
111
  const char* const additional_constraints_inproc_cancel_stream = "{}";
@@ -336,6 +339,8 @@ const ExperimentMetadata g_experiment_metadata[] = {
336
339
  description_h2_max_deallocating_streams_headroom,
337
340
  additional_constraints_h2_max_deallocating_streams_headroom, nullptr, 0,
338
341
  false, true},
342
+ {"header_data_frame", description_header_data_frame,
343
+ additional_constraints_header_data_frame, nullptr, 0, true, true},
339
344
  {"inproc_cancel_stream", description_inproc_cancel_stream,
340
345
  additional_constraints_inproc_cancel_stream, nullptr, 0, true, true},
341
346
  {"keep_alive_ping_timer_batch", description_keep_alive_ping_timer_batch,
@@ -348,7 +353,7 @@ const ExperimentMetadata g_experiment_metadata[] = {
348
353
  {"memory_optimization_02", description_memory_optimization_02,
349
354
  additional_constraints_memory_optimization_02, nullptr, 0, false, false},
350
355
  {"message_size_refactoring", description_message_size_refactoring,
351
- additional_constraints_message_size_refactoring, nullptr, 0, false, true},
356
+ additional_constraints_message_size_refactoring, nullptr, 0, true, true},
352
357
  {"metadata_outstanding_token_refactor",
353
358
  description_metadata_outstanding_token_refactor,
354
359
  additional_constraints_metadata_outstanding_token_refactor, nullptr, 0,
@@ -380,7 +385,7 @@ const ExperimentMetadata g_experiment_metadata[] = {
380
385
  {"ph2_client_server", description_ph2_client_server,
381
386
  additional_constraints_ph2_client_server, nullptr, 0, false, true},
382
387
  {"ph2_perf_01", description_ph2_perf_01, additional_constraints_ph2_perf_01,
383
- nullptr, 0, false, true},
388
+ nullptr, 0, true, true},
384
389
  {"ph2_server", description_ph2_server, additional_constraints_ph2_server,
385
390
  nullptr, 0, false, true},
386
391
  {"pick_first_ignore_empty_updates",
@@ -554,6 +559,9 @@ const char* const description_h2_max_deallocating_streams_headroom =
554
559
  "Separate allocated max concurrent streams.";
555
560
  const char* const additional_constraints_h2_max_deallocating_streams_headroom =
556
561
  "{}";
562
+ const char* const description_header_data_frame =
563
+ "Managing header and data memory better";
564
+ const char* const additional_constraints_header_data_frame = "{}";
557
565
  const char* const description_inproc_cancel_stream =
558
566
  "If set, cancel inproc stream inside the transport mutex.";
559
567
  const char* const additional_constraints_inproc_cancel_stream = "{}";
@@ -787,6 +795,8 @@ const ExperimentMetadata g_experiment_metadata[] = {
787
795
  description_h2_max_deallocating_streams_headroom,
788
796
  additional_constraints_h2_max_deallocating_streams_headroom, nullptr, 0,
789
797
  false, true},
798
+ {"header_data_frame", description_header_data_frame,
799
+ additional_constraints_header_data_frame, nullptr, 0, true, true},
790
800
  {"inproc_cancel_stream", description_inproc_cancel_stream,
791
801
  additional_constraints_inproc_cancel_stream, nullptr, 0, true, true},
792
802
  {"keep_alive_ping_timer_batch", description_keep_alive_ping_timer_batch,
@@ -799,7 +809,7 @@ const ExperimentMetadata g_experiment_metadata[] = {
799
809
  {"memory_optimization_02", description_memory_optimization_02,
800
810
  additional_constraints_memory_optimization_02, nullptr, 0, false, false},
801
811
  {"message_size_refactoring", description_message_size_refactoring,
802
- additional_constraints_message_size_refactoring, nullptr, 0, false, true},
812
+ additional_constraints_message_size_refactoring, nullptr, 0, true, true},
803
813
  {"metadata_outstanding_token_refactor",
804
814
  description_metadata_outstanding_token_refactor,
805
815
  additional_constraints_metadata_outstanding_token_refactor, nullptr, 0,
@@ -831,7 +841,7 @@ const ExperimentMetadata g_experiment_metadata[] = {
831
841
  {"ph2_client_server", description_ph2_client_server,
832
842
  additional_constraints_ph2_client_server, nullptr, 0, false, true},
833
843
  {"ph2_perf_01", description_ph2_perf_01, additional_constraints_ph2_perf_01,
834
- nullptr, 0, false, true},
844
+ nullptr, 0, true, true},
835
845
  {"ph2_server", description_ph2_server, additional_constraints_ph2_server,
836
846
  nullptr, 0, false, true},
837
847
  {"pick_first_ignore_empty_updates",
@@ -1005,6 +1015,9 @@ const char* const description_h2_max_deallocating_streams_headroom =
1005
1015
  "Separate allocated max concurrent streams.";
1006
1016
  const char* const additional_constraints_h2_max_deallocating_streams_headroom =
1007
1017
  "{}";
1018
+ const char* const description_header_data_frame =
1019
+ "Managing header and data memory better";
1020
+ const char* const additional_constraints_header_data_frame = "{}";
1008
1021
  const char* const description_inproc_cancel_stream =
1009
1022
  "If set, cancel inproc stream inside the transport mutex.";
1010
1023
  const char* const additional_constraints_inproc_cancel_stream = "{}";
@@ -1238,6 +1251,8 @@ const ExperimentMetadata g_experiment_metadata[] = {
1238
1251
  description_h2_max_deallocating_streams_headroom,
1239
1252
  additional_constraints_h2_max_deallocating_streams_headroom, nullptr, 0,
1240
1253
  false, true},
1254
+ {"header_data_frame", description_header_data_frame,
1255
+ additional_constraints_header_data_frame, nullptr, 0, true, true},
1241
1256
  {"inproc_cancel_stream", description_inproc_cancel_stream,
1242
1257
  additional_constraints_inproc_cancel_stream, nullptr, 0, true, true},
1243
1258
  {"keep_alive_ping_timer_batch", description_keep_alive_ping_timer_batch,
@@ -1250,7 +1265,7 @@ const ExperimentMetadata g_experiment_metadata[] = {
1250
1265
  {"memory_optimization_02", description_memory_optimization_02,
1251
1266
  additional_constraints_memory_optimization_02, nullptr, 0, false, false},
1252
1267
  {"message_size_refactoring", description_message_size_refactoring,
1253
- additional_constraints_message_size_refactoring, nullptr, 0, false, true},
1268
+ additional_constraints_message_size_refactoring, nullptr, 0, true, true},
1254
1269
  {"metadata_outstanding_token_refactor",
1255
1270
  description_metadata_outstanding_token_refactor,
1256
1271
  additional_constraints_metadata_outstanding_token_refactor, nullptr, 0,
@@ -1282,7 +1297,7 @@ const ExperimentMetadata g_experiment_metadata[] = {
1282
1297
  {"ph2_client_server", description_ph2_client_server,
1283
1298
  additional_constraints_ph2_client_server, nullptr, 0, false, true},
1284
1299
  {"ph2_perf_01", description_ph2_perf_01, additional_constraints_ph2_perf_01,
1285
- nullptr, 0, false, true},
1300
+ nullptr, 0, true, true},
1286
1301
  {"ph2_server", description_ph2_server, additional_constraints_ph2_server,
1287
1302
  nullptr, 0, false, true},
1288
1303
  {"pick_first_ignore_empty_updates",
@@ -93,13 +93,16 @@ inline bool IsFailRecvMetadataOnDeadlineExceededEnabled() { return false; }
93
93
  inline bool IsFreeLargeAllocatorEnabled() { return false; }
94
94
  inline bool IsFuseFiltersEnabled() { return false; }
95
95
  inline bool IsH2MaxDeallocatingStreamsHeadroomEnabled() { return false; }
96
+ #define GRPC_EXPERIMENT_IS_INCLUDED_HEADER_DATA_FRAME
97
+ inline bool IsHeaderDataFrameEnabled() { return true; }
96
98
  #define GRPC_EXPERIMENT_IS_INCLUDED_INPROC_CANCEL_STREAM
97
99
  inline bool IsInprocCancelStreamEnabled() { return true; }
98
100
  inline bool IsKeepAlivePingTimerBatchEnabled() { return false; }
99
101
  inline bool IsLocalConnectorSecureEnabled() { return false; }
100
102
  inline bool IsMemoryOptimization01Enabled() { return false; }
101
103
  inline bool IsMemoryOptimization02Enabled() { return false; }
102
- inline bool IsMessageSizeRefactoringEnabled() { return false; }
104
+ #define GRPC_EXPERIMENT_IS_INCLUDED_MESSAGE_SIZE_REFACTORING
105
+ inline bool IsMessageSizeRefactoringEnabled() { return true; }
103
106
  inline bool IsMetadataOutstandingTokenRefactorEnabled() { return false; }
104
107
  inline bool IsMetadataPublishToAppTagEnabled() { return false; }
105
108
  #define GRPC_EXPERIMENT_IS_INCLUDED_MONITORING_EXPERIMENT
@@ -118,7 +121,8 @@ inline bool IsOptimization06Enabled() { return false; }
118
121
  inline bool IsOtelExportTelemetryDomainsEnabled() { return false; }
119
122
  inline bool IsPh2ClientEnabled() { return false; }
120
123
  inline bool IsPh2ClientServerEnabled() { return false; }
121
- inline bool IsPh2Perf01Enabled() { return false; }
124
+ #define GRPC_EXPERIMENT_IS_INCLUDED_PH2_PERF_01
125
+ inline bool IsPh2Perf01Enabled() { return true; }
122
126
  inline bool IsPh2ServerEnabled() { return false; }
123
127
  inline bool IsPickFirstIgnoreEmptyUpdatesEnabled() { return false; }
124
128
  inline bool IsPipelinedReadSecureEndpointEnabled() { return false; }
@@ -185,13 +189,16 @@ inline bool IsFailRecvMetadataOnDeadlineExceededEnabled() { return false; }
185
189
  inline bool IsFreeLargeAllocatorEnabled() { return false; }
186
190
  inline bool IsFuseFiltersEnabled() { return false; }
187
191
  inline bool IsH2MaxDeallocatingStreamsHeadroomEnabled() { return false; }
192
+ #define GRPC_EXPERIMENT_IS_INCLUDED_HEADER_DATA_FRAME
193
+ inline bool IsHeaderDataFrameEnabled() { return true; }
188
194
  #define GRPC_EXPERIMENT_IS_INCLUDED_INPROC_CANCEL_STREAM
189
195
  inline bool IsInprocCancelStreamEnabled() { return true; }
190
196
  inline bool IsKeepAlivePingTimerBatchEnabled() { return false; }
191
197
  inline bool IsLocalConnectorSecureEnabled() { return false; }
192
198
  inline bool IsMemoryOptimization01Enabled() { return false; }
193
199
  inline bool IsMemoryOptimization02Enabled() { return false; }
194
- inline bool IsMessageSizeRefactoringEnabled() { return false; }
200
+ #define GRPC_EXPERIMENT_IS_INCLUDED_MESSAGE_SIZE_REFACTORING
201
+ inline bool IsMessageSizeRefactoringEnabled() { return true; }
195
202
  inline bool IsMetadataOutstandingTokenRefactorEnabled() { return false; }
196
203
  inline bool IsMetadataPublishToAppTagEnabled() { return false; }
197
204
  #define GRPC_EXPERIMENT_IS_INCLUDED_MONITORING_EXPERIMENT
@@ -210,7 +217,8 @@ inline bool IsOptimization06Enabled() { return false; }
210
217
  inline bool IsOtelExportTelemetryDomainsEnabled() { return false; }
211
218
  inline bool IsPh2ClientEnabled() { return false; }
212
219
  inline bool IsPh2ClientServerEnabled() { return false; }
213
- inline bool IsPh2Perf01Enabled() { return false; }
220
+ #define GRPC_EXPERIMENT_IS_INCLUDED_PH2_PERF_01
221
+ inline bool IsPh2Perf01Enabled() { return true; }
214
222
  inline bool IsPh2ServerEnabled() { return false; }
215
223
  inline bool IsPickFirstIgnoreEmptyUpdatesEnabled() { return false; }
216
224
  inline bool IsPipelinedReadSecureEndpointEnabled() { return false; }
@@ -277,13 +285,16 @@ inline bool IsFailRecvMetadataOnDeadlineExceededEnabled() { return false; }
277
285
  inline bool IsFreeLargeAllocatorEnabled() { return false; }
278
286
  inline bool IsFuseFiltersEnabled() { return false; }
279
287
  inline bool IsH2MaxDeallocatingStreamsHeadroomEnabled() { return false; }
288
+ #define GRPC_EXPERIMENT_IS_INCLUDED_HEADER_DATA_FRAME
289
+ inline bool IsHeaderDataFrameEnabled() { return true; }
280
290
  #define GRPC_EXPERIMENT_IS_INCLUDED_INPROC_CANCEL_STREAM
281
291
  inline bool IsInprocCancelStreamEnabled() { return true; }
282
292
  inline bool IsKeepAlivePingTimerBatchEnabled() { return false; }
283
293
  inline bool IsLocalConnectorSecureEnabled() { return false; }
284
294
  inline bool IsMemoryOptimization01Enabled() { return false; }
285
295
  inline bool IsMemoryOptimization02Enabled() { return false; }
286
- inline bool IsMessageSizeRefactoringEnabled() { return false; }
296
+ #define GRPC_EXPERIMENT_IS_INCLUDED_MESSAGE_SIZE_REFACTORING
297
+ inline bool IsMessageSizeRefactoringEnabled() { return true; }
287
298
  inline bool IsMetadataOutstandingTokenRefactorEnabled() { return false; }
288
299
  inline bool IsMetadataPublishToAppTagEnabled() { return false; }
289
300
  #define GRPC_EXPERIMENT_IS_INCLUDED_MONITORING_EXPERIMENT
@@ -302,7 +313,8 @@ inline bool IsOptimization06Enabled() { return false; }
302
313
  inline bool IsOtelExportTelemetryDomainsEnabled() { return false; }
303
314
  inline bool IsPh2ClientEnabled() { return false; }
304
315
  inline bool IsPh2ClientServerEnabled() { return false; }
305
- inline bool IsPh2Perf01Enabled() { return false; }
316
+ #define GRPC_EXPERIMENT_IS_INCLUDED_PH2_PERF_01
317
+ inline bool IsPh2Perf01Enabled() { return true; }
306
318
  inline bool IsPh2ServerEnabled() { return false; }
307
319
  inline bool IsPickFirstIgnoreEmptyUpdatesEnabled() { return false; }
308
320
  inline bool IsPipelinedReadSecureEndpointEnabled() { return false; }
@@ -354,6 +366,7 @@ enum ExperimentIds {
354
366
  kExperimentIdFreeLargeAllocator,
355
367
  kExperimentIdFuseFilters,
356
368
  kExperimentIdH2MaxDeallocatingStreamsHeadroom,
369
+ kExperimentIdHeaderDataFrame,
357
370
  kExperimentIdInprocCancelStream,
358
371
  kExperimentIdKeepAlivePingTimerBatch,
359
372
  kExperimentIdLocalConnectorSecure,
@@ -479,6 +492,10 @@ inline bool IsFuseFiltersEnabled() {
479
492
  inline bool IsH2MaxDeallocatingStreamsHeadroomEnabled() {
480
493
  return IsExperimentEnabled<kExperimentIdH2MaxDeallocatingStreamsHeadroom>();
481
494
  }
495
+ #define GRPC_EXPERIMENT_IS_INCLUDED_HEADER_DATA_FRAME
496
+ inline bool IsHeaderDataFrameEnabled() {
497
+ return IsExperimentEnabled<kExperimentIdHeaderDataFrame>();
498
+ }
482
499
  #define GRPC_EXPERIMENT_IS_INCLUDED_INPROC_CANCEL_STREAM
483
500
  inline bool IsInprocCancelStreamEnabled() {
484
501
  return IsExperimentEnabled<kExperimentIdInprocCancelStream>();
@@ -180,7 +180,9 @@ grpc_call* LegacyChannel::CreateCall(
180
180
  args.authority = std::move(authority);
181
181
  args.send_deadline = deadline;
182
182
  args.registered_method = registered_method;
183
- args.arena_init_function = arena_init_function;
183
+ if (arena_init_function.has_value()) {
184
+ args.arena_init_function.emplace(*arena_init_function);
185
+ }
184
186
  grpc_call* call;
185
187
  GRPC_LOG_IF_ERROR("call_create", grpc_call_create(&args, &call));
186
188
  return call;
@@ -14,5 +14,5 @@
14
14
 
15
15
  # GRPC contains the General RPC module.
16
16
  module GRPC
17
- VERSION = '1.83.0.pre1'
17
+ VERSION = '1.83.1'
18
18
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grpc
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.83.0.pre1
4
+ version: 1.83.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - gRPC Authors
@@ -3981,7 +3981,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
3981
3981
  - !ruby/object:Gem::Version
3982
3982
  version: '0'
3983
3983
  requirements: []
3984
- rubygems_version: 4.0.15
3984
+ rubygems_version: 4.0.19
3985
3985
  specification_version: 4
3986
3986
  summary: GRPC system in Ruby
3987
3987
  test_files: