grpc 1.59.0 → 1.59.2

Sign up to get free protection for your applications and to get access to all the features.
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