grpc 1.6.7 → 1.7.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 (277) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +579 -77
  3. data/include/grpc/byte_buffer.h +1 -63
  4. data/include/grpc/compression.h +27 -5
  5. data/include/grpc/fork.h +24 -0
  6. data/include/grpc/grpc.h +12 -6
  7. data/include/grpc/grpc_security.h +28 -7
  8. data/include/grpc/impl/codegen/atm.h +1 -0
  9. data/include/grpc/impl/codegen/byte_buffer.h +86 -0
  10. data/include/grpc/impl/codegen/compression_types.h +63 -5
  11. data/include/grpc/impl/codegen/fork.h +48 -0
  12. data/include/grpc/impl/codegen/grpc_types.h +26 -9
  13. data/include/grpc/impl/codegen/port_platform.h +11 -4
  14. data/include/grpc/impl/codegen/slice.h +6 -1
  15. data/include/grpc/impl/codegen/sync.h +3 -1
  16. data/include/grpc/impl/codegen/sync_custom.h +36 -0
  17. data/include/grpc/module.modulemap +75 -3
  18. data/include/grpc/slice.h +1 -5
  19. data/include/grpc/support/sync_custom.h +24 -0
  20. data/src/core/ext/census/base_resources.c +14 -14
  21. data/src/core/ext/census/context.c +7 -5
  22. data/src/core/ext/census/grpc_filter.c +12 -14
  23. data/src/core/ext/census/mlog.c +2 -1
  24. data/src/core/ext/census/resource.c +13 -9
  25. data/src/core/ext/filters/client_channel/channel_connectivity.c +15 -8
  26. data/src/core/ext/filters/client_channel/client_channel.c +418 -439
  27. data/src/core/ext/filters/client_channel/client_channel_factory.c +4 -5
  28. data/src/core/ext/filters/client_channel/client_channel_plugin.c +2 -2
  29. data/src/core/ext/filters/client_channel/http_connect_handshaker.c +7 -5
  30. data/src/core/ext/filters/client_channel/http_proxy.c +17 -21
  31. data/src/core/ext/filters/client_channel/lb_policy.c +1 -1
  32. data/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.c +7 -7
  33. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c +371 -257
  34. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.c +7 -5
  35. data/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c +25 -14
  36. data/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.c +16 -16
  37. data/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.c +33 -28
  38. data/src/core/ext/filters/client_channel/lb_policy_factory.c +10 -8
  39. data/src/core/ext/filters/client_channel/lb_policy_factory.h +1 -1
  40. data/src/core/ext/filters/client_channel/proxy_mapper_registry.c +1 -1
  41. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.c +7 -6
  42. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.c +62 -28
  43. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.c +29 -23
  44. data/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.c +25 -14
  45. data/src/core/ext/filters/client_channel/retry_throttle.c +9 -6
  46. data/src/core/ext/filters/client_channel/subchannel.c +30 -30
  47. data/src/core/ext/filters/client_channel/subchannel.h +1 -4
  48. data/src/core/ext/filters/client_channel/subchannel_index.c +31 -15
  49. data/src/core/ext/filters/client_channel/subchannel_index.h +7 -0
  50. data/src/core/ext/filters/client_channel/uri_parser.c +4 -3
  51. data/src/core/ext/filters/deadline/deadline_filter.c +78 -39
  52. data/src/core/ext/filters/deadline/deadline_filter.h +7 -1
  53. data/src/core/ext/filters/http/client/http_client_filter.c +14 -14
  54. data/src/core/ext/filters/http/http_filters_plugin.c +1 -1
  55. data/src/core/ext/filters/http/message_compress/message_compress_filter.c +240 -175
  56. data/src/core/ext/filters/http/server/http_server_filter.c +48 -36
  57. data/src/core/ext/filters/load_reporting/{load_reporting_filter.c → server_load_reporting_filter.c} +11 -12
  58. data/src/core/ext/filters/load_reporting/{load_reporting_filter.h → server_load_reporting_filter.h} +6 -5
  59. data/src/core/ext/filters/load_reporting/{load_reporting.c → server_load_reporting_plugin.c} +19 -13
  60. data/src/core/ext/filters/load_reporting/{load_reporting.h → server_load_reporting_plugin.h} +4 -3
  61. data/src/core/ext/filters/max_age/max_age_filter.c +2 -3
  62. data/src/core/ext/filters/message_size/message_size_filter.c +4 -2
  63. data/src/core/ext/filters/workarounds/workaround_cronet_compression_filter.c +0 -1
  64. data/src/core/ext/transport/chttp2/client/chttp2_connector.c +5 -5
  65. data/src/core/ext/transport/chttp2/client/insecure/channel_create.c +1 -1
  66. data/src/core/ext/transport/chttp2/client/insecure/channel_create_posix.c +1 -1
  67. data/src/core/ext/transport/chttp2/server/chttp2_server.c +20 -18
  68. data/src/core/ext/transport/chttp2/transport/chttp2_plugin.c +1 -0
  69. data/src/core/ext/transport/chttp2/transport/chttp2_transport.c +493 -210
  70. data/src/core/ext/transport/chttp2/transport/chttp2_transport.h +1 -0
  71. data/src/core/ext/transport/chttp2/transport/flow_control.c +9 -8
  72. data/src/core/ext/transport/chttp2/transport/frame_data.c +2 -2
  73. data/src/core/ext/transport/chttp2/transport/frame_goaway.c +2 -2
  74. data/src/core/ext/transport/chttp2/transport/frame_ping.c +5 -4
  75. data/src/core/ext/transport/chttp2/transport/frame_rst_stream.c +1 -1
  76. data/src/core/ext/transport/chttp2/transport/frame_settings.c +10 -9
  77. data/src/core/ext/transport/chttp2/transport/frame_window_update.c +9 -5
  78. data/src/core/ext/transport/chttp2/transport/hpack_encoder.c +62 -41
  79. data/src/core/ext/transport/chttp2/transport/hpack_parser.c +52 -8
  80. data/src/core/ext/transport/chttp2/transport/hpack_table.c +2 -2
  81. data/src/core/ext/transport/chttp2/transport/incoming_metadata.c +3 -2
  82. data/src/core/ext/transport/chttp2/transport/internal.h +60 -30
  83. data/src/core/ext/transport/chttp2/transport/parsing.c +16 -5
  84. data/src/core/ext/transport/chttp2/transport/stream_lists.c +36 -16
  85. data/src/core/ext/transport/chttp2/transport/stream_map.c +6 -4
  86. data/src/core/ext/transport/chttp2/transport/writing.c +133 -105
  87. data/src/core/ext/transport/inproc/inproc_transport.c +61 -65
  88. data/src/core/lib/channel/channel_args.c +112 -12
  89. data/src/core/lib/channel/channel_args.h +31 -0
  90. data/src/core/lib/channel/channel_stack.c +1 -15
  91. data/src/core/lib/channel/channel_stack.h +3 -10
  92. data/src/core/lib/channel/channel_stack_builder.c +41 -10
  93. data/src/core/lib/channel/channel_stack_builder.h +10 -0
  94. data/src/core/lib/channel/connected_channel.c +94 -23
  95. data/src/core/lib/channel/handshaker.c +8 -6
  96. data/src/core/lib/channel/handshaker_registry.c +1 -1
  97. data/src/core/lib/compression/algorithm_metadata.h +14 -0
  98. data/src/core/lib/compression/compression.c +101 -1
  99. data/src/core/lib/compression/stream_compression.c +32 -146
  100. data/src/core/lib/compression/stream_compression.h +28 -4
  101. data/src/core/lib/compression/stream_compression_gzip.c +228 -0
  102. data/src/core/lib/{iomgr/ev_epoll_thread_pool_linux.h → compression/stream_compression_gzip.h} +5 -7
  103. data/src/core/lib/compression/stream_compression_identity.c +94 -0
  104. data/src/core/lib/{iomgr/ev_epoll_limited_pollers_linux.h → compression/stream_compression_identity.h} +7 -8
  105. data/src/core/lib/debug/stats.c +174 -0
  106. data/src/core/lib/debug/stats.h +61 -0
  107. data/src/core/lib/debug/stats_data.c +687 -0
  108. data/src/core/lib/debug/stats_data.h +470 -0
  109. data/src/core/lib/debug/trace.c +3 -3
  110. data/src/core/lib/debug/trace.h +1 -1
  111. data/src/core/lib/http/format_request.c +1 -1
  112. data/src/core/lib/http/httpcli.c +8 -7
  113. data/src/core/lib/http/httpcli_security_connector.c +2 -1
  114. data/src/core/lib/http/parser.c +4 -3
  115. data/src/core/lib/iomgr/call_combiner.c +202 -0
  116. data/src/core/lib/iomgr/call_combiner.h +121 -0
  117. data/src/core/lib/iomgr/closure.c +18 -4
  118. data/src/core/lib/iomgr/combiner.c +11 -4
  119. data/src/core/lib/iomgr/error.c +26 -24
  120. data/src/core/lib/iomgr/ev_epoll1_linux.c +395 -212
  121. data/src/core/lib/iomgr/ev_epollex_linux.c +141 -128
  122. data/src/core/lib/iomgr/ev_epollsig_linux.c +44 -41
  123. data/src/core/lib/iomgr/ev_poll_posix.c +99 -75
  124. data/src/core/lib/iomgr/ev_posix.c +5 -9
  125. data/src/core/lib/iomgr/ev_posix.h +1 -1
  126. data/src/core/lib/iomgr/exec_ctx.h +6 -1
  127. data/src/core/lib/iomgr/executor.c +142 -36
  128. data/src/core/lib/iomgr/executor.h +6 -1
  129. data/src/core/lib/iomgr/fork_posix.c +88 -0
  130. data/src/core/lib/iomgr/fork_windows.c +39 -0
  131. data/src/core/lib/iomgr/iocp_windows.c +2 -0
  132. data/src/core/lib/iomgr/iomgr.c +2 -8
  133. data/src/core/lib/iomgr/is_epollexclusive_available.c +6 -6
  134. data/src/core/lib/iomgr/load_file.c +2 -1
  135. data/src/core/lib/iomgr/polling_entity.c +9 -9
  136. data/src/core/lib/iomgr/polling_entity.h +7 -1
  137. data/src/core/lib/iomgr/pollset.h +1 -1
  138. data/src/core/lib/iomgr/pollset_uv.c +1 -1
  139. data/src/core/lib/iomgr/pollset_windows.c +3 -3
  140. data/src/core/lib/iomgr/port.h +4 -0
  141. data/src/core/lib/iomgr/resolve_address_posix.c +8 -7
  142. data/src/core/lib/iomgr/resolve_address_windows.c +1 -1
  143. data/src/core/lib/iomgr/resource_quota.c +24 -19
  144. data/src/core/lib/iomgr/socket_factory_posix.c +4 -4
  145. data/src/core/lib/iomgr/socket_mutator.c +4 -4
  146. data/src/core/lib/iomgr/socket_utils_windows.c +0 -4
  147. data/src/core/lib/iomgr/tcp_client_posix.c +5 -4
  148. data/src/core/lib/iomgr/tcp_posix.c +181 -20
  149. data/src/core/lib/iomgr/tcp_server_posix.c +8 -7
  150. data/src/core/lib/iomgr/tcp_server_utils_posix_common.c +1 -1
  151. data/src/core/lib/iomgr/timer.h +4 -0
  152. data/src/core/lib/iomgr/timer_generic.c +138 -3
  153. data/src/core/lib/iomgr/timer_generic.h +3 -0
  154. data/src/core/lib/iomgr/timer_heap.c +4 -4
  155. data/src/core/lib/iomgr/timer_manager.c +2 -2
  156. data/src/core/lib/iomgr/timer_uv.c +2 -0
  157. data/src/core/lib/iomgr/udp_server.c +10 -8
  158. data/src/core/lib/iomgr/unix_sockets_posix.c +4 -2
  159. data/src/core/lib/iomgr/wakeup_fd_cv.c +9 -8
  160. data/src/core/lib/iomgr/wakeup_fd_cv.h +2 -2
  161. data/src/core/lib/json/json.c +1 -1
  162. data/src/core/lib/json/json_string.c +13 -13
  163. data/src/core/lib/profiling/timers.h +18 -8
  164. data/src/core/lib/security/credentials/composite/composite_credentials.c +4 -10
  165. data/src/core/lib/security/credentials/google_default/google_default_credentials.c +2 -1
  166. data/src/core/lib/security/credentials/jwt/jwt_verifier.c +11 -6
  167. data/src/core/lib/security/credentials/oauth2/oauth2_credentials.c +4 -4
  168. data/src/core/lib/security/credentials/plugin/plugin_credentials.c +132 -50
  169. data/src/core/lib/security/credentials/plugin/plugin_credentials.h +2 -0
  170. data/src/core/lib/security/transport/client_auth_filter.c +68 -135
  171. data/src/core/lib/security/transport/secure_endpoint.c +110 -90
  172. data/src/core/lib/security/transport/secure_endpoint.h +8 -3
  173. data/src/core/lib/security/transport/security_connector.c +10 -12
  174. data/src/core/lib/security/transport/security_handshaker.c +45 -24
  175. data/src/core/lib/security/transport/server_auth_filter.c +71 -20
  176. data/src/core/lib/slice/b64.c +2 -2
  177. data/src/core/lib/slice/slice.c +16 -14
  178. data/src/core/lib/slice/slice_buffer.c +5 -4
  179. data/src/core/lib/slice/slice_hash_table.c +3 -2
  180. data/src/core/lib/slice/slice_intern.c +8 -5
  181. data/src/core/lib/support/block_annotate.h +22 -0
  182. data/src/core/lib/support/fork.c +62 -0
  183. data/src/core/lib/support/fork.h +35 -0
  184. data/src/core/lib/support/log_linux.c +1 -1
  185. data/src/core/lib/support/string.c +15 -1
  186. data/src/core/lib/support/string.h +3 -0
  187. data/src/core/lib/support/thd_internal.h +6 -0
  188. data/src/core/lib/support/thd_posix.c +56 -0
  189. data/src/core/lib/support/thd_windows.c +2 -0
  190. data/src/core/lib/surface/alarm.c +22 -15
  191. data/src/core/lib/surface/byte_buffer.c +4 -2
  192. data/src/core/lib/surface/call.c +442 -141
  193. data/src/core/lib/surface/call.h +6 -6
  194. data/src/core/lib/surface/call_log_batch.c +1 -1
  195. data/src/core/lib/surface/call_test_only.h +12 -0
  196. data/src/core/lib/surface/channel.c +39 -4
  197. data/src/core/lib/surface/channel_init.c +6 -6
  198. data/src/core/lib/surface/channel_ping.c +2 -2
  199. data/src/core/lib/surface/completion_queue.c +56 -57
  200. data/src/core/lib/surface/init.c +17 -3
  201. data/src/core/lib/surface/init_secure.c +5 -1
  202. data/src/core/lib/surface/lame_client.cc +9 -10
  203. data/src/core/lib/surface/server.c +81 -72
  204. data/src/core/lib/surface/version.c +2 -2
  205. data/src/core/lib/transport/byte_stream.c +1 -0
  206. data/src/core/lib/transport/byte_stream.h +3 -1
  207. data/src/core/lib/transport/connectivity_state.c +2 -1
  208. data/src/core/lib/transport/metadata.c +7 -4
  209. data/src/core/lib/transport/metadata_batch.c +18 -16
  210. data/src/core/lib/transport/metadata_batch.h +1 -0
  211. data/src/core/lib/transport/service_config.c +5 -3
  212. data/src/core/lib/transport/static_metadata.c +395 -614
  213. data/src/core/lib/transport/static_metadata.h +165 -133
  214. data/src/core/lib/transport/status_conversion.c +1 -1
  215. data/src/core/lib/transport/transport.c +20 -20
  216. data/src/core/lib/transport/transport.h +8 -5
  217. data/src/core/lib/transport/transport_impl.h +0 -3
  218. data/src/core/lib/transport/transport_op_string.c +8 -1
  219. data/src/core/plugin_registry/grpc_plugin_registry.c +4 -4
  220. data/src/core/tsi/fake_transport_security.c +133 -2
  221. data/src/core/tsi/fake_transport_security.h +5 -0
  222. data/src/core/tsi/ssl_transport_security.c +105 -8
  223. data/src/core/tsi/ssl_transport_security.h +30 -7
  224. data/src/core/tsi/transport_security.h +8 -2
  225. data/src/core/tsi/transport_security_grpc.c +20 -13
  226. data/src/core/tsi/transport_security_grpc.h +13 -9
  227. data/src/ruby/ext/grpc/rb_call_credentials.c +6 -2
  228. data/src/ruby/ext/grpc/rb_grpc.c +1 -1
  229. data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +30 -20
  230. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +50 -35
  231. data/src/ruby/lib/grpc.rb +1 -0
  232. data/src/ruby/lib/grpc/generic/active_call.rb +34 -9
  233. data/src/ruby/lib/grpc/generic/bidi_call.rb +19 -10
  234. data/src/ruby/lib/grpc/generic/client_stub.rb +95 -38
  235. data/src/ruby/lib/grpc/generic/interceptor_registry.rb +53 -0
  236. data/src/ruby/lib/grpc/generic/interceptors.rb +186 -0
  237. data/src/ruby/lib/grpc/generic/rpc_desc.rb +66 -20
  238. data/src/ruby/lib/grpc/generic/rpc_server.rb +15 -3
  239. data/src/ruby/lib/grpc/google_rpc_status_utils.rb +1 -2
  240. data/src/ruby/lib/grpc/version.rb +1 -1
  241. data/src/ruby/pb/grpc/testing/duplicate/echo_duplicate_services_pb.rb +1 -0
  242. data/src/ruby/spec/channel_connection_spec.rb +1 -34
  243. data/src/ruby/spec/client_server_spec.rb +188 -82
  244. data/src/ruby/spec/generic/active_call_spec.rb +65 -11
  245. data/src/ruby/spec/generic/client_interceptors_spec.rb +153 -0
  246. data/src/ruby/spec/generic/interceptor_registry_spec.rb +65 -0
  247. data/src/ruby/spec/generic/rpc_desc_spec.rb +38 -0
  248. data/src/ruby/spec/generic/rpc_server_spec.rb +1 -34
  249. data/src/ruby/spec/generic/server_interceptors_spec.rb +218 -0
  250. data/src/ruby/spec/spec_helper.rb +4 -0
  251. data/src/ruby/spec/support/helpers.rb +73 -0
  252. data/src/ruby/spec/support/services.rb +147 -0
  253. data/third_party/cares/ares_build.h +21 -62
  254. data/third_party/cares/cares/ares.h +23 -1
  255. data/third_party/cares/cares/ares__close_sockets.c +2 -2
  256. data/third_party/cares/cares/ares_create_query.c +3 -3
  257. data/third_party/cares/cares/ares_expand_name.c +6 -2
  258. data/third_party/cares/cares/ares_expand_string.c +1 -1
  259. data/third_party/cares/cares/ares_getnameinfo.c +27 -7
  260. data/third_party/cares/cares/ares_init.c +407 -39
  261. data/third_party/cares/cares/ares_library_init.c +10 -0
  262. data/third_party/cares/cares/ares_library_init.h +2 -1
  263. data/third_party/cares/cares/ares_nowarn.c +6 -6
  264. data/third_party/cares/cares/ares_nowarn.h +2 -2
  265. data/third_party/cares/cares/ares_parse_naptr_reply.c +6 -1
  266. data/third_party/cares/cares/ares_private.h +11 -0
  267. data/third_party/cares/cares/ares_process.c +126 -37
  268. data/third_party/cares/cares/ares_version.h +2 -2
  269. data/third_party/cares/cares/ares_writev.c +2 -2
  270. data/third_party/cares/cares/config-win32.h +8 -34
  271. data/third_party/cares/cares/inet_net_pton.c +2 -2
  272. data/third_party/cares/cares/setup_once.h +5 -5
  273. data/third_party/cares/config_darwin/ares_config.h +98 -196
  274. data/third_party/cares/config_linux/ares_config.h +103 -203
  275. metadata +47 -20
  276. data/src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c +0 -1957
  277. data/src/core/lib/iomgr/ev_epoll_thread_pool_linux.c +0 -1182
@@ -55,7 +55,7 @@ static grpc_channel *client_channel_factory_create_channel(
55
55
  }
56
56
  // Add channel arg containing the server URI.
57
57
  grpc_arg arg = grpc_channel_arg_string_create(
58
- GRPC_ARG_SERVER_URI,
58
+ (char *)GRPC_ARG_SERVER_URI,
59
59
  grpc_resolver_factory_add_default_prefix_if_needed(exec_ctx, target));
60
60
  const char *to_remove[] = {GRPC_ARG_SERVER_URI};
61
61
  grpc_channel_args *new_args =
@@ -42,7 +42,7 @@ grpc_channel *grpc_insecure_channel_create_from_fd(
42
42
  (target, fd, args));
43
43
 
44
44
  grpc_arg default_authority_arg = grpc_channel_arg_string_create(
45
- GRPC_ARG_DEFAULT_AUTHORITY, "test.authority");
45
+ (char *)GRPC_ARG_DEFAULT_AUTHORITY, (char *)"test.authority");
46
46
  grpc_channel_args *final_args =
47
47
  grpc_channel_args_copy_and_add(args, &default_authority_arg, 1);
48
48
 
@@ -52,7 +52,7 @@ typedef struct {
52
52
  } server_state;
53
53
 
54
54
  typedef struct {
55
- server_state *server_state;
55
+ server_state *svr_state;
56
56
  grpc_pollset *accepting_pollset;
57
57
  grpc_tcp_server_acceptor *acceptor;
58
58
  grpc_handshake_manager *handshake_mgr;
@@ -60,10 +60,11 @@ typedef struct {
60
60
 
61
61
  static void on_handshake_done(grpc_exec_ctx *exec_ctx, void *arg,
62
62
  grpc_error *error) {
63
- grpc_handshaker_args *args = arg;
64
- server_connection_state *connection_state = args->user_data;
65
- gpr_mu_lock(&connection_state->server_state->mu);
66
- if (error != GRPC_ERROR_NONE || connection_state->server_state->shutdown) {
63
+ grpc_handshaker_args *args = (grpc_handshaker_args *)arg;
64
+ server_connection_state *connection_state =
65
+ (server_connection_state *)args->user_data;
66
+ gpr_mu_lock(&connection_state->svr_state->mu);
67
+ if (error != GRPC_ERROR_NONE || connection_state->svr_state->shutdown) {
67
68
  const char *error_str = grpc_error_string(error);
68
69
  gpr_log(GPR_DEBUG, "Handshaking failed: %s", error_str);
69
70
 
@@ -88,7 +89,7 @@ static void on_handshake_done(grpc_exec_ctx *exec_ctx, void *arg,
88
89
  grpc_transport *transport =
89
90
  grpc_create_chttp2_transport(exec_ctx, args->args, args->endpoint, 0);
90
91
  grpc_server_setup_transport(
91
- exec_ctx, connection_state->server_state->server, transport,
92
+ exec_ctx, connection_state->svr_state->server, transport,
92
93
  connection_state->accepting_pollset, args->args);
93
94
  grpc_chttp2_transport_start_reading(exec_ctx, transport,
94
95
  args->read_buffer);
@@ -96,11 +97,11 @@ static void on_handshake_done(grpc_exec_ctx *exec_ctx, void *arg,
96
97
  }
97
98
  }
98
99
  grpc_handshake_manager_pending_list_remove(
99
- &connection_state->server_state->pending_handshake_mgrs,
100
+ &connection_state->svr_state->pending_handshake_mgrs,
100
101
  connection_state->handshake_mgr);
101
- gpr_mu_unlock(&connection_state->server_state->mu);
102
+ gpr_mu_unlock(&connection_state->svr_state->mu);
102
103
  grpc_handshake_manager_destroy(exec_ctx, connection_state->handshake_mgr);
103
- grpc_tcp_server_unref(exec_ctx, connection_state->server_state->tcp_server);
104
+ grpc_tcp_server_unref(exec_ctx, connection_state->svr_state->tcp_server);
104
105
  gpr_free(connection_state->acceptor);
105
106
  gpr_free(connection_state);
106
107
  }
@@ -108,7 +109,7 @@ static void on_handshake_done(grpc_exec_ctx *exec_ctx, void *arg,
108
109
  static void on_accept(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *tcp,
109
110
  grpc_pollset *accepting_pollset,
110
111
  grpc_tcp_server_acceptor *acceptor) {
111
- server_state *state = arg;
112
+ server_state *state = (server_state *)arg;
112
113
  gpr_mu_lock(&state->mu);
113
114
  if (state->shutdown) {
114
115
  gpr_mu_unlock(&state->mu);
@@ -123,8 +124,8 @@ static void on_accept(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *tcp,
123
124
  gpr_mu_unlock(&state->mu);
124
125
  grpc_tcp_server_ref(state->tcp_server);
125
126
  server_connection_state *connection_state =
126
- gpr_malloc(sizeof(*connection_state));
127
- connection_state->server_state = state;
127
+ (server_connection_state *)gpr_malloc(sizeof(*connection_state));
128
+ connection_state->svr_state = state;
128
129
  connection_state->accepting_pollset = accepting_pollset;
129
130
  connection_state->acceptor = acceptor;
130
131
  connection_state->handshake_mgr = handshake_mgr;
@@ -143,7 +144,7 @@ static void on_accept(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *tcp,
143
144
  static void server_start_listener(grpc_exec_ctx *exec_ctx, grpc_server *server,
144
145
  void *arg, grpc_pollset **pollsets,
145
146
  size_t pollset_count) {
146
- server_state *state = arg;
147
+ server_state *state = (server_state *)arg;
147
148
  gpr_mu_lock(&state->mu);
148
149
  state->shutdown = false;
149
150
  gpr_mu_unlock(&state->mu);
@@ -153,7 +154,7 @@ static void server_start_listener(grpc_exec_ctx *exec_ctx, grpc_server *server,
153
154
 
154
155
  static void tcp_server_shutdown_complete(grpc_exec_ctx *exec_ctx, void *arg,
155
156
  grpc_error *error) {
156
- server_state *state = arg;
157
+ server_state *state = (server_state *)arg;
157
158
  /* ensure all threads have unlocked */
158
159
  gpr_mu_lock(&state->mu);
159
160
  grpc_closure *destroy_done = state->server_destroy_listener_done;
@@ -178,7 +179,7 @@ static void tcp_server_shutdown_complete(grpc_exec_ctx *exec_ctx, void *arg,
178
179
  static void server_destroy_listener(grpc_exec_ctx *exec_ctx,
179
180
  grpc_server *server, void *arg,
180
181
  grpc_closure *destroy_done) {
181
- server_state *state = arg;
182
+ server_state *state = (server_state *)arg;
182
183
  gpr_mu_lock(&state->mu);
183
184
  state->shutdown = true;
184
185
  state->server_destroy_listener_done = destroy_done;
@@ -200,6 +201,7 @@ grpc_error *grpc_chttp2_server_add_port(grpc_exec_ctx *exec_ctx,
200
201
  grpc_error *err = GRPC_ERROR_NONE;
201
202
  server_state *state = NULL;
202
203
  grpc_error **errors = NULL;
204
+ size_t naddrs = 0;
203
205
 
204
206
  *port_num = -1;
205
207
 
@@ -208,7 +210,7 @@ grpc_error *grpc_chttp2_server_add_port(grpc_exec_ctx *exec_ctx,
208
210
  if (err != GRPC_ERROR_NONE) {
209
211
  goto error;
210
212
  }
211
- state = gpr_zalloc(sizeof(*state));
213
+ state = (server_state *)gpr_zalloc(sizeof(*state));
212
214
  GRPC_CLOSURE_INIT(&state->tcp_server_shutdown_complete,
213
215
  tcp_server_shutdown_complete, state,
214
216
  grpc_schedule_on_exec_ctx);
@@ -224,8 +226,8 @@ grpc_error *grpc_chttp2_server_add_port(grpc_exec_ctx *exec_ctx,
224
226
  state->shutdown = true;
225
227
  gpr_mu_init(&state->mu);
226
228
 
227
- const size_t naddrs = resolved->naddrs;
228
- errors = gpr_malloc(sizeof(*errors) * naddrs);
229
+ naddrs = resolved->naddrs;
230
+ errors = (grpc_error **)gpr_malloc(sizeof(*errors) * naddrs);
229
231
  for (i = 0; i < naddrs; i++) {
230
232
  errors[i] =
231
233
  grpc_tcp_server_add_port(tcp_server, &resolved->addrs[i], &port_temp);
@@ -23,6 +23,7 @@
23
23
  void grpc_chttp2_plugin_init(void) {
24
24
  grpc_register_tracer(&grpc_http_trace);
25
25
  grpc_register_tracer(&grpc_flowctl_trace);
26
+ grpc_register_tracer(&grpc_trace_http2_stream_state);
26
27
  #ifndef NDEBUG
27
28
  grpc_register_tracer(&grpc_trace_chttp2_refcount);
28
29
  #endif
@@ -34,6 +34,7 @@
34
34
  #include "src/core/ext/transport/chttp2/transport/varint.h"
35
35
  #include "src/core/lib/channel/channel_args.h"
36
36
  #include "src/core/lib/compression/stream_compression.h"
37
+ #include "src/core/lib/debug/stats.h"
37
38
  #include "src/core/lib/http/parser.h"
38
39
  #include "src/core/lib/iomgr/executor.h"
39
40
  #include "src/core/lib/iomgr/timer.h"
@@ -63,6 +64,11 @@
63
64
  #define DEFAULT_KEEPALIVE_PERMIT_WITHOUT_CALLS false
64
65
  #define KEEPALIVE_TIME_BACKOFF_MULTIPLIER 2
65
66
 
67
+ #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
+
66
72
  static int g_default_client_keepalive_time_ms =
67
73
  DEFAULT_CLIENT_KEEPALIVE_TIME_MS;
68
74
  static int g_default_client_keepalive_timeout_ms =
@@ -74,6 +80,13 @@ static int g_default_server_keepalive_timeout_ms =
74
80
  static bool g_default_keepalive_permit_without_calls =
75
81
  DEFAULT_KEEPALIVE_PERMIT_WITHOUT_CALLS;
76
82
 
83
+ static int g_default_min_sent_ping_interval_without_data_ms =
84
+ DEFAULT_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS;
85
+ static int g_default_min_recv_ping_interval_without_data_ms =
86
+ DEFAULT_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS;
87
+ static int g_default_max_pings_without_data = DEFAULT_MAX_PINGS_BETWEEN_DATA;
88
+ static int g_default_max_ping_strikes = DEFAULT_MAX_PING_STRIKES;
89
+
77
90
  #define MAX_CLIENT_STREAM_ID 0x7fffffffu
78
91
  grpc_tracer_flag grpc_http_trace = GRPC_TRACER_INITIALIZER(false, "http");
79
92
  grpc_tracer_flag grpc_flowctl_trace = GRPC_TRACER_INITIALIZER(false, "flowctl");
@@ -83,8 +96,6 @@ grpc_tracer_flag grpc_trace_chttp2_refcount =
83
96
  GRPC_TRACER_INITIALIZER(false, "chttp2_refcount");
84
97
  #endif
85
98
 
86
- static const grpc_transport_vtable vtable;
87
-
88
99
  /* forward declarations of various callbacks that we'll build closures around */
89
100
  static void write_action_begin_locked(grpc_exec_ctx *exec_ctx, void *t,
90
101
  grpc_error *error);
@@ -145,18 +156,14 @@ static void finish_bdp_ping_locked(grpc_exec_ctx *exec_ctx, void *tp,
145
156
 
146
157
  static void cancel_pings(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
147
158
  grpc_error *error);
148
- static void send_ping_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
149
- grpc_chttp2_ping_type ping_type,
150
- grpc_closure *on_initiate,
151
- grpc_closure *on_complete);
159
+ static 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);
152
164
  static void retry_initiate_ping_locked(grpc_exec_ctx *exec_ctx, void *tp,
153
165
  grpc_error *error);
154
166
 
155
- #define DEFAULT_MIN_TIME_BETWEEN_PINGS_MS 0
156
- #define DEFAULT_MAX_PINGS_BETWEEN_DATA 3
157
- #define DEFAULT_MAX_PING_STRIKES 2
158
- #define DEFAULT_MIN_PING_INTERVAL_WITHOUT_DATA_MS 300000 /* 5 minutes */
159
-
160
167
  /** keepalive-relevant functions */
161
168
  static void init_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg,
162
169
  grpc_error *error);
@@ -247,6 +254,8 @@ void grpc_chttp2_unref_transport(grpc_exec_ctx *exec_ctx,
247
254
  void grpc_chttp2_ref_transport(grpc_chttp2_transport *t) { gpr_ref(&t->refs); }
248
255
  #endif
249
256
 
257
+ static const grpc_transport_vtable *get_vtable(void);
258
+
250
259
  static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
251
260
  const grpc_channel_args *channel_args,
252
261
  grpc_endpoint *ep, bool is_client) {
@@ -256,7 +265,7 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
256
265
  GPR_ASSERT(strlen(GRPC_CHTTP2_CLIENT_CONNECT_STRING) ==
257
266
  GRPC_CHTTP2_CLIENT_CONNECT_STRLEN);
258
267
 
259
- t->base.vtable = &vtable;
268
+ t->base.vtable = get_vtable();
260
269
  t->ep = ep;
261
270
  /* one ref is for destroy */
262
271
  gpr_ref_init(&t->refs, 1);
@@ -345,7 +354,6 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
345
354
  if (is_client) {
346
355
  grpc_slice_buffer_add(&t->outbuf, grpc_slice_from_copied_string(
347
356
  GRPC_CHTTP2_CLIENT_CONNECT_STRING));
348
- grpc_chttp2_initiate_write(exec_ctx, t, "initial_write");
349
357
  }
350
358
 
351
359
  /* configure http2 the way we like it */
@@ -361,14 +369,12 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
361
369
  queue_setting_update(exec_ctx, t,
362
370
  GRPC_CHTTP2_SETTINGS_GRPC_ALLOW_TRUE_BINARY_METADATA, 1);
363
371
 
364
- t->ping_policy = (grpc_chttp2_repeated_ping_policy){
365
- .max_pings_without_data = DEFAULT_MAX_PINGS_BETWEEN_DATA,
366
- .min_time_between_pings =
367
- gpr_time_from_millis(DEFAULT_MIN_TIME_BETWEEN_PINGS_MS, GPR_TIMESPAN),
368
- .max_ping_strikes = DEFAULT_MAX_PING_STRIKES,
369
- .min_ping_interval_without_data = gpr_time_from_millis(
370
- DEFAULT_MIN_PING_INTERVAL_WITHOUT_DATA_MS, GPR_TIMESPAN),
371
- };
372
+ t->ping_policy.max_pings_without_data = g_default_max_pings_without_data;
373
+ t->ping_policy.min_sent_ping_interval_without_data = gpr_time_from_millis(
374
+ g_default_min_sent_ping_interval_without_data_ms, GPR_TIMESPAN);
375
+ t->ping_policy.max_ping_strikes = g_default_max_ping_strikes;
376
+ t->ping_policy.min_recv_ping_interval_without_data = gpr_time_from_millis(
377
+ g_default_min_recv_ping_interval_without_data_ms, GPR_TIMESPAN);
372
378
 
373
379
  /* Keepalive setting */
374
380
  if (t->is_client) {
@@ -427,29 +433,37 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
427
433
  GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA)) {
428
434
  t->ping_policy.max_pings_without_data = grpc_channel_arg_get_integer(
429
435
  &channel_args->args[i],
430
- (grpc_integer_options){DEFAULT_MAX_PINGS_BETWEEN_DATA, 0, INT_MAX});
436
+ (grpc_integer_options){g_default_max_pings_without_data, 0,
437
+ INT_MAX});
431
438
  } else if (0 == strcmp(channel_args->args[i].key,
432
439
  GRPC_ARG_HTTP2_MAX_PING_STRIKES)) {
433
440
  t->ping_policy.max_ping_strikes = grpc_channel_arg_get_integer(
434
441
  &channel_args->args[i],
435
- (grpc_integer_options){DEFAULT_MAX_PING_STRIKES, 0, INT_MAX});
436
- } else if (0 == strcmp(channel_args->args[i].key,
437
- GRPC_ARG_HTTP2_MIN_TIME_BETWEEN_PINGS_MS)) {
438
- t->ping_policy.min_time_between_pings = gpr_time_from_millis(
439
- grpc_channel_arg_get_integer(
440
- &channel_args->args[i],
441
- (grpc_integer_options){DEFAULT_MIN_TIME_BETWEEN_PINGS_MS, 0,
442
- INT_MAX}),
443
- GPR_TIMESPAN);
442
+ (grpc_integer_options){g_default_max_ping_strikes, 0, INT_MAX});
444
443
  } else if (0 ==
445
- strcmp(channel_args->args[i].key,
446
- GRPC_ARG_HTTP2_MIN_PING_INTERVAL_WITHOUT_DATA_MS)) {
447
- t->ping_policy.min_ping_interval_without_data = gpr_time_from_millis(
448
- grpc_channel_arg_get_integer(
449
- &channel_args->args[i],
450
- (grpc_integer_options){
451
- DEFAULT_MIN_PING_INTERVAL_WITHOUT_DATA_MS, 0, INT_MAX}),
452
- GPR_TIMESPAN);
444
+ strcmp(
445
+ channel_args->args[i].key,
446
+ GRPC_ARG_HTTP2_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS)) {
447
+ t->ping_policy.min_sent_ping_interval_without_data =
448
+ gpr_time_from_millis(
449
+ grpc_channel_arg_get_integer(
450
+ &channel_args->args[i],
451
+ (grpc_integer_options){
452
+ g_default_min_sent_ping_interval_without_data_ms, 0,
453
+ INT_MAX}),
454
+ GPR_TIMESPAN);
455
+ } else if (0 ==
456
+ strcmp(
457
+ channel_args->args[i].key,
458
+ GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS)) {
459
+ t->ping_policy.min_recv_ping_interval_without_data =
460
+ gpr_time_from_millis(
461
+ grpc_channel_arg_get_integer(
462
+ &channel_args->args[i],
463
+ (grpc_integer_options){
464
+ g_default_min_recv_ping_interval_without_data_ms, 0,
465
+ INT_MAX}),
466
+ GPR_TIMESPAN);
453
467
  } else if (0 == strcmp(channel_args->args[i].key,
454
468
  GRPC_ARG_HTTP2_WRITE_BUFFER_SIZE)) {
455
469
  t->write_buffer_size = (uint32_t)grpc_channel_arg_get_integer(
@@ -556,13 +570,8 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
556
570
  }
557
571
  }
558
572
 
559
- GRPC_CLOSURE_INIT(&t->write_action, write_action, t,
560
- t->opt_target == GRPC_CHTTP2_OPTIMIZE_FOR_THROUGHPUT
561
- ? grpc_executor_scheduler
562
- : grpc_schedule_on_exec_ctx);
563
-
564
- t->ping_state.pings_before_data_required =
565
- t->ping_policy.max_pings_without_data;
573
+ /* No pings allowed before receiving a header or data frame. */
574
+ t->ping_state.pings_before_data_required = 0;
566
575
  t->ping_state.is_delayed_ping_timer_set = false;
567
576
 
568
577
  t->ping_recv_state.last_ping_recv_time = gpr_inf_past(GPR_CLOCK_MONOTONIC);
@@ -582,13 +591,14 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
582
591
  t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_DISABLED;
583
592
  }
584
593
 
585
- grpc_chttp2_initiate_write(exec_ctx, t, "init");
594
+ grpc_chttp2_initiate_write(exec_ctx, t,
595
+ GRPC_CHTTP2_INITIATE_WRITE_INITIAL_WRITE);
586
596
  post_benign_reclaimer(exec_ctx, t);
587
597
  }
588
598
 
589
599
  static void destroy_transport_locked(grpc_exec_ctx *exec_ctx, void *tp,
590
600
  grpc_error *error) {
591
- grpc_chttp2_transport *t = tp;
601
+ grpc_chttp2_transport *t = (grpc_chttp2_transport *)tp;
592
602
  t->destroying = 1;
593
603
  close_transport_locked(
594
604
  exec_ctx, t,
@@ -628,6 +638,9 @@ static void close_transport_locked(grpc_exec_ctx *exec_ctx,
628
638
  connectivity_state_set(exec_ctx, t, GRPC_CHANNEL_SHUTDOWN,
629
639
  GRPC_ERROR_REF(error), "close_transport");
630
640
  grpc_endpoint_shutdown(exec_ctx, t->ep, GRPC_ERROR_REF(error));
641
+ if (t->ping_state.is_delayed_ping_timer_set) {
642
+ grpc_timer_cancel(exec_ctx, &t->ping_state.delayed_ping_timer);
643
+ }
631
644
  switch (t->keepalive_state) {
632
645
  case GRPC_CHTTP2_KEEPALIVE_STATE_WAITING:
633
646
  grpc_timer_cancel(exec_ctx, &t->keepalive_ping_timer);
@@ -693,7 +706,10 @@ static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
693
706
  grpc_schedule_on_exec_ctx);
694
707
  grpc_slice_buffer_init(&s->unprocessed_incoming_frames_buffer);
695
708
  grpc_slice_buffer_init(&s->frame_storage);
709
+ grpc_slice_buffer_init(&s->compressed_data_buffer);
710
+ grpc_slice_buffer_init(&s->decompressed_data_buffer);
696
711
  s->pending_byte_stream = false;
712
+ s->decompressed_header_bytes = 0;
697
713
  GRPC_CLOSURE_INIT(&s->reset_byte_stream, reset_byte_stream, s,
698
714
  grpc_combiner_scheduler(t->combiner));
699
715
 
@@ -714,7 +730,7 @@ static int init_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
714
730
 
715
731
  static void destroy_stream_locked(grpc_exec_ctx *exec_ctx, void *sp,
716
732
  grpc_error *error) {
717
- grpc_chttp2_stream *s = sp;
733
+ grpc_chttp2_stream *s = (grpc_chttp2_stream *)sp;
718
734
  grpc_chttp2_transport *t = s->t;
719
735
 
720
736
  GPR_TIMER_BEGIN("destroy_stream", 0);
@@ -727,14 +743,8 @@ static void destroy_stream_locked(grpc_exec_ctx *exec_ctx, void *sp,
727
743
  grpc_slice_buffer_destroy_internal(exec_ctx,
728
744
  &s->unprocessed_incoming_frames_buffer);
729
745
  grpc_slice_buffer_destroy_internal(exec_ctx, &s->frame_storage);
730
- if (s->compressed_data_buffer) {
731
- grpc_slice_buffer_destroy_internal(exec_ctx, s->compressed_data_buffer);
732
- gpr_free(s->compressed_data_buffer);
733
- }
734
- if (s->decompressed_data_buffer) {
735
- grpc_slice_buffer_destroy_internal(exec_ctx, s->decompressed_data_buffer);
736
- gpr_free(s->decompressed_data_buffer);
737
- }
746
+ grpc_slice_buffer_destroy_internal(exec_ctx, &s->compressed_data_buffer);
747
+ grpc_slice_buffer_destroy_internal(exec_ctx, &s->decompressed_data_buffer);
738
748
 
739
749
  grpc_chttp2_list_remove_stalled_by_transport(t, s);
740
750
  grpc_chttp2_list_remove_stalled_by_stream(t, s);
@@ -798,7 +808,7 @@ static void destroy_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
798
808
 
799
809
  grpc_chttp2_stream *grpc_chttp2_parsing_lookup_stream(grpc_chttp2_transport *t,
800
810
  uint32_t id) {
801
- return grpc_chttp2_stream_map_find(&t->stream_map, id);
811
+ return (grpc_chttp2_stream *)grpc_chttp2_stream_map_find(&t->stream_map, id);
802
812
  }
803
813
 
804
814
  grpc_chttp2_stream *grpc_chttp2_parsing_accept_stream(grpc_exec_ctx *exec_ctx,
@@ -850,13 +860,92 @@ static void set_write_state(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
850
860
  }
851
861
  }
852
862
 
863
+ static void inc_initiate_write_reason(
864
+ grpc_exec_ctx *exec_ctx, grpc_chttp2_initiate_write_reason reason) {
865
+ switch (reason) {
866
+ case GRPC_CHTTP2_INITIATE_WRITE_INITIAL_WRITE:
867
+ GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_INITIAL_WRITE(exec_ctx);
868
+ break;
869
+ case GRPC_CHTTP2_INITIATE_WRITE_START_NEW_STREAM:
870
+ GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_START_NEW_STREAM(exec_ctx);
871
+ break;
872
+ case GRPC_CHTTP2_INITIATE_WRITE_SEND_MESSAGE:
873
+ GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_SEND_MESSAGE(exec_ctx);
874
+ break;
875
+ case GRPC_CHTTP2_INITIATE_WRITE_SEND_INITIAL_METADATA:
876
+ GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_SEND_INITIAL_METADATA(
877
+ exec_ctx);
878
+ break;
879
+ case GRPC_CHTTP2_INITIATE_WRITE_SEND_TRAILING_METADATA:
880
+ GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_SEND_TRAILING_METADATA(
881
+ exec_ctx);
882
+ break;
883
+ case GRPC_CHTTP2_INITIATE_WRITE_RETRY_SEND_PING:
884
+ GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_RETRY_SEND_PING(exec_ctx);
885
+ break;
886
+ case GRPC_CHTTP2_INITIATE_WRITE_CONTINUE_PINGS:
887
+ GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_CONTINUE_PINGS(exec_ctx);
888
+ break;
889
+ case GRPC_CHTTP2_INITIATE_WRITE_GOAWAY_SENT:
890
+ GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_GOAWAY_SENT(exec_ctx);
891
+ break;
892
+ case GRPC_CHTTP2_INITIATE_WRITE_RST_STREAM:
893
+ GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_RST_STREAM(exec_ctx);
894
+ break;
895
+ case GRPC_CHTTP2_INITIATE_WRITE_CLOSE_FROM_API:
896
+ GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_CLOSE_FROM_API(exec_ctx);
897
+ break;
898
+ case GRPC_CHTTP2_INITIATE_WRITE_STREAM_FLOW_CONTROL:
899
+ GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_STREAM_FLOW_CONTROL(exec_ctx);
900
+ break;
901
+ case GRPC_CHTTP2_INITIATE_WRITE_TRANSPORT_FLOW_CONTROL:
902
+ GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_TRANSPORT_FLOW_CONTROL(
903
+ exec_ctx);
904
+ break;
905
+ case GRPC_CHTTP2_INITIATE_WRITE_SEND_SETTINGS:
906
+ GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_SEND_SETTINGS(exec_ctx);
907
+ break;
908
+ case GRPC_CHTTP2_INITIATE_WRITE_BDP_ESTIMATOR_PING:
909
+ GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_BDP_ESTIMATOR_PING(exec_ctx);
910
+ break;
911
+ case GRPC_CHTTP2_INITIATE_WRITE_FLOW_CONTROL_UNSTALLED_BY_SETTING:
912
+ GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_FLOW_CONTROL_UNSTALLED_BY_SETTING(
913
+ exec_ctx);
914
+ break;
915
+ case GRPC_CHTTP2_INITIATE_WRITE_FLOW_CONTROL_UNSTALLED_BY_UPDATE:
916
+ GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_FLOW_CONTROL_UNSTALLED_BY_UPDATE(
917
+ exec_ctx);
918
+ break;
919
+ case GRPC_CHTTP2_INITIATE_WRITE_APPLICATION_PING:
920
+ GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_APPLICATION_PING(exec_ctx);
921
+ break;
922
+ case GRPC_CHTTP2_INITIATE_WRITE_KEEPALIVE_PING:
923
+ GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_KEEPALIVE_PING(exec_ctx);
924
+ break;
925
+ case GRPC_CHTTP2_INITIATE_WRITE_TRANSPORT_FLOW_CONTROL_UNSTALLED:
926
+ GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_TRANSPORT_FLOW_CONTROL_UNSTALLED(
927
+ exec_ctx);
928
+ break;
929
+ case GRPC_CHTTP2_INITIATE_WRITE_PING_RESPONSE:
930
+ GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_PING_RESPONSE(exec_ctx);
931
+ break;
932
+ case GRPC_CHTTP2_INITIATE_WRITE_FORCE_RST_STREAM:
933
+ GRPC_STATS_INC_HTTP2_INITIATE_WRITE_DUE_TO_FORCE_RST_STREAM(exec_ctx);
934
+ break;
935
+ }
936
+ }
937
+
853
938
  void grpc_chttp2_initiate_write(grpc_exec_ctx *exec_ctx,
854
- grpc_chttp2_transport *t, const char *reason) {
939
+ grpc_chttp2_transport *t,
940
+ grpc_chttp2_initiate_write_reason reason) {
855
941
  GPR_TIMER_BEGIN("grpc_chttp2_initiate_write", 0);
856
942
 
857
943
  switch (t->write_state) {
858
944
  case GRPC_CHTTP2_WRITE_STATE_IDLE:
859
- set_write_state(exec_ctx, t, GRPC_CHTTP2_WRITE_STATE_WRITING, reason);
945
+ inc_initiate_write_reason(exec_ctx, reason);
946
+ set_write_state(exec_ctx, t, GRPC_CHTTP2_WRITE_STATE_WRITING,
947
+ grpc_chttp2_initiate_write_reason_string(reason));
948
+ t->is_first_write_in_batch = true;
860
949
  GRPC_CHTTP2_REF_TRANSPORT(t, "writing");
861
950
  GRPC_CLOSURE_SCHED(
862
951
  exec_ctx,
@@ -867,7 +956,7 @@ void grpc_chttp2_initiate_write(grpc_exec_ctx *exec_ctx,
867
956
  break;
868
957
  case GRPC_CHTTP2_WRITE_STATE_WRITING:
869
958
  set_write_state(exec_ctx, t, GRPC_CHTTP2_WRITE_STATE_WRITING_WITH_MORE,
870
- reason);
959
+ grpc_chttp2_initiate_write_reason_string(reason));
871
960
  break;
872
961
  case GRPC_CHTTP2_WRITE_STATE_WRITING_WITH_MORE:
873
962
  break;
@@ -875,52 +964,96 @@ void grpc_chttp2_initiate_write(grpc_exec_ctx *exec_ctx,
875
964
  GPR_TIMER_END("grpc_chttp2_initiate_write", 0);
876
965
  }
877
966
 
878
- void grpc_chttp2_become_writable(
879
- grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s,
880
- grpc_chttp2_stream_write_type stream_write_type, const char *reason) {
967
+ void grpc_chttp2_mark_stream_writable(grpc_exec_ctx *exec_ctx,
968
+ grpc_chttp2_transport *t,
969
+ grpc_chttp2_stream *s) {
881
970
  if (!t->closed && grpc_chttp2_list_add_writable_stream(t, s)) {
882
971
  GRPC_CHTTP2_STREAM_REF(s, "chttp2_writing:become");
883
972
  }
884
- switch (stream_write_type) {
885
- case GRPC_CHTTP2_STREAM_WRITE_PIGGYBACK:
886
- break;
887
- case GRPC_CHTTP2_STREAM_WRITE_INITIATE_COVERED:
888
- grpc_chttp2_initiate_write(exec_ctx, t, reason);
889
- break;
890
- case GRPC_CHTTP2_STREAM_WRITE_INITIATE_UNCOVERED:
891
- grpc_chttp2_initiate_write(exec_ctx, t, reason);
892
- break;
973
+ }
974
+
975
+ static grpc_closure_scheduler *write_scheduler(grpc_chttp2_transport *t,
976
+ bool early_results_scheduled,
977
+ bool partial_write) {
978
+ /* if it's not the first write in a batch, always offload to the executor:
979
+ we'll probably end up queuing against the kernel anyway, so we'll likely
980
+ get better latency overall if we switch writing work elsewhere and continue
981
+ with application work above */
982
+ if (!t->is_first_write_in_batch) {
983
+ return grpc_executor_scheduler(GRPC_EXECUTOR_SHORT);
984
+ }
985
+ /* equivalently, if it's a partial write, we *know* we're going to be taking a
986
+ thread jump to write it because of the above, may as well do so
987
+ immediately */
988
+ if (partial_write) {
989
+ return grpc_executor_scheduler(GRPC_EXECUTOR_SHORT);
990
+ }
991
+ switch (t->opt_target) {
992
+ case GRPC_CHTTP2_OPTIMIZE_FOR_THROUGHPUT:
993
+ /* executor gives us the largest probability of being able to batch a
994
+ * write with others on this transport */
995
+ return grpc_executor_scheduler(GRPC_EXECUTOR_SHORT);
996
+ case GRPC_CHTTP2_OPTIMIZE_FOR_LATENCY:
997
+ return grpc_schedule_on_exec_ctx;
998
+ }
999
+ GPR_UNREACHABLE_CODE(return NULL);
1000
+ }
1001
+
1002
+ #define WRITE_STATE_TUPLE_TO_INT(p, i) (2 * (int)(p) + (int)(i))
1003
+ static const char *begin_writing_desc(bool partial, bool inlined) {
1004
+ switch (WRITE_STATE_TUPLE_TO_INT(partial, inlined)) {
1005
+ case WRITE_STATE_TUPLE_TO_INT(false, false):
1006
+ return "begin write in background";
1007
+ case WRITE_STATE_TUPLE_TO_INT(false, true):
1008
+ return "begin write in current thread";
1009
+ case WRITE_STATE_TUPLE_TO_INT(true, false):
1010
+ return "begin partial write in background";
1011
+ case WRITE_STATE_TUPLE_TO_INT(true, true):
1012
+ return "begin partial write in current thread";
893
1013
  }
1014
+ GPR_UNREACHABLE_CODE(return "bad state tuple");
894
1015
  }
895
1016
 
896
1017
  static void write_action_begin_locked(grpc_exec_ctx *exec_ctx, void *gt,
897
1018
  grpc_error *error_ignored) {
898
1019
  GPR_TIMER_BEGIN("write_action_begin_locked", 0);
899
- grpc_chttp2_transport *t = gt;
1020
+ grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
900
1021
  GPR_ASSERT(t->write_state != GRPC_CHTTP2_WRITE_STATE_IDLE);
901
- switch (t->closed ? GRPC_CHTTP2_NOTHING_TO_WRITE
902
- : grpc_chttp2_begin_write(exec_ctx, t)) {
903
- case GRPC_CHTTP2_NOTHING_TO_WRITE:
904
- set_write_state(exec_ctx, t, GRPC_CHTTP2_WRITE_STATE_IDLE,
905
- "begin writing nothing");
906
- GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "writing");
907
- break;
908
- case GRPC_CHTTP2_PARTIAL_WRITE:
909
- set_write_state(exec_ctx, t, GRPC_CHTTP2_WRITE_STATE_WRITING_WITH_MORE,
910
- "begin writing partial");
911
- GRPC_CLOSURE_SCHED(exec_ctx, &t->write_action, GRPC_ERROR_NONE);
912
- break;
913
- case GRPC_CHTTP2_FULL_WRITE:
914
- set_write_state(exec_ctx, t, GRPC_CHTTP2_WRITE_STATE_WRITING,
915
- "begin writing");
916
- GRPC_CLOSURE_SCHED(exec_ctx, &t->write_action, GRPC_ERROR_NONE);
917
- break;
1022
+ grpc_chttp2_begin_write_result r;
1023
+ if (t->closed) {
1024
+ r.writing = false;
1025
+ } else {
1026
+ r = grpc_chttp2_begin_write(exec_ctx, t);
1027
+ }
1028
+ if (r.writing) {
1029
+ if (r.partial) {
1030
+ GRPC_STATS_INC_HTTP2_PARTIAL_WRITES(exec_ctx);
1031
+ }
1032
+ if (!t->is_first_write_in_batch) {
1033
+ GRPC_STATS_INC_HTTP2_WRITES_CONTINUED(exec_ctx);
1034
+ }
1035
+ grpc_closure_scheduler *scheduler =
1036
+ write_scheduler(t, r.early_results_scheduled, r.partial);
1037
+ if (scheduler != grpc_schedule_on_exec_ctx) {
1038
+ GRPC_STATS_INC_HTTP2_WRITES_OFFLOADED(exec_ctx);
1039
+ }
1040
+ set_write_state(
1041
+ exec_ctx, t, r.partial ? GRPC_CHTTP2_WRITE_STATE_WRITING_WITH_MORE
1042
+ : GRPC_CHTTP2_WRITE_STATE_WRITING,
1043
+ begin_writing_desc(r.partial, scheduler == grpc_schedule_on_exec_ctx));
1044
+ GRPC_CLOSURE_SCHED(exec_ctx, GRPC_CLOSURE_INIT(&t->write_action,
1045
+ write_action, t, scheduler),
1046
+ GRPC_ERROR_NONE);
1047
+ } else {
1048
+ set_write_state(exec_ctx, t, GRPC_CHTTP2_WRITE_STATE_IDLE,
1049
+ "begin writing nothing");
1050
+ GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "writing");
918
1051
  }
919
1052
  GPR_TIMER_END("write_action_begin_locked", 0);
920
1053
  }
921
1054
 
922
1055
  static void write_action(grpc_exec_ctx *exec_ctx, void *gt, grpc_error *error) {
923
- grpc_chttp2_transport *t = gt;
1056
+ grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
924
1057
  GPR_TIMER_BEGIN("write_action", 0);
925
1058
  grpc_endpoint_write(
926
1059
  exec_ctx, t->ep, &t->outbuf,
@@ -932,7 +1065,7 @@ static void write_action(grpc_exec_ctx *exec_ctx, void *gt, grpc_error *error) {
932
1065
  static void write_action_end_locked(grpc_exec_ctx *exec_ctx, void *tp,
933
1066
  grpc_error *error) {
934
1067
  GPR_TIMER_BEGIN("terminate_writing_with_lock", 0);
935
- grpc_chttp2_transport *t = tp;
1068
+ grpc_chttp2_transport *t = (grpc_chttp2_transport *)tp;
936
1069
 
937
1070
  if (error != GRPC_ERROR_NONE) {
938
1071
  close_transport_locked(exec_ctx, t, GRPC_ERROR_REF(error));
@@ -957,7 +1090,8 @@ static void write_action_end_locked(grpc_exec_ctx *exec_ctx, void *tp,
957
1090
  case GRPC_CHTTP2_WRITE_STATE_WRITING_WITH_MORE:
958
1091
  GPR_TIMER_MARK("state=writing_stale_no_poller", 0);
959
1092
  set_write_state(exec_ctx, t, GRPC_CHTTP2_WRITE_STATE_WRITING,
960
- "continue writing [!covered]");
1093
+ "continue writing");
1094
+ t->is_first_write_in_batch = false;
961
1095
  GRPC_CHTTP2_REF_TRANSPORT(t, "writing");
962
1096
  GRPC_CLOSURE_RUN(
963
1097
  exec_ctx,
@@ -1059,9 +1193,9 @@ static void maybe_start_some_streams(grpc_exec_ctx *exec_ctx,
1059
1193
 
1060
1194
  grpc_chttp2_stream_map_add(&t->stream_map, s->id, s);
1061
1195
  post_destructive_reclaimer(exec_ctx, t);
1062
- grpc_chttp2_become_writable(exec_ctx, t, s,
1063
- GRPC_CHTTP2_STREAM_WRITE_INITIATE_COVERED,
1064
- "new_stream");
1196
+ grpc_chttp2_mark_stream_writable(exec_ctx, t, s);
1197
+ grpc_chttp2_initiate_write(exec_ctx, t,
1198
+ GRPC_CHTTP2_INITIATE_WRITE_START_NEW_STREAM);
1065
1199
  }
1066
1200
  /* cancel out streams that will never be started */
1067
1201
  while (t->next_stream_id >= MAX_CLIENT_STREAM_ID &&
@@ -1110,12 +1244,14 @@ void grpc_chttp2_complete_closure_step(grpc_exec_ctx *exec_ctx,
1110
1244
  closure->next_data.scratch -= CLOSURE_BARRIER_FIRST_REF_BIT;
1111
1245
  if (GRPC_TRACER_ON(grpc_http_trace)) {
1112
1246
  const char *errstr = grpc_error_string(error);
1113
- gpr_log(GPR_DEBUG,
1114
- "complete_closure_step: %p refs=%d flags=0x%04x desc=%s err=%s",
1115
- closure,
1116
- (int)(closure->next_data.scratch / CLOSURE_BARRIER_FIRST_REF_BIT),
1117
- (int)(closure->next_data.scratch % CLOSURE_BARRIER_FIRST_REF_BIT),
1118
- desc, errstr);
1247
+ gpr_log(
1248
+ GPR_DEBUG,
1249
+ "complete_closure_step: t=%p %p refs=%d flags=0x%04x desc=%s err=%s "
1250
+ "write_state=%s",
1251
+ t, closure,
1252
+ (int)(closure->next_data.scratch / CLOSURE_BARRIER_FIRST_REF_BIT),
1253
+ (int)(closure->next_data.scratch % CLOSURE_BARRIER_FIRST_REF_BIT), desc,
1254
+ errstr, write_state_name(t->write_state));
1119
1255
  }
1120
1256
  if (error != GRPC_ERROR_NONE) {
1121
1257
  if (closure->error_data.error == GRPC_ERROR_NONE) {
@@ -1156,9 +1292,9 @@ static void maybe_become_writable_due_to_send_msg(grpc_exec_ctx *exec_ctx,
1156
1292
  grpc_chttp2_stream *s) {
1157
1293
  if (s->id != 0 && (!s->write_buffering ||
1158
1294
  s->flow_controlled_buffer.length > t->write_buffer_size)) {
1159
- grpc_chttp2_become_writable(exec_ctx, t, s,
1160
- GRPC_CHTTP2_STREAM_WRITE_INITIATE_COVERED,
1161
- "op.send_message");
1295
+ grpc_chttp2_mark_stream_writable(exec_ctx, t, s);
1296
+ grpc_chttp2_initiate_write(exec_ctx, t,
1297
+ GRPC_CHTTP2_INITIATE_WRITE_SEND_MESSAGE);
1162
1298
  }
1163
1299
  }
1164
1300
 
@@ -1190,15 +1326,19 @@ static void continue_fetching_send_locked(grpc_exec_ctx *exec_ctx,
1190
1326
  } else {
1191
1327
  grpc_chttp2_write_cb *cb = t->write_cb_pool;
1192
1328
  if (cb == NULL) {
1193
- cb = gpr_malloc(sizeof(*cb));
1329
+ cb = (grpc_chttp2_write_cb *)gpr_malloc(sizeof(*cb));
1194
1330
  } else {
1195
1331
  t->write_cb_pool = cb->next;
1196
1332
  }
1197
1333
  cb->call_at_byte = notify_offset;
1198
1334
  cb->closure = s->fetching_send_message_finished;
1199
1335
  s->fetching_send_message_finished = NULL;
1200
- cb->next = s->on_write_finished_cbs;
1201
- s->on_write_finished_cbs = cb;
1336
+ grpc_chttp2_write_cb **list =
1337
+ s->fetching_send_message->flags & GRPC_WRITE_THROUGH
1338
+ ? &s->on_write_finished_cbs
1339
+ : &s->on_flow_controlled_cbs;
1340
+ cb->next = *list;
1341
+ *list = cb;
1202
1342
  }
1203
1343
  s->fetching_send_message = NULL;
1204
1344
  return; /* early out */
@@ -1218,7 +1358,7 @@ static void continue_fetching_send_locked(grpc_exec_ctx *exec_ctx,
1218
1358
 
1219
1359
  static void complete_fetch_locked(grpc_exec_ctx *exec_ctx, void *gs,
1220
1360
  grpc_error *error) {
1221
- grpc_chttp2_stream *s = gs;
1361
+ grpc_chttp2_stream *s = (grpc_chttp2_stream *)gs;
1222
1362
  grpc_chttp2_transport *t = s->t;
1223
1363
  if (error == GRPC_ERROR_NONE) {
1224
1364
  error = grpc_byte_stream_pull(exec_ctx, s->fetching_send_message,
@@ -1253,11 +1393,14 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op,
1253
1393
  grpc_error *error_ignored) {
1254
1394
  GPR_TIMER_BEGIN("perform_stream_op_locked", 0);
1255
1395
 
1256
- grpc_transport_stream_op_batch *op = stream_op;
1257
- grpc_chttp2_stream *s = op->handler_private.extra_arg;
1396
+ grpc_transport_stream_op_batch *op =
1397
+ (grpc_transport_stream_op_batch *)stream_op;
1398
+ grpc_chttp2_stream *s = (grpc_chttp2_stream *)op->handler_private.extra_arg;
1258
1399
  grpc_transport_stream_op_batch_payload *op_payload = op->payload;
1259
1400
  grpc_chttp2_transport *t = s->t;
1260
1401
 
1402
+ GRPC_STATS_INC_HTTP2_OP_BATCHES(exec_ctx);
1403
+
1261
1404
  if (GRPC_TRACER_ON(grpc_http_trace)) {
1262
1405
  char *str = grpc_transport_stream_op_batch_string(op);
1263
1406
  gpr_log(GPR_DEBUG, "perform_stream_op_locked: %s; on_complete = %p", str,
@@ -1291,13 +1434,27 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op,
1291
1434
  }
1292
1435
 
1293
1436
  if (op->cancel_stream) {
1437
+ GRPC_STATS_INC_HTTP2_OP_CANCEL(exec_ctx);
1294
1438
  grpc_chttp2_cancel_stream(exec_ctx, t, s,
1295
1439
  op_payload->cancel_stream.cancel_error);
1296
1440
  }
1297
1441
 
1298
1442
  if (op->send_initial_metadata) {
1443
+ GRPC_STATS_INC_HTTP2_OP_SEND_INITIAL_METADATA(exec_ctx);
1299
1444
  GPR_ASSERT(s->send_initial_metadata_finished == NULL);
1300
1445
  on_complete->next_data.scratch |= CLOSURE_BARRIER_MAY_COVER_WRITE;
1446
+
1447
+ /* Identify stream compression */
1448
+ if (op_payload->send_initial_metadata.send_initial_metadata->idx.named
1449
+ .content_encoding == NULL ||
1450
+ grpc_stream_compression_method_parse(
1451
+ GRPC_MDVALUE(
1452
+ op_payload->send_initial_metadata.send_initial_metadata->idx
1453
+ .named.content_encoding->md),
1454
+ true, &s->stream_compression_method) == 0) {
1455
+ s->stream_compression_method = GRPC_STREAM_COMPRESSION_IDENTITY_COMPRESS;
1456
+ }
1457
+
1301
1458
  s->send_initial_metadata_finished = add_closure_barrier(on_complete);
1302
1459
  s->send_initial_metadata =
1303
1460
  op_payload->send_initial_metadata.send_initial_metadata;
@@ -1341,15 +1498,13 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op,
1341
1498
  }
1342
1499
  } else {
1343
1500
  GPR_ASSERT(s->id != 0);
1344
- grpc_chttp2_stream_write_type write_type =
1345
- GRPC_CHTTP2_STREAM_WRITE_INITIATE_COVERED;
1346
- if (op->send_message &&
1347
- (op->payload->send_message.send_message->flags &
1348
- GRPC_WRITE_BUFFER_HINT)) {
1349
- write_type = GRPC_CHTTP2_STREAM_WRITE_PIGGYBACK;
1501
+ grpc_chttp2_mark_stream_writable(exec_ctx, t, s);
1502
+ if (!(op->send_message &&
1503
+ (op->payload->send_message.send_message->flags &
1504
+ GRPC_WRITE_BUFFER_HINT))) {
1505
+ grpc_chttp2_initiate_write(
1506
+ exec_ctx, t, GRPC_CHTTP2_INITIATE_WRITE_SEND_INITIAL_METADATA);
1350
1507
  }
1351
- grpc_chttp2_become_writable(exec_ctx, t, s, write_type,
1352
- "op.send_initial_metadata");
1353
1508
  }
1354
1509
  } else {
1355
1510
  s->send_initial_metadata = NULL;
@@ -1361,17 +1516,31 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op,
1361
1516
  "send_initial_metadata_finished");
1362
1517
  }
1363
1518
  }
1519
+ if (op_payload->send_initial_metadata.peer_string != NULL) {
1520
+ gpr_atm_rel_store(op_payload->send_initial_metadata.peer_string,
1521
+ (gpr_atm)gpr_strdup(t->peer_string));
1522
+ }
1364
1523
  }
1365
1524
 
1366
1525
  if (op->send_message) {
1526
+ GRPC_STATS_INC_HTTP2_OP_SEND_MESSAGE(exec_ctx);
1527
+ GRPC_STATS_INC_HTTP2_SEND_MESSAGE_SIZE(
1528
+ exec_ctx, op->payload->send_message.send_message->length);
1367
1529
  on_complete->next_data.scratch |= CLOSURE_BARRIER_MAY_COVER_WRITE;
1368
1530
  s->fetching_send_message_finished = add_closure_barrier(op->on_complete);
1369
1531
  if (s->write_closed) {
1532
+ // Return an error unless the client has already received trailing
1533
+ // metadata from the server, since an application using a
1534
+ // streaming call might send another message before getting a
1535
+ // recv_message failure, breaking out of its loop, and then
1536
+ // starting recv_trailing_metadata.
1370
1537
  grpc_chttp2_complete_closure_step(
1371
1538
  exec_ctx, t, s, &s->fetching_send_message_finished,
1372
- GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
1373
- "Attempt to send message after stream was closed",
1374
- &s->write_closed_error, 1),
1539
+ t->is_client && s->received_trailing_metadata
1540
+ ? GRPC_ERROR_NONE
1541
+ : GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
1542
+ "Attempt to send message after stream was closed",
1543
+ &s->write_closed_error, 1),
1375
1544
  "fetching_send_message_finished");
1376
1545
  } else {
1377
1546
  GPR_ASSERT(s->fetching_send_message == NULL);
@@ -1401,6 +1570,7 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op,
1401
1570
  }
1402
1571
 
1403
1572
  if (op->send_trailing_metadata) {
1573
+ GRPC_STATS_INC_HTTP2_OP_SEND_TRAILING_METADATA(exec_ctx);
1404
1574
  GPR_ASSERT(s->send_trailing_metadata_finished == NULL);
1405
1575
  on_complete->next_data.scratch |= CLOSURE_BARRIER_MAY_COVER_WRITE;
1406
1576
  s->send_trailing_metadata_finished = add_closure_barrier(on_complete);
@@ -1442,14 +1612,15 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op,
1442
1612
  } else if (s->id != 0) {
1443
1613
  /* TODO(ctiller): check if there's flow control for any outstanding
1444
1614
  bytes before going writable */
1445
- grpc_chttp2_become_writable(exec_ctx, t, s,
1446
- GRPC_CHTTP2_STREAM_WRITE_INITIATE_COVERED,
1447
- "op.send_trailing_metadata");
1615
+ grpc_chttp2_mark_stream_writable(exec_ctx, t, s);
1616
+ grpc_chttp2_initiate_write(
1617
+ exec_ctx, t, GRPC_CHTTP2_INITIATE_WRITE_SEND_TRAILING_METADATA);
1448
1618
  }
1449
1619
  }
1450
1620
  }
1451
1621
 
1452
1622
  if (op->recv_initial_metadata) {
1623
+ GRPC_STATS_INC_HTTP2_OP_RECV_INITIAL_METADATA(exec_ctx);
1453
1624
  GPR_ASSERT(s->recv_initial_metadata_ready == NULL);
1454
1625
  s->recv_initial_metadata_ready =
1455
1626
  op_payload->recv_initial_metadata.recv_initial_metadata_ready;
@@ -1457,10 +1628,15 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op,
1457
1628
  op_payload->recv_initial_metadata.recv_initial_metadata;
1458
1629
  s->trailing_metadata_available =
1459
1630
  op_payload->recv_initial_metadata.trailing_metadata_available;
1631
+ if (op_payload->recv_initial_metadata.peer_string != NULL) {
1632
+ gpr_atm_rel_store(op_payload->recv_initial_metadata.peer_string,
1633
+ (gpr_atm)gpr_strdup(t->peer_string));
1634
+ }
1460
1635
  grpc_chttp2_maybe_complete_recv_initial_metadata(exec_ctx, t, s);
1461
1636
  }
1462
1637
 
1463
1638
  if (op->recv_message) {
1639
+ GRPC_STATS_INC_HTTP2_OP_RECV_MESSAGE(exec_ctx);
1464
1640
  size_t already_received;
1465
1641
  GPR_ASSERT(s->recv_message_ready == NULL);
1466
1642
  GPR_ASSERT(!s->pending_byte_stream);
@@ -1482,6 +1658,7 @@ static void perform_stream_op_locked(grpc_exec_ctx *exec_ctx, void *stream_op,
1482
1658
  }
1483
1659
 
1484
1660
  if (op->recv_trailing_metadata) {
1661
+ GRPC_STATS_INC_HTTP2_OP_RECV_TRAILING_METADATA(exec_ctx);
1485
1662
  GPR_ASSERT(s->recv_trailing_metadata_finished == NULL);
1486
1663
  s->recv_trailing_metadata_finished = add_closure_barrier(on_complete);
1487
1664
  s->recv_trailing_metadata =
@@ -1549,23 +1726,28 @@ static void cancel_pings(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
1549
1726
  GRPC_ERROR_UNREF(error);
1550
1727
  }
1551
1728
 
1552
- static void send_ping_locked(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
1553
- grpc_chttp2_ping_type ping_type,
1554
- grpc_closure *on_initiate, grpc_closure *on_ack) {
1729
+ static void send_ping_locked(
1730
+ grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
1731
+ grpc_chttp2_ping_type ping_type, grpc_closure *on_initiate,
1732
+ grpc_closure *on_ack,
1733
+ grpc_chttp2_initiate_write_reason initiate_write_reason) {
1555
1734
  grpc_chttp2_ping_queue *pq = &t->ping_queues[ping_type];
1556
1735
  grpc_closure_list_append(&pq->lists[GRPC_CHTTP2_PCL_INITIATE], on_initiate,
1557
1736
  GRPC_ERROR_NONE);
1558
1737
  if (grpc_closure_list_append(&pq->lists[GRPC_CHTTP2_PCL_NEXT], on_ack,
1559
1738
  GRPC_ERROR_NONE)) {
1560
- grpc_chttp2_initiate_write(exec_ctx, t, "send_ping");
1739
+ grpc_chttp2_initiate_write(exec_ctx, t, initiate_write_reason);
1561
1740
  }
1562
1741
  }
1563
1742
 
1564
1743
  static void retry_initiate_ping_locked(grpc_exec_ctx *exec_ctx, void *tp,
1565
1744
  grpc_error *error) {
1566
- grpc_chttp2_transport *t = tp;
1745
+ grpc_chttp2_transport *t = (grpc_chttp2_transport *)tp;
1567
1746
  t->ping_state.is_delayed_ping_timer_set = false;
1568
- grpc_chttp2_initiate_write(exec_ctx, t, "retry_send_ping");
1747
+ if (error == GRPC_ERROR_NONE) {
1748
+ grpc_chttp2_initiate_write(exec_ctx, t,
1749
+ GRPC_CHTTP2_INITIATE_WRITE_RETRY_SEND_PING);
1750
+ }
1569
1751
  }
1570
1752
 
1571
1753
  void grpc_chttp2_ack_ping(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
@@ -1580,7 +1762,8 @@ void grpc_chttp2_ack_ping(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
1580
1762
  }
1581
1763
  GRPC_CLOSURE_LIST_SCHED(exec_ctx, &pq->lists[GRPC_CHTTP2_PCL_INFLIGHT]);
1582
1764
  if (!grpc_closure_list_empty(pq->lists[GRPC_CHTTP2_PCL_NEXT])) {
1583
- grpc_chttp2_initiate_write(exec_ctx, t, "continue_pings");
1765
+ grpc_chttp2_initiate_write(exec_ctx, t,
1766
+ GRPC_CHTTP2_INITIATE_WRITE_CONTINUE_PINGS);
1584
1767
  }
1585
1768
  }
1586
1769
 
@@ -1593,7 +1776,8 @@ static void send_goaway(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
1593
1776
  &slice, &http_error);
1594
1777
  grpc_chttp2_goaway_append(t->last_new_stream_id, (uint32_t)http_error,
1595
1778
  grpc_slice_ref_internal(slice), &t->qbuf);
1596
- grpc_chttp2_initiate_write(exec_ctx, t, "goaway_sent");
1779
+ grpc_chttp2_initiate_write(exec_ctx, t,
1780
+ GRPC_CHTTP2_INITIATE_WRITE_GOAWAY_SENT);
1597
1781
  GRPC_ERROR_UNREF(error);
1598
1782
  }
1599
1783
 
@@ -1615,8 +1799,9 @@ void grpc_chttp2_add_ping_strike(grpc_exec_ctx *exec_ctx,
1615
1799
  static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx,
1616
1800
  void *stream_op,
1617
1801
  grpc_error *error_ignored) {
1618
- grpc_transport_op *op = stream_op;
1619
- grpc_chttp2_transport *t = op->handler_private.extra_arg;
1802
+ grpc_transport_op *op = (grpc_transport_op *)stream_op;
1803
+ grpc_chttp2_transport *t =
1804
+ (grpc_chttp2_transport *)op->handler_private.extra_arg;
1620
1805
  grpc_error *close_transport = op->disconnect_with_error;
1621
1806
 
1622
1807
  if (op->goaway_error) {
@@ -1639,7 +1824,8 @@ static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx,
1639
1824
 
1640
1825
  if (op->send_ping) {
1641
1826
  send_ping_locked(exec_ctx, t, GRPC_CHTTP2_PING_ON_NEXT_WRITE, NULL,
1642
- op->send_ping);
1827
+ op->send_ping,
1828
+ GRPC_CHTTP2_INITIATE_WRITE_APPLICATION_PING);
1643
1829
  }
1644
1830
 
1645
1831
  if (op->on_connectivity_state_change != NULL) {
@@ -1715,20 +1901,20 @@ void grpc_chttp2_maybe_complete_recv_message(grpc_exec_ctx *exec_ctx,
1715
1901
  &s->frame_storage);
1716
1902
  s->unprocessed_incoming_frames_decompressed = false;
1717
1903
  }
1718
- if (s->stream_compression_recv_enabled &&
1719
- !s->unprocessed_incoming_frames_decompressed) {
1720
- GPR_ASSERT(s->decompressed_data_buffer->length == 0);
1904
+ if (!s->unprocessed_incoming_frames_decompressed) {
1905
+ GPR_ASSERT(s->decompressed_data_buffer.length == 0);
1721
1906
  bool end_of_context;
1722
1907
  if (!s->stream_decompression_ctx) {
1723
1908
  s->stream_decompression_ctx =
1724
1909
  grpc_stream_compression_context_create(
1725
- GRPC_STREAM_COMPRESSION_DECOMPRESS);
1910
+ s->stream_decompression_method);
1726
1911
  }
1727
- if (!grpc_stream_decompress(s->stream_decompression_ctx,
1728
- &s->unprocessed_incoming_frames_buffer,
1729
- s->decompressed_data_buffer, NULL,
1730
- GRPC_HEADER_SIZE_IN_BYTES,
1731
- &end_of_context)) {
1912
+ if (!grpc_stream_decompress(
1913
+ s->stream_decompression_ctx,
1914
+ &s->unprocessed_incoming_frames_buffer,
1915
+ &s->decompressed_data_buffer, NULL,
1916
+ GRPC_HEADER_SIZE_IN_BYTES - s->decompressed_header_bytes,
1917
+ &end_of_context)) {
1732
1918
  grpc_slice_buffer_reset_and_unref_internal(exec_ctx,
1733
1919
  &s->frame_storage);
1734
1920
  grpc_slice_buffer_reset_and_unref_internal(
@@ -1736,9 +1922,13 @@ void grpc_chttp2_maybe_complete_recv_message(grpc_exec_ctx *exec_ctx,
1736
1922
  error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
1737
1923
  "Stream decompression error.");
1738
1924
  } else {
1925
+ s->decompressed_header_bytes += s->decompressed_data_buffer.length;
1926
+ if (s->decompressed_header_bytes == GRPC_HEADER_SIZE_IN_BYTES) {
1927
+ s->decompressed_header_bytes = 0;
1928
+ }
1739
1929
  error = grpc_deframe_unprocessed_incoming_frames(
1740
- exec_ctx, &s->data_parser, s, s->decompressed_data_buffer, NULL,
1741
- s->recv_message);
1930
+ exec_ctx, &s->data_parser, s, &s->decompressed_data_buffer,
1931
+ NULL, s->recv_message);
1742
1932
  if (end_of_context) {
1743
1933
  grpc_stream_compression_context_destroy(
1744
1934
  s->stream_decompression_ctx);
@@ -1787,15 +1977,14 @@ void grpc_chttp2_maybe_complete_recv_trailing_metadata(grpc_exec_ctx *exec_ctx,
1787
1977
  }
1788
1978
  bool pending_data = s->pending_byte_stream ||
1789
1979
  s->unprocessed_incoming_frames_buffer.length > 0;
1790
- if (s->stream_compression_recv_enabled && s->read_closed &&
1791
- s->frame_storage.length > 0 && !pending_data && !s->seen_error &&
1792
- s->recv_trailing_metadata_finished != NULL) {
1980
+ if (s->read_closed && s->frame_storage.length > 0 && !pending_data &&
1981
+ !s->seen_error && s->recv_trailing_metadata_finished != NULL) {
1793
1982
  /* Maybe some SYNC_FLUSH data is left in frame_storage. Consume them and
1794
1983
  * maybe decompress the next 5 bytes in the stream. */
1795
1984
  bool end_of_context;
1796
1985
  if (!s->stream_decompression_ctx) {
1797
1986
  s->stream_decompression_ctx = grpc_stream_compression_context_create(
1798
- GRPC_STREAM_COMPRESSION_DECOMPRESS);
1987
+ s->stream_decompression_method);
1799
1988
  }
1800
1989
  if (!grpc_stream_decompress(s->stream_decompression_ctx,
1801
1990
  &s->frame_storage,
@@ -1808,6 +1997,7 @@ void grpc_chttp2_maybe_complete_recv_trailing_metadata(grpc_exec_ctx *exec_ctx,
1808
1997
  } else {
1809
1998
  if (s->unprocessed_incoming_frames_buffer.length > 0) {
1810
1999
  s->unprocessed_incoming_frames_decompressed = true;
2000
+ pending_data = true;
1811
2001
  }
1812
2002
  if (end_of_context) {
1813
2003
  grpc_stream_compression_context_destroy(s->stream_decompression_ctx);
@@ -1815,8 +2005,7 @@ void grpc_chttp2_maybe_complete_recv_trailing_metadata(grpc_exec_ctx *exec_ctx,
1815
2005
  }
1816
2006
  }
1817
2007
  }
1818
- if (s->read_closed && s->frame_storage.length == 0 &&
1819
- (!pending_data || s->seen_error) &&
2008
+ if (s->read_closed && s->frame_storage.length == 0 && !pending_data &&
1820
2009
  s->recv_trailing_metadata_finished != NULL) {
1821
2010
  grpc_chttp2_incoming_metadata_buffer_publish(
1822
2011
  exec_ctx, &s->metadata_buffer[1], s->recv_trailing_metadata);
@@ -1829,7 +2018,8 @@ void grpc_chttp2_maybe_complete_recv_trailing_metadata(grpc_exec_ctx *exec_ctx,
1829
2018
 
1830
2019
  static void remove_stream(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
1831
2020
  uint32_t id, grpc_error *error) {
1832
- grpc_chttp2_stream *s = grpc_chttp2_stream_map_delete(&t->stream_map, id);
2021
+ grpc_chttp2_stream *s =
2022
+ (grpc_chttp2_stream *)grpc_chttp2_stream_map_delete(&t->stream_map, id);
1833
2023
  GPR_ASSERT(s);
1834
2024
  if (t->incoming_stream == s) {
1835
2025
  t->incoming_stream = NULL;
@@ -1884,7 +2074,8 @@ void grpc_chttp2_cancel_stream(grpc_exec_ctx *exec_ctx,
1884
2074
  grpc_slice_buffer_add(
1885
2075
  &t->qbuf, grpc_chttp2_rst_stream_create(s->id, (uint32_t)http_error,
1886
2076
  &s->stats.outgoing));
1887
- grpc_chttp2_initiate_write(exec_ctx, t, "rst_stream");
2077
+ grpc_chttp2_initiate_write(exec_ctx, t,
2078
+ GRPC_CHTTP2_INITIATE_WRITE_RST_STREAM);
1888
2079
  }
1889
2080
  }
1890
2081
  if (due_to_error != GRPC_ERROR_NONE && !s->seen_error) {
@@ -1960,6 +2151,21 @@ static grpc_error *removal_error(grpc_error *extra_error, grpc_chttp2_stream *s,
1960
2151
  return error;
1961
2152
  }
1962
2153
 
2154
+ static void flush_write_list(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
2155
+ grpc_chttp2_stream *s, grpc_chttp2_write_cb **list,
2156
+ grpc_error *error) {
2157
+ while (*list) {
2158
+ grpc_chttp2_write_cb *cb = *list;
2159
+ *list = cb->next;
2160
+ grpc_chttp2_complete_closure_step(exec_ctx, t, s, &cb->closure,
2161
+ GRPC_ERROR_REF(error),
2162
+ "on_write_finished_cb");
2163
+ cb->next = t->write_cb_pool;
2164
+ t->write_cb_pool = cb;
2165
+ }
2166
+ GRPC_ERROR_UNREF(error);
2167
+ }
2168
+
1963
2169
  void grpc_chttp2_fail_pending_writes(grpc_exec_ctx *exec_ctx,
1964
2170
  grpc_chttp2_transport *t,
1965
2171
  grpc_chttp2_stream *s, grpc_error *error) {
@@ -1979,16 +2185,9 @@ void grpc_chttp2_fail_pending_writes(grpc_exec_ctx *exec_ctx,
1979
2185
  grpc_chttp2_complete_closure_step(
1980
2186
  exec_ctx, t, s, &s->fetching_send_message_finished, GRPC_ERROR_REF(error),
1981
2187
  "fetching_send_message_finished");
1982
- while (s->on_write_finished_cbs) {
1983
- grpc_chttp2_write_cb *cb = s->on_write_finished_cbs;
1984
- s->on_write_finished_cbs = cb->next;
1985
- grpc_chttp2_complete_closure_step(exec_ctx, t, s, &cb->closure,
1986
- GRPC_ERROR_REF(error),
1987
- "on_write_finished_cb");
1988
- cb->next = t->write_cb_pool;
1989
- t->write_cb_pool = cb;
1990
- }
1991
- GRPC_ERROR_UNREF(error);
2188
+ flush_write_list(exec_ctx, t, s, &s->on_write_finished_cbs,
2189
+ GRPC_ERROR_REF(error));
2190
+ flush_write_list(exec_ctx, t, s, &s->on_flow_controlled_cbs, error);
1992
2191
  }
1993
2192
 
1994
2193
  void grpc_chttp2_mark_stream_closed(grpc_exec_ctx *exec_ctx,
@@ -2197,7 +2396,8 @@ static void close_from_api(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
2197
2396
  &s->stats.outgoing));
2198
2397
 
2199
2398
  grpc_chttp2_mark_stream_closed(exec_ctx, t, s, 1, 1, error);
2200
- grpc_chttp2_initiate_write(exec_ctx, t, "close_from_api");
2399
+ grpc_chttp2_initiate_write(exec_ctx, t,
2400
+ GRPC_CHTTP2_INITIATE_WRITE_CLOSE_FROM_API);
2201
2401
  }
2202
2402
 
2203
2403
  typedef struct {
@@ -2207,8 +2407,8 @@ typedef struct {
2207
2407
  } cancel_stream_cb_args;
2208
2408
 
2209
2409
  static void cancel_stream_cb(void *user_data, uint32_t key, void *stream) {
2210
- cancel_stream_cb_args *args = user_data;
2211
- grpc_chttp2_stream *s = stream;
2410
+ cancel_stream_cb_args *args = (cancel_stream_cb_args *)user_data;
2411
+ grpc_chttp2_stream *s = (grpc_chttp2_stream *)stream;
2212
2412
  grpc_chttp2_cancel_stream(args->exec_ctx, args->t, s,
2213
2413
  GRPC_ERROR_REF(args->error));
2214
2414
  }
@@ -2232,21 +2432,20 @@ void grpc_chttp2_act_on_flowctl_action(grpc_exec_ctx *exec_ctx,
2232
2432
  case GRPC_CHTTP2_FLOWCTL_NO_ACTION_NEEDED:
2233
2433
  break;
2234
2434
  case GRPC_CHTTP2_FLOWCTL_UPDATE_IMMEDIATELY:
2235
- grpc_chttp2_become_writable(exec_ctx, t, s,
2236
- GRPC_CHTTP2_STREAM_WRITE_INITIATE_COVERED,
2237
- "immediate stream flowctl");
2435
+ grpc_chttp2_mark_stream_writable(exec_ctx, t, s);
2436
+ grpc_chttp2_initiate_write(
2437
+ exec_ctx, t, GRPC_CHTTP2_INITIATE_WRITE_STREAM_FLOW_CONTROL);
2238
2438
  break;
2239
2439
  case GRPC_CHTTP2_FLOWCTL_QUEUE_UPDATE:
2240
- grpc_chttp2_become_writable(exec_ctx, t, s,
2241
- GRPC_CHTTP2_STREAM_WRITE_PIGGYBACK,
2242
- "queue stream flowctl");
2440
+ grpc_chttp2_mark_stream_writable(exec_ctx, t, s);
2243
2441
  break;
2244
2442
  }
2245
2443
  switch (action.send_transport_update) {
2246
2444
  case GRPC_CHTTP2_FLOWCTL_NO_ACTION_NEEDED:
2247
2445
  break;
2248
2446
  case GRPC_CHTTP2_FLOWCTL_UPDATE_IMMEDIATELY:
2249
- grpc_chttp2_initiate_write(exec_ctx, t, "immediate transport flowctl");
2447
+ grpc_chttp2_initiate_write(
2448
+ exec_ctx, t, GRPC_CHTTP2_INITIATE_WRITE_TRANSPORT_FLOW_CONTROL);
2250
2449
  break;
2251
2450
  // this is the same as no action b/c every time the transport enters the
2252
2451
  // writing path it will maybe do an update
@@ -2264,7 +2463,8 @@ void grpc_chttp2_act_on_flowctl_action(grpc_exec_ctx *exec_ctx,
2264
2463
  (uint32_t)action.max_frame_size);
2265
2464
  }
2266
2465
  if (action.send_setting_update == GRPC_CHTTP2_FLOWCTL_UPDATE_IMMEDIATELY) {
2267
- grpc_chttp2_initiate_write(exec_ctx, t, "immediate setting update");
2466
+ grpc_chttp2_initiate_write(exec_ctx, t,
2467
+ GRPC_CHTTP2_INITIATE_WRITE_SEND_SETTINGS);
2268
2468
  }
2269
2469
  }
2270
2470
  if (action.need_ping) {
@@ -2272,7 +2472,8 @@ void grpc_chttp2_act_on_flowctl_action(grpc_exec_ctx *exec_ctx,
2272
2472
  grpc_bdp_estimator_schedule_ping(&t->flow_control.bdp_estimator);
2273
2473
  send_ping_locked(exec_ctx, t,
2274
2474
  GRPC_CHTTP2_PING_BEFORE_TRANSPORT_WINDOW_UPDATE,
2275
- &t->start_bdp_ping_locked, &t->finish_bdp_ping_locked);
2475
+ &t->start_bdp_ping_locked, &t->finish_bdp_ping_locked,
2476
+ GRPC_CHTTP2_INITIATE_WRITE_BDP_ESTIMATOR_PING);
2276
2477
  }
2277
2478
  }
2278
2479
 
@@ -2310,7 +2511,7 @@ static void read_action_locked(grpc_exec_ctx *exec_ctx, void *tp,
2310
2511
  grpc_error *error) {
2311
2512
  GPR_TIMER_BEGIN("reading_action_locked", 0);
2312
2513
 
2313
- grpc_chttp2_transport *t = tp;
2514
+ grpc_chttp2_transport *t = (grpc_chttp2_transport *)tp;
2314
2515
 
2315
2516
  GRPC_ERROR_REF(error);
2316
2517
 
@@ -2351,9 +2552,10 @@ static void read_action_locked(grpc_exec_ctx *exec_ctx, void *tp,
2351
2552
  if (t->flow_control.initial_window_update > 0) {
2352
2553
  grpc_chttp2_stream *s;
2353
2554
  while (grpc_chttp2_list_pop_stalled_by_stream(t, &s)) {
2354
- grpc_chttp2_become_writable(
2355
- exec_ctx, t, s, GRPC_CHTTP2_STREAM_WRITE_INITIATE_UNCOVERED,
2356
- "unstalled");
2555
+ grpc_chttp2_mark_stream_writable(exec_ctx, t, s);
2556
+ grpc_chttp2_initiate_write(
2557
+ exec_ctx, t,
2558
+ GRPC_CHTTP2_INITIATE_WRITE_FLOW_CONTROL_UNSTALLED_BY_SETTING);
2357
2559
  }
2358
2560
  }
2359
2561
  t->flow_control.initial_window_update = 0;
@@ -2395,7 +2597,7 @@ static void read_action_locked(grpc_exec_ctx *exec_ctx, void *tp,
2395
2597
 
2396
2598
  static void start_bdp_ping_locked(grpc_exec_ctx *exec_ctx, void *tp,
2397
2599
  grpc_error *error) {
2398
- grpc_chttp2_transport *t = tp;
2600
+ grpc_chttp2_transport *t = (grpc_chttp2_transport *)tp;
2399
2601
  if (GRPC_TRACER_ON(grpc_http_trace)) {
2400
2602
  gpr_log(GPR_DEBUG, "%s: Start BDP ping", t->peer_string);
2401
2603
  }
@@ -2408,7 +2610,7 @@ static void start_bdp_ping_locked(grpc_exec_ctx *exec_ctx, void *tp,
2408
2610
 
2409
2611
  static void finish_bdp_ping_locked(grpc_exec_ctx *exec_ctx, void *tp,
2410
2612
  grpc_error *error) {
2411
- grpc_chttp2_transport *t = tp;
2613
+ grpc_chttp2_transport *t = (grpc_chttp2_transport *)tp;
2412
2614
  if (GRPC_TRACER_ON(grpc_http_trace)) {
2413
2615
  gpr_log(GPR_DEBUG, "%s: Complete BDP ping", t->peer_string);
2414
2616
  }
@@ -2450,6 +2652,36 @@ void grpc_chttp2_config_default_keepalive_args(grpc_channel_args *args,
2450
2652
  &args->args[i],
2451
2653
  (grpc_integer_options){g_default_keepalive_permit_without_calls,
2452
2654
  0, 1});
2655
+ } else if (0 ==
2656
+ strcmp(args->args[i].key, GRPC_ARG_HTTP2_MAX_PING_STRIKES)) {
2657
+ g_default_max_ping_strikes = grpc_channel_arg_get_integer(
2658
+ &args->args[i],
2659
+ (grpc_integer_options){g_default_max_ping_strikes, 0, INT_MAX});
2660
+ } else if (0 == strcmp(args->args[i].key,
2661
+ GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA)) {
2662
+ g_default_max_pings_without_data = grpc_channel_arg_get_integer(
2663
+ &args->args[i], (grpc_integer_options){
2664
+ g_default_max_pings_without_data, 0, INT_MAX});
2665
+ } else if (0 ==
2666
+ strcmp(
2667
+ args->args[i].key,
2668
+ GRPC_ARG_HTTP2_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS)) {
2669
+ g_default_min_sent_ping_interval_without_data_ms =
2670
+ grpc_channel_arg_get_integer(
2671
+ &args->args[i],
2672
+ (grpc_integer_options){
2673
+ g_default_min_sent_ping_interval_without_data_ms, 0,
2674
+ INT_MAX});
2675
+ } else if (0 ==
2676
+ strcmp(
2677
+ args->args[i].key,
2678
+ GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS)) {
2679
+ g_default_min_recv_ping_interval_without_data_ms =
2680
+ grpc_channel_arg_get_integer(
2681
+ &args->args[i],
2682
+ (grpc_integer_options){
2683
+ g_default_min_recv_ping_interval_without_data_ms, 0,
2684
+ INT_MAX});
2453
2685
  }
2454
2686
  }
2455
2687
  }
@@ -2457,7 +2689,7 @@ void grpc_chttp2_config_default_keepalive_args(grpc_channel_args *args,
2457
2689
 
2458
2690
  static void init_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg,
2459
2691
  grpc_error *error) {
2460
- grpc_chttp2_transport *t = arg;
2692
+ grpc_chttp2_transport *t = (grpc_chttp2_transport *)arg;
2461
2693
  GPR_ASSERT(t->keepalive_state == GRPC_CHTTP2_KEEPALIVE_STATE_WAITING);
2462
2694
  if (t->destroying || t->closed) {
2463
2695
  t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_DYING;
@@ -2468,7 +2700,8 @@ static void init_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg,
2468
2700
  GRPC_CHTTP2_REF_TRANSPORT(t, "keepalive ping end");
2469
2701
  send_ping_locked(exec_ctx, t, GRPC_CHTTP2_PING_ON_NEXT_WRITE,
2470
2702
  &t->start_keepalive_ping_locked,
2471
- &t->finish_keepalive_ping_locked);
2703
+ &t->finish_keepalive_ping_locked,
2704
+ GRPC_CHTTP2_INITIATE_WRITE_KEEPALIVE_PING);
2472
2705
  } else {
2473
2706
  GRPC_CHTTP2_REF_TRANSPORT(t, "init keepalive ping");
2474
2707
  grpc_timer_init(
@@ -2489,7 +2722,7 @@ static void init_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg,
2489
2722
 
2490
2723
  static void start_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg,
2491
2724
  grpc_error *error) {
2492
- grpc_chttp2_transport *t = arg;
2725
+ grpc_chttp2_transport *t = (grpc_chttp2_transport *)arg;
2493
2726
  GRPC_CHTTP2_REF_TRANSPORT(t, "keepalive watchdog");
2494
2727
  grpc_timer_init(
2495
2728
  exec_ctx, &t->keepalive_watchdog_timer,
@@ -2499,7 +2732,7 @@ static void start_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg,
2499
2732
 
2500
2733
  static void finish_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg,
2501
2734
  grpc_error *error) {
2502
- grpc_chttp2_transport *t = arg;
2735
+ grpc_chttp2_transport *t = (grpc_chttp2_transport *)arg;
2503
2736
  if (t->keepalive_state == GRPC_CHTTP2_KEEPALIVE_STATE_PINGING) {
2504
2737
  if (error == GRPC_ERROR_NONE) {
2505
2738
  t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_WAITING;
@@ -2516,7 +2749,7 @@ static void finish_keepalive_ping_locked(grpc_exec_ctx *exec_ctx, void *arg,
2516
2749
 
2517
2750
  static void keepalive_watchdog_fired_locked(grpc_exec_ctx *exec_ctx, void *arg,
2518
2751
  grpc_error *error) {
2519
- grpc_chttp2_transport *t = arg;
2752
+ grpc_chttp2_transport *t = (grpc_chttp2_transport *)arg;
2520
2753
  if (t->keepalive_state == GRPC_CHTTP2_KEEPALIVE_STATE_PINGING) {
2521
2754
  if (error == GRPC_ERROR_NONE) {
2522
2755
  t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_DYING;
@@ -2583,7 +2816,7 @@ static void reset_byte_stream(grpc_exec_ctx *exec_ctx, void *arg,
2583
2816
  GRPC_ERROR_UNREF(s->byte_stream_error);
2584
2817
  s->byte_stream_error = GRPC_ERROR_NONE;
2585
2818
  grpc_chttp2_cancel_stream(exec_ctx, s->t, s, GRPC_ERROR_REF(error));
2586
- s->byte_stream_error = error;
2819
+ s->byte_stream_error = GRPC_ERROR_REF(error);
2587
2820
  }
2588
2821
  }
2589
2822
 
@@ -2597,7 +2830,8 @@ static void incoming_byte_stream_unref(grpc_exec_ctx *exec_ctx,
2597
2830
  static void incoming_byte_stream_next_locked(grpc_exec_ctx *exec_ctx,
2598
2831
  void *argp,
2599
2832
  grpc_error *error_ignored) {
2600
- grpc_chttp2_incoming_byte_stream *bs = argp;
2833
+ grpc_chttp2_incoming_byte_stream *bs =
2834
+ (grpc_chttp2_incoming_byte_stream *)argp;
2601
2835
  grpc_chttp2_transport *t = bs->transport;
2602
2836
  grpc_chttp2_stream *s = bs->stream;
2603
2837
 
@@ -2680,29 +2914,31 @@ static grpc_error *incoming_byte_stream_pull(grpc_exec_ctx *exec_ctx,
2680
2914
  grpc_error *error;
2681
2915
 
2682
2916
  if (s->unprocessed_incoming_frames_buffer.length > 0) {
2683
- if (s->stream_compression_recv_enabled &&
2684
- !s->unprocessed_incoming_frames_decompressed) {
2917
+ if (!s->unprocessed_incoming_frames_decompressed) {
2685
2918
  bool end_of_context;
2686
2919
  if (!s->stream_decompression_ctx) {
2687
2920
  s->stream_decompression_ctx = grpc_stream_compression_context_create(
2688
- GRPC_STREAM_COMPRESSION_DECOMPRESS);
2921
+ s->stream_decompression_method);
2689
2922
  }
2690
2923
  if (!grpc_stream_decompress(s->stream_decompression_ctx,
2691
2924
  &s->unprocessed_incoming_frames_buffer,
2692
- s->decompressed_data_buffer, NULL, MAX_SIZE_T,
2693
- &end_of_context)) {
2925
+ &s->decompressed_data_buffer, NULL,
2926
+ MAX_SIZE_T, &end_of_context)) {
2694
2927
  error =
2695
2928
  GRPC_ERROR_CREATE_FROM_STATIC_STRING("Stream decompression error.");
2696
2929
  return error;
2697
2930
  }
2698
2931
  GPR_ASSERT(s->unprocessed_incoming_frames_buffer.length == 0);
2699
2932
  grpc_slice_buffer_swap(&s->unprocessed_incoming_frames_buffer,
2700
- s->decompressed_data_buffer);
2933
+ &s->decompressed_data_buffer);
2701
2934
  s->unprocessed_incoming_frames_decompressed = true;
2702
2935
  if (end_of_context) {
2703
2936
  grpc_stream_compression_context_destroy(s->stream_decompression_ctx);
2704
2937
  s->stream_decompression_ctx = NULL;
2705
2938
  }
2939
+ if (s->unprocessed_incoming_frames_buffer.length == 0) {
2940
+ *slice = grpc_empty_slice();
2941
+ }
2706
2942
  }
2707
2943
  error = grpc_deframe_unprocessed_incoming_frames(
2708
2944
  exec_ctx, &s->data_parser, s, &s->unprocessed_incoming_frames_buffer,
@@ -2804,7 +3040,8 @@ static const grpc_byte_stream_vtable grpc_chttp2_incoming_byte_stream_vtable = {
2804
3040
  static void incoming_byte_stream_destroy_locked(grpc_exec_ctx *exec_ctx,
2805
3041
  void *byte_stream,
2806
3042
  grpc_error *error_ignored) {
2807
- grpc_chttp2_incoming_byte_stream *bs = byte_stream;
3043
+ grpc_chttp2_incoming_byte_stream *bs =
3044
+ (grpc_chttp2_incoming_byte_stream *)byte_stream;
2808
3045
  grpc_chttp2_stream *s = bs->stream;
2809
3046
  grpc_chttp2_transport *t = s->t;
2810
3047
 
@@ -2819,7 +3056,8 @@ grpc_chttp2_incoming_byte_stream *grpc_chttp2_incoming_byte_stream_create(
2819
3056
  grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s,
2820
3057
  uint32_t frame_size, uint32_t flags) {
2821
3058
  grpc_chttp2_incoming_byte_stream *incoming_byte_stream =
2822
- gpr_malloc(sizeof(*incoming_byte_stream));
3059
+ (grpc_chttp2_incoming_byte_stream *)gpr_malloc(
3060
+ sizeof(*incoming_byte_stream));
2823
3061
  incoming_byte_stream->base.length = frame_size;
2824
3062
  incoming_byte_stream->remaining_bytes = frame_size;
2825
3063
  incoming_byte_stream->base.flags = flags;
@@ -2860,7 +3098,7 @@ static void post_destructive_reclaimer(grpc_exec_ctx *exec_ctx,
2860
3098
 
2861
3099
  static void benign_reclaimer_locked(grpc_exec_ctx *exec_ctx, void *arg,
2862
3100
  grpc_error *error) {
2863
- grpc_chttp2_transport *t = arg;
3101
+ grpc_chttp2_transport *t = (grpc_chttp2_transport *)arg;
2864
3102
  if (error == GRPC_ERROR_NONE &&
2865
3103
  grpc_chttp2_stream_map_size(&t->stream_map) == 0) {
2866
3104
  /* Channel with no active streams: send a goaway to try and make it
@@ -2890,11 +3128,12 @@ static void benign_reclaimer_locked(grpc_exec_ctx *exec_ctx, void *arg,
2890
3128
 
2891
3129
  static void destructive_reclaimer_locked(grpc_exec_ctx *exec_ctx, void *arg,
2892
3130
  grpc_error *error) {
2893
- grpc_chttp2_transport *t = arg;
3131
+ grpc_chttp2_transport *t = (grpc_chttp2_transport *)arg;
2894
3132
  size_t n = grpc_chttp2_stream_map_size(&t->stream_map);
2895
3133
  t->destructive_reclaimer_registered = false;
2896
3134
  if (error == GRPC_ERROR_NONE && n > 0) {
2897
- grpc_chttp2_stream *s = grpc_chttp2_stream_map_rand(&t->stream_map);
3135
+ grpc_chttp2_stream *s =
3136
+ (grpc_chttp2_stream *)grpc_chttp2_stream_map_rand(&t->stream_map);
2898
3137
  if (GRPC_TRACER_ON(grpc_resource_quota_trace)) {
2899
3138
  gpr_log(GPR_DEBUG, "HTTP2: %s - abandon stream id %d", t->peer_string,
2900
3139
  s->id);
@@ -2920,16 +3159,58 @@ static void destructive_reclaimer_locked(grpc_exec_ctx *exec_ctx, void *arg,
2920
3159
  }
2921
3160
 
2922
3161
  /*******************************************************************************
2923
- * INTEGRATION GLUE
3162
+ * MONITORING
2924
3163
  */
2925
3164
 
2926
- static char *chttp2_get_peer(grpc_exec_ctx *exec_ctx, grpc_transport *t) {
2927
- return gpr_strdup(((grpc_chttp2_transport *)t)->peer_string);
3165
+ const 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");
2928
3212
  }
2929
3213
 
2930
- /*******************************************************************************
2931
- * MONITORING
2932
- */
2933
3214
  static grpc_endpoint *chttp2_get_endpoint(grpc_exec_ctx *exec_ctx,
2934
3215
  grpc_transport *t) {
2935
3216
  return ((grpc_chttp2_transport *)t)->ep;
@@ -2944,13 +3225,15 @@ static const grpc_transport_vtable vtable = {sizeof(grpc_chttp2_stream),
2944
3225
  perform_transport_op,
2945
3226
  destroy_stream,
2946
3227
  destroy_transport,
2947
- chttp2_get_peer,
2948
3228
  chttp2_get_endpoint};
2949
3229
 
3230
+ static const grpc_transport_vtable *get_vtable(void) { return &vtable; }
3231
+
2950
3232
  grpc_transport *grpc_create_chttp2_transport(
2951
3233
  grpc_exec_ctx *exec_ctx, const grpc_channel_args *channel_args,
2952
3234
  grpc_endpoint *ep, int is_client) {
2953
- grpc_chttp2_transport *t = gpr_zalloc(sizeof(grpc_chttp2_transport));
3235
+ grpc_chttp2_transport *t =
3236
+ (grpc_chttp2_transport *)gpr_zalloc(sizeof(grpc_chttp2_transport));
2954
3237
  init_transport(exec_ctx, t, channel_args, ep, is_client != 0);
2955
3238
  return &t->base;
2956
3239
  }