grpc 1.82.0 → 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 (153) 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/rbac/rbac_service_config_parser.cc +2 -1
  31. data/src/core/ext/transport/chttp2/server/chttp2_server.cc +19 -13
  32. data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +11 -9
  33. data/src/core/ext/transport/chttp2/transport/flow_control.cc +2 -2
  34. data/src/core/ext/transport/chttp2/transport/flow_control.h +3 -2
  35. data/src/core/ext/transport/chttp2/transport/frame.cc +58 -1
  36. data/src/core/ext/transport/chttp2/transport/frame.h +13 -1
  37. data/src/core/ext/transport/chttp2/transport/frame_rst_stream.cc +2 -4
  38. data/src/core/ext/transport/chttp2/transport/frame_security.cc +10 -1
  39. data/src/core/ext/transport/chttp2/transport/frame_security.h +2 -1
  40. data/src/core/ext/transport/chttp2/transport/goaway.cc +11 -1
  41. data/src/core/ext/transport/chttp2/transport/goaway.h +17 -1
  42. data/src/core/ext/transport/chttp2/transport/hpack_parser.cc +9 -0
  43. data/src/core/ext/transport/chttp2/transport/http2_client_transport.cc +117 -276
  44. data/src/core/ext/transport/chttp2/transport/http2_client_transport.h +44 -17
  45. data/src/core/ext/transport/chttp2/transport/http2_server_transport.cc +382 -496
  46. data/src/core/ext/transport/chttp2/transport/http2_server_transport.h +75 -77
  47. data/src/core/ext/transport/chttp2/transport/http2_settings.cc +1 -1
  48. data/src/core/ext/transport/chttp2/transport/http2_settings.h +30 -11
  49. data/src/core/ext/transport/chttp2/transport/http2_settings_promises.h +24 -9
  50. data/src/core/ext/transport/chttp2/transport/http2_transport.cc +26 -0
  51. data/src/core/ext/transport/chttp2/transport/http2_transport.h +2 -0
  52. data/src/core/ext/transport/chttp2/transport/internal.h +4 -0
  53. data/src/core/ext/transport/chttp2/transport/parsing.cc +3 -2
  54. data/src/core/ext/transport/chttp2/transport/ping_promise.cc +1 -1
  55. data/src/core/ext/transport/chttp2/transport/ping_rate_policy.cc +4 -10
  56. data/src/core/ext/transport/chttp2/transport/read_context.h +62 -20
  57. data/src/core/ext/transport/chttp2/transport/security_frame.h +1 -0
  58. data/src/core/ext/transport/chttp2/transport/stream.h +271 -120
  59. data/src/core/ext/transport/chttp2/transport/stream_data_queue.h +77 -61
  60. data/src/core/handshaker/security/secure_endpoint.cc +0 -13
  61. data/src/core/lib/channel/promise_based_filter.cc +77 -3
  62. data/src/core/lib/channel/promise_based_filter.h +238 -184
  63. data/src/core/lib/event_engine/extensions/receive_coalescing_extension.h +0 -4
  64. data/src/core/lib/event_engine/extensions/tcp_trace.h +1 -1
  65. data/src/core/lib/event_engine/posix_engine/posix_engine.cc +2 -12
  66. data/src/core/lib/event_engine/shim.cc +2 -16
  67. data/src/core/lib/event_engine/shim.h +0 -4
  68. data/src/core/lib/experiments/experiments.cc +51 -102
  69. data/src/core/lib/experiments/experiments.h +37 -59
  70. data/src/core/lib/iomgr/error.cc +3 -73
  71. data/src/core/lib/iomgr/error.h +8 -6
  72. data/src/core/lib/iomgr/error_cfstream.cc +1 -2
  73. data/src/core/lib/iomgr/ev_epoll1_linux.cc +2 -6
  74. data/src/core/lib/iomgr/ev_poll_posix.cc +2 -6
  75. data/src/core/lib/iomgr/tcp_posix.cc +2 -6
  76. data/src/core/lib/security/authorization/audit_logging.cc +2 -2
  77. data/src/core/lib/security/authorization/audit_logging.h +3 -3
  78. data/src/core/lib/security/authorization/grpc_authorization_engine.cc +11 -13
  79. data/src/core/lib/security/authorization/grpc_authorization_engine.h +1 -1
  80. data/src/core/lib/security/authorization/matchers.cc +20 -20
  81. data/src/core/lib/security/authorization/matchers.h +15 -16
  82. data/src/core/lib/security/authorization/rbac_policy.h +1 -1
  83. data/src/core/lib/security/authorization/stdout_logger.cc +3 -3
  84. data/src/core/lib/security/authorization/stdout_logger.h +6 -5
  85. data/src/core/lib/surface/call.cc +0 -8
  86. data/src/core/lib/surface/call.h +2 -0
  87. data/src/core/lib/surface/channel.cc +21 -2
  88. data/src/core/lib/surface/channel.h +14 -6
  89. data/src/core/lib/surface/filter_stack_call.cc +10 -29
  90. data/src/core/lib/surface/legacy_channel.cc +7 -7
  91. data/src/core/lib/surface/legacy_channel.h +3 -1
  92. data/src/core/lib/surface/version.cc +2 -2
  93. data/src/core/lib/transport/bdp_estimator.cc +13 -13
  94. data/src/core/lib/transport/bdp_estimator.h +9 -5
  95. data/src/core/lib/transport/error_utils.cc +26 -138
  96. data/src/core/lib/transport/promise_endpoint.h +2 -4
  97. data/src/core/load_balancing/grpclb/grpclb.cc +2 -1
  98. data/src/core/load_balancing/pick_first/pick_first.cc +33 -2
  99. data/src/core/load_balancing/pick_first/pick_first.h +6 -0
  100. data/src/core/load_balancing/ring_hash/ring_hash.cc +3 -10
  101. data/src/core/load_balancing/rls/rls.cc +2 -1
  102. data/src/core/load_balancing/weighted_round_robin/weighted_round_robin.cc +2 -7
  103. data/src/core/load_balancing/xds/cds.cc +80 -56
  104. data/src/core/load_balancing/xds/cds.h +21 -0
  105. data/src/core/mitigation_engine/mitigation.h +53 -0
  106. data/src/core/mitigation_engine/mitigation_provider.h +62 -0
  107. data/src/core/resolver/dns/dns_resolver_plugin.cc +1 -6
  108. data/src/core/resolver/xds/xds_resolver.cc +14 -11
  109. data/src/core/server/server.h +1 -4
  110. data/src/core/server/server_config_selector.h +5 -4
  111. data/src/core/server/server_config_selector_filter.cc +67 -80
  112. data/src/core/server/xds_server_config_fetcher.cc +681 -692
  113. data/src/core/server/xds_server_config_fetcher_legacy.cc +15 -12
  114. data/src/core/telemetry/call_tracer.cc +49 -2
  115. data/src/core/telemetry/call_tracer.h +1 -0
  116. data/src/core/telemetry/tcp_tracer.h +38 -0
  117. data/src/core/tsi/alts/handshaker/alts_handshaker_client.cc +1 -1
  118. data/src/core/tsi/ssl_telemetry_utils.cc +343 -0
  119. data/src/core/tsi/ssl_telemetry_utils.h +74 -0
  120. data/src/core/tsi/ssl_transport_security.cc +577 -301
  121. data/src/core/tsi/ssl_transport_security.h +22 -6
  122. data/src/core/tsi/ssl_transport_security_utils.cc +2 -0
  123. data/src/core/tsi/transport_security.h +7 -0
  124. data/src/core/util/http_client/httpcli.cc +1 -4
  125. data/src/core/util/http_client/httpcli_security_connector.cc +2 -1
  126. data/src/core/util/status_helper.cc +71 -192
  127. data/src/core/util/status_helper.h +16 -21
  128. data/src/core/xds/grpc/file_watcher_certificate_provider_factory.cc +2 -11
  129. data/src/core/xds/grpc/xds_bootstrap_grpc.cc +2 -7
  130. data/src/core/xds/grpc/xds_cluster_parser.cc +5 -16
  131. data/src/core/xds/grpc/xds_common_types.cc +94 -38
  132. data/src/core/xds/grpc/xds_common_types.h +33 -18
  133. data/src/core/xds/grpc/xds_common_types_parser.cc +168 -100
  134. data/src/core/xds/grpc/xds_common_types_parser.h +18 -1
  135. data/src/core/xds/grpc/xds_endpoint_parser.cc +6 -17
  136. data/src/core/xds/grpc/xds_http_filter_registry.cc +2 -10
  137. data/src/core/xds/grpc/xds_http_rbac_filter.cc +3 -12
  138. data/src/core/xds/grpc/xds_metadata_parser.cc +0 -2
  139. data/src/core/xds/grpc/xds_route_config_parser.cc +7 -11
  140. data/src/core/xds/grpc/xds_routing.cc +113 -82
  141. data/src/core/xds/grpc/xds_routing.h +70 -20
  142. data/src/core/xds/grpc/xds_server_grpc.cc +22 -13
  143. data/src/core/xds/grpc/xds_server_grpc.h +16 -2
  144. data/src/core/xds/grpc/xds_server_grpc_interface.h +10 -0
  145. data/src/core/xds/grpc/xds_transport_grpc.cc +123 -18
  146. data/src/core/xds/grpc/xds_transport_grpc.h +28 -4
  147. data/src/core/xds/xds_client/lrs_client.cc +3 -7
  148. data/src/core/xds/xds_client/xds_bootstrap.cc +4 -16
  149. data/src/core/xds/xds_client/xds_client.cc +2 -15
  150. data/src/core/xds/xds_client/xds_transport.h +3 -0
  151. data/src/ruby/lib/grpc/version.rb +1 -1
  152. data/src/ruby/pb/src/proto/grpc/testing/messages_pb.rb +1 -1
  153. metadata +9 -1
@@ -314,6 +314,9 @@ Http2Status Http2ClientTransport::ProcessIncomingFrame(Http2DataFrame&& frame) {
314
314
 
315
315
  template <typename T>
316
316
  Http2Status Http2ClientTransport::ProcessIncomingMetadata(T&& frame) {
317
+ GRPC_HTTP2_CLIENT_DLOG
318
+ << "Http2ClientTransport::ProcessIncomingMetadata { stream_id="
319
+ << frame.stream_id << ", end_headers=" << frame.end_headers << " }";
317
320
  ping_manager_->ReceivedDataFrame();
318
321
 
319
322
  RefCountedPtr<Stream> stream = LookupStream(frame.stream_id);
@@ -366,9 +369,8 @@ Http2Status Http2ClientTransport::ProcessIncomingFrame(
366
369
  Http2HeaderFrame&& frame) {
367
370
  // https://www.rfc-editor.org/rfc/rfc9113.html#name-headers
368
371
  GRPC_HTTP2_CLIENT_DLOG
369
- << "Http2ClientTransport::ProcessIncomingFrame(HeaderFrame) { stream_id="
370
- << frame.stream_id << ", end_headers=" << frame.end_headers
371
- << ", end_stream=" << frame.end_stream << " }";
372
+ << "Http2ClientTransport::ProcessIncomingFrame(HeaderFrame) end_stream="
373
+ << frame.end_stream;
372
374
  return ProcessIncomingMetadata(std::forward<Http2HeaderFrame>(frame));
373
375
  }
374
376
 
@@ -380,15 +382,13 @@ Http2Status Http2ClientTransport::ProcessIncomingFrame(
380
382
  "stream_id="
381
383
  << frame.stream_id << ", error_code=" << frame.error_code << " }";
382
384
 
385
+ read_context_.OnResetFrameReceived();
383
386
  Http2ErrorCode error_code = FrameErrorCodeToHttp2ErrorCode(frame.error_code);
384
387
  absl::Status status = absl::Status(ErrorCodeToAbslStatusCode(error_code),
385
388
  "Reset stream frame received.");
386
389
  RefCountedPtr<Stream> stream = LookupStream(frame.stream_id);
387
390
  if (stream != nullptr) {
388
- stream->MarkHalfClosedRemote();
389
- BeginCloseStream(std::move(stream),
390
- /*reset_stream_error_code=*/std::nullopt,
391
- CancelledServerMetadataFromStatus(status));
391
+ HandleStreamStateChange(*stream, stream->OnResetReceived(status));
392
392
  }
393
393
 
394
394
  // In case of stream error, we do not want the Read Loop to be broken. Hence
@@ -405,6 +405,7 @@ Http2Status Http2ClientTransport::ProcessIncomingFrame(
405
405
  << frame.ack << ", settings length=" << frame.settings.size() << "}";
406
406
 
407
407
  if (!frame.ack) {
408
+ read_context_.OnSettingsFrameReceived();
408
409
  Http2Status s = settings_->BufferPeerSettings(std::move(frame.settings));
409
410
  if (!s.IsOk()) {
410
411
  return s;
@@ -441,17 +442,9 @@ Http2Status Http2ClientTransport::ProcessIncomingFrame(Http2PingFrame&& frame) {
441
442
  if (frame.ack) {
442
443
  return ToHttpOkOrConnError(AckPing(frame.opaque));
443
444
  } else {
445
+ read_context_.OnPingFrameReceived();
444
446
  if (test_only_ack_pings_) {
445
- // TODO(akshitpatel) : [PH2][P2] : Have a counter to track number
446
- // of pending induced frames (Ping/Settings Ack). This is to
447
- // ensure that if write is taking a long time, we can stop reads
448
- // and prioritize writes. RFC9113: PING responses SHOULD be given
449
- // higher priority than any other frame.
450
447
  ping_manager_->AddPendingPingAck(frame.opaque);
451
- // TODO(akshitpatel) : [PH2][P2] : This is done assuming that the
452
- // other ProcessFrame promises may return stream or connection
453
- // failures. If this does not turn out to be true, consider
454
- // returning absl::Status here.
455
448
  return ToHttpOkOrConnError(TriggerWriteCycle());
456
449
  } else {
457
450
  GRPC_HTTP2_CLIENT_DLOG
@@ -487,17 +480,6 @@ Http2Status Http2ClientTransport::ProcessIncomingFrame(
487
480
  }
488
481
  SetMaxAllowedStreamId(last_stream_id);
489
482
 
490
- bool close_transport = false;
491
- {
492
- MutexLock lock(&transport_mutex_);
493
- if (CanCloseTransportLocked()) {
494
- close_transport = true;
495
- GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport::ProcessIncomingFrame("
496
- "GoawayFrame) "
497
- "stream_list_ is empty";
498
- }
499
- }
500
-
501
483
  StateWatcher::DisconnectInfo disconnect_info;
502
484
  disconnect_info.reason = Transport::StateWatcher::kGoaway;
503
485
  disconnect_info.http2_error_code =
@@ -527,21 +509,6 @@ Http2Status Http2ClientTransport::ProcessIncomingFrame(
527
509
  Duration::Milliseconds(throttled_keepalive_time);
528
510
  }
529
511
 
530
- if (close_transport) {
531
- // TODO(akshitpatel) : [PH2][P3] : Ideally the error here should be
532
- // kNoError. However, Http2Status does not support kNoError. We should
533
- // revisit this and update the error code.
534
- MaybeSpawnCloseTransport(Http2Status::Http2ConnectionError(
535
- FrameErrorCodeToHttp2ErrorCode((
536
- frame.error_code ==
537
- Http2ErrorCodeToFrameErrorCode(Http2ErrorCode::kNoError)
538
- ? Http2ErrorCodeToFrameErrorCode(Http2ErrorCode::kInternalError)
539
- : frame.error_code)),
540
- frame.debug_data.empty()
541
- ? std::string("GOAWAY received")
542
- : std::string(frame.debug_data.as_string_view())));
543
- }
544
-
545
512
  // lie: use transient failure from the transport to indicate goaway has been
546
513
  // received.
547
514
  ReportDisconnection(status, disconnect_info, "got_goaway");
@@ -587,9 +554,7 @@ Http2Status Http2ClientTransport::ProcessIncomingFrame(
587
554
  Http2ContinuationFrame&& frame) {
588
555
  // https://www.rfc-editor.org/rfc/rfc9113.html#name-continuation
589
556
  GRPC_HTTP2_CLIENT_DLOG
590
- << "Http2ClientTransport::ProcessIncomingFrame(ContinuationFrame) { "
591
- "stream_id="
592
- << frame.stream_id << ", end_headers=" << frame.end_headers << " }";
557
+ << "Http2ClientTransport::ProcessIncomingFrame(ContinuationFrame)";
593
558
  return ProcessIncomingMetadata(std::forward<Http2ContinuationFrame>(frame));
594
559
  }
595
560
 
@@ -633,11 +598,8 @@ Http2Status Http2ClientTransport::ProcessMetadata(
633
598
  if (read_result.IsOk()) {
634
599
  ServerMetadataHandle metadata = TakeValue(std::move(read_result));
635
600
  if (read_context_.HeaderHasEndStream()) {
636
- stream->MarkHalfClosedRemote();
637
- stream->SetTrailingMetadataReceived();
638
- BeginCloseStream(std::move(stream),
639
- /*reset_stream_error_code=*/std::nullopt,
640
- std::move(metadata));
601
+ HandleStreamStateChange(
602
+ *stream, stream->OnTrailingMetadataReceived(std::move(metadata)));
641
603
  } else {
642
604
  GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport::ProcessMetadata "
643
605
  "SpawnPushServerInitialMetadata";
@@ -677,7 +639,7 @@ auto Http2ClientTransport::ReadAndProcessOneFrame() {
677
639
  if (GPR_UNLIKELY(!status.IsOk())) {
678
640
  GRPC_DCHECK(status.GetType() ==
679
641
  Http2Status::Http2ErrorType::kConnectionError);
680
- return HandleError(/*stream_id=*/std::nullopt, std::move(status));
642
+ return HandleError(/*stream=*/nullptr, std::move(status));
681
643
  }
682
644
  read_context_.SetCurrentFrameHeader(header);
683
645
  return absl::OkStatus();
@@ -701,7 +663,8 @@ auto Http2ClientTransport::ReadAndProcessOneFrame() {
701
663
  TakeValue(std::move(payload)));
702
664
  if (GPR_UNLIKELY(!frame.IsOk())) {
703
665
  return HandleError(
704
- read_context_.GetCurrentFrameHeader().stream_id,
666
+ LookupStream(
667
+ read_context_.GetCurrentFrameHeader().stream_id),
705
668
  ValueOrHttp2Status<Http2Frame>::TakeStatus(
706
669
  std::move(frame)));
707
670
  }
@@ -709,7 +672,8 @@ auto Http2ClientTransport::ReadAndProcessOneFrame() {
709
672
  ProcessOneIncomingFrame(TakeValue(std::move(frame)));
710
673
  if (GPR_UNLIKELY(!status.IsOk())) {
711
674
  return HandleError(
712
- read_context_.GetCurrentFrameHeader().stream_id,
675
+ LookupStream(
676
+ read_context_.GetCurrentFrameHeader().stream_id),
713
677
  std::move(status));
714
678
  }
715
679
  return absl::OkStatus();
@@ -886,14 +850,13 @@ absl::Status Http2ClientTransport::PrepareControlFrames() {
886
850
  // 5. Custom gRPC security frame
887
851
 
888
852
  goaway_manager_.MaybeGetSerializedGoawayFrame(frame_sender);
889
- bool should_spawn_security_frame_loop = false;
853
+ ApplySettingsResult apply_settings_result;
890
854
 
891
855
  const uint32_t old_initial_window_size =
892
856
  settings_->peer().initial_window_size();
893
- http2::Http2ErrorCode apply_status =
894
- settings_->MaybeReportAndApplyBufferedPeerSettings(
895
- event_engine_.get(), should_spawn_security_frame_loop);
896
-
857
+ const http2::Http2ErrorCode apply_status =
858
+ settings_->MaybeReportAndApplyBufferedPeerSettings(event_engine_.get(),
859
+ apply_settings_result);
897
860
  if (apply_status == http2::Http2ErrorCode::kNoError) {
898
861
  const uint32_t new_initial_window_size =
899
862
  settings_->peer().initial_window_size();
@@ -911,7 +874,7 @@ absl::Status Http2ClientTransport::PrepareControlFrames() {
911
874
  }
912
875
  }
913
876
 
914
- if (should_spawn_security_frame_loop) {
877
+ if (apply_settings_result.should_spawn_security_frame_loop) {
915
878
  const SecurityFrameHandler::EndpointExtensionState state =
916
879
  security_frame_handler_->Initialize(event_engine_);
917
880
  if (state.is_set) {
@@ -932,7 +895,7 @@ absl::Status Http2ClientTransport::PrepareControlFrames() {
932
895
  }
933
896
 
934
897
  if (apply_status != http2::Http2ErrorCode::kNoError) {
935
- return HandleError(/*stream_id=*/std::nullopt,
898
+ return HandleError(/*stream=*/nullptr,
936
899
  Http2Status::Http2ConnectionError(
937
900
  apply_status, "Failed to apply incoming settings"));
938
901
  }
@@ -1018,8 +981,7 @@ absl::Status Http2ClientTransport::DequeueStreamFrames(
1018
981
  "enqueue stream "
1019
982
  << stream->GetStreamId() << " with status: " << status;
1020
983
  // Close transport if we fail to enqueue stream.
1021
- return HandleError(/*stream_id=*/std::nullopt,
1022
- ToHttpOkOrConnError(status));
984
+ return HandleError(/*stream=*/nullptr, ToHttpOkOrConnError(status));
1023
985
  }
1024
986
  }
1025
987
 
@@ -1036,7 +998,7 @@ absl::Status Http2ClientTransport::DequeueStreamFrames(
1036
998
  << "Http2ClientTransport::DequeueStreamFrames InitialMetadataDequeued "
1037
999
  "stream_id = "
1038
1000
  << stream->GetStreamId();
1039
- stream->SentInitialMetadata();
1001
+ stream->OnInitialMetadataSent();
1040
1002
  // After this point, initial metadata is guaranteed to be sent out.
1041
1003
  AddToStreamList(stream);
1042
1004
  }
@@ -1045,21 +1007,14 @@ absl::Status Http2ClientTransport::DequeueStreamFrames(
1045
1007
  GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport::DequeueStreamFrames "
1046
1008
  "HalfCloseDequeued stream_id = "
1047
1009
  << stream->GetStreamId();
1048
- stream->MarkHalfClosedLocal();
1049
-
1050
- if (stream->IsTrailingMetadataReceived()) {
1051
- CloseStream(*stream, CloseStreamArgs{/*close_reads=*/true,
1052
- /*close_writes=*/true});
1053
- }
1010
+ HandleStreamStateChange(*stream, stream->OnHalfCloseSent());
1054
1011
  }
1055
1012
  if (result.IsResetStreamDequeued()) {
1056
1013
  GRPC_HTTP2_CLIENT_DLOG
1057
1014
  << "Http2ClientTransport::DequeueStreamFrames ResetStreamDequeued "
1058
1015
  "stream_id = "
1059
1016
  << stream->GetStreamId();
1060
- stream->MarkHalfClosedLocal();
1061
- CloseStream(*stream, CloseStreamArgs{/*close_reads=*/true,
1062
- /*close_writes=*/true});
1017
+ HandleStreamStateChange(*stream, stream->OnResetSent());
1063
1018
  }
1064
1019
 
1065
1020
  GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport::DequeueStreamFrames "
@@ -1130,9 +1085,7 @@ auto Http2ClientTransport::MultiplexerLoop() {
1130
1085
  "Failed to assign stream id and add to stream list for"
1131
1086
  " stream: "
1132
1087
  << stream.get() << " closing this stream.";
1133
- BeginCloseStream(std::move(stream),
1134
- /*reset_stream_error_code=*/std::nullopt,
1135
- CancelledServerMetadataFromStatus(status));
1088
+ HandleStreamStateChange(*stream, stream->ForceClose(status));
1136
1089
  continue;
1137
1090
  }
1138
1091
  }
@@ -1232,10 +1185,9 @@ auto Http2ClientTransport::WaitForSettingsTimeoutOnDone() {
1232
1185
  return [self = RefAsSubclass<Http2ClientTransport>()](absl::Status status) {
1233
1186
  if (!status.ok()) {
1234
1187
  GRPC_UNUSED absl::Status result = self->HandleError(
1235
- /*stream_id=*/std::nullopt,
1236
- Http2Status::Http2ConnectionError(
1237
- Http2ErrorCode::kProtocolError,
1238
- std::string(RFC9113::kSettingsTimeout)));
1188
+ /*stream=*/nullptr, Http2Status::Http2ConnectionError(
1189
+ Http2ErrorCode::kProtocolError,
1190
+ std::string(RFC9113::kSettingsTimeout)));
1239
1191
  }
1240
1192
  };
1241
1193
  }
@@ -1275,10 +1227,11 @@ Http2ClientTransport::Http2ClientTransport(
1275
1227
  event_engine_(std::move(event_engine)),
1276
1228
  endpoint_(std::move(endpoint)),
1277
1229
  settings_(MakeRefCounted<SettingsPromiseManager>(
1278
- std::move(on_receive_settings))),
1230
+ kIsClient, std::move(on_receive_settings))),
1279
1231
  next_stream_id_(/*Initial Stream ID*/ 1),
1280
1232
  should_reset_ping_clock_(false),
1281
- read_context_(MaxNewStreamsPerRead(channel_args), endpoint_, kIsClient),
1233
+ read_context_(MaxNewStreamsPerRead(channel_args), endpoint_, kIsClient,
1234
+ GetMaxSecurityFrameSize(channel_args)),
1282
1235
  transport_write_context_(kIsClient),
1283
1236
  ping_manager_(std::nullopt),
1284
1237
  keepalive_manager_(std::nullopt),
@@ -1287,7 +1240,7 @@ Http2ClientTransport::Http2ClientTransport(
1287
1240
  ->memory_quota()
1288
1241
  ->CreateMemoryOwner()),
1289
1242
  flow_control_(
1290
- "PH2_Client",
1243
+ /*peer_name=*/read_context_.peer_string().as_string_view(),
1291
1244
  channel_args.GetBool(GRPC_ARG_HTTP2_BDP_PROBE).value_or(true),
1292
1245
  &memory_owner_),
1293
1246
  security_frame_handler_(MakeRefCounted<SecurityFrameHandler>()),
@@ -1358,9 +1311,9 @@ void Http2ClientTransport::ReadChannelArgs(const ChannelArgs& channel_args,
1358
1311
  }
1359
1312
  }
1360
1313
 
1361
- absl::Status Http2ClientTransport::HandleError(
1362
- const std::optional<uint32_t> stream_id, Http2Status status,
1363
- DebugLocation whence) {
1314
+ absl::Status Http2ClientTransport::HandleError(RefCountedPtr<Stream> stream,
1315
+ Http2Status status,
1316
+ DebugLocation whence) {
1364
1317
  Http2Status::Http2ErrorType error_type = status.GetType();
1365
1318
  GRPC_DCHECK(error_type != Http2Status::Http2ErrorType::kOk);
1366
1319
 
@@ -1368,13 +1321,13 @@ absl::Status Http2ClientTransport::HandleError(
1368
1321
  GRPC_HTTP2_CLIENT_ERROR_DLOG
1369
1322
  << "Http2ClientTransport::HandleError Stream Error:"
1370
1323
  << status.DebugString();
1371
- GRPC_DCHECK(stream_id.has_value());
1324
+ GRPC_DCHECK(stream != nullptr);
1372
1325
  // Passing a cancelled server metadata handle to propagate the error
1373
1326
  // to the upper layers.
1374
1327
  BeginCloseStream(
1375
- LookupStream(stream_id.value()),
1328
+ std::move(stream),
1376
1329
  Http2ErrorCodeToFrameErrorCode(status.GetStreamErrorCode()),
1377
- CancelledServerMetadataFromStatus(status.GetAbslStreamError()), whence);
1330
+ status.GetAbslStreamError(), whence);
1378
1331
  return absl::OkStatus();
1379
1332
  } else if (error_type == Http2Status::Http2ErrorType::kConnectionError) {
1380
1333
  GRPC_HTTP2_CLIENT_ERROR_DLOG
@@ -1387,186 +1340,73 @@ absl::Status Http2ClientTransport::HandleError(
1387
1340
  GPR_UNREACHABLE_CODE(return absl::InternalError("Invalid error type"));
1388
1341
  }
1389
1342
 
1390
- // This function MUST be idempotent. This function MUST be called from the
1391
- // transport party.
1392
- void Http2ClientTransport::CloseStream(Stream& stream, CloseStreamArgs args,
1393
- DebugLocation whence) {
1394
- std::optional<Http2Status> close_transport_error;
1395
-
1396
- {
1397
- // TODO(akshitpatel) : [PH2][P3] : Measure the impact of holding mutex
1398
- // throughout this function.
1399
- MutexLock lock(&transport_mutex_);
1400
- GRPC_HTTP2_CLIENT_DLOG
1401
- << "Http2ClientTransport::CloseStream for stream id: "
1402
- << stream.GetStreamId() << " close_reads=" << args.close_reads
1403
- << " close_writes=" << args.close_writes
1404
- << " read_context_=" << read_context_.DebugString()
1405
- << " location=" << whence.file() << ":" << whence.line();
1406
-
1407
- if (args.close_writes) {
1408
- stream.SetWriteClosed();
1409
- }
1410
-
1411
- if (args.close_reads) {
1412
- GRPC_HTTP2_CLIENT_DLOG
1413
- << "Http2ClientTransport::CloseStream for stream id: "
1414
- << stream.GetStreamId() << " closing stream for reads.";
1415
- // If the stream is closed while reading HEADER/CONTINUATION frames, we
1416
- // should still parse the enqueued buffer to maintain HPACK state between
1417
- // peers.
1418
- if (read_context_.IsWaitingForContinuationFrame()) {
1419
- Http2Status result = read_context_.ParseAndDiscardHeaders(
1420
- SliceBuffer(), /*is_end_headers=*/false,
1421
- /*original_status=*/Http2Status::Ok(),
1422
- settings_->acked().max_header_list_size());
1423
- if (result.GetType() == Http2Status::Http2ErrorType::kConnectionError) {
1424
- GRPC_HTTP2_CLIENT_DLOG
1425
- << "Http2ClientTransport::CloseStream for stream id: "
1426
- << stream.GetStreamId() << " failed to partially process header: "
1427
- << result.DebugString();
1428
- close_transport_error.emplace(std::move(result));
1429
- }
1430
- }
1431
-
1432
- stream_list_.erase(stream.GetStreamId());
1433
- if (!close_transport_error.has_value() && CanCloseTransportLocked()) {
1434
- // TODO(akshitpatel) : [PH2][P3] : Is kInternalError the right error
1435
- // code to use here? IMO it should be kNoError.
1436
- close_transport_error.emplace(Http2Status::Http2ConnectionError(
1437
- Http2ErrorCode::kInternalError,
1438
- std::string(RFC9113::kLastStreamClosed)));
1343
+ void Http2ClientTransport::HandleStreamStateChange(Stream& stream,
1344
+ StreamStateChange change) {
1345
+ if (change.reads_became_closed) {
1346
+ // If a stream is closing for reads and was actively waiting for a
1347
+ // continuation frame, parse the buffered HEADER/CONTINUATION frames
1348
+ if (read_context_.IsWaitingForContinuationFrame() &&
1349
+ read_context_.GetStreamId() == stream.GetStreamId()) {
1350
+ Http2Status result = read_context_.ParseAndDiscardHeaders(
1351
+ SliceBuffer(), /*is_end_headers=*/false,
1352
+ /*original_status=*/Http2Status::Ok(),
1353
+ settings_->acked().max_header_list_size());
1354
+ if (GPR_UNLIKELY(result.GetType() ==
1355
+ Http2Status::Http2ErrorType::kConnectionError)) {
1356
+ GRPC_HTTP2_CLIENT_DLOG
1357
+ << "Http2ClientTransport::HandleStreamStateChange (DiscardHeaders) "
1358
+ "for "
1359
+ "stream id: "
1360
+ << stream.GetStreamId()
1361
+ << " failed to partially process header: " << result.DebugString();
1362
+ GRPC_UNUSED absl::Status unused =
1363
+ HandleError(/*stream=*/nullptr, std::move(result));
1364
+ return;
1439
1365
  }
1440
1366
  }
1441
1367
  }
1442
-
1443
- if (close_transport_error.has_value()) {
1444
- GRPC_UNUSED absl::Status status = HandleError(
1445
- /*stream_id=*/std::nullopt, std::move(*close_transport_error));
1368
+ if (change.stream_became_closed) {
1369
+ CleanupStream(stream);
1446
1370
  }
1447
1371
  }
1448
1372
 
1449
- // This function is idempotent and MUST be called from the transport party.
1450
- // All the scenarios that can lead to this function being called are:
1451
- // 1. Reading a RST stream frame: In this case, the stream is immediately
1452
- // closed for reads and writes and removed from the stream_list_.
1453
- // 2. Reading a Trailing Metadata frame: There are two possible scenarios:
1454
- // a. The stream is closed for writes: Close the stream for reads and writes
1455
- // and remove the stream from the stream_list_.
1456
- // b. The stream is NOT closed for writes: Stream is kept open for reads and
1457
- // writes. CallHandler OnDone will trigger sending a half close frame. If
1458
- // before the multiplexer loop triggers sending a half close a RST stream
1459
- // is read, the stream is closed for reads and writes immediately and the
1460
- // half close is discarded. If no RST stream is read, the stream is closed
1461
- // for reads and writes upon sending the half close frame from the
1462
- // multiplexer loop.
1463
- // 3. Hitting error condition in the transport: In this case, RST stream is
1464
- // enqueued and the stream is closed for reads immediately. This implies we
1465
- // reduce the number of active streams inline. When multiplexer loop
1466
- // processes the RST stream frame, the stream ref will dropped. The other
1467
- // stream ref will be dropped when CallHandler's OnDone is executed causing
1468
- // the stream to be destroyed. CallHandlers OnDone also tries to enqueue a
1469
- // RST stream frame. This is a no-op at this point.
1470
- // 4. Application abort: In this case, CallHandler OnDone will enqueue RST
1471
- // stream frame to the stream data queue. The multiplexer loop will send the
1472
- // reset stream frame and close the stream from reads and writes.
1473
- // 5. Transport close: This takes up the same path as case 3.
1474
- // In all the above cases, trailing metadata is pushed to the call spine.
1475
- // Note: The stream ref is held in atmost 3 places:
1476
- // 1. stream_list_ : This is released when the stream is closed for reads.
1477
- // 2. CallHandler OnDone : This is released when Trailing Metadata is pushed to
1478
- // the call spine.
1479
- // 3. List of writable streams : This is released after the final frame is
1480
- // dequeued from the StreamDataQueue.
1373
+ void Http2ClientTransport::CleanupStream(Stream& stream) {
1374
+ MutexLock lock(&transport_mutex_);
1375
+ stream_list_.erase(stream.GetStreamId());
1376
+ }
1377
+
1481
1378
  void Http2ClientTransport::BeginCloseStream(
1482
- RefCountedPtr<Stream> stream,
1483
- std::optional<uint32_t> reset_stream_error_code,
1484
- ServerMetadataHandle&& metadata, DebugLocation whence) {
1379
+ RefCountedPtr<Stream> stream, uint32_t reset_stream_error_code,
1380
+ absl::Status trailing_metadata_status, DebugLocation whence) {
1381
+ GRPC_DCHECK(!trailing_metadata_status.ok());
1485
1382
  if (stream == nullptr) {
1486
1383
  GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport::BeginCloseStream stream "
1487
1384
  "is null reset_stream_error_code="
1488
- << (reset_stream_error_code.has_value()
1489
- ? absl::StrCat(*reset_stream_error_code)
1490
- : "nullopt")
1491
- << " metadata=" << metadata->DebugString();
1385
+ << reset_stream_error_code;
1492
1386
  return;
1493
1387
  }
1494
1388
 
1495
1389
  GRPC_HTTP2_CLIENT_DLOG
1496
1390
  << "Http2ClientTransport::BeginCloseStream for stream id: "
1497
- << stream->GetStreamId() << " error_code="
1498
- << (reset_stream_error_code.has_value()
1499
- ? absl::StrCat(*reset_stream_error_code)
1500
- : "nullopt")
1501
- << " ServerMetadata=" << metadata->DebugString()
1502
- << " location=" << whence.file() << ":" << whence.line();
1503
-
1504
- bool close_reads = false;
1505
- bool close_writes = false;
1506
- if (metadata->get(GrpcCallWasCancelled())) {
1507
- if (!reset_stream_error_code) {
1508
- // Callers taking this path:
1509
- // 1. Reading a RST stream frame (will not send any frame out).
1510
- // 2. Closing a stream before initial metadata is sent.
1511
- close_reads = true;
1512
- close_writes = true;
1513
- GRPC_HTTP2_CLIENT_DLOG
1514
- << "Http2ClientTransport::BeginCloseStream for stream id: "
1515
- << stream->GetStreamId() << " close_reads= " << close_reads
1516
- << " close_writes= " << close_writes;
1517
- } else {
1518
- // Callers taking this path:
1519
- // 1. Processing Error in transport (will send reset stream from here).
1520
- absl::StatusOr<StreamWritabilityUpdate> enqueue_result =
1521
- stream->EnqueueResetStream(reset_stream_error_code.value());
1522
- GRPC_HTTP2_CLIENT_DLOG << "Enqueued ResetStream with error code="
1523
- << reset_stream_error_code.value()
1524
- << " status=" << enqueue_result.status();
1525
- if (enqueue_result.ok()) {
1526
- GRPC_UNUSED absl::Status status =
1527
- MaybeAddStreamToWritableStreamList(stream, enqueue_result.value());
1528
- }
1529
- close_reads = true;
1530
- GRPC_HTTP2_CLIENT_DLOG
1531
- << "Http2ClientTransport::BeginCloseStream for stream id: "
1532
- << stream->GetStreamId() << " close_reads= " << close_reads
1533
- << " close_writes= " << close_writes;
1534
- }
1535
- } else {
1536
- // Callers taking this path:
1537
- // 1. Reading Trailing Metadata (MAY send half close from OnDone).
1538
- // If a half close frame has already been sent, we should close the stream
1539
- // for reads and writes.
1540
- if (stream->IsHalfClosedLocal() || stream->IsStreamClosed()) {
1541
- close_reads = true;
1542
- close_writes = true;
1543
- GRPC_HTTP2_CLIENT_DLOG
1544
- << "Http2ClientTransport::BeginCloseStream for stream id: "
1545
- << stream->GetStreamId() << " close_reads= " << close_reads
1546
- << " close_writes= " << close_writes;
1547
- }
1548
- }
1549
-
1550
- if (close_reads || close_writes) {
1551
- CloseStream(*stream, CloseStreamArgs{close_reads, close_writes}, whence);
1552
- }
1553
-
1554
- // If the call was cancelled, the stream MUST be closed for reads.
1555
- GRPC_DCHECK(metadata->get(GrpcCallWasCancelled()) ? close_reads : true);
1556
-
1557
- // This maybe called multiple times while closing a stream. In CallV3, the
1558
- // flow for pushing server trailing metadata is idempotent. However, there is
1559
- // a subtle difference. When we push server trailing metadata with a cancelled
1560
- // status PushServerTrailingMetadata is spawned inline on the Call party
1561
- // whereas for the non-cancelled status, PushServerTrailingMetadata is
1562
- // spawned in the server_to_client spawn serializer. Because of this, in
1563
- // case when the server pushes trailing metadata (non-cancelled) followed by a
1564
- // RST stream with cancelled status, it is possible that the cancelled
1565
- // trailing metadata (for RST stream) is processed before. This would result
1566
- // in losing the actual status/message pushed by the server.
1567
- // To address this, we push the server trailing metadata to the stream only
1568
- // if it is not pushed already.
1569
- stream->MaybePushServerTrailingMetadata(std::move(metadata));
1391
+ << stream->GetStreamId() << " error_code=" << reset_stream_error_code
1392
+ << " status=" << trailing_metadata_status << " location=" << whence.file()
1393
+ << ":" << whence.line();
1394
+
1395
+ // Enqueue RST_STREAM.
1396
+ absl::StatusOr<StreamWritabilityUpdate> enqueue_result =
1397
+ stream->EnqueueResetStream(reset_stream_error_code);
1398
+ GRPC_HTTP2_CLIENT_DLOG << "Enqueued ResetStream with error code="
1399
+ << reset_stream_error_code
1400
+ << " status=" << enqueue_result.status();
1401
+ if (enqueue_result.ok()) {
1402
+ GRPC_UNUSED absl::Status status =
1403
+ MaybeAddStreamToWritableStreamList(stream, enqueue_result.value());
1404
+ }
1405
+ // Close reads immediately. Writes will be closed by the write loop after
1406
+ // the RST_STREAM frame is written.
1407
+ HandleStreamStateChange(*stream,
1408
+ stream->OnInitiateReset(trailing_metadata_status));
1409
+ read_context_.OnResetFrameEnqueued(reset_stream_error_code);
1570
1410
  }
1571
1411
 
1572
1412
  void Http2ClientTransport::CloseTransport() {
@@ -1624,8 +1464,7 @@ void Http2ClientTransport::MaybeSpawnCloseTransport(Http2Status http2_status,
1624
1464
  self->BeginCloseStream(std::move(stream),
1625
1465
  Http2ErrorCodeToFrameErrorCode(
1626
1466
  http2_status.GetConnectionErrorCode()),
1627
- CancelledServerMetadataFromStatus(
1628
- http2_status.GetAbslConnectionError()));
1467
+ http2_status.GetAbslConnectionError());
1629
1468
  }
1630
1469
 
1631
1470
  // RFC9113 : A GOAWAY frame might not immediately precede closing of
@@ -1654,20 +1493,6 @@ void Http2ClientTransport::MaybeSpawnCloseTransport(Http2Status http2_status,
1654
1493
  });
1655
1494
  }
1656
1495
 
1657
- bool Http2ClientTransport::CanCloseTransportLocked() const {
1658
- // If there are no more streams and next stream id is greater than the
1659
- // max allowed stream id, then no more streams can be created and it is
1660
- // safe to close the transport.
1661
- GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport::CanCloseTransportLocked "
1662
- "GetActiveStreamCountLocked="
1663
- << GetActiveStreamCountLocked()
1664
- << " PeekNextStreamId=" << PeekNextStreamId()
1665
- << " GetMaxAllowedStreamId="
1666
- << GetMaxAllowedStreamId();
1667
- return GetActiveStreamCountLocked() == 0 &&
1668
- PeekNextStreamId() > GetMaxAllowedStreamId();
1669
- }
1670
-
1671
1496
  Http2ClientTransport::~Http2ClientTransport() {
1672
1497
  GRPC_HTTP2_CLIENT_DLOG << "Http2ClientTransport::~Http2ClientTransport Begin";
1673
1498
  GRPC_DCHECK(stream_list_.empty());
@@ -1795,7 +1620,7 @@ absl::Status Http2ClientTransport::MaybeAddStreamToWritableStreamList(
1795
1620
  writable_stream_list_.Enqueue(std::move(stream), result.priority);
1796
1621
  if (!status.ok()) {
1797
1622
  return HandleError(
1798
- /*stream_id=*/std::nullopt,
1623
+ /*stream=*/nullptr,
1799
1624
  Http2Status::Http2ConnectionError(
1800
1625
  Http2ErrorCode::kRefusedStream,
1801
1626
  std::string(GrpcErrors::kFailedToEnqueueStream)));
@@ -1965,15 +1790,31 @@ auto Http2ClientTransport::CallOutboundLoop(RefCountedPtr<Stream> stream) {
1965
1790
  [send_half_closed = std::move(send_half_closed)]() mutable {
1966
1791
  return std::move(send_half_closed)();
1967
1792
  },
1968
- [stream]() mutable {
1793
+ [this, stream]() mutable {
1969
1794
  return Map(
1970
- stream->GetCallHandler().WasCancelled(), [](bool cancelled) {
1795
+ stream->GetCallHandler().WasCancelled(),
1796
+ [this, stream](bool cancelled) mutable {
1971
1797
  GRPC_HTTP2_CLIENT_DLOG
1972
1798
  << "Http2ClientTransport::CallOutboundLoop End with "
1973
1799
  "cancelled="
1974
1800
  << cancelled;
1975
- return (cancelled) ? absl::CancelledError()
1976
- : absl::OkStatus();
1801
+ if (cancelled) {
1802
+ // Enqueue an RST_STREAM frame immediately upon call
1803
+ // cancellation rather than waiting for CallHandler::OnDone.
1804
+ absl::StatusOr<StreamWritabilityUpdate> enqueue_result =
1805
+ stream->EnqueueResetStream(
1806
+ static_cast<uint32_t>(Http2ErrorCode::kCancel));
1807
+ GRPC_HTTP2_CLIENT_DLOG
1808
+ << "Enqueued ResetStream with error code="
1809
+ << static_cast<uint32_t>(Http2ErrorCode::kCancel)
1810
+ << " status=" << enqueue_result.status();
1811
+ if (GPR_LIKELY(enqueue_result.ok())) {
1812
+ GRPC_UNUSED absl::Status status =
1813
+ MaybeAddStreamToWritableStreamList(
1814
+ std::move(stream), enqueue_result.value());
1815
+ }
1816
+ }
1817
+ return absl::OkStatus();
1977
1818
  });
1978
1819
  }));
1979
1820
  }
@@ -2073,7 +1914,7 @@ Http2ClientTransport::PingSystemInterfaceImpl::PingTimeout() {
2073
1914
  // kRefusedStream doesn't seem to fit this case. We should revisit this
2074
1915
  // and update the error code.
2075
1916
  return Immediate(transport_->HandleError(
2076
- std::nullopt,
1917
+ nullptr,
2077
1918
  Http2Status::Http2ConnectionError(Http2ErrorCode::kRefusedStream,
2078
1919
  GRPC_CHTTP2_PING_TIMEOUT_STR)));
2079
1920
  }
@@ -2105,7 +1946,7 @@ Http2ClientTransport::KeepAliveInterfaceImpl::OnKeepAliveTimeout() {
2105
1946
  // kRefusedStream doesn't seem to fit this case. We should revisit this
2106
1947
  // and update the error code.
2107
1948
  return Immediate(transport_->HandleError(
2108
- std::nullopt,
1949
+ nullptr,
2109
1950
  Http2Status::Http2ConnectionError(Http2ErrorCode::kRefusedStream,
2110
1951
  GRPC_CHTTP2_KEEPALIVE_TIMEOUT_STR)));
2111
1952
  }