grpc 1.82.2 → 1.83.0.pre1

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.
Files changed (160) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +8 -5
  3. data/etc/roots.pem +10400 -3855
  4. data/include/grpc/grpc_audit_logging.h +2 -2
  5. data/include/grpc/grpc_security_constants.h +2 -0
  6. data/include/grpc/impl/channel_arg_names.h +23 -0
  7. data/src/core/call/call_filters.h +19 -3
  8. data/src/core/call/call_spine.h +4 -4
  9. data/src/core/call/client_call.cc +1 -1
  10. data/src/core/call/metadata.cc +7 -2
  11. data/src/core/call/server_call.cc +13 -3
  12. data/src/core/call/server_call.h +5 -3
  13. data/src/core/client_channel/backup_poller.cc +2 -17
  14. data/src/core/client_channel/client_channel.cc +17 -14
  15. data/src/core/client_channel/client_channel.h +3 -1
  16. data/src/core/client_channel/client_channel_filter.cc +11 -13
  17. data/src/core/client_channel/client_channel_service_config.cc +5 -13
  18. data/src/core/client_channel/direct_channel.cc +5 -1
  19. data/src/core/client_channel/direct_channel.h +3 -1
  20. data/src/core/config/experiment_env_var.cc +30 -0
  21. data/src/core/config/experiment_env_var.h +26 -0
  22. data/src/core/credentials/call/regional_access_boundary_fetcher.cc +6 -6
  23. data/src/core/credentials/transport/ssl/ssl_security_connector.cc +14 -2
  24. data/src/core/credentials/transport/tls/grpc_tls_certificate_selector.cc +172 -0
  25. data/src/core/credentials/transport/tls/grpc_tls_certificate_selector.h +103 -0
  26. data/src/core/credentials/transport/tls/load_system_roots_fallback.cc +3 -2
  27. data/src/core/credentials/transport/tls/load_system_roots_supported.cc +10 -3
  28. data/src/core/credentials/transport/tls/tls_security_connector.cc +14 -2
  29. data/src/core/credentials/transport/xds/xds_credentials.cc +4 -12
  30. data/src/core/ext/filters/http/message_compress/compression_filter.cc +32 -25
  31. data/src/core/ext/filters/http/message_compress/compression_filter.h +1 -0
  32. data/src/core/ext/filters/rbac/rbac_service_config_parser.cc +2 -1
  33. data/src/core/ext/transport/chttp2/server/chttp2_server.cc +19 -13
  34. data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +14 -57
  35. data/src/core/ext/transport/chttp2/transport/flow_control.cc +2 -2
  36. data/src/core/ext/transport/chttp2/transport/flow_control.h +3 -2
  37. data/src/core/ext/transport/chttp2/transport/frame.cc +58 -1
  38. data/src/core/ext/transport/chttp2/transport/frame.h +13 -1
  39. data/src/core/ext/transport/chttp2/transport/frame_data.cc +2 -34
  40. data/src/core/ext/transport/chttp2/transport/frame_goaway.cc +23 -55
  41. data/src/core/ext/transport/chttp2/transport/frame_goaway.h +0 -1
  42. data/src/core/ext/transport/chttp2/transport/frame_rst_stream.cc +2 -4
  43. data/src/core/ext/transport/chttp2/transport/frame_security.cc +10 -1
  44. data/src/core/ext/transport/chttp2/transport/frame_security.h +2 -1
  45. data/src/core/ext/transport/chttp2/transport/goaway.cc +11 -1
  46. data/src/core/ext/transport/chttp2/transport/goaway.h +17 -1
  47. data/src/core/ext/transport/chttp2/transport/hpack_parser.cc +9 -0
  48. data/src/core/ext/transport/chttp2/transport/http2_client_transport.cc +117 -276
  49. data/src/core/ext/transport/chttp2/transport/http2_client_transport.h +44 -17
  50. data/src/core/ext/transport/chttp2/transport/http2_server_transport.cc +382 -496
  51. data/src/core/ext/transport/chttp2/transport/http2_server_transport.h +75 -77
  52. data/src/core/ext/transport/chttp2/transport/http2_settings.cc +1 -1
  53. data/src/core/ext/transport/chttp2/transport/http2_settings.h +30 -11
  54. data/src/core/ext/transport/chttp2/transport/http2_settings_promises.h +24 -9
  55. data/src/core/ext/transport/chttp2/transport/http2_transport.cc +26 -0
  56. data/src/core/ext/transport/chttp2/transport/http2_transport.h +2 -0
  57. data/src/core/ext/transport/chttp2/transport/internal.h +4 -6
  58. data/src/core/ext/transport/chttp2/transport/parsing.cc +3 -10
  59. data/src/core/ext/transport/chttp2/transport/ping_promise.cc +1 -1
  60. data/src/core/ext/transport/chttp2/transport/ping_rate_policy.cc +4 -10
  61. data/src/core/ext/transport/chttp2/transport/read_context.h +62 -20
  62. data/src/core/ext/transport/chttp2/transport/security_frame.h +1 -0
  63. data/src/core/ext/transport/chttp2/transport/stream.h +271 -120
  64. data/src/core/ext/transport/chttp2/transport/stream_data_queue.h +77 -61
  65. data/src/core/handshaker/security/secure_endpoint.cc +0 -13
  66. data/src/core/lib/channel/promise_based_filter.cc +77 -3
  67. data/src/core/lib/channel/promise_based_filter.h +238 -184
  68. data/src/core/lib/compression/message_compress.cc +97 -132
  69. data/src/core/lib/compression/message_compress.h +0 -24
  70. data/src/core/lib/event_engine/extensions/receive_coalescing_extension.h +0 -4
  71. data/src/core/lib/event_engine/extensions/tcp_trace.h +1 -1
  72. data/src/core/lib/event_engine/posix_engine/posix_engine.cc +2 -12
  73. data/src/core/lib/event_engine/shim.cc +2 -16
  74. data/src/core/lib/event_engine/shim.h +0 -4
  75. data/src/core/lib/experiments/experiments.cc +57 -123
  76. data/src/core/lib/experiments/experiments.h +43 -82
  77. data/src/core/lib/iomgr/error.cc +3 -73
  78. data/src/core/lib/iomgr/error.h +8 -6
  79. data/src/core/lib/iomgr/error_cfstream.cc +1 -2
  80. data/src/core/lib/iomgr/ev_epoll1_linux.cc +2 -6
  81. data/src/core/lib/iomgr/ev_poll_posix.cc +2 -6
  82. data/src/core/lib/iomgr/tcp_posix.cc +2 -6
  83. data/src/core/lib/security/authorization/audit_logging.cc +2 -2
  84. data/src/core/lib/security/authorization/audit_logging.h +3 -3
  85. data/src/core/lib/security/authorization/grpc_authorization_engine.cc +11 -13
  86. data/src/core/lib/security/authorization/grpc_authorization_engine.h +1 -1
  87. data/src/core/lib/security/authorization/matchers.cc +20 -20
  88. data/src/core/lib/security/authorization/matchers.h +15 -16
  89. data/src/core/lib/security/authorization/rbac_policy.h +1 -1
  90. data/src/core/lib/security/authorization/stdout_logger.cc +3 -3
  91. data/src/core/lib/security/authorization/stdout_logger.h +6 -5
  92. data/src/core/lib/surface/call.cc +0 -8
  93. data/src/core/lib/surface/call.h +2 -0
  94. data/src/core/lib/surface/channel.cc +21 -2
  95. data/src/core/lib/surface/channel.h +14 -6
  96. data/src/core/lib/surface/filter_stack_call.cc +10 -29
  97. data/src/core/lib/surface/legacy_channel.cc +7 -7
  98. data/src/core/lib/surface/legacy_channel.h +3 -1
  99. data/src/core/lib/surface/version.cc +2 -2
  100. data/src/core/lib/transport/bdp_estimator.cc +13 -13
  101. data/src/core/lib/transport/bdp_estimator.h +9 -5
  102. data/src/core/lib/transport/error_utils.cc +26 -138
  103. data/src/core/lib/transport/promise_endpoint.h +2 -4
  104. data/src/core/load_balancing/grpclb/grpclb.cc +2 -1
  105. data/src/core/load_balancing/pick_first/pick_first.cc +33 -2
  106. data/src/core/load_balancing/pick_first/pick_first.h +6 -0
  107. data/src/core/load_balancing/ring_hash/ring_hash.cc +3 -10
  108. data/src/core/load_balancing/rls/rls.cc +2 -1
  109. data/src/core/load_balancing/weighted_round_robin/weighted_round_robin.cc +2 -7
  110. data/src/core/load_balancing/xds/cds.cc +80 -56
  111. data/src/core/load_balancing/xds/cds.h +21 -0
  112. data/src/core/mitigation_engine/mitigation.h +53 -0
  113. data/src/core/mitigation_engine/mitigation_provider.h +62 -0
  114. data/src/core/resolver/dns/dns_resolver_plugin.cc +1 -6
  115. data/src/core/resolver/xds/xds_resolver.cc +14 -11
  116. data/src/core/server/server.h +1 -4
  117. data/src/core/server/server_config_selector.h +5 -4
  118. data/src/core/server/server_config_selector_filter.cc +67 -80
  119. data/src/core/server/xds_server_config_fetcher.cc +681 -692
  120. data/src/core/server/xds_server_config_fetcher_legacy.cc +15 -12
  121. data/src/core/telemetry/call_tracer.cc +49 -2
  122. data/src/core/telemetry/call_tracer.h +1 -0
  123. data/src/core/telemetry/tcp_tracer.h +38 -0
  124. data/src/core/tsi/alts/handshaker/alts_handshaker_client.cc +1 -1
  125. data/src/core/tsi/ssl_telemetry_utils.cc +343 -0
  126. data/src/core/tsi/ssl_telemetry_utils.h +74 -0
  127. data/src/core/tsi/ssl_transport_security.cc +577 -301
  128. data/src/core/tsi/ssl_transport_security.h +22 -6
  129. data/src/core/tsi/ssl_transport_security_utils.cc +2 -0
  130. data/src/core/tsi/transport_security.h +7 -0
  131. data/src/core/util/http_client/httpcli.cc +1 -4
  132. data/src/core/util/http_client/httpcli_security_connector.cc +2 -1
  133. data/src/core/util/status_helper.cc +71 -192
  134. data/src/core/util/status_helper.h +16 -21
  135. data/src/core/xds/grpc/file_watcher_certificate_provider_factory.cc +2 -11
  136. data/src/core/xds/grpc/xds_bootstrap_grpc.cc +2 -7
  137. data/src/core/xds/grpc/xds_cluster_parser.cc +5 -16
  138. data/src/core/xds/grpc/xds_common_types.cc +94 -38
  139. data/src/core/xds/grpc/xds_common_types.h +33 -18
  140. data/src/core/xds/grpc/xds_common_types_parser.cc +168 -100
  141. data/src/core/xds/grpc/xds_common_types_parser.h +18 -1
  142. data/src/core/xds/grpc/xds_endpoint_parser.cc +6 -17
  143. data/src/core/xds/grpc/xds_http_filter_registry.cc +2 -10
  144. data/src/core/xds/grpc/xds_http_rbac_filter.cc +3 -12
  145. data/src/core/xds/grpc/xds_metadata_parser.cc +0 -2
  146. data/src/core/xds/grpc/xds_route_config_parser.cc +7 -11
  147. data/src/core/xds/grpc/xds_routing.cc +113 -82
  148. data/src/core/xds/grpc/xds_routing.h +70 -20
  149. data/src/core/xds/grpc/xds_server_grpc.cc +22 -13
  150. data/src/core/xds/grpc/xds_server_grpc.h +16 -2
  151. data/src/core/xds/grpc/xds_server_grpc_interface.h +10 -0
  152. data/src/core/xds/grpc/xds_transport_grpc.cc +123 -18
  153. data/src/core/xds/grpc/xds_transport_grpc.h +28 -4
  154. data/src/core/xds/xds_client/lrs_client.cc +3 -7
  155. data/src/core/xds/xds_client/xds_bootstrap.cc +4 -16
  156. data/src/core/xds/xds_client/xds_client.cc +2 -15
  157. data/src/core/xds/xds_client/xds_transport.h +3 -0
  158. data/src/ruby/lib/grpc/version.rb +1 -1
  159. data/src/ruby/pb/src/proto/grpc/testing/messages_pb.rb +1 -1
  160. metadata +10 -2
@@ -106,7 +106,6 @@
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"
110
109
  #include "src/core/util/bitset.h"
111
110
  #include "src/core/util/crash.h"
112
111
  #include "src/core/util/debug_location.h"
@@ -546,6 +545,10 @@ static void read_channel_args(grpc_chttp2_transport* t,
546
545
 
547
546
  t->settings.mutable_local().SetAllowSecurityFrame(
548
547
  channel_args.GetBool(GRPC_ARG_SECURITY_FRAME_ALLOWED).value_or(false));
548
+ t->max_security_frame_size = static_cast<uint32_t>(grpc_core::Clamp(
549
+ channel_args.GetInt(GRPC_ARG_MAX_SECURITY_FRAME_SIZE)
550
+ .value_or(kMaxSecurityFrameSize),
551
+ kMinMaxSecurityFrameSize, static_cast<int>(kMaxSecurityFrameSize)));
549
552
 
550
553
  t->ping_on_rst_stream_percent = grpc_core::Clamp(
551
554
  channel_args.GetInt(GRPC_ARG_HTTP2_PING_ON_RST_STREAM_PERCENT)
@@ -760,7 +763,8 @@ grpc_chttp2_transport::grpc_chttp2_transport(
760
763
  grpc_core::GlobalStatsPluginRegistry::StatsPluginGroup>();
761
764
  if (epte != nullptr && stats_plugin_group != nullptr) {
762
765
  epte->EnableTcpTelemetry(stats_plugin_group->GetCollectionScope(),
763
- /*is_control_endpoint=*/false);
766
+ /*is_control_endpoint=*/false,
767
+ /*trace_full_buffer=*/false);
764
768
  epte->SetTcpTracer(std::make_shared<grpc_core::DefaultTcpTracer>(
765
769
  std::move(stats_plugin_group)));
766
770
  }
@@ -812,7 +816,6 @@ grpc_chttp2_transport::grpc_chttp2_transport(
812
816
  Ref(), &init_keepalive_ping_locked),
813
817
  absl::OkStatus());
814
818
 
815
- // TODO(tjagtap) : [PH2][P0] : Do this for PH2.
816
819
  if (flow_control.bdp_probe()) {
817
820
  bdp_ping_blocked = true;
818
821
  grpc_chttp2_act_on_flowctl_action(flow_control.PeriodicUpdate(), this,
@@ -856,9 +859,6 @@ grpc_chttp2_transport::grpc_chttp2_transport(
856
859
  epte->SetSocketNode(channelz_socket);
857
860
  }
858
861
  }
859
-
860
- max_recv_message_length =
861
- grpc_core::GetMaxRecvSizeFromChannelArgs(channel_args);
862
862
  }
863
863
 
864
864
  static void destroy_transport_locked(void* tp, grpc_error_handle /*error*/) {
@@ -879,10 +879,6 @@ static void close_transport_locked(grpc_chttp2_transport* t,
879
879
  grpc_error_handle error) {
880
880
  end_all_the_calls(t, error);
881
881
  cancel_pings(t, error);
882
- if (t->transport_framing_endpoint_extension != nullptr) {
883
- t->transport_framing_endpoint_extension->SetSendFrameCallback(nullptr);
884
- t->transport_framing_endpoint_extension = nullptr;
885
- }
886
882
  if (t->closed_with_error.ok()) {
887
883
  if (!grpc_error_has_clear_grpc_status(error)) {
888
884
  error =
@@ -1381,14 +1377,11 @@ void grpc_chttp2_add_incoming_goaway(grpc_chttp2_transport* t,
1381
1377
  uint32_t last_stream_id,
1382
1378
  absl::string_view goaway_text) {
1383
1379
  t->goaway_error = grpc_error_set_int(
1384
- grpc_error_set_int(
1385
- grpc_core::StatusCreate(
1386
- absl::StatusCode::kUnavailable,
1387
- absl::StrFormat("GOAWAY received; Error code: %u; Debug Text: %s",
1388
- goaway_error, goaway_text),
1389
- DEBUG_LOCATION, {}),
1390
- grpc_core::StatusIntProperty::kHttp2Error,
1391
- static_cast<intptr_t>(goaway_error)),
1380
+ grpc_error_set_int(absl::UnavailableError(absl::StrFormat(
1381
+ "GOAWAY received; Error code: %u; Debug Text: %s",
1382
+ goaway_error, goaway_text)),
1383
+ grpc_core::StatusIntProperty::kHttp2Error,
1384
+ static_cast<intptr_t>(goaway_error)),
1392
1385
  grpc_core::StatusIntProperty::kRpcStatus, GRPC_STATUS_UNAVAILABLE);
1393
1386
 
1394
1387
  GRPC_TRACE_LOG(http, INFO)
@@ -1514,8 +1507,7 @@ static grpc_closure* add_closure_barrier(grpc_closure* closure) {
1514
1507
  return closure;
1515
1508
  }
1516
1509
 
1517
- static void null_then_sched_closure_with_error(grpc_closure** closure,
1518
- grpc_error_handle error) {
1510
+ static void null_then_sched_closure(grpc_closure** closure) {
1519
1511
  grpc_closure* c = *closure;
1520
1512
  *closure = nullptr;
1521
1513
  // null_then_schedule_closure might be run during a start_batch which might
@@ -1524,11 +1516,7 @@ static void null_then_sched_closure_with_error(grpc_closure** closure,
1524
1516
  // completion, have the application see it, and make a new operation on the
1525
1517
  // call which recycles the batch BEFORE the call to start_batch completes,
1526
1518
  // forcing a race.
1527
- grpc_core::ExecCtx::Run(DEBUG_LOCATION, c, error);
1528
- }
1529
-
1530
- static void null_then_sched_closure(grpc_closure** closure) {
1531
- null_then_sched_closure_with_error(closure, absl::OkStatus());
1519
+ grpc_core::ExecCtx::Run(DEBUG_LOCATION, c, absl::OkStatus());
1532
1520
  }
1533
1521
 
1534
1522
  void grpc_chttp2_complete_closure_step(grpc_chttp2_transport* t,
@@ -2355,8 +2343,6 @@ void grpc_chttp2_maybe_complete_recv_initial_metadata(grpc_chttp2_transport* t,
2355
2343
  t->registered_method_matcher_cb(t->accept_stream_cb_user_data,
2356
2344
  s->recv_initial_metadata);
2357
2345
  }
2358
- s->max_recv_message_length =
2359
- GetMaxRecvSizeFromCallContext(s->arena, t->max_recv_message_length);
2360
2346
  null_then_sched_closure(&s->recv_initial_metadata_ready);
2361
2347
  }
2362
2348
  }
@@ -2429,36 +2415,7 @@ void grpc_chttp2_maybe_complete_recv_message(grpc_chttp2_transport* t,
2429
2415
  *s->call_failed_before_recv_message =
2430
2416
  (s->published_metadata[1] != GRPC_METADATA_PUBLISHED_AT_CLOSE);
2431
2417
  }
2432
- if (s->seen_error && s->message_size_limit_exceeded) {
2433
- null_then_sched_closure_with_error(&s->recv_message_ready, error);
2434
- } else {
2435
- null_then_sched_closure(&s->recv_message_ready);
2436
- }
2437
- } else if (s->seen_error && s->message_size_limit_exceeded) {
2438
- null_then_sched_closure_with_error(&s->recv_message_ready, error);
2439
- }
2440
-
2441
- if (grpc_core::IsMessageSizeRefactoringEnabled() && s->seen_error &&
2442
- s->message_size_limit_exceeded) {
2443
- s->message_size_limit_exceeded = false;
2444
- // Explicitly cancel the stream to fail the RPC immediately.
2445
- // We delay the cancellation until the recv_message_ready closure is
2446
- // executed to prevent re-entrancy issues. When the HTTP/2 frame deframer
2447
- // in `grpc_deframe_unprocessed_incoming_frames`
2448
- // returns a size violation error, invoking `grpc_chttp2_cancel_stream`
2449
- // immediately triggers `grpc_chttp2_mark_stream_closed`. This in turn
2450
- // synchronously re-enters `grpc_chttp2_maybe_complete_recv_message` while
2451
- // the original deframing loop is still active on the call stack.
2452
- //
2453
- // Because the re-entrant invocation observes that the incoming frame
2454
- // storage has been cleared but `s->recv_message_ready` is still non-null,
2455
- // it preemptively schedules the closure as a standard/non-error stream
2456
- // termination (i.e., via `null_then_sched_closure(...,
2457
- // absl::OkStatus())`). By the time control returns to the initial (outer)
2458
- // deframing loop to execute `null_then_sched_closure_with_error`, the
2459
- // closure pointer is already null, causing the original error context to
2460
- // be discarded.
2461
- grpc_chttp2_cancel_stream(t, s, error, true, nullptr);
2418
+ null_then_sched_closure(&s->recv_message_ready);
2462
2419
  }
2463
2420
  }();
2464
2421
 
@@ -119,12 +119,12 @@ std::string FlowControlAction::ImmediateUpdateReasons() const {
119
119
  return result;
120
120
  }
121
121
 
122
- TransportFlowControl::TransportFlowControl(absl::string_view name,
122
+ TransportFlowControl::TransportFlowControl(absl::string_view peer_name,
123
123
  bool enable_bdp_probe,
124
124
  MemoryOwner* memory_owner)
125
125
  : memory_owner_(memory_owner),
126
126
  enable_bdp_probe_(enable_bdp_probe),
127
- bdp_estimator_(name) {}
127
+ bdp_estimator_(peer_name) {}
128
128
 
129
129
  uint32_t TransportFlowControl::DesiredAnnounceSize(bool writing_anyway) const {
130
130
  const uint32_t target_announced_window =
@@ -201,7 +201,8 @@ std::ostream& operator<<(std::ostream& out, const FlowControlAction& action);
201
201
  // This class manages the flow control at a connection level.
202
202
  class TransportFlowControl final {
203
203
  public:
204
- explicit TransportFlowControl(absl::string_view name, bool enable_bdp_probe,
204
+ explicit TransportFlowControl(absl::string_view peer_name,
205
+ bool enable_bdp_probe,
205
206
  MemoryOwner* memory_owner);
206
207
  ~TransportFlowControl() {}
207
208
 
@@ -318,7 +319,7 @@ class TransportFlowControl final {
318
319
  // Call periodically (at a low-ish rate, 100ms - 10s makes sense)
319
320
  // to perform more complex flow control calculations and return an action
320
321
  // to let the transport change its parameters.
321
- // TODO(tjagtap) [PH2][P2] Plumb with PH2 flow control.
322
+ // TODO(tjagtap) [PH2][P2][FCV3] Plumb with PH2 flow control.
322
323
  FlowControlAction PeriodicUpdate();
323
324
 
324
325
  int64_t test_only_target_window() const { return target_window(); }
@@ -831,7 +831,8 @@ Http2Status ValidateFrameHeader(const uint32_t max_frame_size_setting,
831
831
  const uint32_t last_stream_id,
832
832
  const bool is_client,
833
833
  const bool is_first_settings_processed,
834
- Http2FrameCountTracker& tracker) {
834
+ Http2FrameCountTracker& tracker,
835
+ const uint32_t max_security_frame_size) {
835
836
  const bool is_data_frame =
836
837
  current_frame_header.type == static_cast<uint8_t>(FrameType::kData);
837
838
  const bool is_continuation_frame =
@@ -861,6 +862,16 @@ Http2Status ValidateFrameHeader(const uint32_t max_frame_size_setting,
861
862
  ", Max Size = ", max_frame_size_setting));
862
863
  }
863
864
 
865
+ if (GPR_UNLIKELY(current_frame_header.type ==
866
+ static_cast<uint8_t>(FrameType::kCustomSecurity) &&
867
+ current_frame_header.length > max_security_frame_size)) {
868
+ return Http2Status::Http2ConnectionError(
869
+ Http2ErrorCode::kFrameSizeError,
870
+ absl::StrCat(GrpcErrors::kSecurityFrameTooLarge,
871
+ max_security_frame_size,
872
+ ", Received size : ", current_frame_header.length));
873
+ }
874
+
864
875
  // RFC 9113 (Section 6.10) requires that if a HEADERS frame does not have
865
876
  // END_HEADERS set, it must be followed by a contiguous sequence of
866
877
  // CONTINUATION frames for the same stream, ending with END_HEADERS. No other
@@ -928,3 +939,49 @@ Http2Status ValidateFrameHeader(const uint32_t max_frame_size_setting,
928
939
  return Http2Status::Ok();
929
940
  }
930
941
  } // namespace grpc_core
942
+
943
+ /*
944
+ A note on Security Frames
945
+
946
+ Security Frame is a custom frame defined by gRPC.
947
+
948
+ SECURITY Frame
949
+
950
+ The SECURITY frame (type=200) is used to transmit out-of-band security and
951
+ transport-level privacy information between peers.
952
+
953
+ Both peers MUST agree to allow SECURITY frames.
954
+
955
+ +------------------------+
956
+ | Payload Length |
957
+ | (24) |
958
+ +--------+--------+------+
959
+ | Type | Flags |
960
+ | (200) | (8) |
961
+ +-+------+--------+---------------+
962
+ |R| Stream Identifier |
963
+ | | (31) |
964
+ +=+===============================+
965
+ | Security Payload (*) ...
966
+ +---------------------------------+
967
+
968
+ The SECURITY frame payload contains opaque data intended for the registered
969
+ transport framing endpoint extension.
970
+
971
+ The SECURITY frame does not define flags.
972
+
973
+ Payload Size Limits and Chunking
974
+
975
+ The current implementation of the SECURITY frame has a HARD limit of 16,384
976
+ bytes (16 KB) for its payload.
977
+
978
+ This strict 16 KB limit is enforced because 16,384 bytes is the minimum
979
+ valid value for SETTINGS_MAX_FRAME_SIZE (the smallest maximum frame size an
980
+ HTTP/2 peer is allowed to advertise). Currently, the SECURITY frame does not
981
+ support chunking. Therefore, if a peer attempts to send a SECURITY payload
982
+ larger than the receiver's advertised SETTINGS_MAX_FRAME_SIZE, the endpoint
983
+ MUST treat this as a CONNECTION ERROR of type FRAME_SIZE_ERROR. By enforcing
984
+ a hard 16 KB upper bound, we guarantee that the frame will safely fit within any
985
+ compliant peer's single-frame receive buffer without requiring payload chunking.
986
+
987
+ */
@@ -294,13 +294,14 @@ struct Http2FrameCountTracker {
294
294
  http2::Http2Status ValidateSettingsValues(
295
295
  std::vector<Http2SettingsFrame::Setting>& list);
296
296
 
297
+ // The checks in this function MUST be done before the frame payload is read.
297
298
  http2::Http2Status ValidateFrameHeader(
298
299
  const uint32_t max_frame_size_setting,
299
300
  const bool incoming_header_in_progress,
300
301
  const uint32_t incoming_header_stream_id,
301
302
  const Http2FrameHeader& current_frame_header, const uint32_t last_stream_id,
302
303
  const bool is_client, const bool is_first_settings_processed,
303
- Http2FrameCountTracker& tracker);
304
+ Http2FrameCountTracker& tracker, const uint32_t max_security_frame_size);
304
305
 
305
306
  ///////////////////////////////////////////////////////////////////////////////
306
307
  // RFC9113 Related Strings and Consts
@@ -424,6 +425,7 @@ inline constexpr uint32_t kHttp2InitialWindowSize = 65535u;
424
425
  } // namespace RFC9113
425
426
 
426
427
  namespace GrpcErrors {
428
+
427
429
  inline constexpr absl::string_view kTooManyMetadata =
428
430
  "gRPC Error : A gRPC server can send upto 1 initial metadata followed by "
429
431
  "upto 1 trailing metadata.";
@@ -441,6 +443,16 @@ inline constexpr absl::string_view kFailedToEnqueueStream =
441
443
  "gRPC Transport Error : Failed to enqueue stream to writable stream list";
442
444
  inline constexpr absl::string_view kStreamCreationFailed =
443
445
  "gRPC Transport Error : Stream creation failed";
446
+
447
+ inline constexpr uint32_t kDefaultMaxPendingInducedFrames = 10000u;
448
+
449
+ // Security frame related limits and errors
450
+ inline constexpr uint32_t kMaxSecurityFrameSize = 16u * 1024u;
451
+ inline constexpr int kMinMaxSecurityFrameSize = 0;
452
+ inline constexpr absl::string_view kSecurityFrameTooLarge =
453
+ "gRPC Transport Error : Security frame is larger than the maximum allowed "
454
+ "size : ";
455
+
444
456
  } // namespace GrpcErrors
445
457
 
446
458
  } // namespace grpc_core
@@ -48,7 +48,6 @@ 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;
52
51
 
53
52
  return absl::OkStatus();
54
53
  }
@@ -124,24 +123,6 @@ grpc_core::Poll<grpc_error_handle> grpc_deframe_unprocessed_incoming_frames(
124
123
  (static_cast<uint32_t>(header[3]) << 8) |
125
124
  static_cast<uint32_t>(header[4]);
126
125
 
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
-
145
126
  if (slices->length < length + GRPC_HEADER_SIZE_IN_BYTES) {
146
127
  if (min_progress_size != nullptr) {
147
128
  *min_progress_size = length + GRPC_HEADER_SIZE_IN_BYTES - slices->length;
@@ -157,7 +138,6 @@ grpc_core::Poll<grpc_error_handle> grpc_deframe_unprocessed_incoming_frames(
157
138
  grpc_slice_buffer_move_first_into_buffer(slices, GRPC_HEADER_SIZE_IN_BYTES,
158
139
  header);
159
140
  grpc_slice_buffer_move_first(slices, length, stream_out->c_slice_buffer());
160
- s->num_frames = 0;
161
141
  }
162
142
 
163
143
  return absl::OkStatus();
@@ -168,20 +148,8 @@ grpc_error_handle grpc_chttp2_data_parser_parse(void* /*parser*/,
168
148
  grpc_chttp2_stream* s,
169
149
  const grpc_slice& slice,
170
150
  int is_last) {
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
- }
151
+ grpc_core::CSliceRef(slice);
152
+ grpc_slice_buffer_add(&s->frame_storage, slice);
185
153
  grpc_chttp2_maybe_complete_recv_message(t, s);
186
154
 
187
155
  if (is_last) {
@@ -31,15 +31,11 @@
31
31
  #include "absl/strings/string_view.h"
32
32
 
33
33
  void grpc_chttp2_goaway_parser_init(grpc_chttp2_goaway_parser* p) {
34
- if (!grpc_core::IsPh2Perf01Enabled()) {
35
- p->debug_data = nullptr;
36
- }
34
+ p->debug_data = nullptr;
37
35
  }
38
36
 
39
37
  void grpc_chttp2_goaway_parser_destroy(grpc_chttp2_goaway_parser* p) {
40
- if (!grpc_core::IsPh2Perf01Enabled()) {
41
- gpr_free(p->debug_data);
42
- }
38
+ gpr_free(p->debug_data);
43
39
  }
44
40
 
45
41
  grpc_error_handle grpc_chttp2_goaway_parser_begin_frame(
@@ -49,14 +45,10 @@ grpc_error_handle grpc_chttp2_goaway_parser_begin_frame(
49
45
  absl::StrFormat("goaway frame too short (%d bytes)", length));
50
46
  }
51
47
 
48
+ gpr_free(p->debug_data);
52
49
  p->debug_length = length - 8;
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
- }
50
+ p->debug_data = static_cast<char*>(gpr_malloc(p->debug_length));
51
+ p->debug_pos = 0;
60
52
  p->state = GRPC_CHTTP2_GOAWAY_LSI0;
61
53
  return absl::OkStatus();
62
54
  }
@@ -138,48 +130,24 @@ grpc_error_handle grpc_chttp2_goaway_parser_parse(void* parser,
138
130
  ++cur;
139
131
  [[fallthrough]];
140
132
  case GRPC_CHTTP2_GOAWAY_DEBUG:
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
- }
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;
183
151
  }
184
152
  return absl::OkStatus();
185
153
  }
@@ -44,7 +44,6 @@ 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;
48
47
  uint32_t debug_length;
49
48
  uint32_t debug_pos;
50
49
  };
@@ -132,10 +132,8 @@ grpc_error_handle grpc_chttp2_rst_stream_parser_parse(void* parser,
132
132
  if (reason != static_cast<uint32_t>(Http2ErrorCode::kNoError) ||
133
133
  s->trailing_metadata_buffer.empty()) {
134
134
  error = grpc_error_set_int(
135
- grpc_error_set_str(
136
- GRPC_ERROR_CREATE("RST_STREAM"),
137
- grpc_core::StatusStrProperty::kGrpcMessage,
138
- absl::StrCat("Received RST_STREAM with error code ", reason)),
135
+ GRPC_ERROR_CREATE(absl::StrCat(
136
+ "RST_STREAM (Received RST_STREAM with error code ", reason, ")")),
139
137
  grpc_core::StatusIntProperty::kHttp2Error,
140
138
  static_cast<intptr_t>(reason));
141
139
  }
@@ -27,6 +27,7 @@
27
27
  #include "src/core/lib/transport/transport_framing_endpoint_extension.h"
28
28
  #include "src/core/util/grpc_check.h"
29
29
  #include "absl/status/status.h"
30
+ #include "absl/strings/str_cat.h"
30
31
 
31
32
  absl::Status grpc_chttp2_security_frame_parser_parse(void* parser,
32
33
  grpc_chttp2_transport* t,
@@ -52,7 +53,15 @@ absl::Status grpc_chttp2_security_frame_parser_parse(void* parser,
52
53
  }
53
54
 
54
55
  absl::Status grpc_chttp2_security_frame_parser_begin_frame(
55
- grpc_chttp2_security_frame_parser* parser) {
56
+ grpc_chttp2_security_frame_parser* parser, const uint32_t length,
57
+ const uint32_t max_frame_size) {
58
+ if (GPR_UNLIKELY(length > max_frame_size &&
59
+ grpc_core::IsCustomFrameCheckEnabled())) {
60
+ return GRPC_ERROR_CREATE(absl::StrCat(
61
+ "gRPC Transport Error : Security frame is larger than the maximum "
62
+ "allowed size : ",
63
+ max_frame_size, ", Received size : ", length));
64
+ }
56
65
  parser->payload.Clear();
57
66
  return absl::OkStatus();
58
67
  }
@@ -35,7 +35,8 @@ void grpc_chttp2_security_frame_create(grpc_slice_buffer* payload,
35
35
  grpc_slice_buffer* frame);
36
36
 
37
37
  absl::Status grpc_chttp2_security_frame_parser_begin_frame(
38
- grpc_chttp2_security_frame_parser* parser);
38
+ grpc_chttp2_security_frame_parser* parser, uint32_t length,
39
+ uint32_t max_frame_size);
39
40
 
40
41
  grpc_error_handle grpc_chttp2_security_frame_parser_parse(
41
42
  void* parser, grpc_chttp2_transport* t, grpc_chttp2_stream* s,
@@ -32,6 +32,7 @@ GoawayManager::GoawayManager(std::unique_ptr<GoawayInterface> goaway_interface)
32
32
  std::optional<Http2Frame> GoawayManager::MaybeGetGoawayFrame() {
33
33
  switch (context_->goaway_state) {
34
34
  case GoawayState::kIdle:
35
+ case GoawayState::kInitialGracefulGoawaySent:
35
36
  case GoawayState::kDone:
36
37
  break;
37
38
  case GoawayState::kInitialGracefulGoawayScheduled: {
@@ -85,9 +86,16 @@ void GoawayManager::Context::SentGoawayTransition() {
85
86
  << GoawayStateToString(goaway_state);
86
87
  switch (goaway_state) {
87
88
  case GoawayState::kIdle:
88
- case GoawayState::kInitialGracefulGoawayScheduled:
89
+ case GoawayState::kInitialGracefulGoawaySent:
89
90
  case GoawayState::kDone:
90
91
  break;
92
+ case GoawayState::kInitialGracefulGoawayScheduled: {
93
+ GRPC_HTTP2_GOAWAY_LOG
94
+ << "Transitioning to kInitialGracefulGoawaySent from "
95
+ << GoawayStateToString(goaway_state);
96
+ goaway_state = GoawayState::kInitialGracefulGoawaySent;
97
+ break;
98
+ }
91
99
  case GoawayState::kFinalGracefulGoawayScheduled:
92
100
  case GoawayState::kImmediateGoawayRequested: {
93
101
  GRPC_HTTP2_GOAWAY_LOG << "Transitioning to kDone from "
@@ -109,6 +117,8 @@ std::string GoawayManager::Context::GoawayStateToString(
109
117
  return "kIdle";
110
118
  case GoawayState::kInitialGracefulGoawayScheduled:
111
119
  return "kInitialGracefulGoawayScheduled";
120
+ case GoawayState::kInitialGracefulGoawaySent:
121
+ return "kInitialGracefulGoawaySent";
112
122
  case GoawayState::kFinalGracefulGoawayScheduled:
113
123
  return "kFinalGracefulGoawayScheduled";
114
124
  case GoawayState::kImmediateGoawayRequested:
@@ -64,6 +64,8 @@ enum class GoawayState : uint8_t {
64
64
  // Initial graceful GOAWAY is scheduled to be sent in the next transport write
65
65
  // cycle.
66
66
  kInitialGracefulGoawayScheduled,
67
+ // Initial graceful GOAWAY has been written on the wire.
68
+ kInitialGracefulGoawaySent,
67
69
  // Final graceful GOAWAY is scheduled to be sent in the next transport write
68
70
  // cycle. Sending this GOAWAY frame completes the graceful GOAWAY process and
69
71
  // transitions the state to kDone.
@@ -161,6 +163,7 @@ class GoawayManager {
161
163
  absl::Status TriggerWriteCycle();
162
164
 
163
165
  GoawayState goaway_state = GoawayState::kIdle;
166
+ bool was_immediate = false;
164
167
  std::unique_ptr<GoawayInterface> goaway_interface;
165
168
  // TODO(akshitpatel) : [PH2][P4] : There is scope to make this
166
169
  // IntractivityWaker.
@@ -222,6 +225,7 @@ class GoawayManager {
222
225
  << " -> "
223
226
  "kImmediateGoawayRequested.";
224
227
 
228
+ ctx->was_immediate = true;
225
229
  ctx->goaway_state = GoawayState::kImmediateGoawayRequested;
226
230
  ctx->SetGoawayArgs(
227
231
  /*error_code=*/static_cast<uint32_t>(error_code),
@@ -275,6 +279,7 @@ class GoawayManager {
275
279
  << " -> "
276
280
  "kInitialGracefulGoawayScheduled.";
277
281
  GRPC_DCHECK(error_code == Http2ErrorCode::kNoError);
282
+ ctx->was_immediate = false;
278
283
  ctx->goaway_state = GoawayState::kInitialGracefulGoawayScheduled;
279
284
  ctx->SetGoawayArgs(
280
285
  /*error_code=*/static_cast<uint32_t>(Http2ErrorCode::kNoError),
@@ -290,7 +295,7 @@ class GoawayManager {
290
295
  << "Ping resolved. Current state: "
291
296
  << ctx->GoawayStateToString(ctx->goaway_state);
292
297
  if (ctx->goaway_state ==
293
- GoawayState::kInitialGracefulGoawayScheduled) {
298
+ GoawayState::kInitialGracefulGoawaySent) {
294
299
  GRPC_HTTP2_GOAWAY_LOG
295
300
  << " [Graceful GOAWAY] state change "
296
301
  << ctx->GoawayStateToString(ctx->goaway_state)
@@ -349,6 +354,17 @@ class GoawayManager {
349
354
  return context_->goaway_state == GoawayState::kImmediateGoawayRequested;
350
355
  }
351
356
 
357
+ bool IsFinalGracefulGoawayScheduledOrSent() const {
358
+ return (context_->goaway_state ==
359
+ GoawayState::kFinalGracefulGoawayScheduled) ||
360
+ IsFinalGracefulGoawaySent();
361
+ }
362
+
363
+ bool IsFinalGracefulGoawaySent() const {
364
+ return context_->goaway_state == GoawayState::kDone &&
365
+ !context_->was_immediate;
366
+ }
367
+
352
368
  // Called from the transport write cycle to notify the GOAWAY manager that a
353
369
  // GOAWAY frame may have been sent. If a GOAWAY frame is sent in current
354
370
  // write cycle, this function handles the needed state transition.
@@ -996,6 +996,15 @@ class HPackParser::Parser {
996
996
  }
997
997
  }
998
998
  auto value_slice = value.value.Take();
999
+ if (IsOptimization05Enabled() && !state_.is_binary_header &&
1000
+ state_.field_error.ok()) {
1001
+ auto r =
1002
+ ValidateNonBinaryHeaderValueIsLegal(value_slice.as_string_view());
1003
+ if (r != ValidateMetadataResult::kOk) {
1004
+ input_->SetErrorAndContinueParsing(
1005
+ HpackParseResult::InvalidMetadataError(r, key_string));
1006
+ }
1007
+ }
999
1008
  const auto transport_size =
1000
1009
  key_string.size() + value.wire_size + hpack_constants::kEntryOverhead;
1001
1010
  if (state_.mitigation_engine != nullptr) {