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.
- checksums.yaml +4 -4
- data/Makefile +7 -1
- data/src/core/ext/filters/http/server/http_server_filter.cc +21 -17
- data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +504 -361
- data/src/core/ext/transport/chttp2/transport/frame_ping.cc +11 -1
- data/src/core/ext/transport/chttp2/transport/frame_rst_stream.cc +9 -0
- data/src/core/ext/transport/chttp2/transport/internal.h +92 -28
- data/src/core/ext/transport/chttp2/transport/max_concurrent_streams_policy.cc +44 -0
- data/src/core/ext/transport/chttp2/transport/max_concurrent_streams_policy.h +67 -0
- data/src/core/ext/transport/chttp2/transport/parsing.cc +103 -14
- data/src/core/ext/transport/chttp2/transport/ping_callbacks.cc +108 -0
- data/src/core/ext/transport/chttp2/transport/ping_callbacks.h +115 -0
- data/src/core/ext/transport/chttp2/transport/ping_rate_policy.cc +26 -4
- data/src/core/ext/transport/chttp2/transport/ping_rate_policy.h +16 -1
- data/src/core/ext/transport/chttp2/transport/write_size_policy.cc +60 -0
- data/src/core/ext/transport/chttp2/transport/write_size_policy.h +66 -0
- data/src/core/ext/transport/chttp2/transport/writing.cc +149 -77
- data/src/core/lib/channel/promise_based_filter.cc +9 -4
- data/src/core/lib/channel/promise_based_filter.h +2 -1
- data/src/core/lib/experiments/experiments.cc +222 -0
- data/src/core/lib/experiments/experiments.h +135 -0
- data/src/core/lib/iomgr/combiner.cc +3 -0
- data/src/core/lib/transport/metadata_batch.h +11 -1
- data/src/core/lib/transport/transport.h +6 -0
- data/src/ruby/lib/grpc/version.rb +1 -1
- metadata +9 -3
@@ -24,7 +24,9 @@
|
|
24
24
|
#include <string.h>
|
25
25
|
|
26
26
|
#include <algorithm>
|
27
|
+
#include <atomic>
|
27
28
|
#include <initializer_list>
|
29
|
+
#include <limits>
|
28
30
|
#include <memory>
|
29
31
|
#include <new>
|
30
32
|
#include <string>
|
@@ -36,12 +38,14 @@
|
|
36
38
|
#include "absl/container/flat_hash_map.h"
|
37
39
|
#include "absl/hash/hash.h"
|
38
40
|
#include "absl/meta/type_traits.h"
|
41
|
+
#include "absl/random/random.h"
|
39
42
|
#include "absl/status/status.h"
|
40
43
|
#include "absl/strings/cord.h"
|
41
44
|
#include "absl/strings/str_cat.h"
|
42
45
|
#include "absl/strings/str_format.h"
|
43
46
|
#include "absl/strings/string_view.h"
|
44
47
|
#include "absl/types/optional.h"
|
48
|
+
#include "absl/types/variant.h"
|
45
49
|
|
46
50
|
#include <grpc/event_engine/event_engine.h>
|
47
51
|
#include <grpc/grpc.h>
|
@@ -63,9 +67,12 @@
|
|
63
67
|
#include "src/core/ext/transport/chttp2/transport/http_trace.h"
|
64
68
|
#include "src/core/ext/transport/chttp2/transport/internal.h"
|
65
69
|
#include "src/core/ext/transport/chttp2/transport/legacy_frame.h"
|
70
|
+
#include "src/core/ext/transport/chttp2/transport/max_concurrent_streams_policy.h"
|
66
71
|
#include "src/core/ext/transport/chttp2/transport/ping_abuse_policy.h"
|
72
|
+
#include "src/core/ext/transport/chttp2/transport/ping_callbacks.h"
|
67
73
|
#include "src/core/ext/transport/chttp2/transport/ping_rate_policy.h"
|
68
74
|
#include "src/core/ext/transport/chttp2/transport/varint.h"
|
75
|
+
#include "src/core/ext/transport/chttp2/transport/write_size_policy.h"
|
69
76
|
#include "src/core/lib/channel/call_tracer.h"
|
70
77
|
#include "src/core/lib/channel/channel_args.h"
|
71
78
|
#include "src/core/lib/channel/context.h"
|
@@ -116,6 +123,9 @@
|
|
116
123
|
|
117
124
|
#define DEFAULT_MAX_PENDING_INDUCED_FRAMES 10000
|
118
125
|
|
126
|
+
#define GRPC_ARG_HTTP2_PING_ON_RST_STREAM_PERCENT \
|
127
|
+
"grpc.http2.ping_on_rst_stream_percent"
|
128
|
+
|
119
129
|
static grpc_core::Duration g_default_client_keepalive_time =
|
120
130
|
grpc_core::Duration::Infinity();
|
121
131
|
static grpc_core::Duration g_default_client_keepalive_timeout =
|
@@ -127,6 +137,11 @@ static grpc_core::Duration g_default_server_keepalive_timeout =
|
|
127
137
|
static bool g_default_client_keepalive_permit_without_calls = false;
|
128
138
|
static bool g_default_server_keepalive_permit_without_calls = false;
|
129
139
|
|
140
|
+
// EXPERIMENTAL: control tarpitting in chttp2
|
141
|
+
#define GRPC_ARG_HTTP_ALLOW_TARPIT "grpc.http.tarpit"
|
142
|
+
#define GRPC_ARG_HTTP_TARPIT_MIN_DURATION_MS "grpc.http.tarpit_min_duration_ms"
|
143
|
+
#define GRPC_ARG_HTTP_TARPIT_MAX_DURATION_MS "grpc.http.tarpit_max_duration_ms"
|
144
|
+
|
130
145
|
#define MAX_CLIENT_STREAM_ID 0x7fffffffu
|
131
146
|
grpc_core::TraceFlag grpc_keepalive_trace(false, "http_keepalive");
|
132
147
|
grpc_core::DebugOnlyTraceFlag grpc_trace_chttp2_refcount(false,
|
@@ -153,7 +168,7 @@ static void queue_setting_update(grpc_chttp2_transport* t,
|
|
153
168
|
grpc_chttp2_setting_id id, uint32_t value);
|
154
169
|
|
155
170
|
static void close_from_api(grpc_chttp2_transport* t, grpc_chttp2_stream* s,
|
156
|
-
grpc_error_handle error);
|
171
|
+
grpc_error_handle error, bool tarpit);
|
157
172
|
|
158
173
|
// Start new streams that have been created if we can
|
159
174
|
static void maybe_start_some_streams(grpc_chttp2_transport* t);
|
@@ -202,21 +217,18 @@ static void init_keepalive_ping(
|
|
202
217
|
static void init_keepalive_ping_locked(
|
203
218
|
grpc_core::RefCountedPtr<grpc_chttp2_transport> t,
|
204
219
|
GRPC_UNUSED grpc_error_handle error);
|
205
|
-
static void start_keepalive_ping(
|
206
|
-
grpc_core::RefCountedPtr<grpc_chttp2_transport> t, grpc_error_handle error);
|
207
220
|
static void finish_keepalive_ping(
|
208
221
|
grpc_core::RefCountedPtr<grpc_chttp2_transport> t, grpc_error_handle error);
|
209
|
-
static void start_keepalive_ping_locked(
|
210
|
-
grpc_core::RefCountedPtr<grpc_chttp2_transport> t, grpc_error_handle error);
|
211
222
|
static void finish_keepalive_ping_locked(
|
212
223
|
grpc_core::RefCountedPtr<grpc_chttp2_transport> t, grpc_error_handle error);
|
213
|
-
static void keepalive_watchdog_fired(
|
214
|
-
grpc_core::RefCountedPtr<grpc_chttp2_transport> t);
|
215
|
-
static void keepalive_watchdog_fired_locked(
|
216
|
-
grpc_core::RefCountedPtr<grpc_chttp2_transport> t,
|
217
|
-
GRPC_UNUSED grpc_error_handle error);
|
218
224
|
static void maybe_reset_keepalive_ping_timer_locked(grpc_chttp2_transport* t);
|
219
225
|
|
226
|
+
static void send_goaway(grpc_chttp2_transport* t, grpc_error_handle error,
|
227
|
+
bool immediate_disconnect_hint);
|
228
|
+
|
229
|
+
// Timeout for getting an ack back on settings changes
|
230
|
+
#define GRPC_ARG_SETTINGS_TIMEOUT "grpc.http2.settings_timeout"
|
231
|
+
|
220
232
|
namespace {
|
221
233
|
grpc_core::CallTracerInterface* CallTracerIfEnabled(grpc_chttp2_stream* s) {
|
222
234
|
if (s->context == nullptr || !grpc_core::IsTraceRecordCallopsEnabled()) {
|
@@ -317,6 +329,8 @@ void ForEachContextListEntryExecute(void* arg, Timestamps* ts,
|
|
317
329
|
grpc_chttp2_transport::~grpc_chttp2_transport() {
|
318
330
|
size_t i;
|
319
331
|
|
332
|
+
cancel_pings(this, GRPC_ERROR_CREATE("Transport destroyed"));
|
333
|
+
|
320
334
|
event_engine.reset();
|
321
335
|
|
322
336
|
if (channelz_socket != nullptr) {
|
@@ -327,8 +341,6 @@ grpc_chttp2_transport::~grpc_chttp2_transport() {
|
|
327
341
|
|
328
342
|
grpc_slice_buffer_destroy(&qbuf);
|
329
343
|
|
330
|
-
grpc_slice_buffer_destroy(&outbuf);
|
331
|
-
|
332
344
|
grpc_error_handle error = GRPC_ERROR_CREATE("Transport destroyed");
|
333
345
|
// ContextList::Execute follows semantics of a callback function and does not
|
334
346
|
// take a ref on error
|
@@ -348,8 +360,6 @@ grpc_chttp2_transport::~grpc_chttp2_transport() {
|
|
348
360
|
GPR_ASSERT(stream_map.empty());
|
349
361
|
GRPC_COMBINER_UNREF(combiner, "chttp2_transport");
|
350
362
|
|
351
|
-
cancel_pings(this, GRPC_ERROR_CREATE("Transport destroyed"));
|
352
|
-
|
353
363
|
while (write_cb_pool) {
|
354
364
|
grpc_chttp2_write_cb* next = write_cb_pool->next;
|
355
365
|
gpr_free(write_cb_pool);
|
@@ -396,8 +406,16 @@ static void read_channel_args(grpc_chttp2_transport* t,
|
|
396
406
|
t->keepalive_timeout = std::max(
|
397
407
|
grpc_core::Duration::Zero(),
|
398
408
|
channel_args.GetDurationFromIntMillis(GRPC_ARG_KEEPALIVE_TIMEOUT_MS)
|
399
|
-
.value_or(t->
|
400
|
-
|
409
|
+
.value_or(t->keepalive_time == grpc_core::Duration::Infinity()
|
410
|
+
? grpc_core::Duration::Infinity()
|
411
|
+
: (t->is_client ? g_default_client_keepalive_timeout
|
412
|
+
: g_default_server_keepalive_timeout)));
|
413
|
+
t->ping_timeout = std::max(
|
414
|
+
grpc_core::Duration::Zero(),
|
415
|
+
channel_args.GetDurationFromIntMillis(GRPC_ARG_PING_TIMEOUT_MS)
|
416
|
+
.value_or(t->keepalive_time == grpc_core::Duration::Infinity()
|
417
|
+
? grpc_core::Duration::Infinity()
|
418
|
+
: grpc_core::Duration::Minutes(1)));
|
401
419
|
if (t->is_client) {
|
402
420
|
t->keepalive_permit_without_calls =
|
403
421
|
channel_args.GetBool(GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS)
|
@@ -412,6 +430,11 @@ static void read_channel_args(grpc_chttp2_transport* t,
|
|
412
430
|
: false);
|
413
431
|
}
|
414
432
|
|
433
|
+
t->settings_timeout =
|
434
|
+
channel_args.GetDurationFromIntMillis(GRPC_ARG_SETTINGS_TIMEOUT)
|
435
|
+
.value_or(std::max(t->keepalive_timeout * 2,
|
436
|
+
grpc_core::Duration::Minutes(1)));
|
437
|
+
|
415
438
|
// Only send the prefered rx frame size http2 setting if we are instructed
|
416
439
|
// to auto size the buffers allocated at tcp level and we also can adjust
|
417
440
|
// sending frame size.
|
@@ -420,6 +443,17 @@ static void read_channel_args(grpc_chttp2_transport* t,
|
|
420
443
|
.GetBool(GRPC_ARG_EXPERIMENTAL_HTTP2_PREFERRED_CRYPTO_FRAME_SIZE)
|
421
444
|
.value_or(false);
|
422
445
|
|
446
|
+
const auto max_requests_per_read =
|
447
|
+
channel_args.GetInt("grpc.http2.max_requests_per_read");
|
448
|
+
if (max_requests_per_read.has_value()) {
|
449
|
+
t->max_requests_per_read =
|
450
|
+
grpc_core::Clamp(*max_requests_per_read, 1, 10000);
|
451
|
+
} else if (grpc_core::IsChttp2BatchRequestsEnabled()) {
|
452
|
+
t->max_requests_per_read = 32;
|
453
|
+
} else {
|
454
|
+
t->max_requests_per_read = std::numeric_limits<size_t>::max();
|
455
|
+
}
|
456
|
+
|
423
457
|
if (channel_args.GetBool(GRPC_ARG_ENABLE_CHANNELZ)
|
424
458
|
.value_or(GRPC_ENABLE_CHANNELZ_DEFAULT)) {
|
425
459
|
t->channelz_socket =
|
@@ -434,6 +468,19 @@ static void read_channel_args(grpc_chttp2_transport* t,
|
|
434
468
|
|
435
469
|
t->ack_pings = channel_args.GetBool("grpc.http2.ack_pings").value_or(true);
|
436
470
|
|
471
|
+
t->allow_tarpit = channel_args.GetBool(GRPC_ARG_HTTP_ALLOW_TARPIT)
|
472
|
+
.value_or(grpc_core::IsTarpitEnabled());
|
473
|
+
t->min_tarpit_duration_ms =
|
474
|
+
channel_args
|
475
|
+
.GetDurationFromIntMillis(GRPC_ARG_HTTP_TARPIT_MIN_DURATION_MS)
|
476
|
+
.value_or(grpc_core::Duration::Milliseconds(100))
|
477
|
+
.millis();
|
478
|
+
t->max_tarpit_duration_ms =
|
479
|
+
channel_args
|
480
|
+
.GetDurationFromIntMillis(GRPC_ARG_HTTP_TARPIT_MAX_DURATION_MS)
|
481
|
+
.value_or(grpc_core::Duration::Seconds(1))
|
482
|
+
.millis();
|
483
|
+
|
437
484
|
const int soft_limit =
|
438
485
|
channel_args.GetInt(GRPC_ARG_MAX_METADATA_SIZE).value_or(-1);
|
439
486
|
if (soft_limit < 0) {
|
@@ -499,8 +546,12 @@ static void read_channel_args(grpc_chttp2_transport* t,
|
|
499
546
|
const int value = channel_args.GetInt(setting.channel_arg_name)
|
500
547
|
.value_or(setting.default_value);
|
501
548
|
if (value >= 0) {
|
502
|
-
|
503
|
-
|
549
|
+
const int clamped_value =
|
550
|
+
grpc_core::Clamp(value, setting.min, setting.max);
|
551
|
+
queue_setting_update(t, setting.setting_id, clamped_value);
|
552
|
+
if (setting.setting_id == GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS) {
|
553
|
+
t->max_concurrent_streams_policy.SetTarget(clamped_value);
|
554
|
+
}
|
504
555
|
} else if (setting.setting_id ==
|
505
556
|
GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE) {
|
506
557
|
// Set value to 1.25 * soft limit if this is larger than
|
@@ -533,6 +584,11 @@ static void read_channel_args(grpc_chttp2_transport* t,
|
|
533
584
|
grpc_core::Clamp(INT_MAX, static_cast<int>(sp->min_value),
|
534
585
|
static_cast<int>(sp->max_value)));
|
535
586
|
}
|
587
|
+
|
588
|
+
t->ping_on_rst_stream_percent = grpc_core::Clamp(
|
589
|
+
channel_args.GetInt(GRPC_ARG_HTTP2_PING_ON_RST_STREAM_PERCENT)
|
590
|
+
.value_or(1),
|
591
|
+
0, 100);
|
536
592
|
}
|
537
593
|
|
538
594
|
static void init_keepalive_pings_if_enabled_locked(
|
@@ -590,10 +646,10 @@ grpc_chttp2_transport::grpc_chttp2_transport(
|
|
590
646
|
base.vtable = get_vtable();
|
591
647
|
|
592
648
|
grpc_slice_buffer_init(&read_buffer);
|
593
|
-
grpc_slice_buffer_init(&outbuf);
|
594
649
|
if (is_client) {
|
595
|
-
grpc_slice_buffer_add(
|
596
|
-
|
650
|
+
grpc_slice_buffer_add(
|
651
|
+
outbuf.c_slice_buffer(),
|
652
|
+
grpc_slice_from_copied_string(GRPC_CHTTP2_CLIENT_CONNECT_STRING));
|
597
653
|
}
|
598
654
|
grpc_slice_buffer_init(&qbuf);
|
599
655
|
// copy in initial settings to all setting sets
|
@@ -618,6 +674,12 @@ grpc_chttp2_transport::grpc_chttp2_transport(
|
|
618
674
|
|
619
675
|
read_channel_args(this, channel_args, is_client);
|
620
676
|
|
677
|
+
// Initially allow *UP TO* MAX_CONCURRENT_STREAMS incoming before we start
|
678
|
+
// blanket cancelling them.
|
679
|
+
num_incoming_streams_before_settings_ack =
|
680
|
+
settings[GRPC_LOCAL_SETTINGS]
|
681
|
+
[GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS];
|
682
|
+
|
621
683
|
grpc_core::ExecCtx exec_ctx;
|
622
684
|
combiner->Run(
|
623
685
|
grpc_core::InitTransportClosure<init_keepalive_pings_if_enabled_locked>(
|
@@ -686,6 +748,18 @@ static void close_transport_locked(grpc_chttp2_transport* t,
|
|
686
748
|
t->closed_with_error = error;
|
687
749
|
connectivity_state_set(t, GRPC_CHANNEL_SHUTDOWN, absl::Status(),
|
688
750
|
"close_transport");
|
751
|
+
if (t->keepalive_ping_timeout_handle !=
|
752
|
+
grpc_event_engine::experimental::EventEngine::TaskHandle::kInvalid) {
|
753
|
+
t->event_engine->Cancel(std::exchange(
|
754
|
+
t->keepalive_ping_timeout_handle,
|
755
|
+
grpc_event_engine::experimental::EventEngine::TaskHandle::kInvalid));
|
756
|
+
}
|
757
|
+
if (t->settings_ack_watchdog !=
|
758
|
+
grpc_event_engine::experimental::EventEngine::TaskHandle::kInvalid) {
|
759
|
+
t->event_engine->Cancel(std::exchange(
|
760
|
+
t->settings_ack_watchdog,
|
761
|
+
grpc_event_engine::experimental::EventEngine::TaskHandle::kInvalid));
|
762
|
+
}
|
689
763
|
if (t->delayed_ping_timer_handle.has_value()) {
|
690
764
|
if (t->event_engine->Cancel(*t->delayed_ping_timer_handle)) {
|
691
765
|
t->delayed_ping_timer_handle.reset();
|
@@ -710,11 +784,6 @@ static void close_transport_locked(grpc_chttp2_transport* t,
|
|
710
784
|
t->keepalive_ping_timer_handle.reset();
|
711
785
|
}
|
712
786
|
}
|
713
|
-
if (t->keepalive_watchdog_timer_handle.has_value()) {
|
714
|
-
if (t->event_engine->Cancel(*t->keepalive_watchdog_timer_handle)) {
|
715
|
-
t->keepalive_watchdog_timer_handle.reset();
|
716
|
-
}
|
717
|
-
}
|
718
787
|
break;
|
719
788
|
case GRPC_CHTTP2_KEEPALIVE_STATE_DYING:
|
720
789
|
case GRPC_CHTTP2_KEEPALIVE_STATE_DISABLED:
|
@@ -777,6 +846,7 @@ grpc_chttp2_stream::grpc_chttp2_stream(grpc_chttp2_transport* t,
|
|
777
846
|
initial_metadata_buffer(arena),
|
778
847
|
trailing_metadata_buffer(arena),
|
779
848
|
flow_control(&t->flow_control) {
|
849
|
+
t->streams_allocated.fetch_add(1, std::memory_order_relaxed);
|
780
850
|
if (server_data) {
|
781
851
|
id = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(server_data));
|
782
852
|
if (grpc_http_trace.enabled()) {
|
@@ -793,6 +863,7 @@ grpc_chttp2_stream::grpc_chttp2_stream(grpc_chttp2_transport* t,
|
|
793
863
|
}
|
794
864
|
|
795
865
|
grpc_chttp2_stream::~grpc_chttp2_stream() {
|
866
|
+
t->streams_allocated.fetch_sub(1, std::memory_order_relaxed);
|
796
867
|
grpc_chttp2_list_remove_stalled_by_stream(t.get(), this);
|
797
868
|
grpc_chttp2_list_remove_stalled_by_transport(t.get(), this);
|
798
869
|
|
@@ -1016,7 +1087,12 @@ static void write_action(grpc_chttp2_transport* t) {
|
|
1016
1087
|
if (max_frame_size == 0) {
|
1017
1088
|
max_frame_size = INT_MAX;
|
1018
1089
|
}
|
1019
|
-
|
1090
|
+
if (GRPC_TRACE_FLAG_ENABLED(grpc_ping_trace)) {
|
1091
|
+
gpr_log(GPR_INFO, "%s[%p]: Write %" PRIdPTR " bytes",
|
1092
|
+
t->is_client ? "CLIENT" : "SERVER", t, t->outbuf.Length());
|
1093
|
+
}
|
1094
|
+
t->write_size_policy.BeginWrite(t->outbuf.Length());
|
1095
|
+
grpc_endpoint_write(t->ep, t->outbuf.c_slice_buffer(),
|
1020
1096
|
grpc_core::InitTransportClosure<write_action_end>(
|
1021
1097
|
t->Ref(), &t->write_action_end_locked),
|
1022
1098
|
cl, max_frame_size);
|
@@ -1025,6 +1101,10 @@ static void write_action(grpc_chttp2_transport* t) {
|
|
1025
1101
|
static void write_action_end(grpc_core::RefCountedPtr<grpc_chttp2_transport> t,
|
1026
1102
|
grpc_error_handle error) {
|
1027
1103
|
auto* tp = t.get();
|
1104
|
+
if (GRPC_TRACE_FLAG_ENABLED(grpc_ping_trace)) {
|
1105
|
+
gpr_log(GPR_INFO, "%s[%p]: Finish write",
|
1106
|
+
t->is_client ? "CLIENT" : "SERVER", t.get());
|
1107
|
+
}
|
1028
1108
|
tp->combiner->Run(grpc_core::InitTransportClosure<write_action_end_locked>(
|
1029
1109
|
std::move(t), &tp->write_action_end_locked),
|
1030
1110
|
error);
|
@@ -1035,6 +1115,8 @@ static void write_action_end(grpc_core::RefCountedPtr<grpc_chttp2_transport> t,
|
|
1035
1115
|
static void write_action_end_locked(
|
1036
1116
|
grpc_core::RefCountedPtr<grpc_chttp2_transport> t,
|
1037
1117
|
grpc_error_handle error) {
|
1118
|
+
t->write_size_policy.EndWrite(error.ok());
|
1119
|
+
|
1038
1120
|
bool closed = false;
|
1039
1121
|
if (!error.ok()) {
|
1040
1122
|
close_transport_locked(t.get(), error);
|
@@ -1095,13 +1177,13 @@ static void queue_setting_update(grpc_chttp2_transport* t,
|
|
1095
1177
|
|
1096
1178
|
// Cancel out streams that haven't yet started if we have received a GOAWAY
|
1097
1179
|
static void cancel_unstarted_streams(grpc_chttp2_transport* t,
|
1098
|
-
grpc_error_handle error) {
|
1180
|
+
grpc_error_handle error, bool tarpit) {
|
1099
1181
|
grpc_chttp2_stream* s;
|
1100
1182
|
while (grpc_chttp2_list_pop_waiting_for_concurrency(t, &s)) {
|
1101
1183
|
s->trailing_metadata_buffer.Set(
|
1102
1184
|
grpc_core::GrpcStreamNetworkState(),
|
1103
1185
|
grpc_core::GrpcStreamNetworkState::kNotSentOnWire);
|
1104
|
-
grpc_chttp2_cancel_stream(t, s, error);
|
1186
|
+
grpc_chttp2_cancel_stream(t, s, error, tarpit);
|
1105
1187
|
}
|
1106
1188
|
}
|
1107
1189
|
|
@@ -1134,7 +1216,7 @@ void grpc_chttp2_add_incoming_goaway(grpc_chttp2_transport* t,
|
|
1134
1216
|
grpc_core::StatusToString(t->goaway_error).c_str());
|
1135
1217
|
}
|
1136
1218
|
if (t->is_client) {
|
1137
|
-
cancel_unstarted_streams(t, t->goaway_error);
|
1219
|
+
cancel_unstarted_streams(t, t->goaway_error, false);
|
1138
1220
|
// Cancel all unseen streams
|
1139
1221
|
std::vector<grpc_chttp2_stream*> to_cancel;
|
1140
1222
|
for (auto id_stream : t->stream_map) {
|
@@ -1146,7 +1228,7 @@ void grpc_chttp2_add_incoming_goaway(grpc_chttp2_transport* t,
|
|
1146
1228
|
s->trailing_metadata_buffer.Set(
|
1147
1229
|
grpc_core::GrpcStreamNetworkState(),
|
1148
1230
|
grpc_core::GrpcStreamNetworkState::kNotSeenByServer);
|
1149
|
-
grpc_chttp2_cancel_stream(s->t.get(), s, s->t->goaway_error);
|
1231
|
+
grpc_chttp2_cancel_stream(s->t.get(), s, s->t->goaway_error, false);
|
1150
1232
|
}
|
1151
1233
|
}
|
1152
1234
|
absl::Status status = grpc_error_to_absl_status(t->goaway_error);
|
@@ -1185,7 +1267,7 @@ static void maybe_start_some_streams(grpc_chttp2_transport* t) {
|
|
1185
1267
|
// maybe cancel out streams that haven't yet started if we have received a
|
1186
1268
|
// GOAWAY
|
1187
1269
|
if (!t->goaway_error.ok()) {
|
1188
|
-
cancel_unstarted_streams(t, t->goaway_error);
|
1270
|
+
cancel_unstarted_streams(t, t->goaway_error, false);
|
1189
1271
|
return;
|
1190
1272
|
}
|
1191
1273
|
// start streams where we have free grpc_chttp2_stream ids and free
|
@@ -1227,7 +1309,8 @@ static void maybe_start_some_streams(grpc_chttp2_transport* t) {
|
|
1227
1309
|
t, s,
|
1228
1310
|
grpc_error_set_int(GRPC_ERROR_CREATE("Stream IDs exhausted"),
|
1229
1311
|
grpc_core::StatusIntProperty::kRpcStatus,
|
1230
|
-
GRPC_STATUS_UNAVAILABLE)
|
1312
|
+
GRPC_STATUS_UNAVAILABLE),
|
1313
|
+
false);
|
1231
1314
|
}
|
1232
1315
|
}
|
1233
1316
|
}
|
@@ -1372,7 +1455,8 @@ static void perform_stream_op_locked(void* stream_op,
|
|
1372
1455
|
}
|
1373
1456
|
|
1374
1457
|
if (op->cancel_stream) {
|
1375
|
-
grpc_chttp2_cancel_stream(t, s, op_payload->cancel_stream.cancel_error
|
1458
|
+
grpc_chttp2_cancel_stream(t, s, op_payload->cancel_stream.cancel_error,
|
1459
|
+
op_payload->cancel_stream.tarpit);
|
1376
1460
|
}
|
1377
1461
|
|
1378
1462
|
if (op->send_initial_metadata) {
|
@@ -1410,7 +1494,8 @@ static void perform_stream_op_locked(void* stream_op,
|
|
1410
1494
|
GRPC_ERROR_CREATE_REFERENCING("Transport closed",
|
1411
1495
|
&t->closed_with_error, 1),
|
1412
1496
|
grpc_core::StatusIntProperty::kRpcStatus,
|
1413
|
-
GRPC_STATUS_UNAVAILABLE)
|
1497
|
+
GRPC_STATUS_UNAVAILABLE),
|
1498
|
+
false);
|
1414
1499
|
}
|
1415
1500
|
} else {
|
1416
1501
|
GPR_ASSERT(s->id != 0);
|
@@ -1618,14 +1703,38 @@ static void cancel_pings(grpc_chttp2_transport* t, grpc_error_handle error) {
|
|
1618
1703
|
grpc_core::StatusToString(error).c_str()));
|
1619
1704
|
// callback remaining pings: they're not allowed to call into the transport,
|
1620
1705
|
// and maybe they hold resources that need to be freed
|
1621
|
-
|
1622
|
-
GPR_ASSERT(!error.ok());
|
1623
|
-
for (size_t j = 0; j < GRPC_CHTTP2_PCL_COUNT; j++) {
|
1624
|
-
grpc_closure_list_fail_all(&pq->lists[j], error);
|
1625
|
-
grpc_core::ExecCtx::RunList(DEBUG_LOCATION, &pq->lists[j]);
|
1626
|
-
}
|
1706
|
+
t->ping_callbacks.CancelAll(t->event_engine.get());
|
1627
1707
|
}
|
1628
1708
|
|
1709
|
+
namespace {
|
1710
|
+
class PingClosureWrapper {
|
1711
|
+
public:
|
1712
|
+
explicit PingClosureWrapper(grpc_closure* closure) : closure_(closure) {}
|
1713
|
+
PingClosureWrapper(const PingClosureWrapper&) = delete;
|
1714
|
+
PingClosureWrapper& operator=(const PingClosureWrapper&) = delete;
|
1715
|
+
PingClosureWrapper(PingClosureWrapper&& other) noexcept
|
1716
|
+
: closure_(other.Take()) {}
|
1717
|
+
PingClosureWrapper& operator=(PingClosureWrapper&& other) noexcept {
|
1718
|
+
std::swap(closure_, other.closure_);
|
1719
|
+
return *this;
|
1720
|
+
}
|
1721
|
+
~PingClosureWrapper() {
|
1722
|
+
if (closure_ != nullptr) {
|
1723
|
+
grpc_core::ExecCtx::Run(DEBUG_LOCATION, closure_, absl::CancelledError());
|
1724
|
+
}
|
1725
|
+
}
|
1726
|
+
|
1727
|
+
void operator()() {
|
1728
|
+
grpc_core::ExecCtx::Run(DEBUG_LOCATION, Take(), absl::OkStatus());
|
1729
|
+
}
|
1730
|
+
|
1731
|
+
private:
|
1732
|
+
grpc_closure* Take() { return std::exchange(closure_, nullptr); }
|
1733
|
+
|
1734
|
+
grpc_closure* closure_ = nullptr;
|
1735
|
+
};
|
1736
|
+
} // namespace
|
1737
|
+
|
1629
1738
|
static void send_ping_locked(grpc_chttp2_transport* t,
|
1630
1739
|
grpc_closure* on_initiate, grpc_closure* on_ack) {
|
1631
1740
|
if (!t->closed_with_error.ok()) {
|
@@ -1633,11 +1742,8 @@ static void send_ping_locked(grpc_chttp2_transport* t,
|
|
1633
1742
|
grpc_core::ExecCtx::Run(DEBUG_LOCATION, on_ack, t->closed_with_error);
|
1634
1743
|
return;
|
1635
1744
|
}
|
1636
|
-
|
1637
|
-
|
1638
|
-
absl::OkStatus());
|
1639
|
-
grpc_closure_list_append(&pq->lists[GRPC_CHTTP2_PCL_NEXT], on_ack,
|
1640
|
-
absl::OkStatus());
|
1745
|
+
t->ping_callbacks.OnPing(PingClosureWrapper(on_initiate),
|
1746
|
+
PingClosureWrapper(on_ack));
|
1641
1747
|
}
|
1642
1748
|
|
1643
1749
|
// Specialized form of send_ping_locked for keepalive ping. If there is already
|
@@ -1646,40 +1752,15 @@ static void send_ping_locked(grpc_chttp2_transport* t,
|
|
1646
1752
|
static void send_keepalive_ping_locked(
|
1647
1753
|
grpc_core::RefCountedPtr<grpc_chttp2_transport> t) {
|
1648
1754
|
if (!t->closed_with_error.ok()) {
|
1649
|
-
t->combiner->Run(
|
1650
|
-
grpc_core::InitTransportClosure<start_keepalive_ping_locked>(
|
1651
|
-
t->Ref(), &t->start_keepalive_ping_locked),
|
1652
|
-
t->closed_with_error);
|
1653
1755
|
t->combiner->Run(
|
1654
1756
|
grpc_core::InitTransportClosure<finish_keepalive_ping_locked>(
|
1655
1757
|
t->Ref(), &t->finish_keepalive_ping_locked),
|
1656
1758
|
t->closed_with_error);
|
1657
1759
|
return;
|
1658
1760
|
}
|
1659
|
-
|
1660
|
-
|
1661
|
-
|
1662
|
-
t->combiner->Run(
|
1663
|
-
grpc_core::InitTransportClosure<start_keepalive_ping_locked>(
|
1664
|
-
t->Ref(), &t->start_keepalive_ping_locked),
|
1665
|
-
t->closed_with_error);
|
1666
|
-
grpc_closure_list_append(
|
1667
|
-
&pq->lists[GRPC_CHTTP2_PCL_INFLIGHT],
|
1668
|
-
grpc_core::InitTransportClosure<finish_keepalive_ping>(
|
1669
|
-
t->Ref(), &t->finish_keepalive_ping_locked),
|
1670
|
-
absl::OkStatus());
|
1671
|
-
return;
|
1672
|
-
}
|
1673
|
-
grpc_closure_list_append(
|
1674
|
-
&pq->lists[GRPC_CHTTP2_PCL_INITIATE],
|
1675
|
-
grpc_core::InitTransportClosure<start_keepalive_ping>(
|
1676
|
-
t->Ref(), &t->start_keepalive_ping_locked),
|
1677
|
-
absl::OkStatus());
|
1678
|
-
grpc_closure_list_append(
|
1679
|
-
&pq->lists[GRPC_CHTTP2_PCL_NEXT],
|
1680
|
-
grpc_core::InitTransportClosure<finish_keepalive_ping>(
|
1681
|
-
t->Ref(), &t->finish_keepalive_ping_locked),
|
1682
|
-
absl::OkStatus());
|
1761
|
+
t->ping_callbacks.OnPingAck(
|
1762
|
+
PingClosureWrapper(grpc_core::InitTransportClosure<finish_keepalive_ping>(
|
1763
|
+
t->Ref(), &t->finish_keepalive_ping_locked)));
|
1683
1764
|
}
|
1684
1765
|
|
1685
1766
|
void grpc_chttp2_retry_initiate_ping(
|
@@ -1701,19 +1782,79 @@ static void retry_initiate_ping_locked(
|
|
1701
1782
|
}
|
1702
1783
|
|
1703
1784
|
void grpc_chttp2_ack_ping(grpc_chttp2_transport* t, uint64_t id) {
|
1704
|
-
|
1705
|
-
if (pq->inflight_id != id) {
|
1785
|
+
if (!t->ping_callbacks.AckPing(id, t->event_engine.get())) {
|
1706
1786
|
gpr_log(GPR_DEBUG, "Unknown ping response from %s: %" PRIx64,
|
1707
1787
|
std::string(t->peer_string.as_string_view()).c_str(), id);
|
1708
1788
|
return;
|
1709
1789
|
}
|
1710
|
-
|
1711
|
-
&pq->lists[GRPC_CHTTP2_PCL_INFLIGHT]);
|
1712
|
-
if (!grpc_closure_list_empty(pq->lists[GRPC_CHTTP2_PCL_NEXT])) {
|
1790
|
+
if (t->ping_callbacks.ping_requested()) {
|
1713
1791
|
grpc_chttp2_initiate_write(t, GRPC_CHTTP2_INITIATE_WRITE_CONTINUE_PINGS);
|
1714
1792
|
}
|
1715
1793
|
}
|
1716
1794
|
|
1795
|
+
void grpc_chttp2_keepalive_timeout(
|
1796
|
+
grpc_core::RefCountedPtr<grpc_chttp2_transport> t) {
|
1797
|
+
t->combiner->Run(
|
1798
|
+
grpc_core::NewClosure([t](grpc_error_handle) {
|
1799
|
+
gpr_log(GPR_INFO, "%s: Keepalive timeout. Closing transport.",
|
1800
|
+
std::string(t->peer_string.as_string_view()).c_str());
|
1801
|
+
send_goaway(
|
1802
|
+
t.get(),
|
1803
|
+
grpc_error_set_int(GRPC_ERROR_CREATE("keepalive_timeout"),
|
1804
|
+
grpc_core::StatusIntProperty::kHttp2Error,
|
1805
|
+
GRPC_HTTP2_ENHANCE_YOUR_CALM),
|
1806
|
+
/*immediate_disconnect_hint=*/true);
|
1807
|
+
close_transport_locked(
|
1808
|
+
t.get(),
|
1809
|
+
grpc_error_set_int(GRPC_ERROR_CREATE("keepalive timeout"),
|
1810
|
+
grpc_core::StatusIntProperty::kRpcStatus,
|
1811
|
+
GRPC_STATUS_UNAVAILABLE));
|
1812
|
+
}),
|
1813
|
+
absl::OkStatus());
|
1814
|
+
}
|
1815
|
+
|
1816
|
+
void grpc_chttp2_ping_timeout(
|
1817
|
+
grpc_core::RefCountedPtr<grpc_chttp2_transport> t) {
|
1818
|
+
t->combiner->Run(
|
1819
|
+
grpc_core::NewClosure([t](grpc_error_handle) {
|
1820
|
+
gpr_log(GPR_INFO, "%s: Ping timeout. Closing transport.",
|
1821
|
+
std::string(t->peer_string.as_string_view()).c_str());
|
1822
|
+
send_goaway(
|
1823
|
+
t.get(),
|
1824
|
+
grpc_error_set_int(GRPC_ERROR_CREATE("ping_timeout"),
|
1825
|
+
grpc_core::StatusIntProperty::kHttp2Error,
|
1826
|
+
GRPC_HTTP2_ENHANCE_YOUR_CALM),
|
1827
|
+
/*immediate_disconnect_hint=*/true);
|
1828
|
+
close_transport_locked(
|
1829
|
+
t.get(),
|
1830
|
+
grpc_error_set_int(GRPC_ERROR_CREATE("ping timeout"),
|
1831
|
+
grpc_core::StatusIntProperty::kRpcStatus,
|
1832
|
+
GRPC_STATUS_UNAVAILABLE));
|
1833
|
+
}),
|
1834
|
+
absl::OkStatus());
|
1835
|
+
}
|
1836
|
+
|
1837
|
+
void grpc_chttp2_settings_timeout(
|
1838
|
+
grpc_core::RefCountedPtr<grpc_chttp2_transport> t) {
|
1839
|
+
t->combiner->Run(
|
1840
|
+
grpc_core::NewClosure([t](grpc_error_handle) {
|
1841
|
+
gpr_log(GPR_INFO, "%s: Settings timeout. Closing transport.",
|
1842
|
+
std::string(t->peer_string.as_string_view()).c_str());
|
1843
|
+
send_goaway(
|
1844
|
+
t.get(),
|
1845
|
+
grpc_error_set_int(GRPC_ERROR_CREATE("settings_timeout"),
|
1846
|
+
grpc_core::StatusIntProperty::kHttp2Error,
|
1847
|
+
GRPC_HTTP2_SETTINGS_TIMEOUT),
|
1848
|
+
/*immediate_disconnect_hint=*/true);
|
1849
|
+
close_transport_locked(
|
1850
|
+
t.get(),
|
1851
|
+
grpc_error_set_int(GRPC_ERROR_CREATE("settings timeout"),
|
1852
|
+
grpc_core::StatusIntProperty::kRpcStatus,
|
1853
|
+
GRPC_STATUS_UNAVAILABLE));
|
1854
|
+
}),
|
1855
|
+
absl::OkStatus());
|
1856
|
+
}
|
1857
|
+
|
1717
1858
|
namespace {
|
1718
1859
|
|
1719
1860
|
// Fire and forget (deletes itself on completion). Does a graceful shutdown by
|
@@ -1733,20 +1874,13 @@ class GracefulGoaway : public grpc_core::RefCounted<GracefulGoaway> {
|
|
1733
1874
|
explicit GracefulGoaway(grpc_chttp2_transport* t) : t_(t->Ref()) {
|
1734
1875
|
t->sent_goaway_state = GRPC_CHTTP2_GRACEFUL_GOAWAY;
|
1735
1876
|
grpc_chttp2_goaway_append((1u << 31) - 1, 0, grpc_empty_slice(), &t->qbuf);
|
1877
|
+
t->keepalive_timeout =
|
1878
|
+
std::min(t->keepalive_timeout, grpc_core::Duration::Seconds(20));
|
1879
|
+
t->ping_timeout =
|
1880
|
+
std::min(t->ping_timeout, grpc_core::Duration::Seconds(20));
|
1736
1881
|
send_ping_locked(
|
1737
1882
|
t, nullptr, GRPC_CLOSURE_INIT(&on_ping_ack_, OnPingAck, this, nullptr));
|
1738
1883
|
grpc_chttp2_initiate_write(t, GRPC_CHTTP2_INITIATE_WRITE_GOAWAY_SENT);
|
1739
|
-
timer_handle_ = t_->event_engine->RunAfter(
|
1740
|
-
grpc_core::Duration::Seconds(20),
|
1741
|
-
[self = Ref(DEBUG_LOCATION, "GoawayTimer")]() mutable {
|
1742
|
-
grpc_core::ApplicationCallbackExecCtx callback_exec_ctx;
|
1743
|
-
grpc_core::ExecCtx exec_ctx;
|
1744
|
-
// The ref will be unreffed in the combiner.
|
1745
|
-
auto* ptr = self.release();
|
1746
|
-
ptr->t_->combiner->Run(
|
1747
|
-
GRPC_CLOSURE_INIT(&ptr->on_timer_, OnTimerLocked, ptr, nullptr),
|
1748
|
-
absl::OkStatus());
|
1749
|
-
});
|
1750
1884
|
}
|
1751
1885
|
|
1752
1886
|
void MaybeSendFinalGoawayLocked() {
|
@@ -1787,26 +1921,12 @@ class GracefulGoaway : public grpc_core::RefCounted<GracefulGoaway> {
|
|
1787
1921
|
|
1788
1922
|
static void OnPingAckLocked(void* arg, grpc_error_handle /* error */) {
|
1789
1923
|
auto* self = static_cast<GracefulGoaway*>(arg);
|
1790
|
-
if (self->timer_handle_ != TaskHandle::kInvalid) {
|
1791
|
-
self->t_->event_engine->Cancel(
|
1792
|
-
std::exchange(self->timer_handle_, TaskHandle::kInvalid));
|
1793
|
-
}
|
1794
|
-
self->MaybeSendFinalGoawayLocked();
|
1795
|
-
self->Unref();
|
1796
|
-
}
|
1797
|
-
|
1798
|
-
static void OnTimerLocked(void* arg, grpc_error_handle /* error */) {
|
1799
|
-
auto* self = static_cast<GracefulGoaway*>(arg);
|
1800
|
-
// Clearing the handle since the timer has fired and the handle is invalid.
|
1801
|
-
self->timer_handle_ = TaskHandle::kInvalid;
|
1802
1924
|
self->MaybeSendFinalGoawayLocked();
|
1803
1925
|
self->Unref();
|
1804
1926
|
}
|
1805
1927
|
|
1806
1928
|
const grpc_core::RefCountedPtr<grpc_chttp2_transport> t_;
|
1807
1929
|
grpc_closure on_ping_ack_;
|
1808
|
-
TaskHandle timer_handle_ = TaskHandle::kInvalid;
|
1809
|
-
grpc_closure on_timer_;
|
1810
1930
|
};
|
1811
1931
|
|
1812
1932
|
} // namespace
|
@@ -2059,8 +2179,8 @@ void grpc_chttp2_maybe_complete_recv_trailing_metadata(grpc_chttp2_transport* t,
|
|
2059
2179
|
}
|
2060
2180
|
}
|
2061
2181
|
|
2062
|
-
static
|
2063
|
-
|
2182
|
+
static grpc_chttp2_transport::RemovedStreamHandle remove_stream(
|
2183
|
+
grpc_chttp2_transport* t, uint32_t id, grpc_error_handle error) {
|
2064
2184
|
grpc_chttp2_stream* s = t->stream_map.extract(id).mapped();
|
2065
2185
|
GPR_DEBUG_ASSERT(s);
|
2066
2186
|
if (t->incoming_stream == s) {
|
@@ -2083,29 +2203,74 @@ static void remove_stream(grpc_chttp2_transport* t, uint32_t id,
|
|
2083
2203
|
grpc_chttp2_list_remove_stalled_by_transport(t, s);
|
2084
2204
|
|
2085
2205
|
maybe_start_some_streams(t);
|
2206
|
+
|
2207
|
+
if (t->is_client) return grpc_chttp2_transport::RemovedStreamHandle();
|
2208
|
+
return grpc_chttp2_transport::RemovedStreamHandle(t->Ref());
|
2086
2209
|
}
|
2087
2210
|
|
2211
|
+
namespace grpc_core {
|
2212
|
+
namespace {
|
2213
|
+
|
2214
|
+
Duration TarpitDuration(grpc_chttp2_transport* t) {
|
2215
|
+
return Duration::Milliseconds(absl::LogUniform<int>(
|
2216
|
+
absl::BitGen(), t->min_tarpit_duration_ms, t->max_tarpit_duration_ms));
|
2217
|
+
}
|
2218
|
+
|
2219
|
+
template <typename F>
|
2220
|
+
void MaybeTarpit(grpc_chttp2_transport* t, bool tarpit, F fn) {
|
2221
|
+
if (!tarpit || !t->allow_tarpit || t->is_client) {
|
2222
|
+
fn(t);
|
2223
|
+
return;
|
2224
|
+
}
|
2225
|
+
const auto duration = TarpitDuration(t);
|
2226
|
+
t->event_engine->RunAfter(
|
2227
|
+
duration, [t = t->Ref(), fn = std::move(fn)]() mutable {
|
2228
|
+
ApplicationCallbackExecCtx app_exec_ctx;
|
2229
|
+
ExecCtx exec_ctx;
|
2230
|
+
t->combiner->Run(
|
2231
|
+
NewClosure([t, fn = std::move(fn)](grpc_error_handle) mutable {
|
2232
|
+
// TODO(ctiller): this can result in not sending RST_STREAMS if a
|
2233
|
+
// request gets tarpit behind a transport close.
|
2234
|
+
if (!t->closed_with_error.ok()) return;
|
2235
|
+
fn(t.get());
|
2236
|
+
}),
|
2237
|
+
absl::OkStatus());
|
2238
|
+
});
|
2239
|
+
}
|
2240
|
+
|
2241
|
+
} // namespace
|
2242
|
+
} // namespace grpc_core
|
2243
|
+
|
2088
2244
|
void grpc_chttp2_cancel_stream(grpc_chttp2_transport* t, grpc_chttp2_stream* s,
|
2089
|
-
grpc_error_handle due_to_error) {
|
2245
|
+
grpc_error_handle due_to_error, bool tarpit) {
|
2090
2246
|
if (!t->is_client && !s->sent_trailing_metadata &&
|
2091
|
-
grpc_error_has_clear_grpc_status(due_to_error)
|
2092
|
-
|
2247
|
+
grpc_error_has_clear_grpc_status(due_to_error) &&
|
2248
|
+
!(s->read_closed && s->write_closed)) {
|
2249
|
+
close_from_api(t, s, due_to_error, tarpit);
|
2093
2250
|
return;
|
2094
2251
|
}
|
2095
2252
|
|
2253
|
+
if (!due_to_error.ok() && !s->seen_error) {
|
2254
|
+
s->seen_error = true;
|
2255
|
+
}
|
2096
2256
|
if (!s->read_closed || !s->write_closed) {
|
2097
2257
|
if (s->id != 0) {
|
2098
2258
|
grpc_http2_error_code http_error;
|
2099
2259
|
grpc_error_get_status(due_to_error, s->deadline, nullptr, nullptr,
|
2100
2260
|
&http_error, nullptr);
|
2101
|
-
|
2102
|
-
t,
|
2103
|
-
|
2261
|
+
grpc_core::MaybeTarpit(
|
2262
|
+
t, tarpit,
|
2263
|
+
[id = s->id, http_error,
|
2264
|
+
remove_stream_handle = grpc_chttp2_mark_stream_closed(
|
2265
|
+
t, s, 1, 1, due_to_error)](grpc_chttp2_transport* t) {
|
2266
|
+
grpc_chttp2_add_rst_stream_to_next_write(
|
2267
|
+
t, id, static_cast<uint32_t>(http_error), nullptr);
|
2268
|
+
grpc_chttp2_initiate_write(t,
|
2269
|
+
GRPC_CHTTP2_INITIATE_WRITE_RST_STREAM);
|
2270
|
+
});
|
2271
|
+
return;
|
2104
2272
|
}
|
2105
2273
|
}
|
2106
|
-
if (!due_to_error.ok() && !s->seen_error) {
|
2107
|
-
s->seen_error = true;
|
2108
|
-
}
|
2109
2274
|
grpc_chttp2_mark_stream_closed(t, s, 1, 1, due_to_error);
|
2110
2275
|
}
|
2111
2276
|
|
@@ -2198,9 +2363,10 @@ void grpc_chttp2_fail_pending_writes(grpc_chttp2_transport* t,
|
|
2198
2363
|
flush_write_list(t, s, &s->on_flow_controlled_cbs, error);
|
2199
2364
|
}
|
2200
2365
|
|
2201
|
-
|
2202
|
-
|
2203
|
-
|
2366
|
+
grpc_chttp2_transport::RemovedStreamHandle grpc_chttp2_mark_stream_closed(
|
2367
|
+
grpc_chttp2_transport* t, grpc_chttp2_stream* s, int close_reads,
|
2368
|
+
int close_writes, grpc_error_handle error) {
|
2369
|
+
grpc_chttp2_transport::RemovedStreamHandle rsh;
|
2204
2370
|
if (grpc_http_trace.enabled()) {
|
2205
2371
|
gpr_log(
|
2206
2372
|
GPR_DEBUG, "MARK_STREAM_CLOSED: t=%p s=%p(id=%d) %s [%s]", t, s, s->id,
|
@@ -2216,7 +2382,7 @@ void grpc_chttp2_mark_stream_closed(grpc_chttp2_transport* t,
|
|
2216
2382
|
grpc_chttp2_fake_status(t, s, overall_error);
|
2217
2383
|
}
|
2218
2384
|
grpc_chttp2_maybe_complete_recv_trailing_metadata(t, s);
|
2219
|
-
return;
|
2385
|
+
return rsh;
|
2220
2386
|
}
|
2221
2387
|
bool closed_read = false;
|
2222
2388
|
bool became_closed = false;
|
@@ -2234,7 +2400,7 @@ void grpc_chttp2_mark_stream_closed(grpc_chttp2_transport* t,
|
|
2234
2400
|
became_closed = true;
|
2235
2401
|
grpc_error_handle overall_error = removal_error(error, s, "Stream removed");
|
2236
2402
|
if (s->id != 0) {
|
2237
|
-
remove_stream(t, s->id, overall_error);
|
2403
|
+
rsh = remove_stream(t, s->id, overall_error);
|
2238
2404
|
} else {
|
2239
2405
|
// Purge streams waiting on concurrency still waiting for id assignment
|
2240
2406
|
grpc_chttp2_list_remove_waiting_for_concurrency(t, s);
|
@@ -2258,17 +2424,11 @@ void grpc_chttp2_mark_stream_closed(grpc_chttp2_transport* t,
|
|
2258
2424
|
grpc_chttp2_maybe_complete_recv_trailing_metadata(t, s);
|
2259
2425
|
GRPC_CHTTP2_STREAM_UNREF(s, "chttp2");
|
2260
2426
|
}
|
2427
|
+
return rsh;
|
2261
2428
|
}
|
2262
2429
|
|
2263
2430
|
static void close_from_api(grpc_chttp2_transport* t, grpc_chttp2_stream* s,
|
2264
|
-
grpc_error_handle error) {
|
2265
|
-
grpc_slice hdr;
|
2266
|
-
grpc_slice status_hdr;
|
2267
|
-
grpc_slice http_status_hdr;
|
2268
|
-
grpc_slice content_type_hdr;
|
2269
|
-
grpc_slice message_pfx;
|
2270
|
-
uint8_t* p;
|
2271
|
-
uint32_t len = 0;
|
2431
|
+
grpc_error_handle error, bool tarpit) {
|
2272
2432
|
grpc_status_code grpc_status;
|
2273
2433
|
std::string message;
|
2274
2434
|
grpc_error_get_status(error, s->deadline, &grpc_status, &message, nullptr,
|
@@ -2276,147 +2436,167 @@ static void close_from_api(grpc_chttp2_transport* t, grpc_chttp2_stream* s,
|
|
2276
2436
|
|
2277
2437
|
GPR_ASSERT(grpc_status >= 0 && (int)grpc_status < 100);
|
2278
2438
|
|
2279
|
-
|
2280
|
-
|
2281
|
-
|
2282
|
-
|
2283
|
-
|
2284
|
-
|
2285
|
-
|
2286
|
-
|
2287
|
-
|
2288
|
-
|
2289
|
-
|
2290
|
-
|
2291
|
-
|
2292
|
-
|
2293
|
-
|
2294
|
-
|
2295
|
-
|
2296
|
-
|
2297
|
-
|
2298
|
-
|
2299
|
-
|
2300
|
-
|
2301
|
-
|
2302
|
-
|
2303
|
-
|
2304
|
-
|
2305
|
-
|
2306
|
-
|
2307
|
-
|
2308
|
-
|
2309
|
-
|
2310
|
-
|
2311
|
-
|
2312
|
-
|
2313
|
-
|
2314
|
-
|
2315
|
-
|
2316
|
-
|
2317
|
-
|
2318
|
-
|
2319
|
-
|
2320
|
-
|
2321
|
-
|
2322
|
-
|
2323
|
-
|
2324
|
-
|
2325
|
-
|
2326
|
-
|
2327
|
-
|
2328
|
-
|
2329
|
-
|
2330
|
-
|
2331
|
-
|
2332
|
-
|
2333
|
-
|
2334
|
-
|
2335
|
-
|
2336
|
-
|
2337
|
-
|
2338
|
-
|
2339
|
-
|
2340
|
-
|
2341
|
-
|
2342
|
-
|
2343
|
-
|
2344
|
-
|
2345
|
-
|
2346
|
-
|
2347
|
-
|
2348
|
-
|
2349
|
-
|
2350
|
-
|
2351
|
-
|
2352
|
-
|
2353
|
-
|
2354
|
-
|
2355
|
-
|
2356
|
-
|
2357
|
-
|
2358
|
-
|
2359
|
-
|
2360
|
-
|
2361
|
-
|
2362
|
-
|
2363
|
-
|
2364
|
-
|
2365
|
-
|
2366
|
-
|
2367
|
-
|
2368
|
-
|
2369
|
-
|
2370
|
-
|
2371
|
-
|
2372
|
-
|
2373
|
-
|
2374
|
-
|
2375
|
-
|
2376
|
-
|
2377
|
-
|
2378
|
-
|
2379
|
-
|
2380
|
-
|
2381
|
-
|
2382
|
-
|
2383
|
-
|
2384
|
-
|
2385
|
-
|
2386
|
-
|
2387
|
-
|
2388
|
-
|
2389
|
-
|
2390
|
-
|
2391
|
-
|
2392
|
-
|
2393
|
-
|
2394
|
-
|
2395
|
-
|
2396
|
-
|
2397
|
-
|
2398
|
-
|
2399
|
-
|
2400
|
-
|
2401
|
-
|
2402
|
-
|
2403
|
-
|
2404
|
-
|
2405
|
-
|
2406
|
-
|
2407
|
-
|
2408
|
-
|
2409
|
-
|
2410
|
-
|
2411
|
-
|
2412
|
-
|
2413
|
-
|
2414
|
-
|
2415
|
-
|
2416
|
-
|
2417
|
-
|
2418
|
-
|
2419
|
-
|
2439
|
+
auto remove_stream_handle = grpc_chttp2_mark_stream_closed(t, s, 1, 1, error);
|
2440
|
+
grpc_core::MaybeTarpit(
|
2441
|
+
t, tarpit,
|
2442
|
+
[error = std::move(error),
|
2443
|
+
sent_initial_metadata = s->sent_initial_metadata, id = s->id,
|
2444
|
+
grpc_status, message = std::move(message),
|
2445
|
+
remove_stream_handle =
|
2446
|
+
std::move(remove_stream_handle)](grpc_chttp2_transport* t) mutable {
|
2447
|
+
grpc_slice hdr;
|
2448
|
+
grpc_slice status_hdr;
|
2449
|
+
grpc_slice http_status_hdr;
|
2450
|
+
grpc_slice content_type_hdr;
|
2451
|
+
grpc_slice message_pfx;
|
2452
|
+
uint8_t* p;
|
2453
|
+
uint32_t len = 0;
|
2454
|
+
|
2455
|
+
// Hand roll a header block.
|
2456
|
+
// This is unnecessarily ugly - at some point we should find a more
|
2457
|
+
// elegant solution.
|
2458
|
+
// It's complicated by the fact that our send machinery would be dead
|
2459
|
+
// by the time we got around to sending this, so instead we ignore
|
2460
|
+
// HPACK compression and just write the uncompressed bytes onto the
|
2461
|
+
// wire.
|
2462
|
+
if (!sent_initial_metadata) {
|
2463
|
+
http_status_hdr = GRPC_SLICE_MALLOC(13);
|
2464
|
+
p = GRPC_SLICE_START_PTR(http_status_hdr);
|
2465
|
+
*p++ = 0x00;
|
2466
|
+
*p++ = 7;
|
2467
|
+
*p++ = ':';
|
2468
|
+
*p++ = 's';
|
2469
|
+
*p++ = 't';
|
2470
|
+
*p++ = 'a';
|
2471
|
+
*p++ = 't';
|
2472
|
+
*p++ = 'u';
|
2473
|
+
*p++ = 's';
|
2474
|
+
*p++ = 3;
|
2475
|
+
*p++ = '2';
|
2476
|
+
*p++ = '0';
|
2477
|
+
*p++ = '0';
|
2478
|
+
GPR_ASSERT(p == GRPC_SLICE_END_PTR(http_status_hdr));
|
2479
|
+
len += static_cast<uint32_t> GRPC_SLICE_LENGTH(http_status_hdr);
|
2480
|
+
|
2481
|
+
content_type_hdr = GRPC_SLICE_MALLOC(31);
|
2482
|
+
p = GRPC_SLICE_START_PTR(content_type_hdr);
|
2483
|
+
*p++ = 0x00;
|
2484
|
+
*p++ = 12;
|
2485
|
+
*p++ = 'c';
|
2486
|
+
*p++ = 'o';
|
2487
|
+
*p++ = 'n';
|
2488
|
+
*p++ = 't';
|
2489
|
+
*p++ = 'e';
|
2490
|
+
*p++ = 'n';
|
2491
|
+
*p++ = 't';
|
2492
|
+
*p++ = '-';
|
2493
|
+
*p++ = 't';
|
2494
|
+
*p++ = 'y';
|
2495
|
+
*p++ = 'p';
|
2496
|
+
*p++ = 'e';
|
2497
|
+
*p++ = 16;
|
2498
|
+
*p++ = 'a';
|
2499
|
+
*p++ = 'p';
|
2500
|
+
*p++ = 'p';
|
2501
|
+
*p++ = 'l';
|
2502
|
+
*p++ = 'i';
|
2503
|
+
*p++ = 'c';
|
2504
|
+
*p++ = 'a';
|
2505
|
+
*p++ = 't';
|
2506
|
+
*p++ = 'i';
|
2507
|
+
*p++ = 'o';
|
2508
|
+
*p++ = 'n';
|
2509
|
+
*p++ = '/';
|
2510
|
+
*p++ = 'g';
|
2511
|
+
*p++ = 'r';
|
2512
|
+
*p++ = 'p';
|
2513
|
+
*p++ = 'c';
|
2514
|
+
GPR_ASSERT(p == GRPC_SLICE_END_PTR(content_type_hdr));
|
2515
|
+
len += static_cast<uint32_t> GRPC_SLICE_LENGTH(content_type_hdr);
|
2516
|
+
}
|
2517
|
+
|
2518
|
+
status_hdr = GRPC_SLICE_MALLOC(15 + (grpc_status >= 10));
|
2519
|
+
p = GRPC_SLICE_START_PTR(status_hdr);
|
2520
|
+
*p++ = 0x00; // literal header, not indexed
|
2521
|
+
*p++ = 11; // len(grpc-status)
|
2522
|
+
*p++ = 'g';
|
2523
|
+
*p++ = 'r';
|
2524
|
+
*p++ = 'p';
|
2525
|
+
*p++ = 'c';
|
2526
|
+
*p++ = '-';
|
2527
|
+
*p++ = 's';
|
2528
|
+
*p++ = 't';
|
2529
|
+
*p++ = 'a';
|
2530
|
+
*p++ = 't';
|
2531
|
+
*p++ = 'u';
|
2532
|
+
*p++ = 's';
|
2533
|
+
if (grpc_status < 10) {
|
2534
|
+
*p++ = 1;
|
2535
|
+
*p++ = static_cast<uint8_t>('0' + grpc_status);
|
2536
|
+
} else {
|
2537
|
+
*p++ = 2;
|
2538
|
+
*p++ = static_cast<uint8_t>('0' + (grpc_status / 10));
|
2539
|
+
*p++ = static_cast<uint8_t>('0' + (grpc_status % 10));
|
2540
|
+
}
|
2541
|
+
GPR_ASSERT(p == GRPC_SLICE_END_PTR(status_hdr));
|
2542
|
+
len += static_cast<uint32_t> GRPC_SLICE_LENGTH(status_hdr);
|
2543
|
+
|
2544
|
+
size_t msg_len = message.length();
|
2545
|
+
GPR_ASSERT(msg_len <= UINT32_MAX);
|
2546
|
+
grpc_core::VarintWriter<1> msg_len_writer(
|
2547
|
+
static_cast<uint32_t>(msg_len));
|
2548
|
+
message_pfx = GRPC_SLICE_MALLOC(14 + msg_len_writer.length());
|
2549
|
+
p = GRPC_SLICE_START_PTR(message_pfx);
|
2550
|
+
*p++ = 0x00; // literal header, not indexed
|
2551
|
+
*p++ = 12; // len(grpc-message)
|
2552
|
+
*p++ = 'g';
|
2553
|
+
*p++ = 'r';
|
2554
|
+
*p++ = 'p';
|
2555
|
+
*p++ = 'c';
|
2556
|
+
*p++ = '-';
|
2557
|
+
*p++ = 'm';
|
2558
|
+
*p++ = 'e';
|
2559
|
+
*p++ = 's';
|
2560
|
+
*p++ = 's';
|
2561
|
+
*p++ = 'a';
|
2562
|
+
*p++ = 'g';
|
2563
|
+
*p++ = 'e';
|
2564
|
+
msg_len_writer.Write(0, p);
|
2565
|
+
p += msg_len_writer.length();
|
2566
|
+
GPR_ASSERT(p == GRPC_SLICE_END_PTR(message_pfx));
|
2567
|
+
len += static_cast<uint32_t> GRPC_SLICE_LENGTH(message_pfx);
|
2568
|
+
len += static_cast<uint32_t>(msg_len);
|
2569
|
+
|
2570
|
+
hdr = GRPC_SLICE_MALLOC(9);
|
2571
|
+
p = GRPC_SLICE_START_PTR(hdr);
|
2572
|
+
*p++ = static_cast<uint8_t>(len >> 16);
|
2573
|
+
*p++ = static_cast<uint8_t>(len >> 8);
|
2574
|
+
*p++ = static_cast<uint8_t>(len);
|
2575
|
+
*p++ = GRPC_CHTTP2_FRAME_HEADER;
|
2576
|
+
*p++ = GRPC_CHTTP2_DATA_FLAG_END_STREAM |
|
2577
|
+
GRPC_CHTTP2_DATA_FLAG_END_HEADERS;
|
2578
|
+
*p++ = static_cast<uint8_t>(id >> 24);
|
2579
|
+
*p++ = static_cast<uint8_t>(id >> 16);
|
2580
|
+
*p++ = static_cast<uint8_t>(id >> 8);
|
2581
|
+
*p++ = static_cast<uint8_t>(id);
|
2582
|
+
GPR_ASSERT(p == GRPC_SLICE_END_PTR(hdr));
|
2583
|
+
|
2584
|
+
grpc_slice_buffer_add(&t->qbuf, hdr);
|
2585
|
+
if (!sent_initial_metadata) {
|
2586
|
+
grpc_slice_buffer_add(&t->qbuf, http_status_hdr);
|
2587
|
+
grpc_slice_buffer_add(&t->qbuf, content_type_hdr);
|
2588
|
+
}
|
2589
|
+
grpc_slice_buffer_add(&t->qbuf, status_hdr);
|
2590
|
+
grpc_slice_buffer_add(&t->qbuf, message_pfx);
|
2591
|
+
grpc_slice_buffer_add(&t->qbuf,
|
2592
|
+
grpc_slice_from_cpp_string(std::move(message)));
|
2593
|
+
grpc_chttp2_reset_ping_clock(t);
|
2594
|
+
grpc_chttp2_add_rst_stream_to_next_write(t, id, GRPC_HTTP2_NO_ERROR,
|
2595
|
+
nullptr);
|
2596
|
+
|
2597
|
+
grpc_chttp2_initiate_write(t,
|
2598
|
+
GRPC_CHTTP2_INITIATE_WRITE_CLOSE_FROM_API);
|
2599
|
+
});
|
2420
2600
|
}
|
2421
2601
|
|
2422
2602
|
static void end_all_the_calls(grpc_chttp2_transport* t,
|
@@ -2429,13 +2609,13 @@ static void end_all_the_calls(grpc_chttp2_transport* t,
|
|
2429
2609
|
error = grpc_error_set_int(error, grpc_core::StatusIntProperty::kRpcStatus,
|
2430
2610
|
GRPC_STATUS_UNAVAILABLE);
|
2431
2611
|
}
|
2432
|
-
cancel_unstarted_streams(t, error);
|
2612
|
+
cancel_unstarted_streams(t, error, false);
|
2433
2613
|
std::vector<grpc_chttp2_stream*> to_cancel;
|
2434
2614
|
for (auto id_stream : t->stream_map) {
|
2435
2615
|
to_cancel.push_back(id_stream.second);
|
2436
2616
|
}
|
2437
2617
|
for (auto s : to_cancel) {
|
2438
|
-
grpc_chttp2_cancel_stream(t, s, error);
|
2618
|
+
grpc_chttp2_cancel_stream(t, s, error, false);
|
2439
2619
|
}
|
2440
2620
|
}
|
2441
2621
|
|
@@ -2528,21 +2708,34 @@ static void read_action(grpc_core::RefCountedPtr<grpc_chttp2_transport> t,
|
|
2528
2708
|
error);
|
2529
2709
|
}
|
2530
2710
|
|
2531
|
-
static void
|
2711
|
+
static void read_action_parse_loop_locked(
|
2532
2712
|
grpc_core::RefCountedPtr<grpc_chttp2_transport> t,
|
2533
2713
|
grpc_error_handle error) {
|
2534
|
-
grpc_error_handle err = error;
|
2535
|
-
if (!err.ok()) {
|
2536
|
-
err = grpc_error_set_int(
|
2537
|
-
GRPC_ERROR_CREATE_REFERENCING("Endpoint read failed", &err, 1),
|
2538
|
-
grpc_core::StatusIntProperty::kOccurredDuringWrite, t->write_state);
|
2539
|
-
}
|
2540
|
-
std::swap(err, error);
|
2541
2714
|
if (t->closed_with_error.ok()) {
|
2542
|
-
size_t i = 0;
|
2543
2715
|
grpc_error_handle errors[3] = {error, absl::OkStatus(), absl::OkStatus()};
|
2544
|
-
|
2545
|
-
|
2716
|
+
size_t requests_started = 0;
|
2717
|
+
for (size_t i = 0;
|
2718
|
+
i < t->read_buffer.count && errors[1] == absl::OkStatus(); i++) {
|
2719
|
+
auto r = grpc_chttp2_perform_read(t.get(), t->read_buffer.slices[i],
|
2720
|
+
requests_started);
|
2721
|
+
if (auto* partial_read_size = absl::get_if<size_t>(&r)) {
|
2722
|
+
for (size_t j = 0; j < i; j++) {
|
2723
|
+
grpc_core::CSliceUnref(grpc_slice_buffer_take_first(&t->read_buffer));
|
2724
|
+
}
|
2725
|
+
grpc_slice_buffer_sub_first(
|
2726
|
+
&t->read_buffer, *partial_read_size,
|
2727
|
+
GRPC_SLICE_LENGTH(t->read_buffer.slices[0]));
|
2728
|
+
t->combiner->ForceOffload();
|
2729
|
+
auto* tp = t.get();
|
2730
|
+
tp->combiner->Run(
|
2731
|
+
grpc_core::InitTransportClosure<read_action_parse_loop_locked>(
|
2732
|
+
std::move(t), &tp->read_action_locked),
|
2733
|
+
std::move(errors[0]));
|
2734
|
+
// Early return: we queued to retry later.
|
2735
|
+
return;
|
2736
|
+
} else {
|
2737
|
+
errors[1] = std::move(absl::get<absl::Status>(r));
|
2738
|
+
}
|
2546
2739
|
}
|
2547
2740
|
if (errors[1] != absl::OkStatus()) {
|
2548
2741
|
errors[2] = try_http_parsing(t.get());
|
@@ -2601,6 +2794,33 @@ static void read_action_locked(
|
|
2601
2794
|
}
|
2602
2795
|
}
|
2603
2796
|
|
2797
|
+
static void read_action_locked(
|
2798
|
+
grpc_core::RefCountedPtr<grpc_chttp2_transport> t,
|
2799
|
+
grpc_error_handle error) {
|
2800
|
+
// got an incoming read, cancel any pending keepalive timers
|
2801
|
+
t->keepalive_incoming_data_wanted = false;
|
2802
|
+
if (t->keepalive_ping_timeout_handle !=
|
2803
|
+
grpc_event_engine::experimental::EventEngine::TaskHandle::kInvalid) {
|
2804
|
+
if (GRPC_TRACE_FLAG_ENABLED(grpc_ping_trace) ||
|
2805
|
+
GRPC_TRACE_FLAG_ENABLED(grpc_keepalive_trace)) {
|
2806
|
+
gpr_log(GPR_INFO,
|
2807
|
+
"%s[%p]: Clear keepalive timer because data was received",
|
2808
|
+
t->is_client ? "CLIENT" : "SERVER", t.get());
|
2809
|
+
}
|
2810
|
+
t->event_engine->Cancel(std::exchange(
|
2811
|
+
t->keepalive_ping_timeout_handle,
|
2812
|
+
grpc_event_engine::experimental::EventEngine::TaskHandle::kInvalid));
|
2813
|
+
}
|
2814
|
+
grpc_error_handle err = error;
|
2815
|
+
if (!err.ok()) {
|
2816
|
+
err = grpc_error_set_int(
|
2817
|
+
GRPC_ERROR_CREATE_REFERENCING("Endpoint read failed", &err, 1),
|
2818
|
+
grpc_core::StatusIntProperty::kOccurredDuringWrite, t->write_state);
|
2819
|
+
}
|
2820
|
+
std::swap(err, error);
|
2821
|
+
read_action_parse_loop_locked(std::move(t), std::move(err));
|
2822
|
+
}
|
2823
|
+
|
2604
2824
|
static void continue_read_action_locked(
|
2605
2825
|
grpc_core::RefCountedPtr<grpc_chttp2_transport> t) {
|
2606
2826
|
const bool urgent = !t->goaway_error.ok();
|
@@ -2793,39 +3013,6 @@ static void init_keepalive_ping_locked(
|
|
2793
3013
|
}
|
2794
3014
|
}
|
2795
3015
|
|
2796
|
-
static void start_keepalive_ping(
|
2797
|
-
grpc_core::RefCountedPtr<grpc_chttp2_transport> t,
|
2798
|
-
grpc_error_handle error) {
|
2799
|
-
auto* tp = t.get();
|
2800
|
-
tp->combiner->Run(
|
2801
|
-
grpc_core::InitTransportClosure<start_keepalive_ping_locked>(
|
2802
|
-
std::move(t), &tp->start_keepalive_ping_locked),
|
2803
|
-
error);
|
2804
|
-
}
|
2805
|
-
|
2806
|
-
static void start_keepalive_ping_locked(
|
2807
|
-
grpc_core::RefCountedPtr<grpc_chttp2_transport> t,
|
2808
|
-
grpc_error_handle error) {
|
2809
|
-
if (!error.ok()) {
|
2810
|
-
return;
|
2811
|
-
}
|
2812
|
-
if (t->channelz_socket != nullptr) {
|
2813
|
-
t->channelz_socket->RecordKeepaliveSent();
|
2814
|
-
}
|
2815
|
-
if (GRPC_TRACE_FLAG_ENABLED(grpc_http_trace) ||
|
2816
|
-
GRPC_TRACE_FLAG_ENABLED(grpc_keepalive_trace)) {
|
2817
|
-
gpr_log(GPR_INFO, "%s: Start keepalive ping",
|
2818
|
-
std::string(t->peer_string.as_string_view()).c_str());
|
2819
|
-
}
|
2820
|
-
t->keepalive_watchdog_timer_handle =
|
2821
|
-
t->event_engine->RunAfter(t->keepalive_timeout, [t]() mutable {
|
2822
|
-
grpc_core::ApplicationCallbackExecCtx callback_exec_ctx;
|
2823
|
-
grpc_core::ExecCtx exec_ctx;
|
2824
|
-
keepalive_watchdog_fired(std::move(t));
|
2825
|
-
});
|
2826
|
-
t->keepalive_ping_started = true;
|
2827
|
-
}
|
2828
|
-
|
2829
3016
|
static void finish_keepalive_ping(
|
2830
3017
|
grpc_core::RefCountedPtr<grpc_chttp2_transport> t,
|
2831
3018
|
grpc_error_handle error) {
|
@@ -2846,19 +3033,7 @@ static void finish_keepalive_ping_locked(
|
|
2846
3033
|
gpr_log(GPR_INFO, "%s: Finish keepalive ping",
|
2847
3034
|
std::string(t->peer_string.as_string_view()).c_str());
|
2848
3035
|
}
|
2849
|
-
if (!t->keepalive_ping_started) {
|
2850
|
-
// start_keepalive_ping_locked has not run yet. Reschedule
|
2851
|
-
// finish_keepalive_ping_locked for it to be run later.
|
2852
|
-
finish_keepalive_ping(std::move(t), std::move(error));
|
2853
|
-
return;
|
2854
|
-
}
|
2855
|
-
t->keepalive_ping_started = false;
|
2856
3036
|
t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_WAITING;
|
2857
|
-
if (t->keepalive_watchdog_timer_handle.has_value()) {
|
2858
|
-
if (t->event_engine->Cancel(*t->keepalive_watchdog_timer_handle)) {
|
2859
|
-
t->keepalive_watchdog_timer_handle.reset();
|
2860
|
-
}
|
2861
|
-
}
|
2862
3037
|
GPR_ASSERT(!t->keepalive_ping_timer_handle.has_value());
|
2863
3038
|
t->keepalive_ping_timer_handle =
|
2864
3039
|
t->event_engine->RunAfter(t->keepalive_time, [t] {
|
@@ -2870,39 +3045,6 @@ static void finish_keepalive_ping_locked(
|
|
2870
3045
|
}
|
2871
3046
|
}
|
2872
3047
|
|
2873
|
-
static void keepalive_watchdog_fired(
|
2874
|
-
grpc_core::RefCountedPtr<grpc_chttp2_transport> t) {
|
2875
|
-
auto* tp = t.get();
|
2876
|
-
tp->combiner->Run(
|
2877
|
-
grpc_core::InitTransportClosure<keepalive_watchdog_fired_locked>(
|
2878
|
-
std::move(t), &tp->keepalive_watchdog_fired_locked),
|
2879
|
-
absl::OkStatus());
|
2880
|
-
}
|
2881
|
-
|
2882
|
-
static void keepalive_watchdog_fired_locked(
|
2883
|
-
grpc_core::RefCountedPtr<grpc_chttp2_transport> t,
|
2884
|
-
GRPC_UNUSED grpc_error_handle error) {
|
2885
|
-
GPR_DEBUG_ASSERT(error.ok());
|
2886
|
-
GPR_ASSERT(t->keepalive_watchdog_timer_handle.has_value());
|
2887
|
-
t->keepalive_watchdog_timer_handle.reset();
|
2888
|
-
if (t->keepalive_state == GRPC_CHTTP2_KEEPALIVE_STATE_PINGING) {
|
2889
|
-
gpr_log(GPR_INFO, "%s: Keepalive watchdog fired. Closing transport.",
|
2890
|
-
std::string(t->peer_string.as_string_view()).c_str());
|
2891
|
-
t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_DYING;
|
2892
|
-
close_transport_locked(
|
2893
|
-
t.get(),
|
2894
|
-
grpc_error_set_int(GRPC_ERROR_CREATE("keepalive watchdog timeout"),
|
2895
|
-
grpc_core::StatusIntProperty::kRpcStatus,
|
2896
|
-
GRPC_STATUS_UNAVAILABLE));
|
2897
|
-
} else {
|
2898
|
-
// If keepalive_state is not PINGING, we consider it as an error. Maybe the
|
2899
|
-
// cancellation failed in finish_keepalive_ping_locked. Users have seen
|
2900
|
-
// other states: https://github.com/grpc/grpc/issues/32085.
|
2901
|
-
gpr_log(GPR_ERROR, "keepalive_ping_end state error: %d (expect: %d)",
|
2902
|
-
t->keepalive_state, GRPC_CHTTP2_KEEPALIVE_STATE_PINGING);
|
2903
|
-
}
|
2904
|
-
}
|
2905
|
-
|
2906
3048
|
static void maybe_reset_keepalive_ping_timer_locked(grpc_chttp2_transport* t) {
|
2907
3049
|
if (t->keepalive_ping_timer_handle.has_value()) {
|
2908
3050
|
if (t->event_engine->Cancel(*t->keepalive_ping_timer_handle)) {
|
@@ -3038,7 +3180,8 @@ static void destructive_reclaimer_locked(
|
|
3038
3180
|
t.get(), s,
|
3039
3181
|
grpc_error_set_int(GRPC_ERROR_CREATE("Buffers full"),
|
3040
3182
|
grpc_core::StatusIntProperty::kHttp2Error,
|
3041
|
-
GRPC_HTTP2_ENHANCE_YOUR_CALM)
|
3183
|
+
GRPC_HTTP2_ENHANCE_YOUR_CALM),
|
3184
|
+
false);
|
3042
3185
|
if (!t->stream_map.empty()) {
|
3043
3186
|
// Since we cancel one stream per destructive reclamation, if
|
3044
3187
|
// there are more streams left, we can immediately post a new
|