grpc 1.59.0 → 1.59.2

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 (26) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +7 -1
  3. data/src/core/ext/filters/http/server/http_server_filter.cc +21 -17
  4. data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +504 -361
  5. data/src/core/ext/transport/chttp2/transport/frame_ping.cc +11 -1
  6. data/src/core/ext/transport/chttp2/transport/frame_rst_stream.cc +9 -0
  7. data/src/core/ext/transport/chttp2/transport/internal.h +92 -28
  8. data/src/core/ext/transport/chttp2/transport/max_concurrent_streams_policy.cc +44 -0
  9. data/src/core/ext/transport/chttp2/transport/max_concurrent_streams_policy.h +67 -0
  10. data/src/core/ext/transport/chttp2/transport/parsing.cc +103 -14
  11. data/src/core/ext/transport/chttp2/transport/ping_callbacks.cc +108 -0
  12. data/src/core/ext/transport/chttp2/transport/ping_callbacks.h +115 -0
  13. data/src/core/ext/transport/chttp2/transport/ping_rate_policy.cc +26 -4
  14. data/src/core/ext/transport/chttp2/transport/ping_rate_policy.h +16 -1
  15. data/src/core/ext/transport/chttp2/transport/write_size_policy.cc +60 -0
  16. data/src/core/ext/transport/chttp2/transport/write_size_policy.h +66 -0
  17. data/src/core/ext/transport/chttp2/transport/writing.cc +149 -77
  18. data/src/core/lib/channel/promise_based_filter.cc +9 -4
  19. data/src/core/lib/channel/promise_based_filter.h +2 -1
  20. data/src/core/lib/experiments/experiments.cc +222 -0
  21. data/src/core/lib/experiments/experiments.h +135 -0
  22. data/src/core/lib/iomgr/combiner.cc +3 -0
  23. data/src/core/lib/transport/metadata_batch.h +11 -1
  24. data/src/core/lib/transport/transport.h +6 -0
  25. data/src/ruby/lib/grpc/version.rb +1 -1
  26. metadata +9 -3
@@ -20,6 +20,7 @@
20
20
 
21
21
  #include "src/core/ext/transport/chttp2/transport/frame_ping.h"
22
22
 
23
+ #include <inttypes.h>
23
24
  #include <string.h>
24
25
 
25
26
  #include <algorithm>
@@ -35,6 +36,7 @@
35
36
 
36
37
  #include "src/core/ext/transport/chttp2/transport/internal.h"
37
38
  #include "src/core/ext/transport/chttp2/transport/ping_abuse_policy.h"
39
+ #include "src/core/ext/transport/chttp2/transport/ping_callbacks.h"
38
40
  #include "src/core/lib/debug/trace.h"
39
41
 
40
42
  extern grpc_core::TraceFlag grpc_keepalive_trace;
@@ -96,18 +98,26 @@ grpc_error_handle grpc_chttp2_ping_parser_parse(void* parser,
96
98
  if (p->byte == 8) {
97
99
  GPR_ASSERT(is_last);
98
100
  if (p->is_ack) {
101
+ if (grpc_ping_trace.enabled()) {
102
+ gpr_log(GPR_INFO, "%s[%p]: received ping ack %" PRIx64,
103
+ t->is_client ? "CLIENT" : "SERVER", t, p->opaque_8bytes);
104
+ }
99
105
  grpc_chttp2_ack_ping(t, p->opaque_8bytes);
100
106
  } else {
101
107
  if (!t->is_client) {
102
108
  const bool transport_idle =
103
109
  t->keepalive_permit_without_calls == 0 && t->stream_map.empty();
104
110
  if (grpc_keepalive_trace.enabled() || grpc_http_trace.enabled()) {
105
- gpr_log(GPR_INFO, "t=%p received ping: %s", t,
111
+ gpr_log(GPR_INFO, "SERVER[%p]: received ping %" PRIx64 ": %s", t,
112
+ p->opaque_8bytes,
106
113
  t->ping_abuse_policy.GetDebugString(transport_idle).c_str());
107
114
  }
108
115
  if (t->ping_abuse_policy.ReceivedOnePing(transport_idle)) {
109
116
  grpc_chttp2_exceeded_ping_strikes(t);
110
117
  }
118
+ } else if (grpc_ping_trace.enabled()) {
119
+ gpr_log(GPR_INFO, "CLIENT[%p]: received ping %" PRIx64, t,
120
+ p->opaque_8bytes);
111
121
  }
112
122
  if (t->ack_pings) {
113
123
  if (t->ping_ack_count == t->ping_ack_capacity) {
@@ -24,6 +24,7 @@
24
24
 
25
25
  #include <initializer_list>
26
26
 
27
+ #include "absl/random/distributions.h"
27
28
  #include "absl/status/status.h"
28
29
  #include "absl/strings/str_cat.h"
29
30
  #include "absl/strings/str_format.h"
@@ -34,7 +35,9 @@
34
35
  #include "src/core/ext/transport/chttp2/transport/http_trace.h"
35
36
  #include "src/core/ext/transport/chttp2/transport/internal.h"
36
37
  #include "src/core/ext/transport/chttp2/transport/legacy_frame.h"
38
+ #include "src/core/ext/transport/chttp2/transport/ping_callbacks.h"
37
39
  #include "src/core/lib/debug/trace.h"
40
+ #include "src/core/lib/experiments/experiments.h"
38
41
  #include "src/core/lib/gprpp/status_helper.h"
39
42
  #include "src/core/lib/transport/http2_errors.h"
40
43
  #include "src/core/lib/transport/metadata_batch.h"
@@ -125,6 +128,12 @@ grpc_error_handle grpc_chttp2_rst_stream_parser_parse(void* parser,
125
128
  grpc_core::StatusIntProperty::kHttp2Error,
126
129
  static_cast<intptr_t>(reason));
127
130
  }
131
+ if (grpc_core::IsPingOnRstStreamEnabled() && !t->is_client &&
132
+ absl::Bernoulli(t->bitgen, t->ping_on_rst_stream_percent / 100.0)) {
133
+ ++t->num_pending_induced_frames;
134
+ t->ping_callbacks.RequestPing();
135
+ grpc_chttp2_initiate_write(t, GRPC_CHTTP2_INITIATE_WRITE_KEEPALIVE_PING);
136
+ }
128
137
  grpc_chttp2_mark_stream_closed(t, s, true, true, error);
129
138
  }
130
139
 
@@ -24,13 +24,17 @@
24
24
  #include <stddef.h>
25
25
  #include <stdint.h>
26
26
 
27
+ #include <atomic>
27
28
  #include <memory>
29
+ #include <utility>
28
30
 
29
31
  #include "absl/container/flat_hash_map.h"
30
32
  #include "absl/meta/type_traits.h"
31
33
  #include "absl/random/random.h"
34
+ #include "absl/status/status.h"
32
35
  #include "absl/strings/string_view.h"
33
36
  #include "absl/types/optional.h"
37
+ #include "absl/types/variant.h"
34
38
 
35
39
  #include <grpc/event_engine/event_engine.h>
36
40
  #include <grpc/event_engine/memory_allocator.h>
@@ -49,8 +53,11 @@
49
53
  #include "src/core/ext/transport/chttp2/transport/hpack_parser.h"
50
54
  #include "src/core/ext/transport/chttp2/transport/http2_settings.h"
51
55
  #include "src/core/ext/transport/chttp2/transport/legacy_frame.h"
56
+ #include "src/core/ext/transport/chttp2/transport/max_concurrent_streams_policy.h"
52
57
  #include "src/core/ext/transport/chttp2/transport/ping_abuse_policy.h"
58
+ #include "src/core/ext/transport/chttp2/transport/ping_callbacks.h"
53
59
  #include "src/core/ext/transport/chttp2/transport/ping_rate_policy.h"
60
+ #include "src/core/ext/transport/chttp2/transport/write_size_policy.h"
54
61
  #include "src/core/lib/channel/channel_args.h"
55
62
  #include "src/core/lib/channel/channelz.h"
56
63
  #include "src/core/lib/debug/trace.h"
@@ -145,18 +152,6 @@ typedef enum {
145
152
  const char* grpc_chttp2_initiate_write_reason_string(
146
153
  grpc_chttp2_initiate_write_reason reason);
147
154
 
148
- struct grpc_chttp2_ping_queue {
149
- grpc_closure_list lists[GRPC_CHTTP2_PCL_COUNT] = {};
150
- uint64_t inflight_id = 0;
151
- };
152
-
153
- struct grpc_chttp2_repeated_ping_state {
154
- grpc_core::Timestamp last_ping_sent_time;
155
- int pings_before_data_required;
156
- absl::optional<grpc_event_engine::experimental::EventEngine::TaskHandle>
157
- delayed_ping_timer_handle;
158
- };
159
-
160
155
  // deframer state for the overall http2 stream of bytes
161
156
  typedef enum {
162
157
  // prefix: one entry per http2 connection prefix byte
@@ -283,6 +278,31 @@ struct grpc_chttp2_transport : public grpc_core::KeepsGrpcInitialized {
283
278
 
284
279
  /// maps stream id to grpc_chttp2_stream objects
285
280
  absl::flat_hash_map<uint32_t, grpc_chttp2_stream*> stream_map;
281
+ // Count of streams that should be counted against max concurrent streams but
282
+ // are not in stream_map (due to tarpitting).
283
+ size_t extra_streams = 0;
284
+
285
+ class RemovedStreamHandle {
286
+ public:
287
+ RemovedStreamHandle() = default;
288
+ explicit RemovedStreamHandle(
289
+ grpc_core::RefCountedPtr<grpc_chttp2_transport> t)
290
+ : transport_(std::move(t)) {
291
+ ++transport_->extra_streams;
292
+ }
293
+ ~RemovedStreamHandle() {
294
+ if (transport_ != nullptr) {
295
+ --transport_->extra_streams;
296
+ }
297
+ }
298
+ RemovedStreamHandle(const RemovedStreamHandle&) = delete;
299
+ RemovedStreamHandle& operator=(const RemovedStreamHandle&) = delete;
300
+ RemovedStreamHandle(RemovedStreamHandle&&) = default;
301
+ RemovedStreamHandle& operator=(RemovedStreamHandle&&) = default;
302
+
303
+ private:
304
+ grpc_core::RefCountedPtr<grpc_chttp2_transport> transport_;
305
+ };
286
306
 
287
307
  grpc_closure write_action_begin_locked;
288
308
  grpc_closure write_action;
@@ -311,13 +331,15 @@ struct grpc_chttp2_transport : public grpc_core::KeepsGrpcInitialized {
311
331
  grpc_core::ConnectivityStateTracker state_tracker;
312
332
 
313
333
  /// data to write now
314
- grpc_slice_buffer outbuf;
334
+ grpc_core::SliceBuffer outbuf;
315
335
  /// hpack encoding
316
336
  grpc_core::HPackCompressor hpack_compressor;
317
337
 
318
338
  /// data to write next write
319
339
  grpc_slice_buffer qbuf;
320
340
 
341
+ size_t max_requests_per_read;
342
+
321
343
  /// Set to a grpc_error object if a goaway frame is received. By default, set
322
344
  /// to absl::OkStatus()
323
345
  grpc_error_handle goaway_error;
@@ -331,6 +353,10 @@ struct grpc_chttp2_transport : public grpc_core::KeepsGrpcInitialized {
331
353
  /// settings values
332
354
  uint32_t settings[GRPC_NUM_SETTING_SETS][GRPC_CHTTP2_NUM_SETTINGS];
333
355
 
356
+ grpc_event_engine::experimental::EventEngine::TaskHandle
357
+ settings_ack_watchdog =
358
+ grpc_event_engine::experimental::EventEngine::TaskHandle::kInvalid;
359
+
334
360
  /// what is the next stream id to be allocated by this peer?
335
361
  /// copied to next_stream_id in parsing when parsing commences
336
362
  uint32_t next_stream_id = 0;
@@ -338,15 +364,19 @@ struct grpc_chttp2_transport : public grpc_core::KeepsGrpcInitialized {
338
364
  /// last new stream id
339
365
  uint32_t last_new_stream_id = 0;
340
366
 
367
+ /// Number of incoming streams allowed before a settings ACK is required
368
+ uint32_t num_incoming_streams_before_settings_ack = 0;
369
+
341
370
  /// ping queues for various ping insertion points
342
- grpc_chttp2_ping_queue ping_queue = grpc_chttp2_ping_queue();
343
371
  grpc_core::Chttp2PingAbusePolicy ping_abuse_policy;
344
372
  grpc_core::Chttp2PingRatePolicy ping_rate_policy;
373
+ grpc_core::Chttp2PingCallbacks ping_callbacks;
345
374
  absl::optional<grpc_event_engine::experimental::EventEngine::TaskHandle>
346
375
  delayed_ping_timer_handle;
347
- uint64_t ping_ctr = 0; // unique id for pings
348
376
  grpc_closure retry_initiate_ping_locked;
349
377
 
378
+ grpc_core::Chttp2MaxConcurrentStreamsPolicy max_concurrent_streams_policy;
379
+
350
380
  /// ping acks
351
381
  size_t ping_ack_count = 0;
352
382
  size_t ping_ack_capacity = 0;
@@ -379,6 +409,10 @@ struct grpc_chttp2_transport : public grpc_core::KeepsGrpcInitialized {
379
409
  uint32_t expect_continuation_stream_id = 0;
380
410
  uint32_t incoming_frame_size = 0;
381
411
 
412
+ int min_tarpit_duration_ms;
413
+ int max_tarpit_duration_ms;
414
+ bool allow_tarpit;
415
+
382
416
  grpc_chttp2_stream* incoming_stream = nullptr;
383
417
  // active parser
384
418
  struct Parser {
@@ -425,13 +459,13 @@ struct grpc_chttp2_transport : public grpc_core::KeepsGrpcInitialized {
425
459
  /// timer to initiate ping events
426
460
  absl::optional<grpc_event_engine::experimental::EventEngine::TaskHandle>
427
461
  keepalive_ping_timer_handle;
428
- /// watchdog to kill the transport when waiting for the keepalive ping
429
- absl::optional<grpc_event_engine::experimental::EventEngine::TaskHandle>
430
- keepalive_watchdog_timer_handle;
431
462
  /// time duration in between pings
432
463
  grpc_core::Duration keepalive_time;
433
- /// grace period for a ping to complete before watchdog kicks in
464
+ /// grace period to wait for data after sending a ping before keepalives
465
+ /// timeout
434
466
  grpc_core::Duration keepalive_timeout;
467
+ /// number of stream objects currently allocated by this transport
468
+ std::atomic<size_t> streams_allocated{0};
435
469
  /// keep-alive state machine state
436
470
  grpc_chttp2_keepalive_state keepalive_state;
437
471
  // Soft limit on max header size.
@@ -447,10 +481,20 @@ struct grpc_chttp2_transport : public grpc_core::KeepsGrpcInitialized {
447
481
  uint32_t num_pending_induced_frames = 0;
448
482
  uint32_t incoming_stream_id = 0;
449
483
 
484
+ /// grace period after sending a ping to wait for the ping ack
485
+ grpc_core::Duration ping_timeout;
486
+ grpc_event_engine::experimental::EventEngine::TaskHandle
487
+ keepalive_ping_timeout_handle =
488
+ grpc_event_engine::experimental::EventEngine::TaskHandle::kInvalid;
489
+ /// grace period before settings timeout expires
490
+ grpc_core::Duration settings_timeout;
491
+
450
492
  /// how much data are we willing to buffer when the WRITE_BUFFER_HINT is set?
451
- ///
452
493
  uint32_t write_buffer_size = grpc_core::chttp2::kDefaultWindow;
453
494
 
495
+ /// policy for how much data we're willing to put into one http2 write
496
+ grpc_core::Chttp2WriteSizePolicy write_size_policy;
497
+
454
498
  bool reading_paused_on_pending_induced_frames = false;
455
499
  /// Based on channel args, preferred_rx_crypto_frame_sizes are advertised to
456
500
  /// the peer
@@ -492,6 +536,12 @@ struct grpc_chttp2_transport : public grpc_core::KeepsGrpcInitialized {
492
536
  bool bdp_ping_started = false;
493
537
  // True if pings should be acked
494
538
  bool ack_pings = true;
539
+ /// True if the keepalive system wants to see some data incoming
540
+ bool keepalive_incoming_data_wanted = false;
541
+
542
+ // What percentage of rst_stream frames on the server should cause a ping
543
+ // frame to be generated.
544
+ uint8_t ping_on_rst_stream_percent;
495
545
 
496
546
  /// write execution state of the transport
497
547
  grpc_chttp2_write_state write_state = GRPC_CHTTP2_WRITE_STATE_IDLE;
@@ -618,6 +668,8 @@ struct grpc_chttp2_stream {
618
668
  bool traced = false;
619
669
  };
620
670
 
671
+ #define GRPC_ARG_PING_TIMEOUT_MS "grpc.http2.ping_timeout_ms"
672
+
621
673
  /// Transport writing call flow:
622
674
  /// grpc_chttp2_initiate_write() is called anywhere that we know bytes need to
623
675
  /// go out on the wire.
@@ -645,10 +697,14 @@ grpc_chttp2_begin_write_result grpc_chttp2_begin_write(
645
697
  grpc_chttp2_transport* t);
646
698
  void grpc_chttp2_end_write(grpc_chttp2_transport* t, grpc_error_handle error);
647
699
 
648
- /// Process one slice of incoming data; return 1 if the connection is still
649
- /// viable after reading, or 0 if the connection should be torn down
650
- grpc_error_handle grpc_chttp2_perform_read(grpc_chttp2_transport* t,
651
- const grpc_slice& slice);
700
+ /// Process one slice of incoming data
701
+ /// Returns:
702
+ /// - a count of parsed bytes in the event of a partial read: the caller should
703
+ /// offload responsibilities to another thread to continue parsing.
704
+ /// - or a status in the case of a completed read
705
+ absl::variant<size_t, absl::Status> grpc_chttp2_perform_read(
706
+ grpc_chttp2_transport* t, const grpc_slice& slice,
707
+ size_t& requests_started);
652
708
 
653
709
  bool grpc_chttp2_list_add_writable_stream(grpc_chttp2_transport* t,
654
710
  grpc_chttp2_stream* s);
@@ -723,6 +779,14 @@ void grpc_chttp2_complete_closure_step(grpc_chttp2_transport* t,
723
779
  const char* desc,
724
780
  grpc_core::DebugLocation whence = {});
725
781
 
782
+ void grpc_chttp2_keepalive_timeout(
783
+ grpc_core::RefCountedPtr<grpc_chttp2_transport> t);
784
+ void grpc_chttp2_ping_timeout(
785
+ grpc_core::RefCountedPtr<grpc_chttp2_transport> t);
786
+
787
+ void grpc_chttp2_settings_timeout(
788
+ grpc_core::RefCountedPtr<grpc_chttp2_transport> t);
789
+
726
790
  #define GRPC_HEADER_SIZE_IN_BYTES 5
727
791
  #define MAX_SIZE_T (~(size_t)0)
728
792
 
@@ -742,9 +806,9 @@ void grpc_chttp2_complete_closure_step(grpc_chttp2_transport* t,
742
806
  void grpc_chttp2_fake_status(grpc_chttp2_transport* t,
743
807
  grpc_chttp2_stream* stream,
744
808
  grpc_error_handle error);
745
- void grpc_chttp2_mark_stream_closed(grpc_chttp2_transport* t,
746
- grpc_chttp2_stream* s, int close_reads,
747
- int close_writes, grpc_error_handle error);
809
+ grpc_chttp2_transport::RemovedStreamHandle grpc_chttp2_mark_stream_closed(
810
+ grpc_chttp2_transport* t, grpc_chttp2_stream* s, int close_reads,
811
+ int close_writes, grpc_error_handle error);
748
812
  void grpc_chttp2_start_writing(grpc_chttp2_transport* t);
749
813
 
750
814
  #ifndef NDEBUG
@@ -780,7 +844,7 @@ void grpc_chttp2_mark_stream_writable(grpc_chttp2_transport* t,
780
844
  grpc_chttp2_stream* s);
781
845
 
782
846
  void grpc_chttp2_cancel_stream(grpc_chttp2_transport* t, grpc_chttp2_stream* s,
783
- grpc_error_handle due_to_error);
847
+ grpc_error_handle due_to_error, bool tarpit);
784
848
 
785
849
  void grpc_chttp2_maybe_complete_recv_initial_metadata(grpc_chttp2_transport* t,
786
850
  grpc_chttp2_stream* s);
@@ -0,0 +1,44 @@
1
+ // Copyright 2023 gRPC authors.
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ #include <grpc/support/port_platform.h>
16
+
17
+ #include "src/core/ext/transport/chttp2/transport/max_concurrent_streams_policy.h"
18
+
19
+ #include <utility>
20
+
21
+ #include <grpc/support/log.h>
22
+
23
+ namespace grpc_core {
24
+
25
+ void Chttp2MaxConcurrentStreamsPolicy::AddDemerit() {
26
+ ++new_demerits_;
27
+ ++unacked_demerits_;
28
+ }
29
+
30
+ void Chttp2MaxConcurrentStreamsPolicy::FlushedSettings() {
31
+ sent_demerits_ += std::exchange(new_demerits_, 0);
32
+ }
33
+
34
+ void Chttp2MaxConcurrentStreamsPolicy::AckLastSend() {
35
+ GPR_ASSERT(unacked_demerits_ >= sent_demerits_);
36
+ unacked_demerits_ -= std::exchange(sent_demerits_, 0);
37
+ }
38
+
39
+ uint32_t Chttp2MaxConcurrentStreamsPolicy::AdvertiseValue() const {
40
+ if (target_ < unacked_demerits_) return 0;
41
+ return target_ - unacked_demerits_;
42
+ }
43
+
44
+ } // namespace grpc_core
@@ -0,0 +1,67 @@
1
+ // Copyright 2023 gRPC authors.
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ #ifndef GRPC_SRC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_MAX_CONCURRENT_STREAMS_POLICY_H
16
+ #define GRPC_SRC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_MAX_CONCURRENT_STREAMS_POLICY_H
17
+
18
+ #include <grpc/support/port_platform.h>
19
+
20
+ #include <cstdint>
21
+ #include <limits>
22
+
23
+ namespace grpc_core {
24
+
25
+ class Chttp2MaxConcurrentStreamsPolicy {
26
+ public:
27
+ // Set the target number of concurrent streams.
28
+ // If everything is idle we should advertise this number.
29
+ void SetTarget(uint32_t target) { target_ = target; }
30
+
31
+ // Add one demerit to the current target.
32
+ // We need to do one full settings round trip after this to clear this
33
+ // demerit.
34
+ // It will reduce our advertised max concurrent streams by one.
35
+ void AddDemerit();
36
+
37
+ // Notify the policy that we've sent a settings frame.
38
+ // Newly added demerits since the last settings frame was sent will be cleared
39
+ // once that settings frame is acknowledged.
40
+ void FlushedSettings();
41
+
42
+ // Notify the policy that we've received an acknowledgement for the last
43
+ // settings frame we sent.
44
+ void AckLastSend();
45
+
46
+ // Returns what we should advertise as max concurrent streams.
47
+ uint32_t AdvertiseValue() const;
48
+
49
+ private:
50
+ uint32_t target_ = std::numeric_limits<int32_t>::max();
51
+ // Demerit flow:
52
+ // When we add a demerit, we add to both new & unacked.
53
+ // When we flush settings, we move new to sent.
54
+ // When we ack settings, we remove what we sent from unacked.
55
+ // eg:
56
+ // we add 10 demerits - now new=10, sent=0, unacked=10
57
+ // we send settings - now new=0, sent=10, unacked=10
58
+ // we add 5 demerits - now new=5, sent=10, unacked=15
59
+ // we get the settings ack - now new=5, sent=0, unacked=5
60
+ uint32_t new_demerits_ = 0;
61
+ uint32_t sent_demerits_ = 0;
62
+ uint32_t unacked_demerits_ = 0;
63
+ };
64
+
65
+ } // namespace grpc_core
66
+
67
+ #endif // GRPC_SRC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_MAX_CONCURRENT_STREAMS_POLICY_H