grpc 1.1.2 → 1.2.0.pre1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of grpc might be problematic. Click here for more details.

Files changed (255) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +1257 -404
  3. data/etc/roots.pem +189 -102
  4. data/include/grpc/census.h +7 -7
  5. data/include/grpc/compression.h +4 -4
  6. data/include/grpc/grpc.h +13 -7
  7. data/include/grpc/impl/codegen/atm_gcc_atomic.h +26 -9
  8. data/include/grpc/impl/codegen/grpc_types.h +39 -30
  9. data/include/grpc/impl/codegen/slice.h +24 -6
  10. data/include/grpc/impl/codegen/sync.h +8 -0
  11. data/include/grpc/load_reporting.h +63 -0
  12. data/include/grpc/slice.h +37 -1
  13. data/include/grpc/slice_buffer.h +7 -0
  14. data/include/grpc/support/alloc.h +3 -0
  15. data/include/grpc/support/useful.h +3 -0
  16. data/src/core/ext/census/gen/census.pb.h +1 -1
  17. data/src/core/ext/census/gen/trace_context.pb.c +9 -36
  18. data/src/core/ext/census/gen/trace_context.pb.h +20 -26
  19. data/src/core/ext/census/grpc_filter.c +3 -5
  20. data/src/core/ext/census/trace_context.c +1 -1
  21. data/src/core/ext/census/trace_context.h +3 -0
  22. data/src/core/ext/census/trace_label.h +61 -0
  23. data/src/core/ext/census/trace_propagation.h +63 -0
  24. data/src/core/ext/census/trace_status.h +45 -0
  25. data/src/core/ext/census/trace_string.h +50 -0
  26. data/src/core/ext/census/tracing.c +31 -11
  27. data/src/core/ext/census/tracing.h +124 -0
  28. data/src/core/ext/client_channel/client_channel.c +456 -368
  29. data/src/core/ext/client_channel/client_channel.h +4 -0
  30. data/src/core/ext/client_channel/client_channel_plugin.c +6 -1
  31. data/src/core/ext/client_channel/connector.c +3 -3
  32. data/src/core/ext/client_channel/connector.h +4 -3
  33. data/src/core/ext/client_channel/http_connect_handshaker.c +62 -72
  34. data/src/core/ext/client_channel/http_connect_handshaker.h +7 -10
  35. data/src/core/ext/client_channel/http_proxy.c +125 -0
  36. data/src/core/ext/client_channel/http_proxy.h +39 -0
  37. data/src/core/ext/client_channel/lb_policy.c +56 -35
  38. data/src/core/ext/client_channel/lb_policy.h +46 -39
  39. data/src/core/ext/client_channel/lb_policy_factory.h +1 -0
  40. data/src/core/ext/client_channel/parse_address.c +32 -6
  41. data/src/core/ext/client_channel/proxy_mapper.c +63 -0
  42. data/src/core/ext/client_channel/proxy_mapper.h +89 -0
  43. data/src/core/ext/client_channel/proxy_mapper_registry.c +133 -0
  44. data/src/core/ext/client_channel/proxy_mapper_registry.h +59 -0
  45. data/src/core/ext/client_channel/resolver.c +16 -9
  46. data/src/core/ext/client_channel/resolver.h +23 -12
  47. data/src/core/ext/client_channel/resolver_factory.h +1 -0
  48. data/src/core/ext/client_channel/resolver_registry.c +15 -11
  49. data/src/core/ext/client_channel/resolver_registry.h +5 -3
  50. data/src/core/ext/client_channel/subchannel.c +44 -27
  51. data/src/core/ext/client_channel/subchannel.h +6 -2
  52. data/src/core/ext/client_channel/uri_parser.c +26 -14
  53. data/src/core/ext/client_channel/uri_parser.h +3 -1
  54. data/src/core/ext/lb_policy/grpclb/grpclb.c +220 -209
  55. data/src/core/ext/lb_policy/grpclb/grpclb_channel.h +56 -0
  56. data/src/core/ext/lb_policy/grpclb/grpclb_channel_secure.c +107 -0
  57. data/src/core/ext/lb_policy/grpclb/load_balancer_api.c +3 -6
  58. data/src/core/ext/lb_policy/pick_first/pick_first.c +71 -116
  59. data/src/core/ext/lb_policy/round_robin/round_robin.c +52 -67
  60. data/src/core/ext/load_reporting/load_reporting.c +20 -0
  61. data/src/core/ext/load_reporting/load_reporting.h +1 -16
  62. data/src/core/ext/load_reporting/load_reporting_filter.c +28 -54
  63. data/src/core/ext/resolver/dns/native/dns_resolver.c +31 -45
  64. data/src/core/ext/resolver/sockaddr/sockaddr_resolver.c +20 -29
  65. data/src/core/ext/transport/chttp2/client/chttp2_connector.c +11 -8
  66. data/src/core/ext/transport/chttp2/client/insecure/channel_create.c +11 -2
  67. data/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c +143 -46
  68. data/src/core/ext/transport/chttp2/server/chttp2_server.c +12 -50
  69. data/src/core/ext/transport/chttp2/server/insecure/server_chttp2.c +1 -1
  70. data/src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.c +1 -1
  71. data/src/core/ext/transport/chttp2/transport/bin_decoder.c +7 -7
  72. data/src/core/ext/transport/chttp2/transport/bin_encoder.c +1 -2
  73. data/src/core/ext/transport/chttp2/transport/bin_encoder.h +1 -2
  74. data/src/core/ext/transport/chttp2/transport/chttp2_plugin.c +0 -3
  75. data/src/core/ext/transport/chttp2/transport/chttp2_transport.c +606 -374
  76. data/src/core/ext/transport/chttp2/transport/frame_ping.c +17 -5
  77. data/src/core/ext/transport/chttp2/transport/frame_ping.h +2 -2
  78. data/src/core/ext/transport/chttp2/transport/frame_rst_stream.c +9 -13
  79. data/src/core/ext/transport/chttp2/transport/frame_settings.c +12 -11
  80. data/src/core/ext/transport/chttp2/transport/frame_settings.h +1 -1
  81. data/src/core/ext/transport/chttp2/transport/frame_window_update.c +5 -6
  82. data/src/core/ext/transport/chttp2/transport/hpack_encoder.c +100 -53
  83. data/src/core/ext/transport/chttp2/transport/hpack_encoder.h +2 -2
  84. data/src/core/ext/transport/chttp2/transport/hpack_parser.c +126 -70
  85. data/src/core/ext/transport/chttp2/transport/hpack_parser.h +13 -7
  86. data/src/core/ext/transport/chttp2/transport/hpack_table.c +22 -19
  87. data/src/core/ext/transport/chttp2/transport/hpack_table.h +6 -6
  88. data/src/core/ext/transport/chttp2/transport/incoming_metadata.c +23 -11
  89. data/src/core/ext/transport/chttp2/transport/incoming_metadata.h +6 -2
  90. data/src/core/ext/transport/chttp2/transport/internal.h +169 -42
  91. data/src/core/ext/transport/chttp2/transport/parsing.c +98 -41
  92. data/src/core/ext/transport/chttp2/transport/stream_lists.c +29 -14
  93. data/src/core/ext/transport/chttp2/transport/writing.c +137 -15
  94. data/src/core/lib/channel/channel_stack.c +14 -44
  95. data/src/core/lib/channel/channel_stack.h +10 -17
  96. data/src/core/lib/channel/channel_stack_builder.c +2 -3
  97. data/src/core/lib/channel/compress_filter.c +54 -46
  98. data/src/core/lib/channel/connected_channel.c +4 -4
  99. data/src/core/lib/channel/connected_channel.h +5 -0
  100. data/src/core/lib/channel/context.h +3 -0
  101. data/src/core/lib/channel/deadline_filter.c +61 -61
  102. data/src/core/lib/channel/deadline_filter.h +8 -5
  103. data/src/core/lib/channel/handshaker.c +47 -7
  104. data/src/core/lib/channel/handshaker.h +21 -3
  105. data/src/core/lib/channel/http_client_filter.c +149 -99
  106. data/src/core/lib/channel/http_server_filter.c +163 -147
  107. data/src/core/lib/channel/message_size_filter.c +15 -10
  108. data/src/core/lib/compression/algorithm_metadata.h +4 -4
  109. data/src/core/lib/compression/compression.c +17 -23
  110. data/src/core/lib/http/httpcli.c +3 -2
  111. data/src/core/lib/http/httpcli.h +2 -1
  112. data/src/core/lib/http/httpcli_security_connector.c +2 -3
  113. data/src/core/lib/http/parser.c +2 -2
  114. data/src/core/lib/iomgr/closure.c +6 -3
  115. data/src/core/lib/iomgr/closure.h +4 -2
  116. data/src/core/lib/iomgr/combiner.c +35 -5
  117. data/src/core/lib/iomgr/combiner.h +21 -2
  118. data/src/core/lib/iomgr/endpoint.c +3 -2
  119. data/src/core/lib/iomgr/endpoint.h +3 -2
  120. data/src/core/lib/iomgr/error.c +60 -94
  121. data/src/core/lib/iomgr/error.h +7 -10
  122. data/src/core/lib/iomgr/error_internal.h +54 -0
  123. data/src/core/lib/iomgr/ev_epoll_linux.c +253 -109
  124. data/src/core/lib/iomgr/ev_poll_posix.c +61 -29
  125. data/src/core/lib/iomgr/ev_posix.c +7 -8
  126. data/src/core/lib/iomgr/ev_posix.h +4 -4
  127. data/src/core/lib/iomgr/exec_ctx.c +11 -6
  128. data/src/core/lib/iomgr/exec_ctx.h +11 -14
  129. data/src/core/lib/iomgr/executor.c +2 -2
  130. data/src/core/lib/iomgr/load_file.c +1 -1
  131. data/src/core/lib/iomgr/network_status_tracker.c +5 -81
  132. data/src/core/lib/iomgr/pollset.h +1 -3
  133. data/src/core/lib/iomgr/pollset_set.h +2 -1
  134. data/src/core/lib/iomgr/pollset_set_uv.c +2 -1
  135. data/src/core/lib/iomgr/pollset_set_windows.c +2 -1
  136. data/src/core/lib/iomgr/pollset_uv.c +25 -11
  137. data/src/core/lib/iomgr/pollset_windows.c +0 -11
  138. data/src/core/lib/iomgr/resolve_address_uv.c +50 -2
  139. data/src/core/lib/iomgr/resource_quota.c +41 -11
  140. data/src/core/lib/iomgr/resource_quota.h +6 -0
  141. data/src/core/lib/iomgr/sockaddr_utils.c +33 -17
  142. data/src/core/lib/iomgr/sockaddr_utils.h +4 -0
  143. data/src/core/lib/iomgr/tcp_client_posix.c +2 -3
  144. data/src/core/lib/iomgr/tcp_client_uv.c +1 -3
  145. data/src/core/lib/iomgr/tcp_client_windows.c +21 -6
  146. data/src/core/lib/iomgr/tcp_posix.c +4 -5
  147. data/src/core/lib/iomgr/tcp_server_posix.c +269 -94
  148. data/src/core/lib/iomgr/tcp_server_windows.c +1 -1
  149. data/src/core/lib/iomgr/tcp_uv.c +11 -5
  150. data/src/core/lib/iomgr/tcp_windows.c +20 -7
  151. data/src/core/lib/iomgr/timer_generic.c +15 -22
  152. data/src/core/lib/iomgr/timer_generic.h +1 -1
  153. data/src/core/lib/iomgr/timer_uv.c +10 -6
  154. data/src/core/lib/iomgr/timer_uv.h +1 -1
  155. data/src/core/lib/iomgr/udp_server.c +45 -6
  156. data/src/core/lib/iomgr/udp_server.h +7 -1
  157. data/src/core/lib/iomgr/unix_sockets_posix.c +11 -1
  158. data/src/core/lib/json/json.c +1 -2
  159. data/src/core/lib/profiling/basic_timers.c +17 -3
  160. data/src/core/lib/security/context/security_context.c +3 -10
  161. data/src/core/lib/security/credentials/composite/composite_credentials.c +4 -8
  162. data/src/core/lib/security/credentials/credentials.c +48 -2
  163. data/src/core/lib/security/credentials/credentials.h +13 -0
  164. data/src/core/lib/security/credentials/credentials_metadata.c +1 -2
  165. data/src/core/lib/security/credentials/fake/fake_credentials.c +6 -8
  166. data/src/core/lib/security/credentials/fake/fake_credentials.h +15 -0
  167. data/src/core/lib/security/credentials/google_default/google_default_credentials.c +3 -3
  168. data/src/core/lib/security/credentials/iam/iam_credentials.c +1 -2
  169. data/src/core/lib/security/credentials/jwt/jwt_credentials.c +1 -2
  170. data/src/core/lib/security/credentials/jwt/jwt_verifier.c +5 -8
  171. data/src/core/lib/security/credentials/jwt/jwt_verifier.h +2 -1
  172. data/src/core/lib/security/credentials/oauth2/oauth2_credentials.c +3 -5
  173. data/src/core/lib/security/credentials/plugin/plugin_credentials.c +15 -13
  174. data/src/core/lib/security/credentials/ssl/ssl_credentials.c +2 -4
  175. data/src/core/lib/security/transport/client_auth_filter.c +72 -47
  176. data/src/core/lib/security/transport/lb_targets_info.c +70 -0
  177. data/src/core/lib/security/transport/lb_targets_info.h +47 -0
  178. data/src/core/lib/security/transport/secure_endpoint.c +3 -3
  179. data/src/core/lib/security/transport/security_connector.c +125 -28
  180. data/src/core/lib/security/transport/security_connector.h +4 -3
  181. data/src/core/lib/security/transport/security_handshaker.c +13 -9
  182. data/src/core/lib/security/transport/server_auth_filter.c +31 -40
  183. data/src/core/lib/security/util/b64.c +1 -1
  184. data/src/core/lib/slice/slice.c +110 -20
  185. data/src/core/lib/slice/slice_buffer.c +92 -39
  186. data/src/core/lib/{transport/mdstr_hash_table.c → slice/slice_hash_table.c} +40 -33
  187. data/src/core/lib/{transport/mdstr_hash_table.h → slice/slice_hash_table.h} +21 -21
  188. data/src/core/lib/slice/slice_intern.c +346 -0
  189. data/src/core/lib/slice/slice_internal.h +15 -0
  190. data/src/core/lib/slice/slice_string_helpers.c +5 -0
  191. data/src/core/lib/slice/slice_string_helpers.h +5 -0
  192. data/src/core/lib/support/alloc.c +26 -1
  193. data/src/core/lib/support/cmdline.c +2 -4
  194. data/src/core/lib/support/cpu_posix.c +2 -7
  195. data/src/core/lib/support/histogram.c +1 -2
  196. data/src/core/lib/support/log_posix.c +8 -4
  197. data/src/core/lib/support/spinlock.h +52 -0
  198. data/src/core/lib/support/subprocess_posix.c +1 -2
  199. data/src/core/lib/support/sync.c +7 -1
  200. data/src/core/lib/support/sync_posix.c +9 -0
  201. data/src/core/lib/support/time_windows.c +7 -1
  202. data/src/core/lib/surface/call.c +647 -629
  203. data/src/core/lib/surface/call.h +4 -1
  204. data/src/core/lib/surface/call_details.c +8 -2
  205. data/src/core/lib/surface/call_log_batch.c +17 -6
  206. data/src/core/lib/surface/channel.c +49 -59
  207. data/src/core/lib/surface/channel.h +5 -6
  208. data/src/core/lib/surface/completion_queue.c +16 -45
  209. data/src/core/lib/surface/completion_queue.h +0 -3
  210. data/src/core/lib/surface/init.c +6 -2
  211. data/src/core/lib/surface/init_secure.c +1 -1
  212. data/src/core/lib/surface/lame_client.c +14 -4
  213. data/src/core/lib/surface/server.c +79 -82
  214. data/src/core/lib/surface/validate_metadata.c +46 -15
  215. data/src/core/lib/surface/validate_metadata.h +43 -0
  216. data/src/core/lib/surface/version.c +2 -2
  217. data/src/core/lib/transport/bdp_estimator.c +104 -0
  218. data/src/core/lib/transport/bdp_estimator.h +76 -0
  219. data/src/core/lib/transport/connectivity_state.c +33 -13
  220. data/src/core/lib/transport/connectivity_state.h +15 -5
  221. data/src/core/lib/transport/error_utils.c +124 -0
  222. data/src/core/lib/transport/error_utils.h +56 -0
  223. data/src/core/{ext/transport/chttp2 → lib}/transport/http2_errors.h +18 -18
  224. data/src/core/lib/transport/metadata.c +259 -503
  225. data/src/core/lib/transport/metadata.h +69 -68
  226. data/src/core/lib/transport/metadata_batch.c +183 -63
  227. data/src/core/lib/transport/metadata_batch.h +50 -26
  228. data/src/core/lib/transport/pid_controller.c +28 -8
  229. data/src/core/lib/transport/pid_controller.h +15 -2
  230. data/src/core/lib/transport/service_config.c +21 -18
  231. data/src/core/lib/transport/service_config.h +5 -5
  232. data/src/core/lib/transport/static_metadata.c +753 -112
  233. data/src/core/lib/transport/static_metadata.h +403 -264
  234. data/src/core/{ext/transport/chttp2 → lib}/transport/status_conversion.c +18 -20
  235. data/src/core/{ext/transport/chttp2 → lib}/transport/status_conversion.h +9 -10
  236. data/src/core/lib/transport/timeout_encoding.c +11 -9
  237. data/src/core/lib/transport/timeout_encoding.h +3 -1
  238. data/src/core/lib/transport/transport.c +47 -87
  239. data/src/core/lib/transport/transport.h +20 -25
  240. data/src/core/lib/transport/transport_op_string.c +7 -19
  241. data/src/core/lib/tsi/fake_transport_security.c +2 -4
  242. data/src/core/lib/tsi/ssl_transport_security.c +7 -16
  243. data/src/core/lib/tsi/transport_security.c +2 -4
  244. data/src/ruby/ext/grpc/extconf.rb +4 -1
  245. data/src/ruby/ext/grpc/rb_byte_buffer.c +7 -0
  246. data/src/ruby/ext/grpc/rb_byte_buffer.h +3 -0
  247. data/src/ruby/ext/grpc/rb_call.c +47 -46
  248. data/src/ruby/ext/grpc/rb_channel.c +21 -6
  249. data/src/ruby/ext/grpc/rb_compression_options.c +9 -6
  250. data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +36 -2
  251. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +59 -8
  252. data/src/ruby/ext/grpc/rb_server.c +6 -4
  253. data/src/ruby/lib/grpc/generic/client_stub.rb +1 -1
  254. data/src/ruby/lib/grpc/version.rb +1 -1
  255. metadata +33 -9
@@ -55,11 +55,6 @@
55
55
  #include "src/core/lib/surface/api_trace.h"
56
56
  #include "src/core/lib/surface/server.h"
57
57
 
58
- typedef struct pending_handshake_manager_node {
59
- grpc_handshake_manager *handshake_mgr;
60
- struct pending_handshake_manager_node *next;
61
- } pending_handshake_manager_node;
62
-
63
58
  typedef struct {
64
59
  grpc_server *server;
65
60
  grpc_tcp_server *tcp_server;
@@ -68,7 +63,7 @@ typedef struct {
68
63
  bool shutdown;
69
64
  grpc_closure tcp_server_shutdown_complete;
70
65
  grpc_closure *server_destroy_listener_done;
71
- pending_handshake_manager_node *pending_handshake_mgrs;
66
+ grpc_handshake_manager *pending_handshake_mgrs;
72
67
  } server_state;
73
68
 
74
69
  typedef struct {
@@ -78,41 +73,6 @@ typedef struct {
78
73
  grpc_handshake_manager *handshake_mgr;
79
74
  } server_connection_state;
80
75
 
81
- static void pending_handshake_manager_add_locked(
82
- server_state *state, grpc_handshake_manager *handshake_mgr) {
83
- pending_handshake_manager_node *node = gpr_malloc(sizeof(*node));
84
- node->handshake_mgr = handshake_mgr;
85
- node->next = state->pending_handshake_mgrs;
86
- state->pending_handshake_mgrs = node;
87
- }
88
-
89
- static void pending_handshake_manager_remove_locked(
90
- server_state *state, grpc_handshake_manager *handshake_mgr) {
91
- pending_handshake_manager_node **prev_node = &state->pending_handshake_mgrs;
92
- for (pending_handshake_manager_node *node = state->pending_handshake_mgrs;
93
- node != NULL; node = node->next) {
94
- if (node->handshake_mgr == handshake_mgr) {
95
- *prev_node = node->next;
96
- gpr_free(node);
97
- break;
98
- }
99
- prev_node = &node->next;
100
- }
101
- }
102
-
103
- static void pending_handshake_manager_shutdown_locked(grpc_exec_ctx *exec_ctx,
104
- server_state *state) {
105
- pending_handshake_manager_node *prev_node = NULL;
106
- for (pending_handshake_manager_node *node = state->pending_handshake_mgrs;
107
- node != NULL; node = node->next) {
108
- grpc_handshake_manager_shutdown(exec_ctx, node->handshake_mgr);
109
- gpr_free(prev_node);
110
- prev_node = node;
111
- }
112
- gpr_free(prev_node);
113
- state->pending_handshake_mgrs = NULL;
114
- }
115
-
116
76
  static void on_handshake_done(grpc_exec_ctx *exec_ctx, void *arg,
117
77
  grpc_error *error) {
118
78
  grpc_handshaker_args *args = arg;
@@ -121,7 +81,7 @@ static void on_handshake_done(grpc_exec_ctx *exec_ctx, void *arg,
121
81
  if (error != GRPC_ERROR_NONE || connection_state->server_state->shutdown) {
122
82
  const char *error_str = grpc_error_string(error);
123
83
  gpr_log(GPR_ERROR, "Handshaking failed: %s", error_str);
124
- grpc_error_free_string(error_str);
84
+
125
85
  if (error == GRPC_ERROR_NONE && args->endpoint != NULL) {
126
86
  // We were shut down after handshaking completed successfully, so
127
87
  // destroy the endpoint here.
@@ -129,7 +89,7 @@ static void on_handshake_done(grpc_exec_ctx *exec_ctx, void *arg,
129
89
  // before destroying them, even if we know that there are no
130
90
  // pending read/write callbacks. This should be fixed, at which
131
91
  // point this can be removed.
132
- grpc_endpoint_shutdown(exec_ctx, args->endpoint);
92
+ grpc_endpoint_shutdown(exec_ctx, args->endpoint, GRPC_ERROR_NONE);
133
93
  grpc_endpoint_destroy(exec_ctx, args->endpoint);
134
94
  grpc_channel_args_destroy(exec_ctx, args->args);
135
95
  grpc_slice_buffer_destroy_internal(exec_ctx, args->read_buffer);
@@ -150,8 +110,9 @@ static void on_handshake_done(grpc_exec_ctx *exec_ctx, void *arg,
150
110
  grpc_channel_args_destroy(exec_ctx, args->args);
151
111
  }
152
112
  }
153
- pending_handshake_manager_remove_locked(connection_state->server_state,
154
- connection_state->handshake_mgr);
113
+ grpc_handshake_manager_pending_list_remove(
114
+ &connection_state->server_state->pending_handshake_mgrs,
115
+ connection_state->handshake_mgr);
155
116
  gpr_mu_unlock(&connection_state->server_state->mu);
156
117
  grpc_handshake_manager_destroy(exec_ctx, connection_state->handshake_mgr);
157
118
  grpc_tcp_server_unref(exec_ctx, connection_state->server_state->tcp_server);
@@ -171,7 +132,8 @@ static void on_accept(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *tcp,
171
132
  return;
172
133
  }
173
134
  grpc_handshake_manager *handshake_mgr = grpc_handshake_manager_create();
174
- pending_handshake_manager_add_locked(state, handshake_mgr);
135
+ grpc_handshake_manager_pending_list_add(&state->pending_handshake_mgrs,
136
+ handshake_mgr);
175
137
  gpr_mu_unlock(&state->mu);
176
138
  grpc_tcp_server_ref(state->tcp_server);
177
139
  server_connection_state *connection_state =
@@ -210,7 +172,8 @@ static void tcp_server_shutdown_complete(grpc_exec_ctx *exec_ctx, void *arg,
210
172
  gpr_mu_lock(&state->mu);
211
173
  grpc_closure *destroy_done = state->server_destroy_listener_done;
212
174
  GPR_ASSERT(state->shutdown);
213
- pending_handshake_manager_shutdown_locked(exec_ctx, state);
175
+ grpc_handshake_manager_pending_list_shutdown_all(
176
+ exec_ctx, state->pending_handshake_mgrs, GRPC_ERROR_REF(error));
214
177
  gpr_mu_unlock(&state->mu);
215
178
  // Flush queued work before destroying handshaker factory, since that
216
179
  // may do a synchronous unref.
@@ -259,8 +222,7 @@ grpc_error *grpc_chttp2_server_add_port(grpc_exec_ctx *exec_ctx,
259
222
  if (err != GRPC_ERROR_NONE) {
260
223
  goto error;
261
224
  }
262
- state = gpr_malloc(sizeof(*state));
263
- memset(state, 0, sizeof(*state));
225
+ state = gpr_zalloc(sizeof(*state));
264
226
  grpc_closure_init(&state->tcp_server_shutdown_complete,
265
227
  tcp_server_shutdown_complete, state,
266
228
  grpc_schedule_on_exec_ctx);
@@ -307,7 +269,7 @@ grpc_error *grpc_chttp2_server_add_port(grpc_exec_ctx *exec_ctx,
307
269
 
308
270
  const char *warning_message = grpc_error_string(err);
309
271
  gpr_log(GPR_INFO, "WARNING: %s", warning_message);
310
- grpc_error_free_string(warning_message);
272
+
311
273
  /* we managed to bind some addresses: continue */
312
274
  }
313
275
  grpc_resolved_addresses_destroy(resolved);
@@ -51,7 +51,7 @@ int grpc_server_add_insecure_http2_port(grpc_server *server, const char *addr) {
51
51
  if (err != GRPC_ERROR_NONE) {
52
52
  const char *msg = grpc_error_string(err);
53
53
  gpr_log(GPR_ERROR, "%s", msg);
54
- grpc_error_free_string(msg);
54
+
55
55
  GRPC_ERROR_UNREF(err);
56
56
  }
57
57
  grpc_exec_ctx_finish(&exec_ctx);
@@ -94,7 +94,7 @@ done:
94
94
  if (err != GRPC_ERROR_NONE) {
95
95
  const char *msg = grpc_error_string(err);
96
96
  gpr_log(GPR_ERROR, "%s", msg);
97
- grpc_error_free_string(msg);
97
+
98
98
  GRPC_ERROR_UNREF(err);
99
99
  }
100
100
  return port_num;
@@ -157,7 +157,7 @@ grpc_slice grpc_chttp2_base64_decode(grpc_exec_ctx *exec_ctx,
157
157
  "grpc_chttp2_base64_decode has a length of %d, which is not a "
158
158
  "multiple of 4.\n",
159
159
  (int)input_length);
160
- return gpr_empty_slice();
160
+ return grpc_empty_slice();
161
161
  }
162
162
 
163
163
  if (input_length > 0) {
@@ -178,11 +178,11 @@ grpc_slice grpc_chttp2_base64_decode(grpc_exec_ctx *exec_ctx,
178
178
  ctx.contains_tail = false;
179
179
 
180
180
  if (!grpc_base64_decode_partial(&ctx)) {
181
- char *s = grpc_dump_slice(input, GPR_DUMP_ASCII);
181
+ char *s = grpc_slice_to_c_string(input);
182
182
  gpr_log(GPR_ERROR, "Base64 decoding failed, input string:\n%s\n", s);
183
183
  gpr_free(s);
184
184
  grpc_slice_unref_internal(exec_ctx, output);
185
- return gpr_empty_slice();
185
+ return grpc_empty_slice();
186
186
  }
187
187
  GPR_ASSERT(ctx.output_cur == GRPC_SLICE_END_PTR(output));
188
188
  GPR_ASSERT(ctx.input_cur == GRPC_SLICE_END_PTR(input));
@@ -204,7 +204,7 @@ grpc_slice grpc_chttp2_base64_decode_with_length(grpc_exec_ctx *exec_ctx,
204
204
  "has a tail of 1 byte.\n",
205
205
  (int)input_length);
206
206
  grpc_slice_unref_internal(exec_ctx, output);
207
- return gpr_empty_slice();
207
+ return grpc_empty_slice();
208
208
  }
209
209
 
210
210
  if (output_length > input_length / 4 * 3 + tail_xtra[input_length % 4]) {
@@ -214,7 +214,7 @@ grpc_slice grpc_chttp2_base64_decode_with_length(grpc_exec_ctx *exec_ctx,
214
214
  (int)output_length,
215
215
  (int)(input_length / 4 * 3 + tail_xtra[input_length % 4]));
216
216
  grpc_slice_unref_internal(exec_ctx, output);
217
- return gpr_empty_slice();
217
+ return grpc_empty_slice();
218
218
  }
219
219
 
220
220
  ctx.input_cur = GRPC_SLICE_START_PTR(input);
@@ -224,11 +224,11 @@ grpc_slice grpc_chttp2_base64_decode_with_length(grpc_exec_ctx *exec_ctx,
224
224
  ctx.contains_tail = true;
225
225
 
226
226
  if (!grpc_base64_decode_partial(&ctx)) {
227
- char *s = grpc_dump_slice(input, GPR_DUMP_ASCII);
227
+ char *s = grpc_slice_to_c_string(input);
228
228
  gpr_log(GPR_ERROR, "Base64 decoding failed, input string:\n%s\n", s);
229
229
  gpr_free(s);
230
230
  grpc_slice_unref_internal(exec_ctx, output);
231
- return gpr_empty_slice();
231
+ return grpc_empty_slice();
232
232
  }
233
233
  GPR_ASSERT(ctx.output_cur == GRPC_SLICE_END_PTR(output));
234
234
  GPR_ASSERT(ctx.input_cur <= GRPC_SLICE_END_PTR(input));
@@ -177,8 +177,7 @@ static void enc_add1(huff_out *out, uint8_t a) {
177
177
  enc_flush_some(out);
178
178
  }
179
179
 
180
- grpc_slice grpc_chttp2_base64_encode_and_huffman_compress_impl(
181
- grpc_slice input) {
180
+ grpc_slice grpc_chttp2_base64_encode_and_huffman_compress(grpc_slice input) {
182
181
  size_t input_length = GRPC_SLICE_LENGTH(input);
183
182
  size_t input_triplets = input_length / 3;
184
183
  size_t tail_case = input_length % 3;
@@ -49,7 +49,6 @@ grpc_slice grpc_chttp2_huffman_compress(grpc_slice input);
49
49
  grpc_slice y = grpc_chttp2_huffman_compress(x);
50
50
  grpc_slice_unref_internal(exec_ctx, x);
51
51
  return y; */
52
- grpc_slice grpc_chttp2_base64_encode_and_huffman_compress_impl(
53
- grpc_slice input);
52
+ grpc_slice grpc_chttp2_base64_encode_and_huffman_compress(grpc_slice input);
54
53
 
55
54
  #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_BIN_ENCODER_H */
@@ -31,14 +31,11 @@
31
31
  *
32
32
  */
33
33
 
34
- #include "src/core/ext/transport/chttp2/transport/bin_encoder.h"
35
34
  #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
36
35
  #include "src/core/lib/debug/trace.h"
37
36
  #include "src/core/lib/transport/metadata.h"
38
37
 
39
38
  void grpc_chttp2_plugin_init(void) {
40
- grpc_chttp2_base64_encode_and_huffman_compress =
41
- grpc_chttp2_base64_encode_and_huffman_compress_impl;
42
39
  grpc_register_tracer("http", &grpc_http_trace);
43
40
  grpc_register_tracer("flowctl", &grpc_flowctl_trace);
44
41
  }
@@ -44,19 +44,23 @@
44
44
  #include <grpc/support/string_util.h>
45
45
  #include <grpc/support/useful.h>
46
46
 
47
- #include "src/core/ext/transport/chttp2/transport/http2_errors.h"
48
47
  #include "src/core/ext/transport/chttp2/transport/internal.h"
49
- #include "src/core/ext/transport/chttp2/transport/status_conversion.h"
50
48
  #include "src/core/ext/transport/chttp2/transport/varint.h"
51
49
  #include "src/core/lib/channel/channel_args.h"
52
50
  #include "src/core/lib/http/parser.h"
51
+ #include "src/core/lib/iomgr/timer.h"
53
52
  #include "src/core/lib/iomgr/workqueue.h"
54
53
  #include "src/core/lib/profiling/timers.h"
55
54
  #include "src/core/lib/slice/slice_internal.h"
56
55
  #include "src/core/lib/slice/slice_string_helpers.h"
56
+ #include "src/core/lib/support/env.h"
57
57
  #include "src/core/lib/support/string.h"
58
+ #include "src/core/lib/transport/error_utils.h"
59
+ #include "src/core/lib/transport/http2_errors.h"
58
60
  #include "src/core/lib/transport/static_metadata.h"
61
+ #include "src/core/lib/transport/status_conversion.h"
59
62
  #include "src/core/lib/transport/timeout_encoding.h"
63
+ #include "src/core/lib/transport/transport.h"
60
64
  #include "src/core/lib/transport/transport_impl.h"
61
65
 
62
66
  #define DEFAULT_WINDOW 65535
@@ -65,6 +69,10 @@
65
69
  #define MAX_WRITE_BUFFER_SIZE (64 * 1024 * 1024)
66
70
  #define DEFAULT_MAX_HEADER_LIST_SIZE (16 * 1024)
67
71
 
72
+ #define DEFAULT_KEEPALIVE_TIME_SECOND INT_MAX
73
+ #define DEFAULT_KEEPALIVE_TIMEOUT_SECOND 20
74
+ #define DEFAULT_KEEPALIVE_PERMIT_WITHOUT_CALLS false
75
+
68
76
  #define MAX_CLIENT_STREAM_ID 0x7fffffffu
69
77
  int grpc_http_trace = 0;
70
78
  int grpc_flowctl_trace = 0;
@@ -123,6 +131,31 @@ static void close_transport_locked(grpc_exec_ctx *exec_ctx,
123
131
  static void end_all_the_calls(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
124
132
  grpc_error *error);
125
133
 
134
+ static void start_bdp_ping_locked(grpc_exec_ctx *exec_ctx, void *tp,
135
+ grpc_error *error);
136
+ static void finish_bdp_ping_locked(grpc_exec_ctx *exec_ctx, void *tp,
137
+ grpc_error *error);
138
+
139
+ static void cancel_pings(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
140
+ grpc_error *error);
141
+ static void send_ping_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
142
+ grpc_chttp2_ping_type ping_type,
143
+ grpc_closure *on_initiate,
144
+ grpc_closure *on_complete);
145
+
146
+ #define DEFAULT_MIN_TIME_BETWEEN_PINGS_MS 0
147
+ #define DEFAULT_MAX_PINGS_BETWEEN_DATA 3
148
+
149
+ /** keepalive-relevant functions */
150
+ static void init_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg,
151
+ grpc_error *error);
152
+ static void start_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg,
153
+ grpc_error *error);
154
+ static void finish_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg,
155
+ grpc_error *error);
156
+ static void keepalive_watchdog_fired_locked(grpc_exec_ctx *exec_ctx, void *arg,
157
+ grpc_error *error);
158
+
126
159
  /*******************************************************************************
127
160
  * CONSTRUCTION/DESTRUCTION/REFCOUNTING
128
161
  */
@@ -152,18 +185,9 @@ static void destruct_transport(grpc_exec_ctx *exec_ctx,
152
185
  grpc_chttp2_stream_map_destroy(&t->stream_map);
153
186
  grpc_connectivity_state_destroy(exec_ctx, &t->channel_callback.state_tracker);
154
187
 
155
- grpc_combiner_destroy(exec_ctx, t->combiner);
188
+ GRPC_COMBINER_UNREF(exec_ctx, t->combiner, "chttp2_transport");
156
189
 
157
- /* callback remaining pings: they're not allowed to call into the transpot,
158
- and maybe they hold resources that need to be freed */
159
- while (t->pings.next != &t->pings) {
160
- grpc_chttp2_outstanding_ping *ping = t->pings.next;
161
- grpc_closure_sched(exec_ctx, ping->on_recv,
162
- GRPC_ERROR_CREATE("Transport closed"));
163
- ping->next->prev = ping->prev;
164
- ping->prev->next = ping->next;
165
- gpr_free(ping);
166
- }
190
+ cancel_pings(exec_ctx, t, GRPC_ERROR_CREATE("Transport destroyed"));
167
191
 
168
192
  while (t->write_cb_pool) {
169
193
  grpc_chttp2_write_cb *next = t->write_cb_pool->next;
@@ -171,6 +195,7 @@ static void destruct_transport(grpc_exec_ctx *exec_ctx,
171
195
  t->write_cb_pool = next;
172
196
  }
173
197
 
198
+ gpr_free(t->ping_acks);
174
199
  gpr_free(t->peer_string);
175
200
  gpr_free(t);
176
201
  }
@@ -210,8 +235,6 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
210
235
  GPR_ASSERT(strlen(GRPC_CHTTP2_CLIENT_CONNECT_STRING) ==
211
236
  GRPC_CHTTP2_CLIENT_CONNECT_STRLEN);
212
237
 
213
- memset(t, 0, sizeof(*t));
214
-
215
238
  t->base.vtable = &vtable;
216
239
  t->ep = ep;
217
240
  /* one ref is for destroy */
@@ -223,10 +246,6 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
223
246
  t->is_client = is_client;
224
247
  t->outgoing_window = DEFAULT_WINDOW;
225
248
  t->incoming_window = DEFAULT_WINDOW;
226
- t->stream_lookahead = DEFAULT_WINDOW;
227
- t->connection_window_target = DEFAULT_CONNECTION_WINDOW_TARGET;
228
- t->ping_counter = 1;
229
- t->pings.next = t->pings.prev = &t->pings;
230
249
  t->deframe_state = is_client ? GRPC_DTS_FH_0 : GRPC_DTS_CLIENT_PREFIX_0;
231
250
  t->is_first_frame = true;
232
251
  grpc_connectivity_state_init(
@@ -247,6 +266,33 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
247
266
  grpc_closure_init(&t->destructive_reclaimer_locked,
248
267
  destructive_reclaimer_locked, t,
249
268
  grpc_combiner_scheduler(t->combiner, false));
269
+ grpc_closure_init(&t->start_bdp_ping_locked, start_bdp_ping_locked, t,
270
+ grpc_combiner_scheduler(t->combiner, false));
271
+ grpc_closure_init(&t->finish_bdp_ping_locked, finish_bdp_ping_locked, t,
272
+ grpc_combiner_scheduler(t->combiner, false));
273
+ grpc_closure_init(&t->init_keepalive_ping_locked, init_keepalive_ping_locked,
274
+ t, grpc_combiner_scheduler(t->combiner, false));
275
+ grpc_closure_init(&t->start_keepalive_ping_locked,
276
+ start_keepalive_ping_locked, t,
277
+ grpc_combiner_scheduler(t->combiner, false));
278
+ grpc_closure_init(&t->finish_keepalive_ping_locked,
279
+ finish_keepalive_ping_locked, t,
280
+ grpc_combiner_scheduler(t->combiner, false));
281
+ grpc_closure_init(&t->keepalive_watchdog_fired_locked,
282
+ keepalive_watchdog_fired_locked, t,
283
+ grpc_combiner_scheduler(t->combiner, false));
284
+
285
+ grpc_bdp_estimator_init(&t->bdp_estimator, t->peer_string);
286
+ t->last_pid_update = gpr_now(GPR_CLOCK_MONOTONIC);
287
+ grpc_pid_controller_init(
288
+ &t->pid_controller,
289
+ (grpc_pid_controller_args){.gain_p = 4,
290
+ .gain_i = 8,
291
+ .gain_d = 0,
292
+ .initial_control_value = log2(DEFAULT_WINDOW),
293
+ .min_control_value = -1,
294
+ .max_control_value = 25,
295
+ .integral_range = 10});
250
296
 
251
297
  grpc_chttp2_goaway_parser_init(&t->goaway_parser);
252
298
  grpc_chttp2_hpack_parser_init(exec_ctx, &t->hpack_parser);
@@ -272,6 +318,7 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
272
318
  t->force_send_settings = 1 << GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
273
319
  t->sent_local_settings = 0;
274
320
  t->write_buffer_size = DEFAULT_WINDOW;
321
+ t->enable_bdp_probe = true;
275
322
 
276
323
  if (is_client) {
277
324
  grpc_slice_buffer_add(&t->outbuf, grpc_slice_from_copied_string(
@@ -289,6 +336,24 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
289
336
  push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE,
290
337
  DEFAULT_MAX_HEADER_LIST_SIZE);
291
338
 
339
+ t->ping_policy = (grpc_chttp2_repeated_ping_policy){
340
+ .max_pings_without_data = DEFAULT_MAX_PINGS_BETWEEN_DATA,
341
+ .min_time_between_pings =
342
+ gpr_time_from_millis(DEFAULT_MIN_TIME_BETWEEN_PINGS_MS, GPR_TIMESPAN),
343
+ };
344
+
345
+ /* client-side keepalive setting */
346
+ t->keepalive_time =
347
+ DEFAULT_KEEPALIVE_TIME_SECOND == INT_MAX
348
+ ? gpr_inf_future(GPR_TIMESPAN)
349
+ : gpr_time_from_seconds(DEFAULT_KEEPALIVE_TIME_SECOND, GPR_TIMESPAN);
350
+ t->keepalive_timeout =
351
+ DEFAULT_KEEPALIVE_TIMEOUT_SECOND == INT_MAX
352
+ ? gpr_inf_future(GPR_TIMESPAN)
353
+ : gpr_time_from_seconds(DEFAULT_KEEPALIVE_TIMEOUT_SECOND,
354
+ GPR_TIMESPAN);
355
+ t->keepalive_permit_without_calls = DEFAULT_KEEPALIVE_PERMIT_WITHOUT_CALLS;
356
+
292
357
  if (channel_args) {
293
358
  for (i = 0; i < channel_args->num_args; i++) {
294
359
  if (0 == strcmp(channel_args->args[i].key,
@@ -305,14 +370,6 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
305
370
  t->next_stream_id = (uint32_t)value;
306
371
  }
307
372
  }
308
- } else if (0 == strcmp(channel_args->args[i].key,
309
- GRPC_ARG_HTTP2_STREAM_LOOKAHEAD_BYTES)) {
310
- const grpc_integer_options options = {-1, 5, INT_MAX};
311
- const int value =
312
- grpc_channel_arg_get_integer(&channel_args->args[i], options);
313
- if (value >= 0) {
314
- t->stream_lookahead = (uint32_t)value;
315
- }
316
373
  } else if (0 == strcmp(channel_args->args[i].key,
317
374
  GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_ENCODER)) {
318
375
  const grpc_integer_options options = {-1, 0, INT_MAX};
@@ -322,35 +379,76 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
322
379
  grpc_chttp2_hpack_compressor_set_max_usable_size(&t->hpack_compressor,
323
380
  (uint32_t)value);
324
381
  }
382
+ } else if (0 == strcmp(channel_args->args[i].key,
383
+ GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA)) {
384
+ t->ping_policy.max_pings_without_data = grpc_channel_arg_get_integer(
385
+ &channel_args->args[i],
386
+ (grpc_integer_options){DEFAULT_MAX_PINGS_BETWEEN_DATA, 0, INT_MAX});
387
+ } else if (0 == strcmp(channel_args->args[i].key,
388
+ GRPC_ARG_HTTP2_MIN_TIME_BETWEEN_PINGS_MS)) {
389
+ t->ping_policy.min_time_between_pings = gpr_time_from_millis(
390
+ grpc_channel_arg_get_integer(
391
+ &channel_args->args[i],
392
+ (grpc_integer_options){DEFAULT_MIN_TIME_BETWEEN_PINGS_MS, 0,
393
+ INT_MAX}),
394
+ GPR_TIMESPAN);
325
395
  } else if (0 == strcmp(channel_args->args[i].key,
326
396
  GRPC_ARG_HTTP2_WRITE_BUFFER_SIZE)) {
327
397
  t->write_buffer_size = (uint32_t)grpc_channel_arg_get_integer(
328
398
  &channel_args->args[i],
329
399
  (grpc_integer_options){0, 0, MAX_WRITE_BUFFER_SIZE});
400
+ } else if (0 ==
401
+ strcmp(channel_args->args[i].key, GRPC_ARG_HTTP2_BDP_PROBE)) {
402
+ t->enable_bdp_probe = grpc_channel_arg_get_integer(
403
+ &channel_args->args[i], (grpc_integer_options){1, 0, 1});
404
+ } else if (0 == strcmp(channel_args->args[i].key,
405
+ GRPC_ARG_HTTP2_KEEPALIVE_TIME)) {
406
+ const int value = grpc_channel_arg_get_integer(
407
+ &channel_args->args[i],
408
+ (grpc_integer_options){DEFAULT_KEEPALIVE_TIME_SECOND, 1, INT_MAX});
409
+ t->keepalive_time = value == INT_MAX
410
+ ? gpr_inf_future(GPR_TIMESPAN)
411
+ : gpr_time_from_seconds(value, GPR_TIMESPAN);
412
+ } else if (0 == strcmp(channel_args->args[i].key,
413
+ GRPC_ARG_HTTP2_KEEPALIVE_TIMEOUT)) {
414
+ const int value = grpc_channel_arg_get_integer(
415
+ &channel_args->args[i],
416
+ (grpc_integer_options){DEFAULT_KEEPALIVE_TIMEOUT_SECOND, 0,
417
+ INT_MAX});
418
+ t->keepalive_timeout = value == INT_MAX
419
+ ? gpr_inf_future(GPR_TIMESPAN)
420
+ : gpr_time_from_seconds(value, GPR_TIMESPAN);
421
+ } else if (0 == strcmp(channel_args->args[i].key,
422
+ GRPC_ARG_HTTP2_KEEPALIVE_PERMIT_WITHOUT_CALLS)) {
423
+ t->keepalive_permit_without_calls =
424
+ (uint32_t)grpc_channel_arg_get_integer(
425
+ &channel_args->args[i], (grpc_integer_options){0, 0, 1});
330
426
  } else {
331
427
  static const struct {
332
428
  const char *channel_arg_name;
333
429
  grpc_chttp2_setting_id setting_id;
334
430
  grpc_integer_options integer_options;
335
431
  bool availability[2] /* server, client */;
336
- } settings_map[] = {
337
- {GRPC_ARG_MAX_CONCURRENT_STREAMS,
338
- GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS,
339
- {-1, 0, INT_MAX},
340
- {true, false}},
341
- {GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER,
342
- GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE,
343
- {-1, 0, INT_MAX},
344
- {true, true}},
345
- {GRPC_ARG_MAX_METADATA_SIZE,
346
- GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE,
347
- {-1, 0, INT_MAX},
348
- {true, true}},
349
- {GRPC_ARG_HTTP2_MAX_FRAME_SIZE,
350
- GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE,
351
- {-1, 16384, 16777215},
352
- {true, true}},
353
- };
432
+ } settings_map[] = {{GRPC_ARG_MAX_CONCURRENT_STREAMS,
433
+ GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS,
434
+ {-1, 0, INT32_MAX},
435
+ {true, false}},
436
+ {GRPC_ARG_HTTP2_HPACK_TABLE_SIZE_DECODER,
437
+ GRPC_CHTTP2_SETTINGS_HEADER_TABLE_SIZE,
438
+ {-1, 0, INT32_MAX},
439
+ {true, true}},
440
+ {GRPC_ARG_MAX_METADATA_SIZE,
441
+ GRPC_CHTTP2_SETTINGS_MAX_HEADER_LIST_SIZE,
442
+ {-1, 0, INT32_MAX},
443
+ {true, true}},
444
+ {GRPC_ARG_HTTP2_MAX_FRAME_SIZE,
445
+ GRPC_CHTTP2_SETTINGS_MAX_FRAME_SIZE,
446
+ {-1, 16384, 16777215},
447
+ {true, true}},
448
+ {GRPC_ARG_HTTP2_STREAM_LOOKAHEAD_BYTES,
449
+ GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE,
450
+ {-1, 5, INT32_MAX},
451
+ {true, true}}};
354
452
  for (j = 0; j < (int)GPR_ARRAY_SIZE(settings_map); j++) {
355
453
  if (0 == strcmp(channel_args->args[i].key,
356
454
  settings_map[j].channel_arg_name)) {
@@ -373,6 +471,19 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
373
471
  }
374
472
  }
375
473
 
474
+ t->ping_state.pings_before_data_required =
475
+ t->ping_policy.max_pings_without_data;
476
+
477
+ /** Start client-side keepalive pings */
478
+ if (t->is_client) {
479
+ t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_WAITING;
480
+ GRPC_CHTTP2_REF_TRANSPORT(t, "init keepalive ping");
481
+ grpc_timer_init(
482
+ exec_ctx, &t->keepalive_ping_timer,
483
+ gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), t->keepalive_time),
484
+ &t->init_keepalive_ping_locked, gpr_now(GPR_CLOCK_MONOTONIC));
485
+ }
486
+
376
487
  grpc_chttp2_initiate_write(exec_ctx, t, false, "init");
377
488
  post_benign_reclaimer(exec_ctx, t);
378
489
  }
@@ -400,6 +511,10 @@ static void close_transport_locked(grpc_exec_ctx *exec_ctx,
400
511
  grpc_chttp2_transport *t,
401
512
  grpc_error *error) {
402
513
  if (!t->closed) {
514
+ if (!grpc_error_has_clear_grpc_status(error)) {
515
+ error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS,
516
+ GRPC_STATUS_UNAVAILABLE);
517
+ }
403
518
  if (t->write_state != GRPC_CHTTP2_WRITE_STATE_IDLE) {
404
519
  if (t->close_transport_on_writes_finished == NULL) {
405
520
  t->close_transport_on_writes_finished =
@@ -409,14 +524,26 @@ static void close_transport_locked(grpc_exec_ctx *exec_ctx,
409
524
  grpc_error_add_child(t->close_transport_on_writes_finished, error);
410
525
  return;
411
526
  }
412
- if (!grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, NULL)) {
413
- error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS,
414
- GRPC_STATUS_UNAVAILABLE);
415
- }
416
527
  t->closed = 1;
417
528
  connectivity_state_set(exec_ctx, t, GRPC_CHANNEL_SHUTDOWN,
418
529
  GRPC_ERROR_REF(error), "close_transport");
419
- grpc_endpoint_shutdown(exec_ctx, t->ep);
530
+ grpc_endpoint_shutdown(exec_ctx, t->ep, GRPC_ERROR_REF(error));
531
+ if (t->is_client) {
532
+ switch (t->keepalive_state) {
533
+ case GRPC_CHTTP2_KEEPALIVE_STATE_WAITING: {
534
+ grpc_timer_cancel(exec_ctx, &t->keepalive_ping_timer);
535
+ break;
536
+ }
537
+ case GRPC_CHTTP2_KEEPALIVE_STATE_PINGING: {
538
+ grpc_timer_cancel(exec_ctx, &t->keepalive_ping_timer);
539
+ grpc_timer_cancel(exec_ctx, &t->keepalive_watchdog_timer);
540
+ break;
541
+ }
542
+ case GRPC_CHTTP2_KEEPALIVE_STATE_DYING: {
543
+ break;
544
+ }
545
+ }
546
+ }
420
547
 
421
548
  /* flush writable stream list to avoid dangling references */
422
549
  grpc_chttp2_stream *s;
@@ -424,6 +551,7 @@ static void close_transport_locked(grpc_exec_ctx *exec_ctx,
424
551
  GRPC_CHTTP2_STREAM_UNREF(exec_ctx, s, "chttp2_writing:close");
425
552
  }
426
553
  end_all_the_calls(exec_ctx, t, GRPC_ERROR_REF(error));
554
+ cancel_pings(exec_ctx, t, GRPC_ERROR_REF(error));
427
555
  }
428
556
  GRPC_ERROR_UNREF(error);
429
557
  }
@@ -452,8 +580,6 @@ static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
452
580
  grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
453
581
  grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs;
454
582
 
455
- memset(s, 0, sizeof(*s));
456
-
457
583
  s->t = t;
458
584
  s->refcount = refcount;
459
585
  /* We reserve one 'active stream' that's dropped when the stream is
@@ -474,11 +600,6 @@ static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
474
600
 
475
601
  if (server_data) {
476
602
  s->id = (uint32_t)(uintptr_t)server_data;
477
- s->outgoing_window = t->settings[GRPC_PEER_SETTINGS]
478
- [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
479
- s->incoming_window = s->max_recv_bytes =
480
- t->settings[GRPC_SENT_SETTINGS]
481
- [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
482
603
  *t->accepting_stream = s;
483
604
  grpc_chttp2_stream_map_add(&t->stream_map, s->id, s);
484
605
  post_destructive_reclaimer(exec_ctx, t);
@@ -507,6 +628,7 @@ static void destroy_stream_locked(grpc_exec_ctx *exec_ctx, void *sp,
507
628
  }
508
629
 
509
630
  grpc_chttp2_list_remove_stalled_by_transport(t, s);
631
+ grpc_chttp2_list_remove_stalled_by_stream(t, s);
510
632
 
511
633
  for (int i = 0; i < STREAM_LIST_COUNT; i++) {
512
634
  if (s->included[i]) {
@@ -531,6 +653,14 @@ static void destroy_stream_locked(grpc_exec_ctx *exec_ctx, void *sp,
531
653
  GRPC_ERROR_UNREF(s->read_closed_error);
532
654
  GRPC_ERROR_UNREF(s->write_closed_error);
533
655
 
656
+ if (s->incoming_window_delta > 0) {
657
+ GRPC_CHTTP2_FLOW_DEBIT_STREAM_INCOMING_WINDOW_DELTA(
658
+ "destroy", t, s, s->incoming_window_delta);
659
+ } else if (s->incoming_window_delta < 0) {
660
+ GRPC_CHTTP2_FLOW_CREDIT_STREAM_INCOMING_WINDOW_DELTA(
661
+ "destroy", t, s, -s->incoming_window_delta);
662
+ }
663
+
534
664
  GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "stream");
535
665
 
536
666
  GPR_TIMER_END("destroy_stream", 0);
@@ -646,13 +776,21 @@ void grpc_chttp2_initiate_write(grpc_exec_ctx *exec_ctx,
646
776
  GPR_TIMER_END("grpc_chttp2_initiate_write", 0);
647
777
  }
648
778
 
649
- void grpc_chttp2_become_writable(grpc_exec_ctx *exec_ctx,
650
- grpc_chttp2_transport *t,
651
- grpc_chttp2_stream *s, bool covered_by_poller,
652
- const char *reason) {
779
+ void grpc_chttp2_become_writable(
780
+ grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s,
781
+ grpc_chttp2_stream_write_type stream_write_type, const char *reason) {
653
782
  if (!t->closed && grpc_chttp2_list_add_writable_stream(t, s)) {
654
783
  GRPC_CHTTP2_STREAM_REF(s, "chttp2_writing:become");
655
- grpc_chttp2_initiate_write(exec_ctx, t, covered_by_poller, reason);
784
+ }
785
+ switch (stream_write_type) {
786
+ case GRPC_CHTTP2_STREAM_WRITE_PIGGYBACK:
787
+ break;
788
+ case GRPC_CHTTP2_STREAM_WRITE_INITIATE_COVERED:
789
+ grpc_chttp2_initiate_write(exec_ctx, t, true, reason);
790
+ break;
791
+ case GRPC_CHTTP2_STREAM_WRITE_INITIATE_UNCOVERED:
792
+ grpc_chttp2_initiate_write(exec_ctx, t, false, reason);
793
+ break;
656
794
  }
657
795
  }
658
796
 
@@ -780,7 +918,6 @@ void grpc_chttp2_add_incoming_goaway(grpc_exec_ctx *exec_ctx,
780
918
  static void maybe_start_some_streams(grpc_exec_ctx *exec_ctx,
781
919
  grpc_chttp2_transport *t) {
782
920
  grpc_chttp2_stream *s;
783
- uint32_t stream_incoming_window;
784
921
  /* start streams where we have free grpc_chttp2_stream ids and free
785
922
  * concurrency */
786
923
  while (t->next_stream_id <= MAX_CLIENT_STREAM_ID &&
@@ -803,15 +940,11 @@ static void maybe_start_some_streams(grpc_exec_ctx *exec_ctx,
803
940
  "no_more_stream_ids");
804
941
  }
805
942
 
806
- s->outgoing_window = t->settings[GRPC_PEER_SETTINGS]
807
- [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
808
- s->incoming_window = stream_incoming_window =
809
- t->settings[GRPC_SENT_SETTINGS]
810
- [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
811
- s->max_recv_bytes = GPR_MAX(stream_incoming_window, s->max_recv_bytes);
812
943
  grpc_chttp2_stream_map_add(&t->stream_map, s->id, s);
813
944
  post_destructive_reclaimer(exec_ctx, t);
814
- grpc_chttp2_become_writable(exec_ctx, t, s, true, "new_stream");
945
+ grpc_chttp2_become_writable(exec_ctx, t, s,
946
+ GRPC_CHTTP2_STREAM_WRITE_INITIATE_COVERED,
947
+ "new_stream");
815
948
  }
816
949
  /* cancel out streams that will never be started */
817
950
  while (t->next_stream_id >= MAX_CLIENT_STREAM_ID &&
@@ -866,7 +999,6 @@ void grpc_chttp2_complete_closure_step(grpc_exec_ctx *exec_ctx,
866
999
  (int)(closure->next_data.scratch / CLOSURE_BARRIER_FIRST_REF_BIT),
867
1000
  (int)(closure->next_data.scratch % CLOSURE_BARRIER_FIRST_REF_BIT),
868
1001
  desc, errstr);
869
- grpc_error_free_string(errstr);
870
1002
  }
871
1003
  if (error != GRPC_ERROR_NONE) {
872
1004
  if (closure->error_data.error == GRPC_ERROR_NONE) {
@@ -895,12 +1027,9 @@ void grpc_chttp2_complete_closure_step(grpc_exec_ctx *exec_ctx,
895
1027
  }
896
1028
 
897
1029
  static bool contains_non_ok_status(grpc_metadata_batch *batch) {
898
- grpc_linked_mdelem *l;
899
- for (l = batch->list.head; l; l = l->next) {
900
- if (l->md->key == GRPC_MDSTR_GRPC_STATUS &&
901
- l->md != GRPC_MDELEM_GRPC_STATUS_0) {
902
- return true;
903
- }
1030
+ if (batch->idx.named.grpc_status != NULL) {
1031
+ return !grpc_mdelem_eq(batch->idx.named.grpc_status->md,
1032
+ GRPC_MDELEM_GRPC_STATUS_0);
904
1033
  }
905
1034
  return false;
906
1035
  }
@@ -910,7 +1039,9 @@ static void maybe_become_writable_due_to_send_msg(grpc_exec_ctx *exec_ctx,
910
1039
  grpc_chttp2_stream *s) {
911
1040
  if (s->id != 0 && (!s->write_buffering ||
912
1041
  s->flow_controlled_buffer.length > t->write_buffer_size)) {
913
- grpc_chttp2_become_writable(exec_ctx, t, s, true, "op.send_message");
1042
+ grpc_chttp2_become_writable(exec_ctx, t, s,
1043
+ GRPC_CHTTP2_STREAM_WRITE_INITIATE_COVERED,
1044
+ "op.send_message");
914
1045
  }
915
1046
  }
916
1047
 
@@ -980,9 +1111,12 @@ static void log_metadata(const grpc_metadata_batch *md_batch, uint32_t id,
980
1111
  bool is_client, bool is_initial) {
981
1112
  for (grpc_linked_mdelem *md = md_batch->list.head; md != md_batch->list.tail;
982
1113
  md = md->next) {
1114
+ char *key = grpc_slice_to_c_string(GRPC_MDKEY(md->md));
1115
+ char *value = grpc_slice_to_c_string(GRPC_MDVALUE(md->md));
983
1116
  gpr_log(GPR_INFO, "HTTP:%d:%s:%s: %s: %s", id, is_initial ? "HDR" : "TRL",
984
- is_client ? "CLI" : "SVR", grpc_mdstr_as_c_string(md->md->key),
985
- grpc_mdstr_as_c_string(md->md->value));
1117
+ is_client ? "CLI" : "SVR", key, value);
1118
+ gpr_free(key);
1119
+ gpr_free(value);
986
1120
  }
987
1121
  }
988
1122
 
@@ -991,8 +1125,8 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op,
991
1125
  GPR_TIMER_BEGIN("perform_stream_op_locked", 0);
992
1126
 
993
1127
  grpc_transport_stream_op *op = stream_op;
994
- grpc_chttp2_transport *t = op->transport_private.args[0];
995
- grpc_chttp2_stream *s = op->transport_private.args[1];
1128
+ grpc_chttp2_transport *t = op->handler_private.args[0];
1129
+ grpc_chttp2_stream *s = op->handler_private.args[1];
996
1130
 
997
1131
  if (grpc_http_trace) {
998
1132
  char *str = grpc_transport_stream_op_string(op);
@@ -1025,11 +1159,7 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op,
1025
1159
  }
1026
1160
 
1027
1161
  if (op->cancel_error != GRPC_ERROR_NONE) {
1028
- grpc_chttp2_cancel_stream(exec_ctx, t, s, GRPC_ERROR_REF(op->cancel_error));
1029
- }
1030
-
1031
- if (op->close_error != GRPC_ERROR_NONE) {
1032
- close_from_api(exec_ctx, t, s, GRPC_ERROR_REF(op->close_error));
1162
+ grpc_chttp2_cancel_stream(exec_ctx, t, s, op->cancel_error);
1033
1163
  }
1034
1164
 
1035
1165
  if (op->send_initial_metadata != NULL) {
@@ -1068,20 +1198,25 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op,
1068
1198
  grpc_chttp2_list_add_waiting_for_concurrency(t, s);
1069
1199
  maybe_start_some_streams(exec_ctx, t);
1070
1200
  } else {
1071
- grpc_chttp2_cancel_stream(exec_ctx, t, s,
1072
- GRPC_ERROR_CREATE("Transport closed"));
1201
+ grpc_chttp2_cancel_stream(
1202
+ exec_ctx, t, s,
1203
+ grpc_error_set_int(GRPC_ERROR_CREATE("Transport closed"),
1204
+ GRPC_ERROR_INT_GRPC_STATUS,
1205
+ GRPC_STATUS_UNAVAILABLE));
1073
1206
  }
1074
1207
  } else {
1075
1208
  GPR_ASSERT(s->id != 0);
1076
- grpc_chttp2_become_writable(exec_ctx, t, s, true,
1209
+ grpc_chttp2_become_writable(exec_ctx, t, s,
1210
+ GRPC_CHTTP2_STREAM_WRITE_INITIATE_COVERED,
1077
1211
  "op.send_initial_metadata");
1078
1212
  }
1079
1213
  } else {
1080
1214
  s->send_initial_metadata = NULL;
1081
1215
  grpc_chttp2_complete_closure_step(
1082
1216
  exec_ctx, t, s, &s->send_initial_metadata_finished,
1083
- GRPC_ERROR_CREATE(
1084
- "Attempt to send initial metadata after stream was closed"),
1217
+ GRPC_ERROR_CREATE_REFERENCING(
1218
+ "Attempt to send initial metadata after stream was closed",
1219
+ &s->write_closed_error, 1),
1085
1220
  "send_initial_metadata_finished");
1086
1221
  }
1087
1222
  }
@@ -1093,7 +1228,9 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op,
1093
1228
  if (s->write_closed) {
1094
1229
  grpc_chttp2_complete_closure_step(
1095
1230
  exec_ctx, t, s, &s->fetching_send_message_finished,
1096
- GRPC_ERROR_CREATE("Attempt to send message after stream was closed"),
1231
+ GRPC_ERROR_CREATE_REFERENCING(
1232
+ "Attempt to send message after stream was closed",
1233
+ &s->write_closed_error, 1),
1097
1234
  "fetching_send_message_finished");
1098
1235
  } else {
1099
1236
  GPR_ASSERT(s->fetching_send_message == NULL);
@@ -1161,7 +1298,8 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op,
1161
1298
  } else if (s->id != 0) {
1162
1299
  /* TODO(ctiller): check if there's flow control for any outstanding
1163
1300
  bytes before going writable */
1164
- grpc_chttp2_become_writable(exec_ctx, t, s, true,
1301
+ grpc_chttp2_become_writable(exec_ctx, t, s,
1302
+ GRPC_CHTTP2_STREAM_WRITE_INITIATE_COVERED,
1165
1303
  "op.send_trailing_metadata");
1166
1304
  }
1167
1305
  }
@@ -1180,8 +1318,7 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op,
1180
1318
  s->recv_message = op->recv_message;
1181
1319
  if (s->id != 0 &&
1182
1320
  (s->incoming_frames.head == NULL || s->incoming_frames.head->is_tail)) {
1183
- incoming_byte_stream_update_flow_control(exec_ctx, t, s,
1184
- t->stream_lookahead, 0);
1321
+ incoming_byte_stream_update_flow_control(exec_ctx, t, s, 5, 0);
1185
1322
  }
1186
1323
  grpc_chttp2_maybe_complete_recv_message(exec_ctx, t, s);
1187
1324
  }
@@ -1213,63 +1350,71 @@ static void perform_stream_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
1213
1350
  gpr_free(str);
1214
1351
  }
1215
1352
 
1216
- op->transport_private.args[0] = gt;
1217
- op->transport_private.args[1] = gs;
1353
+ op->handler_private.args[0] = gt;
1354
+ op->handler_private.args[1] = gs;
1218
1355
  GRPC_CHTTP2_STREAM_REF(s, "perform_stream_op");
1219
1356
  grpc_closure_sched(
1220
1357
  exec_ctx,
1221
1358
  grpc_closure_init(
1222
- &op->transport_private.closure, perform_stream_op_locked, op,
1359
+ &op->handler_private.closure, perform_stream_op_locked, op,
1223
1360
  grpc_combiner_scheduler(t->combiner, op->covered_by_poller)),
1224
1361
  GRPC_ERROR_NONE);
1225
1362
  GPR_TIMER_END("perform_stream_op", 0);
1226
1363
  }
1227
1364
 
1365
+ static void cancel_pings(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
1366
+ grpc_error *error) {
1367
+ /* callback remaining pings: they're not allowed to call into the transpot,
1368
+ and maybe they hold resources that need to be freed */
1369
+ for (size_t i = 0; i < GRPC_CHTTP2_PING_TYPE_COUNT; i++) {
1370
+ grpc_chttp2_ping_queue *pq = &t->ping_queues[i];
1371
+ for (size_t j = 0; j < GRPC_CHTTP2_PCL_COUNT; j++) {
1372
+ grpc_closure_list_fail_all(&pq->lists[j], GRPC_ERROR_REF(error));
1373
+ grpc_closure_list_sched(exec_ctx, &pq->lists[j]);
1374
+ }
1375
+ }
1376
+ GRPC_ERROR_UNREF(error);
1377
+ }
1378
+
1228
1379
  static void send_ping_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
1229
- grpc_closure *on_recv) {
1230
- grpc_chttp2_outstanding_ping *p = gpr_malloc(sizeof(*p));
1231
- p->next = &t->pings;
1232
- p->prev = p->next->prev;
1233
- p->prev->next = p->next->prev = p;
1234
- p->id[0] = (uint8_t)((t->ping_counter >> 56) & 0xff);
1235
- p->id[1] = (uint8_t)((t->ping_counter >> 48) & 0xff);
1236
- p->id[2] = (uint8_t)((t->ping_counter >> 40) & 0xff);
1237
- p->id[3] = (uint8_t)((t->ping_counter >> 32) & 0xff);
1238
- p->id[4] = (uint8_t)((t->ping_counter >> 24) & 0xff);
1239
- p->id[5] = (uint8_t)((t->ping_counter >> 16) & 0xff);
1240
- p->id[6] = (uint8_t)((t->ping_counter >> 8) & 0xff);
1241
- p->id[7] = (uint8_t)(t->ping_counter & 0xff);
1242
- t->ping_counter++;
1243
- p->on_recv = on_recv;
1244
- grpc_slice_buffer_add(&t->qbuf, grpc_chttp2_ping_create(0, p->id));
1245
- grpc_chttp2_initiate_write(exec_ctx, t, true, "send_ping");
1380
+ grpc_chttp2_ping_type ping_type,
1381
+ grpc_closure *on_initiate, grpc_closure *on_ack) {
1382
+ grpc_chttp2_ping_queue *pq = &t->ping_queues[ping_type];
1383
+ grpc_closure_list_append(&pq->lists[GRPC_CHTTP2_PCL_INITIATE], on_initiate,
1384
+ GRPC_ERROR_NONE);
1385
+ if (grpc_closure_list_append(&pq->lists[GRPC_CHTTP2_PCL_NEXT], on_ack,
1386
+ GRPC_ERROR_NONE)) {
1387
+ grpc_chttp2_initiate_write(exec_ctx, t, false, "send_ping");
1388
+ }
1246
1389
  }
1247
1390
 
1248
1391
  void grpc_chttp2_ack_ping(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
1249
- const uint8_t *opaque_8bytes) {
1250
- grpc_chttp2_outstanding_ping *ping;
1251
- for (ping = t->pings.next; ping != &t->pings; ping = ping->next) {
1252
- if (0 == memcmp(opaque_8bytes, ping->id, 8)) {
1253
- grpc_closure_sched(exec_ctx, ping->on_recv, GRPC_ERROR_NONE);
1254
- ping->next->prev = ping->prev;
1255
- ping->prev->next = ping->next;
1256
- gpr_free(ping);
1257
- return;
1258
- }
1392
+ uint64_t id) {
1393
+ grpc_chttp2_ping_queue *pq =
1394
+ &t->ping_queues[id % GRPC_CHTTP2_PING_TYPE_COUNT];
1395
+ if (pq->inflight_id != id) {
1396
+ char *from = grpc_endpoint_get_peer(t->ep);
1397
+ gpr_log(GPR_DEBUG, "Unknown ping response from %s: %" PRIx64, from, id);
1398
+ gpr_free(from);
1399
+ return;
1400
+ }
1401
+ grpc_closure_list_sched(exec_ctx, &pq->lists[GRPC_CHTTP2_PCL_INFLIGHT]);
1402
+ if (!grpc_closure_list_empty(pq->lists[GRPC_CHTTP2_PCL_NEXT])) {
1403
+ grpc_chttp2_initiate_write(exec_ctx, t, false, "continue_pings");
1259
1404
  }
1260
- char *msg = gpr_dump((const char *)opaque_8bytes, 8, GPR_DUMP_HEX);
1261
- char *from = grpc_endpoint_get_peer(t->ep);
1262
- gpr_log(GPR_DEBUG, "Unknown ping response from %s: %s", from, msg);
1263
- gpr_free(from);
1264
- gpr_free(msg);
1265
1405
  }
1266
1406
 
1267
1407
  static void send_goaway(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
1268
- grpc_chttp2_error_code error, grpc_slice data) {
1408
+ grpc_error *error) {
1269
1409
  t->sent_goaway_state = GRPC_CHTTP2_GOAWAY_SEND_SCHEDULED;
1270
- grpc_chttp2_goaway_append(t->last_new_stream_id, (uint32_t)error, data,
1271
- &t->qbuf);
1410
+ grpc_http2_error_code http_error;
1411
+ const char *msg;
1412
+ grpc_error_get_status(error, gpr_inf_future(GPR_CLOCK_MONOTONIC), NULL, &msg,
1413
+ &http_error);
1414
+ grpc_chttp2_goaway_append(t->last_new_stream_id, (uint32_t)http_error,
1415
+ grpc_slice_from_copied_string(msg), &t->qbuf);
1272
1416
  grpc_chttp2_initiate_write(exec_ctx, t, false, "goaway_sent");
1417
+ GRPC_ERROR_UNREF(error);
1273
1418
  }
1274
1419
 
1275
1420
  static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx,
@@ -1285,10 +1430,8 @@ static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx,
1285
1430
  op->on_connectivity_state_change);
1286
1431
  }
1287
1432
 
1288
- if (op->send_goaway) {
1289
- send_goaway(exec_ctx, t,
1290
- grpc_chttp2_grpc_status_to_http2_error(op->goaway_status),
1291
- grpc_slice_ref_internal(*op->goaway_message));
1433
+ if (op->goaway_error) {
1434
+ send_goaway(exec_ctx, t, op->goaway_error);
1292
1435
  }
1293
1436
 
1294
1437
  if (op->set_accept_stream) {
@@ -1306,7 +1449,8 @@ static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx,
1306
1449
  }
1307
1450
 
1308
1451
  if (op->send_ping) {
1309
- send_ping_locked(exec_ctx, t, op->send_ping);
1452
+ send_ping_locked(exec_ctx, t, GRPC_CHTTP2_PING_ON_NEXT_WRITE, NULL,
1453
+ op->send_ping);
1310
1454
  }
1311
1455
 
1312
1456
  if (close_transport != GRPC_ERROR_NONE) {
@@ -1348,8 +1492,8 @@ void grpc_chttp2_maybe_complete_recv_initial_metadata(grpc_exec_ctx *exec_ctx,
1348
1492
  incoming_byte_stream_destroy_locked(exec_ctx, bs, GRPC_ERROR_NONE);
1349
1493
  }
1350
1494
  }
1351
- grpc_chttp2_incoming_metadata_buffer_publish(&s->metadata_buffer[0],
1352
- s->recv_initial_metadata);
1495
+ grpc_chttp2_incoming_metadata_buffer_publish(
1496
+ exec_ctx, &s->metadata_buffer[0], s->recv_initial_metadata);
1353
1497
  null_then_run_closure(exec_ctx, &s->recv_initial_metadata_ready,
1354
1498
  GRPC_ERROR_NONE);
1355
1499
  }
@@ -1392,8 +1536,8 @@ void grpc_chttp2_maybe_complete_recv_trailing_metadata(grpc_exec_ctx *exec_ctx,
1392
1536
  }
1393
1537
  if (s->all_incoming_byte_streams_finished &&
1394
1538
  s->recv_trailing_metadata_finished != NULL) {
1395
- grpc_chttp2_incoming_metadata_buffer_publish(&s->metadata_buffer[1],
1396
- s->recv_trailing_metadata);
1539
+ grpc_chttp2_incoming_metadata_buffer_publish(
1540
+ exec_ctx, &s->metadata_buffer[1], s->recv_trailing_metadata);
1397
1541
  grpc_chttp2_complete_closure_step(
1398
1542
  exec_ctx, t, s, &s->recv_trailing_metadata_finished, GRPC_ERROR_NONE,
1399
1543
  "recv_trailing_metadata_finished");
@@ -1441,70 +1585,37 @@ static void remove_stream(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
1441
1585
  maybe_start_some_streams(exec_ctx, t);
1442
1586
  }
1443
1587
 
1444
- static void status_codes_from_error(grpc_error *error, gpr_timespec deadline,
1445
- grpc_chttp2_error_code *http2_error,
1446
- grpc_status_code *grpc_status) {
1447
- intptr_t ip_http;
1448
- intptr_t ip_grpc;
1449
- bool have_http =
1450
- grpc_error_get_int(error, GRPC_ERROR_INT_HTTP2_ERROR, &ip_http);
1451
- bool have_grpc =
1452
- grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, &ip_grpc);
1453
- if (have_http) {
1454
- *http2_error = (grpc_chttp2_error_code)ip_http;
1455
- } else if (have_grpc) {
1456
- *http2_error =
1457
- grpc_chttp2_grpc_status_to_http2_error((grpc_status_code)ip_grpc);
1458
- } else {
1459
- *http2_error = GRPC_CHTTP2_INTERNAL_ERROR;
1460
- }
1461
- if (have_grpc) {
1462
- *grpc_status = (grpc_status_code)ip_grpc;
1463
- } else if (have_http) {
1464
- *grpc_status = grpc_chttp2_http2_error_to_grpc_status(
1465
- (grpc_chttp2_error_code)ip_http, deadline);
1466
- } else {
1467
- *grpc_status = GRPC_STATUS_INTERNAL;
1468
- }
1469
- }
1470
-
1471
1588
  void grpc_chttp2_cancel_stream(grpc_exec_ctx *exec_ctx,
1472
1589
  grpc_chttp2_transport *t, grpc_chttp2_stream *s,
1473
1590
  grpc_error *due_to_error) {
1474
- if (!s->read_closed || !s->write_closed) {
1475
- grpc_status_code grpc_status;
1476
- grpc_chttp2_error_code http_error;
1477
- status_codes_from_error(due_to_error, s->deadline, &http_error,
1478
- &grpc_status);
1591
+ if (!t->is_client && !s->sent_trailing_metadata &&
1592
+ grpc_error_has_clear_grpc_status(due_to_error)) {
1593
+ close_from_api(exec_ctx, t, s, due_to_error);
1594
+ return;
1595
+ }
1479
1596
 
1597
+ if (!s->read_closed || !s->write_closed) {
1480
1598
  if (s->id != 0) {
1599
+ grpc_http2_error_code http_error;
1600
+ grpc_error_get_status(due_to_error, s->deadline, NULL, NULL, &http_error);
1481
1601
  grpc_slice_buffer_add(
1482
1602
  &t->qbuf, grpc_chttp2_rst_stream_create(s->id, (uint32_t)http_error,
1483
1603
  &s->stats.outgoing));
1484
1604
  grpc_chttp2_initiate_write(exec_ctx, t, false, "rst_stream");
1485
1605
  }
1486
-
1487
- const char *msg =
1488
- grpc_error_get_str(due_to_error, GRPC_ERROR_STR_GRPC_MESSAGE);
1489
- bool free_msg = false;
1490
- if (msg == NULL) {
1491
- free_msg = true;
1492
- msg = grpc_error_string(due_to_error);
1493
- }
1494
- grpc_slice msg_slice = grpc_slice_from_copied_string(msg);
1495
- grpc_chttp2_fake_status(exec_ctx, t, s, grpc_status, &msg_slice);
1496
- if (free_msg) grpc_error_free_string(msg);
1497
1606
  }
1498
1607
  if (due_to_error != GRPC_ERROR_NONE && !s->seen_error) {
1499
1608
  s->seen_error = true;
1500
- grpc_chttp2_maybe_complete_recv_trailing_metadata(exec_ctx, t, s);
1501
1609
  }
1502
1610
  grpc_chttp2_mark_stream_closed(exec_ctx, t, s, 1, 1, due_to_error);
1503
1611
  }
1504
1612
 
1505
1613
  void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
1506
- grpc_chttp2_stream *s, grpc_status_code status,
1507
- grpc_slice *slice) {
1614
+ grpc_chttp2_stream *s, grpc_error *error) {
1615
+ grpc_status_code status;
1616
+ const char *msg;
1617
+ grpc_error_get_status(error, s->deadline, &status, &msg, NULL);
1618
+
1508
1619
  if (status != GRPC_STATUS_OK) {
1509
1620
  s->seen_error = true;
1510
1621
  }
@@ -1518,24 +1629,21 @@ void grpc_chttp2_fake_status(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
1518
1629
  s->recv_trailing_metadata_finished != NULL) {
1519
1630
  char status_string[GPR_LTOA_MIN_BUFSIZE];
1520
1631
  gpr_ltoa(status, status_string);
1521
- grpc_chttp2_incoming_metadata_buffer_add(
1522
- &s->metadata_buffer[1], grpc_mdelem_from_metadata_strings(
1523
- exec_ctx, GRPC_MDSTR_GRPC_STATUS,
1524
- grpc_mdstr_from_string(status_string)));
1525
- if (slice) {
1526
- grpc_chttp2_incoming_metadata_buffer_add(
1527
- &s->metadata_buffer[1],
1528
- grpc_mdelem_from_metadata_strings(
1529
- exec_ctx, GRPC_MDSTR_GRPC_MESSAGE,
1530
- grpc_mdstr_from_slice(exec_ctx,
1531
- grpc_slice_ref_internal(*slice))));
1632
+ grpc_chttp2_incoming_metadata_buffer_replace_or_add(
1633
+ exec_ctx, &s->metadata_buffer[1],
1634
+ grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_GRPC_STATUS,
1635
+ grpc_slice_from_copied_string(status_string)));
1636
+ if (msg != NULL) {
1637
+ grpc_chttp2_incoming_metadata_buffer_replace_or_add(
1638
+ exec_ctx, &s->metadata_buffer[1],
1639
+ grpc_mdelem_from_slices(exec_ctx, GRPC_MDSTR_GRPC_MESSAGE,
1640
+ grpc_slice_from_copied_string(msg)));
1532
1641
  }
1533
1642
  s->published_metadata[1] = GRPC_METADATA_SYNTHESIZED_FROM_FAKE;
1534
1643
  grpc_chttp2_maybe_complete_recv_trailing_metadata(exec_ctx, t, s);
1535
1644
  }
1536
- if (slice) {
1537
- grpc_slice_unref_internal(exec_ctx, *slice);
1538
- }
1645
+
1646
+ GRPC_ERROR_UNREF(error);
1539
1647
  }
1540
1648
 
1541
1649
  static void add_error(grpc_error *error, grpc_error **refs, size_t *nrefs) {
@@ -1601,36 +1709,48 @@ void grpc_chttp2_mark_stream_closed(grpc_exec_ctx *exec_ctx,
1601
1709
  int close_writes, grpc_error *error) {
1602
1710
  if (s->read_closed && s->write_closed) {
1603
1711
  /* already closed */
1712
+ grpc_chttp2_maybe_complete_recv_trailing_metadata(exec_ctx, t, s);
1604
1713
  GRPC_ERROR_UNREF(error);
1605
1714
  return;
1606
1715
  }
1716
+ bool closed_read = false;
1717
+ bool became_closed = false;
1607
1718
  if (close_reads && !s->read_closed) {
1608
1719
  s->read_closed_error = GRPC_ERROR_REF(error);
1609
1720
  s->read_closed = true;
1610
- for (int i = 0; i < 2; i++) {
1611
- if (s->published_metadata[i] == GRPC_METADATA_NOT_PUBLISHED) {
1612
- s->published_metadata[i] = GPRC_METADATA_PUBLISHED_AT_CLOSE;
1613
- }
1614
- }
1615
- decrement_active_streams_locked(exec_ctx, t, s);
1616
- grpc_chttp2_maybe_complete_recv_initial_metadata(exec_ctx, t, s);
1617
- grpc_chttp2_maybe_complete_recv_message(exec_ctx, t, s);
1618
- grpc_chttp2_maybe_complete_recv_trailing_metadata(exec_ctx, t, s);
1721
+ closed_read = true;
1619
1722
  }
1620
1723
  if (close_writes && !s->write_closed) {
1621
1724
  s->write_closed_error = GRPC_ERROR_REF(error);
1622
1725
  s->write_closed = true;
1623
1726
  grpc_chttp2_fail_pending_writes(exec_ctx, t, s, GRPC_ERROR_REF(error));
1624
- grpc_chttp2_maybe_complete_recv_trailing_metadata(exec_ctx, t, s);
1625
1727
  }
1626
1728
  if (s->read_closed && s->write_closed) {
1729
+ became_closed = true;
1730
+ grpc_error *overall_error =
1731
+ removal_error(GRPC_ERROR_REF(error), s, "Stream removed");
1627
1732
  if (s->id != 0) {
1628
- remove_stream(exec_ctx, t, s->id,
1629
- removal_error(GRPC_ERROR_REF(error), s, "Stream removed"));
1733
+ remove_stream(exec_ctx, t, s->id, GRPC_ERROR_REF(overall_error));
1630
1734
  } else {
1631
1735
  /* Purge streams waiting on concurrency still waiting for id assignment */
1632
1736
  grpc_chttp2_list_remove_waiting_for_concurrency(t, s);
1633
1737
  }
1738
+ if (overall_error != GRPC_ERROR_NONE) {
1739
+ grpc_chttp2_fake_status(exec_ctx, t, s, overall_error);
1740
+ }
1741
+ }
1742
+ if (closed_read) {
1743
+ for (int i = 0; i < 2; i++) {
1744
+ if (s->published_metadata[i] == GRPC_METADATA_NOT_PUBLISHED) {
1745
+ s->published_metadata[i] = GPRC_METADATA_PUBLISHED_AT_CLOSE;
1746
+ }
1747
+ }
1748
+ decrement_active_streams_locked(exec_ctx, t, s);
1749
+ grpc_chttp2_maybe_complete_recv_initial_metadata(exec_ctx, t, s);
1750
+ grpc_chttp2_maybe_complete_recv_message(exec_ctx, t, s);
1751
+ }
1752
+ if (became_closed) {
1753
+ grpc_chttp2_maybe_complete_recv_trailing_metadata(exec_ctx, t, s);
1634
1754
  GRPC_CHTTP2_STREAM_UNREF(exec_ctx, s, "chttp2");
1635
1755
  }
1636
1756
  GRPC_ERROR_UNREF(error);
@@ -1644,112 +1764,92 @@ static void close_from_api(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
1644
1764
  uint8_t *p;
1645
1765
  uint32_t len = 0;
1646
1766
  grpc_status_code grpc_status;
1647
- grpc_chttp2_error_code http_error;
1648
- status_codes_from_error(error, s->deadline, &http_error, &grpc_status);
1767
+ const char *msg;
1768
+ grpc_error_get_status(error, s->deadline, &grpc_status, &msg, NULL);
1649
1769
 
1650
1770
  GPR_ASSERT(grpc_status >= 0 && (int)grpc_status < 100);
1651
1771
 
1652
- if (s->id != 0 && !t->is_client) {
1653
- /* Hand roll a header block.
1654
- This is unnecessarily ugly - at some point we should find a more
1655
- elegant
1656
- solution.
1657
- It's complicated by the fact that our send machinery would be dead by
1658
- the
1659
- time we got around to sending this, so instead we ignore HPACK
1660
- compression
1661
- and just write the uncompressed bytes onto the wire. */
1662
- status_hdr = grpc_slice_malloc(15 + (grpc_status >= 10));
1663
- p = GRPC_SLICE_START_PTR(status_hdr);
1664
- *p++ = 0x40; /* literal header */
1665
- *p++ = 11; /* len(grpc-status) */
1772
+ /* Hand roll a header block.
1773
+ This is unnecessarily ugly - at some point we should find a more
1774
+ elegant solution.
1775
+ It's complicated by the fact that our send machinery would be dead by
1776
+ the time we got around to sending this, so instead we ignore HPACK
1777
+ compression and just write the uncompressed bytes onto the wire. */
1778
+ status_hdr = grpc_slice_malloc(15 + (grpc_status >= 10));
1779
+ p = GRPC_SLICE_START_PTR(status_hdr);
1780
+ *p++ = 0x00; /* literal header, not indexed */
1781
+ *p++ = 11; /* len(grpc-status) */
1782
+ *p++ = 'g';
1783
+ *p++ = 'r';
1784
+ *p++ = 'p';
1785
+ *p++ = 'c';
1786
+ *p++ = '-';
1787
+ *p++ = 's';
1788
+ *p++ = 't';
1789
+ *p++ = 'a';
1790
+ *p++ = 't';
1791
+ *p++ = 'u';
1792
+ *p++ = 's';
1793
+ if (grpc_status < 10) {
1794
+ *p++ = 1;
1795
+ *p++ = (uint8_t)('0' + grpc_status);
1796
+ } else {
1797
+ *p++ = 2;
1798
+ *p++ = (uint8_t)('0' + (grpc_status / 10));
1799
+ *p++ = (uint8_t)('0' + (grpc_status % 10));
1800
+ }
1801
+ GPR_ASSERT(p == GRPC_SLICE_END_PTR(status_hdr));
1802
+ len += (uint32_t)GRPC_SLICE_LENGTH(status_hdr);
1803
+
1804
+ if (msg != NULL) {
1805
+ size_t msg_len = strlen(msg);
1806
+ GPR_ASSERT(msg_len <= UINT32_MAX);
1807
+ uint32_t msg_len_len = GRPC_CHTTP2_VARINT_LENGTH((uint32_t)msg_len, 0);
1808
+ message_pfx = grpc_slice_malloc(14 + msg_len_len);
1809
+ p = GRPC_SLICE_START_PTR(message_pfx);
1810
+ *p++ = 0x00; /* literal header, not indexed */
1811
+ *p++ = 12; /* len(grpc-message) */
1666
1812
  *p++ = 'g';
1667
1813
  *p++ = 'r';
1668
1814
  *p++ = 'p';
1669
1815
  *p++ = 'c';
1670
1816
  *p++ = '-';
1817
+ *p++ = 'm';
1818
+ *p++ = 'e';
1671
1819
  *p++ = 's';
1672
- *p++ = 't';
1673
- *p++ = 'a';
1674
- *p++ = 't';
1675
- *p++ = 'u';
1676
1820
  *p++ = 's';
1677
- if (grpc_status < 10) {
1678
- *p++ = 1;
1679
- *p++ = (uint8_t)('0' + grpc_status);
1680
- } else {
1681
- *p++ = 2;
1682
- *p++ = (uint8_t)('0' + (grpc_status / 10));
1683
- *p++ = (uint8_t)('0' + (grpc_status % 10));
1684
- }
1685
- GPR_ASSERT(p == GRPC_SLICE_END_PTR(status_hdr));
1686
- len += (uint32_t)GRPC_SLICE_LENGTH(status_hdr);
1687
-
1688
- const char *optional_message =
1689
- grpc_error_get_str(error, GRPC_ERROR_STR_GRPC_MESSAGE);
1690
-
1691
- if (optional_message != NULL) {
1692
- size_t msg_len = strlen(optional_message);
1693
- GPR_ASSERT(msg_len <= UINT32_MAX);
1694
- uint32_t msg_len_len = GRPC_CHTTP2_VARINT_LENGTH((uint32_t)msg_len, 0);
1695
- message_pfx = grpc_slice_malloc(14 + msg_len_len);
1696
- p = GRPC_SLICE_START_PTR(message_pfx);
1697
- *p++ = 0x40;
1698
- *p++ = 12; /* len(grpc-message) */
1699
- *p++ = 'g';
1700
- *p++ = 'r';
1701
- *p++ = 'p';
1702
- *p++ = 'c';
1703
- *p++ = '-';
1704
- *p++ = 'm';
1705
- *p++ = 'e';
1706
- *p++ = 's';
1707
- *p++ = 's';
1708
- *p++ = 'a';
1709
- *p++ = 'g';
1710
- *p++ = 'e';
1711
- GRPC_CHTTP2_WRITE_VARINT((uint32_t)msg_len, 0, 0, p,
1712
- (uint32_t)msg_len_len);
1713
- p += msg_len_len;
1714
- GPR_ASSERT(p == GRPC_SLICE_END_PTR(message_pfx));
1715
- len += (uint32_t)GRPC_SLICE_LENGTH(message_pfx);
1716
- len += (uint32_t)msg_len;
1717
- }
1718
-
1719
- hdr = grpc_slice_malloc(9);
1720
- p = GRPC_SLICE_START_PTR(hdr);
1721
- *p++ = (uint8_t)(len >> 16);
1722
- *p++ = (uint8_t)(len >> 8);
1723
- *p++ = (uint8_t)(len);
1724
- *p++ = GRPC_CHTTP2_FRAME_HEADER;
1725
- *p++ = GRPC_CHTTP2_DATA_FLAG_END_STREAM | GRPC_CHTTP2_DATA_FLAG_END_HEADERS;
1726
- *p++ = (uint8_t)(s->id >> 24);
1727
- *p++ = (uint8_t)(s->id >> 16);
1728
- *p++ = (uint8_t)(s->id >> 8);
1729
- *p++ = (uint8_t)(s->id);
1730
- GPR_ASSERT(p == GRPC_SLICE_END_PTR(hdr));
1731
-
1732
- grpc_slice_buffer_add(&t->qbuf, hdr);
1733
- grpc_slice_buffer_add(&t->qbuf, status_hdr);
1734
- if (optional_message) {
1735
- grpc_slice_buffer_add(&t->qbuf, message_pfx);
1736
- grpc_slice_buffer_add(&t->qbuf,
1737
- grpc_slice_from_copied_string(optional_message));
1738
- }
1739
- grpc_slice_buffer_add(
1740
- &t->qbuf, grpc_chttp2_rst_stream_create(s->id, GRPC_CHTTP2_NO_ERROR,
1741
- &s->stats.outgoing));
1742
- }
1743
-
1744
- const char *msg = grpc_error_get_str(error, GRPC_ERROR_STR_GRPC_MESSAGE);
1745
- bool free_msg = false;
1746
- if (msg == NULL) {
1747
- free_msg = true;
1748
- msg = grpc_error_string(error);
1749
- }
1750
- grpc_slice msg_slice = grpc_slice_from_copied_string(msg);
1751
- grpc_chttp2_fake_status(exec_ctx, t, s, grpc_status, &msg_slice);
1752
- if (free_msg) grpc_error_free_string(msg);
1821
+ *p++ = 'a';
1822
+ *p++ = 'g';
1823
+ *p++ = 'e';
1824
+ GRPC_CHTTP2_WRITE_VARINT((uint32_t)msg_len, 0, 0, p, (uint32_t)msg_len_len);
1825
+ p += msg_len_len;
1826
+ GPR_ASSERT(p == GRPC_SLICE_END_PTR(message_pfx));
1827
+ len += (uint32_t)GRPC_SLICE_LENGTH(message_pfx);
1828
+ len += (uint32_t)msg_len;
1829
+ }
1830
+
1831
+ hdr = grpc_slice_malloc(9);
1832
+ p = GRPC_SLICE_START_PTR(hdr);
1833
+ *p++ = (uint8_t)(len >> 16);
1834
+ *p++ = (uint8_t)(len >> 8);
1835
+ *p++ = (uint8_t)(len);
1836
+ *p++ = GRPC_CHTTP2_FRAME_HEADER;
1837
+ *p++ = GRPC_CHTTP2_DATA_FLAG_END_STREAM | GRPC_CHTTP2_DATA_FLAG_END_HEADERS;
1838
+ *p++ = (uint8_t)(s->id >> 24);
1839
+ *p++ = (uint8_t)(s->id >> 16);
1840
+ *p++ = (uint8_t)(s->id >> 8);
1841
+ *p++ = (uint8_t)(s->id);
1842
+ GPR_ASSERT(p == GRPC_SLICE_END_PTR(hdr));
1843
+
1844
+ grpc_slice_buffer_add(&t->qbuf, hdr);
1845
+ grpc_slice_buffer_add(&t->qbuf, status_hdr);
1846
+ if (msg != NULL) {
1847
+ grpc_slice_buffer_add(&t->qbuf, message_pfx);
1848
+ grpc_slice_buffer_add(&t->qbuf, grpc_slice_from_copied_string(msg));
1849
+ }
1850
+ grpc_slice_buffer_add(
1851
+ &t->qbuf, grpc_chttp2_rst_stream_create(s->id, GRPC_HTTP2_NO_ERROR,
1852
+ &s->stats.outgoing));
1753
1853
 
1754
1854
  grpc_chttp2_mark_stream_closed(exec_ctx, t, s, 1, 1, error);
1755
1855
  grpc_chttp2_initiate_write(exec_ctx, t, false, "close_from_api");
@@ -1775,40 +1875,34 @@ static void end_all_the_calls(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
1775
1875
  GRPC_ERROR_UNREF(error);
1776
1876
  }
1777
1877
 
1778
- /** update window from a settings change */
1779
- typedef struct {
1780
- grpc_chttp2_transport *t;
1781
- grpc_exec_ctx *exec_ctx;
1782
- } update_global_window_args;
1878
+ /*******************************************************************************
1879
+ * INPUT PROCESSING - PARSING
1880
+ */
1783
1881
 
1784
- static void update_global_window(void *args, uint32_t id, void *stream) {
1785
- update_global_window_args *a = args;
1786
- grpc_chttp2_transport *t = a->t;
1787
- grpc_chttp2_stream *s = stream;
1788
- int was_zero;
1789
- int is_zero;
1790
- int64_t initial_window_update = t->initial_window_update;
1791
-
1792
- if (initial_window_update > 0) {
1793
- was_zero = s->outgoing_window <= 0;
1794
- GRPC_CHTTP2_FLOW_CREDIT_STREAM("settings", t, s, outgoing_window,
1795
- initial_window_update);
1796
- is_zero = s->outgoing_window <= 0;
1797
-
1798
- if (was_zero && !is_zero) {
1799
- grpc_chttp2_become_writable(a->exec_ctx, t, s, true,
1800
- "update_global_window");
1801
- }
1882
+ static void update_bdp(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
1883
+ double bdp_dbl) {
1884
+ uint32_t bdp;
1885
+ if (bdp_dbl <= 0) {
1886
+ bdp = 0;
1887
+ } else if (bdp_dbl > UINT32_MAX) {
1888
+ bdp = UINT32_MAX;
1802
1889
  } else {
1803
- GRPC_CHTTP2_FLOW_DEBIT_STREAM("settings", t, s, outgoing_window,
1804
- -initial_window_update);
1890
+ bdp = (uint32_t)(bdp_dbl);
1805
1891
  }
1892
+ int64_t delta =
1893
+ (int64_t)bdp -
1894
+ (int64_t)t->settings[GRPC_LOCAL_SETTINGS]
1895
+ [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
1896
+ if (delta == 0 || (bdp != 0 && delta > -1024 && delta < 1024)) {
1897
+ return;
1898
+ }
1899
+ if (grpc_bdp_estimator_trace) {
1900
+ gpr_log(GPR_DEBUG, "%s: update initial window size to %d", t->peer_string,
1901
+ (int)bdp);
1902
+ }
1903
+ push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, bdp);
1806
1904
  }
1807
1905
 
1808
- /*******************************************************************************
1809
- * INPUT PROCESSING - PARSING
1810
- */
1811
-
1812
1906
  static grpc_error *try_http_parsing(grpc_exec_ctx *exec_ctx,
1813
1907
  grpc_chttp2_transport *t) {
1814
1908
  grpc_http_parser parser;
@@ -1827,8 +1921,10 @@ static grpc_error *try_http_parsing(grpc_exec_ctx *exec_ctx,
1827
1921
  if (parse_error == GRPC_ERROR_NONE &&
1828
1922
  (parse_error = grpc_http_parser_eof(&parser)) == GRPC_ERROR_NONE) {
1829
1923
  error = grpc_error_set_int(
1830
- GRPC_ERROR_CREATE("Trying to connect an http1.x server"),
1831
- GRPC_ERROR_INT_HTTP_STATUS, response.status);
1924
+ grpc_error_set_int(
1925
+ GRPC_ERROR_CREATE("Trying to connect an http1.x server"),
1926
+ GRPC_ERROR_INT_HTTP_STATUS, response.status),
1927
+ GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
1832
1928
  }
1833
1929
  GRPC_ERROR_UNREF(parse_error);
1834
1930
 
@@ -1842,6 +1938,7 @@ static void read_action_locked(grpc_exec_ctx *exec_ctx, void *tp,
1842
1938
  GPR_TIMER_BEGIN("reading_action_locked", 0);
1843
1939
 
1844
1940
  grpc_chttp2_transport *t = tp;
1941
+ bool need_bdp_ping = false;
1845
1942
 
1846
1943
  GRPC_ERROR_REF(error);
1847
1944
 
@@ -1859,9 +1956,14 @@ static void read_action_locked(grpc_exec_ctx *exec_ctx, void *tp,
1859
1956
  grpc_error *errors[3] = {GRPC_ERROR_REF(error), GRPC_ERROR_NONE,
1860
1957
  GRPC_ERROR_NONE};
1861
1958
  for (; i < t->read_buffer.count && errors[1] == GRPC_ERROR_NONE; i++) {
1959
+ if (grpc_bdp_estimator_add_incoming_bytes(
1960
+ &t->bdp_estimator,
1961
+ (int64_t)GRPC_SLICE_LENGTH(t->read_buffer.slices[i]))) {
1962
+ need_bdp_ping = true;
1963
+ }
1862
1964
  errors[1] =
1863
1965
  grpc_chttp2_perform_read(exec_ctx, t, t->read_buffer.slices[i]);
1864
- };
1966
+ }
1865
1967
  if (errors[1] != GRPC_ERROR_NONE) {
1866
1968
  errors[2] = try_http_parsing(exec_ctx, t);
1867
1969
  GRPC_ERROR_UNREF(error);
@@ -1875,21 +1977,16 @@ static void read_action_locked(grpc_exec_ctx *exec_ctx, void *tp,
1875
1977
 
1876
1978
  GPR_TIMER_BEGIN("post_parse_locked", 0);
1877
1979
  if (t->initial_window_update != 0) {
1878
- update_global_window_args args = {t, exec_ctx};
1879
- grpc_chttp2_stream_map_for_each(&t->stream_map, update_global_window,
1880
- &args);
1980
+ if (t->initial_window_update > 0) {
1981
+ grpc_chttp2_stream *s;
1982
+ while (grpc_chttp2_list_pop_stalled_by_stream(t, &s)) {
1983
+ grpc_chttp2_become_writable(
1984
+ exec_ctx, t, s, GRPC_CHTTP2_STREAM_WRITE_INITIATE_UNCOVERED,
1985
+ "unstalled");
1986
+ }
1987
+ }
1881
1988
  t->initial_window_update = 0;
1882
1989
  }
1883
- /* handle higher level things */
1884
- if (t->incoming_window < t->connection_window_target * 3 / 4) {
1885
- int64_t announce_bytes = t->connection_window_target - t->incoming_window;
1886
- GRPC_CHTTP2_FLOW_CREDIT_TRANSPORT("parsed", t, announce_incoming_window,
1887
- announce_bytes);
1888
- GRPC_CHTTP2_FLOW_CREDIT_TRANSPORT("parsed", t, incoming_window,
1889
- announce_bytes);
1890
- grpc_chttp2_initiate_write(exec_ctx, t, false, "global incoming window");
1891
- }
1892
-
1893
1990
  GPR_TIMER_END("post_parse_locked", 0);
1894
1991
  }
1895
1992
 
@@ -1910,6 +2007,38 @@ static void read_action_locked(grpc_exec_ctx *exec_ctx, void *tp,
1910
2007
  if (keep_reading) {
1911
2008
  grpc_endpoint_read(exec_ctx, t->ep, &t->read_buffer,
1912
2009
  &t->read_action_locked);
2010
+
2011
+ if (t->enable_bdp_probe) {
2012
+ if (need_bdp_ping) {
2013
+ GRPC_CHTTP2_REF_TRANSPORT(t, "bdp_ping");
2014
+ grpc_bdp_estimator_schedule_ping(&t->bdp_estimator);
2015
+ send_ping_locked(exec_ctx, t,
2016
+ GRPC_CHTTP2_PING_BEFORE_TRANSPORT_WINDOW_UPDATE,
2017
+ &t->start_bdp_ping_locked, &t->finish_bdp_ping_locked);
2018
+ }
2019
+
2020
+ int64_t estimate = -1;
2021
+ if (grpc_bdp_estimator_get_estimate(&t->bdp_estimator, &estimate)) {
2022
+ double target = 1 + log2((double)estimate);
2023
+ double memory_pressure = grpc_resource_quota_get_memory_pressure(
2024
+ grpc_resource_user_quota(grpc_endpoint_get_resource_user(t->ep)));
2025
+ if (memory_pressure > 0.8) {
2026
+ target *= 1 - GPR_MIN(1, (memory_pressure - 0.8) / 0.1);
2027
+ }
2028
+ double bdp_error =
2029
+ target - grpc_pid_controller_last(&t->pid_controller);
2030
+ gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
2031
+ gpr_timespec dt_timespec = gpr_time_sub(now, t->last_pid_update);
2032
+ double dt = (double)dt_timespec.tv_sec + dt_timespec.tv_nsec * 1e-9;
2033
+ if (dt > 0.1) {
2034
+ dt = 0.1;
2035
+ }
2036
+ double log2_bdp_guess =
2037
+ grpc_pid_controller_update(&t->pid_controller, bdp_error, dt);
2038
+ update_bdp(exec_ctx, t, pow(2, log2_bdp_guess));
2039
+ t->last_pid_update = now;
2040
+ }
2041
+ }
1913
2042
  GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "keep_reading");
1914
2043
  } else {
1915
2044
  GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "reading_action");
@@ -1922,6 +2051,97 @@ static void read_action_locked(grpc_exec_ctx *exec_ctx, void *tp,
1922
2051
  GPR_TIMER_END("reading_action_locked", 0);
1923
2052
  }
1924
2053
 
2054
+ static void start_bdp_ping_locked(grpc_exec_ctx *exec_ctx, void *tp,
2055
+ grpc_error *error) {
2056
+ grpc_chttp2_transport *t = tp;
2057
+ if (grpc_http_trace) {
2058
+ gpr_log(GPR_DEBUG, "%s: Start BDP ping", t->peer_string);
2059
+ }
2060
+ grpc_bdp_estimator_start_ping(&t->bdp_estimator);
2061
+ }
2062
+
2063
+ static void finish_bdp_ping_locked(grpc_exec_ctx *exec_ctx, void *tp,
2064
+ grpc_error *error) {
2065
+ grpc_chttp2_transport *t = tp;
2066
+ if (grpc_http_trace) {
2067
+ gpr_log(GPR_DEBUG, "%s: Complete BDP ping", t->peer_string);
2068
+ }
2069
+ grpc_bdp_estimator_complete_ping(&t->bdp_estimator);
2070
+
2071
+ GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "bdp_ping");
2072
+ }
2073
+
2074
+ static void init_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg,
2075
+ grpc_error *error) {
2076
+ grpc_chttp2_transport *t = arg;
2077
+ GPR_ASSERT(t->keepalive_state == GRPC_CHTTP2_KEEPALIVE_STATE_WAITING);
2078
+ if (error == GRPC_ERROR_NONE && !(t->destroying || t->closed)) {
2079
+ if (t->keepalive_permit_without_calls || t->stream_map.count > 0) {
2080
+ t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_PINGING;
2081
+ GRPC_CHTTP2_REF_TRANSPORT(t, "keepalive ping end");
2082
+ send_ping_locked(exec_ctx, t, GRPC_CHTTP2_PING_ON_NEXT_WRITE,
2083
+ &t->start_keepalive_ping_locked,
2084
+ &t->finish_keepalive_ping_locked);
2085
+ } else {
2086
+ GRPC_CHTTP2_REF_TRANSPORT(t, "init keepalive ping");
2087
+ grpc_timer_init(
2088
+ exec_ctx, &t->keepalive_ping_timer,
2089
+ gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), t->keepalive_time),
2090
+ &t->init_keepalive_ping_locked, gpr_now(GPR_CLOCK_MONOTONIC));
2091
+ }
2092
+ }
2093
+ GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "init keepalive ping");
2094
+ }
2095
+
2096
+ static void start_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg,
2097
+ grpc_error *error) {
2098
+ grpc_chttp2_transport *t = arg;
2099
+ GRPC_CHTTP2_REF_TRANSPORT(t, "keepalive watchdog");
2100
+ grpc_timer_init(
2101
+ exec_ctx, &t->keepalive_watchdog_timer,
2102
+ gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), t->keepalive_timeout),
2103
+ &t->keepalive_watchdog_fired_locked, gpr_now(GPR_CLOCK_MONOTONIC));
2104
+ }
2105
+
2106
+ static void finish_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg,
2107
+ grpc_error *error) {
2108
+ grpc_chttp2_transport *t = arg;
2109
+ if (t->keepalive_state == GRPC_CHTTP2_KEEPALIVE_STATE_PINGING) {
2110
+ if (error == GRPC_ERROR_NONE) {
2111
+ t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_WAITING;
2112
+ grpc_timer_cancel(exec_ctx, &t->keepalive_watchdog_timer);
2113
+ GRPC_CHTTP2_REF_TRANSPORT(t, "init keepalive ping");
2114
+ grpc_timer_init(
2115
+ exec_ctx, &t->keepalive_ping_timer,
2116
+ gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), t->keepalive_time),
2117
+ grpc_closure_create(init_keepalive_ping_locked, t,
2118
+ grpc_combiner_scheduler(t->combiner, false)),
2119
+ gpr_now(GPR_CLOCK_MONOTONIC));
2120
+ }
2121
+ }
2122
+ GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "keepalive ping end");
2123
+ }
2124
+
2125
+ static void keepalive_watchdog_fired_locked(grpc_exec_ctx *exec_ctx, void *arg,
2126
+ grpc_error *error) {
2127
+ grpc_chttp2_transport *t = arg;
2128
+ if (t->keepalive_state == GRPC_CHTTP2_KEEPALIVE_STATE_PINGING) {
2129
+ if (error == GRPC_ERROR_NONE) {
2130
+ t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_DYING;
2131
+ close_transport_locked(exec_ctx, t,
2132
+ GRPC_ERROR_CREATE("keepalive watchdog timeout"));
2133
+ }
2134
+ } else {
2135
+ /** The watchdog timer should have been cancelled by
2136
+ finish_keepalive_ping_locked. */
2137
+ if (error != GRPC_ERROR_CANCELLED) {
2138
+ gpr_log(GPR_ERROR, "keepalive_ping_end state error: %d (expect: %d)",
2139
+ t->keepalive_state, GRPC_CHTTP2_KEEPALIVE_STATE_PINGING);
2140
+ }
2141
+ }
2142
+ GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "keepalive watchdog");
2143
+ }
2144
+
1925
2145
  /*******************************************************************************
1926
2146
  * CALLBACK LOOP
1927
2147
  */
@@ -1972,10 +2192,12 @@ static void incoming_byte_stream_update_flow_control(grpc_exec_ctx *exec_ctx,
1972
2192
  size_t max_size_hint,
1973
2193
  size_t have_already) {
1974
2194
  uint32_t max_recv_bytes;
2195
+ uint32_t initial_window_size =
2196
+ t->settings[GRPC_SENT_SETTINGS][GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
1975
2197
 
1976
2198
  /* clamp max recv hint to an allowable size */
1977
- if (max_size_hint >= UINT32_MAX - t->stream_lookahead) {
1978
- max_recv_bytes = UINT32_MAX - t->stream_lookahead;
2199
+ if (max_size_hint >= UINT32_MAX - initial_window_size) {
2200
+ max_recv_bytes = UINT32_MAX - initial_window_size;
1979
2201
  } else {
1980
2202
  max_recv_bytes = (uint32_t)max_size_hint;
1981
2203
  }
@@ -1988,20 +2210,26 @@ static void incoming_byte_stream_update_flow_control(grpc_exec_ctx *exec_ctx,
1988
2210
  }
1989
2211
 
1990
2212
  /* add some small lookahead to keep pipelines flowing */
1991
- GPR_ASSERT(max_recv_bytes <= UINT32_MAX - t->stream_lookahead);
1992
- max_recv_bytes += t->stream_lookahead;
1993
- if (s->max_recv_bytes < max_recv_bytes) {
1994
- uint32_t add_max_recv_bytes = max_recv_bytes - s->max_recv_bytes;
1995
- bool new_window_write_is_covered_by_poller =
1996
- s->max_recv_bytes < have_already;
1997
- GRPC_CHTTP2_FLOW_CREDIT_STREAM("op", t, s, max_recv_bytes,
1998
- add_max_recv_bytes);
1999
- GRPC_CHTTP2_FLOW_CREDIT_STREAM("op", t, s, incoming_window,
2000
- add_max_recv_bytes);
2213
+ GPR_ASSERT(max_recv_bytes <= UINT32_MAX - initial_window_size);
2214
+ if (s->incoming_window_delta < max_recv_bytes && !s->read_closed) {
2215
+ uint32_t add_max_recv_bytes =
2216
+ (uint32_t)(max_recv_bytes - s->incoming_window_delta);
2217
+ grpc_chttp2_stream_write_type write_type =
2218
+ GRPC_CHTTP2_STREAM_WRITE_INITIATE_UNCOVERED;
2219
+ if (s->incoming_window_delta + initial_window_size <
2220
+ (int64_t)have_already) {
2221
+ write_type = GRPC_CHTTP2_STREAM_WRITE_INITIATE_COVERED;
2222
+ }
2223
+ GRPC_CHTTP2_FLOW_CREDIT_STREAM_INCOMING_WINDOW_DELTA("op", t, s,
2224
+ add_max_recv_bytes);
2001
2225
  GRPC_CHTTP2_FLOW_CREDIT_STREAM("op", t, s, announce_window,
2002
2226
  add_max_recv_bytes);
2003
- grpc_chttp2_become_writable(exec_ctx, t, s,
2004
- new_window_write_is_covered_by_poller,
2227
+ if ((int64_t)s->incoming_window_delta + (int64_t)initial_window_size -
2228
+ (int64_t)s->announce_window >
2229
+ (int64_t)initial_window_size / 2) {
2230
+ write_type = GRPC_CHTTP2_STREAM_WRITE_PIGGYBACK;
2231
+ }
2232
+ grpc_chttp2_become_writable(exec_ctx, t, s, write_type,
2005
2233
  "read_incoming_stream");
2006
2234
  }
2007
2235
  }
@@ -2089,6 +2317,8 @@ static void incoming_byte_stream_publish_error(
2089
2317
  grpc_closure_sched(exec_ctx, bs->on_next, GRPC_ERROR_REF(error));
2090
2318
  bs->on_next = NULL;
2091
2319
  GRPC_ERROR_UNREF(bs->error);
2320
+ grpc_chttp2_cancel_stream(exec_ctx, bs->transport, bs->stream,
2321
+ GRPC_ERROR_REF(error));
2092
2322
  bs->error = error;
2093
2323
  }
2094
2324
 
@@ -2197,8 +2427,10 @@ static void benign_reclaimer_locked(grpc_exec_ctx *exec_ctx, void *arg,
2197
2427
  gpr_log(GPR_DEBUG, "HTTP2: %s - send goaway to free memory",
2198
2428
  t->peer_string);
2199
2429
  }
2200
- send_goaway(exec_ctx, t, GRPC_CHTTP2_ENHANCE_YOUR_CALM,
2201
- grpc_slice_from_static_string("Buffers full"));
2430
+ send_goaway(exec_ctx, t,
2431
+ grpc_error_set_int(GRPC_ERROR_CREATE("Buffers full"),
2432
+ GRPC_ERROR_INT_HTTP2_ERROR,
2433
+ GRPC_HTTP2_ENHANCE_YOUR_CALM));
2202
2434
  } else if (error == GRPC_ERROR_NONE && grpc_resource_quota_trace) {
2203
2435
  gpr_log(GPR_DEBUG,
2204
2436
  "HTTP2: %s - skip benign reclamation, there are still %" PRIdPTR
@@ -2227,7 +2459,7 @@ static void destructive_reclaimer_locked(grpc_exec_ctx *exec_ctx, void *arg,
2227
2459
  grpc_chttp2_cancel_stream(
2228
2460
  exec_ctx, t, s, grpc_error_set_int(GRPC_ERROR_CREATE("Buffers full"),
2229
2461
  GRPC_ERROR_INT_HTTP2_ERROR,
2230
- GRPC_CHTTP2_ENHANCE_YOUR_CALM));
2462
+ GRPC_HTTP2_ENHANCE_YOUR_CALM));
2231
2463
  if (n > 1) {
2232
2464
  /* Since we cancel one stream per destructive reclamation, if
2233
2465
  there are more streams left, we can immediately post a new
@@ -2351,7 +2583,7 @@ static const grpc_transport_vtable vtable = {sizeof(grpc_chttp2_stream),
2351
2583
  grpc_transport *grpc_create_chttp2_transport(
2352
2584
  grpc_exec_ctx *exec_ctx, const grpc_channel_args *channel_args,
2353
2585
  grpc_endpoint *ep, int is_client) {
2354
- grpc_chttp2_transport *t = gpr_malloc(sizeof(grpc_chttp2_transport));
2586
+ grpc_chttp2_transport *t = gpr_zalloc(sizeof(grpc_chttp2_transport));
2355
2587
  init_transport(exec_ctx, t, channel_args, ep, is_client != 0);
2356
2588
  return &t->base;
2357
2589
  }