blob: 144780b67b047b51a8e7a31094ea8ae2950d9be5 [file] [log] [blame]
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001/*
2 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02003 * Copyright 2015 gRPC authors.
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08004 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02005 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08008 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02009 * http://www.apache.org/licenses/LICENSE-2.0
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080010 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +020011 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080016 *
17 */
18
Craig Tillerc7762a82016-03-28 10:13:08 -070019#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080020
Mark D. Rothc3c6faf2016-08-26 09:20:49 -070021#include <limits.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080022#include <math.h>
23#include <stdio.h>
24#include <string.h>
25
Craig Tiller0f310802016-10-26 16:25:56 -070026#include <grpc/slice_buffer.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080027#include <grpc/support/alloc.h>
28#include <grpc/support/log.h>
Craig Tiller285b8822015-06-17 15:58:13 -070029#include <grpc/support/string_util.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080030#include <grpc/support/useful.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080031
Muxi Yan29723ee2017-04-12 20:24:42 -070032#include "src/core/ext/transport/chttp2/transport/frame_data.h"
Craig Tillerc7762a82016-03-28 10:13:08 -070033#include "src/core/ext/transport/chttp2/transport/internal.h"
Craig Tiller599db642017-01-05 11:21:59 -080034#include "src/core/ext/transport/chttp2/transport/varint.h"
Mark D. Rothc3c6faf2016-08-26 09:20:49 -070035#include "src/core/lib/channel/channel_args.h"
Muxi Yane87a7e12017-06-29 16:53:24 -070036#include "src/core/lib/compression/stream_compression.h"
Craig Tiller57bb9a92017-08-31 16:44:15 -070037#include "src/core/lib/debug/stats.h"
Yuchen Zenga9d8c552016-06-02 16:11:28 -070038#include "src/core/lib/http/parser.h"
Craig Tillerf1633a92017-06-19 10:01:52 -070039#include "src/core/lib/iomgr/executor.h"
Yuchen Zeng990d9fe2017-02-26 16:54:18 -080040#include "src/core/lib/iomgr/timer.h"
Craig Tiller9533d042016-03-25 17:11:06 -070041#include "src/core/lib/profiling/timers.h"
Craig Tillera59c16c2016-10-31 07:25:01 -070042#include "src/core/lib/slice/slice_internal.h"
Craig Tiller0f310802016-10-26 16:25:56 -070043#include "src/core/lib/slice/slice_string_helpers.h"
Yuchen Zeng990d9fe2017-02-26 16:54:18 -080044#include "src/core/lib/support/env.h"
Craig Tiller9533d042016-03-25 17:11:06 -070045#include "src/core/lib/support/string.h"
Craig Tiller7c70b6c2017-01-23 07:48:42 -080046#include "src/core/lib/transport/error_utils.h"
47#include "src/core/lib/transport/http2_errors.h"
Craig Tiller9533d042016-03-25 17:11:06 -070048#include "src/core/lib/transport/static_metadata.h"
Craig Tiller7c70b6c2017-01-23 07:48:42 -080049#include "src/core/lib/transport/status_conversion.h"
Robbie Shade710d2422016-07-13 15:15:38 -040050#include "src/core/lib/transport/timeout_encoding.h"
Yuchen Zeng990d9fe2017-02-26 16:54:18 -080051#include "src/core/lib/transport/transport.h"
Craig Tiller9533d042016-03-25 17:11:06 -070052#include "src/core/lib/transport/transport_impl.h"
Craig Tiller08a1cf82015-06-29 09:37:52 -070053
ctiller493fbcc2014-12-07 15:09:10 -080054#define DEFAULT_WINDOW 65535
55#define DEFAULT_CONNECTION_WINDOW_TARGET (1024 * 1024)
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080056#define MAX_WINDOW 0x7fffffffu
Craig Tiller0a5a3182017-01-13 16:54:03 -080057#define MAX_WRITE_BUFFER_SIZE (64 * 1024 * 1024)
Mark D. Roth83737502017-06-09 07:27:16 -070058#define DEFAULT_MAX_HEADER_LIST_SIZE (8 * 1024)
Mark D. Rothbc846722016-05-04 10:53:50 -070059
Yuchen Zengc18d4b32017-03-29 15:04:42 -070060#define DEFAULT_CLIENT_KEEPALIVE_TIME_MS INT_MAX
Yuchen Zeng5f899962017-03-29 17:55:28 -070061#define DEFAULT_CLIENT_KEEPALIVE_TIMEOUT_MS 20000 /* 20 seconds */
62#define DEFAULT_SERVER_KEEPALIVE_TIME_MS 7200000 /* 2 hours */
63#define DEFAULT_SERVER_KEEPALIVE_TIMEOUT_MS 20000 /* 20 seconds */
Yuchen Zeng990d9fe2017-02-26 16:54:18 -080064#define DEFAULT_KEEPALIVE_PERMIT_WITHOUT_CALLS false
Yuchen Zeng8b0a4d22017-04-03 11:24:42 -070065#define KEEPALIVE_TIME_BACKOFF_MULTIPLIER 2
Yuchen Zeng990d9fe2017-02-26 16:54:18 -080066
Yuchen Zengd7eda612017-06-29 18:55:45 -070067#define DEFAULT_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS 300000 /* 5 minutes */
68#define DEFAULT_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS 300000 /* 5 minutes */
69#define DEFAULT_MAX_PINGS_BETWEEN_DATA 0 /* unlimited */
70#define DEFAULT_MAX_PING_STRIKES 2
71
Yuchen Zengc18d4b32017-03-29 15:04:42 -070072static int g_default_client_keepalive_time_ms =
73 DEFAULT_CLIENT_KEEPALIVE_TIME_MS;
74static int g_default_client_keepalive_timeout_ms =
75 DEFAULT_CLIENT_KEEPALIVE_TIMEOUT_MS;
Yuchen Zeng5f899962017-03-29 17:55:28 -070076static int g_default_server_keepalive_time_ms =
77 DEFAULT_SERVER_KEEPALIVE_TIME_MS;
78static int g_default_server_keepalive_timeout_ms =
79 DEFAULT_SERVER_KEEPALIVE_TIMEOUT_MS;
Yuchen Zeng3d43da72017-03-27 11:33:21 -070080static bool g_default_keepalive_permit_without_calls =
81 DEFAULT_KEEPALIVE_PERMIT_WITHOUT_CALLS;
82
Yuchen Zengd7eda612017-06-29 18:55:45 -070083static int g_default_min_sent_ping_interval_without_data_ms =
84 DEFAULT_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS;
85static int g_default_min_recv_ping_interval_without_data_ms =
86 DEFAULT_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS;
87static int g_default_max_pings_without_data = DEFAULT_MAX_PINGS_BETWEEN_DATA;
88static int g_default_max_ping_strikes = DEFAULT_MAX_PING_STRIKES;
89
Craig Tiller7098c032015-05-04 10:18:28 -070090#define MAX_CLIENT_STREAM_ID 0x7fffffffu
ncteisen06bce6e2017-07-10 07:58:49 -070091grpc_tracer_flag grpc_http_trace = GRPC_TRACER_INITIALIZER(false, "http");
92grpc_tracer_flag grpc_flowctl_trace = GRPC_TRACER_INITIALIZER(false, "flowctl");
Craig Tiller5dc3b302015-06-15 16:06:50 -070093
ncteisenffe72092017-04-24 15:36:56 -070094#ifndef NDEBUG
ncteisen7712c7c2017-07-12 23:11:27 -070095grpc_tracer_flag grpc_trace_chttp2_refcount =
96 GRPC_TRACER_INITIALIZER(false, "chttp2_refcount");
ncteisenffe72092017-04-24 15:36:56 -070097#endif
98
Craig Tiller4aa71a12015-06-15 13:00:55 -070099/* forward declarations of various callbacks that we'll build closures around */
Craig Tiller4e5b4522016-08-26 16:31:34 -0700100static void write_action_begin_locked(grpc_exec_ctx *exec_ctx, void *t,
101 grpc_error *error);
102static void write_action(grpc_exec_ctx *exec_ctx, void *t, grpc_error *error);
Craig Tiller4e5b4522016-08-26 16:31:34 -0700103static void write_action_end_locked(grpc_exec_ctx *exec_ctx, void *t,
Craig Tiller93023e42016-07-11 12:43:23 -0700104 grpc_error *error);
Craig Tiller99f80552015-06-11 16:26:03 -0700105
Craig Tiller4e5b4522016-08-26 16:31:34 -0700106static void read_action_locked(grpc_exec_ctx *exec_ctx, void *t,
107 grpc_error *error);
Craig Tillerd7906f52016-05-31 16:07:27 -0700108
Craig Tiller16966842016-08-29 10:34:57 -0700109static void complete_fetch_locked(grpc_exec_ctx *exec_ctx, void *gs,
110 grpc_error *error);
Craig Tiller4aa71a12015-06-15 13:00:55 -0700111/** Set a transport level setting, and push it to our peer */
ncteisen08cefa02017-06-20 11:29:26 -0700112static void queue_setting_update(grpc_exec_ctx *exec_ctx,
113 grpc_chttp2_transport *t,
114 grpc_chttp2_setting_id id, uint32_t value);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800115
Craig Tiller3d7c6092016-08-26 11:39:05 -0700116static void close_from_api(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
117 grpc_chttp2_stream *s, grpc_error *error);
Craig Tiller45ce9272015-07-31 11:22:35 -0700118
Craig Tiller564872d2015-06-18 11:21:22 -0700119/** Start new streams that have been created if we can */
Craig Tiller3d7c6092016-08-26 11:39:05 -0700120static void maybe_start_some_streams(grpc_exec_ctx *exec_ctx,
121 grpc_chttp2_transport *t);
Craig Tiller564872d2015-06-18 11:21:22 -0700122
Craig Tiller3d7c6092016-08-26 11:39:05 -0700123static void connectivity_state_set(grpc_exec_ctx *exec_ctx,
124 grpc_chttp2_transport *t,
125 grpc_connectivity_state state,
126 grpc_error *error, const char *reason);
Craig Tillerff3ae682015-06-29 17:44:04 -0700127
Craig Tillera3b54cd2016-03-25 15:59:55 -0700128static void incoming_byte_stream_destroy_locked(grpc_exec_ctx *exec_ctx,
Craig Tiller93023e42016-07-11 12:43:23 -0700129 void *byte_stream,
130 grpc_error *error_ignored);
Muxi Yan29723ee2017-04-12 20:24:42 -0700131static void incoming_byte_stream_publish_error(
132 grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_byte_stream *bs,
133 grpc_error *error);
134static void incoming_byte_stream_unref(grpc_exec_ctx *exec_ctx,
135 grpc_chttp2_incoming_byte_stream *bs);
Craig Tillerabb2e3d2015-12-15 06:23:59 -0800136
Craig Tiller25f29af2016-09-26 16:31:00 -0700137static void benign_reclaimer_locked(grpc_exec_ctx *exec_ctx, void *t,
138 grpc_error *error);
Craig Tiller25f29af2016-09-26 16:31:00 -0700139static void destructive_reclaimer_locked(grpc_exec_ctx *exec_ctx, void *t,
140 grpc_error *error);
141
Craig Tiller795451f2016-09-27 08:47:28 -0700142static void post_benign_reclaimer(grpc_exec_ctx *exec_ctx,
143 grpc_chttp2_transport *t);
144static void post_destructive_reclaimer(grpc_exec_ctx *exec_ctx,
145 grpc_chttp2_transport *t);
146
Craig Tiller936f1ea2016-10-14 15:15:19 -0700147static void close_transport_locked(grpc_exec_ctx *exec_ctx,
148 grpc_chttp2_transport *t, grpc_error *error);
149static void end_all_the_calls(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
150 grpc_error *error);
151
Craig Tiller57150a42016-12-29 11:01:18 -0800152static void start_bdp_ping_locked(grpc_exec_ctx *exec_ctx, void *tp,
153 grpc_error *error);
Craig Tillerf7970dd2016-10-20 16:49:13 -0700154static void finish_bdp_ping_locked(grpc_exec_ctx *exec_ctx, void *tp,
155 grpc_error *error);
156
157static void cancel_pings(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
158 grpc_error *error);
Craig Tiller3ff1fa62017-09-14 11:07:48 -0700159static void send_ping_locked(
160 grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
161 grpc_chttp2_ping_type ping_type, grpc_closure *on_initiate,
162 grpc_closure *on_complete,
163 grpc_chttp2_initiate_write_reason initiate_write_reason);
Yuchen Zengb4b6a0e2017-02-28 22:06:52 -0800164static void retry_initiate_ping_locked(grpc_exec_ctx *exec_ctx, void *tp,
165 grpc_error *error);
Craig Tillerf7970dd2016-10-20 16:49:13 -0700166
Yuchen Zeng990d9fe2017-02-26 16:54:18 -0800167/** keepalive-relevant functions */
Yuchen Zengefdf5a32017-02-26 23:29:54 -0800168static void init_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg,
169 grpc_error *error);
170static void start_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg,
171 grpc_error *error);
172static void finish_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg,
173 grpc_error *error);
Yuchen Zeng990d9fe2017-02-26 16:54:18 -0800174static void keepalive_watchdog_fired_locked(grpc_exec_ctx *exec_ctx, void *arg,
175 grpc_error *error);
176
Muxi Yan29723ee2017-04-12 20:24:42 -0700177static void reset_byte_stream(grpc_exec_ctx *exec_ctx, void *arg,
178 grpc_error *error);
179
Craig Tiller0cb803d2016-03-02 22:17:24 -0800180/*******************************************************************************
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800181 * CONSTRUCTION/DESTRUCTION/REFCOUNTING
182 */
183
Craig Tillera82950e2015-09-22 12:33:20 -0700184static void destruct_transport(grpc_exec_ctx *exec_ctx,
185 grpc_chttp2_transport *t) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800186 size_t i;
187
Craig Tiller93023e42016-07-11 12:43:23 -0700188 grpc_endpoint_destroy(exec_ctx, t->ep);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800189
Craig Tillera59c16c2016-10-31 07:25:01 -0700190 grpc_slice_buffer_destroy_internal(exec_ctx, &t->qbuf);
Craig Tiller1e6facb2015-06-11 22:47:11 -0700191
Craig Tillera59c16c2016-10-31 07:25:01 -0700192 grpc_slice_buffer_destroy_internal(exec_ctx, &t->outbuf);
193 grpc_chttp2_hpack_compressor_destroy(exec_ctx, &t->hpack_compressor);
Craig Tiller1e6facb2015-06-11 22:47:11 -0700194
Craig Tillera59c16c2016-10-31 07:25:01 -0700195 grpc_slice_buffer_destroy_internal(exec_ctx, &t->read_buffer);
Craig Tillerbd1795c2016-10-31 15:30:00 -0700196 grpc_chttp2_hpack_parser_destroy(exec_ctx, &t->hpack_parser);
Craig Tiller3d7c6092016-08-26 11:39:05 -0700197 grpc_chttp2_goaway_parser_destroy(&t->goaway_parser);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800198
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800199 for (i = 0; i < STREAM_LIST_COUNT; i++) {
200 GPR_ASSERT(t->lists[i].head == NULL);
201 GPR_ASSERT(t->lists[i].tail == NULL);
202 }
203
Craig Tiller796f5252016-08-19 10:44:48 -0700204 GPR_ASSERT(grpc_chttp2_stream_map_size(&t->stream_map) == 0);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800205
Craig Tiller796f5252016-08-19 10:44:48 -0700206 grpc_chttp2_stream_map_destroy(&t->stream_map);
Craig Tillera82950e2015-09-22 12:33:20 -0700207 grpc_connectivity_state_destroy(exec_ctx, &t->channel_callback.state_tracker);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800208
Craig Tiller3845e552017-02-09 15:19:28 -0800209 GRPC_COMBINER_UNREF(exec_ctx, t->combiner, "chttp2_transport");
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800210
ncteisen4b36a3d2017-03-13 19:08:06 -0700211 cancel_pings(exec_ctx, t,
212 GRPC_ERROR_CREATE_FROM_STATIC_STRING("Transport destroyed"));
Craig Tiller8ed35ea2015-01-30 11:27:43 -0800213
Craig Tillerdf1d3da2016-09-01 13:51:42 -0700214 while (t->write_cb_pool) {
215 grpc_chttp2_write_cb *next = t->write_cb_pool->next;
216 gpr_free(t->write_cb_pool);
217 t->write_cb_pool = next;
218 }
219
Craig Tiller2cf2c5a2017-01-30 09:49:31 -0800220 gpr_free(t->ping_acks);
Craig Tillera82950e2015-09-22 12:33:20 -0700221 gpr_free(t->peer_string);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800222 gpr_free(t);
223}
224
ncteisenffe72092017-04-24 15:36:56 -0700225#ifndef NDEBUG
Craig Tillerdfd3a8f2016-08-24 09:43:45 -0700226void grpc_chttp2_unref_transport(grpc_exec_ctx *exec_ctx,
227 grpc_chttp2_transport *t, const char *reason,
228 const char *file, int line) {
ncteisenffe72092017-04-24 15:36:56 -0700229 if (GRPC_TRACER_ON(grpc_trace_chttp2_refcount)) {
230 gpr_atm val = gpr_atm_no_barrier_load(&t->refs.count);
231 gpr_log(GPR_DEBUG, "chttp2:unref:%p %" PRIdPTR "->%" PRIdPTR " %s [%s:%d]",
232 t, val, val - 1, reason, file, line);
233 }
Craig Tiller759eb322015-06-16 22:41:18 -0700234 if (!gpr_unref(&t->refs)) return;
Craig Tillera82950e2015-09-22 12:33:20 -0700235 destruct_transport(exec_ctx, t);
Craig Tiller759eb322015-06-16 22:41:18 -0700236}
237
Craig Tillerdfd3a8f2016-08-24 09:43:45 -0700238void grpc_chttp2_ref_transport(grpc_chttp2_transport *t, const char *reason,
239 const char *file, int line) {
ncteisenffe72092017-04-24 15:36:56 -0700240 if (GRPC_TRACER_ON(grpc_trace_chttp2_refcount)) {
241 gpr_atm val = gpr_atm_no_barrier_load(&t->refs.count);
242 gpr_log(GPR_DEBUG, "chttp2: ref:%p %" PRIdPTR "->%" PRIdPTR " %s [%s:%d]",
243 t, val, val + 1, reason, file, line);
244 }
Craig Tiller285b8822015-06-17 15:58:13 -0700245 gpr_ref(&t->refs);
Craig Tiller759eb322015-06-16 22:41:18 -0700246}
247#else
Craig Tillerdfd3a8f2016-08-24 09:43:45 -0700248void grpc_chttp2_unref_transport(grpc_exec_ctx *exec_ctx,
249 grpc_chttp2_transport *t) {
Craig Tiller9be83ee2015-02-18 14:16:15 -0800250 if (!gpr_unref(&t->refs)) return;
Craig Tillera82950e2015-09-22 12:33:20 -0700251 destruct_transport(exec_ctx, t);
Craig Tiller9be83ee2015-02-18 14:16:15 -0800252}
253
Craig Tillerdfd3a8f2016-08-24 09:43:45 -0700254void grpc_chttp2_ref_transport(grpc_chttp2_transport *t) { gpr_ref(&t->refs); }
Craig Tiller759eb322015-06-16 22:41:18 -0700255#endif
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800256
Craig Tillera6ca5712017-07-11 14:51:57 -0700257static const grpc_transport_vtable *get_vtable(void);
258
Craig Tillera82950e2015-09-22 12:33:20 -0700259static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
Craig Tiller4aa71a12015-06-15 13:00:55 -0700260 const grpc_channel_args *channel_args,
Craig Tiller13d455e2016-05-27 12:06:34 -0700261 grpc_endpoint *ep, bool is_client) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800262 size_t i;
263 int j;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800264
Craig Tiller4aa71a12015-06-15 13:00:55 -0700265 GPR_ASSERT(strlen(GRPC_CHTTP2_CLIENT_CONNECT_STRING) ==
266 GRPC_CHTTP2_CLIENT_CONNECT_STRLEN);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800267
Craig Tillera6ca5712017-07-11 14:51:57 -0700268 t->base.vtable = get_vtable();
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800269 t->ep = ep;
Craig Tiller93023e42016-07-11 12:43:23 -0700270 /* one ref is for destroy */
271 gpr_ref_init(&t->refs, 1);
Craig Tilleree4b1452017-05-12 10:56:03 -0700272 t->combiner = grpc_combiner_create();
Craig Tillera82950e2015-09-22 12:33:20 -0700273 t->peer_string = grpc_endpoint_get_peer(ep);
Craig Tiller606d8742015-06-15 06:58:50 -0700274 t->endpoint_reading = 1;
Craig Tiller3d7c6092016-08-26 11:39:05 -0700275 t->next_stream_id = is_client ? 1 : 2;
276 t->is_client = is_client;
ncteisen3c909d52017-07-13 19:45:51 -0700277 t->flow_control.remote_window = DEFAULT_WINDOW;
278 t->flow_control.announced_window = DEFAULT_WINDOW;
ncteisen3c909d52017-07-13 19:45:51 -0700279 t->flow_control.t = t;
Craig Tiller3d7c6092016-08-26 11:39:05 -0700280 t->deframe_state = is_client ? GRPC_DTS_FH_0 : GRPC_DTS_CLIENT_PREFIX_0;
281 t->is_first_frame = true;
Craig Tillera82950e2015-09-22 12:33:20 -0700282 grpc_connectivity_state_init(
283 &t->channel_callback.state_tracker, GRPC_CHANNEL_READY,
284 is_client ? "client_transport" : "server_transport");
Craig Tiller42cdf942015-06-12 07:35:44 -0700285
Craig Tillerd41a4a72016-10-26 16:16:06 -0700286 grpc_slice_buffer_init(&t->qbuf);
Craig Tiller42cdf942015-06-12 07:35:44 -0700287
Craig Tillerd41a4a72016-10-26 16:16:06 -0700288 grpc_slice_buffer_init(&t->outbuf);
Craig Tiller3d7c6092016-08-26 11:39:05 -0700289 grpc_chttp2_hpack_compressor_init(&t->hpack_compressor);
Craig Tiller4e5b4522016-08-26 16:31:34 -0700290
ncteisen274bbbe2017-06-08 14:57:11 -0700291 GRPC_CLOSURE_INIT(&t->read_action_locked, read_action_locked, t,
Craig Tilleree4b1452017-05-12 10:56:03 -0700292 grpc_combiner_scheduler(t->combiner));
ncteisen274bbbe2017-06-08 14:57:11 -0700293 GRPC_CLOSURE_INIT(&t->benign_reclaimer_locked, benign_reclaimer_locked, t,
Craig Tilleree4b1452017-05-12 10:56:03 -0700294 grpc_combiner_scheduler(t->combiner));
ncteisen274bbbe2017-06-08 14:57:11 -0700295 GRPC_CLOSURE_INIT(&t->destructive_reclaimer_locked,
Craig Tiller91031da2016-12-28 15:44:25 -0800296 destructive_reclaimer_locked, t,
Craig Tilleree4b1452017-05-12 10:56:03 -0700297 grpc_combiner_scheduler(t->combiner));
ncteisen274bbbe2017-06-08 14:57:11 -0700298 GRPC_CLOSURE_INIT(&t->retry_initiate_ping_locked, retry_initiate_ping_locked,
Craig Tilleree4b1452017-05-12 10:56:03 -0700299 t, grpc_combiner_scheduler(t->combiner));
ncteisen274bbbe2017-06-08 14:57:11 -0700300 GRPC_CLOSURE_INIT(&t->start_bdp_ping_locked, start_bdp_ping_locked, t,
Craig Tilleree4b1452017-05-12 10:56:03 -0700301 grpc_combiner_scheduler(t->combiner));
ncteisen274bbbe2017-06-08 14:57:11 -0700302 GRPC_CLOSURE_INIT(&t->finish_bdp_ping_locked, finish_bdp_ping_locked, t,
Craig Tilleree4b1452017-05-12 10:56:03 -0700303 grpc_combiner_scheduler(t->combiner));
ncteisen274bbbe2017-06-08 14:57:11 -0700304 GRPC_CLOSURE_INIT(&t->init_keepalive_ping_locked, init_keepalive_ping_locked,
Craig Tilleree4b1452017-05-12 10:56:03 -0700305 t, grpc_combiner_scheduler(t->combiner));
ncteisen274bbbe2017-06-08 14:57:11 -0700306 GRPC_CLOSURE_INIT(&t->start_keepalive_ping_locked,
Yuchen Zengefdf5a32017-02-26 23:29:54 -0800307 start_keepalive_ping_locked, t,
Craig Tilleree4b1452017-05-12 10:56:03 -0700308 grpc_combiner_scheduler(t->combiner));
ncteisen274bbbe2017-06-08 14:57:11 -0700309 GRPC_CLOSURE_INIT(&t->finish_keepalive_ping_locked,
Yuchen Zengefdf5a32017-02-26 23:29:54 -0800310 finish_keepalive_ping_locked, t,
Craig Tilleree4b1452017-05-12 10:56:03 -0700311 grpc_combiner_scheduler(t->combiner));
ncteisen274bbbe2017-06-08 14:57:11 -0700312 GRPC_CLOSURE_INIT(&t->keepalive_watchdog_fired_locked,
Yuchen Zeng380a3be2017-02-26 23:37:50 -0800313 keepalive_watchdog_fired_locked, t,
Craig Tilleree4b1452017-05-12 10:56:03 -0700314 grpc_combiner_scheduler(t->combiner));
Craig Tillerf7970dd2016-10-20 16:49:13 -0700315
ncteisen41ba2682017-07-14 16:15:10 -0700316 grpc_bdp_estimator_init(&t->flow_control.bdp_estimator, t->peer_string);
317 t->flow_control.last_pid_update = gpr_now(GPR_CLOCK_MONOTONIC);
Craig Tiller68c9dbe2017-01-03 11:31:34 -0800318 grpc_pid_controller_init(
ncteisen41ba2682017-07-14 16:15:10 -0700319 &t->flow_control.pid_controller,
Craig Tiller68c9dbe2017-01-03 11:31:34 -0800320 (grpc_pid_controller_args){.gain_p = 4,
321 .gain_i = 8,
322 .gain_d = 0,
323 .initial_control_value = log2(DEFAULT_WINDOW),
324 .min_control_value = -1,
Craig Tillere2894b42017-02-15 08:12:55 -0800325 .max_control_value = 25,
Craig Tiller68c9dbe2017-01-03 11:31:34 -0800326 .integral_range = 10});
Craig Tiller42cdf942015-06-12 07:35:44 -0700327
Craig Tiller3d7c6092016-08-26 11:39:05 -0700328 grpc_chttp2_goaway_parser_init(&t->goaway_parser);
Craig Tillerbd1795c2016-10-31 15:30:00 -0700329 grpc_chttp2_hpack_parser_init(exec_ctx, &t->hpack_parser);
Craig Tiller42cdf942015-06-12 07:35:44 -0700330
Craig Tillerd41a4a72016-10-26 16:16:06 -0700331 grpc_slice_buffer_init(&t->read_buffer);
Craig Tillerb0298592015-08-27 07:38:01 -0700332
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800333 /* 8 is a random stab in the dark as to a good initial size: it's small enough
334 that it shouldn't waste memory for infrequently used connections, yet
335 large enough that the exponential growth should happen nicely when it's
336 needed.
337 TODO(ctiller): tune this */
Craig Tiller796f5252016-08-19 10:44:48 -0700338 grpc_chttp2_stream_map_init(&t->stream_map, 8);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800339
340 /* copy in initial settings to all setting sets */
Craig Tillercdf52bc2015-06-16 13:00:27 -0700341 for (i = 0; i < GRPC_CHTTP2_NUM_SETTINGS; i++) {
Craig Tillerab630732015-06-25 11:20:01 -0700342 for (j = 0; j < GRPC_NUM_SETTING_SETS; j++) {
Craig Tiller3d7c6092016-08-26 11:39:05 -0700343 t->settings[j][i] = grpc_chttp2_settings_parameters[i].default_value;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800344 }
345 }
Craig Tiller3d7c6092016-08-26 11:39:05 -0700346 t->dirtied_local_settings = 1;
ctiller493fbcc2014-12-07 15:09:10 -0800347 /* Hack: it's common for implementations to assume 65536 bytes initial send
348 window -- this should by rights be 0 */
Craig Tiller3d7c6092016-08-26 11:39:05 -0700349 t->force_send_settings = 1 << GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
350 t->sent_local_settings = 0;
Craig Tiller4e6247a2017-01-05 10:17:01 -0800351 t->write_buffer_size = DEFAULT_WINDOW;
ncteisen41ba2682017-07-14 16:15:10 -0700352 t->flow_control.enable_bdp_probe = true;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800353
Craig Tillerc8a85132016-07-13 10:18:53 -0700354 if (is_client) {
Craig Tillerd41a4a72016-10-26 16:16:06 -0700355 grpc_slice_buffer_add(&t->outbuf, grpc_slice_from_copied_string(
Craig Tiller0f310802016-10-26 16:25:56 -0700356 GRPC_CHTTP2_CLIENT_CONNECT_STRING));
Craig Tillerc8a85132016-07-13 10:18:53 -0700357 }
358
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800359 /* configure http2 the way we like it */
Craig Tiller606d8742015-06-15 06:58:50 -0700360 if (is_client) {
ncteisen08cefa02017-06-20 11:29:26 -0700361 queue_setting_update(exec_ctx, t, GRPC_CHTTP2_SETTINGS_ENABLE_PUSH, 0);
362 queue_setting_update(exec_ctx, t,
363 GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 0);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800364 }
ncteisen08cefa02017-06-20 11:29:26 -0700365 queue_setting_update(exec_ctx, t, GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE,
366 DEFAULT_WINDOW);
367 queue_setting_update(exec_ctx, t, GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE,
368 DEFAULT_MAX_HEADER_LIST_SIZE);
369 queue_setting_update(exec_ctx, t,
370 GRPC_CHTTP2_SETTINGS_GRPC_ALLOW_TRUE_BINARY_METADATA, 1);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800371
Craig Tiller1b36a7d2017-01-03 16:19:16 -0800372 t->ping_policy = (grpc_chttp2_repeated_ping_policy){
Yuchen Zengd7eda612017-06-29 18:55:45 -0700373 .max_pings_without_data = g_default_max_pings_without_data,
Yuchen Zengad320752017-05-15 15:38:06 -0700374 .min_sent_ping_interval_without_data = gpr_time_from_millis(
Yuchen Zengd7eda612017-06-29 18:55:45 -0700375 g_default_min_sent_ping_interval_without_data_ms, GPR_TIMESPAN),
376 .max_ping_strikes = g_default_max_ping_strikes,
Yuchen Zengad320752017-05-15 15:38:06 -0700377 .min_recv_ping_interval_without_data = gpr_time_from_millis(
Yuchen Zengd7eda612017-06-29 18:55:45 -0700378 g_default_min_recv_ping_interval_without_data_ms, GPR_TIMESPAN),
Craig Tiller1b36a7d2017-01-03 16:19:16 -0800379 };
380
Yuchen Zeng5f899962017-03-29 17:55:28 -0700381 /* Keepalive setting */
382 if (t->is_client) {
383 t->keepalive_time =
384 g_default_client_keepalive_time_ms == INT_MAX
385 ? gpr_inf_future(GPR_TIMESPAN)
386 : gpr_time_from_millis(g_default_client_keepalive_time_ms,
387 GPR_TIMESPAN);
388 t->keepalive_timeout =
389 g_default_client_keepalive_timeout_ms == INT_MAX
390 ? gpr_inf_future(GPR_TIMESPAN)
391 : gpr_time_from_millis(g_default_client_keepalive_timeout_ms,
392 GPR_TIMESPAN);
393 } else {
394 t->keepalive_time =
395 g_default_server_keepalive_time_ms == INT_MAX
396 ? gpr_inf_future(GPR_TIMESPAN)
397 : gpr_time_from_millis(g_default_server_keepalive_time_ms,
398 GPR_TIMESPAN);
399 t->keepalive_timeout =
400 g_default_server_keepalive_timeout_ms == INT_MAX
401 ? gpr_inf_future(GPR_TIMESPAN)
402 : gpr_time_from_millis(g_default_server_keepalive_timeout_ms,
403 GPR_TIMESPAN);
404 }
Yuchen Zeng3d43da72017-03-27 11:33:21 -0700405 t->keepalive_permit_without_calls = g_default_keepalive_permit_without_calls;
Yuchen Zeng990d9fe2017-02-26 16:54:18 -0800406
Craig Tillerf1633a92017-06-19 10:01:52 -0700407 t->opt_target = GRPC_CHTTP2_OPTIMIZE_FOR_LATENCY;
408
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800409 if (channel_args) {
410 for (i = 0; i < channel_args->num_args; i++) {
Craig Tiller1edc77c2016-09-20 11:02:51 -0700411 if (0 == strcmp(channel_args->args[i].key,
412 GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER)) {
Mark D. Rothc3c6faf2016-08-26 09:20:49 -0700413 const grpc_integer_options options = {-1, 0, INT_MAX};
Mark D. Rothc09e21f2016-08-26 13:34:53 -0700414 const int value =
415 grpc_channel_arg_get_integer(&channel_args->args[i], options);
Mark D. Rothc3c6faf2016-08-26 09:20:49 -0700416 if (value >= 0) {
Craig Tiller1edc77c2016-09-20 11:02:51 -0700417 if ((t->next_stream_id & 1) != (value & 1)) {
Mark D. Rothc3c6faf2016-08-26 09:20:49 -0700418 gpr_log(GPR_ERROR, "%s: low bit must be %d on %s",
419 GRPC_ARG_HTTP2_INITIAL_SEQUENCE_NUMBER,
Craig Tiller1edc77c2016-09-20 11:02:51 -0700420 t->next_stream_id & 1, is_client ? "client" : "server");
Mark D. Rothc3c6faf2016-08-26 09:20:49 -0700421 } else {
Craig Tiller1edc77c2016-09-20 11:02:51 -0700422 t->next_stream_id = (uint32_t)value;
Mark D. Rothc3c6faf2016-08-26 09:20:49 -0700423 }
Craig Tillera82950e2015-09-22 12:33:20 -0700424 }
Craig Tiller3c53bb22015-11-10 14:24:36 +0000425 } else if (0 == strcmp(channel_args->args[i].key,
Craig Tiller3c53bb22015-11-10 14:24:36 +0000426 GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_ENCODER)) {
Mark D. Rothc3c6faf2016-08-26 09:20:49 -0700427 const grpc_integer_options options = {-1, 0, INT_MAX};
Mark D. Rothc09e21f2016-08-26 13:34:53 -0700428 const int value =
429 grpc_channel_arg_get_integer(&channel_args->args[i], options);
Mark D. Rothc3c6faf2016-08-26 09:20:49 -0700430 if (value >= 0) {
Craig Tiller1edc77c2016-09-20 11:02:51 -0700431 grpc_chttp2_hpack_compressor_set_max_usable_size(&t->hpack_compressor,
432 (uint32_t)value);
Craig Tiller88025582015-05-04 09:41:10 -0700433 }
Craig Tiller1b36a7d2017-01-03 16:19:16 -0800434 } else if (0 == strcmp(channel_args->args[i].key,
435 GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA)) {
436 t->ping_policy.max_pings_without_data = grpc_channel_arg_get_integer(
437 &channel_args->args[i],
Yuchen Zengd7eda612017-06-29 18:55:45 -0700438 (grpc_integer_options){g_default_max_pings_without_data, 0,
439 INT_MAX});
Craig Tiller1b36a7d2017-01-03 16:19:16 -0800440 } else if (0 == strcmp(channel_args->args[i].key,
Yuchen Zeng0937fc12017-02-27 23:19:00 -0800441 GRPC_ARG_HTTP2_MAX_PING_STRIKES)) {
442 t->ping_policy.max_ping_strikes = grpc_channel_arg_get_integer(
443 &channel_args->args[i],
Yuchen Zengd7eda612017-06-29 18:55:45 -0700444 (grpc_integer_options){g_default_max_ping_strikes, 0, INT_MAX});
Yuchen Zengc18d4b32017-03-29 15:04:42 -0700445 } else if (0 ==
Yuchen Zengad320752017-05-15 15:38:06 -0700446 strcmp(
447 channel_args->args[i].key,
448 GRPC_ARG_HTTP2_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS)) {
449 t->ping_policy.min_sent_ping_interval_without_data =
450 gpr_time_from_millis(
451 grpc_channel_arg_get_integer(
452 &channel_args->args[i],
453 (grpc_integer_options){
Yuchen Zengd7eda612017-06-29 18:55:45 -0700454 g_default_min_sent_ping_interval_without_data_ms, 0,
Yuchen Zengad320752017-05-15 15:38:06 -0700455 INT_MAX}),
456 GPR_TIMESPAN);
457 } else if (0 ==
458 strcmp(
459 channel_args->args[i].key,
460 GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS)) {
461 t->ping_policy.min_recv_ping_interval_without_data =
462 gpr_time_from_millis(
463 grpc_channel_arg_get_integer(
464 &channel_args->args[i],
465 (grpc_integer_options){
Yuchen Zengd7eda612017-06-29 18:55:45 -0700466 g_default_min_recv_ping_interval_without_data_ms, 0,
Yuchen Zengad320752017-05-15 15:38:06 -0700467 INT_MAX}),
468 GPR_TIMESPAN);
Craig Tillera66243d2017-01-17 12:23:05 -0800469 } else if (0 == strcmp(channel_args->args[i].key,
Craig Tiller4e6247a2017-01-05 10:17:01 -0800470 GRPC_ARG_HTTP2_WRITE_BUFFER_SIZE)) {
471 t->write_buffer_size = (uint32_t)grpc_channel_arg_get_integer(
472 &channel_args->args[i],
Craig Tiller0a5a3182017-01-13 16:54:03 -0800473 (grpc_integer_options){0, 0, MAX_WRITE_BUFFER_SIZE});
Craig Tiller78e64512017-02-07 07:03:26 -0800474 } else if (0 ==
475 strcmp(channel_args->args[i].key, GRPC_ARG_HTTP2_BDP_PROBE)) {
ncteisen41ba2682017-07-14 16:15:10 -0700476 t->flow_control.enable_bdp_probe = grpc_channel_arg_get_integer(
Craig Tiller78e64512017-02-07 07:03:26 -0800477 &channel_args->args[i], (grpc_integer_options){1, 0, 1});
Yuchen Zeng990d9fe2017-02-26 16:54:18 -0800478 } else if (0 == strcmp(channel_args->args[i].key,
Yuchen Zeng5f899962017-03-29 17:55:28 -0700479 GRPC_ARG_KEEPALIVE_TIME_MS)) {
Yuchen Zeng990d9fe2017-02-26 16:54:18 -0800480 const int value = grpc_channel_arg_get_integer(
481 &channel_args->args[i],
Yuchen Zeng5f899962017-03-29 17:55:28 -0700482 (grpc_integer_options){t->is_client
483 ? g_default_client_keepalive_time_ms
484 : g_default_server_keepalive_time_ms,
485 1, INT_MAX});
Yuchen Zeng990d9fe2017-02-26 16:54:18 -0800486 t->keepalive_time = value == INT_MAX
487 ? gpr_inf_future(GPR_TIMESPAN)
Yuchen Zengc18d4b32017-03-29 15:04:42 -0700488 : gpr_time_from_millis(value, GPR_TIMESPAN);
Yuchen Zeng990d9fe2017-02-26 16:54:18 -0800489 } else if (0 == strcmp(channel_args->args[i].key,
Yuchen Zeng5f899962017-03-29 17:55:28 -0700490 GRPC_ARG_KEEPALIVE_TIMEOUT_MS)) {
Yuchen Zeng990d9fe2017-02-26 16:54:18 -0800491 const int value = grpc_channel_arg_get_integer(
492 &channel_args->args[i],
Yuchen Zeng5f899962017-03-29 17:55:28 -0700493 (grpc_integer_options){t->is_client
494 ? g_default_client_keepalive_timeout_ms
495 : g_default_server_keepalive_timeout_ms,
496 0, INT_MAX});
Yuchen Zeng990d9fe2017-02-26 16:54:18 -0800497 t->keepalive_timeout = value == INT_MAX
498 ? gpr_inf_future(GPR_TIMESPAN)
Yuchen Zengc18d4b32017-03-29 15:04:42 -0700499 : gpr_time_from_millis(value, GPR_TIMESPAN);
Yuchen Zeng990d9fe2017-02-26 16:54:18 -0800500 } else if (0 == strcmp(channel_args->args[i].key,
Yuchen Zeng3d43da72017-03-27 11:33:21 -0700501 GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS)) {
Yuchen Zeng990d9fe2017-02-26 16:54:18 -0800502 t->keepalive_permit_without_calls =
503 (uint32_t)grpc_channel_arg_get_integer(
Yuchen Zenge0b1e462017-02-27 11:03:07 -0800504 &channel_args->args[i], (grpc_integer_options){0, 0, 1});
Craig Tillerf1633a92017-06-19 10:01:52 -0700505 } else if (0 == strcmp(channel_args->args[i].key,
506 GRPC_ARG_OPTIMIZATION_TARGET)) {
507 if (channel_args->args[i].type != GRPC_ARG_STRING) {
508 gpr_log(GPR_ERROR, "%s should be a string",
509 GRPC_ARG_OPTIMIZATION_TARGET);
510 } else if (0 == strcmp(channel_args->args[i].value.string, "blend")) {
511 t->opt_target = GRPC_CHTTP2_OPTIMIZE_FOR_LATENCY;
512 } else if (0 == strcmp(channel_args->args[i].value.string, "latency")) {
513 t->opt_target = GRPC_CHTTP2_OPTIMIZE_FOR_LATENCY;
514 } else if (0 ==
515 strcmp(channel_args->args[i].value.string, "throughput")) {
516 t->opt_target = GRPC_CHTTP2_OPTIMIZE_FOR_THROUGHPUT;
517 } else {
518 gpr_log(GPR_ERROR, "%s value '%s' unknown, assuming 'blend'",
519 GRPC_ARG_OPTIMIZATION_TARGET,
520 channel_args->args[i].value.string);
521 }
Craig Tiller1edc77c2016-09-20 11:02:51 -0700522 } else {
523 static const struct {
524 const char *channel_arg_name;
525 grpc_chttp2_setting_id setting_id;
526 grpc_integer_options integer_options;
Craig Tiller1808bbd2016-09-20 11:29:34 -0700527 bool availability[2] /* server, client */;
Craig Tiller87c79792017-04-03 17:05:12 -0700528 } settings_map[] = {
529 {GRPC_ARG_MAX_CONCURRENT_STREAMS,
530 GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS,
531 {-1, 0, INT32_MAX},
532 {true, false}},
533 {GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER,
534 GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE,
535 {-1, 0, INT32_MAX},
536 {true, true}},
537 {GRPC_ARG_MAX_METADATA_SIZE,
538 GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE,
539 {-1, 0, INT32_MAX},
540 {true, true}},
541 {GRPC_ARG_HTTP2_MAX_FRAME_SIZE,
542 GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE,
543 {-1, 16384, 16777215},
544 {true, true}},
545 {GRPC_ARG_HTTP2_ENABLE_TRUE_BINARY,
546 GRPC_CHTTP2_SETTINGS_GRPC_ALLOW_TRUE_BINARY_METADATA,
547 {1, 0, 1},
548 {true, true}},
549 {GRPC_ARG_HTTP2_STREAM_LOOKAHEAD_BYTES,
550 GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE,
551 {-1, 5, INT32_MAX},
552 {true, true}}};
Craig Tiller1808bbd2016-09-20 11:29:34 -0700553 for (j = 0; j < (int)GPR_ARRAY_SIZE(settings_map); j++) {
Craig Tiller1edc77c2016-09-20 11:02:51 -0700554 if (0 == strcmp(channel_args->args[i].key,
555 settings_map[j].channel_arg_name)) {
556 if (!settings_map[j].availability[is_client]) {
557 gpr_log(GPR_DEBUG, "%s is not available on %s",
558 settings_map[j].channel_arg_name,
559 is_client ? "clients" : "servers");
560 } else {
561 int value = grpc_channel_arg_get_integer(
562 &channel_args->args[i], settings_map[j].integer_options);
563 if (value >= 0) {
ncteisen08cefa02017-06-20 11:29:26 -0700564 queue_setting_update(exec_ctx, t, settings_map[j].setting_id,
565 (uint32_t)value);
Craig Tiller1edc77c2016-09-20 11:02:51 -0700566 }
567 }
568 break;
569 }
Craig Tiller24096ce2016-08-24 15:54:29 -0700570 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800571 }
572 }
573 }
Craig Tiller198036f2016-07-13 16:25:13 -0700574
Yuchen Zeng6a8c0ac2017-05-14 23:18:05 -0700575 /* No pings allowed before receiving a header or data frame. */
576 t->ping_state.pings_before_data_required = 0;
Yuchen Zengcbcdb402017-03-01 01:42:18 -0800577 t->ping_state.is_delayed_ping_timer_set = false;
Craig Tillerfa057952017-01-30 10:16:02 -0800578
Yuchen Zeng0937fc12017-02-27 23:19:00 -0800579 t->ping_recv_state.last_ping_recv_time = gpr_inf_past(GPR_CLOCK_MONOTONIC);
580 t->ping_recv_state.ping_strikes = 0;
581
Yuchen Zeng5f899962017-03-29 17:55:28 -0700582 /* Start keepalive pings */
583 if (gpr_time_cmp(t->keepalive_time, gpr_inf_future(GPR_TIMESPAN)) != 0) {
Yuchen Zeng990d9fe2017-02-26 16:54:18 -0800584 t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_WAITING;
Yuchen Zengefdf5a32017-02-26 23:29:54 -0800585 GRPC_CHTTP2_REF_TRANSPORT(t, "init keepalive ping");
Yuchen Zeng990d9fe2017-02-26 16:54:18 -0800586 grpc_timer_init(
587 exec_ctx, &t->keepalive_ping_timer,
588 gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), t->keepalive_time),
Yuchen Zeng380a3be2017-02-26 23:37:50 -0800589 &t->init_keepalive_ping_locked, gpr_now(GPR_CLOCK_MONOTONIC));
Yuchen Zeng6cb260a2017-04-05 18:44:36 -0700590 } else {
Yuchen Zengaaa779e2017-04-12 18:06:36 -0700591 /* Use GRPC_CHTTP2_KEEPALIVE_STATE_DISABLED to indicate there are no
592 inflight keeaplive timers */
593 t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_DISABLED;
Yuchen Zeng990d9fe2017-02-26 16:54:18 -0800594 }
595
Craig Tiller3ff1fa62017-09-14 11:07:48 -0700596 grpc_chttp2_initiate_write(exec_ctx, t,
597 GRPC_CHTTP2_INITIATE_WRITE_INITIAL_WRITE);
Craig Tillerdd339ea2016-09-27 13:21:31 -0700598 post_benign_reclaimer(exec_ctx, t);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800599}
600
Craig Tiller93023e42016-07-11 12:43:23 -0700601static void destroy_transport_locked(grpc_exec_ctx *exec_ctx, void *tp,
602 grpc_error *error) {
Yash Tibrewal7cdd99c2017-09-08 16:04:12 -0700603 grpc_chttp2_transport *t = (grpc_chttp2_transport *)tp;
Craig Tiller1fe7b9d2015-02-17 11:57:02 -0800604 t->destroying = 1;
Craig Tiller936f1ea2016-10-14 15:15:19 -0700605 close_transport_locked(
606 exec_ctx, t,
ncteisen4b36a3d2017-03-13 19:08:06 -0700607 grpc_error_set_int(
608 GRPC_ERROR_CREATE_FROM_STATIC_STRING("Transport destroyed"),
609 GRPC_ERROR_INT_OCCURRED_DURING_WRITE, t->write_state));
Craig Tillerdfd3a8f2016-08-24 09:43:45 -0700610 GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "destroy");
Craig Tiller1766a912015-06-22 16:43:43 -0700611}
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800612
Craig Tiller45b135e2016-03-22 16:02:39 -0700613static void destroy_transport(grpc_exec_ctx *exec_ctx, grpc_transport *gt) {
Craig Tiller1766a912015-06-22 16:43:43 -0700614 grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
ncteisen274bbbe2017-06-08 14:57:11 -0700615 GRPC_CLOSURE_SCHED(exec_ctx,
616 GRPC_CLOSURE_CREATE(destroy_transport_locked, t,
Craig Tilleree4b1452017-05-12 10:56:03 -0700617 grpc_combiner_scheduler(t->combiner)),
Craig Tiller91031da2016-12-28 15:44:25 -0800618 GRPC_ERROR_NONE);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800619}
620
Craig Tillera82950e2015-09-22 12:33:20 -0700621static void close_transport_locked(grpc_exec_ctx *exec_ctx,
Craig Tillerd76eb8a2016-03-22 08:49:28 -0700622 grpc_chttp2_transport *t,
Craig Tiller804ff712016-05-05 16:25:40 -0700623 grpc_error *error) {
Craig Tillera82950e2015-09-22 12:33:20 -0700624 if (!t->closed) {
murgatroid99d0cda5c2017-03-07 18:04:52 -0800625 if (!grpc_error_has_clear_grpc_status(error)) {
626 error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS,
627 GRPC_STATUS_UNAVAILABLE);
628 }
Craig Tiller936f1ea2016-10-14 15:15:19 -0700629 if (t->write_state != GRPC_CHTTP2_WRITE_STATE_IDLE) {
630 if (t->close_transport_on_writes_finished == NULL) {
631 t->close_transport_on_writes_finished =
ncteisen4b36a3d2017-03-13 19:08:06 -0700632 GRPC_ERROR_CREATE_FROM_STATIC_STRING(
633 "Delayed close due to in-progress write");
Craig Tiller936f1ea2016-10-14 15:15:19 -0700634 }
635 t->close_transport_on_writes_finished =
636 grpc_error_add_child(t->close_transport_on_writes_finished, error);
637 return;
638 }
Craig Tillera82950e2015-09-22 12:33:20 -0700639 t->closed = 1;
Craig Tiller3d7c6092016-08-26 11:39:05 -0700640 connectivity_state_set(exec_ctx, t, GRPC_CHANNEL_SHUTDOWN,
Craig Tiller71d28ad2016-05-07 21:48:44 -0700641 GRPC_ERROR_REF(error), "close_transport");
Craig Tillercda759d2017-01-27 11:37:37 -0800642 grpc_endpoint_shutdown(exec_ctx, t->ep, GRPC_ERROR_REF(error));
Yuchen Zengad320752017-05-15 15:38:06 -0700643 if (t->ping_state.is_delayed_ping_timer_set) {
644 grpc_timer_cancel(exec_ctx, &t->ping_state.delayed_ping_timer);
645 }
Yuchen Zeng6cb260a2017-04-05 18:44:36 -0700646 switch (t->keepalive_state) {
Yuchen Zengaaa779e2017-04-12 18:06:36 -0700647 case GRPC_CHTTP2_KEEPALIVE_STATE_WAITING:
Yuchen Zeng6cb260a2017-04-05 18:44:36 -0700648 grpc_timer_cancel(exec_ctx, &t->keepalive_ping_timer);
649 break;
Yuchen Zengaaa779e2017-04-12 18:06:36 -0700650 case GRPC_CHTTP2_KEEPALIVE_STATE_PINGING:
Yuchen Zeng6cb260a2017-04-05 18:44:36 -0700651 grpc_timer_cancel(exec_ctx, &t->keepalive_ping_timer);
652 grpc_timer_cancel(exec_ctx, &t->keepalive_watchdog_timer);
653 break;
Yuchen Zengaaa779e2017-04-12 18:06:36 -0700654 case GRPC_CHTTP2_KEEPALIVE_STATE_DYING:
655 case GRPC_CHTTP2_KEEPALIVE_STATE_DISABLED:
656 /* keepalive timers are not set in these two states */
Yuchen Zeng6cb260a2017-04-05 18:44:36 -0700657 break;
Yuchen Zeng990d9fe2017-02-26 16:54:18 -0800658 }
Craig Tillerad23ae12016-03-04 10:50:56 -0800659
660 /* flush writable stream list to avoid dangling references */
Craig Tiller3d7c6092016-08-26 11:39:05 -0700661 grpc_chttp2_stream *s;
662 while (grpc_chttp2_list_pop_writable_stream(t, &s)) {
Craig Tillerfd4c6472016-09-06 20:03:06 -0700663 GRPC_CHTTP2_STREAM_UNREF(exec_ctx, s, "chttp2_writing:close");
Craig Tillerad23ae12016-03-04 10:50:56 -0800664 }
Craig Tiller936f1ea2016-10-14 15:15:19 -0700665 end_all_the_calls(exec_ctx, t, GRPC_ERROR_REF(error));
Craig Tillerf7970dd2016-10-20 16:49:13 -0700666 cancel_pings(exec_ctx, t, GRPC_ERROR_REF(error));
Craig Tillera82950e2015-09-22 12:33:20 -0700667 }
Craig Tiller71d28ad2016-05-07 21:48:44 -0700668 GRPC_ERROR_UNREF(error);
Craig Tillerec3aa892015-05-29 17:22:17 -0700669}
670
ncteisen9c43fc02017-06-08 16:06:23 -0700671#ifndef NDEBUG
Craig Tiller3d7c6092016-08-26 11:39:05 -0700672void grpc_chttp2_stream_ref(grpc_chttp2_stream *s, const char *reason) {
673 grpc_stream_ref(s->refcount, reason);
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800674}
Craig Tiller3d7c6092016-08-26 11:39:05 -0700675void grpc_chttp2_stream_unref(grpc_exec_ctx *exec_ctx, grpc_chttp2_stream *s,
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800676 const char *reason) {
Craig Tiller3d7c6092016-08-26 11:39:05 -0700677 grpc_stream_unref(exec_ctx, s->refcount, reason);
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800678}
679#else
Craig Tiller3d7c6092016-08-26 11:39:05 -0700680void grpc_chttp2_stream_ref(grpc_chttp2_stream *s) {
681 grpc_stream_ref(s->refcount);
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800682}
Craig Tiller3d7c6092016-08-26 11:39:05 -0700683void grpc_chttp2_stream_unref(grpc_exec_ctx *exec_ctx, grpc_chttp2_stream *s) {
684 grpc_stream_unref(exec_ctx, s->refcount);
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800685}
686#endif
687
Craig Tillera82950e2015-09-22 12:33:20 -0700688static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800689 grpc_stream *gs, grpc_stream_refcount *refcount,
Craig Tiller7d2c3982017-03-13 12:58:29 -0700690 const void *server_data, gpr_arena *arena) {
Craig Tillerc69d27b2016-07-14 13:20:22 -0700691 GPR_TIMER_BEGIN("init_stream", 0);
Craig Tillerb084d902015-06-12 07:50:02 -0700692 grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
693 grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800694
Craig Tiller9dc01dd2016-07-11 16:26:34 -0700695 s->t = t;
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800696 s->refcount = refcount;
Craig Tiller414217e2016-03-25 13:31:06 -0700697 /* We reserve one 'active stream' that's dropped when the stream is
698 read-closed. The others are for incoming_byte_streams that are actively
699 reading */
Craig Tiller3d7c6092016-08-26 11:39:05 -0700700 GRPC_CHTTP2_STREAM_REF(s, "chttp2");
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800701
Craig Tiller7d2c3982017-03-13 12:58:29 -0700702 grpc_chttp2_incoming_metadata_buffer_init(&s->metadata_buffer[0], arena);
703 grpc_chttp2_incoming_metadata_buffer_init(&s->metadata_buffer[1], arena);
Craig Tiller3d7c6092016-08-26 11:39:05 -0700704 grpc_chttp2_data_parser_init(&s->data_parser);
Craig Tillerd41a4a72016-10-26 16:16:06 -0700705 grpc_slice_buffer_init(&s->flow_controlled_buffer);
Craig Tiller3d7c6092016-08-26 11:39:05 -0700706 s->deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
ncteisen274bbbe2017-06-08 14:57:11 -0700707 GRPC_CLOSURE_INIT(&s->complete_fetch_locked, complete_fetch_locked, s,
Craig Tiller91031da2016-12-28 15:44:25 -0800708 grpc_schedule_on_exec_ctx);
Muxi Yan29723ee2017-04-12 20:24:42 -0700709 grpc_slice_buffer_init(&s->unprocessed_incoming_frames_buffer);
710 grpc_slice_buffer_init(&s->frame_storage);
711 s->pending_byte_stream = false;
ncteisen274bbbe2017-06-08 14:57:11 -0700712 GRPC_CLOSURE_INIT(&s->reset_byte_stream, reset_byte_stream, s,
Craig Tilleree4b1452017-05-12 10:56:03 -0700713 grpc_combiner_scheduler(t->combiner));
Craig Tiller606d8742015-06-15 06:58:50 -0700714
Craig Tillerdfd3a8f2016-08-24 09:43:45 -0700715 GRPC_CHTTP2_REF_TRANSPORT(t, "stream");
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800716
Craig Tiller606d8742015-06-15 06:58:50 -0700717 if (server_data) {
Craig Tiller3d7c6092016-08-26 11:39:05 -0700718 s->id = (uint32_t)(uintptr_t)server_data;
Craig Tiller606d8742015-06-15 06:58:50 -0700719 *t->accepting_stream = s;
Craig Tiller3d7c6092016-08-26 11:39:05 -0700720 grpc_chttp2_stream_map_add(&t->stream_map, s->id, s);
Craig Tiller795451f2016-09-27 08:47:28 -0700721 post_destructive_reclaimer(exec_ctx, t);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800722 }
723
ncteisen3c909d52017-07-13 19:45:51 -0700724 s->flow_control.s = s;
Craig Tillerc69d27b2016-07-14 13:20:22 -0700725 GPR_TIMER_END("init_stream", 0);
726
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800727 return 0;
728}
729
Craig Tiller93023e42016-07-11 12:43:23 -0700730static void destroy_stream_locked(grpc_exec_ctx *exec_ctx, void *sp,
731 grpc_error *error) {
Yash Tibrewal7cdd99c2017-09-08 16:04:12 -0700732 grpc_chttp2_stream *s = (grpc_chttp2_stream *)sp;
Craig Tiller93023e42016-07-11 12:43:23 -0700733 grpc_chttp2_transport *t = s->t;
Craig Tiller1766a912015-06-22 16:43:43 -0700734
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800735 GPR_TIMER_BEGIN("destroy_stream", 0);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800736
Craig Tiller3d7c6092016-08-26 11:39:05 -0700737 GPR_ASSERT((s->write_closed && s->read_closed) || s->id == 0);
Craig Tiller3d7c6092016-08-26 11:39:05 -0700738 if (s->id != 0) {
739 GPR_ASSERT(grpc_chttp2_stream_map_find(&t->stream_map, s->id) == NULL);
Craig Tillera82950e2015-09-22 12:33:20 -0700740 }
741
Muxi Yan29723ee2017-04-12 20:24:42 -0700742 grpc_slice_buffer_destroy_internal(exec_ctx,
743 &s->unprocessed_incoming_frames_buffer);
744 grpc_slice_buffer_destroy_internal(exec_ctx, &s->frame_storage);
Muxi Yan9469ac42017-07-21 12:50:35 -0700745 if (s->compressed_data_buffer) {
746 grpc_slice_buffer_destroy_internal(exec_ctx, s->compressed_data_buffer);
747 gpr_free(s->compressed_data_buffer);
748 }
749 if (s->decompressed_data_buffer) {
750 grpc_slice_buffer_destroy_internal(exec_ctx, s->decompressed_data_buffer);
751 gpr_free(s->decompressed_data_buffer);
752 }
Craig Tillera3b54cd2016-03-25 15:59:55 -0700753
Craig Tiller3d7c6092016-08-26 11:39:05 -0700754 grpc_chttp2_list_remove_stalled_by_transport(t, s);
Craig Tiller1f675992016-10-19 14:43:06 -0700755 grpc_chttp2_list_remove_stalled_by_stream(t, s);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800756
Craig Tiller2c8063c2016-03-22 22:12:15 -0700757 for (int i = 0; i < STREAM_LIST_COUNT; i++) {
Craig Tillera82950e2015-09-22 12:33:20 -0700758 if (s->included[i]) {
759 gpr_log(GPR_ERROR, "%s stream %d still included in list %d",
Craig Tiller3d7c6092016-08-26 11:39:05 -0700760 t->is_client ? "client" : "server", s->id, i);
Craig Tillera82950e2015-09-22 12:33:20 -0700761 abort();
Craig Tiller05cc0c42015-07-23 16:01:27 -0700762 }
Craig Tillerc3fdaf92015-06-18 10:16:52 -0700763 }
764
Craig Tiller3d7c6092016-08-26 11:39:05 -0700765 GPR_ASSERT(s->send_initial_metadata_finished == NULL);
Craig Tiller16966842016-08-29 10:34:57 -0700766 GPR_ASSERT(s->fetching_send_message == NULL);
Craig Tiller3d7c6092016-08-26 11:39:05 -0700767 GPR_ASSERT(s->send_trailing_metadata_finished == NULL);
768 GPR_ASSERT(s->recv_initial_metadata_ready == NULL);
769 GPR_ASSERT(s->recv_message_ready == NULL);
770 GPR_ASSERT(s->recv_trailing_metadata_finished == NULL);
771 grpc_chttp2_data_parser_destroy(exec_ctx, &s->data_parser);
Craig Tillerbd1795c2016-10-31 15:30:00 -0700772 grpc_chttp2_incoming_metadata_buffer_destroy(exec_ctx,
773 &s->metadata_buffer[0]);
774 grpc_chttp2_incoming_metadata_buffer_destroy(exec_ctx,
775 &s->metadata_buffer[1]);
Craig Tillera59c16c2016-10-31 07:25:01 -0700776 grpc_slice_buffer_destroy_internal(exec_ctx, &s->flow_controlled_buffer);
Craig Tiller3d7c6092016-08-26 11:39:05 -0700777 GRPC_ERROR_UNREF(s->read_closed_error);
778 GRPC_ERROR_UNREF(s->write_closed_error);
Muxi Yan29723ee2017-04-12 20:24:42 -0700779 GRPC_ERROR_UNREF(s->byte_stream_error);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800780
ncteisen3c909d52017-07-13 19:45:51 -0700781 grpc_chttp2_flowctl_destroy_stream(&t->flow_control, &s->flow_control);
Craig Tillerfd2cd782017-02-15 06:53:51 -0800782
Craig Tillerdfd3a8f2016-08-24 09:43:45 -0700783 GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "stream");
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800784
785 GPR_TIMER_END("destroy_stream", 0);
Craig Tiller2c8063c2016-03-22 22:12:15 -0700786
ncteisen274bbbe2017-06-08 14:57:11 -0700787 GRPC_CLOSURE_SCHED(exec_ctx, s->destroy_stream_arg, GRPC_ERROR_NONE);
Craig Tiller2c8063c2016-03-22 22:12:15 -0700788}
789
790static void destroy_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
Craig Tillerd426cac2017-03-13 12:30:45 -0700791 grpc_stream *gs,
792 grpc_closure *then_schedule_closure) {
Craig Tillerc69d27b2016-07-14 13:20:22 -0700793 GPR_TIMER_BEGIN("destroy_stream", 0);
Craig Tiller2c8063c2016-03-22 22:12:15 -0700794 grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
795 grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs;
796
Muxi Yane89c83a2017-07-12 11:49:27 -0700797 if (s->stream_compression_ctx != NULL) {
798 grpc_stream_compression_context_destroy(s->stream_compression_ctx);
799 s->stream_compression_ctx = NULL;
800 }
Muxi Yan68198b52017-07-12 11:43:23 -0700801 if (s->stream_decompression_ctx != NULL) {
802 grpc_stream_compression_context_destroy(s->stream_decompression_ctx);
803 s->stream_decompression_ctx = NULL;
804 }
805
Craig Tillerd426cac2017-03-13 12:30:45 -0700806 s->destroy_stream_arg = then_schedule_closure;
ncteisen274bbbe2017-06-08 14:57:11 -0700807 GRPC_CLOSURE_SCHED(
808 exec_ctx, GRPC_CLOSURE_INIT(&s->destroy_stream, destroy_stream_locked, s,
Craig Tilleree4b1452017-05-12 10:56:03 -0700809 grpc_combiner_scheduler(t->combiner)),
Craig Tiller91031da2016-12-28 15:44:25 -0800810 GRPC_ERROR_NONE);
Craig Tillerc69d27b2016-07-14 13:20:22 -0700811 GPR_TIMER_END("destroy_stream", 0);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800812}
813
Craig Tiller3d7c6092016-08-26 11:39:05 -0700814grpc_chttp2_stream *grpc_chttp2_parsing_lookup_stream(grpc_chttp2_transport *t,
815 uint32_t id) {
Craig Tillera6ca5712017-07-11 14:51:57 -0700816 return (grpc_chttp2_stream *)grpc_chttp2_stream_map_find(&t->stream_map, id);
Craig Tillercfb5db92015-06-15 17:14:41 -0700817}
818
Craig Tiller3d7c6092016-08-26 11:39:05 -0700819grpc_chttp2_stream *grpc_chttp2_parsing_accept_stream(grpc_exec_ctx *exec_ctx,
820 grpc_chttp2_transport *t,
821 uint32_t id) {
Craig Tiller7f0bf532016-09-29 10:19:28 -0700822 if (t->channel_callback.accept_stream == NULL) {
823 return NULL;
824 }
Craig Tiller1937b062015-06-16 08:47:38 -0700825 grpc_chttp2_stream *accepting;
Craig Tiller1937b062015-06-16 08:47:38 -0700826 GPR_ASSERT(t->accepting_stream == NULL);
827 t->accepting_stream = &accepting;
Craig Tiller9d35a1f2015-11-02 14:16:12 -0800828 t->channel_callback.accept_stream(exec_ctx,
829 t->channel_callback.accept_stream_user_data,
Craig Tiller7536af02015-12-22 13:49:30 -0800830 &t->base, (void *)(uintptr_t)id);
Craig Tiller1937b062015-06-16 08:47:38 -0700831 t->accepting_stream = NULL;
Craig Tiller3d7c6092016-08-26 11:39:05 -0700832 return accepting;
Craig Tiller1937b062015-06-16 08:47:38 -0700833}
834
Craig Tiller0cb803d2016-03-02 22:17:24 -0800835/*******************************************************************************
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800836 * OUTPUT PROCESSING
837 */
838
Craig Tiller2c4043b2016-09-05 14:50:16 -0700839static const char *write_state_name(grpc_chttp2_write_state st) {
840 switch (st) {
Craig Tillerbd37a212016-09-07 11:28:56 -0700841 case GRPC_CHTTP2_WRITE_STATE_IDLE:
842 return "IDLE";
843 case GRPC_CHTTP2_WRITE_STATE_WRITING:
844 return "WRITING";
Craig Tiller09b05fd2016-09-07 13:02:05 -0700845 case GRPC_CHTTP2_WRITE_STATE_WRITING_WITH_MORE:
Craig Tillerbd37a212016-09-07 11:28:56 -0700846 return "WRITING+MORE";
Craig Tiller2c4043b2016-09-05 14:50:16 -0700847 }
848 GPR_UNREACHABLE_CODE(return "UNKNOWN");
849}
850
Craig Tiller936f1ea2016-10-14 15:15:19 -0700851static void set_write_state(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
Craig Tillerfc2636d2016-09-12 09:57:07 -0700852 grpc_chttp2_write_state st, const char *reason) {
853 GRPC_CHTTP2_IF_TRACING(gpr_log(GPR_DEBUG, "W:%p %s state %s -> %s [%s]", t,
Craig Tillerbd37a212016-09-07 11:28:56 -0700854 t->is_client ? "CLIENT" : "SERVER",
855 write_state_name(t->write_state),
Craig Tillerfc2636d2016-09-12 09:57:07 -0700856 write_state_name(st), reason));
Craig Tillerbd37a212016-09-07 11:28:56 -0700857 t->write_state = st;
Craig Tiller90993502016-12-05 08:32:53 -0800858 if (st == GRPC_CHTTP2_WRITE_STATE_IDLE) {
ncteisen274bbbe2017-06-08 14:57:11 -0700859 GRPC_CLOSURE_LIST_SCHED(exec_ctx, &t->run_after_write);
Craig Tiller90993502016-12-05 08:32:53 -0800860 if (t->close_transport_on_writes_finished != NULL) {
861 grpc_error *err = t->close_transport_on_writes_finished;
862 t->close_transport_on_writes_finished = NULL;
863 close_transport_locked(exec_ctx, t, err);
864 }
Craig Tiller936f1ea2016-10-14 15:15:19 -0700865 }
Craig Tiller2c4043b2016-09-05 14:50:16 -0700866}
867
Craig Tiller3ff1fa62017-09-14 11:07:48 -0700868static void inc_initiate_write_reason(
869 grpc_exec_ctx *exec_ctx, grpc_chttp2_initiate_write_reason reason) {
870 switch (reason) {
871 case GRPC_CHTTP2_INITIATE_WRITE_INITIAL_WRITE:
872 GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_INITIAL_WRITE(exec_ctx);
873 break;
874 case GRPC_CHTTP2_INITIATE_WRITE_START_NEW_STREAM:
875 GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_START_NEW_STREAM(exec_ctx);
876 break;
877 case GRPC_CHTTP2_INITIATE_WRITE_SEND_MESSAGE:
878 GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_SEND_MESSAGE(exec_ctx);
879 break;
880 case GRPC_CHTTP2_INITIATE_WRITE_SEND_INITIAL_METADATA:
881 GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_SEND_INITIAL_METADATA(
882 exec_ctx);
883 break;
884 case GRPC_CHTTP2_INITIATE_WRITE_SEND_TRAILING_METADATA:
885 GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_SEND_TRAILING_METADATA(
886 exec_ctx);
887 break;
888 case GRPC_CHTTP2_INITIATE_WRITE_RETRY_SEND_PING:
889 GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_RETRY_SEND_PING(exec_ctx);
890 break;
891 case GRPC_CHTTP2_INITIATE_WRITE_CONTINUE_PINGS:
892 GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_CONTINUE_PINGS(exec_ctx);
893 break;
894 case GRPC_CHTTP2_INITIATE_WRITE_GOAWAY_SENT:
895 GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_GOAWAY_SENT(exec_ctx);
896 break;
897 case GRPC_CHTTP2_INITIATE_WRITE_RST_STREAM:
898 GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_RST_STREAM(exec_ctx);
899 break;
900 case GRPC_CHTTP2_INITIATE_WRITE_CLOSE_FROM_API:
901 GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_CLOSE_FROM_API(exec_ctx);
902 break;
903 case GRPC_CHTTP2_INITIATE_WRITE_STREAM_FLOW_CONTROL:
904 GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_STREAM_FLOW_CONTROL(exec_ctx);
905 break;
906 case GRPC_CHTTP2_INITIATE_WRITE_TRANSPORT_FLOW_CONTROL:
907 GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_TRANSPORT_FLOW_CONTROL(
908 exec_ctx);
909 break;
910 case GRPC_CHTTP2_INITIATE_WRITE_SEND_SETTINGS:
911 GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_SEND_SETTINGS(exec_ctx);
912 break;
913 case GRPC_CHTTP2_INITIATE_WRITE_BDP_ESTIMATOR_PING:
914 GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_BDP_ESTIMATOR_PING(exec_ctx);
915 break;
916 case GRPC_CHTTP2_INITIATE_WRITE_FLOW_CONTROL_UNSTALLED_BY_SETTING:
917 GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_FLOW_CONTROL_UNSTALLED_BY_SETTING(
918 exec_ctx);
919 break;
920 case GRPC_CHTTP2_INITIATE_WRITE_FLOW_CONTROL_UNSTALLED_BY_UPDATE:
921 GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_FLOW_CONTROL_UNSTALLED_BY_UPDATE(
922 exec_ctx);
923 break;
924 case GRPC_CHTTP2_INITIATE_WRITE_APPLICATION_PING:
925 GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_APPLICATION_PING(exec_ctx);
926 break;
927 case GRPC_CHTTP2_INITIATE_WRITE_KEEPALIVE_PING:
928 GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_KEEPALIVE_PING(exec_ctx);
929 break;
930 case GRPC_CHTTP2_INITIATE_WRITE_TRANSPORT_FLOW_CONTROL_UNSTALLED:
931 GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_TRANSPORT_FLOW_CONTROL_UNSTALLED(
932 exec_ctx);
933 break;
934 case GRPC_CHTTP2_INITIATE_WRITE_PING_RESPONSE:
935 GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_PING_RESPONSE(exec_ctx);
936 break;
937 case GRPC_CHTTP2_INITIATE_WRITE_FORCE_RST_STREAM:
938 GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_FORCE_RST_STREAM(exec_ctx);
939 break;
940 }
941}
942
Craig Tillerd7906f52016-05-31 16:07:27 -0700943void grpc_chttp2_initiate_write(grpc_exec_ctx *exec_ctx,
Craig Tiller3ff1fa62017-09-14 11:07:48 -0700944 grpc_chttp2_transport *t,
945 grpc_chttp2_initiate_write_reason reason) {
Craig Tillerc69d27b2016-07-14 13:20:22 -0700946 GPR_TIMER_BEGIN("grpc_chttp2_initiate_write", 0);
Craig Tiller64d80242016-07-15 07:53:33 -0700947
Craig Tiller3d7c6092016-08-26 11:39:05 -0700948 switch (t->write_state) {
949 case GRPC_CHTTP2_WRITE_STATE_IDLE:
Craig Tiller3ff1fa62017-09-14 11:07:48 -0700950 inc_initiate_write_reason(exec_ctx, reason);
951 set_write_state(exec_ctx, t, GRPC_CHTTP2_WRITE_STATE_WRITING,
952 grpc_chttp2_initiate_write_reason_string(reason));
Craig Tiller39951552017-07-20 12:52:09 -0700953 t->is_first_write_in_batch = true;
Craig Tillerdfd3a8f2016-08-24 09:43:45 -0700954 GRPC_CHTTP2_REF_TRANSPORT(t, "writing");
ncteisen274bbbe2017-06-08 14:57:11 -0700955 GRPC_CLOSURE_SCHED(
Craig Tiller91031da2016-12-28 15:44:25 -0800956 exec_ctx,
ncteisen274bbbe2017-06-08 14:57:11 -0700957 GRPC_CLOSURE_INIT(&t->write_action_begin_locked,
Craig Tilleree4b1452017-05-12 10:56:03 -0700958 write_action_begin_locked, t,
959 grpc_combiner_finally_scheduler(t->combiner)),
Craig Tiller91031da2016-12-28 15:44:25 -0800960 GRPC_ERROR_NONE);
Craig Tillerd7906f52016-05-31 16:07:27 -0700961 break;
Craig Tiller3d7c6092016-08-26 11:39:05 -0700962 case GRPC_CHTTP2_WRITE_STATE_WRITING:
Craig Tilleree4b1452017-05-12 10:56:03 -0700963 set_write_state(exec_ctx, t, GRPC_CHTTP2_WRITE_STATE_WRITING_WITH_MORE,
Craig Tiller3ff1fa62017-09-14 11:07:48 -0700964 grpc_chttp2_initiate_write_reason_string(reason));
Craig Tillerd7906f52016-05-31 16:07:27 -0700965 break;
Craig Tiller09b05fd2016-09-07 13:02:05 -0700966 case GRPC_CHTTP2_WRITE_STATE_WRITING_WITH_MORE:
Craig Tillerd7906f52016-05-31 16:07:27 -0700967 break;
968 }
Craig Tillerc69d27b2016-07-14 13:20:22 -0700969 GPR_TIMER_END("grpc_chttp2_initiate_write", 0);
Craig Tillerd7906f52016-05-31 16:07:27 -0700970}
971
Craig Tiller3ff1fa62017-09-14 11:07:48 -0700972void grpc_chttp2_mark_stream_writable(grpc_exec_ctx *exec_ctx,
973 grpc_chttp2_transport *t,
974 grpc_chttp2_stream *s) {
Craig Tiller3d7c6092016-08-26 11:39:05 -0700975 if (!t->closed && grpc_chttp2_list_add_writable_stream(t, s)) {
Craig Tillerfd4c6472016-09-06 20:03:06 -0700976 GRPC_CHTTP2_STREAM_REF(s, "chttp2_writing:become");
Craig Tiller3ceabde2017-02-02 10:17:42 -0800977 }
Craig Tiller3d7c6092016-08-26 11:39:05 -0700978}
979
Craig Tiller7561b822017-07-11 15:40:30 -0700980static grpc_closure_scheduler *write_scheduler(grpc_chttp2_transport *t,
Craig Tillerc5fe5cc2017-07-21 14:43:55 -0700981 bool early_results_scheduled,
982 bool partial_write) {
Craig Tiller39951552017-07-20 12:52:09 -0700983 /* if it's not the first write in a batch, always offload to the executor:
984 we'll probably end up queuing against the kernel anyway, so we'll likely
985 get better latency overall if we switch writing work elsewhere and continue
986 with application work above */
987 if (!t->is_first_write_in_batch) {
988 return grpc_executor_scheduler(GRPC_EXECUTOR_SHORT);
989 }
Craig Tillerc5fe5cc2017-07-21 14:43:55 -0700990 /* equivalently, if it's a partial write, we *know* we're going to be taking a
991 thread jump to write it because of the above, may as well do so
992 immediately */
993 if (partial_write) {
994 return grpc_executor_scheduler(GRPC_EXECUTOR_SHORT);
995 }
Craig Tiller7561b822017-07-11 15:40:30 -0700996 switch (t->opt_target) {
Craig Tiller7561b822017-07-11 15:40:30 -0700997 case GRPC_CHTTP2_OPTIMIZE_FOR_THROUGHPUT:
Craig Tiller39951552017-07-20 12:52:09 -0700998 /* executor gives us the largest probability of being able to batch a
999 * write with others on this transport */
Craig Tiller21001012017-07-20 12:07:34 -07001000 return grpc_executor_scheduler(GRPC_EXECUTOR_SHORT);
1001 case GRPC_CHTTP2_OPTIMIZE_FOR_LATENCY:
Craig Tiller39951552017-07-20 12:52:09 -07001002 return grpc_schedule_on_exec_ctx;
Craig Tiller7561b822017-07-11 15:40:30 -07001003 }
1004 GPR_UNREACHABLE_CODE(return NULL);
1005}
1006
Craig Tilleraf723b02017-07-17 17:56:28 -07001007#define WRITE_STATE_TUPLE_TO_INT(p, i) (2 * (int)(p) + (int)(i))
1008static const char *begin_writing_desc(bool partial, bool inlined) {
1009 switch (WRITE_STATE_TUPLE_TO_INT(partial, inlined)) {
1010 case WRITE_STATE_TUPLE_TO_INT(false, false):
1011 return "begin write in background";
1012 case WRITE_STATE_TUPLE_TO_INT(false, true):
1013 return "begin write in current thread";
1014 case WRITE_STATE_TUPLE_TO_INT(true, false):
1015 return "begin partial write in background";
1016 case WRITE_STATE_TUPLE_TO_INT(true, true):
1017 return "begin partial write in current thread";
1018 }
1019 GPR_UNREACHABLE_CODE(return "bad state tuple");
1020}
1021
Craig Tiller4e5b4522016-08-26 16:31:34 -07001022static void write_action_begin_locked(grpc_exec_ctx *exec_ctx, void *gt,
1023 grpc_error *error_ignored) {
1024 GPR_TIMER_BEGIN("write_action_begin_locked", 0);
Yash Tibrewal7cdd99c2017-09-08 16:04:12 -07001025 grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
Craig Tiller3d7c6092016-08-26 11:39:05 -07001026 GPR_ASSERT(t->write_state != GRPC_CHTTP2_WRITE_STATE_IDLE);
Craig Tiller7561b822017-07-11 15:40:30 -07001027 grpc_chttp2_begin_write_result r;
1028 if (t->closed) {
1029 r.writing = false;
1030 } else {
1031 r = grpc_chttp2_begin_write(exec_ctx, t);
1032 }
1033 if (r.writing) {
Craig Tiller073a88f2017-09-08 14:26:22 -07001034 if (r.partial) {
1035 GRPC_STATS_INC_HTTP2_PARTIAL_WRITES(exec_ctx);
1036 }
1037 if (!t->is_first_write_in_batch) {
1038 GRPC_STATS_INC_HTTP2_WRITES_CONTINUED(exec_ctx);
1039 }
Craig Tilleraf723b02017-07-17 17:56:28 -07001040 grpc_closure_scheduler *scheduler =
Craig Tillerc5fe5cc2017-07-21 14:43:55 -07001041 write_scheduler(t, r.early_results_scheduled, r.partial);
Craig Tiller06a1bae2017-09-07 13:31:12 -07001042 if (scheduler != grpc_schedule_on_exec_ctx) {
1043 GRPC_STATS_INC_HTTP2_WRITES_OFFLOADED(exec_ctx);
1044 }
Craig Tilleraf723b02017-07-17 17:56:28 -07001045 set_write_state(
1046 exec_ctx, t, r.partial ? GRPC_CHTTP2_WRITE_STATE_WRITING_WITH_MORE
1047 : GRPC_CHTTP2_WRITE_STATE_WRITING,
1048 begin_writing_desc(r.partial, scheduler == grpc_schedule_on_exec_ctx));
Craig Tilleraf723b02017-07-17 17:56:28 -07001049 GRPC_CLOSURE_SCHED(exec_ctx, GRPC_CLOSURE_INIT(&t->write_action,
1050 write_action, t, scheduler),
1051 GRPC_ERROR_NONE);
Craig Tiller7561b822017-07-11 15:40:30 -07001052 } else {
1053 set_write_state(exec_ctx, t, GRPC_CHTTP2_WRITE_STATE_IDLE,
1054 "begin writing nothing");
1055 GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "writing");
Craig Tiller13d455e2016-05-27 12:06:34 -07001056 }
Craig Tiller4e5b4522016-08-26 16:31:34 -07001057 GPR_TIMER_END("write_action_begin_locked", 0);
Craig Tiller13d455e2016-05-27 12:06:34 -07001058}
1059
Craig Tiller4e5b4522016-08-26 16:31:34 -07001060static void write_action(grpc_exec_ctx *exec_ctx, void *gt, grpc_error *error) {
Yash Tibrewal7cdd99c2017-09-08 16:04:12 -07001061 grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
Craig Tiller4e5b4522016-08-26 16:31:34 -07001062 GPR_TIMER_BEGIN("write_action", 0);
Craig Tiller91031da2016-12-28 15:44:25 -08001063 grpc_endpoint_write(
1064 exec_ctx, t->ep, &t->outbuf,
ncteisen274bbbe2017-06-08 14:57:11 -07001065 GRPC_CLOSURE_INIT(&t->write_action_end_locked, write_action_end_locked, t,
Craig Tilleree4b1452017-05-12 10:56:03 -07001066 grpc_combiner_scheduler(t->combiner)));
Craig Tiller4e5b4522016-08-26 16:31:34 -07001067 GPR_TIMER_END("write_action", 0);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001068}
1069
Craig Tiller4e5b4522016-08-26 16:31:34 -07001070static void write_action_end_locked(grpc_exec_ctx *exec_ctx, void *tp,
1071 grpc_error *error) {
Craig Tillerc69d27b2016-07-14 13:20:22 -07001072 GPR_TIMER_BEGIN("terminate_writing_with_lock", 0);
Yash Tibrewal7cdd99c2017-09-08 16:04:12 -07001073 grpc_chttp2_transport *t = (grpc_chttp2_transport *)tp;
Craig Tillerd20efd22015-06-12 16:17:09 -07001074
Craig Tiller2b782d82016-05-04 16:29:57 -07001075 if (error != GRPC_ERROR_NONE) {
Craig Tiller936f1ea2016-10-14 15:15:19 -07001076 close_transport_locked(exec_ctx, t, GRPC_ERROR_REF(error));
ctiller00297df2015-01-12 11:23:09 -08001077 }
Craig Tillerd20efd22015-06-12 16:17:09 -07001078
Craig Tiller25f29af2016-09-26 16:31:00 -07001079 if (t->sent_goaway_state == GRPC_CHTTP2_GOAWAY_SEND_SCHEDULED) {
1080 t->sent_goaway_state = GRPC_CHTTP2_GOAWAY_SENT;
1081 if (grpc_chttp2_stream_map_size(&t->stream_map) == 0) {
ncteisen4b36a3d2017-03-13 19:08:06 -07001082 close_transport_locked(
1083 exec_ctx, t, GRPC_ERROR_CREATE_FROM_STATIC_STRING("goaway sent"));
Craig Tiller25f29af2016-09-26 16:31:00 -07001084 }
1085 }
1086
Craig Tiller3d7c6092016-08-26 11:39:05 -07001087 switch (t->write_state) {
1088 case GRPC_CHTTP2_WRITE_STATE_IDLE:
Craig Tillerd7906f52016-05-31 16:07:27 -07001089 GPR_UNREACHABLE_CODE(break);
Craig Tiller3d7c6092016-08-26 11:39:05 -07001090 case GRPC_CHTTP2_WRITE_STATE_WRITING:
Craig Tillerc69d27b2016-07-14 13:20:22 -07001091 GPR_TIMER_MARK("state=writing", 0);
Craig Tiller936f1ea2016-10-14 15:15:19 -07001092 set_write_state(exec_ctx, t, GRPC_CHTTP2_WRITE_STATE_IDLE,
1093 "finish writing");
Craig Tillerd7906f52016-05-31 16:07:27 -07001094 break;
Craig Tiller09b05fd2016-09-07 13:02:05 -07001095 case GRPC_CHTTP2_WRITE_STATE_WRITING_WITH_MORE:
1096 GPR_TIMER_MARK("state=writing_stale_no_poller", 0);
Craig Tiller936f1ea2016-10-14 15:15:19 -07001097 set_write_state(exec_ctx, t, GRPC_CHTTP2_WRITE_STATE_WRITING,
Craig Tillera8be5bf2017-07-13 15:23:43 -07001098 "continue writing");
Craig Tiller39951552017-07-20 12:52:09 -07001099 t->is_first_write_in_batch = false;
Craig Tiller09b05fd2016-09-07 13:02:05 -07001100 GRPC_CHTTP2_REF_TRANSPORT(t, "writing");
ncteisen274bbbe2017-06-08 14:57:11 -07001101 GRPC_CLOSURE_RUN(
Craig Tiller91031da2016-12-28 15:44:25 -08001102 exec_ctx,
ncteisen274bbbe2017-06-08 14:57:11 -07001103 GRPC_CLOSURE_INIT(&t->write_action_begin_locked,
Craig Tiller91031da2016-12-28 15:44:25 -08001104 write_action_begin_locked, t,
Craig Tilleree4b1452017-05-12 10:56:03 -07001105 grpc_combiner_finally_scheduler(t->combiner)),
Craig Tiller91031da2016-12-28 15:44:25 -08001106 GRPC_ERROR_NONE);
Craig Tillerd7906f52016-05-31 16:07:27 -07001107 break;
Craig Tiller13d455e2016-05-27 12:06:34 -07001108 }
Craig Tillerd7906f52016-05-31 16:07:27 -07001109
Craig Tillerac88ca12016-11-16 14:21:29 -08001110 grpc_chttp2_end_write(exec_ctx, t, GRPC_ERROR_REF(error));
1111
Craig Tillerdfd3a8f2016-08-24 09:43:45 -07001112 GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "writing");
Craig Tillerc69d27b2016-07-14 13:20:22 -07001113 GPR_TIMER_END("terminate_writing_with_lock", 0);
ctiller00297df2015-01-12 11:23:09 -08001114}
Craig Tiller4b074d52015-06-23 07:48:21 -07001115
ncteisen08cefa02017-06-20 11:29:26 -07001116// Dirties an HTTP2 setting to be sent out next time a writing path occurs.
1117// If the change needs to occur immediately, manually initiate a write.
1118static void queue_setting_update(grpc_exec_ctx *exec_ctx,
1119 grpc_chttp2_transport *t,
1120 grpc_chttp2_setting_id id, uint32_t value) {
Craig Tiller4e5b4522016-08-26 16:31:34 -07001121 const grpc_chttp2_setting_parameters *sp =
1122 &grpc_chttp2_settings_parameters[id];
1123 uint32_t use_value = GPR_CLAMP(value, sp->min_value, sp->max_value);
1124 if (use_value != value) {
1125 gpr_log(GPR_INFO, "Requested parameter %s clamped from %d to %d", sp->name,
1126 value, use_value);
1127 }
1128 if (use_value != t->settings[GRPC_LOCAL_SETTINGS][id]) {
1129 t->settings[GRPC_LOCAL_SETTINGS][id] = use_value;
1130 t->dirtied_local_settings = 1;
Craig Tiller4e5b4522016-08-26 16:31:34 -07001131 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001132}
1133
Craig Tiller3d7c6092016-08-26 11:39:05 -07001134void grpc_chttp2_add_incoming_goaway(grpc_exec_ctx *exec_ctx,
1135 grpc_chttp2_transport *t,
1136 uint32_t goaway_error,
Craig Tillerd41a4a72016-10-26 16:16:06 -07001137 grpc_slice goaway_text) {
ncteisenbbb38012017-03-10 14:58:43 -08001138 // GRPC_CHTTP2_IF_TRACING(
1139 // gpr_log(GPR_DEBUG, "got goaway [%d]: %s", goaway_error, msg));
Craig Tiller3d7c6092016-08-26 11:39:05 -07001140 t->seen_goaway = 1;
Yuchen Zengebe6baa2017-03-31 16:28:46 -07001141
1142 /* When a client receives a GOAWAY with error code ENHANCE_YOUR_CALM and debug
Jan Tattermuscha1f3c202017-05-10 20:26:41 +02001143 * data equal to "too_many_pings", it should log the occurrence at a log level
Yuchen Zengebe6baa2017-03-31 16:28:46 -07001144 * that is enabled by default and double the configured KEEPALIVE_TIME used
1145 * for new connections on that channel. */
1146 if (t->is_client && goaway_error == GRPC_HTTP2_ENHANCE_YOUR_CALM &&
1147 grpc_slice_str_cmp(goaway_text, "too_many_pings") == 0) {
1148 gpr_log(GPR_ERROR,
Yuchen Zeng8b0a4d22017-04-03 11:24:42 -07001149 "Received a GOAWAY with error code ENHANCE_YOUR_CALM and debug "
1150 "data equal to \"too_many_pings\"");
Yuchen Zengebe6baa2017-03-31 16:28:46 -07001151 double current_keepalive_time_ms =
1152 gpr_timespec_to_micros(t->keepalive_time) / 1000;
1153 t->keepalive_time =
Yuchen Zeng8b0a4d22017-04-03 11:24:42 -07001154 current_keepalive_time_ms > INT_MAX / KEEPALIVE_TIME_BACKOFF_MULTIPLIER
Yuchen Zengebe6baa2017-03-31 16:28:46 -07001155 ? gpr_inf_future(GPR_TIMESPAN)
Yuchen Zeng8b0a4d22017-04-03 11:24:42 -07001156 : gpr_time_from_millis((int64_t)(current_keepalive_time_ms *
1157 KEEPALIVE_TIME_BACKOFF_MULTIPLIER),
Yuchen Zengebe6baa2017-03-31 16:28:46 -07001158 GPR_TIMESPAN);
1159 }
1160
Craig Tiller6ae6fc72016-06-01 16:28:00 -07001161 /* lie: use transient failure from the transport to indicate goaway has been
1162 * received */
Craig Tiller804ff712016-05-05 16:25:40 -07001163 connectivity_state_set(
Craig Tiller3d7c6092016-08-26 11:39:05 -07001164 exec_ctx, t, GRPC_CHANNEL_TRANSIENT_FAILURE,
Craig Tiller804ff712016-05-05 16:25:40 -07001165 grpc_error_set_str(
ncteisen4b36a3d2017-03-13 19:08:06 -07001166 grpc_error_set_int(
1167 GRPC_ERROR_CREATE_FROM_STATIC_STRING("GOAWAY received"),
1168 GRPC_ERROR_INT_HTTP2_ERROR, (intptr_t)goaway_error),
ncteisenbbb38012017-03-10 14:58:43 -08001169 GRPC_ERROR_STR_RAW_BYTES, goaway_text),
Craig Tiller804ff712016-05-05 16:25:40 -07001170 "got_goaway");
Craig Tiller7098c032015-05-04 10:18:28 -07001171}
1172
Craig Tiller3d7c6092016-08-26 11:39:05 -07001173static void maybe_start_some_streams(grpc_exec_ctx *exec_ctx,
1174 grpc_chttp2_transport *t) {
1175 grpc_chttp2_stream *s;
Craig Tiller4aa71a12015-06-15 13:00:55 -07001176 /* start streams where we have free grpc_chttp2_stream ids and free
1177 * concurrency */
Craig Tiller3d7c6092016-08-26 11:39:05 -07001178 while (t->next_stream_id <= MAX_CLIENT_STREAM_ID &&
1179 grpc_chttp2_stream_map_size(&t->stream_map) <
1180 t->settings[GRPC_PEER_SETTINGS]
1181 [GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS] &&
1182 grpc_chttp2_list_pop_waiting_for_concurrency(t, &s)) {
Craig Tiller9d35a1f2015-11-02 14:16:12 -08001183 /* safe since we can't (legally) be parsing this stream yet */
Craig Tillerab630732015-06-25 11:20:01 -07001184 GRPC_CHTTP2_IF_TRACING(gpr_log(
1185 GPR_DEBUG, "HTTP:%s: Allocating new grpc_chttp2_stream %p to id %d",
Craig Tiller3d7c6092016-08-26 11:39:05 -07001186 t->is_client ? "CLI" : "SVR", s, t->next_stream_id));
Craig Tillerc1f75602015-04-24 11:44:53 -07001187
Craig Tiller3d7c6092016-08-26 11:39:05 -07001188 GPR_ASSERT(s->id == 0);
1189 s->id = t->next_stream_id;
1190 t->next_stream_id += 2;
Craig Tiller564872d2015-06-18 11:21:22 -07001191
Craig Tiller3d7c6092016-08-26 11:39:05 -07001192 if (t->next_stream_id >= MAX_CLIENT_STREAM_ID) {
ncteisen4b36a3d2017-03-13 19:08:06 -07001193 connectivity_state_set(
1194 exec_ctx, t, GRPC_CHANNEL_TRANSIENT_FAILURE,
1195 GRPC_ERROR_CREATE_FROM_STATIC_STRING("Stream IDs exhausted"),
1196 "no_more_stream_ids");
Craig Tiller7098c032015-05-04 10:18:28 -07001197 }
1198
Craig Tiller3d7c6092016-08-26 11:39:05 -07001199 grpc_chttp2_stream_map_add(&t->stream_map, s->id, s);
Craig Tiller795451f2016-09-27 08:47:28 -07001200 post_destructive_reclaimer(exec_ctx, t);
Craig Tiller3ff1fa62017-09-14 11:07:48 -07001201 grpc_chttp2_mark_stream_writable(exec_ctx, t, s);
1202 grpc_chttp2_initiate_write(exec_ctx, t,
1203 GRPC_CHTTP2_INITIATE_WRITE_START_NEW_STREAM);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001204 }
Craig Tiller7098c032015-05-04 10:18:28 -07001205 /* cancel out streams that will never be started */
Craig Tiller3d7c6092016-08-26 11:39:05 -07001206 while (t->next_stream_id >= MAX_CLIENT_STREAM_ID &&
1207 grpc_chttp2_list_pop_waiting_for_concurrency(t, &s)) {
Craig Tiller31375ac2016-08-22 09:08:00 -07001208 grpc_chttp2_cancel_stream(
Craig Tiller3d7c6092016-08-26 11:39:05 -07001209 exec_ctx, t, s,
ncteisen4b36a3d2017-03-13 19:08:06 -07001210 grpc_error_set_int(
1211 GRPC_ERROR_CREATE_FROM_STATIC_STRING("Stream IDs exhausted"),
1212 GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE));
Craig Tiller7098c032015-05-04 10:18:28 -07001213 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001214}
1215
Craig Tiller73c4f8f2016-12-05 11:11:59 -08001216/* Flag that this closure barrier wants stats to be updated before finishing */
Craig Tiller466129e2016-03-09 14:43:18 -08001217#define CLOSURE_BARRIER_STATS_BIT (1 << 0)
Craig Tiller73c4f8f2016-12-05 11:11:59 -08001218/* Flag that this closure barrier may be covering a write in a pollset, and so
1219 we should not complete this closure until we can prove that the write got
1220 scheduled */
1221#define CLOSURE_BARRIER_MAY_COVER_WRITE (1 << 1)
1222/* First bit of the reference count, stored in the high order bits (with the low
1223 bits being used for flags defined above) */
Craig Tiller466129e2016-03-09 14:43:18 -08001224#define CLOSURE_BARRIER_FIRST_REF_BIT (1 << 16)
1225
Craig Tiller9d35a1f2015-11-02 14:16:12 -08001226static grpc_closure *add_closure_barrier(grpc_closure *closure) {
Craig Tiller781bab532016-05-05 08:15:28 -07001227 closure->next_data.scratch += CLOSURE_BARRIER_FIRST_REF_BIT;
Craig Tiller9d35a1f2015-11-02 14:16:12 -08001228 return closure;
1229}
1230
Craig Tillerbd37a212016-09-07 11:28:56 -07001231static void null_then_run_closure(grpc_exec_ctx *exec_ctx,
1232 grpc_closure **closure, grpc_error *error) {
Craig Tiller15b0ac02016-09-01 17:14:00 -07001233 grpc_closure *c = *closure;
1234 *closure = NULL;
ncteisen274bbbe2017-06-08 14:57:11 -07001235 GRPC_CLOSURE_RUN(exec_ctx, c, error);
Craig Tiller15b0ac02016-09-01 17:14:00 -07001236}
1237
Craig Tiller3d7c6092016-08-26 11:39:05 -07001238void grpc_chttp2_complete_closure_step(grpc_exec_ctx *exec_ctx,
1239 grpc_chttp2_transport *t,
1240 grpc_chttp2_stream *s,
1241 grpc_closure **pclosure,
Craig Tiller15b0ac02016-09-01 17:14:00 -07001242 grpc_error *error, const char *desc) {
Craig Tiller9d35a1f2015-11-02 14:16:12 -08001243 grpc_closure *closure = *pclosure;
Craig Tiller15b0ac02016-09-01 17:14:00 -07001244 *pclosure = NULL;
Craig Tiller9d35a1f2015-11-02 14:16:12 -08001245 if (closure == NULL) {
Craig Tiller965eab32016-05-07 22:11:37 -07001246 GRPC_ERROR_UNREF(error);
Craig Tiller9d35a1f2015-11-02 14:16:12 -08001247 return;
1248 }
Craig Tiller781bab532016-05-05 08:15:28 -07001249 closure->next_data.scratch -= CLOSURE_BARRIER_FIRST_REF_BIT;
Craig Tiller84f75d42017-05-03 13:06:35 -07001250 if (GRPC_TRACER_ON(grpc_http_trace)) {
Craig Tillerc494c7b2016-12-02 17:10:06 -08001251 const char *errstr = grpc_error_string(error);
Craig Tilleraf723b02017-07-17 17:56:28 -07001252 gpr_log(
1253 GPR_DEBUG,
1254 "complete_closure_step: t=%p %p refs=%d flags=0x%04x desc=%s err=%s "
1255 "write_state=%s",
1256 t, closure,
1257 (int)(closure->next_data.scratch / CLOSURE_BARRIER_FIRST_REF_BIT),
1258 (int)(closure->next_data.scratch % CLOSURE_BARRIER_FIRST_REF_BIT), desc,
1259 errstr, write_state_name(t->write_state));
Craig Tillerc494c7b2016-12-02 17:10:06 -08001260 }
Craig Tiller781bab532016-05-05 08:15:28 -07001261 if (error != GRPC_ERROR_NONE) {
Craig Tillera7cd41c2016-08-31 12:59:24 -07001262 if (closure->error_data.error == GRPC_ERROR_NONE) {
ncteisen4b36a3d2017-03-13 19:08:06 -07001263 closure->error_data.error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
1264 "Error in HTTP transport completing operation");
1265 closure->error_data.error = grpc_error_set_str(
1266 closure->error_data.error, GRPC_ERROR_STR_TARGET_ADDRESS,
1267 grpc_slice_from_copied_string(t->peer_string));
Craig Tiller781bab532016-05-05 08:15:28 -07001268 }
Craig Tillera7cd41c2016-08-31 12:59:24 -07001269 closure->error_data.error =
1270 grpc_error_add_child(closure->error_data.error, error);
Craig Tiller9d35a1f2015-11-02 14:16:12 -08001271 }
Craig Tiller781bab532016-05-05 08:15:28 -07001272 if (closure->next_data.scratch < CLOSURE_BARRIER_FIRST_REF_BIT) {
1273 if (closure->next_data.scratch & CLOSURE_BARRIER_STATS_BIT) {
Craig Tiller3d7c6092016-08-26 11:39:05 -07001274 grpc_transport_move_stats(&s->stats, s->collecting_stats);
1275 s->collecting_stats = NULL;
Craig Tiller466129e2016-03-09 14:43:18 -08001276 }
Craig Tiller504ae432016-12-05 11:07:58 -08001277 if ((t->write_state == GRPC_CHTTP2_WRITE_STATE_IDLE) ||
Craig Tiller73c4f8f2016-12-05 11:11:59 -08001278 !(closure->next_data.scratch & CLOSURE_BARRIER_MAY_COVER_WRITE)) {
ncteisen274bbbe2017-06-08 14:57:11 -07001279 GRPC_CLOSURE_RUN(exec_ctx, closure, closure->error_data.error);
Craig Tillerc494c7b2016-12-02 17:10:06 -08001280 } else {
1281 grpc_closure_list_append(&t->run_after_write, closure,
1282 closure->error_data.error);
1283 }
Craig Tiller9d35a1f2015-11-02 14:16:12 -08001284 }
Craig Tiller9d35a1f2015-11-02 14:16:12 -08001285}
1286
Craig Tiller3d7c6092016-08-26 11:39:05 -07001287static bool contains_non_ok_status(grpc_metadata_batch *batch) {
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001288 if (batch->idx.named.grpc_status != NULL) {
1289 return !grpc_mdelem_eq(batch->idx.named.grpc_status->md,
1290 GRPC_MDELEM_GRPC_STATUS_0);
Craig Tiller9d35a1f2015-11-02 14:16:12 -08001291 }
Craig Tiller3d7c6092016-08-26 11:39:05 -07001292 return false;
Craig Tiller9d35a1f2015-11-02 14:16:12 -08001293}
1294
Craig Tiller4e6247a2017-01-05 10:17:01 -08001295static void maybe_become_writable_due_to_send_msg(grpc_exec_ctx *exec_ctx,
1296 grpc_chttp2_transport *t,
1297 grpc_chttp2_stream *s) {
1298 if (s->id != 0 && (!s->write_buffering ||
1299 s->flow_controlled_buffer.length > t->write_buffer_size)) {
Craig Tiller3ff1fa62017-09-14 11:07:48 -07001300 grpc_chttp2_mark_stream_writable(exec_ctx, t, s);
1301 grpc_chttp2_initiate_write(exec_ctx, t,
1302 GRPC_CHTTP2_INITIATE_WRITE_SEND_MESSAGE);
Craig Tiller4e6247a2017-01-05 10:17:01 -08001303 }
1304}
1305
Craig Tiller16966842016-08-29 10:34:57 -07001306static void add_fetched_slice_locked(grpc_exec_ctx *exec_ctx,
1307 grpc_chttp2_transport *t,
Craig Tiller16966842016-08-29 10:34:57 -07001308 grpc_chttp2_stream *s) {
1309 s->fetched_send_message_length +=
Craig Tiller618e67d2016-10-26 21:08:10 -07001310 (uint32_t)GRPC_SLICE_LENGTH(s->fetching_slice);
Craig Tillerd41a4a72016-10-26 16:16:06 -07001311 grpc_slice_buffer_add(&s->flow_controlled_buffer, s->fetching_slice);
Craig Tiller4e6247a2017-01-05 10:17:01 -08001312 maybe_become_writable_due_to_send_msg(exec_ctx, t, s);
Craig Tiller8d301c42016-10-25 09:08:26 -07001313}
Craig Tiller16966842016-08-29 10:34:57 -07001314
1315static void continue_fetching_send_locked(grpc_exec_ctx *exec_ctx,
1316 grpc_chttp2_transport *t,
1317 grpc_chttp2_stream *s) {
Craig Tiller87e004b2016-10-25 08:27:14 -07001318 for (;;) {
1319 if (s->fetching_send_message == NULL) {
1320 /* Stream was cancelled before message fetch completed */
1321 abort(); /* TODO(ctiller): what cleanup here? */
1322 return; /* early out */
Craig Tiller16966842016-08-29 10:34:57 -07001323 }
Craig Tiller87e004b2016-10-25 08:27:14 -07001324 if (s->fetched_send_message_length == s->fetching_send_message->length) {
Mark D. Roth57940612017-07-26 14:29:52 -07001325 grpc_byte_stream_destroy(exec_ctx, s->fetching_send_message);
Craig Tiller87e004b2016-10-25 08:27:14 -07001326 int64_t notify_offset = s->next_message_end_offset;
1327 if (notify_offset <= s->flow_controlled_bytes_written) {
1328 grpc_chttp2_complete_closure_step(
1329 exec_ctx, t, s, &s->fetching_send_message_finished, GRPC_ERROR_NONE,
1330 "fetching_send_message_finished");
1331 } else {
1332 grpc_chttp2_write_cb *cb = t->write_cb_pool;
1333 if (cb == NULL) {
Yash Tibrewal7cdd99c2017-09-08 16:04:12 -07001334 cb = (grpc_chttp2_write_cb *)gpr_malloc(sizeof(*cb));
Craig Tiller87e004b2016-10-25 08:27:14 -07001335 } else {
1336 t->write_cb_pool = cb->next;
1337 }
1338 cb->call_at_byte = notify_offset;
1339 cb->closure = s->fetching_send_message_finished;
1340 s->fetching_send_message_finished = NULL;
Craig Tillere9a76652017-05-12 13:17:14 -07001341 grpc_chttp2_write_cb **list =
1342 s->fetching_send_message->flags & GRPC_WRITE_THROUGH
1343 ? &s->on_write_finished_cbs
1344 : &s->on_flow_controlled_cbs;
1345 cb->next = *list;
1346 *list = cb;
Craig Tiller87e004b2016-10-25 08:27:14 -07001347 }
1348 s->fetching_send_message = NULL;
1349 return; /* early out */
1350 } else if (grpc_byte_stream_next(exec_ctx, s->fetching_send_message,
Muxi Yan29723ee2017-04-12 20:24:42 -07001351 UINT32_MAX, &s->complete_fetch_locked)) {
Mark D. Roth57940612017-07-26 14:29:52 -07001352 grpc_error *error = grpc_byte_stream_pull(
1353 exec_ctx, s->fetching_send_message, &s->fetching_slice);
1354 if (error != GRPC_ERROR_NONE) {
1355 grpc_byte_stream_destroy(exec_ctx, s->fetching_send_message);
1356 grpc_chttp2_cancel_stream(exec_ctx, t, s, error);
1357 } else {
1358 add_fetched_slice_locked(exec_ctx, t, s);
1359 }
Craig Tiller87e004b2016-10-25 08:27:14 -07001360 }
Craig Tiller16966842016-08-29 10:34:57 -07001361 }
1362}
1363
Craig Tiller16966842016-08-29 10:34:57 -07001364static void complete_fetch_locked(grpc_exec_ctx *exec_ctx, void *gs,
1365 grpc_error *error) {
Yash Tibrewal7cdd99c2017-09-08 16:04:12 -07001366 grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs;
Craig Tiller16966842016-08-29 10:34:57 -07001367 grpc_chttp2_transport *t = s->t;
1368 if (error == GRPC_ERROR_NONE) {
Muxi Yan29723ee2017-04-12 20:24:42 -07001369 error = grpc_byte_stream_pull(exec_ctx, s->fetching_send_message,
1370 &s->fetching_slice);
1371 if (error == GRPC_ERROR_NONE) {
1372 add_fetched_slice_locked(exec_ctx, t, s);
1373 continue_fetching_send_locked(exec_ctx, t, s);
1374 }
1375 }
Muxi Yan29723ee2017-04-12 20:24:42 -07001376 if (error != GRPC_ERROR_NONE) {
Mark D. Roth57940612017-07-26 14:29:52 -07001377 grpc_byte_stream_destroy(exec_ctx, s->fetching_send_message);
1378 grpc_chttp2_cancel_stream(exec_ctx, t, s, error);
Craig Tiller16966842016-08-29 10:34:57 -07001379 }
1380}
1381
Craig Tiller2b782d82016-05-04 16:29:57 -07001382static void do_nothing(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {}
Craig Tiller027a74c2015-11-10 08:37:46 +00001383
yang-g8fb73d22016-11-21 16:29:58 -08001384static void log_metadata(const grpc_metadata_batch *md_batch, uint32_t id,
1385 bool is_client, bool is_initial) {
Vijay Pai3d7d5f42017-05-04 10:02:24 -07001386 for (grpc_linked_mdelem *md = md_batch->list.head; md != NULL;
yang-g8fb73d22016-11-21 16:29:58 -08001387 md = md->next) {
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001388 char *key = grpc_slice_to_c_string(GRPC_MDKEY(md->md));
1389 char *value = grpc_slice_to_c_string(GRPC_MDVALUE(md->md));
yang-g8fb73d22016-11-21 16:29:58 -08001390 gpr_log(GPR_INFO, "HTTP:%d:%s:%s: %s: %s", id, is_initial ? "HDR" : "TRL",
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001391 is_client ? "CLI" : "SVR", key, value);
1392 gpr_free(key);
1393 gpr_free(value);
yang-g8fb73d22016-11-21 16:29:58 -08001394 }
1395}
1396
Craig Tiller93023e42016-07-11 12:43:23 -07001397static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op,
1398 grpc_error *error_ignored) {
Craig Tiller0ba432d2015-10-09 16:57:11 -07001399 GPR_TIMER_BEGIN("perform_stream_op_locked", 0);
Craig Tiller9d35a1f2015-11-02 14:16:12 -08001400
Yash Tibrewal7cdd99c2017-09-08 16:04:12 -07001401 grpc_transport_stream_op_batch *op =
1402 (grpc_transport_stream_op_batch *)stream_op;
1403 grpc_chttp2_stream *s = (grpc_chttp2_stream *)op->handler_private.extra_arg;
Craig Tillera0f3abd2017-03-31 15:42:16 -07001404 grpc_transport_stream_op_batch_payload *op_payload = op->payload;
Craig Tiller9c1ec542017-03-02 08:42:54 -08001405 grpc_chttp2_transport *t = s->t;
Craig Tiller45b135e2016-03-22 16:02:39 -07001406
Craig Tiller57bb9a92017-08-31 16:44:15 -07001407 GRPC_STATS_INC_HTTP2_OP_BATCHES(exec_ctx);
1408
Craig Tiller84f75d42017-05-03 13:06:35 -07001409 if (GRPC_TRACER_ON(grpc_http_trace)) {
Craig Tillera0f3abd2017-03-31 15:42:16 -07001410 char *str = grpc_transport_stream_op_batch_string(op);
Craig Tiller35e87832016-09-28 10:53:41 -07001411 gpr_log(GPR_DEBUG, "perform_stream_op_locked: %s; on_complete = %p", str,
1412 op->on_complete);
Craig Tillere7603b82016-07-18 15:43:42 -07001413 gpr_free(str);
yang-g8fb73d22016-11-21 16:29:58 -08001414 if (op->send_initial_metadata) {
Craig Tiller9c1ec542017-03-02 08:42:54 -08001415 log_metadata(op_payload->send_initial_metadata.send_initial_metadata,
1416 s->id, t->is_client, true);
yang-g8fb73d22016-11-21 16:29:58 -08001417 }
1418 if (op->send_trailing_metadata) {
Craig Tiller9c1ec542017-03-02 08:42:54 -08001419 log_metadata(op_payload->send_trailing_metadata.send_trailing_metadata,
1420 s->id, t->is_client, false);
yang-g8fb73d22016-11-21 16:29:58 -08001421 }
Craig Tillere7603b82016-07-18 15:43:42 -07001422 }
1423
Craig Tiller45b135e2016-03-22 16:02:39 -07001424 grpc_closure *on_complete = op->on_complete;
Craig Tiller027a74c2015-11-10 08:37:46 +00001425 if (on_complete == NULL) {
Craig Tiller91031da2016-12-28 15:44:25 -08001426 on_complete =
ncteisen274bbbe2017-06-08 14:57:11 -07001427 GRPC_CLOSURE_CREATE(do_nothing, NULL, grpc_schedule_on_exec_ctx);
Craig Tiller027a74c2015-11-10 08:37:46 +00001428 }
Craig Tillerc8db73c2016-08-30 14:00:48 -07001429
Craig Tiller9d35a1f2015-11-02 14:16:12 -08001430 /* use final_data as a barrier until enqueue time; the inital counter is
1431 dropped at the end of this function */
Craig Tiller781bab532016-05-05 08:15:28 -07001432 on_complete->next_data.scratch = CLOSURE_BARRIER_FIRST_REF_BIT;
Craig Tillera7cd41c2016-08-31 12:59:24 -07001433 on_complete->error_data.error = GRPC_ERROR_NONE;
Craig Tiller466129e2016-03-09 14:43:18 -08001434
Craig Tiller9c1ec542017-03-02 08:42:54 -08001435 if (op->collect_stats) {
Craig Tiller3d7c6092016-08-26 11:39:05 -07001436 GPR_ASSERT(s->collecting_stats == NULL);
Craig Tiller9c1ec542017-03-02 08:42:54 -08001437 s->collecting_stats = op_payload->collect_stats.collect_stats;
Craig Tiller781bab532016-05-05 08:15:28 -07001438 on_complete->next_data.scratch |= CLOSURE_BARRIER_STATS_BIT;
Craig Tiller466129e2016-03-09 14:43:18 -08001439 }
Craig Tiller1766a912015-06-22 16:43:43 -07001440
Craig Tiller9c1ec542017-03-02 08:42:54 -08001441 if (op->cancel_stream) {
Craig Tiller57bb9a92017-08-31 16:44:15 -07001442 GRPC_STATS_INC_HTTP2_OP_CANCEL(exec_ctx);
Craig Tiller9c1ec542017-03-02 08:42:54 -08001443 grpc_chttp2_cancel_stream(exec_ctx, t, s,
1444 op_payload->cancel_stream.cancel_error);
Craig Tillera82950e2015-09-22 12:33:20 -07001445 }
Craig Tiller45724b32015-09-22 10:42:19 -07001446
Craig Tiller9c1ec542017-03-02 08:42:54 -08001447 if (op->send_initial_metadata) {
Craig Tiller57bb9a92017-08-31 16:44:15 -07001448 GRPC_STATS_INC_HTTP2_OP_SEND_INITIAL_METADATA(exec_ctx);
Craig Tiller3d7c6092016-08-26 11:39:05 -07001449 GPR_ASSERT(s->send_initial_metadata_finished == NULL);
Craig Tiller73c4f8f2016-12-05 11:11:59 -08001450 on_complete->next_data.scratch |= CLOSURE_BARRIER_MAY_COVER_WRITE;
Muxi Yana2279bd2017-07-26 14:48:21 -07001451
1452 /* Identify stream compression */
1453 if ((s->stream_compression_send_enabled =
1454 (op_payload->send_initial_metadata.send_initial_metadata->idx.named
1455 .content_encoding != NULL)) == true) {
Yash Tibrewal7cdd99c2017-09-08 16:04:12 -07001456 s->compressed_data_buffer =
1457 (grpc_slice_buffer *)gpr_malloc(sizeof(grpc_slice_buffer));
Muxi Yana2279bd2017-07-26 14:48:21 -07001458 grpc_slice_buffer_init(s->compressed_data_buffer);
1459 }
1460
Craig Tiller3d7c6092016-08-26 11:39:05 -07001461 s->send_initial_metadata_finished = add_closure_barrier(on_complete);
Craig Tiller9c1ec542017-03-02 08:42:54 -08001462 s->send_initial_metadata =
1463 op_payload->send_initial_metadata.send_initial_metadata;
Mark D. Roth22b338e2016-05-04 13:27:56 -07001464 const size_t metadata_size =
Craig Tiller9c1ec542017-03-02 08:42:54 -08001465 grpc_metadata_batch_size(s->send_initial_metadata);
Mark D. Rothebbbce32016-05-02 09:54:04 -07001466 const size_t metadata_peer_limit =
Craig Tiller3d7c6092016-08-26 11:39:05 -07001467 t->settings[GRPC_PEER_SETTINGS]
1468 [GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE];
1469 if (t->is_client) {
1470 s->deadline =
1471 gpr_time_min(s->deadline, s->send_initial_metadata->deadline);
Craig Tillerc22e31f2016-07-08 13:22:18 -07001472 }
Mark D. Rothebbbce32016-05-02 09:54:04 -07001473 if (metadata_size > metadata_peer_limit) {
Craig Tiller31375ac2016-08-22 09:08:00 -07001474 grpc_chttp2_cancel_stream(
Craig Tiller3d7c6092016-08-26 11:39:05 -07001475 exec_ctx, t, s,
Craig Tiller09c464a2016-06-01 08:16:29 -07001476 grpc_error_set_int(
1477 grpc_error_set_int(
ncteisen4b36a3d2017-03-13 19:08:06 -07001478 grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
1479 "to-be-sent initial metadata size "
1480 "exceeds peer limit"),
1481 GRPC_ERROR_INT_SIZE,
1482 (intptr_t)metadata_size),
Craig Tillerf0f70a82016-06-23 13:55:06 -07001483 GRPC_ERROR_INT_LIMIT, (intptr_t)metadata_peer_limit),
1484 GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_RESOURCE_EXHAUSTED));
Craig Tillerc079c112015-04-22 15:23:39 -07001485 } else {
Craig Tiller9c1ec542017-03-02 08:42:54 -08001486 if (contains_non_ok_status(s->send_initial_metadata)) {
Craig Tiller3d7c6092016-08-26 11:39:05 -07001487 s->seen_error = true;
Mark D. Rothebbbce32016-05-02 09:54:04 -07001488 }
Craig Tiller3d7c6092016-08-26 11:39:05 -07001489 if (!s->write_closed) {
1490 if (t->is_client) {
Craig Tiller0f7eb302016-10-27 15:30:21 -07001491 if (!t->closed) {
1492 GPR_ASSERT(s->id == 0);
1493 grpc_chttp2_list_add_waiting_for_concurrency(t, s);
1494 maybe_start_some_streams(exec_ctx, t);
1495 } else {
David Garcia Quintas08f76242017-02-16 12:17:59 -08001496 grpc_chttp2_cancel_stream(
1497 exec_ctx, t, s,
ncteisen4b36a3d2017-03-13 19:08:06 -07001498 grpc_error_set_int(
1499 GRPC_ERROR_CREATE_FROM_STATIC_STRING("Transport closed"),
1500 GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE));
Craig Tiller0f7eb302016-10-27 15:30:21 -07001501 }
Mark D. Rothebbbce32016-05-02 09:54:04 -07001502 } else {
Craig Tiller3d7c6092016-08-26 11:39:05 -07001503 GPR_ASSERT(s->id != 0);
Craig Tiller3ff1fa62017-09-14 11:07:48 -07001504 grpc_chttp2_mark_stream_writable(exec_ctx, t, s);
1505 if (!(op->send_message &&
1506 (op->payload->send_message.send_message->flags &
1507 GRPC_WRITE_BUFFER_HINT))) {
1508 grpc_chttp2_initiate_write(
1509 exec_ctx, t, GRPC_CHTTP2_INITIATE_WRITE_SEND_INITIAL_METADATA);
Yuxuan Li34894e42017-02-08 17:57:24 -08001510 }
Mark D. Rothebbbce32016-05-02 09:54:04 -07001511 }
1512 } else {
David Garcia Quintas3fde3992016-11-10 14:20:17 -08001513 s->send_initial_metadata = NULL;
Mark D. Rothebbbce32016-05-02 09:54:04 -07001514 grpc_chttp2_complete_closure_step(
Craig Tiller3d7c6092016-08-26 11:39:05 -07001515 exec_ctx, t, s, &s->send_initial_metadata_finished,
ncteisen4b36a3d2017-03-13 19:08:06 -07001516 GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001517 "Attempt to send initial metadata after stream was closed",
1518 &s->write_closed_error, 1),
Craig Tillerbd37a212016-09-07 11:28:56 -07001519 "send_initial_metadata_finished");
Mark D. Rothebbbce32016-05-02 09:54:04 -07001520 }
Craig Tillerc079c112015-04-22 15:23:39 -07001521 }
Mark D. Roth764cf042017-09-01 09:00:06 -07001522 if (op_payload->send_initial_metadata.peer_string != NULL) {
1523 gpr_atm_rel_store(op_payload->send_initial_metadata.peer_string,
1524 (gpr_atm)gpr_strdup(t->peer_string));
1525 }
Craig Tillerbe18b8d2015-04-22 14:00:47 -07001526 }
1527
Craig Tiller9c1ec542017-03-02 08:42:54 -08001528 if (op->send_message) {
Craig Tiller57bb9a92017-08-31 16:44:15 -07001529 GRPC_STATS_INC_HTTP2_OP_SEND_MESSAGE(exec_ctx);
1530 GRPC_STATS_INC_HTTP2_SEND_MESSAGE_SIZE(
1531 exec_ctx, op->payload->send_message.send_message->length);
Craig Tiller73c4f8f2016-12-05 11:11:59 -08001532 on_complete->next_data.scratch |= CLOSURE_BARRIER_MAY_COVER_WRITE;
Craig Tiller16966842016-08-29 10:34:57 -07001533 s->fetching_send_message_finished = add_closure_barrier(op->on_complete);
Craig Tiller0b8e0d52016-08-29 08:52:42 -07001534 if (s->write_closed) {
Mark D. Roth764cf042017-09-01 09:00:06 -07001535 // Return an error unless the client has already received trailing
1536 // metadata from the server, since an application using a
1537 // streaming call might send another message before getting a
1538 // recv_message failure, breaking out of its loop, and then
1539 // starting recv_trailing_metadata.
Craig Tiller0b8e0d52016-08-29 08:52:42 -07001540 grpc_chttp2_complete_closure_step(
Craig Tiller16966842016-08-29 10:34:57 -07001541 exec_ctx, t, s, &s->fetching_send_message_finished,
Mark D. Roth764cf042017-09-01 09:00:06 -07001542 t->is_client && s->received_trailing_metadata
1543 ? GRPC_ERROR_NONE
1544 : GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
1545 "Attempt to send message after stream was closed",
1546 &s->write_closed_error, 1),
Craig Tillerbd37a212016-09-07 11:28:56 -07001547 "fetching_send_message_finished");
Craig Tiller0b8e0d52016-08-29 08:52:42 -07001548 } else {
Craig Tiller16966842016-08-29 10:34:57 -07001549 GPR_ASSERT(s->fetching_send_message == NULL);
Muxi Yanf20bfaa2017-07-19 16:27:02 -07001550 uint8_t *frame_hdr = grpc_slice_buffer_tiny_add(
1551 &s->flow_controlled_buffer, GRPC_HEADER_SIZE_IN_BYTES);
Craig Tiller9c1ec542017-03-02 08:42:54 -08001552 uint32_t flags = op_payload->send_message.send_message->flags;
Craig Tiller0b8e0d52016-08-29 08:52:42 -07001553 frame_hdr[0] = (flags & GRPC_WRITE_INTERNAL_COMPRESS) != 0;
Craig Tiller9c1ec542017-03-02 08:42:54 -08001554 size_t len = op_payload->send_message.send_message->length;
Craig Tiller0b8e0d52016-08-29 08:52:42 -07001555 frame_hdr[1] = (uint8_t)(len >> 24);
1556 frame_hdr[2] = (uint8_t)(len >> 16);
1557 frame_hdr[3] = (uint8_t)(len >> 8);
1558 frame_hdr[4] = (uint8_t)(len);
Craig Tiller9c1ec542017-03-02 08:42:54 -08001559 s->fetching_send_message = op_payload->send_message.send_message;
Craig Tiller16966842016-08-29 10:34:57 -07001560 s->fetched_send_message_length = 0;
Craig Tiller9381c002016-10-07 13:09:45 -07001561 s->next_message_end_offset = s->flow_controlled_bytes_written +
1562 (int64_t)s->flow_controlled_buffer.length +
1563 (int64_t)len;
Craig Tiller16966842016-08-29 10:34:57 -07001564 if (flags & GRPC_WRITE_BUFFER_HINT) {
Craig Tiller4e6247a2017-01-05 10:17:01 -08001565 s->next_message_end_offset -= t->write_buffer_size;
1566 s->write_buffering = true;
1567 } else {
1568 s->write_buffering = false;
Craig Tiller0b8e0d52016-08-29 08:52:42 -07001569 }
Craig Tiller16966842016-08-29 10:34:57 -07001570 continue_fetching_send_locked(exec_ctx, t, s);
Craig Tiller4e6247a2017-01-05 10:17:01 -08001571 maybe_become_writable_due_to_send_msg(exec_ctx, t, s);
Craig Tiller45724b32015-09-22 10:42:19 -07001572 }
Craig Tillerbe18b8d2015-04-22 14:00:47 -07001573 }
1574
Craig Tiller9c1ec542017-03-02 08:42:54 -08001575 if (op->send_trailing_metadata) {
Craig Tiller57bb9a92017-08-31 16:44:15 -07001576 GRPC_STATS_INC_HTTP2_OP_SEND_TRAILING_METADATA(exec_ctx);
Craig Tiller3d7c6092016-08-26 11:39:05 -07001577 GPR_ASSERT(s->send_trailing_metadata_finished == NULL);
Craig Tiller73c4f8f2016-12-05 11:11:59 -08001578 on_complete->next_data.scratch |= CLOSURE_BARRIER_MAY_COVER_WRITE;
Craig Tiller3d7c6092016-08-26 11:39:05 -07001579 s->send_trailing_metadata_finished = add_closure_barrier(on_complete);
Craig Tiller9c1ec542017-03-02 08:42:54 -08001580 s->send_trailing_metadata =
1581 op_payload->send_trailing_metadata.send_trailing_metadata;
Craig Tiller4e6247a2017-01-05 10:17:01 -08001582 s->write_buffering = false;
Mark D. Roth22b338e2016-05-04 13:27:56 -07001583 const size_t metadata_size =
Craig Tiller9c1ec542017-03-02 08:42:54 -08001584 grpc_metadata_batch_size(s->send_trailing_metadata);
Mark D. Rothebbbce32016-05-02 09:54:04 -07001585 const size_t metadata_peer_limit =
Craig Tiller3d7c6092016-08-26 11:39:05 -07001586 t->settings[GRPC_PEER_SETTINGS]
1587 [GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE];
Mark D. Rothebbbce32016-05-02 09:54:04 -07001588 if (metadata_size > metadata_peer_limit) {
Craig Tiller31375ac2016-08-22 09:08:00 -07001589 grpc_chttp2_cancel_stream(
Craig Tiller3d7c6092016-08-26 11:39:05 -07001590 exec_ctx, t, s,
Craig Tillerf0f70a82016-06-23 13:55:06 -07001591 grpc_error_set_int(
1592 grpc_error_set_int(
ncteisen4b36a3d2017-03-13 19:08:06 -07001593 grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
1594 "to-be-sent trailing metadata size "
1595 "exceeds peer limit"),
1596 GRPC_ERROR_INT_SIZE,
1597 (intptr_t)metadata_size),
Craig Tillerf0f70a82016-06-23 13:55:06 -07001598 GRPC_ERROR_INT_LIMIT, (intptr_t)metadata_peer_limit),
1599 GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_RESOURCE_EXHAUSTED));
Mark D. Rothebbbce32016-05-02 09:54:04 -07001600 } else {
Craig Tiller9c1ec542017-03-02 08:42:54 -08001601 if (contains_non_ok_status(s->send_trailing_metadata)) {
Craig Tiller3d7c6092016-08-26 11:39:05 -07001602 s->seen_error = true;
Mark D. Rothebbbce32016-05-02 09:54:04 -07001603 }
Craig Tiller3d7c6092016-08-26 11:39:05 -07001604 if (s->write_closed) {
1605 s->send_trailing_metadata = NULL;
Mark D. Rothebbbce32016-05-02 09:54:04 -07001606 grpc_chttp2_complete_closure_step(
Craig Tiller3d7c6092016-08-26 11:39:05 -07001607 exec_ctx, t, s, &s->send_trailing_metadata_finished,
Craig Tiller306efc72017-03-20 09:45:12 -07001608 grpc_metadata_batch_is_empty(
Craig Tillere6a448c2017-03-30 12:17:41 -07001609 op->payload->send_trailing_metadata.send_trailing_metadata)
Craig Tillera58ed7c2016-05-11 10:55:18 -07001610 ? GRPC_ERROR_NONE
ncteisen4b36a3d2017-03-13 19:08:06 -07001611 : GRPC_ERROR_CREATE_FROM_STATIC_STRING(
1612 "Attempt to send trailing metadata after "
1613 "stream was closed"),
Craig Tillerbd37a212016-09-07 11:28:56 -07001614 "send_trailing_metadata_finished");
Craig Tiller3d7c6092016-08-26 11:39:05 -07001615 } else if (s->id != 0) {
Mark D. Rothebbbce32016-05-02 09:54:04 -07001616 /* TODO(ctiller): check if there's flow control for any outstanding
1617 bytes before going writable */
Craig Tiller3ff1fa62017-09-14 11:07:48 -07001618 grpc_chttp2_mark_stream_writable(exec_ctx, t, s);
1619 grpc_chttp2_initiate_write(
1620 exec_ctx, t, GRPC_CHTTP2_INITIATE_WRITE_SEND_TRAILING_METADATA);
Mark D. Rothebbbce32016-05-02 09:54:04 -07001621 }
Craig Tiller9d35a1f2015-11-02 14:16:12 -08001622 }
Craig Tillerbe18b8d2015-04-22 14:00:47 -07001623 }
Craig Tiller5dde66e2015-06-02 09:05:23 -07001624
Craig Tiller9c1ec542017-03-02 08:42:54 -08001625 if (op->recv_initial_metadata) {
Craig Tiller57bb9a92017-08-31 16:44:15 -07001626 GRPC_STATS_INC_HTTP2_OP_RECV_INITIAL_METADATA(exec_ctx);
Craig Tiller3d7c6092016-08-26 11:39:05 -07001627 GPR_ASSERT(s->recv_initial_metadata_ready == NULL);
Craig Tiller9c1ec542017-03-02 08:42:54 -08001628 s->recv_initial_metadata_ready =
1629 op_payload->recv_initial_metadata.recv_initial_metadata_ready;
1630 s->recv_initial_metadata =
1631 op_payload->recv_initial_metadata.recv_initial_metadata;
Mark D. Rothbd3b93b2017-06-22 10:53:01 -07001632 s->trailing_metadata_available =
1633 op_payload->recv_initial_metadata.trailing_metadata_available;
Mark D. Roth764cf042017-09-01 09:00:06 -07001634 if (op_payload->recv_initial_metadata.peer_string != NULL) {
1635 gpr_atm_rel_store(op_payload->recv_initial_metadata.peer_string,
1636 (gpr_atm)gpr_strdup(t->peer_string));
1637 }
Craig Tillereccf5102016-09-01 15:31:58 -07001638 grpc_chttp2_maybe_complete_recv_initial_metadata(exec_ctx, t, s);
Craig Tiller5dde66e2015-06-02 09:05:23 -07001639 }
Craig Tiller9d35a1f2015-11-02 14:16:12 -08001640
Craig Tiller9c1ec542017-03-02 08:42:54 -08001641 if (op->recv_message) {
Craig Tiller57bb9a92017-08-31 16:44:15 -07001642 GRPC_STATS_INC_HTTP2_OP_RECV_MESSAGE(exec_ctx);
Muxi Yanf0360762017-04-12 20:37:40 -07001643 size_t already_received;
Craig Tiller3d7c6092016-08-26 11:39:05 -07001644 GPR_ASSERT(s->recv_message_ready == NULL);
Muxi Yanf0360762017-04-12 20:37:40 -07001645 GPR_ASSERT(!s->pending_byte_stream);
Craig Tiller9c1ec542017-03-02 08:42:54 -08001646 s->recv_message_ready = op_payload->recv_message.recv_message_ready;
1647 s->recv_message = op_payload->recv_message.recv_message;
Muxi Yandd475482017-04-13 08:54:22 -07001648 if (s->id != 0) {
ncteisen3c909d52017-07-13 19:45:51 -07001649 if (!s->read_closed) {
ncteisenfb193a12017-07-28 15:47:32 -07001650 already_received = s->frame_storage.length;
ncteisen3c909d52017-07-13 19:45:51 -07001651 grpc_chttp2_flowctl_incoming_bs_update(
ncteisen8a46ba52017-08-01 10:59:10 -07001652 &t->flow_control, &s->flow_control, GRPC_HEADER_SIZE_IN_BYTES,
1653 already_received);
ncteisen020dbf22017-07-14 15:42:54 -07001654 grpc_chttp2_act_on_flowctl_action(
ncteisen3c909d52017-07-13 19:45:51 -07001655 exec_ctx,
ncteisen00f74a92017-07-14 15:41:05 -07001656 grpc_chttp2_flowctl_get_action(&t->flow_control, &s->flow_control),
ncteisen3c909d52017-07-13 19:45:51 -07001657 t, s);
1658 }
Craig Tillerc8b70132015-12-09 20:49:09 -08001659 }
Craig Tillereccf5102016-09-01 15:31:58 -07001660 grpc_chttp2_maybe_complete_recv_message(exec_ctx, t, s);
Craig Tiller9d35a1f2015-11-02 14:16:12 -08001661 }
1662
Craig Tiller9c1ec542017-03-02 08:42:54 -08001663 if (op->recv_trailing_metadata) {
Craig Tiller57bb9a92017-08-31 16:44:15 -07001664 GRPC_STATS_INC_HTTP2_OP_RECV_TRAILING_METADATA(exec_ctx);
Craig Tiller3d7c6092016-08-26 11:39:05 -07001665 GPR_ASSERT(s->recv_trailing_metadata_finished == NULL);
1666 s->recv_trailing_metadata_finished = add_closure_barrier(on_complete);
Craig Tiller9c1ec542017-03-02 08:42:54 -08001667 s->recv_trailing_metadata =
1668 op_payload->recv_trailing_metadata.recv_trailing_metadata;
Craig Tiller3d7c6092016-08-26 11:39:05 -07001669 s->final_metadata_requested = true;
Craig Tillereccf5102016-09-01 15:31:58 -07001670 grpc_chttp2_maybe_complete_recv_trailing_metadata(exec_ctx, t, s);
Craig Tiller9d35a1f2015-11-02 14:16:12 -08001671 }
1672
Craig Tiller3d7c6092016-08-26 11:39:05 -07001673 grpc_chttp2_complete_closure_step(exec_ctx, t, s, &on_complete,
Craig Tiller15b0ac02016-09-01 17:14:00 -07001674 GRPC_ERROR_NONE, "op->on_complete");
Craig Tiller9d35a1f2015-11-02 14:16:12 -08001675
Craig Tiller0ba432d2015-10-09 16:57:11 -07001676 GPR_TIMER_END("perform_stream_op_locked", 0);
Craig Tiller3d7c6092016-08-26 11:39:05 -07001677 GRPC_CHTTP2_STREAM_UNREF(exec_ctx, s, "perform_stream_op");
Craig Tiller50d9db52015-04-23 10:52:14 -07001678}
Craig Tillerbe18b8d2015-04-22 14:00:47 -07001679
Craig Tillera82950e2015-09-22 12:33:20 -07001680static void perform_stream_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
Craig Tillera0f3abd2017-03-31 15:42:16 -07001681 grpc_stream *gs,
1682 grpc_transport_stream_op_batch *op) {
Craig Tillerc69d27b2016-07-14 13:20:22 -07001683 GPR_TIMER_BEGIN("perform_stream_op", 0);
Craig Tillerb084d902015-06-12 07:50:02 -07001684 grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
Craig Tillerc3359192016-07-13 15:54:16 -07001685 grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs;
Craig Tillerc8db73c2016-08-30 14:00:48 -07001686
Craig Tiller095a2202017-05-17 09:02:44 -07001687 if (!t->is_client) {
1688 if (op->send_initial_metadata) {
Craig Tiller7ffb7232017-05-17 12:52:10 -07001689 gpr_timespec deadline =
1690 op->payload->send_initial_metadata.send_initial_metadata->deadline;
1691 GPR_ASSERT(0 ==
1692 gpr_time_cmp(gpr_inf_future(deadline.clock_type), deadline));
Craig Tiller095a2202017-05-17 09:02:44 -07001693 }
1694 if (op->send_trailing_metadata) {
Craig Tiller7ffb7232017-05-17 12:52:10 -07001695 gpr_timespec deadline =
1696 op->payload->send_trailing_metadata.send_trailing_metadata->deadline;
1697 GPR_ASSERT(0 ==
1698 gpr_time_cmp(gpr_inf_future(deadline.clock_type), deadline));
Craig Tiller095a2202017-05-17 09:02:44 -07001699 }
1700 }
1701
Craig Tiller84f75d42017-05-03 13:06:35 -07001702 if (GRPC_TRACER_ON(grpc_http_trace)) {
Craig Tillera0f3abd2017-03-31 15:42:16 -07001703 char *str = grpc_transport_stream_op_batch_string(op);
Craig Tiller9ba9f702017-05-04 08:17:30 -07001704 gpr_log(GPR_DEBUG, "perform_stream_op[s=%p]: %s", s, str);
Craig Tillerc8db73c2016-08-30 14:00:48 -07001705 gpr_free(str);
1706 }
1707
Craig Tiller9c1ec542017-03-02 08:42:54 -08001708 op->handler_private.extra_arg = gs;
Craig Tiller3d7c6092016-08-26 11:39:05 -07001709 GRPC_CHTTP2_STREAM_REF(s, "perform_stream_op");
ncteisen274bbbe2017-06-08 14:57:11 -07001710 GRPC_CLOSURE_SCHED(
Craig Tiller91031da2016-12-28 15:44:25 -08001711 exec_ctx,
ncteisen274bbbe2017-06-08 14:57:11 -07001712 GRPC_CLOSURE_INIT(&op->handler_private.closure, perform_stream_op_locked,
Craig Tilleree4b1452017-05-12 10:56:03 -07001713 op, grpc_combiner_scheduler(t->combiner)),
Craig Tiller91031da2016-12-28 15:44:25 -08001714 GRPC_ERROR_NONE);
Craig Tillerc69d27b2016-07-14 13:20:22 -07001715 GPR_TIMER_END("perform_stream_op", 0);
Craig Tillerbe18b8d2015-04-22 14:00:47 -07001716}
1717
Craig Tillerf7970dd2016-10-20 16:49:13 -07001718static void cancel_pings(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
1719 grpc_error *error) {
1720 /* callback remaining pings: they're not allowed to call into the transpot,
1721 and maybe they hold resources that need to be freed */
Craig Tillerad2a11f2016-12-28 13:05:00 -08001722 for (size_t i = 0; i < GRPC_CHTTP2_PING_TYPE_COUNT; i++) {
1723 grpc_chttp2_ping_queue *pq = &t->ping_queues[i];
Craig Tillerc0118b42016-12-29 12:17:57 -08001724 for (size_t j = 0; j < GRPC_CHTTP2_PCL_COUNT; j++) {
1725 grpc_closure_list_fail_all(&pq->lists[j], GRPC_ERROR_REF(error));
ncteisen274bbbe2017-06-08 14:57:11 -07001726 GRPC_CLOSURE_LIST_SCHED(exec_ctx, &pq->lists[j]);
Craig Tillerc0118b42016-12-29 12:17:57 -08001727 }
Craig Tillerf7970dd2016-10-20 16:49:13 -07001728 }
1729 GRPC_ERROR_UNREF(error);
1730}
1731
Craig Tiller3ff1fa62017-09-14 11:07:48 -07001732static void send_ping_locked(
1733 grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
1734 grpc_chttp2_ping_type ping_type, grpc_closure *on_initiate,
1735 grpc_closure *on_ack,
1736 grpc_chttp2_initiate_write_reason initiate_write_reason) {
Craig Tillerad2a11f2016-12-28 13:05:00 -08001737 grpc_chttp2_ping_queue *pq = &t->ping_queues[ping_type];
Craig Tillerc0118b42016-12-29 12:17:57 -08001738 grpc_closure_list_append(&pq->lists[GRPC_CHTTP2_PCL_INITIATE], on_initiate,
1739 GRPC_ERROR_NONE);
1740 if (grpc_closure_list_append(&pq->lists[GRPC_CHTTP2_PCL_NEXT], on_ack,
1741 GRPC_ERROR_NONE)) {
Craig Tiller3ff1fa62017-09-14 11:07:48 -07001742 grpc_chttp2_initiate_write(exec_ctx, t, initiate_write_reason);
Craig Tillerad2a11f2016-12-28 13:05:00 -08001743 }
Craig Tiller1766a912015-06-22 16:43:43 -07001744}
1745
Yuchen Zengb4b6a0e2017-02-28 22:06:52 -08001746static void retry_initiate_ping_locked(grpc_exec_ctx *exec_ctx, void *tp,
1747 grpc_error *error) {
Yash Tibrewal7cdd99c2017-09-08 16:04:12 -07001748 grpc_chttp2_transport *t = (grpc_chttp2_transport *)tp;
Yuchen Zengcbcdb402017-03-01 01:42:18 -08001749 t->ping_state.is_delayed_ping_timer_set = false;
Yuchen Zengad320752017-05-15 15:38:06 -07001750 if (error == GRPC_ERROR_NONE) {
1751 grpc_chttp2_initiate_write(exec_ctx, t,
1752 GRPC_CHTTP2_INITIATE_WRITE_RETRY_SEND_PING);
1753 }
Yuchen Zengb4b6a0e2017-02-28 22:06:52 -08001754}
1755
Craig Tiller3d7c6092016-08-26 11:39:05 -07001756void grpc_chttp2_ack_ping(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
Craig Tillerad2a11f2016-12-28 13:05:00 -08001757 uint64_t id) {
1758 grpc_chttp2_ping_queue *pq =
1759 &t->ping_queues[id % GRPC_CHTTP2_PING_TYPE_COUNT];
1760 if (pq->inflight_id != id) {
1761 char *from = grpc_endpoint_get_peer(t->ep);
1762 gpr_log(GPR_DEBUG, "Unknown ping response from %s: %" PRIx64, from, id);
1763 gpr_free(from);
1764 return;
Craig Tiller28bf8912015-12-07 16:07:04 -08001765 }
ncteisen274bbbe2017-06-08 14:57:11 -07001766 GRPC_CLOSURE_LIST_SCHED(exec_ctx, &pq->lists[GRPC_CHTTP2_PCL_INFLIGHT]);
Craig Tillerc0118b42016-12-29 12:17:57 -08001767 if (!grpc_closure_list_empty(pq->lists[GRPC_CHTTP2_PCL_NEXT])) {
Craig Tiller3ff1fa62017-09-14 11:07:48 -07001768 grpc_chttp2_initiate_write(exec_ctx, t,
1769 GRPC_CHTTP2_INITIATE_WRITE_CONTINUE_PINGS);
Craig Tillerc0118b42016-12-29 12:17:57 -08001770 }
Craig Tiller28bf8912015-12-07 16:07:04 -08001771}
1772
Craig Tiller25f29af2016-09-26 16:31:00 -07001773static void send_goaway(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001774 grpc_error *error) {
Craig Tiller25f29af2016-09-26 16:31:00 -07001775 t->sent_goaway_state = GRPC_CHTTP2_GOAWAY_SEND_SCHEDULED;
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001776 grpc_http2_error_code http_error;
ncteisenbbb38012017-03-10 14:58:43 -08001777 grpc_slice slice;
ncteisen4b36a3d2017-03-13 19:08:06 -07001778 grpc_error_get_status(error, gpr_inf_future(GPR_CLOCK_MONOTONIC), NULL,
1779 &slice, &http_error);
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001780 grpc_chttp2_goaway_append(t->last_new_stream_id, (uint32_t)http_error,
ncteisenbbb38012017-03-10 14:58:43 -08001781 grpc_slice_ref_internal(slice), &t->qbuf);
Craig Tiller3ff1fa62017-09-14 11:07:48 -07001782 grpc_chttp2_initiate_write(exec_ctx, t,
1783 GRPC_CHTTP2_INITIATE_WRITE_GOAWAY_SENT);
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001784 GRPC_ERROR_UNREF(error);
Craig Tiller25f29af2016-09-26 16:31:00 -07001785}
1786
Yuchen Zengfe593412017-03-27 15:36:53 -07001787void grpc_chttp2_add_ping_strike(grpc_exec_ctx *exec_ctx,
1788 grpc_chttp2_transport *t) {
Yuchen Zeng114a8482017-03-22 14:34:37 -07001789 gpr_log(GPR_DEBUG, "PING strike");
Yuchen Zeng0937fc12017-02-27 23:19:00 -08001790 if (++t->ping_recv_state.ping_strikes > t->ping_policy.max_ping_strikes &&
1791 t->ping_policy.max_ping_strikes != 0) {
1792 send_goaway(exec_ctx, t,
Yuchen Zeng78da2502017-03-24 13:40:22 -07001793 grpc_error_set_int(
1794 GRPC_ERROR_CREATE_FROM_STATIC_STRING("too_many_pings"),
1795 GRPC_ERROR_INT_HTTP2_ERROR, GRPC_HTTP2_ENHANCE_YOUR_CALM));
Yuchen Zeng0937fc12017-02-27 23:19:00 -08001796 /*The transport will be closed after the write is done */
Yuchen Zeng78da2502017-03-24 13:40:22 -07001797 close_transport_locked(
1798 exec_ctx, t, GRPC_ERROR_CREATE_FROM_STATIC_STRING("Too many pings"));
Yuchen Zeng0937fc12017-02-27 23:19:00 -08001799 }
1800}
1801
Craig Tillerd7f12e32016-03-03 10:08:31 -08001802static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx,
Craig Tiller93023e42016-07-11 12:43:23 -07001803 void *stream_op,
1804 grpc_error *error_ignored) {
Yash Tibrewal7cdd99c2017-09-08 16:04:12 -07001805 grpc_transport_op *op = (grpc_transport_op *)stream_op;
1806 grpc_chttp2_transport *t =
1807 (grpc_chttp2_transport *)op->handler_private.extra_arg;
Craig Tiller804ff712016-05-05 16:25:40 -07001808 grpc_error *close_transport = op->disconnect_with_error;
Craig Tiller45b135e2016-03-22 16:02:39 -07001809
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001810 if (op->goaway_error) {
1811 send_goaway(exec_ctx, t, op->goaway_error);
Craig Tillera82950e2015-09-22 12:33:20 -07001812 }
Craig Tiller1064f8b2015-06-25 13:52:57 -07001813
Craig Tillerd7f12e32016-03-03 10:08:31 -08001814 if (op->set_accept_stream) {
1815 t->channel_callback.accept_stream = op->set_accept_stream_fn;
Craig Tillera82950e2015-09-22 12:33:20 -07001816 t->channel_callback.accept_stream_user_data =
1817 op->set_accept_stream_user_data;
1818 }
Craig Tiller1064f8b2015-06-25 13:52:57 -07001819
Craig Tillera82950e2015-09-22 12:33:20 -07001820 if (op->bind_pollset) {
Craig Tiller93023e42016-07-11 12:43:23 -07001821 grpc_endpoint_add_to_pollset(exec_ctx, t->ep, op->bind_pollset);
Craig Tillera82950e2015-09-22 12:33:20 -07001822 }
Craig Tiller1064f8b2015-06-25 13:52:57 -07001823
Craig Tillera82950e2015-09-22 12:33:20 -07001824 if (op->bind_pollset_set) {
Craig Tiller93023e42016-07-11 12:43:23 -07001825 grpc_endpoint_add_to_pollset_set(exec_ctx, t->ep, op->bind_pollset_set);
Craig Tillera82950e2015-09-22 12:33:20 -07001826 }
Craig Tiller1ada6ad2015-07-16 16:19:14 -07001827
Craig Tillera82950e2015-09-22 12:33:20 -07001828 if (op->send_ping) {
Craig Tillerad2a11f2016-12-28 13:05:00 -08001829 send_ping_locked(exec_ctx, t, GRPC_CHTTP2_PING_ON_NEXT_WRITE, NULL,
Craig Tiller3ff1fa62017-09-14 11:07:48 -07001830 op->send_ping,
1831 GRPC_CHTTP2_INITIATE_WRITE_APPLICATION_PING);
Craig Tillera82950e2015-09-22 12:33:20 -07001832 }
Craig Tiller1064f8b2015-06-25 13:52:57 -07001833
Craig Tillerf7c8c9f2017-05-17 15:22:05 -07001834 if (op->on_connectivity_state_change != NULL) {
1835 grpc_connectivity_state_notify_on_state_change(
1836 exec_ctx, &t->channel_callback.state_tracker, op->connectivity_state,
1837 op->on_connectivity_state_change);
1838 }
1839
Craig Tiller804ff712016-05-05 16:25:40 -07001840 if (close_transport != GRPC_ERROR_NONE) {
1841 close_transport_locked(exec_ctx, t, close_transport);
Craig Tillera82950e2015-09-22 12:33:20 -07001842 }
Craig Tiller93023e42016-07-11 12:43:23 -07001843
ncteisen274bbbe2017-06-08 14:57:11 -07001844 GRPC_CLOSURE_RUN(exec_ctx, op->on_consumed, GRPC_ERROR_NONE);
Craig Tillerc3359192016-07-13 15:54:16 -07001845
Craig Tillerdfd3a8f2016-08-24 09:43:45 -07001846 GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "transport_op");
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001847}
1848
Craig Tillerd7f12e32016-03-03 10:08:31 -08001849static void perform_transport_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
1850 grpc_transport_op *op) {
1851 grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
Craig Tillere194ff02016-08-29 15:48:41 -07001852 char *msg = grpc_transport_op_string(op);
Craig Tillere194ff02016-08-29 15:48:41 -07001853 gpr_free(msg);
Craig Tillerc55c1022017-03-10 10:26:42 -08001854 op->handler_private.extra_arg = gt;
Craig Tillerdfd3a8f2016-08-24 09:43:45 -07001855 GRPC_CHTTP2_REF_TRANSPORT(t, "transport_op");
ncteisen274bbbe2017-06-08 14:57:11 -07001856 GRPC_CLOSURE_SCHED(exec_ctx,
1857 GRPC_CLOSURE_INIT(&op->handler_private.closure,
Craig Tilleree4b1452017-05-12 10:56:03 -07001858 perform_transport_op_locked, op,
1859 grpc_combiner_scheduler(t->combiner)),
1860 GRPC_ERROR_NONE);
Craig Tillerd7f12e32016-03-03 10:08:31 -08001861}
1862
Craig Tiller0cb803d2016-03-02 22:17:24 -08001863/*******************************************************************************
Craig Tiller45b135e2016-03-22 16:02:39 -07001864 * INPUT PROCESSING - GENERAL
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001865 */
1866
Craig Tillereccf5102016-09-01 15:31:58 -07001867void grpc_chttp2_maybe_complete_recv_initial_metadata(grpc_exec_ctx *exec_ctx,
1868 grpc_chttp2_transport *t,
1869 grpc_chttp2_stream *s) {
Craig Tillerbd37a212016-09-07 11:28:56 -07001870 if (s->recv_initial_metadata_ready != NULL &&
1871 s->published_metadata[0] != GRPC_METADATA_NOT_PUBLISHED) {
Craig Tillereccf5102016-09-01 15:31:58 -07001872 if (s->seen_error) {
Muxi Yan29723ee2017-04-12 20:24:42 -07001873 grpc_slice_buffer_reset_and_unref_internal(exec_ctx, &s->frame_storage);
1874 if (!s->pending_byte_stream) {
1875 grpc_slice_buffer_reset_and_unref_internal(
1876 exec_ctx, &s->unprocessed_incoming_frames_buffer);
yang-gad0df7b2016-02-22 10:00:20 -08001877 }
Craig Tiller9d35a1f2015-11-02 14:16:12 -08001878 }
Craig Tiller7c70b6c2017-01-23 07:48:42 -08001879 grpc_chttp2_incoming_metadata_buffer_publish(
1880 exec_ctx, &s->metadata_buffer[0], s->recv_initial_metadata);
Craig Tillerbd37a212016-09-07 11:28:56 -07001881 null_then_run_closure(exec_ctx, &s->recv_initial_metadata_ready,
1882 GRPC_ERROR_NONE);
Craig Tillereccf5102016-09-01 15:31:58 -07001883 }
1884}
1885
1886void grpc_chttp2_maybe_complete_recv_message(grpc_exec_ctx *exec_ctx,
1887 grpc_chttp2_transport *t,
1888 grpc_chttp2_stream *s) {
Muxi Yan29723ee2017-04-12 20:24:42 -07001889 grpc_error *error = GRPC_ERROR_NONE;
Craig Tillereccf5102016-09-01 15:31:58 -07001890 if (s->recv_message_ready != NULL) {
Muxi Yan29723ee2017-04-12 20:24:42 -07001891 *s->recv_message = NULL;
1892 if (s->final_metadata_requested && s->seen_error) {
1893 grpc_slice_buffer_reset_and_unref_internal(exec_ctx, &s->frame_storage);
1894 if (!s->pending_byte_stream) {
1895 grpc_slice_buffer_reset_and_unref_internal(
1896 exec_ctx, &s->unprocessed_incoming_frames_buffer);
1897 }
Craig Tillereccf5102016-09-01 15:31:58 -07001898 }
Muxi Yan29723ee2017-04-12 20:24:42 -07001899 if (!s->pending_byte_stream) {
1900 while (s->unprocessed_incoming_frames_buffer.length > 0 ||
1901 s->frame_storage.length > 0) {
1902 if (s->unprocessed_incoming_frames_buffer.length == 0) {
1903 grpc_slice_buffer_swap(&s->unprocessed_incoming_frames_buffer,
1904 &s->frame_storage);
Muxi Yan68198b52017-07-12 11:43:23 -07001905 s->unprocessed_incoming_frames_decompressed = false;
Muxi Yan29723ee2017-04-12 20:24:42 -07001906 }
Muxi Yan68198b52017-07-12 11:43:23 -07001907 if (s->stream_compression_recv_enabled &&
1908 !s->unprocessed_incoming_frames_decompressed) {
Muxi Yan9469ac42017-07-21 12:50:35 -07001909 GPR_ASSERT(s->decompressed_data_buffer->length == 0);
Muxi Yan68198b52017-07-12 11:43:23 -07001910 bool end_of_context;
Muxi Yan68198b52017-07-12 11:43:23 -07001911 if (!s->stream_decompression_ctx) {
1912 s->stream_decompression_ctx =
1913 grpc_stream_compression_context_create(
1914 GRPC_STREAM_COMPRESSION_DECOMPRESS);
1915 }
1916 if (!grpc_stream_decompress(s->stream_decompression_ctx,
1917 &s->unprocessed_incoming_frames_buffer,
Muxi Yan9469ac42017-07-21 12:50:35 -07001918 s->decompressed_data_buffer, NULL,
Muxi Yanf20bfaa2017-07-19 16:27:02 -07001919 GRPC_HEADER_SIZE_IN_BYTES,
Muxi Yan68198b52017-07-12 11:43:23 -07001920 &end_of_context)) {
1921 grpc_slice_buffer_reset_and_unref_internal(exec_ctx,
1922 &s->frame_storage);
1923 grpc_slice_buffer_reset_and_unref_internal(
1924 exec_ctx, &s->unprocessed_incoming_frames_buffer);
Muxi Yan26b33de2017-07-17 15:15:53 -07001925 error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
1926 "Stream decompression error.");
Muxi Yan68198b52017-07-12 11:43:23 -07001927 } else {
1928 error = grpc_deframe_unprocessed_incoming_frames(
Muxi Yan9469ac42017-07-21 12:50:35 -07001929 exec_ctx, &s->data_parser, s, s->decompressed_data_buffer, NULL,
1930 s->recv_message);
Muxi Yan68198b52017-07-12 11:43:23 -07001931 if (end_of_context) {
1932 grpc_stream_compression_context_destroy(
1933 s->stream_decompression_ctx);
1934 s->stream_decompression_ctx = NULL;
1935 }
1936 }
1937 } else {
1938 error = grpc_deframe_unprocessed_incoming_frames(
1939 exec_ctx, &s->data_parser, s,
1940 &s->unprocessed_incoming_frames_buffer, NULL, s->recv_message);
1941 }
Muxi Yan29723ee2017-04-12 20:24:42 -07001942 if (error != GRPC_ERROR_NONE) {
1943 s->seen_error = true;
1944 grpc_slice_buffer_reset_and_unref_internal(exec_ctx,
1945 &s->frame_storage);
1946 grpc_slice_buffer_reset_and_unref_internal(
1947 exec_ctx, &s->unprocessed_incoming_frames_buffer);
1948 break;
1949 } else if (*s->recv_message != NULL) {
1950 break;
1951 }
1952 }
1953 }
1954 if (error == GRPC_ERROR_NONE && *s->recv_message != NULL) {
Craig Tillerbd37a212016-09-07 11:28:56 -07001955 null_then_run_closure(exec_ctx, &s->recv_message_ready, GRPC_ERROR_NONE);
1956 } else if (s->published_metadata[1] != GRPC_METADATA_NOT_PUBLISHED) {
Craig Tillereccf5102016-09-01 15:31:58 -07001957 *s->recv_message = NULL;
Craig Tillerbd37a212016-09-07 11:28:56 -07001958 null_then_run_closure(exec_ctx, &s->recv_message_ready, GRPC_ERROR_NONE);
Craig Tiller9d35a1f2015-11-02 14:16:12 -08001959 }
Muxi Yan29723ee2017-04-12 20:24:42 -07001960 GRPC_ERROR_UNREF(error);
Craig Tiller9d35a1f2015-11-02 14:16:12 -08001961 }
Craig Tillereccf5102016-09-01 15:31:58 -07001962}
1963
1964void grpc_chttp2_maybe_complete_recv_trailing_metadata(grpc_exec_ctx *exec_ctx,
1965 grpc_chttp2_transport *t,
1966 grpc_chttp2_stream *s) {
Craig Tiller15b0ac02016-09-01 17:14:00 -07001967 grpc_chttp2_maybe_complete_recv_message(exec_ctx, t, s);
Craig Tillereccf5102016-09-01 15:31:58 -07001968 if (s->recv_trailing_metadata_finished != NULL && s->read_closed &&
1969 s->write_closed) {
1970 if (s->seen_error) {
Muxi Yan29723ee2017-04-12 20:24:42 -07001971 grpc_slice_buffer_reset_and_unref_internal(exec_ctx, &s->frame_storage);
1972 if (!s->pending_byte_stream) {
1973 grpc_slice_buffer_reset_and_unref_internal(
1974 exec_ctx, &s->unprocessed_incoming_frames_buffer);
Craig Tillereccf5102016-09-01 15:31:58 -07001975 }
1976 }
Muxi Yan29723ee2017-04-12 20:24:42 -07001977 bool pending_data = s->pending_byte_stream ||
1978 s->unprocessed_incoming_frames_buffer.length > 0;
Muxi Yan0fd37e12017-07-13 21:07:29 -07001979 if (s->stream_compression_recv_enabled && s->read_closed &&
Muxi Yan458214f2017-08-07 11:49:26 -07001980 s->frame_storage.length > 0 && !pending_data && !s->seen_error &&
1981 s->recv_trailing_metadata_finished != NULL) {
Muxi Yan0fd37e12017-07-13 21:07:29 -07001982 /* Maybe some SYNC_FLUSH data is left in frame_storage. Consume them and
1983 * maybe decompress the next 5 bytes in the stream. */
1984 bool end_of_context;
1985 if (!s->stream_decompression_ctx) {
Muxi Yan26b33de2017-07-17 15:15:53 -07001986 s->stream_decompression_ctx = grpc_stream_compression_context_create(
1987 GRPC_STREAM_COMPRESSION_DECOMPRESS);
Muxi Yan0fd37e12017-07-13 21:07:29 -07001988 }
1989 if (!grpc_stream_decompress(s->stream_decompression_ctx,
1990 &s->frame_storage,
Muxi Yan26b33de2017-07-17 15:15:53 -07001991 &s->unprocessed_incoming_frames_buffer, NULL,
Muxi Yanf20bfaa2017-07-19 16:27:02 -07001992 GRPC_HEADER_SIZE_IN_BYTES, &end_of_context)) {
Muxi Yan26b33de2017-07-17 15:15:53 -07001993 grpc_slice_buffer_reset_and_unref_internal(exec_ctx, &s->frame_storage);
Muxi Yan0fd37e12017-07-13 21:07:29 -07001994 grpc_slice_buffer_reset_and_unref_internal(
1995 exec_ctx, &s->unprocessed_incoming_frames_buffer);
1996 s->seen_error = true;
1997 } else {
1998 if (s->unprocessed_incoming_frames_buffer.length > 0) {
1999 s->unprocessed_incoming_frames_decompressed = true;
2000 }
2001 if (end_of_context) {
2002 grpc_stream_compression_context_destroy(s->stream_decompression_ctx);
2003 s->stream_decompression_ctx = NULL;
2004 }
2005 }
2006 }
Mark D. Roth764cf042017-09-01 09:00:06 -07002007 if (s->read_closed && s->frame_storage.length == 0 && !pending_data &&
Craig Tillerbd37a212016-09-07 11:28:56 -07002008 s->recv_trailing_metadata_finished != NULL) {
Craig Tiller7c70b6c2017-01-23 07:48:42 -08002009 grpc_chttp2_incoming_metadata_buffer_publish(
2010 exec_ctx, &s->metadata_buffer[1], s->recv_trailing_metadata);
Craig Tillereccf5102016-09-01 15:31:58 -07002011 grpc_chttp2_complete_closure_step(
Craig Tillerbd37a212016-09-07 11:28:56 -07002012 exec_ctx, t, s, &s->recv_trailing_metadata_finished, GRPC_ERROR_NONE,
2013 "recv_trailing_metadata_finished");
Craig Tillereccf5102016-09-01 15:31:58 -07002014 }
2015 }
Craig Tillerf73fcd12015-06-16 16:25:26 -07002016}
2017
Craig Tillera82950e2015-09-22 12:33:20 -07002018static void remove_stream(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
Craig Tiller692bb332016-05-13 11:02:49 -07002019 uint32_t id, grpc_error *error) {
Yash Tibrewal7cdd99c2017-09-08 16:04:12 -07002020 grpc_chttp2_stream *s =
2021 (grpc_chttp2_stream *)grpc_chttp2_stream_map_delete(&t->stream_map, id);
Craig Tiller759eb322015-06-16 22:41:18 -07002022 GPR_ASSERT(s);
Craig Tiller3d7c6092016-08-26 11:39:05 -07002023 if (t->incoming_stream == s) {
2024 t->incoming_stream = NULL;
2025 grpc_chttp2_parsing_become_skip_parser(exec_ctx, t);
Craig Tillera82950e2015-09-22 12:33:20 -07002026 }
Muxi Yan29723ee2017-04-12 20:24:42 -07002027 if (s->pending_byte_stream) {
2028 if (s->on_next != NULL) {
2029 grpc_chttp2_incoming_byte_stream *bs = s->data_parser.parsing_frame;
2030 if (error == GRPC_ERROR_NONE) {
2031 error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Truncated message");
2032 }
2033 incoming_byte_stream_publish_error(exec_ctx, bs, error);
2034 incoming_byte_stream_unref(exec_ctx, bs);
2035 s->data_parser.parsing_frame = NULL;
2036 } else {
2037 GRPC_ERROR_UNREF(s->byte_stream_error);
2038 s->byte_stream_error = GRPC_ERROR_REF(error);
2039 }
Craig Tiller66abdaa2015-06-17 08:00:39 -07002040 }
Craig Tiller8823b142015-06-18 11:41:24 -07002041
Craig Tiller25f29af2016-09-26 16:31:00 -07002042 if (grpc_chttp2_stream_map_size(&t->stream_map) == 0) {
Craig Tiller795451f2016-09-27 08:47:28 -07002043 post_benign_reclaimer(exec_ctx, t);
Craig Tiller25f29af2016-09-26 16:31:00 -07002044 if (t->sent_goaway_state == GRPC_CHTTP2_GOAWAY_SENT) {
2045 close_transport_locked(
2046 exec_ctx, t,
ncteisen4b36a3d2017-03-13 19:08:06 -07002047 GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
Craig Tiller25f29af2016-09-26 16:31:00 -07002048 "Last stream closed after sending GOAWAY", &error, 1));
2049 }
Craig Tillera82950e2015-09-22 12:33:20 -07002050 }
Craig Tiller3d7c6092016-08-26 11:39:05 -07002051 if (grpc_chttp2_list_remove_writable_stream(t, s)) {
Craig Tillerfd4c6472016-09-06 20:03:06 -07002052 GRPC_CHTTP2_STREAM_UNREF(exec_ctx, s, "chttp2_writing:remove_stream");
Craig Tiller0cb803d2016-03-02 22:17:24 -08002053 }
Craig Tiller8823b142015-06-18 11:41:24 -07002054
Craig Tiller692bb332016-05-13 11:02:49 -07002055 GRPC_ERROR_UNREF(error);
Craig Tiller796f5252016-08-19 10:44:48 -07002056
Craig Tiller3d7c6092016-08-26 11:39:05 -07002057 maybe_start_some_streams(exec_ctx, t);
Craig Tiller759eb322015-06-16 22:41:18 -07002058}
2059
Craig Tiller31375ac2016-08-22 09:08:00 -07002060void grpc_chttp2_cancel_stream(grpc_exec_ctx *exec_ctx,
Craig Tiller3d7c6092016-08-26 11:39:05 -07002061 grpc_chttp2_transport *t, grpc_chttp2_stream *s,
Craig Tiller31375ac2016-08-22 09:08:00 -07002062 grpc_error *due_to_error) {
Craig Tiller7c70b6c2017-01-23 07:48:42 -08002063 if (!t->is_client && !s->sent_trailing_metadata &&
2064 grpc_error_has_clear_grpc_status(due_to_error)) {
2065 close_from_api(exec_ctx, t, s, due_to_error);
2066 return;
2067 }
Craig Tiller5e01e2a2017-01-20 18:11:52 -08002068
Craig Tiller7c70b6c2017-01-23 07:48:42 -08002069 if (!s->read_closed || !s->write_closed) {
Craig Tiller3d7c6092016-08-26 11:39:05 -07002070 if (s->id != 0) {
Craig Tiller7c70b6c2017-01-23 07:48:42 -08002071 grpc_http2_error_code http_error;
2072 grpc_error_get_status(due_to_error, s->deadline, NULL, NULL, &http_error);
Craig Tillerd41a4a72016-10-26 16:16:06 -07002073 grpc_slice_buffer_add(
Craig Tiller3d7c6092016-08-26 11:39:05 -07002074 &t->qbuf, grpc_chttp2_rst_stream_create(s->id, (uint32_t)http_error,
2075 &s->stats.outgoing));
Craig Tiller3ff1fa62017-09-14 11:07:48 -07002076 grpc_chttp2_initiate_write(exec_ctx, t,
2077 GRPC_CHTTP2_INITIATE_WRITE_RST_STREAM);
Craig Tillerc48ca712016-04-04 13:42:04 -07002078 }
Craig Tillerb787c502015-06-15 16:14:52 -07002079 }
Craig Tiller3d7c6092016-08-26 11:39:05 -07002080 if (due_to_error != GRPC_ERROR_NONE && !s->seen_error) {
2081 s->seen_error = true;
Craig Tillerb27c0f82016-04-11 22:37:22 -07002082 }
Craig Tiller3d7c6092016-08-26 11:39:05 -07002083 grpc_chttp2_mark_stream_closed(exec_ctx, t, s, 1, 1, due_to_error);
Craig Tillerb787c502015-06-15 16:14:52 -07002084}
2085
Craig Tiller3d7c6092016-08-26 11:39:05 -07002086void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
Craig Tiller7c70b6c2017-01-23 07:48:42 -08002087 grpc_chttp2_stream *s, grpc_error *error) {
2088 grpc_status_code status;
ncteisenbbb38012017-03-10 14:58:43 -08002089 grpc_slice slice;
2090 grpc_error_get_status(error, s->deadline, &status, &slice, NULL);
Craig Tiller7c70b6c2017-01-23 07:48:42 -08002091
Craig Tiller9d35a1f2015-11-02 14:16:12 -08002092 if (status != GRPC_STATUS_OK) {
Craig Tiller3d7c6092016-08-26 11:39:05 -07002093 s->seen_error = true;
Craig Tiller9d35a1f2015-11-02 14:16:12 -08002094 }
Craig Tiller4b65b1d2015-11-03 07:04:30 -08002095 /* stream_global->recv_trailing_metadata_finished gives us a
2096 last chance replacement: we've received trailing metadata,
2097 but something more important has become available to signal
2098 to the upper layers - drop what we've got, and then publish
2099 what we want - which is safe because we haven't told anyone
2100 about the metadata yet */
Craig Tillerbd37a212016-09-07 11:28:56 -07002101 if (s->published_metadata[1] == GRPC_METADATA_NOT_PUBLISHED ||
2102 s->recv_trailing_metadata_finished != NULL) {
Craig Tiller9d35a1f2015-11-02 14:16:12 -08002103 char status_string[GPR_LTOA_MIN_BUFSIZE];
2104 gpr_ltoa(status, status_string);
Craig Tiller7d2c3982017-03-13 12:58:29 -07002105 GRPC_LOG_IF_ERROR("add_status",
2106 grpc_chttp2_incoming_metadata_buffer_replace_or_add(
2107 exec_ctx, &s->metadata_buffer[1],
2108 grpc_mdelem_from_slices(
2109 exec_ctx, GRPC_MDSTR_GRPC_STATUS,
2110 grpc_slice_from_copied_string(status_string))));
Noah Eisen3d194ad2017-03-22 14:34:42 -07002111 if (!GRPC_SLICE_IS_EMPTY(slice)) {
Craig Tiller7d2c3982017-03-13 12:58:29 -07002112 GRPC_LOG_IF_ERROR(
2113 "add_status_message",
2114 grpc_chttp2_incoming_metadata_buffer_replace_or_add(
2115 exec_ctx, &s->metadata_buffer[1],
2116 grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_GRPC_MESSAGE,
Noah Eisen3d194ad2017-03-22 14:34:42 -07002117 grpc_slice_ref_internal(slice))));
Craig Tiller9d35a1f2015-11-02 14:16:12 -08002118 }
Craig Tillerbd37a212016-09-07 11:28:56 -07002119 s->published_metadata[1] = GRPC_METADATA_SYNTHESIZED_FROM_FAKE;
Craig Tillereccf5102016-09-01 15:31:58 -07002120 grpc_chttp2_maybe_complete_recv_trailing_metadata(exec_ctx, t, s);
Craig Tiller9d35a1f2015-11-02 14:16:12 -08002121 }
Craig Tiller7c70b6c2017-01-23 07:48:42 -08002122
2123 GRPC_ERROR_UNREF(error);
Craig Tiller9d35a1f2015-11-02 14:16:12 -08002124}
2125
Craig Tiller4ebfe902016-07-06 16:24:45 -07002126static void add_error(grpc_error *error, grpc_error **refs, size_t *nrefs) {
2127 if (error == GRPC_ERROR_NONE) return;
2128 for (size_t i = 0; i < *nrefs; i++) {
2129 if (error == refs[i]) {
2130 return;
2131 }
2132 }
2133 refs[*nrefs] = error;
2134 ++*nrefs;
2135}
2136
Craig Tiller936f1ea2016-10-14 15:15:19 -07002137static grpc_error *removal_error(grpc_error *extra_error, grpc_chttp2_stream *s,
2138 const char *master_error_msg) {
Craig Tiller4ebfe902016-07-06 16:24:45 -07002139 grpc_error *refs[3];
2140 size_t nrefs = 0;
Craig Tiller3d7c6092016-08-26 11:39:05 -07002141 add_error(s->read_closed_error, refs, &nrefs);
2142 add_error(s->write_closed_error, refs, &nrefs);
Craig Tiller4ebfe902016-07-06 16:24:45 -07002143 add_error(extra_error, refs, &nrefs);
2144 grpc_error *error = GRPC_ERROR_NONE;
2145 if (nrefs > 0) {
ncteisen4b36a3d2017-03-13 19:08:06 -07002146 error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(master_error_msg,
2147 refs, nrefs);
Craig Tiller4ebfe902016-07-06 16:24:45 -07002148 }
2149 GRPC_ERROR_UNREF(extra_error);
2150 return error;
2151}
2152
Craig Tillere9a76652017-05-12 13:17:14 -07002153static void flush_write_list(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
2154 grpc_chttp2_stream *s, grpc_chttp2_write_cb **list,
2155 grpc_error *error) {
2156 while (*list) {
2157 grpc_chttp2_write_cb *cb = *list;
2158 *list = cb->next;
2159 grpc_chttp2_complete_closure_step(exec_ctx, t, s, &cb->closure,
2160 GRPC_ERROR_REF(error),
2161 "on_write_finished_cb");
2162 cb->next = t->write_cb_pool;
2163 t->write_cb_pool = cb;
2164 }
2165 GRPC_ERROR_UNREF(error);
2166}
2167
Craig Tillerac88ca12016-11-16 14:21:29 -08002168void grpc_chttp2_fail_pending_writes(grpc_exec_ctx *exec_ctx,
2169 grpc_chttp2_transport *t,
2170 grpc_chttp2_stream *s, grpc_error *error) {
Craig Tiller936f1ea2016-10-14 15:15:19 -07002171 error =
2172 removal_error(error, s, "Pending writes failed due to stream closure");
David Garcia Quintased2f3082016-11-10 18:41:52 -08002173 s->send_initial_metadata = NULL;
Craig Tillerbd37a212016-09-07 11:28:56 -07002174 grpc_chttp2_complete_closure_step(
2175 exec_ctx, t, s, &s->send_initial_metadata_finished, GRPC_ERROR_REF(error),
2176 "send_initial_metadata_finished");
David Garcia Quintased2f3082016-11-10 18:41:52 -08002177
2178 s->send_trailing_metadata = NULL;
Craig Tillerbd37a212016-09-07 11:28:56 -07002179 grpc_chttp2_complete_closure_step(
2180 exec_ctx, t, s, &s->send_trailing_metadata_finished,
2181 GRPC_ERROR_REF(error), "send_trailing_metadata_finished");
David Garcia Quintased2f3082016-11-10 18:41:52 -08002182
2183 s->fetching_send_message = NULL;
Craig Tillerbd37a212016-09-07 11:28:56 -07002184 grpc_chttp2_complete_closure_step(
2185 exec_ctx, t, s, &s->fetching_send_message_finished, GRPC_ERROR_REF(error),
2186 "fetching_send_message_finished");
Craig Tillere9a76652017-05-12 13:17:14 -07002187 flush_write_list(exec_ctx, t, s, &s->on_write_finished_cbs,
2188 GRPC_ERROR_REF(error));
2189 flush_write_list(exec_ctx, t, s, &s->on_flow_controlled_cbs, error);
Craig Tillerabb2e3d2015-12-15 06:23:59 -08002190}
2191
Craig Tiller3d7c6092016-08-26 11:39:05 -07002192void grpc_chttp2_mark_stream_closed(grpc_exec_ctx *exec_ctx,
2193 grpc_chttp2_transport *t,
2194 grpc_chttp2_stream *s, int close_reads,
2195 int close_writes, grpc_error *error) {
2196 if (s->read_closed && s->write_closed) {
Craig Tiller9d35a1f2015-11-02 14:16:12 -08002197 /* already closed */
Craig Tiller7c70b6c2017-01-23 07:48:42 -08002198 grpc_chttp2_maybe_complete_recv_trailing_metadata(exec_ctx, t, s);
Craig Tillerf707d622016-05-06 14:26:12 -07002199 GRPC_ERROR_UNREF(error);
Craig Tiller9d35a1f2015-11-02 14:16:12 -08002200 return;
2201 }
Craig Tiller7c70b6c2017-01-23 07:48:42 -08002202 bool closed_read = false;
2203 bool became_closed = false;
Craig Tiller3d7c6092016-08-26 11:39:05 -07002204 if (close_reads && !s->read_closed) {
2205 s->read_closed_error = GRPC_ERROR_REF(error);
2206 s->read_closed = true;
Craig Tiller7c70b6c2017-01-23 07:48:42 -08002207 closed_read = true;
2208 }
2209 if (close_writes && !s->write_closed) {
2210 s->write_closed_error = GRPC_ERROR_REF(error);
2211 s->write_closed = true;
2212 grpc_chttp2_fail_pending_writes(exec_ctx, t, s, GRPC_ERROR_REF(error));
2213 }
2214 if (s->read_closed && s->write_closed) {
2215 became_closed = true;
2216 grpc_error *overall_error =
2217 removal_error(GRPC_ERROR_REF(error), s, "Stream removed");
2218 if (s->id != 0) {
2219 remove_stream(exec_ctx, t, s->id, GRPC_ERROR_REF(overall_error));
2220 } else {
2221 /* Purge streams waiting on concurrency still waiting for id assignment */
2222 grpc_chttp2_list_remove_waiting_for_concurrency(t, s);
2223 }
2224 if (overall_error != GRPC_ERROR_NONE) {
2225 grpc_chttp2_fake_status(exec_ctx, t, s, overall_error);
2226 }
2227 }
2228 if (closed_read) {
Craig Tillerbd37a212016-09-07 11:28:56 -07002229 for (int i = 0; i < 2; i++) {
2230 if (s->published_metadata[i] == GRPC_METADATA_NOT_PUBLISHED) {
2231 s->published_metadata[i] = GPRC_METADATA_PUBLISHED_AT_CLOSE;
2232 }
2233 }
Craig Tillereccf5102016-09-01 15:31:58 -07002234 grpc_chttp2_maybe_complete_recv_initial_metadata(exec_ctx, t, s);
2235 grpc_chttp2_maybe_complete_recv_message(exec_ctx, t, s);
Craig Tiller5e01e2a2017-01-20 18:11:52 -08002236 }
Craig Tiller7c70b6c2017-01-23 07:48:42 -08002237 if (became_closed) {
Craig Tiller5e01e2a2017-01-20 18:11:52 -08002238 grpc_chttp2_maybe_complete_recv_trailing_metadata(exec_ctx, t, s);
Craig Tiller3d7c6092016-08-26 11:39:05 -07002239 GRPC_CHTTP2_STREAM_UNREF(exec_ctx, s, "chttp2");
Craig Tiller9d35a1f2015-11-02 14:16:12 -08002240 }
Craig Tillerf707d622016-05-06 14:26:12 -07002241 GRPC_ERROR_UNREF(error);
Craig Tiller9d35a1f2015-11-02 14:16:12 -08002242}
2243
Craig Tiller3d7c6092016-08-26 11:39:05 -07002244static void close_from_api(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
2245 grpc_chttp2_stream *s, grpc_error *error) {
Craig Tillerd41a4a72016-10-26 16:16:06 -07002246 grpc_slice hdr;
2247 grpc_slice status_hdr;
Muxi Yan3c3093c2017-03-17 14:36:01 -07002248 grpc_slice http_status_hdr;
Muxi Yan48cba2a2017-04-10 17:08:01 -07002249 grpc_slice content_type_hdr;
Craig Tillerd41a4a72016-10-26 16:16:06 -07002250 grpc_slice message_pfx;
Craig Tiller7536af02015-12-22 13:49:30 -08002251 uint8_t *p;
2252 uint32_t len = 0;
Craig Tillerf0f70a82016-06-23 13:55:06 -07002253 grpc_status_code grpc_status;
ncteisenbbb38012017-03-10 14:58:43 -08002254 grpc_slice slice;
2255 grpc_error_get_status(error, s->deadline, &grpc_status, &slice, NULL);
Craig Tiller45ce9272015-07-31 11:22:35 -07002256
Craig Tillerf0f70a82016-06-23 13:55:06 -07002257 GPR_ASSERT(grpc_status >= 0 && (int)grpc_status < 100);
Craig Tiller45ce9272015-07-31 11:22:35 -07002258
Craig Tiller7c70b6c2017-01-23 07:48:42 -08002259 /* Hand roll a header block.
2260 This is unnecessarily ugly - at some point we should find a more
2261 elegant solution.
2262 It's complicated by the fact that our send machinery would be dead by
2263 the time we got around to sending this, so instead we ignore HPACK
2264 compression and just write the uncompressed bytes onto the wire. */
Muxi Yan3c3093c2017-03-17 14:36:01 -07002265 if (!s->sent_initial_metadata) {
Craig Tiller423d6fd2017-04-12 13:15:45 -07002266 http_status_hdr = GRPC_SLICE_MALLOC(13);
Muxi Yan3c3093c2017-03-17 14:36:01 -07002267 p = GRPC_SLICE_START_PTR(http_status_hdr);
2268 *p++ = 0x00;
2269 *p++ = 7;
2270 *p++ = ':';
2271 *p++ = 's';
2272 *p++ = 't';
2273 *p++ = 'a';
2274 *p++ = 't';
2275 *p++ = 'u';
2276 *p++ = 's';
2277 *p++ = 3;
2278 *p++ = '2';
2279 *p++ = '0';
2280 *p++ = '0';
2281 GPR_ASSERT(p == GRPC_SLICE_END_PTR(http_status_hdr));
2282 len += (uint32_t)GRPC_SLICE_LENGTH(http_status_hdr);
Muxi Yan48cba2a2017-04-10 17:08:01 -07002283
Craig Tillerc39fbcf2017-04-17 08:20:25 -07002284 content_type_hdr = GRPC_SLICE_MALLOC(31);
Muxi Yan48cba2a2017-04-10 17:08:01 -07002285 p = GRPC_SLICE_START_PTR(content_type_hdr);
2286 *p++ = 0x00;
2287 *p++ = 12;
2288 *p++ = 'c';
2289 *p++ = 'o';
2290 *p++ = 'n';
2291 *p++ = 't';
2292 *p++ = 'e';
2293 *p++ = 'n';
2294 *p++ = 't';
2295 *p++ = '-';
2296 *p++ = 't';
2297 *p++ = 'y';
2298 *p++ = 'p';
2299 *p++ = 'e';
2300 *p++ = 16;
2301 *p++ = 'a';
2302 *p++ = 'p';
2303 *p++ = 'p';
2304 *p++ = 'l';
2305 *p++ = 'i';
2306 *p++ = 'c';
2307 *p++ = 'a';
2308 *p++ = 't';
2309 *p++ = 'i';
2310 *p++ = 'o';
2311 *p++ = 'n';
2312 *p++ = '/';
2313 *p++ = 'g';
2314 *p++ = 'r';
2315 *p++ = 'p';
2316 *p++ = 'c';
2317 GPR_ASSERT(p == GRPC_SLICE_END_PTR(content_type_hdr));
2318 len += (uint32_t)GRPC_SLICE_LENGTH(content_type_hdr);
Muxi Yan3c3093c2017-03-17 14:36:01 -07002319 }
2320
Craig Tiller423d6fd2017-04-12 13:15:45 -07002321 status_hdr = GRPC_SLICE_MALLOC(15 + (grpc_status >= 10));
Craig Tiller7c70b6c2017-01-23 07:48:42 -08002322 p = GRPC_SLICE_START_PTR(status_hdr);
2323 *p++ = 0x00; /* literal header, not indexed */
2324 *p++ = 11; /* len(grpc-status) */
2325 *p++ = 'g';
2326 *p++ = 'r';
2327 *p++ = 'p';
2328 *p++ = 'c';
2329 *p++ = '-';
2330 *p++ = 's';
2331 *p++ = 't';
2332 *p++ = 'a';
2333 *p++ = 't';
2334 *p++ = 'u';
2335 *p++ = 's';
2336 if (grpc_status < 10) {
2337 *p++ = 1;
2338 *p++ = (uint8_t)('0' + grpc_status);
2339 } else {
2340 *p++ = 2;
2341 *p++ = (uint8_t)('0' + (grpc_status / 10));
2342 *p++ = (uint8_t)('0' + (grpc_status % 10));
2343 }
2344 GPR_ASSERT(p == GRPC_SLICE_END_PTR(status_hdr));
2345 len += (uint32_t)GRPC_SLICE_LENGTH(status_hdr);
2346
ncteisenbbb38012017-03-10 14:58:43 -08002347 size_t msg_len = GRPC_SLICE_LENGTH(slice);
2348 GPR_ASSERT(msg_len <= UINT32_MAX);
yang-ga8a56902017-03-23 14:07:28 -07002349 uint32_t msg_len_len = GRPC_CHTTP2_VARINT_LENGTH((uint32_t)msg_len, 1);
Craig Tiller423d6fd2017-04-12 13:15:45 -07002350 message_pfx = GRPC_SLICE_MALLOC(14 + msg_len_len);
ncteisenbbb38012017-03-10 14:58:43 -08002351 p = GRPC_SLICE_START_PTR(message_pfx);
2352 *p++ = 0x00; /* literal header, not indexed */
2353 *p++ = 12; /* len(grpc-message) */
2354 *p++ = 'g';
2355 *p++ = 'r';
2356 *p++ = 'p';
2357 *p++ = 'c';
2358 *p++ = '-';
2359 *p++ = 'm';
2360 *p++ = 'e';
2361 *p++ = 's';
2362 *p++ = 's';
2363 *p++ = 'a';
2364 *p++ = 'g';
2365 *p++ = 'e';
yang-ga8a56902017-03-23 14:07:28 -07002366 GRPC_CHTTP2_WRITE_VARINT((uint32_t)msg_len, 1, 0, p, (uint32_t)msg_len_len);
ncteisenbbb38012017-03-10 14:58:43 -08002367 p += msg_len_len;
2368 GPR_ASSERT(p == GRPC_SLICE_END_PTR(message_pfx));
2369 len += (uint32_t)GRPC_SLICE_LENGTH(message_pfx);
2370 len += (uint32_t)msg_len;
Craig Tiller45ce9272015-07-31 11:22:35 -07002371
Craig Tiller423d6fd2017-04-12 13:15:45 -07002372 hdr = GRPC_SLICE_MALLOC(9);
Craig Tiller7c70b6c2017-01-23 07:48:42 -08002373 p = GRPC_SLICE_START_PTR(hdr);
2374 *p++ = (uint8_t)(len >> 16);
2375 *p++ = (uint8_t)(len >> 8);
2376 *p++ = (uint8_t)(len);
2377 *p++ = GRPC_CHTTP2_FRAME_HEADER;
2378 *p++ = GRPC_CHTTP2_DATA_FLAG_END_STREAM | GRPC_CHTTP2_DATA_FLAG_END_HEADERS;
2379 *p++ = (uint8_t)(s->id >> 24);
2380 *p++ = (uint8_t)(s->id >> 16);
2381 *p++ = (uint8_t)(s->id >> 8);
2382 *p++ = (uint8_t)(s->id);
2383 GPR_ASSERT(p == GRPC_SLICE_END_PTR(hdr));
2384
2385 grpc_slice_buffer_add(&t->qbuf, hdr);
Muxi Yan3c3093c2017-03-17 14:36:01 -07002386 if (!s->sent_initial_metadata) {
2387 grpc_slice_buffer_add(&t->qbuf, http_status_hdr);
Muxi Yan48cba2a2017-04-10 17:08:01 -07002388 grpc_slice_buffer_add(&t->qbuf, content_type_hdr);
Craig Tillera82950e2015-09-22 12:33:20 -07002389 }
Craig Tiller45724b32015-09-22 10:42:19 -07002390 grpc_slice_buffer_add(&t->qbuf, status_hdr);
ncteisenbbb38012017-03-10 14:58:43 -08002391 grpc_slice_buffer_add(&t->qbuf, message_pfx);
2392 grpc_slice_buffer_add(&t->qbuf, grpc_slice_ref_internal(slice));
Craig Tiller7c70b6c2017-01-23 07:48:42 -08002393 grpc_slice_buffer_add(
2394 &t->qbuf, grpc_chttp2_rst_stream_create(s->id, GRPC_HTTP2_NO_ERROR,
2395 &s->stats.outgoing));
Craig Tiller45ce9272015-07-31 11:22:35 -07002396
Craig Tiller3d7c6092016-08-26 11:39:05 -07002397 grpc_chttp2_mark_stream_closed(exec_ctx, t, s, 1, 1, error);
Craig Tiller3ff1fa62017-09-14 11:07:48 -07002398 grpc_chttp2_initiate_write(exec_ctx, t,
2399 GRPC_CHTTP2_INITIATE_WRITE_CLOSE_FROM_API);
ctiller00297df2015-01-12 11:23:09 -08002400}
2401
Craig Tillerf0f70a82016-06-23 13:55:06 -07002402typedef struct {
2403 grpc_exec_ctx *exec_ctx;
2404 grpc_error *error;
Craig Tiller032b5152016-08-21 13:30:09 -07002405 grpc_chttp2_transport *t;
Craig Tillerf0f70a82016-06-23 13:55:06 -07002406} cancel_stream_cb_args;
2407
Craig Tiller032b5152016-08-21 13:30:09 -07002408static void cancel_stream_cb(void *user_data, uint32_t key, void *stream) {
Yash Tibrewal7cdd99c2017-09-08 16:04:12 -07002409 cancel_stream_cb_args *args = (cancel_stream_cb_args *)user_data;
2410 grpc_chttp2_stream *s = (grpc_chttp2_stream *)stream;
Craig Tiller3d7c6092016-08-26 11:39:05 -07002411 grpc_chttp2_cancel_stream(args->exec_ctx, args->t, s,
Craig Tiller31375ac2016-08-22 09:08:00 -07002412 GRPC_ERROR_REF(args->error));
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08002413}
2414
Craig Tillerf0f70a82016-06-23 13:55:06 -07002415static void end_all_the_calls(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
2416 grpc_error *error) {
Craig Tiller032b5152016-08-21 13:30:09 -07002417 cancel_stream_cb_args args = {exec_ctx, error, t};
2418 grpc_chttp2_stream_map_for_each(&t->stream_map, cancel_stream_cb, &args);
Craig Tillerf0f70a82016-06-23 13:55:06 -07002419 GRPC_ERROR_UNREF(error);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08002420}
2421
Craig Tiller45b135e2016-03-22 16:02:39 -07002422/*******************************************************************************
2423 * INPUT PROCESSING - PARSING
2424 */
2425
ncteisen020dbf22017-07-14 15:42:54 -07002426void grpc_chttp2_act_on_flowctl_action(grpc_exec_ctx *exec_ctx,
2427 grpc_chttp2_flowctl_action action,
2428 grpc_chttp2_transport *t,
2429 grpc_chttp2_stream *s) {
2430 switch (action.send_stream_update) {
2431 case GRPC_CHTTP2_FLOWCTL_NO_ACTION_NEEDED:
2432 break;
2433 case GRPC_CHTTP2_FLOWCTL_UPDATE_IMMEDIATELY:
Craig Tiller3ff1fa62017-09-14 11:07:48 -07002434 grpc_chttp2_mark_stream_writable(exec_ctx, t, s);
2435 grpc_chttp2_initiate_write(
2436 exec_ctx, t, GRPC_CHTTP2_INITIATE_WRITE_STREAM_FLOW_CONTROL);
ncteisen020dbf22017-07-14 15:42:54 -07002437 break;
2438 case GRPC_CHTTP2_FLOWCTL_QUEUE_UPDATE:
Craig Tiller3ff1fa62017-09-14 11:07:48 -07002439 grpc_chttp2_mark_stream_writable(exec_ctx, t, s);
ncteisen020dbf22017-07-14 15:42:54 -07002440 break;
2441 }
2442 switch (action.send_transport_update) {
2443 case GRPC_CHTTP2_FLOWCTL_NO_ACTION_NEEDED:
2444 break;
2445 case GRPC_CHTTP2_FLOWCTL_UPDATE_IMMEDIATELY:
Craig Tiller3ff1fa62017-09-14 11:07:48 -07002446 grpc_chttp2_initiate_write(
2447 exec_ctx, t, GRPC_CHTTP2_INITIATE_WRITE_TRANSPORT_FLOW_CONTROL);
ncteisen020dbf22017-07-14 15:42:54 -07002448 break;
2449 // this is the same as no action b/c every time the transport enters the
2450 // writing path it will maybe do an update
2451 case GRPC_CHTTP2_FLOWCTL_QUEUE_UPDATE:
2452 break;
2453 }
ncteisen41ba2682017-07-14 16:15:10 -07002454 if (action.send_setting_update != GRPC_CHTTP2_FLOWCTL_NO_ACTION_NEEDED) {
2455 if (action.initial_window_size > 0) {
2456 queue_setting_update(exec_ctx, t,
2457 GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE,
2458 (uint32_t)action.initial_window_size);
2459 }
2460 if (action.max_frame_size > 0) {
2461 queue_setting_update(exec_ctx, t, GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE,
2462 (uint32_t)action.max_frame_size);
2463 }
2464 if (action.send_setting_update == GRPC_CHTTP2_FLOWCTL_UPDATE_IMMEDIATELY) {
Craig Tiller3ff1fa62017-09-14 11:07:48 -07002465 grpc_chttp2_initiate_write(exec_ctx, t,
2466 GRPC_CHTTP2_INITIATE_WRITE_SEND_SETTINGS);
ncteisen41ba2682017-07-14 16:15:10 -07002467 }
Craig Tiller8b34eca2016-10-20 21:13:31 -07002468 }
ncteisen41ba2682017-07-14 16:15:10 -07002469 if (action.need_ping) {
2470 GRPC_CHTTP2_REF_TRANSPORT(t, "bdp_ping");
2471 grpc_bdp_estimator_schedule_ping(&t->flow_control.bdp_estimator);
2472 send_ping_locked(exec_ctx, t,
2473 GRPC_CHTTP2_PING_BEFORE_TRANSPORT_WINDOW_UPDATE,
Craig Tiller3ff1fa62017-09-14 11:07:48 -07002474 &t->start_bdp_ping_locked, &t->finish_bdp_ping_locked,
2475 GRPC_CHTTP2_INITIATE_WRITE_BDP_ESTIMATOR_PING);
Craig Tillere2894b42017-02-15 08:12:55 -08002476 }
Craig Tiller8b34eca2016-10-20 21:13:31 -07002477}
2478
Craig Tiller34b11df2016-06-09 17:17:15 -07002479static grpc_error *try_http_parsing(grpc_exec_ctx *exec_ctx,
2480 grpc_chttp2_transport *t) {
Yuchen Zenga9d8c552016-06-02 16:11:28 -07002481 grpc_http_parser parser;
2482 size_t i = 0;
Craig Tiller34b11df2016-06-09 17:17:15 -07002483 grpc_error *error = GRPC_ERROR_NONE;
2484 grpc_http_response response;
2485 memset(&response, 0, sizeof(response));
Yuchen Zenga9d8c552016-06-02 16:11:28 -07002486
Craig Tiller34b11df2016-06-09 17:17:15 -07002487 grpc_http_parser_init(&parser, GRPC_HTTP_RESPONSE, &response);
Yuchen Zenga9d8c552016-06-02 16:11:28 -07002488
Craig Tiller34b11df2016-06-09 17:17:15 -07002489 grpc_error *parse_error = GRPC_ERROR_NONE;
2490 for (; i < t->read_buffer.count && parse_error == GRPC_ERROR_NONE; i++) {
Mark D. Roth0a05ab62016-08-04 13:10:13 -07002491 parse_error =
2492 grpc_http_parser_parse(&parser, t->read_buffer.slices[i], NULL);
Yuchen Zenga9d8c552016-06-02 16:11:28 -07002493 }
Craig Tiller34b11df2016-06-09 17:17:15 -07002494 if (parse_error == GRPC_ERROR_NONE &&
2495 (parse_error = grpc_http_parser_eof(&parser)) == GRPC_ERROR_NONE) {
2496 error = grpc_error_set_int(
ncteisen4b36a3d2017-03-13 19:08:06 -07002497 grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
2498 "Trying to connect an http1.x server"),
2499 GRPC_ERROR_INT_HTTP_STATUS, response.status),
Craig Tiller7c70b6c2017-01-23 07:48:42 -08002500 GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
Craig Tiller34b11df2016-06-09 17:17:15 -07002501 }
2502 GRPC_ERROR_UNREF(parse_error);
Yuchen Zenga9d8c552016-06-02 16:11:28 -07002503
2504 grpc_http_parser_destroy(&parser);
Craig Tiller34b11df2016-06-09 17:17:15 -07002505 grpc_http_response_destroy(&response);
2506 return error;
Yuchen Zenga9d8c552016-06-02 16:11:28 -07002507}
2508
Craig Tiller4e5b4522016-08-26 16:31:34 -07002509static void read_action_locked(grpc_exec_ctx *exec_ctx, void *tp,
2510 grpc_error *error) {
Craig Tiller67eb59e2016-08-16 11:40:54 -07002511 GPR_TIMER_BEGIN("reading_action_locked", 0);
Craig Tiller4b074d52015-06-23 07:48:21 -07002512
Yash Tibrewal7cdd99c2017-09-08 16:04:12 -07002513 grpc_chttp2_transport *t = (grpc_chttp2_transport *)tp;
Craig Tiller67eb59e2016-08-16 11:40:54 -07002514
2515 GRPC_ERROR_REF(error);
2516
Craig Tiller936f1ea2016-10-14 15:15:19 -07002517 grpc_error *err = error;
2518 if (err != GRPC_ERROR_NONE) {
ncteisen4b36a3d2017-03-13 19:08:06 -07002519 err = grpc_error_set_int(GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
2520 "Endpoint read failed", &err, 1),
2521 GRPC_ERROR_INT_OCCURRED_DURING_WRITE,
2522 t->write_state);
Craig Tiller936f1ea2016-10-14 15:15:19 -07002523 }
2524 GPR_SWAP(grpc_error *, err, error);
2525 GRPC_ERROR_UNREF(err);
Craig Tiller67eb59e2016-08-16 11:40:54 -07002526 if (!t->closed) {
Craig Tiller67eb59e2016-08-16 11:40:54 -07002527 GPR_TIMER_BEGIN("reading_action.parse", 0);
2528 size_t i = 0;
2529 grpc_error *errors[3] = {GRPC_ERROR_REF(error), GRPC_ERROR_NONE,
2530 GRPC_ERROR_NONE};
2531 for (; i < t->read_buffer.count && errors[1] == GRPC_ERROR_NONE; i++) {
ncteisen41ba2682017-07-14 16:15:10 -07002532 grpc_bdp_estimator_add_incoming_bytes(
2533 &t->flow_control.bdp_estimator,
2534 (int64_t)GRPC_SLICE_LENGTH(t->read_buffer.slices[i]));
Craig Tiller3d7c6092016-08-26 11:39:05 -07002535 errors[1] =
2536 grpc_chttp2_perform_read(exec_ctx, t, t->read_buffer.slices[i]);
Craig Tillerf7970dd2016-10-20 16:49:13 -07002537 }
Craig Tiller67eb59e2016-08-16 11:40:54 -07002538 if (errors[1] != GRPC_ERROR_NONE) {
2539 errors[2] = try_http_parsing(exec_ctx, t);
2540 GRPC_ERROR_UNREF(error);
ncteisen4b36a3d2017-03-13 19:08:06 -07002541 error = GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
2542 "Failed parsing HTTP/2", errors, GPR_ARRAY_SIZE(errors));
Craig Tiller67eb59e2016-08-16 11:40:54 -07002543 }
2544 for (i = 0; i < GPR_ARRAY_SIZE(errors); i++) {
2545 GRPC_ERROR_UNREF(errors[i]);
2546 }
2547 GPR_TIMER_END("reading_action.parse", 0);
2548
2549 GPR_TIMER_BEGIN("post_parse_locked", 0);
ncteisen3c909d52017-07-13 19:45:51 -07002550 if (t->flow_control.initial_window_update != 0) {
2551 if (t->flow_control.initial_window_update > 0) {
Craig Tiller1f675992016-10-19 14:43:06 -07002552 grpc_chttp2_stream *s;
2553 while (grpc_chttp2_list_pop_stalled_by_stream(t, &s)) {
Craig Tiller3ff1fa62017-09-14 11:07:48 -07002554 grpc_chttp2_mark_stream_writable(exec_ctx, t, s);
2555 grpc_chttp2_initiate_write(
2556 exec_ctx, t,
2557 GRPC_CHTTP2_INITIATE_WRITE_FLOW_CONTROL_UNSTALLED_BY_SETTING);
Craig Tiller1f675992016-10-19 14:43:06 -07002558 }
2559 }
ncteisen3c909d52017-07-13 19:45:51 -07002560 t->flow_control.initial_window_update = 0;
Craig Tiller67eb59e2016-08-16 11:40:54 -07002561 }
Craig Tiller67eb59e2016-08-16 11:40:54 -07002562 GPR_TIMER_END("post_parse_locked", 0);
Craig Tillerd76eb8a2016-03-22 08:49:28 -07002563 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08002564
Craig Tillerc69d27b2016-07-14 13:20:22 -07002565 GPR_TIMER_BEGIN("post_reading_action_locked", 0);
Craig Tiller45b135e2016-03-22 16:02:39 -07002566 bool keep_reading = false;
Craig Tiller804ff712016-05-05 16:25:40 -07002567 if (error == GRPC_ERROR_NONE && t->closed) {
ncteisen4b36a3d2017-03-13 19:08:06 -07002568 error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Transport closed");
Craig Tiller804ff712016-05-05 16:25:40 -07002569 }
2570 if (error != GRPC_ERROR_NONE) {
Craig Tiller936f1ea2016-10-14 15:15:19 -07002571 close_transport_locked(exec_ctx, t, GRPC_ERROR_REF(error));
Craig Tiller45b135e2016-03-22 16:02:39 -07002572 t->endpoint_reading = 0;
Craig Tillera82950e2015-09-22 12:33:20 -07002573 } else if (!t->closed) {
Craig Tiller45b135e2016-03-22 16:02:39 -07002574 keep_reading = true;
Craig Tillerdfd3a8f2016-08-24 09:43:45 -07002575 GRPC_CHTTP2_REF_TRANSPORT(t, "keep_reading");
Craig Tillera82950e2015-09-22 12:33:20 -07002576 }
Craig Tillera59c16c2016-10-31 07:25:01 -07002577 grpc_slice_buffer_reset_and_unref_internal(exec_ctx, &t->read_buffer);
Craig Tillerb0298592015-08-27 07:38:01 -07002578
Craig Tillera82950e2015-09-22 12:33:20 -07002579 if (keep_reading) {
Craig Tiller91031da2016-12-28 15:44:25 -08002580 grpc_endpoint_read(exec_ctx, t->ep, &t->read_buffer,
2581 &t->read_action_locked);
ncteisen41ba2682017-07-14 16:15:10 -07002582 grpc_chttp2_act_on_flowctl_action(
2583 exec_ctx, grpc_chttp2_flowctl_get_bdp_action(&t->flow_control), t,
2584 NULL);
Craig Tillerdfd3a8f2016-08-24 09:43:45 -07002585 GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "keep_reading");
Craig Tillera82950e2015-09-22 12:33:20 -07002586 } else {
Craig Tillerdfd3a8f2016-08-24 09:43:45 -07002587 GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "reading_action");
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08002588 }
Craig Tillerc69d27b2016-07-14 13:20:22 -07002589
2590 GPR_TIMER_END("post_reading_action_locked", 0);
Craig Tiller67eb59e2016-08-16 11:40:54 -07002591
2592 GRPC_ERROR_UNREF(error);
2593
2594 GPR_TIMER_END("reading_action_locked", 0);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08002595}
2596
Craig Tiller91f77ea2016-12-29 16:59:43 -08002597static void start_bdp_ping_locked(grpc_exec_ctx *exec_ctx, void *tp,
2598 grpc_error *error) {
Yash Tibrewal7cdd99c2017-09-08 16:04:12 -07002599 grpc_chttp2_transport *t = (grpc_chttp2_transport *)tp;
Craig Tiller84f75d42017-05-03 13:06:35 -07002600 if (GRPC_TRACER_ON(grpc_http_trace)) {
Craig Tillerc5235d72017-01-20 14:12:30 -08002601 gpr_log(GPR_DEBUG, "%s: Start BDP ping", t->peer_string);
2602 }
Yuchen Zeng5272dfc2017-02-27 20:39:35 -08002603 /* Reset the keepalive ping timer */
2604 if (t->keepalive_state == GRPC_CHTTP2_KEEPALIVE_STATE_WAITING) {
2605 grpc_timer_cancel(exec_ctx, &t->keepalive_ping_timer);
2606 }
ncteisen41ba2682017-07-14 16:15:10 -07002607 grpc_bdp_estimator_start_ping(&t->flow_control.bdp_estimator);
Craig Tiller91f77ea2016-12-29 16:59:43 -08002608}
2609
Craig Tillerf7970dd2016-10-20 16:49:13 -07002610static void finish_bdp_ping_locked(grpc_exec_ctx *exec_ctx, void *tp,
2611 grpc_error *error) {
Yash Tibrewal7cdd99c2017-09-08 16:04:12 -07002612 grpc_chttp2_transport *t = (grpc_chttp2_transport *)tp;
Craig Tiller84f75d42017-05-03 13:06:35 -07002613 if (GRPC_TRACER_ON(grpc_http_trace)) {
Craig Tillerc5235d72017-01-20 14:12:30 -08002614 gpr_log(GPR_DEBUG, "%s: Complete BDP ping", t->peer_string);
2615 }
ncteisen41ba2682017-07-14 16:15:10 -07002616 grpc_bdp_estimator_complete_ping(&t->flow_control.bdp_estimator);
Craig Tillerf7970dd2016-10-20 16:49:13 -07002617
Craig Tillerf7970dd2016-10-20 16:49:13 -07002618 GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "bdp_ping");
2619}
2620
Yuchen Zeng5f899962017-03-29 17:55:28 -07002621void grpc_chttp2_config_default_keepalive_args(grpc_channel_args *args,
2622 bool is_client) {
Yuchen Zeng3d43da72017-03-27 11:33:21 -07002623 size_t i;
2624 if (args) {
2625 for (i = 0; i < args->num_args; i++) {
Yuchen Zeng5f899962017-03-29 17:55:28 -07002626 if (0 == strcmp(args->args[i].key, GRPC_ARG_KEEPALIVE_TIME_MS)) {
2627 const int value = grpc_channel_arg_get_integer(
Yuchen Zeng3d43da72017-03-27 11:33:21 -07002628 &args->args[i],
Yuchen Zengc18d4b32017-03-29 15:04:42 -07002629 (grpc_integer_options){g_default_client_keepalive_time_ms, 1,
Yuchen Zeng44264d52017-03-27 16:32:15 -07002630 INT_MAX});
Yuchen Zeng5f899962017-03-29 17:55:28 -07002631 if (is_client) {
2632 g_default_client_keepalive_time_ms = value;
2633 } else {
2634 g_default_server_keepalive_time_ms = value;
2635 }
2636 } else if (0 ==
2637 strcmp(args->args[i].key, GRPC_ARG_KEEPALIVE_TIMEOUT_MS)) {
2638 const int value = grpc_channel_arg_get_integer(
Yuchen Zengc18d4b32017-03-29 15:04:42 -07002639 &args->args[i],
2640 (grpc_integer_options){g_default_client_keepalive_timeout_ms, 0,
Yuchen Zeng3d43da72017-03-27 11:33:21 -07002641 INT_MAX});
Yuchen Zeng5f899962017-03-29 17:55:28 -07002642 if (is_client) {
2643 g_default_client_keepalive_timeout_ms = value;
2644 } else {
2645 g_default_server_keepalive_timeout_ms = value;
2646 }
Yuchen Zeng3d43da72017-03-27 11:33:21 -07002647 } else if (0 == strcmp(args->args[i].key,
2648 GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS)) {
2649 g_default_keepalive_permit_without_calls =
2650 (uint32_t)grpc_channel_arg_get_integer(
2651 &args->args[i],
2652 (grpc_integer_options){g_default_keepalive_permit_without_calls,
2653 0, 1});
Yuchen Zengd7eda612017-06-29 18:55:45 -07002654 } else if (0 ==
2655 strcmp(args->args[i].key, GRPC_ARG_HTTP2_MAX_PING_STRIKES)) {
2656 g_default_max_ping_strikes = grpc_channel_arg_get_integer(
2657 &args->args[i],
2658 (grpc_integer_options){g_default_max_ping_strikes, 0, INT_MAX});
2659 } else if (0 == strcmp(args->args[i].key,
2660 GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA)) {
2661 g_default_max_pings_without_data = grpc_channel_arg_get_integer(
2662 &args->args[i], (grpc_integer_options){
2663 g_default_max_pings_without_data, 0, INT_MAX});
2664 } else if (0 ==
2665 strcmp(
2666 args->args[i].key,
2667 GRPC_ARG_HTTP2_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS)) {
2668 g_default_min_sent_ping_interval_without_data_ms =
2669 grpc_channel_arg_get_integer(
2670 &args->args[i],
2671 (grpc_integer_options){
2672 g_default_min_sent_ping_interval_without_data_ms, 0,
2673 INT_MAX});
2674 } else if (0 ==
2675 strcmp(
2676 args->args[i].key,
2677 GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS)) {
2678 g_default_min_recv_ping_interval_without_data_ms =
2679 grpc_channel_arg_get_integer(
2680 &args->args[i],
2681 (grpc_integer_options){
2682 g_default_min_recv_ping_interval_without_data_ms, 0,
2683 INT_MAX});
Yuchen Zeng3d43da72017-03-27 11:33:21 -07002684 }
2685 }
2686 }
2687}
2688
Yuchen Zengefdf5a32017-02-26 23:29:54 -08002689static void init_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg,
2690 grpc_error *error) {
Yash Tibrewal7cdd99c2017-09-08 16:04:12 -07002691 grpc_chttp2_transport *t = (grpc_chttp2_transport *)arg;
Yuchen Zengefdf5a32017-02-26 23:29:54 -08002692 GPR_ASSERT(t->keepalive_state == GRPC_CHTTP2_KEEPALIVE_STATE_WAITING);
Yuchen Zengaaa779e2017-04-12 18:06:36 -07002693 if (t->destroying || t->closed) {
2694 t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_DYING;
2695 } else if (error == GRPC_ERROR_NONE) {
Yuchen Zeng0937fc12017-02-27 23:19:00 -08002696 if (t->keepalive_permit_without_calls ||
2697 grpc_chttp2_stream_map_size(&t->stream_map) > 0) {
Yuchen Zengefdf5a32017-02-26 23:29:54 -08002698 t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_PINGING;
2699 GRPC_CHTTP2_REF_TRANSPORT(t, "keepalive ping end");
2700 send_ping_locked(exec_ctx, t, GRPC_CHTTP2_PING_ON_NEXT_WRITE,
2701 &t->start_keepalive_ping_locked,
Craig Tiller3ff1fa62017-09-14 11:07:48 -07002702 &t->finish_keepalive_ping_locked,
2703 GRPC_CHTTP2_INITIATE_WRITE_KEEPALIVE_PING);
Yuchen Zengefdf5a32017-02-26 23:29:54 -08002704 } else {
2705 GRPC_CHTTP2_REF_TRANSPORT(t, "init keepalive ping");
2706 grpc_timer_init(
2707 exec_ctx, &t->keepalive_ping_timer,
2708 gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), t->keepalive_time),
Yuchen Zeng380a3be2017-02-26 23:37:50 -08002709 &t->init_keepalive_ping_locked, gpr_now(GPR_CLOCK_MONOTONIC));
Yuchen Zengefdf5a32017-02-26 23:29:54 -08002710 }
Yuchen Zengaaa779e2017-04-12 18:06:36 -07002711 } else if (error == GRPC_ERROR_CANCELLED) {
Yuchen Zeng5272dfc2017-02-27 20:39:35 -08002712 /* The keepalive ping timer may be cancelled by bdp */
2713 GRPC_CHTTP2_REF_TRANSPORT(t, "init keepalive ping");
2714 grpc_timer_init(
2715 exec_ctx, &t->keepalive_ping_timer,
2716 gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), t->keepalive_time),
2717 &t->init_keepalive_ping_locked, gpr_now(GPR_CLOCK_MONOTONIC));
Yuchen Zengefdf5a32017-02-26 23:29:54 -08002718 }
2719 GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "init keepalive ping");
2720}
2721
2722static void start_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg,
2723 grpc_error *error) {
Yash Tibrewal7cdd99c2017-09-08 16:04:12 -07002724 grpc_chttp2_transport *t = (grpc_chttp2_transport *)arg;
Yuchen Zengefdf5a32017-02-26 23:29:54 -08002725 GRPC_CHTTP2_REF_TRANSPORT(t, "keepalive watchdog");
2726 grpc_timer_init(
2727 exec_ctx, &t->keepalive_watchdog_timer,
2728 gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), t->keepalive_timeout),
Yuchen Zeng380a3be2017-02-26 23:37:50 -08002729 &t->keepalive_watchdog_fired_locked, gpr_now(GPR_CLOCK_MONOTONIC));
Yuchen Zengefdf5a32017-02-26 23:29:54 -08002730}
2731
2732static void finish_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg,
2733 grpc_error *error) {
Yash Tibrewal7cdd99c2017-09-08 16:04:12 -07002734 grpc_chttp2_transport *t = (grpc_chttp2_transport *)arg;
Yuchen Zengefdf5a32017-02-26 23:29:54 -08002735 if (t->keepalive_state == GRPC_CHTTP2_KEEPALIVE_STATE_PINGING) {
2736 if (error == GRPC_ERROR_NONE) {
2737 t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_WAITING;
2738 grpc_timer_cancel(exec_ctx, &t->keepalive_watchdog_timer);
2739 GRPC_CHTTP2_REF_TRANSPORT(t, "init keepalive ping");
2740 grpc_timer_init(
2741 exec_ctx, &t->keepalive_ping_timer,
2742 gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), t->keepalive_time),
Yuchen Zengb4b6a0e2017-02-28 22:06:52 -08002743 &t->init_keepalive_ping_locked, gpr_now(GPR_CLOCK_MONOTONIC));
Yuchen Zengefdf5a32017-02-26 23:29:54 -08002744 }
2745 }
2746 GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "keepalive ping end");
2747}
2748
2749static void keepalive_watchdog_fired_locked(grpc_exec_ctx *exec_ctx, void *arg,
2750 grpc_error *error) {
Yash Tibrewal7cdd99c2017-09-08 16:04:12 -07002751 grpc_chttp2_transport *t = (grpc_chttp2_transport *)arg;
Yuchen Zengefdf5a32017-02-26 23:29:54 -08002752 if (t->keepalive_state == GRPC_CHTTP2_KEEPALIVE_STATE_PINGING) {
2753 if (error == GRPC_ERROR_NONE) {
2754 t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_DYING;
ncteisen4b36a3d2017-03-13 19:08:06 -07002755 close_transport_locked(exec_ctx, t, GRPC_ERROR_CREATE_FROM_STATIC_STRING(
2756 "keepalive watchdog timeout"));
Yuchen Zengefdf5a32017-02-26 23:29:54 -08002757 }
2758 } else {
Yuchen Zeng5272dfc2017-02-27 20:39:35 -08002759 /* The watchdog timer should have been cancelled by
2760 * finish_keepalive_ping_locked. */
Yuchen Zengefdf5a32017-02-26 23:29:54 -08002761 if (error != GRPC_ERROR_CANCELLED) {
2762 gpr_log(GPR_ERROR, "keepalive_ping_end state error: %d (expect: %d)",
2763 t->keepalive_state, GRPC_CHTTP2_KEEPALIVE_STATE_PINGING);
2764 }
2765 }
2766 GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "keepalive watchdog");
2767}
2768
Craig Tiller0cb803d2016-03-02 22:17:24 -08002769/*******************************************************************************
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08002770 * CALLBACK LOOP
2771 */
2772
Craig Tiller3d7c6092016-08-26 11:39:05 -07002773static void connectivity_state_set(grpc_exec_ctx *exec_ctx,
2774 grpc_chttp2_transport *t,
2775 grpc_connectivity_state state,
2776 grpc_error *error, const char *reason) {
Craig Tillera82950e2015-09-22 12:33:20 -07002777 GRPC_CHTTP2_IF_TRACING(
2778 gpr_log(GPR_DEBUG, "set connectivity_state=%d", state));
Craig Tiller3d7c6092016-08-26 11:39:05 -07002779 grpc_connectivity_state_set(exec_ctx, &t->channel_callback.state_tracker,
2780 state, error, reason);
Craig Tiller1766a912015-06-22 16:43:43 -07002781}
2782
Craig Tiller0cb803d2016-03-02 22:17:24 -08002783/*******************************************************************************
Craig Tillerc079c112015-04-22 15:23:39 -07002784 * POLLSET STUFF
2785 */
2786
Craig Tiller9d35a1f2015-11-02 14:16:12 -08002787static void set_pollset(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
2788 grpc_stream *gs, grpc_pollset *pollset) {
Craig Tiller93023e42016-07-11 12:43:23 -07002789 grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
2790 grpc_endpoint_add_to_pollset(exec_ctx, t->ep, pollset);
Craig Tiller9d35a1f2015-11-02 14:16:12 -08002791}
2792
David Garcia Quintas4afce7e2016-04-18 16:25:17 -07002793static void set_pollset_set(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
2794 grpc_stream *gs, grpc_pollset_set *pollset_set) {
Craig Tiller93023e42016-07-11 12:43:23 -07002795 grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
2796 grpc_endpoint_add_to_pollset_set(exec_ctx, t->ep, pollset_set);
David Garcia Quintas4afce7e2016-04-18 16:25:17 -07002797}
2798
Craig Tiller0cb803d2016-03-02 22:17:24 -08002799/*******************************************************************************
Craig Tiller9d35a1f2015-11-02 14:16:12 -08002800 * BYTE STREAM
2801 */
2802
Muxi Yan29723ee2017-04-12 20:24:42 -07002803static void reset_byte_stream(grpc_exec_ctx *exec_ctx, void *arg,
2804 grpc_error *error) {
2805 grpc_chttp2_stream *s = (grpc_chttp2_stream *)arg;
2806
2807 s->pending_byte_stream = false;
2808 if (error == GRPC_ERROR_NONE) {
2809 grpc_chttp2_maybe_complete_recv_message(exec_ctx, s->t, s);
2810 grpc_chttp2_maybe_complete_recv_trailing_metadata(exec_ctx, s->t, s);
2811 } else {
2812 GPR_ASSERT(error != GRPC_ERROR_NONE);
ncteisen274bbbe2017-06-08 14:57:11 -07002813 GRPC_CLOSURE_SCHED(exec_ctx, s->on_next, GRPC_ERROR_REF(error));
Muxi Yan29723ee2017-04-12 20:24:42 -07002814 s->on_next = NULL;
2815 GRPC_ERROR_UNREF(s->byte_stream_error);
2816 s->byte_stream_error = GRPC_ERROR_NONE;
2817 grpc_chttp2_cancel_stream(exec_ctx, s->t, s, GRPC_ERROR_REF(error));
2818 s->byte_stream_error = error;
2819 }
2820}
2821
Craig Tillera93e5a42016-04-26 21:47:49 -07002822static void incoming_byte_stream_unref(grpc_exec_ctx *exec_ctx,
2823 grpc_chttp2_incoming_byte_stream *bs) {
2824 if (gpr_unref(&bs->refs)) {
Craig Tillera93e5a42016-04-26 21:47:49 -07002825 gpr_free(bs);
2826 }
2827}
2828
Craig Tiller45b135e2016-03-22 16:02:39 -07002829static void incoming_byte_stream_next_locked(grpc_exec_ctx *exec_ctx,
Craig Tiller93023e42016-07-11 12:43:23 -07002830 void *argp,
2831 grpc_error *error_ignored) {
Yash Tibrewal7cdd99c2017-09-08 16:04:12 -07002832 grpc_chttp2_incoming_byte_stream *bs =
2833 (grpc_chttp2_incoming_byte_stream *)argp;
Craig Tiller3d7c6092016-08-26 11:39:05 -07002834 grpc_chttp2_transport *t = bs->transport;
2835 grpc_chttp2_stream *s = bs->stream;
Craig Tiller45b135e2016-03-22 16:02:39 -07002836
Muxi Yan29723ee2017-04-12 20:24:42 -07002837 size_t cur_length = s->frame_storage.length;
ncteisen3c909d52017-07-13 19:45:51 -07002838 if (!s->read_closed) {
ncteisen00f74a92017-07-14 15:41:05 -07002839 grpc_chttp2_flowctl_incoming_bs_update(&t->flow_control, &s->flow_control,
2840 bs->next_action.max_size_hint,
2841 cur_length);
ncteisen020dbf22017-07-14 15:42:54 -07002842 grpc_chttp2_act_on_flowctl_action(
ncteisen00f74a92017-07-14 15:41:05 -07002843 exec_ctx,
2844 grpc_chttp2_flowctl_get_action(&t->flow_control, &s->flow_control), t,
2845 s);
ncteisen3c909d52017-07-13 19:45:51 -07002846 }
Muxi Yan29723ee2017-04-12 20:24:42 -07002847 GPR_ASSERT(s->unprocessed_incoming_frames_buffer.length == 0);
2848 if (s->frame_storage.length > 0) {
2849 grpc_slice_buffer_swap(&s->frame_storage,
2850 &s->unprocessed_incoming_frames_buffer);
Muxi Yan68198b52017-07-12 11:43:23 -07002851 s->unprocessed_incoming_frames_decompressed = false;
ncteisen274bbbe2017-06-08 14:57:11 -07002852 GRPC_CLOSURE_SCHED(exec_ctx, bs->next_action.on_complete, GRPC_ERROR_NONE);
Muxi Yan29723ee2017-04-12 20:24:42 -07002853 } else if (s->byte_stream_error != GRPC_ERROR_NONE) {
ncteisen274bbbe2017-06-08 14:57:11 -07002854 GRPC_CLOSURE_SCHED(exec_ctx, bs->next_action.on_complete,
Muxi Yan29723ee2017-04-12 20:24:42 -07002855 GRPC_ERROR_REF(s->byte_stream_error));
2856 if (s->data_parser.parsing_frame != NULL) {
2857 incoming_byte_stream_unref(exec_ctx, s->data_parser.parsing_frame);
2858 s->data_parser.parsing_frame = NULL;
2859 }
2860 } else if (s->read_closed) {
2861 if (bs->remaining_bytes != 0) {
2862 s->byte_stream_error =
2863 GRPC_ERROR_CREATE_FROM_STATIC_STRING("Truncated message");
ncteisen274bbbe2017-06-08 14:57:11 -07002864 GRPC_CLOSURE_SCHED(exec_ctx, bs->next_action.on_complete,
Muxi Yan29723ee2017-04-12 20:24:42 -07002865 GRPC_ERROR_REF(s->byte_stream_error));
2866 if (s->data_parser.parsing_frame != NULL) {
2867 incoming_byte_stream_unref(exec_ctx, s->data_parser.parsing_frame);
2868 s->data_parser.parsing_frame = NULL;
2869 }
2870 } else {
2871 /* Should never reach here. */
2872 GPR_ASSERT(false);
2873 }
Craig Tillerc71e6a62017-04-12 15:49:39 -07002874 } else {
Muxi Yan29723ee2017-04-12 20:24:42 -07002875 s->on_next = bs->next_action.on_complete;
Craig Tillerc71e6a62017-04-12 15:49:39 -07002876 }
Craig Tillera93e5a42016-04-26 21:47:49 -07002877 incoming_byte_stream_unref(exec_ctx, bs);
Craig Tiller45b135e2016-03-22 16:02:39 -07002878}
2879
Muxi Yan29723ee2017-04-12 20:24:42 -07002880static bool incoming_byte_stream_next(grpc_exec_ctx *exec_ctx,
2881 grpc_byte_stream *byte_stream,
2882 size_t max_size_hint,
2883 grpc_closure *on_complete) {
Craig Tillerc69d27b2016-07-14 13:20:22 -07002884 GPR_TIMER_BEGIN("incoming_byte_stream_next", 0);
Craig Tiller9d35a1f2015-11-02 14:16:12 -08002885 grpc_chttp2_incoming_byte_stream *bs =
2886 (grpc_chttp2_incoming_byte_stream *)byte_stream;
Muxi Yan29723ee2017-04-12 20:24:42 -07002887 grpc_chttp2_stream *s = bs->stream;
2888 if (s->unprocessed_incoming_frames_buffer.length > 0) {
Muxi Yan93b11202017-04-19 11:05:57 -07002889 GPR_TIMER_END("incoming_byte_stream_next", 0);
Muxi Yan29723ee2017-04-12 20:24:42 -07002890 return true;
2891 } else {
2892 gpr_ref(&bs->refs);
2893 bs->next_action.max_size_hint = max_size_hint;
2894 bs->next_action.on_complete = on_complete;
ncteisen274bbbe2017-06-08 14:57:11 -07002895 GRPC_CLOSURE_SCHED(
Muxi Yan29723ee2017-04-12 20:24:42 -07002896 exec_ctx,
ncteisen274bbbe2017-06-08 14:57:11 -07002897 GRPC_CLOSURE_INIT(&bs->next_action.closure,
Craig Tilleree4b1452017-05-12 10:56:03 -07002898 incoming_byte_stream_next_locked, bs,
2899 grpc_combiner_scheduler(bs->transport->combiner)),
Muxi Yan29723ee2017-04-12 20:24:42 -07002900 GRPC_ERROR_NONE);
2901 GPR_TIMER_END("incoming_byte_stream_next", 0);
2902 return false;
2903 }
2904}
2905
2906static grpc_error *incoming_byte_stream_pull(grpc_exec_ctx *exec_ctx,
2907 grpc_byte_stream *byte_stream,
2908 grpc_slice *slice) {
2909 GPR_TIMER_BEGIN("incoming_byte_stream_pull", 0);
2910 grpc_chttp2_incoming_byte_stream *bs =
2911 (grpc_chttp2_incoming_byte_stream *)byte_stream;
2912 grpc_chttp2_stream *s = bs->stream;
Muxi Yan68198b52017-07-12 11:43:23 -07002913 grpc_error *error;
Muxi Yan29723ee2017-04-12 20:24:42 -07002914
2915 if (s->unprocessed_incoming_frames_buffer.length > 0) {
Muxi Yan68198b52017-07-12 11:43:23 -07002916 if (s->stream_compression_recv_enabled &&
2917 !s->unprocessed_incoming_frames_decompressed) {
2918 bool end_of_context;
2919 if (!s->stream_decompression_ctx) {
2920 s->stream_decompression_ctx = grpc_stream_compression_context_create(
2921 GRPC_STREAM_COMPRESSION_DECOMPRESS);
2922 }
2923 if (!grpc_stream_decompress(s->stream_decompression_ctx,
2924 &s->unprocessed_incoming_frames_buffer,
Muxi Yan9469ac42017-07-21 12:50:35 -07002925 s->decompressed_data_buffer, NULL, MAX_SIZE_T,
2926 &end_of_context)) {
Muxi Yan68198b52017-07-12 11:43:23 -07002927 error =
2928 GRPC_ERROR_CREATE_FROM_STATIC_STRING("Stream decompression error.");
2929 return error;
2930 }
2931 GPR_ASSERT(s->unprocessed_incoming_frames_buffer.length == 0);
2932 grpc_slice_buffer_swap(&s->unprocessed_incoming_frames_buffer,
Muxi Yan9469ac42017-07-21 12:50:35 -07002933 s->decompressed_data_buffer);
Muxi Yan68198b52017-07-12 11:43:23 -07002934 s->unprocessed_incoming_frames_decompressed = true;
2935 if (end_of_context) {
2936 grpc_stream_compression_context_destroy(s->stream_decompression_ctx);
2937 s->stream_decompression_ctx = NULL;
2938 }
Muxi Yan684a3972017-08-23 15:11:31 -07002939 if (s->unprocessed_incoming_frames_buffer.length == 0) {
2940 *slice = grpc_empty_slice();
2941 }
Muxi Yan68198b52017-07-12 11:43:23 -07002942 }
2943 error = grpc_deframe_unprocessed_incoming_frames(
Muxi Yan29723ee2017-04-12 20:24:42 -07002944 exec_ctx, &s->data_parser, s, &s->unprocessed_incoming_frames_buffer,
2945 slice, NULL);
2946 if (error != GRPC_ERROR_NONE) {
2947 return error;
2948 }
2949 } else {
Muxi Yan68198b52017-07-12 11:43:23 -07002950 error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Truncated message");
ncteisen274bbbe2017-06-08 14:57:11 -07002951 GRPC_CLOSURE_SCHED(exec_ctx, &s->reset_byte_stream, GRPC_ERROR_REF(error));
Muxi Yan29723ee2017-04-12 20:24:42 -07002952 return error;
2953 }
2954 GPR_TIMER_END("incoming_byte_stream_pull", 0);
2955 return GRPC_ERROR_NONE;
Craig Tiller9d35a1f2015-11-02 14:16:12 -08002956}
2957
Craig Tillera3b54cd2016-03-25 15:59:55 -07002958static void incoming_byte_stream_destroy_locked(grpc_exec_ctx *exec_ctx,
Craig Tiller93023e42016-07-11 12:43:23 -07002959 void *byte_stream,
Mark D. Roth57940612017-07-26 14:29:52 -07002960 grpc_error *error_ignored);
Craig Tillera3b54cd2016-03-25 15:59:55 -07002961
2962static void incoming_byte_stream_destroy(grpc_exec_ctx *exec_ctx,
Craig Tillera3f298f2015-12-16 19:42:09 -08002963 grpc_byte_stream *byte_stream) {
Craig Tillerc69d27b2016-07-14 13:20:22 -07002964 GPR_TIMER_BEGIN("incoming_byte_stream_destroy", 0);
Craig Tiller414217e2016-03-25 13:31:06 -07002965 grpc_chttp2_incoming_byte_stream *bs =
2966 (grpc_chttp2_incoming_byte_stream *)byte_stream;
ncteisen274bbbe2017-06-08 14:57:11 -07002967 GRPC_CLOSURE_SCHED(
2968 exec_ctx, GRPC_CLOSURE_INIT(
Craig Tilleree4b1452017-05-12 10:56:03 -07002969 &bs->destroy_action, incoming_byte_stream_destroy_locked,
2970 bs, grpc_combiner_scheduler(bs->transport->combiner)),
Craig Tiller91031da2016-12-28 15:44:25 -08002971 GRPC_ERROR_NONE);
Craig Tillerc69d27b2016-07-14 13:20:22 -07002972 GPR_TIMER_END("incoming_byte_stream_destroy", 0);
Craig Tiller9d35a1f2015-11-02 14:16:12 -08002973}
2974
Craig Tillera96f8cb2016-09-01 09:17:11 -07002975static void incoming_byte_stream_publish_error(
2976 grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_byte_stream *bs,
2977 grpc_error *error) {
Muxi Yan29723ee2017-04-12 20:24:42 -07002978 grpc_chttp2_stream *s = bs->stream;
2979
Craig Tillera96f8cb2016-09-01 09:17:11 -07002980 GPR_ASSERT(error != GRPC_ERROR_NONE);
ncteisen274bbbe2017-06-08 14:57:11 -07002981 GRPC_CLOSURE_SCHED(exec_ctx, s->on_next, GRPC_ERROR_REF(error));
Muxi Yan29723ee2017-04-12 20:24:42 -07002982 s->on_next = NULL;
2983 GRPC_ERROR_UNREF(s->byte_stream_error);
2984 s->byte_stream_error = GRPC_ERROR_REF(error);
Craig Tiller7c70b6c2017-01-23 07:48:42 -08002985 grpc_chttp2_cancel_stream(exec_ctx, bs->transport, bs->stream,
2986 GRPC_ERROR_REF(error));
Craig Tillera96f8cb2016-09-01 09:17:11 -07002987}
Craig Tiller45b135e2016-03-22 16:02:39 -07002988
Muxi Yan29723ee2017-04-12 20:24:42 -07002989grpc_error *grpc_chttp2_incoming_byte_stream_push(
2990 grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_byte_stream *bs,
2991 grpc_slice slice, grpc_slice *slice_out) {
2992 grpc_chttp2_stream *s = bs->stream;
2993
Craig Tiller618e67d2016-10-26 21:08:10 -07002994 if (bs->remaining_bytes < GRPC_SLICE_LENGTH(slice)) {
Muxi Yan29723ee2017-04-12 20:24:42 -07002995 grpc_error *error =
2996 GRPC_ERROR_CREATE_FROM_STATIC_STRING("Too many bytes in stream");
2997
ncteisen274bbbe2017-06-08 14:57:11 -07002998 GRPC_CLOSURE_SCHED(exec_ctx, &s->reset_byte_stream, GRPC_ERROR_REF(error));
Muxi Yan29723ee2017-04-12 20:24:42 -07002999 grpc_slice_unref_internal(exec_ctx, slice);
3000 return error;
Craig Tiller93023e42016-07-11 12:43:23 -07003001 } else {
Craig Tiller618e67d2016-10-26 21:08:10 -07003002 bs->remaining_bytes -= (uint32_t)GRPC_SLICE_LENGTH(slice);
Muxi Yan29723ee2017-04-12 20:24:42 -07003003 if (slice_out != NULL) {
3004 *slice_out = slice;
Craig Tillera96f8cb2016-09-01 09:17:11 -07003005 }
Muxi Yan29723ee2017-04-12 20:24:42 -07003006 return GRPC_ERROR_NONE;
Craig Tiller93023e42016-07-11 12:43:23 -07003007 }
Craig Tiller45b135e2016-03-22 16:02:39 -07003008}
3009
Muxi Yan29723ee2017-04-12 20:24:42 -07003010grpc_error *grpc_chttp2_incoming_byte_stream_finished(
Craig Tillera7cd41c2016-08-31 12:59:24 -07003011 grpc_exec_ctx *exec_ctx, grpc_chttp2_incoming_byte_stream *bs,
Muxi Yan29723ee2017-04-12 20:24:42 -07003012 grpc_error *error, bool reset_on_error) {
3013 grpc_chttp2_stream *s = bs->stream;
3014
Craig Tillera96f8cb2016-09-01 09:17:11 -07003015 if (error == GRPC_ERROR_NONE) {
Craig Tillera96f8cb2016-09-01 09:17:11 -07003016 if (bs->remaining_bytes != 0) {
ncteisen4b36a3d2017-03-13 19:08:06 -07003017 error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Truncated message");
Craig Tillera96f8cb2016-09-01 09:17:11 -07003018 }
Craig Tillera96f8cb2016-09-01 09:17:11 -07003019 }
Muxi Yan29723ee2017-04-12 20:24:42 -07003020 if (error != GRPC_ERROR_NONE && reset_on_error) {
ncteisen274bbbe2017-06-08 14:57:11 -07003021 GRPC_CLOSURE_SCHED(exec_ctx, &s->reset_byte_stream, GRPC_ERROR_REF(error));
Craig Tiller93023e42016-07-11 12:43:23 -07003022 }
Craig Tillera3b54cd2016-03-25 15:59:55 -07003023 incoming_byte_stream_unref(exec_ctx, bs);
Muxi Yan29723ee2017-04-12 20:24:42 -07003024 return error;
Craig Tiller9d35a1f2015-11-02 14:16:12 -08003025}
3026
Mark D. Roth57940612017-07-26 14:29:52 -07003027static void incoming_byte_stream_shutdown(grpc_exec_ctx *exec_ctx,
3028 grpc_byte_stream *byte_stream,
3029 grpc_error *error) {
3030 grpc_chttp2_incoming_byte_stream *bs =
3031 (grpc_chttp2_incoming_byte_stream *)byte_stream;
3032 GRPC_ERROR_UNREF(grpc_chttp2_incoming_byte_stream_finished(
3033 exec_ctx, bs, error, true /* reset_on_error */));
3034}
3035
3036static const grpc_byte_stream_vtable grpc_chttp2_incoming_byte_stream_vtable = {
3037 incoming_byte_stream_next, incoming_byte_stream_pull,
3038 incoming_byte_stream_shutdown, incoming_byte_stream_destroy};
3039
3040static void incoming_byte_stream_destroy_locked(grpc_exec_ctx *exec_ctx,
3041 void *byte_stream,
3042 grpc_error *error_ignored) {
Yash Tibrewal7cdd99c2017-09-08 16:04:12 -07003043 grpc_chttp2_incoming_byte_stream *bs =
3044 (grpc_chttp2_incoming_byte_stream *)byte_stream;
Mark D. Roth57940612017-07-26 14:29:52 -07003045 grpc_chttp2_stream *s = bs->stream;
3046 grpc_chttp2_transport *t = s->t;
3047
3048 GPR_ASSERT(bs->base.vtable == &grpc_chttp2_incoming_byte_stream_vtable);
3049 incoming_byte_stream_unref(exec_ctx, bs);
3050 s->pending_byte_stream = false;
3051 grpc_chttp2_maybe_complete_recv_message(exec_ctx, t, s);
3052 grpc_chttp2_maybe_complete_recv_trailing_metadata(exec_ctx, t, s);
3053}
3054
Craig Tiller9d35a1f2015-11-02 14:16:12 -08003055grpc_chttp2_incoming_byte_stream *grpc_chttp2_incoming_byte_stream_create(
Craig Tiller3d7c6092016-08-26 11:39:05 -07003056 grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s,
3057 uint32_t frame_size, uint32_t flags) {
Craig Tiller9d35a1f2015-11-02 14:16:12 -08003058 grpc_chttp2_incoming_byte_stream *incoming_byte_stream =
Craig Tiller3ad5c742017-09-14 11:29:30 -07003059 (grpc_chttp2_incoming_byte_stream *)gpr_malloc(
3060 sizeof(*incoming_byte_stream));
Craig Tiller9d35a1f2015-11-02 14:16:12 -08003061 incoming_byte_stream->base.length = frame_size;
Craig Tillera96f8cb2016-09-01 09:17:11 -07003062 incoming_byte_stream->remaining_bytes = frame_size;
Craig Tiller9d35a1f2015-11-02 14:16:12 -08003063 incoming_byte_stream->base.flags = flags;
Mark D. Roth57940612017-07-26 14:29:52 -07003064 incoming_byte_stream->base.vtable = &grpc_chttp2_incoming_byte_stream_vtable;
Craig Tiller9d35a1f2015-11-02 14:16:12 -08003065 gpr_ref_init(&incoming_byte_stream->refs, 2);
Craig Tiller3d7c6092016-08-26 11:39:05 -07003066 incoming_byte_stream->transport = t;
3067 incoming_byte_stream->stream = s;
yang-g0aeede32017-06-19 14:30:14 -07003068 GRPC_ERROR_UNREF(s->byte_stream_error);
Muxi Yan29723ee2017-04-12 20:24:42 -07003069 s->byte_stream_error = GRPC_ERROR_NONE;
Craig Tiller9d35a1f2015-11-02 14:16:12 -08003070 return incoming_byte_stream;
3071}
3072
Craig Tiller0cb803d2016-03-02 22:17:24 -08003073/*******************************************************************************
Craig Tiller6b5d6822016-10-25 16:13:26 -07003074 * RESOURCE QUOTAS
Craig Tiller25f29af2016-09-26 16:31:00 -07003075 */
3076
Craig Tiller795451f2016-09-27 08:47:28 -07003077static void post_benign_reclaimer(grpc_exec_ctx *exec_ctx,
3078 grpc_chttp2_transport *t) {
3079 if (!t->benign_reclaimer_registered) {
3080 t->benign_reclaimer_registered = true;
3081 GRPC_CHTTP2_REF_TRANSPORT(t, "benign_reclaimer");
Craig Tiller20afa3d2016-10-17 14:52:14 -07003082 grpc_resource_user_post_reclaimer(exec_ctx,
3083 grpc_endpoint_get_resource_user(t->ep),
Craig Tiller91031da2016-12-28 15:44:25 -08003084 false, &t->benign_reclaimer_locked);
Craig Tiller795451f2016-09-27 08:47:28 -07003085 }
3086}
3087
3088static void post_destructive_reclaimer(grpc_exec_ctx *exec_ctx,
3089 grpc_chttp2_transport *t) {
3090 if (!t->destructive_reclaimer_registered) {
3091 t->destructive_reclaimer_registered = true;
3092 GRPC_CHTTP2_REF_TRANSPORT(t, "destructive_reclaimer");
Craig Tiller20afa3d2016-10-17 14:52:14 -07003093 grpc_resource_user_post_reclaimer(exec_ctx,
3094 grpc_endpoint_get_resource_user(t->ep),
Craig Tiller91031da2016-12-28 15:44:25 -08003095 true, &t->destructive_reclaimer_locked);
Craig Tiller795451f2016-09-27 08:47:28 -07003096 }
3097}
3098
Craig Tiller25f29af2016-09-26 16:31:00 -07003099static void benign_reclaimer_locked(grpc_exec_ctx *exec_ctx, void *arg,
3100 grpc_error *error) {
Yash Tibrewal7cdd99c2017-09-08 16:04:12 -07003101 grpc_chttp2_transport *t = (grpc_chttp2_transport *)arg;
Craig Tiller25f29af2016-09-26 16:31:00 -07003102 if (error == GRPC_ERROR_NONE &&
3103 grpc_chttp2_stream_map_size(&t->stream_map) == 0) {
Craig Tiller6b5d6822016-10-25 16:13:26 -07003104 /* Channel with no active streams: send a goaway to try and make it
3105 * disconnect cleanly */
Craig Tiller84f75d42017-05-03 13:06:35 -07003106 if (GRPC_TRACER_ON(grpc_resource_quota_trace)) {
Craig Tilleref6b9762016-09-28 08:37:51 -07003107 gpr_log(GPR_DEBUG, "HTTP2: %s - send goaway to free memory",
3108 t->peer_string);
3109 }
Craig Tiller7c70b6c2017-01-23 07:48:42 -08003110 send_goaway(exec_ctx, t,
ncteisen4b36a3d2017-03-13 19:08:06 -07003111 grpc_error_set_int(
3112 GRPC_ERROR_CREATE_FROM_STATIC_STRING("Buffers full"),
3113 GRPC_ERROR_INT_HTTP2_ERROR, GRPC_HTTP2_ENHANCE_YOUR_CALM));
Craig Tiller3b654362017-05-04 08:11:17 -07003114 } else if (error == GRPC_ERROR_NONE &&
3115 GRPC_TRACER_ON(grpc_resource_quota_trace)) {
Craig Tilleref6b9762016-09-28 08:37:51 -07003116 gpr_log(GPR_DEBUG,
Craig Tiller3798e602016-10-21 14:39:27 -07003117 "HTTP2: %s - skip benign reclamation, there are still %" PRIdPTR
Craig Tilleref6b9762016-09-28 08:37:51 -07003118 " streams",
3119 t->peer_string, grpc_chttp2_stream_map_size(&t->stream_map));
Craig Tiller25f29af2016-09-26 16:31:00 -07003120 }
3121 t->benign_reclaimer_registered = false;
Craig Tiller69a1f662016-09-28 10:24:21 -07003122 if (error != GRPC_ERROR_CANCELLED) {
Craig Tiller3798e602016-10-21 14:39:27 -07003123 grpc_resource_user_finish_reclamation(
Craig Tiller20afa3d2016-10-17 14:52:14 -07003124 exec_ctx, grpc_endpoint_get_resource_user(t->ep));
Craig Tiller69a1f662016-09-28 10:24:21 -07003125 }
Craig Tiller25f29af2016-09-26 16:31:00 -07003126 GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "benign_reclaimer");
3127}
3128
3129static void destructive_reclaimer_locked(grpc_exec_ctx *exec_ctx, void *arg,
3130 grpc_error *error) {
Yash Tibrewal7cdd99c2017-09-08 16:04:12 -07003131 grpc_chttp2_transport *t = (grpc_chttp2_transport *)arg;
Craig Tiller25f29af2016-09-26 16:31:00 -07003132 size_t n = grpc_chttp2_stream_map_size(&t->stream_map);
3133 t->destructive_reclaimer_registered = false;
3134 if (error == GRPC_ERROR_NONE && n > 0) {
Yash Tibrewal7cdd99c2017-09-08 16:04:12 -07003135 grpc_chttp2_stream *s =
3136 (grpc_chttp2_stream *)grpc_chttp2_stream_map_rand(&t->stream_map);
Craig Tiller84f75d42017-05-03 13:06:35 -07003137 if (GRPC_TRACER_ON(grpc_resource_quota_trace)) {
Craig Tilleref6b9762016-09-28 08:37:51 -07003138 gpr_log(GPR_DEBUG, "HTTP2: %s - abandon stream id %d", t->peer_string,
3139 s->id);
3140 }
Craig Tiller25f29af2016-09-26 16:31:00 -07003141 grpc_chttp2_cancel_stream(
ncteisen4b36a3d2017-03-13 19:08:06 -07003142 exec_ctx, t, s,
3143 grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING("Buffers full"),
3144 GRPC_ERROR_INT_HTTP2_ERROR,
3145 GRPC_HTTP2_ENHANCE_YOUR_CALM));
Craig Tiller25f29af2016-09-26 16:31:00 -07003146 if (n > 1) {
Craig Tiller8abc7962016-10-26 21:31:29 -07003147 /* Since we cancel one stream per destructive reclamation, if
Craig Tiller6b5d6822016-10-25 16:13:26 -07003148 there are more streams left, we can immediately post a new
3149 reclaimer in case the resource quota needs to free more
3150 memory */
Craig Tiller795451f2016-09-27 08:47:28 -07003151 post_destructive_reclaimer(exec_ctx, t);
Craig Tiller25f29af2016-09-26 16:31:00 -07003152 }
3153 }
Craig Tiller69a1f662016-09-28 10:24:21 -07003154 if (error != GRPC_ERROR_CANCELLED) {
Craig Tiller3798e602016-10-21 14:39:27 -07003155 grpc_resource_user_finish_reclamation(
Craig Tiller20afa3d2016-10-17 14:52:14 -07003156 exec_ctx, grpc_endpoint_get_resource_user(t->ep));
Craig Tiller69a1f662016-09-28 10:24:21 -07003157 }
Craig Tiller25f29af2016-09-26 16:31:00 -07003158 GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "destructive_reclaimer");
3159}
3160
3161/*******************************************************************************
Yuchen Zeng5ab4ca52016-10-24 10:49:55 -07003162 * MONITORING
3163 */
Craig Tiller3ff1fa62017-09-14 11:07:48 -07003164
3165const char *grpc_chttp2_initiate_write_reason_string(
3166 grpc_chttp2_initiate_write_reason reason) {
3167 switch (reason) {
3168 case GRPC_CHTTP2_INITIATE_WRITE_INITIAL_WRITE:
3169 return "INITIAL_WRITE";
3170 case GRPC_CHTTP2_INITIATE_WRITE_START_NEW_STREAM:
3171 return "START_NEW_STREAM";
3172 case GRPC_CHTTP2_INITIATE_WRITE_SEND_MESSAGE:
3173 return "SEND_MESSAGE";
3174 case GRPC_CHTTP2_INITIATE_WRITE_SEND_INITIAL_METADATA:
3175 return "SEND_INITIAL_METADATA";
3176 case GRPC_CHTTP2_INITIATE_WRITE_SEND_TRAILING_METADATA:
3177 return "SEND_TRAILING_METADATA";
3178 case GRPC_CHTTP2_INITIATE_WRITE_RETRY_SEND_PING:
3179 return "RETRY_SEND_PING";
3180 case GRPC_CHTTP2_INITIATE_WRITE_CONTINUE_PINGS:
3181 return "CONTINUE_PINGS";
3182 case GRPC_CHTTP2_INITIATE_WRITE_GOAWAY_SENT:
3183 return "GOAWAY_SENT";
3184 case GRPC_CHTTP2_INITIATE_WRITE_RST_STREAM:
3185 return "RST_STREAM";
3186 case GRPC_CHTTP2_INITIATE_WRITE_CLOSE_FROM_API:
3187 return "CLOSE_FROM_API";
3188 case GRPC_CHTTP2_INITIATE_WRITE_STREAM_FLOW_CONTROL:
3189 return "STREAM_FLOW_CONTROL";
3190 case GRPC_CHTTP2_INITIATE_WRITE_TRANSPORT_FLOW_CONTROL:
3191 return "TRANSPORT_FLOW_CONTROL";
3192 case GRPC_CHTTP2_INITIATE_WRITE_SEND_SETTINGS:
3193 return "SEND_SETTINGS";
3194 case GRPC_CHTTP2_INITIATE_WRITE_BDP_ESTIMATOR_PING:
3195 return "BDP_ESTIMATOR_PING";
3196 case GRPC_CHTTP2_INITIATE_WRITE_FLOW_CONTROL_UNSTALLED_BY_SETTING:
3197 return "FLOW_CONTROL_UNSTALLED_BY_SETTING";
3198 case GRPC_CHTTP2_INITIATE_WRITE_FLOW_CONTROL_UNSTALLED_BY_UPDATE:
3199 return "FLOW_CONTROL_UNSTALLED_BY_UPDATE";
3200 case GRPC_CHTTP2_INITIATE_WRITE_APPLICATION_PING:
3201 return "APPLICATION_PING";
3202 case GRPC_CHTTP2_INITIATE_WRITE_KEEPALIVE_PING:
3203 return "KEEPALIVE_PING";
3204 case GRPC_CHTTP2_INITIATE_WRITE_TRANSPORT_FLOW_CONTROL_UNSTALLED:
3205 return "TRANSPORT_FLOW_CONTROL_UNSTALLED";
3206 case GRPC_CHTTP2_INITIATE_WRITE_PING_RESPONSE:
3207 return "PING_RESPONSE";
3208 case GRPC_CHTTP2_INITIATE_WRITE_FORCE_RST_STREAM:
3209 return "FORCE_RST_STREAM";
3210 }
3211 GPR_UNREACHABLE_CODE(return "unknown");
3212}
3213
Yuchen Zeng5ab4ca52016-10-24 10:49:55 -07003214static grpc_endpoint *chttp2_get_endpoint(grpc_exec_ctx *exec_ctx,
3215 grpc_transport *t) {
3216 return ((grpc_chttp2_transport *)t)->ep;
3217}
3218
Craig Tillera3b54cd2016-03-25 15:59:55 -07003219static const grpc_transport_vtable vtable = {sizeof(grpc_chttp2_stream),
3220 "chttp2",
3221 init_stream,
3222 set_pollset,
David Garcia Quintas4afce7e2016-04-18 16:25:17 -07003223 set_pollset_set,
Craig Tillera3b54cd2016-03-25 15:59:55 -07003224 perform_stream_op,
3225 perform_transport_op,
3226 destroy_stream,
3227 destroy_transport,
Yuchen Zeng5ab4ca52016-10-24 10:49:55 -07003228 chttp2_get_endpoint};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08003229
Craig Tillera6ca5712017-07-11 14:51:57 -07003230static const grpc_transport_vtable *get_vtable(void) { return &vtable; }
3231
Craig Tillera82950e2015-09-22 12:33:20 -07003232grpc_transport *grpc_create_chttp2_transport(
3233 grpc_exec_ctx *exec_ctx, const grpc_channel_args *channel_args,
Craig Tillerb2b42612015-11-20 12:02:17 -08003234 grpc_endpoint *ep, int is_client) {
Yash Tibrewal7cdd99c2017-09-08 16:04:12 -07003235 grpc_chttp2_transport *t =
3236 (grpc_chttp2_transport *)gpr_zalloc(sizeof(grpc_chttp2_transport));
Craig Tillerb2b42612015-11-20 12:02:17 -08003237 init_transport(exec_ctx, t, channel_args, ep, is_client != 0);
Craig Tiller1064f8b2015-06-25 13:52:57 -07003238 return &t->base;
Craig Tiller190d3602015-02-18 09:23:38 -08003239}
Craig Tiller825b21c2015-07-06 08:35:02 -07003240
Craig Tillera82950e2015-09-22 12:33:20 -07003241void grpc_chttp2_transport_start_reading(grpc_exec_ctx *exec_ctx,
3242 grpc_transport *transport,
Craig Tillerd41a4a72016-10-26 16:16:06 -07003243 grpc_slice_buffer *read_buffer) {
Craig Tillera82950e2015-09-22 12:33:20 -07003244 grpc_chttp2_transport *t = (grpc_chttp2_transport *)transport;
Craig Tillerdfd3a8f2016-08-24 09:43:45 -07003245 GRPC_CHTTP2_REF_TRANSPORT(
3246 t, "reading_action"); /* matches unref inside reading_action */
Mark D. Roth7d9f2762016-08-04 11:06:49 -07003247 if (read_buffer != NULL) {
Craig Tillerd41a4a72016-10-26 16:16:06 -07003248 grpc_slice_buffer_move_into(read_buffer, &t->read_buffer);
Mark D. Roth7d9f2762016-08-04 11:06:49 -07003249 gpr_free(read_buffer);
3250 }
ncteisen274bbbe2017-06-08 14:57:11 -07003251 GRPC_CLOSURE_SCHED(exec_ctx, &t->read_action_locked, GRPC_ERROR_NONE);
Craig Tiller06059952015-02-18 08:34:56 -08003252}