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
@@ -173,7 +173,7 @@ void grpc_chttp2_hptbl_init(grpc_exec_ctx *exec_ctx, grpc_chttp2_hptbl *tbl) {
173
173
  GRPC_CHTTP2_INITIAL_HPACK_TABLE_SIZE;
174
174
  tbl->max_entries = tbl->cap_entries =
175
175
  entries_for_bytes(tbl->current_table_bytes);
176
- tbl->ents = gpr_malloc(sizeof(*tbl->ents) * tbl->cap_entries);
176
+ tbl->ents = (grpc_mdelem *)gpr_malloc(sizeof(*tbl->ents) * tbl->cap_entries);
177
177
  memset(tbl->ents, 0, sizeof(*tbl->ents) * tbl->cap_entries);
178
178
  for (i = 1; i <= GRPC_CHTTP2_LAST_STATIC_ENTRY; i++) {
179
179
  tbl->static_ents[i - 1] = grpc_mdelem_from_slices(
@@ -228,7 +228,7 @@ static void evict1(grpc_exec_ctx *exec_ctx, grpc_chttp2_hptbl *tbl) {
228
228
  }
229
229
 
230
230
  static void rebuild_ents(grpc_chttp2_hptbl *tbl, uint32_t new_cap) {
231
- grpc_mdelem *ents = gpr_malloc(sizeof(*ents) * new_cap);
231
+ grpc_mdelem *ents = (grpc_mdelem *)gpr_malloc(sizeof(*ents) * new_cap);
232
232
  uint32_t i;
233
233
 
234
234
  for (i = 0; i < tbl->num_ents; i++) {
@@ -42,8 +42,9 @@ grpc_error *grpc_chttp2_incoming_metadata_buffer_add(
42
42
  grpc_mdelem elem) {
43
43
  buffer->size += GRPC_MDELEM_LENGTH(elem);
44
44
  return grpc_metadata_batch_add_tail(
45
- exec_ctx, &buffer->batch,
46
- gpr_arena_alloc(buffer->arena, sizeof(grpc_linked_mdelem)), elem);
45
+ exec_ctx, &buffer->batch, (grpc_linked_mdelem *)gpr_arena_alloc(
46
+ buffer->arena, sizeof(grpc_linked_mdelem)),
47
+ elem);
47
48
  }
48
49
 
49
50
  grpc_error *grpc_chttp2_incoming_metadata_buffer_replace_or_add(
@@ -79,16 +79,43 @@ typedef enum {
79
79
  GRPC_CHTTP2_PCL_COUNT /* must be last */
80
80
  } grpc_chttp2_ping_closure_list;
81
81
 
82
+ typedef enum {
83
+ GRPC_CHTTP2_INITIATE_WRITE_INITIAL_WRITE,
84
+ GRPC_CHTTP2_INITIATE_WRITE_START_NEW_STREAM,
85
+ GRPC_CHTTP2_INITIATE_WRITE_SEND_MESSAGE,
86
+ GRPC_CHTTP2_INITIATE_WRITE_SEND_INITIAL_METADATA,
87
+ GRPC_CHTTP2_INITIATE_WRITE_SEND_TRAILING_METADATA,
88
+ GRPC_CHTTP2_INITIATE_WRITE_RETRY_SEND_PING,
89
+ GRPC_CHTTP2_INITIATE_WRITE_CONTINUE_PINGS,
90
+ GRPC_CHTTP2_INITIATE_WRITE_GOAWAY_SENT,
91
+ GRPC_CHTTP2_INITIATE_WRITE_RST_STREAM,
92
+ GRPC_CHTTP2_INITIATE_WRITE_CLOSE_FROM_API,
93
+ GRPC_CHTTP2_INITIATE_WRITE_STREAM_FLOW_CONTROL,
94
+ GRPC_CHTTP2_INITIATE_WRITE_TRANSPORT_FLOW_CONTROL,
95
+ GRPC_CHTTP2_INITIATE_WRITE_SEND_SETTINGS,
96
+ GRPC_CHTTP2_INITIATE_WRITE_BDP_ESTIMATOR_PING,
97
+ GRPC_CHTTP2_INITIATE_WRITE_FLOW_CONTROL_UNSTALLED_BY_SETTING,
98
+ GRPC_CHTTP2_INITIATE_WRITE_FLOW_CONTROL_UNSTALLED_BY_UPDATE,
99
+ GRPC_CHTTP2_INITIATE_WRITE_APPLICATION_PING,
100
+ GRPC_CHTTP2_INITIATE_WRITE_KEEPALIVE_PING,
101
+ GRPC_CHTTP2_INITIATE_WRITE_TRANSPORT_FLOW_CONTROL_UNSTALLED,
102
+ GRPC_CHTTP2_INITIATE_WRITE_PING_RESPONSE,
103
+ GRPC_CHTTP2_INITIATE_WRITE_FORCE_RST_STREAM,
104
+ } grpc_chttp2_initiate_write_reason;
105
+
106
+ const char *grpc_chttp2_initiate_write_reason_string(
107
+ grpc_chttp2_initiate_write_reason reason);
108
+
82
109
  typedef struct {
83
110
  grpc_closure_list lists[GRPC_CHTTP2_PCL_COUNT];
84
111
  uint64_t inflight_id;
85
112
  } grpc_chttp2_ping_queue;
86
113
 
87
114
  typedef struct {
88
- gpr_timespec min_time_between_pings;
89
115
  int max_pings_without_data;
90
116
  int max_ping_strikes;
91
- gpr_timespec min_ping_interval_without_data;
117
+ gpr_timespec min_sent_ping_interval_without_data;
118
+ gpr_timespec min_recv_ping_interval_without_data;
92
119
  } grpc_chttp2_repeated_ping_policy;
93
120
 
94
121
  typedef struct {
@@ -262,6 +289,10 @@ struct grpc_chttp2_transport {
262
289
 
263
290
  /** write execution state of the transport */
264
291
  grpc_chttp2_write_state write_state;
292
+ /** is this the first write in a series of writes?
293
+ set when we initiate writing from idle, cleared when we
294
+ initiate writing from writing+more */
295
+ bool is_first_write_in_batch;
265
296
 
266
297
  /** is the transport destroying itself? */
267
298
  uint8_t destroying;
@@ -483,6 +514,7 @@ struct grpc_chttp2_stream {
483
514
  grpc_slice fetching_slice;
484
515
  int64_t next_message_end_offset;
485
516
  int64_t flow_controlled_bytes_written;
517
+ int64_t flow_controlled_bytes_flowed;
486
518
  grpc_closure complete_fetch_locked;
487
519
  grpc_closure *fetching_send_message_finished;
488
520
 
@@ -509,6 +541,8 @@ struct grpc_chttp2_stream {
509
541
  /** Are we buffering writes on this stream? If yes, we won't become writable
510
542
  until there's enough queued up in the flow_controlled_buffer */
511
543
  bool write_buffering;
544
+ /** Has trailing metadata been received. */
545
+ bool received_trailing_metadata;
512
546
 
513
547
  /** the error that resulted in this stream being read-closed */
514
548
  grpc_error *read_closed_error;
@@ -553,29 +587,32 @@ struct grpc_chttp2_stream {
553
587
 
554
588
  grpc_slice_buffer flow_controlled_buffer;
555
589
 
590
+ grpc_chttp2_write_cb *on_flow_controlled_cbs;
556
591
  grpc_chttp2_write_cb *on_write_finished_cbs;
557
592
  grpc_chttp2_write_cb *finish_after_write;
558
593
  size_t sending_bytes;
559
594
 
560
- /** Whether stream compression send is enabled */
561
- bool stream_compression_recv_enabled;
562
- /** Whether stream compression recv is enabled */
563
- bool stream_compression_send_enabled;
564
- /** Whether bytes stored in unprocessed_incoming_byte_stream is decompressed
565
- */
566
- bool unprocessed_incoming_frames_decompressed;
595
+ /* Stream compression method to be used. */
596
+ grpc_stream_compression_method stream_compression_method;
597
+ /* Stream decompression method to be used. */
598
+ grpc_stream_compression_method stream_decompression_method;
567
599
  /** Stream compression decompress context */
568
600
  grpc_stream_compression_context *stream_decompression_ctx;
569
601
  /** Stream compression compress context */
570
602
  grpc_stream_compression_context *stream_compression_ctx;
571
603
 
572
604
  /** Buffer storing data that is compressed but not sent */
573
- grpc_slice_buffer *compressed_data_buffer;
605
+ grpc_slice_buffer compressed_data_buffer;
574
606
  /** Amount of uncompressed bytes sent out when compressed_data_buffer is
575
607
  * emptied */
576
608
  size_t uncompressed_data_size;
577
609
  /** Temporary buffer storing decompressed data */
578
- grpc_slice_buffer *decompressed_data_buffer;
610
+ grpc_slice_buffer decompressed_data_buffer;
611
+ /** Whether bytes stored in unprocessed_incoming_byte_stream is decompressed
612
+ */
613
+ bool unprocessed_incoming_frames_decompressed;
614
+ /** gRPC header bytes that are already decompressed */
615
+ size_t decompressed_header_bytes;
579
616
  };
580
617
 
581
618
  /** Transport writing call flow:
@@ -591,12 +628,16 @@ struct grpc_chttp2_stream {
591
628
  The actual call chain is documented in the implementation of this function.
592
629
  */
593
630
  void grpc_chttp2_initiate_write(grpc_exec_ctx *exec_ctx,
594
- grpc_chttp2_transport *t, const char *reason);
631
+ grpc_chttp2_transport *t,
632
+ grpc_chttp2_initiate_write_reason reason);
595
633
 
596
- typedef enum {
597
- GRPC_CHTTP2_NOTHING_TO_WRITE,
598
- GRPC_CHTTP2_PARTIAL_WRITE,
599
- GRPC_CHTTP2_FULL_WRITE,
634
+ typedef struct {
635
+ /** are we writing? */
636
+ bool writing;
637
+ /** if writing: was it a complete flush (false) or a partial flush (true) */
638
+ bool partial;
639
+ /** did we queue any completions as part of beginning the write */
640
+ bool early_results_scheduled;
600
641
  } grpc_chttp2_begin_write_result;
601
642
 
602
643
  grpc_chttp2_begin_write_result grpc_chttp2_begin_write(
@@ -838,22 +879,11 @@ void grpc_chttp2_ack_ping(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
838
879
  void grpc_chttp2_add_ping_strike(grpc_exec_ctx *exec_ctx,
839
880
  grpc_chttp2_transport *t);
840
881
 
841
- typedef enum {
842
- /* don't initiate a transport write, but piggyback on the next one */
843
- GRPC_CHTTP2_STREAM_WRITE_PIGGYBACK,
844
- /* initiate a covered write */
845
- GRPC_CHTTP2_STREAM_WRITE_INITIATE_COVERED,
846
- /* initiate an uncovered write */
847
- GRPC_CHTTP2_STREAM_WRITE_INITIATE_UNCOVERED
848
- } grpc_chttp2_stream_write_type;
849
-
850
882
  /** add a ref to the stream and add it to the writable list;
851
883
  ref will be dropped in writing.c */
852
- void grpc_chttp2_become_writable(grpc_exec_ctx *exec_ctx,
853
- grpc_chttp2_transport *t,
854
- grpc_chttp2_stream *s,
855
- grpc_chttp2_stream_write_type type,
856
- const char *reason);
884
+ void grpc_chttp2_mark_stream_writable(grpc_exec_ctx *exec_ctx,
885
+ grpc_chttp2_transport *t,
886
+ grpc_chttp2_stream *s);
857
887
 
858
888
  void grpc_chttp2_cancel_stream(grpc_exec_ctx *exec_ctx,
859
889
  grpc_chttp2_transport *t, grpc_chttp2_stream *s,
@@ -106,7 +106,8 @@ grpc_error *grpc_chttp2_perform_read(grpc_exec_ctx *exec_ctx,
106
106
  return err;
107
107
  }
108
108
  ++cur;
109
- ++t->deframe_state;
109
+ t->deframe_state =
110
+ (grpc_chttp2_deframe_transport_state)(1 + (int)t->deframe_state);
110
111
  }
111
112
  if (cur == end) {
112
113
  return GRPC_ERROR_NONE;
@@ -382,6 +383,9 @@ error_handler:
382
383
  /* t->parser = grpc_chttp2_data_parser_parse;*/
383
384
  t->parser = grpc_chttp2_data_parser_parse;
384
385
  t->parser_data = &s->data_parser;
386
+ t->ping_state.pings_before_data_required =
387
+ t->ping_policy.max_pings_without_data;
388
+ t->ping_state.last_ping_sent_time = gpr_inf_past(GPR_CLOCK_MONOTONIC);
385
389
  return GRPC_ERROR_NONE;
386
390
  } else if (grpc_error_get_int(err, GRPC_ERROR_INT_STREAM_ID, NULL)) {
387
391
  /* handle stream errors by closing the stream */
@@ -402,7 +406,7 @@ static void free_timeout(void *p) { gpr_free(p); }
402
406
 
403
407
  static void on_initial_header(grpc_exec_ctx *exec_ctx, void *tp,
404
408
  grpc_mdelem md) {
405
- grpc_chttp2_transport *t = tp;
409
+ grpc_chttp2_transport *t = (grpc_chttp2_transport *)tp;
406
410
  grpc_chttp2_stream *s = t->incoming_stream;
407
411
 
408
412
  GPR_TIMER_BEGIN("on_initial_header", 0);
@@ -426,11 +430,12 @@ static void on_initial_header(grpc_exec_ctx *exec_ctx, void *tp,
426
430
  }
427
431
 
428
432
  if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_GRPC_TIMEOUT)) {
429
- gpr_timespec *cached_timeout = grpc_mdelem_get_user_data(md, free_timeout);
433
+ gpr_timespec *cached_timeout =
434
+ (gpr_timespec *)grpc_mdelem_get_user_data(md, free_timeout);
430
435
  gpr_timespec timeout;
431
436
  if (cached_timeout == NULL) {
432
437
  /* not already parsed: parse it now, and store the result away */
433
- cached_timeout = gpr_malloc(sizeof(gpr_timespec));
438
+ cached_timeout = (gpr_timespec *)gpr_malloc(sizeof(gpr_timespec));
434
439
  if (!grpc_http2_decode_timeout(GRPC_MDVALUE(md), cached_timeout)) {
435
440
  char *val = grpc_slice_to_c_string(GRPC_MDVALUE(md));
436
441
  gpr_log(GPR_ERROR, "Ignoring bad timeout value '%s'", val);
@@ -482,7 +487,7 @@ static void on_initial_header(grpc_exec_ctx *exec_ctx, void *tp,
482
487
 
483
488
  static void on_trailing_header(grpc_exec_ctx *exec_ctx, void *tp,
484
489
  grpc_mdelem md) {
485
- grpc_chttp2_transport *t = tp;
490
+ grpc_chttp2_transport *t = (grpc_chttp2_transport *)tp;
486
491
  grpc_chttp2_stream *s = t->incoming_stream;
487
492
 
488
493
  GPR_TIMER_BEGIN("on_trailing_header", 0);
@@ -557,6 +562,10 @@ static grpc_error *init_header_frame_parser(grpc_exec_ctx *exec_ctx,
557
562
  (t->incoming_frame_flags & GRPC_CHTTP2_DATA_FLAG_END_STREAM) != 0;
558
563
  }
559
564
 
565
+ t->ping_state.pings_before_data_required =
566
+ t->ping_policy.max_pings_without_data;
567
+ t->ping_state.last_ping_sent_time = gpr_inf_past(GPR_CLOCK_MONOTONIC);
568
+
560
569
  /* could be a new grpc_chttp2_stream or an existing grpc_chttp2_stream */
561
570
  s = grpc_chttp2_parsing_lookup_stream(t, t->incoming_stream_id);
562
571
  if (s == NULL) {
@@ -623,6 +632,7 @@ static grpc_error *init_header_frame_parser(grpc_exec_ctx *exec_ctx,
623
632
  *s->trailing_metadata_available = true;
624
633
  }
625
634
  t->hpack_parser.on_header = on_trailing_header;
635
+ s->received_trailing_metadata = true;
626
636
  } else {
627
637
  GRPC_CHTTP2_IF_TRACING(gpr_log(GPR_INFO, "parsing initial_metadata"));
628
638
  t->hpack_parser.on_header = on_initial_header;
@@ -631,6 +641,7 @@ static grpc_error *init_header_frame_parser(grpc_exec_ctx *exec_ctx,
631
641
  case 1:
632
642
  GRPC_CHTTP2_IF_TRACING(gpr_log(GPR_INFO, "parsing trailing_metadata"));
633
643
  t->hpack_parser.on_header = on_trailing_header;
644
+ s->received_trailing_metadata = true;
634
645
  break;
635
646
  case 2:
636
647
  gpr_log(GPR_ERROR, "too many header frames received");
@@ -20,6 +20,27 @@
20
20
 
21
21
  #include <grpc/support/log.h>
22
22
 
23
+ static char *stream_list_id_string(grpc_chttp2_stream_list_id id) {
24
+ switch (id) {
25
+ case GRPC_CHTTP2_LIST_WRITABLE:
26
+ return "writable";
27
+ case GRPC_CHTTP2_LIST_WRITING:
28
+ return "writing";
29
+ case GRPC_CHTTP2_LIST_STALLED_BY_TRANSPORT:
30
+ return "stalled_by_transport";
31
+ case GRPC_CHTTP2_LIST_STALLED_BY_STREAM:
32
+ return "stalled_by_stream";
33
+ case GRPC_CHTTP2_LIST_WAITING_FOR_CONCURRENCY:
34
+ return "waiting_for_concurrency";
35
+ case STREAM_LIST_COUNT:
36
+ GPR_UNREACHABLE_CODE(return "unknown");
37
+ }
38
+ GPR_UNREACHABLE_CODE(return "unknown");
39
+ }
40
+
41
+ grpc_tracer_flag grpc_trace_http2_stream_state =
42
+ GRPC_TRACER_INITIALIZER(false, "http2_stream_state");
43
+
23
44
  /* core list management */
24
45
 
25
46
  static bool stream_list_empty(grpc_chttp2_transport *t,
@@ -44,6 +65,10 @@ static bool stream_list_pop(grpc_chttp2_transport *t,
44
65
  s->included[id] = 0;
45
66
  }
46
67
  *stream = s;
68
+ if (s && GRPC_TRACER_ON(grpc_trace_http2_stream_state)) {
69
+ gpr_log(GPR_DEBUG, "%p[%d][%s]: pop from %s", t, s->id,
70
+ t->is_client ? "cli" : "svr", stream_list_id_string(id));
71
+ }
47
72
  return s != 0;
48
73
  }
49
74
 
@@ -62,6 +87,10 @@ static void stream_list_remove(grpc_chttp2_transport *t, grpc_chttp2_stream *s,
62
87
  } else {
63
88
  t->lists[id].tail = s->links[id].prev;
64
89
  }
90
+ if (GRPC_TRACER_ON(grpc_trace_http2_stream_state)) {
91
+ gpr_log(GPR_DEBUG, "%p[%d][%s]: remove from %s", t, s->id,
92
+ t->is_client ? "cli" : "svr", stream_list_id_string(id));
93
+ }
65
94
  }
66
95
 
67
96
  static bool stream_list_maybe_remove(grpc_chttp2_transport *t,
@@ -90,6 +119,10 @@ static void stream_list_add_tail(grpc_chttp2_transport *t,
90
119
  }
91
120
  t->lists[id].tail = s;
92
121
  s->included[id] = 1;
122
+ if (GRPC_TRACER_ON(grpc_trace_http2_stream_state)) {
123
+ gpr_log(GPR_DEBUG, "%p[%d][%s]: add to %s", t, s->id,
124
+ t->is_client ? "cli" : "svr", stream_list_id_string(id));
125
+ }
93
126
  }
94
127
 
95
128
  static bool stream_list_add(grpc_chttp2_transport *t, grpc_chttp2_stream *s,
@@ -150,17 +183,12 @@ void grpc_chttp2_list_remove_waiting_for_concurrency(grpc_chttp2_transport *t,
150
183
 
151
184
  void grpc_chttp2_list_add_stalled_by_transport(grpc_chttp2_transport *t,
152
185
  grpc_chttp2_stream *s) {
153
- GRPC_FLOW_CONTROL_IF_TRACING(
154
- gpr_log(GPR_DEBUG, "stream %u stalled by transport", s->id));
155
186
  stream_list_add(t, s, GRPC_CHTTP2_LIST_STALLED_BY_TRANSPORT);
156
187
  }
157
188
 
158
189
  bool grpc_chttp2_list_pop_stalled_by_transport(grpc_chttp2_transport *t,
159
190
  grpc_chttp2_stream **s) {
160
- bool ret = stream_list_pop(t, s, GRPC_CHTTP2_LIST_STALLED_BY_TRANSPORT);
161
- GRPC_FLOW_CONTROL_IF_TRACING(if (ret) gpr_log(
162
- GPR_DEBUG, "stream %u un-stalled by transport", (*s)->id));
163
- return ret;
191
+ return stream_list_pop(t, s, GRPC_CHTTP2_LIST_STALLED_BY_TRANSPORT);
164
192
  }
165
193
 
166
194
  void grpc_chttp2_list_remove_stalled_by_transport(grpc_chttp2_transport *t,
@@ -170,23 +198,15 @@ void grpc_chttp2_list_remove_stalled_by_transport(grpc_chttp2_transport *t,
170
198
 
171
199
  void grpc_chttp2_list_add_stalled_by_stream(grpc_chttp2_transport *t,
172
200
  grpc_chttp2_stream *s) {
173
- GRPC_FLOW_CONTROL_IF_TRACING(
174
- gpr_log(GPR_DEBUG, "stream %u stalled by stream", s->id));
175
201
  stream_list_add(t, s, GRPC_CHTTP2_LIST_STALLED_BY_STREAM);
176
202
  }
177
203
 
178
204
  bool grpc_chttp2_list_pop_stalled_by_stream(grpc_chttp2_transport *t,
179
205
  grpc_chttp2_stream **s) {
180
- bool ret = stream_list_pop(t, s, GRPC_CHTTP2_LIST_STALLED_BY_STREAM);
181
- GRPC_FLOW_CONTROL_IF_TRACING(
182
- if (ret) gpr_log(GPR_DEBUG, "stream %u un-stalled by stream", (*s)->id));
183
- return ret;
206
+ return stream_list_pop(t, s, GRPC_CHTTP2_LIST_STALLED_BY_STREAM);
184
207
  }
185
208
 
186
209
  bool grpc_chttp2_list_remove_stalled_by_stream(grpc_chttp2_transport *t,
187
210
  grpc_chttp2_stream *s) {
188
- bool ret = stream_list_maybe_remove(t, s, GRPC_CHTTP2_LIST_STALLED_BY_STREAM);
189
- GRPC_FLOW_CONTROL_IF_TRACING(
190
- if (ret) gpr_log(GPR_DEBUG, "stream %u un-stalled by stream", s->id));
191
- return ret;
211
+ return stream_list_maybe_remove(t, s, GRPC_CHTTP2_LIST_STALLED_BY_STREAM);
192
212
  }
@@ -27,8 +27,8 @@
27
27
  void grpc_chttp2_stream_map_init(grpc_chttp2_stream_map *map,
28
28
  size_t initial_capacity) {
29
29
  GPR_ASSERT(initial_capacity > 1);
30
- map->keys = gpr_malloc(sizeof(uint32_t) * initial_capacity);
31
- map->values = gpr_malloc(sizeof(void *) * initial_capacity);
30
+ map->keys = (uint32_t *)gpr_malloc(sizeof(uint32_t) * initial_capacity);
31
+ map->values = (void **)gpr_malloc(sizeof(void *) * initial_capacity);
32
32
  map->count = 0;
33
33
  map->free = 0;
34
34
  map->capacity = initial_capacity;
@@ -72,8 +72,10 @@ void grpc_chttp2_stream_map_add(grpc_chttp2_stream_map *map, uint32_t key,
72
72
  /* resize when less than 25% of the table is free, because compaction
73
73
  won't help much */
74
74
  map->capacity = capacity = 3 * capacity / 2;
75
- map->keys = keys = gpr_realloc(keys, capacity * sizeof(uint32_t));
76
- map->values = values = gpr_realloc(values, capacity * sizeof(void *));
75
+ map->keys = keys =
76
+ (uint32_t *)gpr_realloc(keys, capacity * sizeof(uint32_t));
77
+ map->values = values =
78
+ (void **)gpr_realloc(values, capacity * sizeof(void *));
77
79
  }
78
80
  }
79
81
 
@@ -22,6 +22,7 @@
22
22
 
23
23
  #include <grpc/support/log.h>
24
24
 
25
+ #include "src/core/lib/debug/stats.h"
25
26
  #include "src/core/lib/profiling/timers.h"
26
27
  #include "src/core/lib/slice/slice_internal.h"
27
28
  #include "src/core/lib/transport/http2_errors.h"
@@ -67,7 +68,7 @@ static void maybe_initiate_ping(grpc_exec_ctx *exec_ctx,
67
68
  }
68
69
  if (t->ping_state.pings_before_data_required == 0 &&
69
70
  t->ping_policy.max_pings_without_data != 0) {
70
- /* need to send something of substance before sending a ping again */
71
+ /* need to receive something of substance before sending a ping again */
71
72
  if (GRPC_TRACER_ON(grpc_http_trace) ||
72
73
  GRPC_TRACER_ON(grpc_bdp_estimator_trace)) {
73
74
  gpr_log(GPR_DEBUG, "Ping delayed [%p]: too many recent pings: %d/%d",
@@ -77,11 +78,18 @@ static void maybe_initiate_ping(grpc_exec_ctx *exec_ctx,
77
78
  return;
78
79
  }
79
80
  gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
80
- gpr_timespec elapsed = gpr_time_sub(now, t->ping_state.last_ping_sent_time);
81
- /*gpr_log(GPR_DEBUG, "elapsed:%d.%09d min:%d.%09d", (int)elapsed.tv_sec,
82
- elapsed.tv_nsec, (int)t->ping_policy.min_time_between_pings.tv_sec,
83
- (int)t->ping_policy.min_time_between_pings.tv_nsec);*/
84
- if (gpr_time_cmp(elapsed, t->ping_policy.min_time_between_pings) < 0) {
81
+ gpr_timespec next_allowed_ping =
82
+ gpr_time_add(t->ping_state.last_ping_sent_time,
83
+ t->ping_policy.min_sent_ping_interval_without_data);
84
+ if (t->keepalive_permit_without_calls == 0 &&
85
+ grpc_chttp2_stream_map_size(&t->stream_map) == 0) {
86
+ next_allowed_ping = gpr_time_add(t->ping_recv_state.last_ping_recv_time,
87
+ gpr_time_from_seconds(7200, GPR_TIMESPAN));
88
+ }
89
+ /* gpr_log(GPR_DEBUG, "next_allowed_ping:%d.%09d now:%d.%09d",
90
+ (int)next_allowed_ping.tv_sec, (int)next_allowed_ping.tv_nsec,
91
+ (int)now.tv_sec, (int)now.tv_nsec); */
92
+ if (gpr_time_cmp(next_allowed_ping, now) > 0) {
85
93
  /* not enough elapsed time between successive pings */
86
94
  if (GRPC_TRACER_ON(grpc_http_trace) ||
87
95
  GRPC_TRACER_ON(grpc_bdp_estimator_trace)) {
@@ -92,9 +100,7 @@ static void maybe_initiate_ping(grpc_exec_ctx *exec_ctx,
92
100
  if (!t->ping_state.is_delayed_ping_timer_set) {
93
101
  t->ping_state.is_delayed_ping_timer_set = true;
94
102
  grpc_timer_init(exec_ctx, &t->ping_state.delayed_ping_timer,
95
- gpr_time_add(t->ping_state.last_ping_sent_time,
96
- t->ping_policy.min_time_between_pings),
97
- &t->retry_initiate_ping_locked,
103
+ next_allowed_ping, &t->retry_initiate_ping_locked,
98
104
  gpr_now(GPR_CLOCK_MONOTONIC));
99
105
  }
100
106
  return;
@@ -116,20 +122,30 @@ static void maybe_initiate_ping(grpc_exec_ctx *exec_ctx,
116
122
  &pq->lists[GRPC_CHTTP2_PCL_INFLIGHT]);
117
123
  grpc_slice_buffer_add(&t->outbuf,
118
124
  grpc_chttp2_ping_create(false, pq->inflight_id));
125
+ GRPC_STATS_INC_HTTP2_PINGS_SENT(exec_ctx);
119
126
  t->ping_state.last_ping_sent_time = now;
127
+ if (GRPC_TRACER_ON(grpc_http_trace) ||
128
+ GRPC_TRACER_ON(grpc_bdp_estimator_trace)) {
129
+ gpr_log(GPR_DEBUG, "Ping sent [%p]: %d/%d", t->peer_string,
130
+ t->ping_state.pings_before_data_required,
131
+ t->ping_policy.max_pings_without_data);
132
+ }
120
133
  t->ping_state.pings_before_data_required -=
121
134
  (t->ping_state.pings_before_data_required != 0);
122
135
  }
123
136
 
124
- static void update_list(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
137
+ static bool update_list(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
125
138
  grpc_chttp2_stream *s, int64_t send_bytes,
126
- grpc_chttp2_write_cb **list, grpc_error *error) {
139
+ grpc_chttp2_write_cb **list, int64_t *ctr,
140
+ grpc_error *error) {
141
+ bool sched_any = false;
127
142
  grpc_chttp2_write_cb *cb = *list;
128
143
  *list = NULL;
129
- s->flow_controlled_bytes_written += send_bytes;
144
+ *ctr += send_bytes;
130
145
  while (cb) {
131
146
  grpc_chttp2_write_cb *next = cb->next;
132
- if (cb->call_at_byte <= s->flow_controlled_bytes_written) {
147
+ if (cb->call_at_byte <= *ctr) {
148
+ sched_any = true;
133
149
  finish_write_cb(exec_ctx, t, s, cb, GRPC_ERROR_REF(error));
134
150
  } else {
135
151
  add_to_write_list(list, cb);
@@ -137,6 +153,7 @@ static void update_list(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
137
153
  cb = next;
138
154
  }
139
155
  GRPC_ERROR_UNREF(error);
156
+ return sched_any;
140
157
  }
141
158
 
142
159
  static bool stream_ref_if_not_destroyed(gpr_refcount *r) {
@@ -154,23 +171,23 @@ static uint32_t target_write_size(grpc_chttp2_transport *t) {
154
171
  }
155
172
 
156
173
  // Returns true if initial_metadata contains only default headers.
157
- //
158
- // TODO(roth): The fact that we hard-code these particular headers here
159
- // is fairly ugly. Need some better way to know which headers are
160
- // default, maybe via a bit in the static metadata table?
161
174
  static bool is_default_initial_metadata(grpc_metadata_batch *initial_metadata) {
162
- int num_default_fields =
163
- (initial_metadata->idx.named.status != NULL) +
164
- (initial_metadata->idx.named.content_type != NULL) +
165
- (initial_metadata->idx.named.grpc_encoding != NULL) +
166
- (initial_metadata->idx.named.grpc_accept_encoding != NULL);
167
- return (size_t)num_default_fields == initial_metadata->list.count;
175
+ return initial_metadata->list.default_count == initial_metadata->list.count;
168
176
  }
169
177
 
170
178
  grpc_chttp2_begin_write_result grpc_chttp2_begin_write(
171
179
  grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) {
172
180
  grpc_chttp2_stream *s;
173
181
 
182
+ /* stats histogram counters: we increment these throughout this function,
183
+ and at the end publish to the central stats histograms */
184
+ int flow_control_writes = 0;
185
+ int initial_metadata_writes = 0;
186
+ int trailing_metadata_writes = 0;
187
+ int message_writes = 0;
188
+
189
+ GRPC_STATS_INC_HTTP2_WRITES_BEGUN(exec_ctx);
190
+
174
191
  GPR_TIMER_BEGIN("grpc_chttp2_begin_write", 0);
175
192
 
176
193
  if (t->dirtied_local_settings && !t->sent_local_settings) {
@@ -182,6 +199,7 @@ grpc_chttp2_begin_write_result grpc_chttp2_begin_write(
182
199
  t->force_send_settings = 0;
183
200
  t->dirtied_local_settings = 0;
184
201
  t->sent_local_settings = 1;
202
+ GRPC_STATS_INC_HTTP2_SETTINGS_WRITES(exec_ctx);
185
203
  }
186
204
 
187
205
  /* simple writes are queued to qbuf, and flushed here */
@@ -194,20 +212,19 @@ grpc_chttp2_begin_write_result grpc_chttp2_begin_write(
194
212
 
195
213
  if (t->flow_control.remote_window > 0) {
196
214
  while (grpc_chttp2_list_pop_stalled_by_transport(t, &s)) {
197
- if (!t->closed && grpc_chttp2_list_add_writable_stream(t, s) &&
198
- stream_ref_if_not_destroyed(&s->refcount->refs)) {
199
- grpc_chttp2_initiate_write(exec_ctx, t, "transport.read_flow_control");
215
+ if (!t->closed && grpc_chttp2_list_add_writable_stream(t, s)) {
216
+ stream_ref_if_not_destroyed(&s->refcount->refs);
200
217
  }
201
218
  }
202
219
  }
203
220
 
204
- bool partial_write = false;
221
+ grpc_chttp2_begin_write_result result = {false, false, false};
205
222
 
206
223
  /* for each grpc_chttp2_stream that's become writable, frame it's data
207
224
  (according to available window sizes) and add to the output buffer */
208
225
  while (true) {
209
226
  if (t->outbuf.length > target_write_size(t)) {
210
- partial_write = true;
227
+ result.partial = true;
211
228
  break;
212
229
  }
213
230
 
@@ -252,13 +269,12 @@ grpc_chttp2_begin_write_result grpc_chttp2_begin_write(
252
269
  grpc_chttp2_encode_header(exec_ctx, &t->hpack_compressor, NULL, 0,
253
270
  s->send_initial_metadata, &hopt, &t->outbuf);
254
271
  now_writing = true;
255
- t->ping_state.pings_before_data_required =
256
- t->ping_policy.max_pings_without_data;
257
272
  if (!t->is_client) {
258
273
  t->ping_recv_state.last_ping_recv_time =
259
274
  gpr_inf_past(GPR_CLOCK_MONOTONIC);
260
275
  t->ping_recv_state.ping_strikes = 0;
261
276
  }
277
+ initial_metadata_writes++;
262
278
  } else {
263
279
  GRPC_CHTTP2_IF_TRACING(
264
280
  gpr_log(GPR_INFO, "not sending initial_metadata (Trailers-Only)"));
@@ -274,10 +290,15 @@ grpc_chttp2_begin_write_result grpc_chttp2_begin_write(
274
290
  [num_extra_headers_for_trailing_metadata++] =
275
291
  &s->send_initial_metadata->idx.named.content_type->md;
276
292
  }
293
+ trailing_metadata_writes++;
277
294
  }
278
295
  s->send_initial_metadata = NULL;
279
296
  s->sent_initial_metadata = true;
280
297
  sent_initial_metadata = true;
298
+ result.early_results_scheduled = true;
299
+ grpc_chttp2_complete_closure_step(
300
+ exec_ctx, t, s, &s->send_initial_metadata_finished, GRPC_ERROR_NONE,
301
+ "send_initial_metadata_finished");
281
302
  }
282
303
  /* send any window updates */
283
304
  uint32_t stream_announce = grpc_chttp2_flowctl_maybe_send_stream_update(
@@ -286,19 +307,17 @@ grpc_chttp2_begin_write_result grpc_chttp2_begin_write(
286
307
  grpc_slice_buffer_add(
287
308
  &t->outbuf, grpc_chttp2_window_update_create(s->id, stream_announce,
288
309
  &s->stats.outgoing));
289
- t->ping_state.pings_before_data_required =
290
- t->ping_policy.max_pings_without_data;
291
310
  if (!t->is_client) {
292
311
  t->ping_recv_state.last_ping_recv_time =
293
312
  gpr_inf_past(GPR_CLOCK_MONOTONIC);
294
313
  t->ping_recv_state.ping_strikes = 0;
295
314
  }
315
+ flow_control_writes++;
296
316
  }
297
317
  if (sent_initial_metadata) {
298
318
  /* send any body bytes, if allowed by flow control */
299
319
  if (s->flow_controlled_buffer.length > 0 ||
300
- (s->stream_compression_send_enabled &&
301
- s->compressed_data_buffer->length > 0)) {
320
+ s->compressed_data_buffer.length > 0) {
302
321
  uint32_t stream_remote_window = (uint32_t)GPR_MAX(
303
322
  0,
304
323
  s->flow_control.remote_window_delta +
@@ -311,59 +330,61 @@ grpc_chttp2_begin_write_result grpc_chttp2_begin_write(
311
330
  if (max_outgoing > 0) {
312
331
  bool is_last_data_frame = false;
313
332
  bool is_last_frame = false;
314
- if (s->stream_compression_send_enabled) {
315
- while ((s->flow_controlled_buffer.length > 0 ||
316
- s->compressed_data_buffer->length > 0) &&
317
- max_outgoing > 0) {
318
- if (s->compressed_data_buffer->length > 0) {
319
- uint32_t send_bytes = (uint32_t)GPR_MIN(
320
- max_outgoing, s->compressed_data_buffer->length);
321
- is_last_data_frame =
322
- (send_bytes == s->compressed_data_buffer->length &&
323
- s->flow_controlled_buffer.length == 0 &&
324
- s->fetching_send_message == NULL);
325
- is_last_frame =
326
- is_last_data_frame && s->send_trailing_metadata != NULL &&
327
- grpc_metadata_batch_is_empty(s->send_trailing_metadata);
328
- grpc_chttp2_encode_data(s->id, s->compressed_data_buffer,
329
- send_bytes, is_last_frame,
330
- &s->stats.outgoing, &t->outbuf);
331
- grpc_chttp2_flowctl_sent_data(&t->flow_control,
332
- &s->flow_control, send_bytes);
333
- max_outgoing -= send_bytes;
334
- if (s->compressed_data_buffer->length == 0) {
335
- s->sending_bytes += s->uncompressed_data_size;
336
- }
337
- } else {
338
- if (s->stream_compression_ctx == NULL) {
339
- s->stream_compression_ctx =
340
- grpc_stream_compression_context_create(
341
- GRPC_STREAM_COMPRESSION_COMPRESS);
333
+ size_t sending_bytes_before = s->sending_bytes;
334
+ while ((s->flow_controlled_buffer.length > 0 ||
335
+ s->compressed_data_buffer.length > 0) &&
336
+ max_outgoing > 0) {
337
+ if (s->compressed_data_buffer.length > 0) {
338
+ uint32_t send_bytes = (uint32_t)GPR_MIN(
339
+ max_outgoing, s->compressed_data_buffer.length);
340
+ is_last_data_frame =
341
+ (send_bytes == s->compressed_data_buffer.length &&
342
+ s->flow_controlled_buffer.length == 0 &&
343
+ s->fetching_send_message == NULL);
344
+ if (is_last_data_frame && s->send_trailing_metadata != NULL &&
345
+ s->stream_compression_ctx != NULL) {
346
+ if (!grpc_stream_compress(
347
+ s->stream_compression_ctx, &s->flow_controlled_buffer,
348
+ &s->compressed_data_buffer, NULL, MAX_SIZE_T,
349
+ GRPC_STREAM_COMPRESSION_FLUSH_FINISH)) {
350
+ gpr_log(GPR_ERROR, "Stream compression failed.");
342
351
  }
343
- s->uncompressed_data_size = s->flow_controlled_buffer.length;
344
- GPR_ASSERT(grpc_stream_compress(
345
- s->stream_compression_ctx, &s->flow_controlled_buffer,
346
- s->compressed_data_buffer, NULL, MAX_SIZE_T,
347
- GRPC_STREAM_COMPRESSION_FLUSH_SYNC));
352
+ grpc_stream_compression_context_destroy(
353
+ s->stream_compression_ctx);
354
+ s->stream_compression_ctx = NULL;
355
+ /* After finish, bytes in s->compressed_data_buffer may be
356
+ * more than max_outgoing. Start another round of the current
357
+ * while loop so that send_bytes and is_last_data_frame are
358
+ * recalculated. */
359
+ continue;
360
+ }
361
+ is_last_frame =
362
+ is_last_data_frame && s->send_trailing_metadata != NULL &&
363
+ grpc_metadata_batch_is_empty(s->send_trailing_metadata);
364
+ grpc_chttp2_encode_data(s->id, &s->compressed_data_buffer,
365
+ send_bytes, is_last_frame,
366
+ &s->stats.outgoing, &t->outbuf);
367
+ grpc_chttp2_flowctl_sent_data(&t->flow_control, &s->flow_control,
368
+ send_bytes);
369
+ max_outgoing -= send_bytes;
370
+ if (s->compressed_data_buffer.length == 0) {
371
+ s->sending_bytes += s->uncompressed_data_size;
372
+ }
373
+ } else {
374
+ if (s->stream_compression_ctx == NULL) {
375
+ s->stream_compression_ctx =
376
+ grpc_stream_compression_context_create(
377
+ s->stream_compression_method);
378
+ }
379
+ s->uncompressed_data_size = s->flow_controlled_buffer.length;
380
+ if (!grpc_stream_compress(
381
+ s->stream_compression_ctx, &s->flow_controlled_buffer,
382
+ &s->compressed_data_buffer, NULL, MAX_SIZE_T,
383
+ GRPC_STREAM_COMPRESSION_FLUSH_SYNC)) {
384
+ gpr_log(GPR_ERROR, "Stream compression failed.");
348
385
  }
349
386
  }
350
- } else {
351
- uint32_t send_bytes = (uint32_t)GPR_MIN(
352
- max_outgoing, s->flow_controlled_buffer.length);
353
- is_last_data_frame = s->fetching_send_message == NULL &&
354
- send_bytes == s->flow_controlled_buffer.length;
355
- is_last_frame =
356
- is_last_data_frame && s->send_trailing_metadata != NULL &&
357
- grpc_metadata_batch_is_empty(s->send_trailing_metadata);
358
- grpc_chttp2_encode_data(s->id, &s->flow_controlled_buffer,
359
- send_bytes, is_last_frame,
360
- &s->stats.outgoing, &t->outbuf);
361
- grpc_chttp2_flowctl_sent_data(&t->flow_control, &s->flow_control,
362
- send_bytes);
363
- s->sending_bytes += send_bytes;
364
387
  }
365
- t->ping_state.pings_before_data_required =
366
- t->ping_policy.max_pings_without_data;
367
388
  if (!t->is_client) {
368
389
  t->ping_recv_state.last_ping_recv_time =
369
390
  gpr_inf_past(GPR_CLOCK_MONOTONIC);
@@ -377,14 +398,21 @@ grpc_chttp2_begin_write_result grpc_chttp2_begin_write(
377
398
  s->id, GRPC_HTTP2_NO_ERROR,
378
399
  &s->stats.outgoing));
379
400
  }
401
+ grpc_chttp2_mark_stream_closed(exec_ctx, t, s, !t->is_client, 1,
402
+ GRPC_ERROR_NONE);
380
403
  }
404
+ result.early_results_scheduled |=
405
+ update_list(exec_ctx, t, s,
406
+ (int64_t)(s->sending_bytes - sending_bytes_before),
407
+ &s->on_flow_controlled_cbs,
408
+ &s->flow_controlled_bytes_flowed, GRPC_ERROR_NONE);
381
409
  now_writing = true;
382
410
  if (s->flow_controlled_buffer.length > 0 ||
383
- (s->stream_compression_send_enabled &&
384
- s->compressed_data_buffer->length > 0)) {
411
+ s->compressed_data_buffer.length > 0) {
385
412
  GRPC_CHTTP2_STREAM_REF(s, "chttp2_writing:fork");
386
413
  grpc_chttp2_list_add_writable_stream(t, s);
387
414
  }
415
+ message_writes++;
388
416
  } else if (t->flow_control.remote_window == 0) {
389
417
  grpc_chttp2_list_add_stalled_by_transport(t, s);
390
418
  now_writing = true;
@@ -396,8 +424,7 @@ grpc_chttp2_begin_write_result grpc_chttp2_begin_write(
396
424
  if (s->send_trailing_metadata != NULL &&
397
425
  s->fetching_send_message == NULL &&
398
426
  s->flow_controlled_buffer.length == 0 &&
399
- (!s->stream_compression_send_enabled ||
400
- s->compressed_data_buffer->length == 0)) {
427
+ s->compressed_data_buffer.length == 0) {
401
428
  GRPC_CHTTP2_IF_TRACING(gpr_log(GPR_INFO, "sending trailing_metadata"));
402
429
  if (grpc_metadata_batch_is_empty(s->send_trailing_metadata)) {
403
430
  grpc_chttp2_encode_data(s->id, &s->flow_controlled_buffer, 0, true,
@@ -420,6 +447,7 @@ grpc_chttp2_begin_write_result grpc_chttp2_begin_write(
420
447
  num_extra_headers_for_trailing_metadata,
421
448
  s->send_trailing_metadata, &hopt,
422
449
  &t->outbuf);
450
+ trailing_metadata_writes++;
423
451
  }
424
452
  s->send_trailing_metadata = NULL;
425
453
  s->sent_trailing_metadata = true;
@@ -428,11 +456,25 @@ grpc_chttp2_begin_write_result grpc_chttp2_begin_write(
428
456
  &t->outbuf, grpc_chttp2_rst_stream_create(
429
457
  s->id, GRPC_HTTP2_NO_ERROR, &s->stats.outgoing));
430
458
  }
459
+ grpc_chttp2_mark_stream_closed(exec_ctx, t, s, !t->is_client, 1,
460
+ GRPC_ERROR_NONE);
431
461
  now_writing = true;
462
+ result.early_results_scheduled = true;
463
+ grpc_chttp2_complete_closure_step(
464
+ exec_ctx, t, s, &s->send_trailing_metadata_finished,
465
+ GRPC_ERROR_NONE, "send_trailing_metadata_finished");
432
466
  }
433
467
  }
434
468
 
435
469
  if (now_writing) {
470
+ GRPC_STATS_INC_HTTP2_SEND_INITIAL_METADATA_PER_WRITE(
471
+ exec_ctx, initial_metadata_writes);
472
+ GRPC_STATS_INC_HTTP2_SEND_MESSAGE_PER_WRITE(exec_ctx, message_writes);
473
+ GRPC_STATS_INC_HTTP2_SEND_TRAILING_METADATA_PER_WRITE(
474
+ exec_ctx, trailing_metadata_writes);
475
+ GRPC_STATS_INC_HTTP2_SEND_FLOWCTL_PER_WRITE(exec_ctx,
476
+ flow_control_writes);
477
+
436
478
  if (!grpc_chttp2_list_add_writing_stream(t, s)) {
437
479
  /* already in writing list: drop ref */
438
480
  GRPC_CHTTP2_STREAM_UNREF(exec_ctx, s, "chttp2_writing:already_writing");
@@ -451,8 +493,6 @@ grpc_chttp2_begin_write_result grpc_chttp2_begin_write(
451
493
  grpc_slice_buffer_add(
452
494
  &t->outbuf, grpc_chttp2_window_update_create(0, transport_announce,
453
495
  &throwaway_stats));
454
- t->ping_state.pings_before_data_required =
455
- t->ping_policy.max_pings_without_data;
456
496
  if (!t->is_client) {
457
497
  t->ping_recv_state.last_ping_recv_time =
458
498
  gpr_inf_past(GPR_CLOCK_MONOTONIC);
@@ -470,9 +510,8 @@ grpc_chttp2_begin_write_result grpc_chttp2_begin_write(
470
510
 
471
511
  GPR_TIMER_END("grpc_chttp2_begin_write", 0);
472
512
 
473
- return t->outbuf.count > 0 ? (partial_write ? GRPC_CHTTP2_PARTIAL_WRITE
474
- : GRPC_CHTTP2_FULL_WRITE)
475
- : GRPC_CHTTP2_NOTHING_TO_WRITE;
513
+ result.writing = t->outbuf.count > 0;
514
+ return result;
476
515
  }
477
516
 
478
517
  void grpc_chttp2_end_write(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
@@ -481,23 +520,12 @@ void grpc_chttp2_end_write(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
481
520
  grpc_chttp2_stream *s;
482
521
 
483
522
  while (grpc_chttp2_list_pop_writing_stream(t, &s)) {
484
- if (s->sent_initial_metadata) {
485
- grpc_chttp2_complete_closure_step(
486
- exec_ctx, t, s, &s->send_initial_metadata_finished,
487
- GRPC_ERROR_REF(error), "send_initial_metadata_finished");
488
- }
489
523
  if (s->sending_bytes != 0) {
490
524
  update_list(exec_ctx, t, s, (int64_t)s->sending_bytes,
491
- &s->on_write_finished_cbs, GRPC_ERROR_REF(error));
525
+ &s->on_write_finished_cbs, &s->flow_controlled_bytes_written,
526
+ GRPC_ERROR_REF(error));
492
527
  s->sending_bytes = 0;
493
528
  }
494
- if (s->sent_trailing_metadata) {
495
- grpc_chttp2_complete_closure_step(
496
- exec_ctx, t, s, &s->send_trailing_metadata_finished,
497
- GRPC_ERROR_REF(error), "send_trailing_metadata_finished");
498
- grpc_chttp2_mark_stream_closed(exec_ctx, t, s, !t->is_client, 1,
499
- GRPC_ERROR_REF(error));
500
- }
501
529
  GRPC_CHTTP2_STREAM_UNREF(exec_ctx, s, "chttp2_writing:end");
502
530
  }
503
531
  grpc_slice_buffer_reset_and_unref_internal(exec_ctx, &t->outbuf);