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
@@ -363,29 +363,36 @@ Http2Status Http2ServerTransport::ProcessIncomingFrame(Http2DataFrame&& frame) {
363
363
  break;
364
364
  }
365
365
 
366
+ if (frame.end_stream) {
367
+ HandleStreamStateChange(*stream, stream->OnHalfCloseReceived());
368
+ }
366
369
  return Http2Status::Ok();
367
370
  }
368
371
 
369
372
  template <typename T>
370
373
  Http2Status Http2ServerTransport::ProcessIncomingMetadata(T&& frame) {
374
+ GRPC_HTTP2_SERVER_DLOG
375
+ << "Http2ServerTransport::ProcessIncomingMetadata { stream_id="
376
+ << frame.stream_id << ", end_headers=" << frame.end_headers << " }";
371
377
  ping_manager_->ReceivedDataFrame();
372
378
 
373
379
  bool is_new_stream = false;
374
380
  RefCountedPtr<Stream> stream = nullptr;
375
381
  // State update MUST happen before processing the frame.
376
- read_context_.UpdateState(frame, /*is_existing_stream=*/(stream != nullptr));
377
382
  if (!read_context_.IsWaitingForContinuationFrame()) {
378
383
  // This is a HEADERS frame.
379
384
  stream = LookupStream(frame.stream_id);
380
385
  is_new_stream = (stream == nullptr);
381
386
  // TODO(tjagtap) : [PH2][P2] : Implement initial stream id checks for new
382
387
  // streams.
388
+ last_incoming_stream_id_ = frame.stream_id;
383
389
  } else {
384
390
  // This is a CONTINUATION frame.
385
391
  GRPC_DCHECK(read_context_.GetStreamId() == frame.stream_id);
386
392
  GRPC_DCHECK(LookupStream(frame.stream_id) != nullptr);
387
393
  is_new_stream = true;
388
394
  }
395
+ read_context_.UpdateState(frame, /*is_existing_stream=*/!is_new_stream);
389
396
 
390
397
  if (is_new_stream) {
391
398
  // TODO(tjagtap) : [PH2][P3] : Implement this.
@@ -395,6 +402,13 @@ Http2Status Http2ServerTransport::ProcessIncomingMetadata(T&& frame) {
395
402
  // frame and streams that are reserved using PUSH_PROMISE. An endpoint that
396
403
  // receives an unexpected stream identifier MUST respond with a connection
397
404
  // error (Section 5.4.1) of type PROTOCOL_ERROR.
405
+
406
+ if (goaway_manager_.IsFinalGracefulGoawayScheduledOrSent()) {
407
+ return read_context_.ParseAndDiscardHeaders(
408
+ std::move(frame.payload), frame.end_headers, Http2Status::Ok(),
409
+ settings_->acked().max_header_list_size());
410
+ }
411
+
398
412
  Http2Status append_result =
399
413
  read_context_.header_assembler().AppendFrame(frame);
400
414
  if (!append_result.IsOk()) {
@@ -433,9 +447,8 @@ Http2Status Http2ServerTransport::ProcessIncomingFrame(
433
447
  Http2HeaderFrame&& frame) {
434
448
  // https://www.rfc-editor.org/rfc/rfc9113.html#name-headers
435
449
  GRPC_HTTP2_SERVER_DLOG
436
- << "Http2ServerTransport::ProcessIncomingFrame(HeaderFrame) { stream_id="
437
- << frame.stream_id << ", end_headers=" << frame.end_headers
438
- << ", end_stream=" << frame.end_stream << " }";
450
+ << "Http2ServerTransport::ProcessIncomingFrame(HeaderFrame) end_stream="
451
+ << frame.end_stream;
439
452
  return ProcessIncomingMetadata(std::forward<Http2HeaderFrame>(frame));
440
453
  }
441
454
 
@@ -443,21 +456,24 @@ Http2Status Http2ServerTransport::ProcessIncomingFrame(
443
456
  Http2RstStreamFrame&& frame) {
444
457
  // https://www.rfc-editor.org/rfc/rfc9113.html#name-rst_stream
445
458
  GRPC_HTTP2_SERVER_DLOG
446
- << "Http2ServerTransport::ProcessIncomingFrame(RstStreamFrame) { "
459
+ << "Http2ServerTransport::ProcessIncomingFrame(ResetStreamFrame) { "
447
460
  "stream_id="
448
461
  << frame.stream_id << ", error_code=" << frame.error_code << " }";
462
+ read_context_.OnResetFrameReceived();
449
463
 
450
- // Http2ErrorCode error_code =
451
- // FrameErrorCodeToHttp2ErrorCode(frame.error_code); absl::Status status =
452
- // absl::Status(ErrorCodeToAbslStatusCode(error_code),
453
- // "Reset stream frame received.");
454
- // RefCountedPtr<Stream> stream = LookupStream(frame.stream_id);
455
- // if (stream != nullptr) {
456
- // stream->MarkHalfClosedRemote();
457
- // BeginCloseStream(std::move(stream),
458
- // /*reset_stream_error_code=*/std::nullopt,
459
- // CancelledServerMetadataFromStatus(status));
460
- // }
464
+ Http2ErrorCode error_code = FrameErrorCodeToHttp2ErrorCode(frame.error_code);
465
+ absl::Status status = absl::Status(ErrorCodeToAbslStatusCode(error_code),
466
+ "Reset stream frame received.");
467
+ RefCountedPtr<Stream> stream = LookupStream(frame.stream_id);
468
+ if (stream != nullptr) {
469
+ if (status.ok()) {
470
+ status =
471
+ absl::UnavailableError("RST_STREAM frame received with no error.");
472
+ }
473
+
474
+ HandleStreamStateChange(*stream,
475
+ stream->OnResetReceived(std::move(status)));
476
+ }
461
477
 
462
478
  // In case of stream error, we do not want the Read Loop to be broken. Hence
463
479
  // returning an ok status.
@@ -473,6 +489,7 @@ Http2Status Http2ServerTransport::ProcessIncomingFrame(
473
489
  << frame.ack << ", settings length=" << frame.settings.size() << "}";
474
490
 
475
491
  if (!frame.ack) {
492
+ read_context_.OnSettingsFrameReceived();
476
493
  Http2Status s = settings_->BufferPeerSettings(std::move(frame.settings));
477
494
  if (!s.IsOk()) {
478
495
  return s;
@@ -509,17 +526,9 @@ Http2Status Http2ServerTransport::ProcessIncomingFrame(Http2PingFrame&& frame) {
509
526
  if (frame.ack) {
510
527
  return ToHttpOkOrConnError(AckPing(frame.opaque));
511
528
  } else {
529
+ read_context_.OnPingFrameReceived();
512
530
  if (test_only_ack_pings_) {
513
- // TODO(akshitpatel) : [PH2][P2] : Have a counter to track number
514
- // of pending induced frames (Ping/Settings Ack). This is to
515
- // ensure that if write is taking a long time, we can stop reads
516
- // and prioritize writes. RFC9113: PING responses SHOULD be given
517
- // higher priority than any other frame.
518
531
  ping_manager_->AddPendingPingAck(frame.opaque);
519
- // TODO(akshitpatel) : [PH2][P2] : This is done assuming that the
520
- // other ProcessFrame promises may return stream or connection
521
- // failures. If this does not turn out to be true, consider
522
- // returning absl::Status here.
523
532
  return ToHttpOkOrConnError(TriggerWriteCycle());
524
533
  } else {
525
534
  GRPC_HTTP2_SERVER_DLOG
@@ -664,9 +673,7 @@ Http2Status Http2ServerTransport::ProcessIncomingFrame(
664
673
  Http2ContinuationFrame&& frame) {
665
674
  // https://www.rfc-editor.org/rfc/rfc9113.html#name-continuation
666
675
  GRPC_HTTP2_SERVER_DLOG
667
- << "Http2ServerTransport::ProcessIncomingFrame(ContinuationFrame) { "
668
- "stream_id="
669
- << frame.stream_id << ", end_headers=" << frame.end_headers << " }";
676
+ << "Http2ServerTransport::ProcessIncomingFrame(ContinuationFrame)";
670
677
  return ProcessIncomingMetadata(std::forward<Http2ContinuationFrame>(frame));
671
678
  }
672
679
 
@@ -708,13 +715,28 @@ Http2Status Http2ServerTransport::ProcessMetadata() {
708
715
  settings_->acked().max_header_list_size());
709
716
  if (read_result.IsOk()) {
710
717
  ServerMetadataHandle metadata = TakeValue(std::move(read_result));
718
+ // TODO(tjagtap): [PH2][P0] : Might be worth differentiating between
719
+ // initial and trailing metadata based on the number of header frames
720
+ // received.
711
721
  if (read_context_.HeaderHasEndStream()) {
712
- // TODO(tjagtap) : [PH2][P1] : Implement receiving trailing metadata.
713
- // stream->MarkHalfClosedRemote();
714
- // stream->SetTrailingMetadataReceived();
715
- // BeginCloseStream(std::move(stream),
716
- // /*reset_stream_error_code=*/std::nullopt,
717
- // std::move(metadata));
722
+ // TODO(akshitpatel) [PH2][P1] : Implement receiving trailing metadata.
723
+ // Details:
724
+ // - Standard gRPC clients do not send trailers (only EOS).
725
+ // - If received (HEADERS with END_STREAM), mark stream as half-closed
726
+ // remote.
727
+ // - Upper layers discard client trailers, so we are fine with not
728
+ // propagating them.
729
+ //
730
+ // With these assumptions, the flow will look like this:
731
+ // - If the client sends trailing metadata with an OK status, we will
732
+ // mark the stream as half-closed remote and do nothing else.
733
+ // - If the client sends trailing metadata with a non-OK status, this
734
+ // case needs to be handled.
735
+ // TODO(akshitpatel) : [PH2][P0] : Verify this.
736
+ RefCountedPtr<Stream> stream =
737
+ LookupStream(read_context_.GetStreamId());
738
+ HandleStreamStateChange(
739
+ *stream, stream->OnTrailingMetadataReceived(std::move(metadata)));
718
740
  } else {
719
741
  GRPC_HTTP2_SERVER_DLOG << "Http2ServerTransport::ProcessMetadata "
720
742
  "SpawnPushServerInitialMetadata";
@@ -745,14 +767,15 @@ auto Http2ServerTransport::ReadAndProcessOneFrame() {
745
767
  /*max_frame_size_setting=*/settings_->acked().max_frame_size(),
746
768
  /*current_frame_header=*/header,
747
769
  // TODO(tjagtap) : [PH2][P0] : Fix
748
- /*last_stream_id=*//*GetLastStreamId()*/ 100,
770
+ /*last_stream_id=*//*GetLastStreamId()*/
771
+ std::numeric_limits<uint32_t>::max(),
749
772
  /*is_first_settings_processed=*/
750
773
  settings_->IsFirstPeerSettingsApplied());
751
774
 
752
775
  if (GPR_UNLIKELY(!status.IsOk())) {
753
776
  GRPC_DCHECK(status.GetType() ==
754
777
  Http2Status::Http2ErrorType::kConnectionError);
755
- return HandleError(/*stream_id=*/std::nullopt, std::move(status));
778
+ return HandleError(/*stream=*/nullptr, std::move(status));
756
779
  }
757
780
  read_context_.SetCurrentFrameHeader(header);
758
781
  return absl::OkStatus();
@@ -776,7 +799,8 @@ auto Http2ServerTransport::ReadAndProcessOneFrame() {
776
799
  TakeValue(std::move(payload)));
777
800
  if (GPR_UNLIKELY(!frame.IsOk())) {
778
801
  return HandleError(
779
- read_context_.GetCurrentFrameHeader().stream_id,
802
+ LookupStream(
803
+ read_context_.GetCurrentFrameHeader().stream_id),
780
804
  ValueOrHttp2Status<Http2Frame>::TakeStatus(
781
805
  std::move(frame)));
782
806
  }
@@ -784,7 +808,8 @@ auto Http2ServerTransport::ReadAndProcessOneFrame() {
784
808
  ProcessOneIncomingFrame(TakeValue(std::move(frame)));
785
809
  if (GPR_UNLIKELY(!status.IsOk())) {
786
810
  return HandleError(
787
- read_context_.GetCurrentFrameHeader().stream_id,
811
+ LookupStream(
812
+ read_context_.GetCurrentFrameHeader().stream_id),
788
813
  std::move(status));
789
814
  }
790
815
  return absl::OkStatus();
@@ -830,13 +855,13 @@ absl::Status Http2ServerTransport::PrepareControlFrames() {
830
855
  // 5. Custom gRPC security frame
831
856
 
832
857
  goaway_manager_.MaybeGetSerializedGoawayFrame(frame_sender);
833
- bool should_spawn_security_frame_loop = false;
858
+ ApplySettingsResult apply_settings_result;
834
859
 
835
860
  const uint32_t old_initial_window_size =
836
861
  settings_->peer().initial_window_size();
837
- http2::Http2ErrorCode apply_status =
838
- settings_->MaybeReportAndApplyBufferedPeerSettings(
839
- event_engine_.get(), should_spawn_security_frame_loop);
862
+ const http2::Http2ErrorCode apply_status =
863
+ settings_->MaybeReportAndApplyBufferedPeerSettings(event_engine_.get(),
864
+ apply_settings_result);
840
865
 
841
866
  if (apply_status == http2::Http2ErrorCode::kNoError) {
842
867
  const uint32_t new_initial_window_size =
@@ -855,7 +880,7 @@ absl::Status Http2ServerTransport::PrepareControlFrames() {
855
880
  }
856
881
  }
857
882
 
858
- if (should_spawn_security_frame_loop) {
883
+ if (apply_settings_result.should_spawn_security_frame_loop) {
859
884
  const SecurityFrameHandler::EndpointExtensionState state =
860
885
  security_frame_handler_->Initialize(event_engine_);
861
886
  if (state.is_set) {
@@ -869,14 +894,14 @@ absl::Status Http2ServerTransport::PrepareControlFrames() {
869
894
  EnforceLatestIncomingSettings();
870
895
  settings_->MaybeGetSettingsAndSettingsAckFrames(flow_control_,
871
896
  frame_sender);
872
- // MaybeSpawnDelayedPing(ping_manager_->MaybeGetSerializedPingFrames(
873
- // frame_sender, NextAllowedPingInterval()));
897
+ MaybeSpawnDelayedPing(ping_manager_->MaybeGetSerializedPingFrames(
898
+ frame_sender, NextAllowedPingInterval()));
874
899
  MaybeGetWindowUpdateFrames(frame_sender);
875
900
  security_frame_handler_->MaybeAppendSecurityFrame(frame_sender);
876
901
  }
877
902
 
878
903
  if (apply_status != http2::Http2ErrorCode::kNoError) {
879
- return HandleError(/*stream_id=*/std::nullopt,
904
+ return HandleError(/*stream=*/nullptr,
880
905
  Http2Status::Http2ConnectionError(
881
906
  apply_status, "Failed to apply incoming settings"));
882
907
  }
@@ -905,7 +930,7 @@ void Http2ServerTransport::NotifyFramesWriteDone() {
905
930
  // All notifications are expected to be synchronous.
906
931
  GRPC_HTTP2_SERVER_DLOG << "Http2ServerTransport::NotifyFramesWriteDone";
907
932
  read_context_.ResumeReadLoopIfPaused();
908
- // MaybeSpawnPingTimeout(ping_manager_->NotifyPingSent());
933
+ MaybeSpawnPingTimeout(ping_manager_->NotifyPingSent());
909
934
  goaway_manager_.NotifyGoawaySent();
910
935
  MaybeSpawnWaitForSettingsTimeout();
911
936
  }
@@ -946,8 +971,7 @@ absl::Status Http2ServerTransport::DequeueStreamFrames(
946
971
  "enqueue stream "
947
972
  << stream->GetStreamId() << " with status: " << status;
948
973
  // Close transport if we fail to enqueue stream.
949
- return HandleError(/*stream_id=*/std::nullopt,
950
- ToHttpOkOrConnError(status));
974
+ return HandleError(/*stream=*/nullptr, ToHttpOkOrConnError(status));
951
975
  }
952
976
  }
953
977
 
@@ -956,26 +980,24 @@ absl::Status Http2ServerTransport::DequeueStreamFrames(
956
980
  << "Http2ServerTransport::DequeueStreamFrames InitialMetadataDequeued "
957
981
  "stream_id = "
958
982
  << stream->GetStreamId();
959
- stream->SentInitialMetadata();
960
983
  }
961
984
 
962
985
  if (result.IsTrailingMetadataDequeued()) {
963
986
  GRPC_HTTP2_SERVER_DLOG << "Http2ServerTransport::DequeueStreamFrames "
964
987
  "TrailingMetadataDequeued stream_id = "
965
988
  << stream->GetStreamId();
966
- stream->SentTrailingMetadata();
967
-
968
- // TODO(akshitpatel) : [PH2][P1] : Close stream for reads and send
969
- // RST_STREAM.
989
+ // Stream is not marked closed here as TrailingMetadata is always followed
990
+ // by RST_STREAM and we close the stream when we dequeue the RST_STREAM.
970
991
  }
992
+
971
993
  if (result.IsResetStreamDequeued()) {
972
994
  GRPC_HTTP2_SERVER_DLOG
973
995
  << "Http2ServerTransport::DequeueStreamFrames ResetStreamDequeued "
974
996
  "stream_id = "
975
997
  << stream->GetStreamId();
976
- stream->MarkHalfClosedLocal();
977
- // CloseStream(*stream, CloseStreamArgs{/*close_reads=*/true,
978
- // /*close_writes=*/true});
998
+ // As Trailing metadata is already read from CallInitiator, no need to send
999
+ // a status to the application.
1000
+ HandleStreamStateChange(*stream, stream->OnResetSent());
979
1001
  }
980
1002
 
981
1003
  GRPC_HTTP2_SERVER_DLOG << "Http2ServerTransport::DequeueStreamFrames "
@@ -1078,9 +1100,6 @@ auto Http2ServerTransport::MultiplexerLoop() {
1078
1100
  }));
1079
1101
  }
1080
1102
 
1081
- //////////////////////////////////////////////////////////////////////////////
1082
- // Spawn Helpers and Promise Helpers
1083
-
1084
1103
  //////////////////////////////////////////////////////////////////////////////
1085
1104
  // Settings
1086
1105
 
@@ -1092,10 +1111,9 @@ auto Http2ServerTransport::WaitForSettingsTimeoutOnDone() {
1092
1111
  return [self = RefAsSubclass<Http2ServerTransport>()](absl::Status status) {
1093
1112
  if (!status.ok()) {
1094
1113
  GRPC_UNUSED absl::Status result = self->HandleError(
1095
- /*stream_id=*/std::nullopt,
1096
- Http2Status::Http2ConnectionError(
1097
- Http2ErrorCode::kProtocolError,
1098
- std::string(RFC9113::kSettingsTimeout)));
1114
+ /*stream=*/nullptr, Http2Status::Http2ConnectionError(
1115
+ Http2ErrorCode::kProtocolError,
1116
+ std::string(RFC9113::kSettingsTimeout)));
1099
1117
  }
1100
1118
  };
1101
1119
  }
@@ -1253,7 +1271,7 @@ absl::Status Http2ServerTransport::MaybeAddStreamToWritableStreamList(
1253
1271
  writable_stream_list_.Enqueue(std::move(stream), result.priority);
1254
1272
  if (!status.ok()) {
1255
1273
  return HandleError(
1256
- /*stream_id=*/std::nullopt,
1274
+ /*stream=*/nullptr,
1257
1275
  Http2Status::Http2ConnectionError(
1258
1276
  Http2ErrorCode::kRefusedStream,
1259
1277
  std::string(GrpcErrors::kFailedToEnqueueStream)));
@@ -1262,53 +1280,13 @@ absl::Status Http2ServerTransport::MaybeAddStreamToWritableStreamList(
1262
1280
  return absl::OkStatus();
1263
1281
  }
1264
1282
 
1265
- // absl::StatusOr<uint32_t> Http2ServerTransport::NextStreamId() {
1266
- // if (next_stream_id_ > GetMaxAllowedStreamId()) {
1267
- // // TODO(tjagtap) : [PH2][P3] : Handle case if transport runs out of
1268
- // stream
1269
- // // ids
1270
- // // RFC9113 : Stream identifiers cannot be reused. Long-lived connections
1271
- // // can result in an endpoint exhausting the available range of stream
1272
- // // identifiers. A client that is unable to establish a new stream
1273
- // // identifier can establish a new connection for new streams. A server
1274
- // // that is unable to establish a new stream identifier can send a GOAWAY
1275
- // // frame so that the client is forced to open a new connection for new
1276
- // // streams.
1277
- // return absl::ResourceExhaustedError("No more stream ids available");
1278
- // }
1279
- // // TODO(akshitpatel) : [PH2][P3] : There is a channel arg to delay
1280
- // // starting new streams instead of failing them. This needs to be
1281
- // // implemented.
1282
- // {
1283
- // // TODO(tjagtap) : [PH2][P1] : For a server we will have to do
1284
- // // this for incoming streams only. If a server receives more
1285
- // // streams from a client than is allowed by the clients settings,
1286
- // // whether or not we should fail is debatable.
1287
- // MutexLock lock(&transport_mutex_);
1288
- // if (GetActiveStreamCountLocked() >=
1289
- // settings_->peer().max_concurrent_streams()) {
1290
- // return absl::ResourceExhaustedError("Reached max concurrent streams");
1291
- // }
1292
- // }
1293
-
1294
- // // RFC9113 : Streams initiated by a client MUST use odd-numbered stream
1295
- // // identifiers.
1296
- // uint32_t new_stream_id = std::exchange(next_stream_id_, next_stream_id_ +
1297
- // 2); if (GPR_UNLIKELY(next_stream_id_ > GetMaxAllowedStreamId())) {
1298
- // ReportDisconnection(
1299
- // absl::ResourceExhaustedError("Transport Stream IDs exhausted"),
1300
- // {}, // TODO(tjagtap) : [PH2][P2] : Report better disconnect info.
1301
- // "no_more_stream_ids");
1302
- // }
1303
- // return new_stream_id;
1304
- // }
1305
-
1306
1283
  //////////////////////////////////////////////////////////////////////////////
1307
1284
  // Stream Operations
1308
1285
  auto Http2ServerTransport::HandleMetadataAndMessages(
1309
1286
  RefCountedPtr<Stream> stream) {
1310
1287
  auto send_message = [this, stream](MessageHandle&& message) mutable {
1311
- return TrySeq(stream->EnqueueMessage(std::move(message)),
1288
+ return TrySeq(HandleStreamErrorOnFailure(
1289
+ stream->EnqueueMessage(std::move(message)), stream),
1312
1290
  [this, stream](const StreamWritabilityUpdate result) mutable {
1313
1291
  GRPC_HTTP2_SERVER_DLOG
1314
1292
  << "Http2ServerTransport::HandleMetadataAndMessages "
@@ -1324,7 +1302,11 @@ auto Http2ServerTransport::HandleMetadataAndMessages(
1324
1302
  stream->EnqueueInitialMetadata(
1325
1303
  std::forward<ServerMetadataHandle>(metadata));
1326
1304
  if (GPR_UNLIKELY(!enqueue_result.ok())) {
1327
- return enqueue_result.status();
1305
+ absl::Status status = enqueue_result.status();
1306
+ GRPC_UNUSED absl::Status unused = HandleError(
1307
+ stream, Http2Status::AbslStreamError(status.code(),
1308
+ std::string(status.message())));
1309
+ return status;
1328
1310
  }
1329
1311
  GRPC_HTTP2_SERVER_DLOG << "Http2ServerTransport::HandleMetadataAndMessages "
1330
1312
  "Enqueued Initial Metadata";
@@ -1333,14 +1315,14 @@ auto Http2ServerTransport::HandleMetadataAndMessages(
1333
1315
  };
1334
1316
 
1335
1317
  return TrySeq(
1336
- stream->GetCallInitiator().PullServerInitialMetadata(),
1337
- [send_initial_metadata = std::move(send_initial_metadata)](
1338
- std::optional<ServerMetadataHandle> initial_metadata) mutable {
1339
- if (initial_metadata.has_value()) {
1340
- return send_initial_metadata(std::move(initial_metadata).value());
1341
- }
1342
- return absl::OkStatus();
1343
- },
1318
+ Map(stream->GetCallInitiator().PullServerInitialMetadata(),
1319
+ [send_initial_metadata = std::move(send_initial_metadata)](
1320
+ std::optional<ServerMetadataHandle> initial_metadata) mutable {
1321
+ if (initial_metadata.has_value()) {
1322
+ return send_initial_metadata(std::move(initial_metadata).value());
1323
+ }
1324
+ return absl::OkStatus();
1325
+ }),
1344
1326
  ForEach(MessagesFrom(stream->GetCallInitiator()),
1345
1327
  std::move(send_message)));
1346
1328
  }
@@ -1354,6 +1336,10 @@ auto Http2ServerTransport::CallOutboundLoop(RefCountedPtr<Stream> stream) {
1354
1336
  absl::StatusOr<StreamWritabilityUpdate> enqueue_result =
1355
1337
  stream->EnqueueTrailingMetadata(std::move(metadata));
1356
1338
  if (GPR_UNLIKELY(!enqueue_result.ok())) {
1339
+ GRPC_HTTP2_SERVER_DLOG
1340
+ << "Http2ServerTransport::CallOutboundLoop Failed to enqueue "
1341
+ "trailing metadata: "
1342
+ << enqueue_result.status();
1357
1343
  return enqueue_result.status();
1358
1344
  }
1359
1345
  GRPC_HTTP2_SERVER_DLOG << "Http2ServerTransport::CallOutboundLoop "
@@ -1366,10 +1352,6 @@ auto Http2ServerTransport::CallOutboundLoop(RefCountedPtr<Stream> stream) {
1366
1352
  "Ph2CallOutboundLoop",
1367
1353
  Seq(Map(HandleMetadataAndMessages(stream),
1368
1354
  [stream = stream.get()](absl::Status&& status) {
1369
- if (GPR_UNLIKELY(!status.ok())) {
1370
- // TODO(akshitpatel) : [PH2][P1] : Call BeginCloseStream.
1371
- // BeginCloseStream(stream, error_code, cancelled_metadata);
1372
- }
1373
1355
  GRPC_HTTP2_SERVER_DLOG
1374
1356
  << "Http2ServerTransport::CallOutboundLoop "
1375
1357
  "Completed initial metadata and messages with status: "
@@ -1385,7 +1367,6 @@ auto Http2ServerTransport::CallOutboundLoop(RefCountedPtr<Stream> stream) {
1385
1367
  GRPC_HTTP2_SERVER_DLOG
1386
1368
  << "Http2ServerTransport::CallOutboundLoop "
1387
1369
  "Received Server Trailing Metadata";
1388
- // TODO(akshitpatel) : [PH2][P1] : Call BeginCloseStream.
1389
1370
  return send_trailing_metadata(std::move(metadata));
1390
1371
  });
1391
1372
  }));
@@ -1409,14 +1390,13 @@ std::optional<RefCountedPtr<Stream>> Http2ServerTransport::MakeStream(
1409
1390
 
1410
1391
  Http2Status Http2ServerTransport::IncomingStream(
1411
1392
  ClientMetadataHandle&& metadata, const uint32_t stream_id) {
1412
- // TODO(akshitpatel) : [PH2][P0] : Check the GOAWAY conditions.
1413
- // if(stream_id > last_accepted_stream_id_) {
1414
- // return HandleError(stream_id, Http2Status::Http2ConnectionError(
1415
- // Http2ErrorCode::kProtocolError,
1416
- // "Stream id is less than last accepted
1417
- // stream id: " +
1418
- // std::to_string(stream_id)));
1419
- // }
1393
+ {
1394
+ MutexLock lock(&transport_mutex_);
1395
+ if (is_transport_closed_) {
1396
+ return Http2Status::Http2ConnectionError(Http2ErrorCode::kRefusedStream,
1397
+ "Transport is closed.");
1398
+ }
1399
+ }
1420
1400
 
1421
1401
  GRPC_DCHECK(LookupStream(stream_id) == nullptr);
1422
1402
 
@@ -1440,210 +1420,94 @@ Http2Status Http2ServerTransport::IncomingStream(
1440
1420
  AddToStreamList(stream);
1441
1421
  stream->SetInitialMetadataReceived();
1442
1422
 
1443
- // TODO(tjagtap) : [PH2][P1] : We could receive a valid Metadata. And
1444
- // Spawn CallOutboundLoop. But before the CallOutboundLoop starts, if
1445
- // a BAD frame is received, it might cause either Stream or Transport Error.
1446
- // Handle those errors.
1447
1423
  stream->GetCallInitiator().SpawnGuarded(
1448
- "CallOutboundLoop", [this, stream = std::move(stream),
1449
- call_handler = std::move(call.handler)]() mutable {
1450
- call_destination_->StartCall(std::move(call_handler));
1451
- return CallOutboundLoop(std::move(stream));
1424
+ "CallOutboundLoop",
1425
+ [self = RefAsSubclass<Http2ServerTransport>(), stream = std::move(stream),
1426
+ call_handler = std::move(call.handler)]() mutable {
1427
+ self->call_destination_->StartCall(std::move(call_handler));
1428
+ return Map(self->CallOutboundLoop(std::move(stream)),
1429
+ [self](absl::Status status) { return status; });
1452
1430
  });
1453
1431
  return Http2Status::Ok();
1454
1432
  }
1455
1433
 
1456
- // This function is idempotent and MUST be called from the transport party.
1457
- // All the scenarios that can lead to this function being called are:
1458
- // 1. Reading a RST stream frame: In this case, the stream is immediately
1459
- // closed for reads and writes and removed from the stream_list_.
1460
- // 2. Reading a Trailing Metadata frame: There are two possible scenarios:
1461
- // a. The stream is closed for writes: Close the stream for reads and writes
1462
- // and remove the stream from the stream_list_.
1463
- // b. The stream is NOT closed for writes: Stream is kept open for reads and
1464
- // writes. CallHandler OnDone will trigger sending a half close frame. If
1465
- // before the multiplexer loop triggers sending a half close a RST stream
1466
- // is read, the stream is closed for reads and writes immediately and the
1467
- // half close is discarded. If no RST stream is read, the stream is closed
1468
- // for reads and writes upon sending the half close frame from the
1469
- // multiplexer loop.
1470
- // 3. Hitting error condition in the transport: In this case, RST stream is
1471
- // enqueued and the stream is closed for reads immediately. This implies we
1472
- // reduce the number of active streams inline. When multiplexer loop
1473
- // processes the RST stream frame, the stream ref will dropped. The other
1474
- // stream ref will be dropped when CallHandler's OnDone is executed causing
1475
- // the stream to be destroyed. CallHandlers OnDone also tries to enqueue a
1476
- // RST stream frame. This is a no-op at this point.
1477
- // 4. Application abort: In this case, CallHandler OnDone will enqueue RST
1478
- // stream frame to the stream data queue. The multiplexer loop will send the
1479
- // reset stream frame and close the stream from reads and writes.
1480
- // 5. Transport close: This takes up the same path as case 3.
1481
- // In all the above cases, trailing metadata is pushed to the call spine.
1482
- // Note: The stream ref is held in atmost 3 places:
1483
- // 1. stream_list_ : This is released when the stream is closed for reads.
1484
- // 2. CallHandler OnDone : This is released when Trailing Metadata is pushed to
1485
- // the call spine.
1486
- // 3. List of writable streams : This is released after the final frame is
1487
- // dequeued from the StreamDataQueue.
1488
- // void Http2ServerTransport::BeginCloseStream(
1489
- // RefCountedPtr<Stream> stream,
1490
- // std::optional<uint32_t> reset_stream_error_code,
1491
- // ServerMetadataHandle&& metadata, DebugLocation whence) {
1492
- // if (stream == nullptr) {
1493
- // GRPC_HTTP2_SERVER_DLOG << "Http2ServerTransport::BeginCloseStream stream
1494
- // "
1495
- // "is null reset_stream_error_code="
1496
- // << (reset_stream_error_code.has_value()
1497
- // ? absl::StrCat(*reset_stream_error_code)
1498
- // : "nullopt")
1499
- // << " metadata=" << metadata->DebugString();
1500
- // return;
1501
- // }
1502
-
1503
- // GRPC_HTTP2_SERVER_DLOG
1504
- // << "Http2ServerTransport::BeginCloseStream for stream id: "
1505
- // << stream->GetStreamId() << " error_code="
1506
- // << (reset_stream_error_code.has_value()
1507
- // ? absl::StrCat(*reset_stream_error_code)
1508
- // : "nullopt")
1509
- // << " ServerMetadata=" << metadata->DebugString()
1510
- // << " location=" << whence.file() << ":" << whence.line();
1511
-
1512
- // bool close_reads = false;
1513
- // bool close_writes = false;
1514
- // if (metadata->get(GrpcCallWasCancelled())) {
1515
- // if (!reset_stream_error_code) {
1516
- // // Callers taking this path:
1517
- // // 1. Reading a RST stream frame (will not send any frame out).
1518
- // // 2. Closing a stream before initial metadata is sent.
1519
- // close_reads = true;
1520
- // close_writes = true;
1521
- // GRPC_HTTP2_SERVER_DLOG
1522
- // << "Http2ServerTransport::BeginCloseStream for stream id: "
1523
- // << stream->GetStreamId() << " close_reads= " << close_reads
1524
- // << " close_writes= " << close_writes;
1525
- // } else {
1526
- // // Callers taking this path:
1527
- // // 1. Processing Error in transport (will send reset stream from here).
1528
- // absl::StatusOr<StreamWritabilityUpdate> enqueue_result =
1529
- // stream->EnqueueResetStream(reset_stream_error_code.value());
1530
- // GRPC_HTTP2_SERVER_DLOG << "Enqueued ResetStream with error code="
1531
- // << reset_stream_error_code.value()
1532
- // << " status=" << enqueue_result.status();
1533
- // if (enqueue_result.ok()) {
1534
- // GRPC_UNUSED absl::Status status =
1535
- // MaybeAddStreamToWritableStreamList(stream,
1536
- // enqueue_result.value());
1537
- // }
1538
- // close_reads = true;
1539
- // GRPC_HTTP2_SERVER_DLOG
1540
- // << "Http2ServerTransport::BeginCloseStream for stream id: "
1541
- // << stream->GetStreamId() << " close_reads= " << close_reads
1542
- // << " close_writes= " << close_writes;
1543
- // }
1544
- // } else {
1545
- // // Callers taking this path:
1546
- // // 1. Reading Trailing Metadata (MAY send half close from OnDone).
1547
- // // If a half close frame has already been sent, we should close the
1548
- // stream
1549
- // // for reads and writes.
1550
- // if (stream->IsHalfClosedLocal() || stream->IsStreamClosed()) {
1551
- // close_reads = true;
1552
- // close_writes = true;
1553
- // GRPC_HTTP2_SERVER_DLOG
1554
- // << "Http2ServerTransport::BeginCloseStream for stream id: "
1555
- // << stream->GetStreamId() << " close_reads= " << close_reads
1556
- // << " close_writes= " << close_writes;
1557
- // }
1558
- // }
1559
-
1560
- // if (close_reads || close_writes) {
1561
- // CloseStream(*stream, CloseStreamArgs{close_reads, close_writes}, whence);
1562
- // }
1563
-
1564
- // // If the call was cancelled, the stream MUST be closed for reads.
1565
- // GRPC_DCHECK(metadata->get(GrpcCallWasCancelled()) ? close_reads : true);
1566
-
1567
- // // This maybe called multiple times while closing a stream. In CallV3, the
1568
- // // flow for pushing server trailing metadata is idempotent. However, there
1569
- // is
1570
- // // a subtle difference. When we push server trailing metadata with a
1571
- // cancelled
1572
- // // status PushServerTrailingMetadata is spawned inline on the Call party
1573
- // // whereas for the non-cancelled status, PushServerTrailingMetadata is
1574
- // // spawned in the server_to_client spawn serializer. Because of this, in
1575
- // // case when the server pushes trailing metadata (non-cancelled) followed
1576
- // by a
1577
- // // RST stream with cancelled status, it is possible that the cancelled
1578
- // // trailing metadata (for RST stream) is processed before. This would
1579
- // result
1580
- // // in losing the actual status/message pushed by the server.
1581
- // // To address this, we push the server trailing metadata to the stream only
1582
- // // if it is not pushed already.
1583
- // stream->MaybePushServerTrailingMetadata(std::move(metadata));
1584
- // }
1585
-
1586
- // This function MUST be idempotent. This function MUST be called from the
1587
- // transport party.
1588
- // void Http2ServerTransport::CloseStream(Stream& stream, CloseStreamArgs args,
1589
- // DebugLocation whence) {
1590
- // std::optional<Http2Status> close_transport_error;
1591
-
1592
- // {
1593
- // // TODO(akshitpatel) : [PH2][P3] : Measure the impact of holding mutex
1594
- // // throughout this function.
1595
- // MutexLock lock(&transport_mutex_);
1596
- // GRPC_HTTP2_SERVER_DLOG
1597
- // << "Http2ServerTransport::CloseStream for stream id: "
1598
- // << stream.GetStreamId() << " close_reads=" << args.close_reads
1599
- // << " close_writes=" << args.close_writes
1600
- // << " read_context_=" << read_context_.DebugString()
1601
- // << " location=" << whence.file() << ":" << whence.line();
1602
-
1603
- // if (args.close_writes) {
1604
- // stream.SetWriteClosed();
1605
- // }
1434
+ void Http2ServerTransport::BeginCloseStream(
1435
+ RefCountedPtr<Stream> stream, uint32_t reset_stream_error_code,
1436
+ absl::Status trailing_metadata_status, DebugLocation whence) {
1437
+ GRPC_DCHECK(!trailing_metadata_status.ok());
1438
+ if (stream == nullptr) {
1439
+ GRPC_HTTP2_SERVER_DLOG << "Http2ServerTransport::BeginCloseStream stream"
1440
+ "is null reset_stream_error_code="
1441
+ << reset_stream_error_code
1442
+ << " status=" << trailing_metadata_status;
1443
+ return;
1444
+ }
1606
1445
 
1607
- // if (args.close_reads) {
1608
- // GRPC_HTTP2_SERVER_DLOG
1609
- // << "Http2ServerTransport::CloseStream for stream id: "
1610
- // << stream.GetStreamId() << " closing stream for reads.";
1611
- // // If the stream is closed while reading HEADER/CONTINUATION frames, we
1612
- // // should still parse the enqueued buffer to maintain HPACK state
1613
- // between
1614
- // // peers.
1615
- // if (read_context_.IsWaitingForContinuationFrame()) {
1616
- // Http2Status result = read_context_.ParseAndDiscardHeaders(
1617
- // SliceBuffer(), /*is_end_headers=*/false,
1618
- // /*original_status=*/Http2Status::Ok(),
1619
- // settings_->acked().max_header_list_size());
1620
- // if (result.GetType() ==
1621
- // Http2Status::Http2ErrorType::kConnectionError) {
1622
- // GRPC_HTTP2_SERVER_DLOG
1623
- // << "Http2ServerTransport::CloseStream for stream id: "
1624
- // << stream.GetStreamId() << " failed to partially process
1625
- // header: "
1626
- // << result.DebugString();
1627
- // close_transport_error.emplace(std::move(result));
1628
- // }
1629
- // }
1630
-
1631
- // stream_list_.erase(stream.GetStreamId());
1632
- // if (!close_transport_error.has_value() && CanCloseTransportLocked()) {
1633
- // // TODO(akshitpatel) : [PH2][P3] : Is kInternalError the right error
1634
- // // code to use here? IMO it should be kNoError.
1635
- // close_transport_error.emplace(Http2Status::Http2ConnectionError(
1636
- // Http2ErrorCode::kInternalError,
1637
- // std::string(RFC9113::kLastStreamClosed)));
1638
- // }
1639
- // }
1640
- // }
1446
+ GRPC_HTTP2_SERVER_DLOG
1447
+ << "Http2ServerTransport::BeginCloseStream for stream id: "
1448
+ << stream->GetStreamId() << " error_code=" << reset_stream_error_code
1449
+ << " Status=" << trailing_metadata_status << " location=" << whence.file()
1450
+ << ":" << whence.line();
1451
+
1452
+ // Enqueue RST_STREAM.
1453
+ absl::StatusOr<StreamWritabilityUpdate> enqueue_result =
1454
+ stream->EnqueueResetStream(reset_stream_error_code);
1455
+ GRPC_HTTP2_SERVER_DLOG << "Enqueued ResetStream with error code="
1456
+ << reset_stream_error_code
1457
+ << " status=" << enqueue_result.status();
1458
+ if (enqueue_result.ok()) {
1459
+ GRPC_UNUSED absl::Status status =
1460
+ MaybeAddStreamToWritableStreamList(stream, enqueue_result.value());
1461
+ }
1462
+ HandleStreamStateChange(
1463
+ *stream, stream->OnInitiateReset(std::move(trailing_metadata_status)));
1464
+ read_context_.OnResetFrameEnqueued(reset_stream_error_code);
1465
+ }
1466
+
1467
+ void Http2ServerTransport::HandleStreamStateChange(Stream& stream,
1468
+ StreamStateChange change) {
1469
+ if (change.reads_became_closed) {
1470
+ // If a stream is closing for reads and was actively waiting for a
1471
+ // continuation frame, parse the buffered HEADER/CONTINUATION frames
1472
+ if (read_context_.IsWaitingForContinuationFrame() &&
1473
+ read_context_.GetStreamId() == stream.GetStreamId()) {
1474
+ Http2Status result = read_context_.ParseAndDiscardHeaders(
1475
+ SliceBuffer(), /*is_end_headers=*/false,
1476
+ /*original_status=*/Http2Status::Ok(),
1477
+ settings_->acked().max_header_list_size());
1478
+ if (result.GetType() == Http2Status::Http2ErrorType::kConnectionError) {
1479
+ GRPC_HTTP2_SERVER_DLOG
1480
+ << "Http2ServerTransport::HandleStreamStateChange (DiscardHeaders) "
1481
+ "for stream id: "
1482
+ << stream.GetStreamId()
1483
+ << " failed to partially process header : " << result.DebugString();
1484
+ GRPC_UNUSED absl::Status status =
1485
+ HandleError(/*stream=*/nullptr, std::move(result));
1486
+ return;
1487
+ }
1488
+ }
1489
+ }
1490
+ if (change.stream_became_closed) {
1491
+ CleanupStream(stream);
1492
+ }
1493
+ }
1641
1494
 
1642
- // if (close_transport_error.has_value()) {
1643
- // GRPC_UNUSED absl::Status status = HandleError(
1644
- // /*stream_id=*/std::nullopt, std::move(*close_transport_error));
1645
- // }
1646
- // }
1495
+ void Http2ServerTransport::CleanupStream(Stream& stream) {
1496
+ bool should_close = false;
1497
+ {
1498
+ MutexLock lock(&transport_mutex_);
1499
+ stream_list_.erase(stream.GetStreamId());
1500
+ // Close transport if graceful GOAWAY has been sent and there are no more
1501
+ // streams.
1502
+ if (goaway_manager_.IsFinalGracefulGoawaySent() && stream_list_.empty()) {
1503
+ should_close = true;
1504
+ }
1505
+ }
1506
+ if (should_close) {
1507
+ MaybeSpawnCloseTransport(Http2Status::AbslConnectionError(
1508
+ absl::StatusCode::kUnavailable, "Graceful shutdown complete."));
1509
+ }
1510
+ }
1647
1511
 
1648
1512
  absl::Status Http2ServerTransport::UpdateAllStreamsWritability() {
1649
1513
  MutexLock lock(&transport_mutex_);
@@ -1674,27 +1538,27 @@ absl::Status Http2ServerTransport::UpdateAllStreamsWritability() {
1674
1538
  //////////////////////////////////////////////////////////////////////////////
1675
1539
  // Ping Keepalive and Goaway
1676
1540
 
1677
- // void Http2ServerTransport::MaybeSpawnPingTimeout(
1678
- // std::optional<uint64_t> opaque_data) {
1679
- // if (opaque_data.has_value()) {
1680
- // SpawnGuardedTransportParty(
1681
- // "PingTimeout", [self = RefAsSubclass<Http2ServerTransport>(),
1682
- // opaque_data = *opaque_data]() {
1683
- // return self->ping_manager_->TimeoutPromise(opaque_data);
1684
- // });
1685
- // }
1686
- // }
1687
- // void Http2ServerTransport::MaybeSpawnDelayedPing(
1688
- // std::optional<Duration> delayed_ping_wait) {
1689
- // if (delayed_ping_wait.has_value()) {
1690
- // SpawnGuardedTransportParty(
1691
- // "DelayedPing", [self = RefAsSubclass<Http2ServerTransport>(),
1692
- // wait = *delayed_ping_wait]() {
1693
- // GRPC_HTTP2_PING_LOG << "Scheduling delayed ping after wait=" <<
1694
- // wait; return self->ping_manager_->DelayedPingPromise(wait);
1695
- // });
1696
- // }
1697
- // }
1541
+ void Http2ServerTransport::MaybeSpawnPingTimeout(
1542
+ std::optional<uint64_t> opaque_data) {
1543
+ if (opaque_data.has_value()) {
1544
+ SpawnGuardedTransportParty(
1545
+ "PingTimeout", [self = RefAsSubclass<Http2ServerTransport>(),
1546
+ opaque_data = *opaque_data]() {
1547
+ return self->ping_manager_->TimeoutPromise(opaque_data);
1548
+ });
1549
+ }
1550
+ }
1551
+ void Http2ServerTransport::MaybeSpawnDelayedPing(
1552
+ std::optional<Duration> delayed_ping_wait) {
1553
+ if (delayed_ping_wait.has_value()) {
1554
+ SpawnGuardedTransportParty(
1555
+ "DelayedPing", [self = RefAsSubclass<Http2ServerTransport>(),
1556
+ wait = *delayed_ping_wait]() {
1557
+ GRPC_HTTP2_PING_LOG << "Scheduling delayed ping after wait=" << wait;
1558
+ return self->ping_manager_->DelayedPingPromise(wait);
1559
+ });
1560
+ }
1561
+ }
1698
1562
 
1699
1563
  absl::Status Http2ServerTransport::AckPing(uint64_t opaque_data) {
1700
1564
  // It is possible that the PingRatePolicy may decide to not send a ping
@@ -1715,122 +1579,151 @@ absl::Status Http2ServerTransport::AckPing(uint64_t opaque_data) {
1715
1579
  return absl::OkStatus();
1716
1580
  }
1717
1581
 
1718
- // void Http2ServerTransport::MaybeSpawnKeepaliveLoop() {
1719
- // if (keepalive_manager_->IsKeepAliveLoopNeeded()) {
1720
- // SpawnGuardedTransportParty(
1721
- // "KeepaliveLoop", [self = RefAsSubclass<Http2ServerTransport>()]() {
1722
- // return self->keepalive_manager_->KeepaliveLoop();
1723
- // });
1724
- // }
1725
- // }
1582
+ void Http2ServerTransport::MaybeSpawnKeepaliveLoop() {
1583
+ if (keepalive_manager_->IsKeepAliveLoopNeeded()) {
1584
+ SpawnGuardedTransportParty(
1585
+ "KeepaliveLoop", [self = RefAsSubclass<Http2ServerTransport>()]() {
1586
+ return self->keepalive_manager_->KeepaliveLoop();
1587
+ });
1588
+ }
1589
+ }
1590
+
1591
+ auto Http2ServerTransport::SpawnGracefulGoawayPromise(Slice&& debug_data) {
1592
+ SpawnGuardedTransportParty(
1593
+ "GracefulGoaway",
1594
+ [self = RefAsSubclass<Http2ServerTransport>(),
1595
+ debug_data = std::forward<Slice>(debug_data)]() mutable {
1596
+ GRPC_HTTP2_SERVER_DLOG
1597
+ << "Http2ServerTransport::SpawnGracefulGoawayPromise: "
1598
+ "Initiated graceful GOAWAY";
1599
+ return self->UntilTransportClosed(Map(
1600
+ self->goaway_manager_.RequestGoaway(
1601
+ Http2ErrorCode::kNoError, std::move(debug_data),
1602
+ self->last_incoming_stream_id_, /*immediate=*/false),
1603
+ [self](absl::Status status) {
1604
+ bool should_close = false;
1605
+ {
1606
+ MutexLock lock(&self->transport_mutex_);
1607
+ if (self->GetActiveStreamCountLocked() == 0) {
1608
+ should_close = true;
1609
+ }
1610
+ }
1611
+ if (should_close) {
1612
+ self->MaybeSpawnCloseTransport(Http2Status::AbslConnectionError(
1613
+ absl::StatusCode::kUnavailable,
1614
+ "Graceful shutdown complete."));
1615
+ }
1616
+ return status;
1617
+ }));
1618
+ });
1619
+ }
1726
1620
 
1727
1621
  //////////////////////////////////////////////////////////////////////////////
1728
1622
  // Error Path and Close Path
1729
1623
 
1730
- // TODO(akshitpatel) : [PH2][P1] : Invoke on_close_callback_ when CloseTransport
1731
- // is implemented.
1732
- // void Http2ServerTransport::MaybeSpawnCloseTransport(Http2Status http2_status,
1733
- // DebugLocation whence) {
1734
- // GRPC_HTTP2_SERVER_DLOG << "Http2ServerTransport::MaybeSpawnCloseTransport "
1735
- // "status="
1736
- // << http2_status << " location=" << whence.file() <<
1737
- // ":"
1738
- // << whence.line();
1739
-
1740
- // // Free up the stream_list at this point. This would still allow the frames
1741
- // // in the MPSC to be drained and block any additional frames from being
1742
- // // enqueued. Additionally this also prevents additional frames with
1743
- // non-zero
1744
- // // stream_ids from being processed by the read loop.
1745
- // ReleasableMutexLock lock(&transport_mutex_);
1746
- // if (is_transport_closed_) {
1747
- // lock.Release();
1748
- // return;
1749
- // }
1750
- // GRPC_HTTP2_SERVER_DLOG << "Http2ServerTransport::MaybeSpawnCloseTransport "
1751
- // "Initiating transport close";
1752
- // is_transport_closed_ = true;
1753
- // absl::flat_hash_map<uint32_t, RefCountedPtr<Stream>> stream_list =
1754
- // std::move(stream_list_);
1755
- // stream_list_.clear();
1756
- // ReportDisconnectionLocked(
1757
- // http2_status.GetAbslConnectionError(), {},
1758
- // absl::StrCat("Transport closed: ",
1759
- // http2_status.DebugString()).c_str());
1760
- // lock.Release();
1761
-
1762
- // SpawnInfallibleTransportParty(
1763
- // "CloseTransport", [self = RefAsSubclass<Http2ServerTransport>(),
1764
- // stream_list = std::move(stream_list),
1765
- // http2_status = std::move(http2_status)]() mutable {
1766
- // self->security_frame_handler_->OnTransportClosed();
1767
- // GRPC_HTTP2_SERVER_DLOG
1768
- // << "Http2ServerTransport::MaybeSpawnCloseTransport "
1769
- // "Cleaning up call stacks";
1770
- // // Clean up the call stacks for all active streams.
1771
- // for (const auto& pair : stream_list) {
1772
- // // There is no merit in transitioning the stream to
1773
- // // closed state here as the subsequent lookups would
1774
- // // fail. Also, as this is running on the transport
1775
- // // party, there would not be concurrent access to the stream.
1776
- // RefCountedPtr<Stream> stream = pair.second;
1777
- // self->BeginCloseStream(std::move(stream),
1778
- // Http2ErrorCodeToFrameErrorCode(
1779
- // http2_status.GetConnectionErrorCode()),
1780
- // CancelledServerMetadataFromStatus(
1781
- // http2_status.GetAbslConnectionError()));
1782
- // }
1783
-
1784
- // // RFC9113 : A GOAWAY frame might not immediately precede closing of
1785
- // // the connection; a receiver of a GOAWAY that has no more use for
1786
- // the
1787
- // // connection SHOULD still send a GOAWAY frame before terminating the
1788
- // // connection.
1789
- // return Map(
1790
- // // TODO(akshitpatel) : [PH2][P4] : This is creating a copy of
1791
- // // the debug data. Verify if this is causing a performance
1792
- // // issue.
1793
- // Race(AssertResultType<absl::Status>(
1794
- // self->goaway_manager_.RequestGoaway(
1795
- // http2_status.GetConnectionErrorCode(),
1796
- // /*debug_data=*/
1797
- // Slice::FromCopiedString(
1798
- // http2_status.GetAbslConnectionError().message()),
1799
- // kLastIncomingStreamIdClient, /*immediate=*/true)),
1800
- // // Failsafe to close the transport if goaway is not
1801
- // // sent within kGoawaySendTimeoutSeconds seconds.
1802
- // Sleep(Duration::Seconds(kGoawaySendTimeoutSeconds))),
1803
- // [self](auto) mutable {
1804
- // self->CloseTransport();
1805
- // return Empty{};
1806
- // });
1807
- // ;
1808
- // });
1809
- // }
1624
+ absl::Status Http2ServerTransport::HandleError(RefCountedPtr<Stream> stream,
1625
+ Http2Status status,
1626
+ DebugLocation whence) {
1627
+ GRPC_HTTP2_SERVER_DLOG << "Http2ServerTransport::HandleError for stream id="
1628
+ << (stream != nullptr
1629
+ ? absl::StrCat(stream->GetStreamId())
1630
+ : "nullopt")
1631
+ << " status=" << status.DebugString()
1632
+ << " location=" << whence.file() << ":"
1633
+ << whence.line();
1634
+ Http2Status::Http2ErrorType error_type = status.GetType();
1635
+ GRPC_DCHECK(error_type != Http2Status::Http2ErrorType::kOk);
1636
+
1637
+ if (error_type == Http2Status::Http2ErrorType::kConnectionError) {
1638
+ GRPC_DCHECK(stream == nullptr);
1639
+ absl::Status absl_status = status.GetAbslConnectionError();
1640
+ MaybeSpawnCloseTransport(std::move(status), whence);
1641
+ return absl_status;
1642
+ } else if (error_type == Http2Status::Http2ErrorType::kStreamError) {
1643
+ uint32_t reset_stream_error_code =
1644
+ Http2ErrorCodeToFrameErrorCode(status.GetStreamErrorCode());
1645
+ if (stream != nullptr) {
1646
+ BeginCloseStream(std::move(stream), reset_stream_error_code,
1647
+ status.GetAbslStreamError(), whence);
1648
+ }
1649
+ return absl::OkStatus();
1650
+ }
1810
1651
 
1811
- // bool Http2ServerTransport::CanCloseTransportLocked() const {
1812
- // // If there are no more streams and next stream id is greater than the
1813
- // // max allowed stream id, then no more streams can be created and it is
1814
- // // safe to close the transport.
1815
- // GRPC_HTTP2_SERVER_DLOG << "Http2ServerTransport::CanCloseTransportLocked "
1816
- // "GetActiveStreamCountLocked="
1817
- // << GetActiveStreamCountLocked()
1818
- // << " PeekNextStreamId=" << PeekNextStreamId()
1819
- // << " GetMaxAllowedStreamId="
1820
- // << GetMaxAllowedStreamId();
1821
- // return GetActiveStreamCountLocked() == 0 &&
1822
- // PeekNextStreamId() > GetMaxAllowedStreamId();
1823
- // }
1652
+ GPR_UNREACHABLE_CODE(return absl::InternalError("Invalid error type"));
1653
+ }
1824
1654
 
1825
- // void Http2ServerTransport::CloseTransport() {
1826
- // GRPC_HTTP2_SERVER_DLOG << "Http2ServerTransport::CloseTransport";
1655
+ void Http2ServerTransport::MaybeSpawnCloseTransport(Http2Status http2_status,
1656
+ DebugLocation whence) {
1657
+ GRPC_HTTP2_SERVER_DLOG << "Http2ServerTransport::MaybeSpawnCloseTransport "
1658
+ "status="
1659
+ << http2_status.DebugString()
1660
+ << " location=" << whence.file() << ":"
1661
+ << whence.line();
1827
1662
 
1828
- // transport_closed_latch_.Set();
1829
- // settings_->HandleTransportShutdown(event_engine_.get());
1663
+ ReleasableMutexLock lock(&transport_mutex_);
1664
+ if (is_transport_closed_) {
1665
+ lock.Release();
1666
+ return;
1667
+ }
1668
+ GRPC_HTTP2_SERVER_DLOG << "Http2ServerTransport::MaybeSpawnCloseTransport "
1669
+ "Initiating transport close";
1670
+ is_transport_closed_ = true;
1671
+ absl::flat_hash_map<uint32_t, RefCountedPtr<Stream>> stream_list =
1672
+ std::move(stream_list_);
1673
+ stream_list_.clear();
1674
+ ReportDisconnectionLocked(
1675
+ GRPC_CHANNEL_SHUTDOWN, http2_status.GetAbslConnectionError(), {},
1676
+ absl::StrCat("Transport closed: ", http2_status.DebugString()).c_str());
1677
+ lock.Release();
1678
+
1679
+ SpawnInfallibleTransportParty(
1680
+ "CloseTransport",
1681
+ [self = RefAsSubclass<Http2ServerTransport>(),
1682
+ stream_list = std::move(stream_list),
1683
+ http2_status = std::move(http2_status), whence]() mutable {
1684
+ self->security_frame_handler_->OnTransportClosed();
1685
+ GRPC_HTTP2_SERVER_DLOG
1686
+ << "Http2ServerTransport::MaybeSpawnCloseTransport "
1687
+ "Cleaning up call stacks";
1688
+ // Clean up the call stacks for all active streams.
1689
+ for (const auto& pair : stream_list) {
1690
+ RefCountedPtr<Stream> stream = pair.second;
1691
+ self->BeginCloseStream(std::move(stream),
1692
+ Http2ErrorCodeToFrameErrorCode(
1693
+ http2_status.GetConnectionErrorCode()),
1694
+ http2_status.GetAbslConnectionError(), whence);
1695
+ }
1830
1696
 
1831
- // // This is the only place where the general_party_ is reset.
1832
- // general_party_.reset();
1833
- // }
1697
+ // Sleep for kGoawaySendTimeoutSeconds before closing the transport to
1698
+ // let write buffers drain.
1699
+ return Map(
1700
+ Race(AssertResultType<absl::Status>(
1701
+ self->goaway_manager_.RequestGoaway(
1702
+ http2_status.GetConnectionErrorCode(),
1703
+ Slice::FromCopiedString(std::string(
1704
+ http2_status.GetAbslConnectionError().message())),
1705
+ self->last_incoming_stream_id_, /*immediate=*/true)),
1706
+ Sleep(Duration::Seconds(kGoawaySendTimeoutSeconds))),
1707
+ [self](auto) mutable {
1708
+ self->CloseTransport();
1709
+ return Empty{};
1710
+ });
1711
+ });
1712
+ }
1713
+
1714
+ void Http2ServerTransport::CloseTransport() {
1715
+ GRPC_HTTP2_SERVER_DLOG << "Http2ServerTransport::CloseTransport";
1716
+
1717
+ transport_closed_latch_.Set();
1718
+ settings_->HandleTransportShutdown(event_engine_.get());
1719
+
1720
+ if (on_close_callback_ != nullptr) {
1721
+ ExecCtx::Run(DEBUG_LOCATION, on_close_callback_, absl::OkStatus());
1722
+ on_close_callback_ = nullptr;
1723
+ }
1724
+
1725
+ general_party_.reset();
1726
+ }
1834
1727
 
1835
1728
  //////////////////////////////////////////////////////////////////////////////
1836
1729
  // Misc Transport Stuff
@@ -1923,10 +1816,6 @@ void Http2ServerTransport::ReadChannelArgs(const ChannelArgs& channel_args,
1923
1816
  keepalive_permit_without_calls_ = args.keepalive_permit_without_calls;
1924
1817
  test_only_ack_pings_ = args.test_only_ack_pings;
1925
1818
 
1926
- if (args.initial_sequence_number > 0) {
1927
- next_stream_id_ = args.initial_sequence_number;
1928
- }
1929
-
1930
1819
  settings_->SetSettingsTimeout(args.settings_timeout);
1931
1820
  if (args.max_usable_hpack_table_size >= 0) {
1932
1821
  encoder_.SetMaxUsableSize(args.max_usable_hpack_table_size);
@@ -1958,7 +1847,7 @@ Http2ServerTransport::PingSystemInterfaceImpl::PingTimeout() {
1958
1847
  // kRefusedStream doesn't seem to fit this case. We should revisit this
1959
1848
  // and update the error code.
1960
1849
  return Immediate(transport_->HandleError(
1961
- std::nullopt,
1850
+ nullptr,
1962
1851
  Http2Status::Http2ConnectionError(Http2ErrorCode::kRefusedStream,
1963
1852
  GRPC_CHTTP2_PING_TIMEOUT_STR)));
1964
1853
  }
@@ -1987,7 +1876,7 @@ Http2ServerTransport::KeepAliveInterfaceImpl::OnKeepAliveTimeout() {
1987
1876
  // kRefusedStream doesn't seem to fit this case. We should revisit this
1988
1877
  // and update the error code.
1989
1878
  return Immediate(transport_->HandleError(
1990
- std::nullopt,
1879
+ nullptr,
1991
1880
  Http2Status::Http2ConnectionError(Http2ErrorCode::kRefusedStream,
1992
1881
  GRPC_CHTTP2_KEEPALIVE_TIMEOUT_STR)));
1993
1882
  }
@@ -2009,9 +1898,7 @@ Http2ServerTransport::GoawayInterfaceImpl::Make(
2009
1898
  }
2010
1899
 
2011
1900
  uint32_t Http2ServerTransport::GoawayInterfaceImpl::GetLastAcceptedStreamId() {
2012
- // TODO(akshitpatel) : [PH2][P1] : This function is not needed for a client.
2013
- // Implement this for the server.
2014
- return 0;
1901
+ return transport_->last_incoming_stream_id_;
2015
1902
  }
2016
1903
 
2017
1904
  //////////////////////////////////////////////////////////////////////////////
@@ -2024,14 +1911,14 @@ Http2ServerTransport::Http2ServerTransport(
2024
1911
  grpc_closure* on_close_callback)
2025
1912
  : channelz::DataSource(http2::CreateChannelzSocketNode(
2026
1913
  endpoint.GetEventEngineEndpoint(), channel_args)),
2027
- outgoing_frames_(10), // TODO(akshitpatel) : [PH2][P0][Write] : Remove
2028
1914
  event_engine_(std::move(event_engine)),
2029
1915
  endpoint_(std::move(endpoint)),
2030
1916
  settings_(MakeRefCounted<SettingsPromiseManager>(
2031
- std::move(on_receive_settings))),
1917
+ kIsClient, std::move(on_receive_settings))),
2032
1918
  on_close_callback_(on_close_callback),
2033
1919
  should_reset_ping_clock_(false),
2034
- read_context_(MaxNewStreamsPerRead(channel_args), endpoint_, kIsClient),
1920
+ read_context_(MaxNewStreamsPerRead(channel_args), endpoint_, kIsClient,
1921
+ GetMaxSecurityFrameSize(channel_args)),
2035
1922
  transport_write_context_(kIsClient),
2036
1923
  ping_manager_(std::nullopt),
2037
1924
  keepalive_manager_(std::nullopt),
@@ -2040,7 +1927,7 @@ Http2ServerTransport::Http2ServerTransport(
2040
1927
  ->memory_quota()
2041
1928
  ->CreateMemoryOwner()),
2042
1929
  flow_control_(
2043
- "PH2_Server",
1930
+ /*peer_name=*/read_context_.peer_string().as_string_view(),
2044
1931
  channel_args.GetBool(GRPC_ARG_HTTP2_BDP_PROBE).value_or(true),
2045
1932
  &memory_owner_),
2046
1933
  security_frame_handler_(MakeRefCounted<SecurityFrameHandler>()),
@@ -2099,7 +1986,6 @@ void Http2ServerTransport::SetCallDestination(
2099
1986
 
2100
1987
  void Http2ServerTransport::PerformOp(grpc_transport_op* op) {
2101
1988
  GRPC_HTTP2_SERVER_DLOG << "Http2ServerTransport PerformOp Begin";
2102
- // TODO(tjagtap) : [PH2][P1] : Implement the needed operations.
2103
1989
  bool did_stuff = false;
2104
1990
  if (op->start_connectivity_watch != nullptr) {
2105
1991
  StartConnectivityWatch(op->start_connectivity_watch_state,
@@ -2110,8 +1996,20 @@ void Http2ServerTransport::PerformOp(grpc_transport_op* op) {
2110
1996
  StopConnectivityWatch(op->stop_connectivity_watch);
2111
1997
  did_stuff = true;
2112
1998
  }
2113
- // GRPC_CHECK(!op->set_accept_stream)
2114
- // << "Set_accept_stream not supported on clients";
1999
+ if (!op->disconnect_with_error.ok()) {
2000
+ MaybeSpawnCloseTransport(Http2Status::Http2ConnectionError(
2001
+ AbslStatusCodeToErrorCode(op->disconnect_with_error.code()),
2002
+ std::string(op->disconnect_with_error.message())));
2003
+ did_stuff = true;
2004
+ }
2005
+ // We always consider this case as a graceful shutdown.
2006
+ if (!op->goaway_error.ok()) {
2007
+ GRPC_HTTP2_SERVER_DLOG << "GracefulGoaway triggered with error: "
2008
+ << op->goaway_error;
2009
+ SpawnGracefulGoawayPromise(
2010
+ Slice::FromCopiedString(op->goaway_error.message()));
2011
+ did_stuff = true;
2012
+ }
2115
2013
  GRPC_DCHECK(did_stuff) << "Unimplemented transport perform op ";
2116
2014
 
2117
2015
  ExecCtx::Run(DEBUG_LOCATION, op->on_consumed, absl::OkStatus());
@@ -2128,27 +2026,15 @@ void Http2ServerTransport::PerformOp(grpc_transport_op* op) {
2128
2026
  void Http2ServerTransport::Orphan() {
2129
2027
  GRPC_HTTP2_SERVER_DLOG << "Http2ServerTransport::Orphan Begin";
2130
2028
  SourceDestructing();
2131
- // MaybeSpawnCloseTransport(
2132
- // ToHttpOkOrConnError(absl::UnavailableError("Orphaned")));
2133
-
2134
- // TODO(akshitpatel) : [PH2][P1] : These calls need to be moved to a different
2135
- // place once shutdown code is added.
2136
- ReportDisconnection(GRPC_CHANNEL_SHUTDOWN, absl::UnavailableError("Orphan"),
2137
- StateWatcher::DisconnectInfo(), "Orphan");
2138
- // TODO(tjagtap) : [PH2][P2] : Implement the needed cleanup. This is not the
2139
- // right place to clean up the party.
2140
- general_party_.reset();
2141
- if (on_close_callback_ != nullptr) {
2142
- ExecCtx::Run(DEBUG_LOCATION, on_close_callback_, absl::OkStatus());
2143
- on_close_callback_ = nullptr;
2144
- }
2029
+ MaybeSpawnCloseTransport(
2030
+ ToHttpOkOrConnError(absl::UnavailableError("Orphaned")));
2145
2031
  Unref();
2146
2032
  GRPC_HTTP2_SERVER_DLOG << "Http2ServerTransport::Orphan End";
2147
2033
  }
2148
2034
 
2149
2035
  void Http2ServerTransport::SpawnTransportLoops() {
2150
2036
  GRPC_HTTP2_SERVER_DLOG << "Http2ServerTransport::SpawnTransportLoops Begin";
2151
- // MaybeSpawnKeepaliveLoop();
2037
+ MaybeSpawnKeepaliveLoop();
2152
2038
 
2153
2039
  // SpawnGuardedTransportParty(
2154
2040
  // "FlowControlPeriodicUpdateLoop",
@@ -2170,16 +2056,16 @@ void Http2ServerTransport::SpawnTransportLoops() {
2170
2056
  void Http2ServerTransport::InitializeAndSpawnTransportLoops() {
2171
2057
  SpawnGuardedTransportParty(
2172
2058
  "SpawnTransportLoops", [self = RefAsSubclass<Http2ServerTransport>()] {
2173
- return Map(
2174
- self->EndpointReadSlice(GRPC_CHTTP2_CLIENT_CONNECT_STRLEN),
2175
- [self](absl::StatusOr<Slice> status) -> absl::Status {
2176
- Http2Status result = ValidateIncomingConnectionPreface(status);
2177
- if (!result.IsOk()) {
2178
- return self->HandleError(std::nullopt, std::move(result));
2179
- }
2180
- self->SpawnTransportLoops();
2181
- return absl::OkStatus();
2182
- });
2059
+ return Map(self->EndpointReadSlice(GRPC_CHTTP2_CLIENT_CONNECT_STRLEN),
2060
+ [self](absl::StatusOr<Slice> status) -> absl::Status {
2061
+ Http2Status result =
2062
+ ValidateIncomingConnectionPreface(status);
2063
+ if (!result.IsOk()) {
2064
+ return self->HandleError(nullptr, std::move(result));
2065
+ }
2066
+ self->SpawnTransportLoops();
2067
+ return absl::OkStatus();
2068
+ });
2183
2069
  });
2184
2070
  }
2185
2071