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
@@ -33,7 +33,6 @@
33
33
  #include "src/core/call/metadata_batch.h"
34
34
  #include "src/core/ext/transport/chttp2/transport/flow_control.h"
35
35
  #include "src/core/ext/transport/chttp2/transport/frame.h"
36
- #include "src/core/ext/transport/chttp2/transport/header_assembler.h"
37
36
  #include "src/core/ext/transport/chttp2/transport/hpack_encoder.h"
38
37
  #include "src/core/ext/transport/chttp2/transport/http2_status.h"
39
38
  #include "src/core/ext/transport/chttp2/transport/message_assembler.h"
@@ -44,6 +43,7 @@
44
43
  #include "src/core/util/ref_counted.h"
45
44
  #include "src/core/util/ref_counted_ptr.h"
46
45
  #include "absl/log/log.h"
46
+ #include "absl/status/status.h"
47
47
 
48
48
  namespace grpc_core {
49
49
  namespace http2 {
@@ -54,13 +54,159 @@ namespace http2 {
54
54
  constexpr uint32_t kStreamQueueSize = /*1 MB*/ 1024u * 1024u;
55
55
  constexpr uint32_t kInvalidStreamId = 0u;
56
56
 
57
- enum class HttpStreamState : uint8_t {
58
- // https://www.rfc-editor.org/rfc/rfc9113.html#name-stream-states
59
- kIdle,
60
- kOpen,
61
- kHalfClosedLocal,
62
- kHalfClosedRemote,
63
- kClosed,
57
+ struct StreamStateChange {
58
+ bool reads_became_closed = false;
59
+ bool stream_became_closed = false;
60
+ std::string DebugString() const {
61
+ return absl::StrCat("reads_became_closed: ", reads_became_closed,
62
+ " stream_became_closed: ", stream_became_closed);
63
+ }
64
+ };
65
+
66
+ class StreamState {
67
+ public:
68
+ explicit StreamState(const bool started) : started_(started) {}
69
+ ~StreamState() = default;
70
+
71
+ // StreamState is neither movable nor copyable.
72
+ StreamState(const StreamState&) = delete;
73
+ StreamState& operator=(const StreamState&) = delete;
74
+ StreamState(StreamState&&) = delete;
75
+ StreamState& operator=(StreamState&&) = delete;
76
+
77
+ // State queries
78
+ bool started() const { return started_; }
79
+ bool reads_closed() const { return reads_closed_; }
80
+ bool half_closed_local() const { return half_closed_local_; }
81
+ bool writes_closed() const {
82
+ return writes_closed_.load(std::memory_order_relaxed);
83
+ }
84
+
85
+ // A stream is closed when both reads and writes are closed.
86
+ bool IsClosed() const { return reads_closed() && writes_closed(); }
87
+
88
+ // A stream is idle if it has not started yet and has not been closed.
89
+ // Note: HTTP/2 does not allow direct transitions from Idle to Half-Closed
90
+ // states (it must go through Open first, which sets `started_` to true).
91
+ // The only transition from Idle for an unstarted stream is to Closed
92
+ // (e.g., via local cancellation). Thus, checking `!started() && !IsClosed()`
93
+ // is sufficient to identify the Idle state.
94
+ bool IsIdle() const { return !started() && !IsClosed(); }
95
+
96
+ bool IsOpen() const {
97
+ return started() && !reads_closed() && !writes_closed() &&
98
+ !half_closed_local();
99
+ }
100
+
101
+ bool IsHalfClosedRemote() const { return reads_closed() && !writes_closed(); }
102
+
103
+ bool IsHalfClosedLocal() const {
104
+ return !reads_closed() && half_closed_local();
105
+ }
106
+
107
+ bool IsHalfClosedLocalSent() const { return half_closed_local(); }
108
+
109
+ std::string DebugString() const {
110
+ return absl::StrCat(
111
+ "started:", started_, " reads_closed:", reads_closed_,
112
+ " half_closed_local:", half_closed_local_,
113
+ " writes_closed:", writes_closed_.load(std::memory_order_relaxed));
114
+ }
115
+
116
+ // Semantic state transitions
117
+ void OnInitialMetadataSent() {
118
+ GRPC_DCHECK(!started_);
119
+ started_ = true;
120
+ }
121
+
122
+ StreamStateChange OnHalfCloseSent() {
123
+ return RunTransition([this]() {
124
+ half_closed_local_ = true;
125
+ MaybeUpdateWritesClosed();
126
+ });
127
+ }
128
+
129
+ StreamStateChange OnTrailingMetadataReceived() {
130
+ return RunTransition([this]() {
131
+ reads_closed_ = true;
132
+ MaybeUpdateWritesClosed();
133
+ });
134
+ }
135
+
136
+ StreamStateChange OnHalfCloseReceived() {
137
+ return RunTransition([this]() { reads_closed_ = true; });
138
+ }
139
+
140
+ StreamStateChange OnResetReceived() {
141
+ return RunTransition([this]() {
142
+ reads_closed_ = true;
143
+ half_closed_local_ = true;
144
+ writes_closed_.store(true, std::memory_order_relaxed);
145
+ });
146
+ }
147
+
148
+ StreamStateChange OnResetSent() {
149
+ return RunTransition([this]() {
150
+ reads_closed_ = true;
151
+ half_closed_local_ = true;
152
+ writes_closed_.store(true, std::memory_order_relaxed);
153
+ });
154
+ }
155
+
156
+ StreamStateChange OnInitiateReset() {
157
+ return RunTransition([this]() { reads_closed_ = true; });
158
+ }
159
+
160
+ // Force setters for fallback/init errors
161
+ StreamStateChange ForceClose() {
162
+ return RunTransition([this]() {
163
+ reads_closed_ = true;
164
+ half_closed_local_ = true;
165
+ writes_closed_.store(true, std::memory_order_relaxed);
166
+ });
167
+ }
168
+
169
+ private:
170
+ template <typename F>
171
+ StreamStateChange RunTransition(F&& transition_func) {
172
+ const bool was_read_closed = reads_closed_;
173
+ const bool was_closed = IsClosed();
174
+
175
+ transition_func();
176
+ GRPC_HTTP2_STREAM_LOG << "StreamState transition from "
177
+ << "{reads_closed: " << was_read_closed
178
+ << ", closed: " << was_closed << "}"
179
+ << " to " << DebugString();
180
+ return {/*reads_became_closed=*/!was_read_closed && reads_closed(),
181
+ /*stream_became_closed=*/!was_closed && IsClosed()};
182
+ }
183
+
184
+ void MaybeUpdateWritesClosed() {
185
+ // Client: if we sent half close and peer closed reads, writes are closed.
186
+ // Server: half_closed_local_ is never explicitly set, so this function is
187
+ // mostly a no-op.
188
+ if (reads_closed_ && half_closed_local_) {
189
+ writes_closed_.store(true, std::memory_order_relaxed);
190
+ }
191
+ }
192
+
193
+ // Started is set to true when initial metadata has been sent on the wire.
194
+ // For client, this is when initial metadata has been sent on the wire. For
195
+ // server, this is when initial metadata has been received from the wire.
196
+ bool started_ = false;
197
+
198
+ // Has peer sent a frame notifying that no more frames will be sent (trailing
199
+ // metadata or RST or half close).
200
+ bool reads_closed_ = false;
201
+
202
+ // Has the transport sent a frame notifying peer that no more data frames will
203
+ // be sent (half close). Note: Client can still send RST after this point
204
+ // until writes are fully closed.
205
+ bool half_closed_local_ = false;
206
+
207
+ // Absolutely nothing can be sent for this stream now (after RST or after both
208
+ // half_close and reads_closed for client).
209
+ std::atomic<bool> writes_closed_{false};
64
210
  };
65
211
 
66
212
  // Managing the streams
@@ -70,12 +216,12 @@ class Stream : public RefCounted<Stream> {
70
216
  chttp2::TransportFlowControl& transport_flow_control)
71
217
  : flow_control_(&transport_flow_control),
72
218
  call_(std::move(call_handler)),
73
- is_write_closed_(false),
219
+ state_(/*started=*/false),
74
220
  stream_id_(kInvalidStreamId),
75
- stream_state_(HttpStreamState::kIdle),
76
221
  did_receive_initial_metadata_(false),
77
222
  did_receive_trailing_metadata_(false),
78
223
  did_push_server_trailing_metadata_(false),
224
+ did_cancel_(false),
79
225
  data_queue_(MakeRefCounted<StreamDataQueue<ClientMetadataHandle>>(
80
226
  std::get<CallHandler>(call_).arena(), /*is_client*/ true,
81
227
  /*queue_size*/ kStreamQueueSize)) {}
@@ -86,12 +232,12 @@ class Stream : public RefCounted<Stream> {
86
232
  const bool allow_true_binary_metadata_peer)
87
233
  : flow_control_(&transport_flow_control),
88
234
  call_(std::move(call_initiator)),
89
- is_write_closed_(false),
235
+ state_(/*started=*/true),
90
236
  stream_id_(stream_id),
91
- stream_state_(HttpStreamState::kIdle),
92
237
  did_receive_initial_metadata_(false),
93
238
  did_receive_trailing_metadata_(false),
94
239
  did_push_server_trailing_metadata_(false),
240
+ did_cancel_(false),
95
241
  data_queue_(MakeRefCounted<StreamDataQueue<ClientMetadataHandle>>(
96
242
  std::get<CallInitiator>(call_).arena(), /*is_client*/ false,
97
243
  /*queue_size*/ kStreamQueueSize)) {
@@ -103,15 +249,9 @@ class Stream : public RefCounted<Stream> {
103
249
  Stream& operator=(const Stream&) = delete;
104
250
  Stream& operator=(Stream&&) = delete;
105
251
 
106
- // TODO(akshitpatel) : [PH2][P4] : SetStreamId can be avoided if we pass the
107
- // stream id as a parameter to the dequeue function. The only downside here
108
- // is that we will be creating two new disassemblers for every dequeue call.
109
- // The upside is that we save 8 bytes per call. Decide based on benchmark
110
- // results.
111
252
  void InitializeClientStream(const uint32_t stream_id,
112
253
  const bool allow_true_binary_metadata_peer) {
113
- GRPC_DCHECK(std::holds_alternative<CallHandler>(call_))
114
- << "Client Only Function";
254
+ GRPC_DCHECK(is_client()) << "Client Only Function";
115
255
  GRPC_DCHECK_NE(stream_id, 0u);
116
256
  GRPC_DCHECK_EQ(this->stream_id_, 0u);
117
257
  GRPC_HTTP2_STREAM_LOG << "Stream::InitializeClientStream stream_id="
@@ -148,7 +288,7 @@ class Stream : public RefCounted<Stream> {
148
288
  }
149
289
 
150
290
  auto EnqueueHalfClosed() {
151
- GRPC_DCHECK(std::holds_alternative<CallHandler>(call_));
291
+ GRPC_DCHECK(is_client());
152
292
  GRPC_HTTP2_STREAM_LOG << "Stream::EnqueueHalfClosed";
153
293
  return data_queue_->EnqueueHalfClosed();
154
294
  }
@@ -164,14 +304,12 @@ class Stream : public RefCounted<Stream> {
164
304
  const uint32_t stream_flow_control_tokens,
165
305
  const uint32_t max_frame_length, HPackCompressor& encoder,
166
306
  FrameSender& frame_sender) {
167
- HttpStreamState state = stream_state_;
168
307
  // Reset stream MUST not be sent if the stream is idle or closed.
169
308
  return data_queue_->DequeueFrames(tokens, max_frame_length,
170
309
  stream_flow_control_tokens, encoder,
171
310
  frame_sender,
172
311
  /*can_send_reset_stream=*/
173
- !(state == HttpStreamState::kIdle ||
174
- state == HttpStreamState::kClosed));
312
+ !(IsStreamIdle() || IsStreamClosed()));
175
313
  }
176
314
 
177
315
  auto UpdateStreamWritability(const int64_t stream_fc_tokens) {
@@ -180,105 +318,91 @@ class Stream : public RefCounted<Stream> {
180
318
 
181
319
  ////////////////////////////////////////////////////////////////////////////
182
320
  // Stream State Management
183
- // All state management helpers MUST be called from the transport party.
184
-
185
- // Modify the stream state
186
- // The possible stream transitions are as follows:
187
- // kIdle -> kOpen
188
- // kOpen -> kClosed/kHalfClosedLocal/kHalfClosedRemote
189
- // kHalfClosedLocal/kHalfClosedRemote -> kClosed
190
- // kClosed -> kClosed
191
- void SentInitialMetadata() {
192
- GRPC_DCHECK(stream_state_ == HttpStreamState::kIdle);
193
- stream_state_ = HttpStreamState::kOpen;
194
- }
195
- void SentTrailingMetadata() {
196
- GRPC_DCHECK(stream_state_ != HttpStreamState::kClosed ||
197
- stream_state_ != HttpStreamState::kHalfClosedLocal)
198
- << "Cannot send trailing metadata in closed or half closed local state";
199
- stream_state_ = HttpStreamState::kClosed;
200
- }
201
-
202
- void MarkHalfClosedLocal() {
203
- switch (stream_state_) {
204
- case HttpStreamState::kIdle:
205
- GRPC_DCHECK(false) << "MarkHalfClosedLocal called for an idle stream";
206
- break;
207
- case HttpStreamState::kOpen:
208
- GRPC_HTTP2_STREAM_LOG
209
- << "Stream::MarkHalfClosedLocal stream_id=" << stream_id_
210
- << " transitioning to kHalfClosedLocal";
211
- stream_state_ = HttpStreamState::kHalfClosedLocal;
212
- break;
213
- case HttpStreamState::kHalfClosedRemote:
214
- GRPC_HTTP2_STREAM_LOG
215
- << "Stream::MarkHalfClosedLocal stream_id=" << stream_id_
216
- << " transitioning to kClosed";
217
- stream_state_ = HttpStreamState::kClosed;
218
- break;
219
- case HttpStreamState::kHalfClosedLocal:
220
- break;
221
- case HttpStreamState::kClosed:
222
- GRPC_HTTP2_STREAM_LOG
223
- << "Stream::MarkHalfClosedLocal stream_id=" << stream_id_
224
- << " already closed";
225
- break;
226
- }
321
+ // All state management helpers, MUST be called from the transport party.
322
+
323
+ // HTTP/2 stream states
324
+ bool IsStreamIdle() const { return state_.IsIdle(); }
325
+ bool IsOpen() const { return state_.IsOpen(); }
326
+ bool IsStreamClosed() const { return state_.IsClosed(); }
327
+ bool IsStreamHalfClosedRemote() const { return state_.IsHalfClosedRemote(); }
328
+ bool IsHalfClosedLocal() const { return state_.IsHalfClosedLocal(); }
329
+ bool IsHalfClosedLocalSent() const { return state_.IsHalfClosedLocalSent(); }
330
+
331
+ // gRPC stream state
332
+ bool IsClosedForReads() const { return state_.reads_closed(); }
333
+ bool IsClosedForWrites() const { return state_.writes_closed(); }
334
+
335
+ // Semantic state transitions
336
+ void OnInitialMetadataSent() {
337
+ GRPC_DCHECK(is_client());
338
+ state_.OnInitialMetadataSent();
227
339
  }
228
340
 
229
- void MarkHalfClosedRemote() {
230
- switch (stream_state_) {
231
- case HttpStreamState::kIdle:
232
- GRPC_DCHECK(false) << "MarkHalfClosedRemote called for an idle stream";
233
- break;
234
- case HttpStreamState::kOpen:
235
- GRPC_HTTP2_STREAM_LOG
236
- << "Stream::MarkHalfClosedRemote stream_id=" << stream_id_
237
- << " transitioning to kHalfClosedRemote";
238
- stream_state_ = HttpStreamState::kHalfClosedRemote;
239
- break;
240
- case HttpStreamState::kHalfClosedLocal:
241
- GRPC_HTTP2_STREAM_LOG
242
- << "Stream::MarkHalfClosedRemote stream_id=" << stream_id_
243
- << " transitioning to kClosed";
244
- stream_state_ = HttpStreamState::kClosed;
245
- break;
246
- case HttpStreamState::kHalfClosedRemote:
247
- break;
248
- case HttpStreamState::kClosed:
249
- GRPC_HTTP2_STREAM_LOG
250
- << "Stream::MarkHalfClosedRemote stream_id=" << stream_id_
251
- << " already closed";
252
- break;
253
- }
341
+ StreamStateChange OnHalfCloseSent() {
342
+ GRPC_DCHECK(is_client());
343
+ return state_.OnHalfCloseSent();
254
344
  }
255
345
 
256
- inline bool IsStreamIdle() const {
257
- return stream_state_ == HttpStreamState::kIdle;
258
- }
259
- inline bool IsStreamHalfClosedRemote() const {
260
- return stream_state_ == HttpStreamState::kHalfClosedRemote;
346
+ StreamStateChange OnTrailingMetadataReceived(ServerMetadataHandle metadata) {
347
+ SetTrailingMetadataReceived();
348
+ const StreamStateChange change = state_.OnTrailingMetadataReceived();
349
+ if (is_client()) {
350
+ MaybePushServerTrailingMetadata(std::move(metadata));
351
+ } else {
352
+ // Server: custom HTTP2 implementations might send trailing metadata.
353
+ // We just close reads and do nothing else (upper layers discard client
354
+ // trailers).
355
+ GRPC_HTTP2_STREAM_LOG << "Stream::OnTrailingMetadataReceived Server "
356
+ "stream_id="
357
+ << stream_id_
358
+ << " StreamStateChange=" << change.DebugString();
359
+ if (change.reads_became_closed) {
360
+ GetCallInitiator().SpawnFinishSends();
361
+ }
362
+ }
363
+ return change;
261
364
  }
262
- inline bool IsHalfClosedLocal() const {
263
- return stream_state_ == HttpStreamState::kHalfClosedLocal;
365
+
366
+ StreamStateChange OnHalfCloseReceived() {
367
+ GRPC_DCHECK(is_server());
368
+ const StreamStateChange change = state_.OnHalfCloseReceived();
369
+ if (change.reads_became_closed) {
370
+ GetCallInitiator().SpawnFinishSends();
371
+ }
372
+ return change;
264
373
  }
265
- inline bool IsStreamClosed() const {
266
- return stream_state_ == HttpStreamState::kClosed;
374
+
375
+ StreamStateChange OnResetReceived(absl::Status status) {
376
+ const StreamStateChange change = state_.OnResetReceived();
377
+ CancelCall(std::move(status));
378
+ return change;
267
379
  }
268
380
 
269
- inline uint32_t GetStreamId() const { return stream_id_; }
381
+ StreamStateChange OnResetSent() {
382
+ const StreamStateChange change = state_.OnResetSent();
270
383
 
271
- inline bool IsClosedForWrites() const {
272
- return is_write_closed_.load(std::memory_order_relaxed);
384
+ // Fallback cancel. Safe even for normal completion as CallSpine would have
385
+ // already processed trailing metadata, making Cancel a no-op.
386
+ CancelCall(absl::CancelledError("RST stream sent"));
387
+ return change;
273
388
  }
274
389
 
275
- inline void SetWriteClosed() {
276
- is_write_closed_.store(true, std::memory_order_relaxed);
390
+ StreamStateChange OnInitiateReset(absl::Status status) {
391
+ const StreamStateChange change = state_.OnInitiateReset();
392
+ CancelCall(std::move(status));
393
+ return change;
277
394
  }
278
395
 
396
+ StreamStateChange ForceClose(absl::Status status) {
397
+ const StreamStateChange change = state_.ForceClose();
398
+ CancelCall(std::move(status));
399
+ return change;
400
+ }
401
+
402
+ inline uint32_t GetStreamId() const { return stream_id_; }
403
+
279
404
  inline bool CanSendWindowUpdateFrames() const {
280
- return stream_state_ == HttpStreamState::kOpen ||
281
- stream_state_ == HttpStreamState::kHalfClosedLocal;
405
+ return IsOpen() || IsHalfClosedLocal();
282
406
  }
283
407
 
284
408
  inline Http2Status CanStreamReceiveDataFrames() const {
@@ -296,7 +420,7 @@ class Stream : public RefCounted<Stream> {
296
420
  }
297
421
 
298
422
  void MaybePushServerTrailingMetadata(ServerMetadataHandle&& metadata) {
299
- GRPC_DCHECK(std::holds_alternative<CallHandler>(call_));
423
+ GRPC_DCHECK(is_client());
300
424
  GRPC_HTTP2_STREAM_LOG << "Stream::MaybePushServerTrailingMetadata "
301
425
  "stream_id="
302
426
  << stream_id_
@@ -330,20 +454,45 @@ class Stream : public RefCounted<Stream> {
330
454
  return std::get<CallHandler>(call_);
331
455
  }
332
456
 
457
+ GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION const CallHandler& GetCallHandler()
458
+ const {
459
+ return std::get<CallHandler>(call_);
460
+ }
461
+
333
462
  GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION CallInitiator& GetCallInitiator() {
334
463
  return std::get<CallInitiator>(call_);
335
464
  }
336
465
 
466
+ GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION const CallInitiator& GetCallInitiator()
467
+ const {
468
+ return std::get<CallInitiator>(call_);
469
+ }
470
+
337
471
  GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION GrpcMessageAssembler&
338
472
  GetGrpcMessageAssembler() {
339
473
  return assembler_;
340
474
  }
341
475
 
476
+ GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION const GrpcMessageAssembler&
477
+ GetGrpcMessageAssembler() const {
478
+ return assembler_;
479
+ }
480
+
342
481
  GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION chttp2::StreamFlowControl&
343
482
  GetStreamFlowControl() {
344
483
  return flow_control_;
345
484
  }
346
485
 
486
+ GPR_ATTRIBUTE_ALWAYS_INLINE_FUNCTION const chttp2::StreamFlowControl&
487
+ GetStreamFlowControl() const {
488
+ return flow_control_;
489
+ }
490
+
491
+ bool is_client() const { return std::holds_alternative<CallHandler>(call_); }
492
+ bool is_server() const {
493
+ return std::holds_alternative<CallInitiator>(call_);
494
+ }
495
+
347
496
  private:
348
497
  void InitializeStream(const bool allow_true_binary_metadata_peer) {
349
498
  GRPC_HTTP2_STREAM_LOG << "Stream::InitializeStream stream_id="
@@ -356,21 +505,23 @@ class Stream : public RefCounted<Stream> {
356
505
  chttp2::StreamFlowControl flow_control_;
357
506
  std::variant<CallInitiator, CallHandler> call_;
358
507
 
359
- // This flag is kept separate from the stream_state as the stream_state
360
- // is inline with the HTTP2 spec, whereas this flag is an implementation
361
- // detail of the PH2 transport. As far as PH2 is concerned, if a stream is
362
- // closed for writes, it will not send any more frames on that stream.
363
- // Similarly if a stream is closed for reads(this is achieved by removing the
364
- // stream from the transport map), then all the frames read on that stream
365
- // will be dropped.
366
- std::atomic<bool> is_write_closed_;
367
- uint32_t stream_id_;
508
+ // This function is idempotent.
509
+ void CancelCall(absl::Status&& status) {
510
+ if (std::exchange(did_cancel_, true)) return;
511
+ if (is_client()) {
512
+ MaybePushServerTrailingMetadata(
513
+ CancelledServerMetadataFromStatus(status));
514
+ } else {
515
+ GetCallInitiator().SpawnCancel(std::forward<absl::Status>(status));
516
+ }
517
+ }
368
518
 
369
- // This MUST be accessed from the transport party.
370
- HttpStreamState stream_state_;
519
+ StreamState state_;
520
+ uint32_t stream_id_;
371
521
  bool did_receive_initial_metadata_;
372
522
  bool did_receive_trailing_metadata_;
373
523
  bool did_push_server_trailing_metadata_;
524
+ bool did_cancel_;
374
525
  // Change this if ClientMetadataHandle and ServerMetadataHandle are changed
375
526
  // to different types.
376
527
  RefCountedPtr<StreamDataQueue<Arena::PoolPtr<grpc_metadata_batch>>>