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
@@ -0,0 +1,35 @@
1
+ /*
2
+ *
3
+ * Copyright 2017 gRPC authors.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ *
17
+ */
18
+
19
+ #ifndef GRPC_CORE_LIB_SUPPORT_FORK_H
20
+ #define GRPC_CORE_LIB_SUPPORT_FORK_H
21
+
22
+ /*
23
+ * NOTE: FORKING IS NOT GENERALLY SUPPORTED, THIS IS ONLY INTENDED TO WORK
24
+ * AROUND VERY SPECIFIC USE CASES.
25
+ */
26
+
27
+ void grpc_fork_support_init(void);
28
+
29
+ int grpc_fork_support_enabled(void);
30
+
31
+ // Test only: Must be called before grpc_init(), and overrides
32
+ // environment variables/compile flags
33
+ void grpc_enable_fork_support(int enable);
34
+
35
+ #endif /* GRPC_CORE_LIB_SUPPORT_FORK_H */
@@ -57,7 +57,7 @@ void gpr_log(const char *file, int line, gpr_log_severity severity,
57
57
  }
58
58
 
59
59
  void gpr_default_log(gpr_log_func_args *args) {
60
- char *final_slash;
60
+ const char *final_slash;
61
61
  char *prefix;
62
62
  const char *display_file;
63
63
  char time_buffer[64];
@@ -276,7 +276,7 @@ static void add_string_to_split(const char *beg, const char *end, char ***strs,
276
276
 
277
277
  void gpr_string_split(const char *input, const char *sep, char ***strs,
278
278
  size_t *nstrs) {
279
- char *next;
279
+ const char *next;
280
280
  *strs = NULL;
281
281
  *nstrs = 0;
282
282
  size_t capstrs = 0;
@@ -298,3 +298,17 @@ void *gpr_memrchr(const void *s, int c, size_t n) {
298
298
  }
299
299
  return NULL;
300
300
  }
301
+
302
+ bool gpr_is_true(const char *s) {
303
+ size_t i;
304
+ if (s == NULL) {
305
+ return false;
306
+ }
307
+ static const char *truthy[] = {"yes", "true", "1"};
308
+ for (i = 0; i < GPR_ARRAY_SIZE(truthy); i++) {
309
+ if (0 == gpr_stricmp(s, truthy[i])) {
310
+ return true;
311
+ }
312
+ }
313
+ return false;
314
+ }
@@ -19,6 +19,7 @@
19
19
  #ifndef GRPC_CORE_LIB_SUPPORT_STRING_H
20
20
  #define GRPC_CORE_LIB_SUPPORT_STRING_H
21
21
 
22
+ #include <stdbool.h>
22
23
  #include <stddef.h>
23
24
 
24
25
  #include <grpc/support/port_platform.h>
@@ -106,6 +107,8 @@ int gpr_stricmp(const char *a, const char *b);
106
107
 
107
108
  void *gpr_memrchr(const void *s, int c, size_t n);
108
109
 
110
+ /** Return true if lower(s) equals "true", "yes" or "1", otherwise false. */
111
+ bool gpr_is_true(const char *s);
109
112
  #ifdef __cplusplus
110
113
  }
111
114
  #endif
@@ -19,6 +19,12 @@
19
19
  #ifndef GRPC_CORE_LIB_SUPPORT_THD_INTERNAL_H
20
20
  #define GRPC_CORE_LIB_SUPPORT_THD_INTERNAL_H
21
21
 
22
+ #include <grpc/support/time.h>
23
+
22
24
  /* Internal interfaces between modules within the gpr support library. */
25
+ void gpr_thd_init();
26
+
27
+ /* Wait for all outstanding threads to finish, up to deadline */
28
+ int gpr_await_threads(gpr_timespec deadline);
23
29
 
24
30
  #endif /* GRPC_CORE_LIB_SUPPORT_THD_INTERNAL_H */
@@ -24,22 +24,34 @@
24
24
 
25
25
  #include <grpc/support/alloc.h>
26
26
  #include <grpc/support/log.h>
27
+ #include <grpc/support/sync.h>
27
28
  #include <grpc/support/thd.h>
28
29
  #include <grpc/support/useful.h>
29
30
  #include <pthread.h>
30
31
  #include <stdlib.h>
31
32
  #include <string.h>
32
33
 
34
+ #include "src/core/lib/support/fork.h"
35
+
36
+ static gpr_mu g_mu;
37
+ static gpr_cv g_cv;
38
+ static int g_thread_count;
39
+ static int g_awaiting_threads;
40
+
33
41
  struct thd_arg {
34
42
  void (*body)(void *arg); /* body of a thread */
35
43
  void *arg; /* argument to a thread */
36
44
  };
37
45
 
46
+ static void inc_thd_count();
47
+ static void dec_thd_count();
48
+
38
49
  /* Body of every thread started via gpr_thd_new. */
39
50
  static void *thread_body(void *v) {
40
51
  struct thd_arg a = *(struct thd_arg *)v;
41
52
  free(v);
42
53
  (*a.body)(a.arg);
54
+ dec_thd_count();
43
55
  return NULL;
44
56
  }
45
57
 
@@ -54,6 +66,7 @@ int gpr_thd_new(gpr_thd_id *t, void (*thd_body)(void *arg), void *arg,
54
66
  GPR_ASSERT(a != NULL);
55
67
  a->body = thd_body;
56
68
  a->arg = arg;
69
+ inc_thd_count();
57
70
 
58
71
  GPR_ASSERT(pthread_attr_init(&attr) == 0);
59
72
  if (gpr_thd_options_is_detached(options)) {
@@ -68,6 +81,7 @@ int gpr_thd_new(gpr_thd_id *t, void (*thd_body)(void *arg), void *arg,
68
81
  if (!thread_started) {
69
82
  /* don't use gpr_free, as this was allocated using malloc (see above) */
70
83
  free(a);
84
+ dec_thd_count();
71
85
  }
72
86
  *t = (gpr_thd_id)p;
73
87
  return thread_started;
@@ -77,4 +91,46 @@ gpr_thd_id gpr_thd_currentid(void) { return (gpr_thd_id)pthread_self(); }
77
91
 
78
92
  void gpr_thd_join(gpr_thd_id t) { pthread_join((pthread_t)t, NULL); }
79
93
 
94
+ /*****************************************
95
+ * Only used when fork support is enabled
96
+ */
97
+
98
+ static void inc_thd_count() {
99
+ if (grpc_fork_support_enabled()) {
100
+ gpr_mu_lock(&g_mu);
101
+ g_thread_count++;
102
+ gpr_mu_unlock(&g_mu);
103
+ }
104
+ }
105
+
106
+ static void dec_thd_count() {
107
+ if (grpc_fork_support_enabled()) {
108
+ gpr_mu_lock(&g_mu);
109
+ g_thread_count--;
110
+ if (g_awaiting_threads && g_thread_count == 0) {
111
+ gpr_cv_signal(&g_cv);
112
+ }
113
+ gpr_mu_unlock(&g_mu);
114
+ }
115
+ }
116
+
117
+ void gpr_thd_init() {
118
+ gpr_mu_init(&g_mu);
119
+ gpr_cv_init(&g_cv);
120
+ g_thread_count = 0;
121
+ g_awaiting_threads = 0;
122
+ }
123
+
124
+ int gpr_await_threads(gpr_timespec deadline) {
125
+ gpr_mu_lock(&g_mu);
126
+ g_awaiting_threads = 1;
127
+ int res = 0;
128
+ if (g_thread_count > 0) {
129
+ res = gpr_cv_wait(&g_cv, &g_mu, deadline);
130
+ }
131
+ g_awaiting_threads = 0;
132
+ gpr_mu_unlock(&g_mu);
133
+ return res == 0;
134
+ }
135
+
80
136
  #endif /* GPR_POSIX_SYNC */
@@ -50,6 +50,8 @@ static void destroy_thread(struct thd_info *t) {
50
50
  gpr_free(t);
51
51
  }
52
52
 
53
+ void gpr_thd_init(void) {}
54
+
53
55
  /* Body of every thread started via gpr_thd_new. */
54
56
  static DWORD WINAPI thread_body(void *v) {
55
57
  g_thd_info = (struct thd_info *)v;
@@ -44,7 +44,9 @@ static void alarm_ref(grpc_alarm *alarm) { gpr_ref(&alarm->refs); }
44
44
  static void alarm_unref(grpc_alarm *alarm) {
45
45
  if (gpr_unref(&alarm->refs)) {
46
46
  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
47
- GRPC_CQ_INTERNAL_UNREF(&exec_ctx, alarm->cq, "alarm");
47
+ if (alarm->cq != NULL) {
48
+ GRPC_CQ_INTERNAL_UNREF(&exec_ctx, alarm->cq, "alarm");
49
+ }
48
50
  grpc_exec_ctx_finish(&exec_ctx);
49
51
  gpr_free(alarm);
50
52
  }
@@ -78,12 +80,12 @@ static void alarm_unref_dbg(grpc_alarm *alarm, const char *reason,
78
80
 
79
81
  static void alarm_end_completion(grpc_exec_ctx *exec_ctx, void *arg,
80
82
  grpc_cq_completion *c) {
81
- grpc_alarm *alarm = arg;
83
+ grpc_alarm *alarm = (grpc_alarm *)arg;
82
84
  GRPC_ALARM_UNREF(alarm, "dequeue-end-op");
83
85
  }
84
86
 
85
87
  static void alarm_cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
86
- grpc_alarm *alarm = arg;
88
+ grpc_alarm *alarm = (grpc_alarm *)arg;
87
89
 
88
90
  /* We are queuing an op on completion queue. This means, the alarm's structure
89
91
  cannot be destroyed until the op is dequeued. Adding an extra ref
@@ -93,12 +95,8 @@ static void alarm_cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
93
95
  (void *)alarm, &alarm->completion);
94
96
  }
95
97
 
96
- grpc_alarm *grpc_alarm_create(grpc_completion_queue *cq, gpr_timespec deadline,
97
- void *tag) {
98
- grpc_alarm *alarm = gpr_malloc(sizeof(grpc_alarm));
99
- grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
100
-
101
- gpr_ref_init(&alarm->refs, 1);
98
+ grpc_alarm *grpc_alarm_create(void *reserved) {
99
+ grpc_alarm *alarm = (grpc_alarm *)gpr_malloc(sizeof(grpc_alarm));
102
100
 
103
101
  #ifndef NDEBUG
104
102
  if (GRPC_TRACER_ON(grpc_trace_alarm_refcount)) {
@@ -106,27 +104,36 @@ grpc_alarm *grpc_alarm_create(grpc_completion_queue *cq, gpr_timespec deadline,
106
104
  }
107
105
  #endif
108
106
 
107
+ gpr_ref_init(&alarm->refs, 1);
108
+ grpc_timer_init_unset(&alarm->alarm);
109
+ alarm->cq = NULL;
110
+ GRPC_CLOSURE_INIT(&alarm->on_alarm, alarm_cb, alarm,
111
+ grpc_schedule_on_exec_ctx);
112
+ return alarm;
113
+ }
114
+
115
+ void grpc_alarm_set(grpc_alarm *alarm, grpc_completion_queue *cq,
116
+ gpr_timespec deadline, void *tag, void *reserved) {
117
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
118
+
109
119
  GRPC_CQ_INTERNAL_REF(cq, "alarm");
110
120
  alarm->cq = cq;
111
121
  alarm->tag = tag;
112
122
 
113
123
  GPR_ASSERT(grpc_cq_begin_op(cq, tag));
114
- GRPC_CLOSURE_INIT(&alarm->on_alarm, alarm_cb, alarm,
115
- grpc_schedule_on_exec_ctx);
116
124
  grpc_timer_init(&exec_ctx, &alarm->alarm,
117
125
  gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC),
118
126
  &alarm->on_alarm, gpr_now(GPR_CLOCK_MONOTONIC));
119
127
  grpc_exec_ctx_finish(&exec_ctx);
120
- return alarm;
121
128
  }
122
129
 
123
- void grpc_alarm_cancel(grpc_alarm *alarm) {
130
+ void grpc_alarm_cancel(grpc_alarm *alarm, void *reserved) {
124
131
  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
125
132
  grpc_timer_cancel(&exec_ctx, &alarm->alarm);
126
133
  grpc_exec_ctx_finish(&exec_ctx);
127
134
  }
128
135
 
129
- void grpc_alarm_destroy(grpc_alarm *alarm) {
130
- grpc_alarm_cancel(alarm);
136
+ void grpc_alarm_destroy(grpc_alarm *alarm, void *reserved) {
137
+ grpc_alarm_cancel(alarm, reserved);
131
138
  GRPC_ALARM_UNREF(alarm, "alarm_destroy");
132
139
  }
@@ -32,7 +32,8 @@ grpc_byte_buffer *grpc_raw_compressed_byte_buffer_create(
32
32
  grpc_slice *slices, size_t nslices,
33
33
  grpc_compression_algorithm compression) {
34
34
  size_t i;
35
- grpc_byte_buffer *bb = gpr_malloc(sizeof(grpc_byte_buffer));
35
+ grpc_byte_buffer *bb =
36
+ (grpc_byte_buffer *)gpr_malloc(sizeof(grpc_byte_buffer));
36
37
  bb->type = GRPC_BB_RAW;
37
38
  bb->data.raw.compression = compression;
38
39
  grpc_slice_buffer_init(&bb->data.raw.slice_buffer);
@@ -45,7 +46,8 @@ grpc_byte_buffer *grpc_raw_compressed_byte_buffer_create(
45
46
 
46
47
  grpc_byte_buffer *grpc_raw_byte_buffer_from_reader(
47
48
  grpc_byte_buffer_reader *reader) {
48
- grpc_byte_buffer *bb = gpr_malloc(sizeof(grpc_byte_buffer));
49
+ grpc_byte_buffer *bb =
50
+ (grpc_byte_buffer *)gpr_malloc(sizeof(grpc_byte_buffer));
49
51
  grpc_slice slice;
50
52
  bb->type = GRPC_BB_RAW;
51
53
  bb->data.raw.compression = GRPC_COMPRESS_NONE;
@@ -32,6 +32,7 @@
32
32
 
33
33
  #include "src/core/lib/channel/channel_stack.h"
34
34
  #include "src/core/lib/compression/algorithm_metadata.h"
35
+ #include "src/core/lib/debug/stats.h"
35
36
  #include "src/core/lib/iomgr/timer.h"
36
37
  #include "src/core/lib/profiling/timers.h"
37
38
  #include "src/core/lib/slice/slice_internal.h"
@@ -121,6 +122,7 @@ typedef struct batch_control {
121
122
  bool is_closure;
122
123
  } notify_tag;
123
124
  } completion_data;
125
+ grpc_closure start_batch;
124
126
  grpc_closure finish_batch;
125
127
  gpr_refcount steps_to_complete;
126
128
 
@@ -144,15 +146,19 @@ typedef struct {
144
146
  grpc_call *sibling_prev;
145
147
  } child_call;
146
148
 
149
+ #define RECV_NONE ((gpr_atm)0)
150
+ #define RECV_INITIAL_METADATA_FIRST ((gpr_atm)1)
151
+
147
152
  struct grpc_call {
148
153
  gpr_refcount ext_ref;
149
154
  gpr_arena *arena;
155
+ grpc_call_combiner call_combiner;
150
156
  grpc_completion_queue *cq;
151
157
  grpc_polling_entity pollent;
152
158
  grpc_channel *channel;
153
159
  gpr_timespec start_time;
154
160
  /* parent_call* */ gpr_atm parent_call_atm;
155
- child_call *child_call;
161
+ child_call *child;
156
162
 
157
163
  /* client or server call */
158
164
  bool is_client;
@@ -170,9 +176,6 @@ struct grpc_call {
170
176
  gpr_atm any_ops_sent_atm;
171
177
  gpr_atm received_final_op_atm;
172
178
 
173
- /* have we received initial metadata */
174
- bool has_initial_md_been_received;
175
-
176
179
  batch_control *active_batches[MAX_CONCURRENT_BATCHES];
177
180
  grpc_transport_stream_op_batch_payload stream_op_payload;
178
181
 
@@ -183,6 +186,11 @@ struct grpc_call {
183
186
  Element 0 is initial metadata, element 1 is trailing metadata. */
184
187
  grpc_metadata_array *buffered_metadata[2];
185
188
 
189
+ grpc_metadata compression_md;
190
+
191
+ // A char* indicating the peer name.
192
+ gpr_atm peer_string;
193
+
186
194
  /* Packed received call statuses from various sources */
187
195
  gpr_atm status[STATUS_SOURCE_COUNT];
188
196
 
@@ -192,8 +200,12 @@ struct grpc_call {
192
200
 
193
201
  /* Compression algorithm for *incoming* data */
194
202
  grpc_compression_algorithm incoming_compression_algorithm;
203
+ /* Stream compression algorithm for *incoming* data */
204
+ grpc_stream_compression_algorithm incoming_stream_compression_algorithm;
195
205
  /* Supported encodings (compression algorithms), a bitset */
196
206
  uint32_t encodings_accepted_by_peer;
207
+ /* Supported stream encodings (stream compression algorithms), a bitset */
208
+ uint32_t stream_encodings_accepted_by_peer;
197
209
 
198
210
  /* Contexts for various subsystems (security, tracing, ...). */
199
211
  grpc_call_context_element context[GRPC_CONTEXT_COUNT];
@@ -226,7 +238,23 @@ struct grpc_call {
226
238
  } server;
227
239
  } final_op;
228
240
 
229
- void *saved_receiving_stream_ready_bctlp;
241
+ /* recv_state can contain one of the following values:
242
+ RECV_NONE : : no initial metadata and messages received
243
+ RECV_INITIAL_METADATA_FIRST : received initial metadata first
244
+ a batch_control* : received messages first
245
+
246
+ +------1------RECV_NONE------3-----+
247
+ | |
248
+ | |
249
+ v v
250
+ RECV_INITIAL_METADATA_FIRST receiving_stream_ready_bctlp
251
+ | ^ | ^
252
+ | | | |
253
+ +-----2-----+ +-----4-----+
254
+
255
+ For 1, 4: See receiving_initial_metadata_ready() function
256
+ For 2, 3: See receiving_stream_ready() function */
257
+ gpr_atm recv_state;
230
258
  };
231
259
 
232
260
  grpc_tracer_flag grpc_call_error_trace =
@@ -241,8 +269,9 @@ grpc_tracer_flag grpc_compression_trace =
241
269
  #define CALL_FROM_TOP_ELEM(top_elem) \
242
270
  CALL_FROM_CALL_STACK(grpc_call_stack_from_top_element(top_elem))
243
271
 
244
- static void execute_op(grpc_exec_ctx *exec_ctx, grpc_call *call,
245
- grpc_transport_stream_op_batch *op);
272
+ static void execute_batch(grpc_exec_ctx *exec_ctx, grpc_call *call,
273
+ grpc_transport_stream_op_batch *op,
274
+ grpc_closure *start_batch_closure);
246
275
  static void cancel_with_status(grpc_exec_ctx *exec_ctx, grpc_call *c,
247
276
  status_source source, grpc_status_code status,
248
277
  const char *description);
@@ -264,11 +293,11 @@ static void post_batch_completion(grpc_exec_ctx *exec_ctx, batch_control *bctl);
264
293
  static void add_batch_error(grpc_exec_ctx *exec_ctx, batch_control *bctl,
265
294
  grpc_error *error, bool has_cancelled);
266
295
 
267
- static void add_init_error(grpc_error **composite, grpc_error *new) {
268
- if (new == GRPC_ERROR_NONE) return;
296
+ static void add_init_error(grpc_error **composite, grpc_error *new_err) {
297
+ if (new_err == GRPC_ERROR_NONE) return;
269
298
  if (*composite == GRPC_ERROR_NONE)
270
299
  *composite = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Call creation failed");
271
- *composite = grpc_error_add_child(*composite, new);
300
+ *composite = grpc_error_add_child(*composite, new_err);
272
301
  }
273
302
 
274
303
  void *grpc_call_arena_alloc(grpc_call *call, size_t size) {
@@ -278,7 +307,7 @@ void *grpc_call_arena_alloc(grpc_call *call, size_t size) {
278
307
  static parent_call *get_or_create_parent_call(grpc_call *call) {
279
308
  parent_call *p = (parent_call *)gpr_atm_acq_load(&call->parent_call_atm);
280
309
  if (p == NULL) {
281
- p = gpr_arena_alloc(call->arena, sizeof(*p));
310
+ p = (parent_call *)gpr_arena_alloc(call->arena, sizeof(*p));
282
311
  gpr_mu_init(&p->child_list_mu);
283
312
  if (!gpr_atm_rel_cas(&call->parent_call_atm, (gpr_atm)NULL, (gpr_atm)p)) {
284
313
  gpr_mu_destroy(&p->child_list_mu);
@@ -301,12 +330,14 @@ grpc_error *grpc_call_create(grpc_exec_ctx *exec_ctx,
301
330
  grpc_channel_get_channel_stack(args->channel);
302
331
  grpc_call *call;
303
332
  GPR_TIMER_BEGIN("grpc_call_create", 0);
304
- gpr_arena *arena =
305
- gpr_arena_create(grpc_channel_get_call_size_estimate(args->channel));
306
- call = gpr_arena_alloc(arena,
307
- sizeof(grpc_call) + channel_stack->call_stack_size);
333
+ size_t initial_size = grpc_channel_get_call_size_estimate(args->channel);
334
+ GRPC_STATS_INC_CALL_INITIAL_SIZE(exec_ctx, initial_size);
335
+ gpr_arena *arena = gpr_arena_create(initial_size);
336
+ call = (grpc_call *)gpr_arena_alloc(
337
+ arena, sizeof(grpc_call) + channel_stack->call_stack_size);
308
338
  gpr_ref_init(&call->ext_ref, 1);
309
339
  call->arena = arena;
340
+ grpc_call_combiner_init(&call->call_combiner);
310
341
  *out_call = call;
311
342
  call->channel = args->channel;
312
343
  call->cq = args->cq;
@@ -314,6 +345,11 @@ grpc_error *grpc_call_create(grpc_exec_ctx *exec_ctx,
314
345
  /* Always support no compression */
315
346
  GPR_BITSET(&call->encodings_accepted_by_peer, GRPC_COMPRESS_NONE);
316
347
  call->is_client = args->server_transport_data == NULL;
348
+ if (call->is_client) {
349
+ GRPC_STATS_INC_CLIENT_CALLS_CREATED(exec_ctx);
350
+ } else {
351
+ GRPC_STATS_INC_SERVER_CALLS_CREATED(exec_ctx);
352
+ }
317
353
  call->stream_op_payload.context = call->context;
318
354
  grpc_slice path = grpc_empty_slice();
319
355
  if (call->is_client) {
@@ -342,24 +378,24 @@ grpc_error *grpc_call_create(grpc_exec_ctx *exec_ctx,
342
378
 
343
379
  bool immediately_cancel = false;
344
380
 
345
- if (args->parent_call != NULL) {
346
- child_call *cc = call->child_call =
347
- gpr_arena_alloc(arena, sizeof(child_call));
348
- call->child_call->parent = args->parent_call;
381
+ if (args->parent != NULL) {
382
+ child_call *cc = call->child =
383
+ (child_call *)gpr_arena_alloc(arena, sizeof(child_call));
384
+ call->child->parent = args->parent;
349
385
 
350
- GRPC_CALL_INTERNAL_REF(args->parent_call, "child");
386
+ GRPC_CALL_INTERNAL_REF(args->parent, "child");
351
387
  GPR_ASSERT(call->is_client);
352
- GPR_ASSERT(!args->parent_call->is_client);
388
+ GPR_ASSERT(!args->parent->is_client);
353
389
 
354
- parent_call *pc = get_or_create_parent_call(args->parent_call);
390
+ parent_call *pc = get_or_create_parent_call(args->parent);
355
391
 
356
392
  gpr_mu_lock(&pc->child_list_mu);
357
393
 
358
394
  if (args->propagation_mask & GRPC_PROPAGATE_DEADLINE) {
359
395
  send_deadline = gpr_time_min(
360
396
  gpr_convert_clock_type(send_deadline,
361
- args->parent_call->send_deadline.clock_type),
362
- args->parent_call->send_deadline);
397
+ args->parent->send_deadline.clock_type),
398
+ args->parent->send_deadline);
363
399
  }
364
400
  /* for now GRPC_PROPAGATE_TRACING_CONTEXT *MUST* be passed with
365
401
  * GRPC_PROPAGATE_STATS_CONTEXT */
@@ -371,9 +407,9 @@ grpc_error *grpc_call_create(grpc_exec_ctx *exec_ctx,
371
407
  "Census tracing propagation requested "
372
408
  "without Census context propagation"));
373
409
  }
374
- grpc_call_context_set(
375
- call, GRPC_CONTEXT_TRACING,
376
- args->parent_call->context[GRPC_CONTEXT_TRACING].value, NULL);
410
+ grpc_call_context_set(call, GRPC_CONTEXT_TRACING,
411
+ args->parent->context[GRPC_CONTEXT_TRACING].value,
412
+ NULL);
377
413
  } else if (args->propagation_mask & GRPC_PROPAGATE_CENSUS_STATS_CONTEXT) {
378
414
  add_init_error(&error, GRPC_ERROR_CREATE_FROM_STATIC_STRING(
379
415
  "Census context propagation requested "
@@ -381,7 +417,7 @@ grpc_error *grpc_call_create(grpc_exec_ctx *exec_ctx,
381
417
  }
382
418
  if (args->propagation_mask & GRPC_PROPAGATE_CANCELLATION) {
383
419
  call->cancellation_is_inherited = 1;
384
- if (gpr_atm_acq_load(&args->parent_call->received_final_op_atm)) {
420
+ if (gpr_atm_acq_load(&args->parent->received_final_op_atm)) {
385
421
  immediately_cancel = true;
386
422
  }
387
423
  }
@@ -391,9 +427,9 @@ grpc_error *grpc_call_create(grpc_exec_ctx *exec_ctx,
391
427
  cc->sibling_next = cc->sibling_prev = call;
392
428
  } else {
393
429
  cc->sibling_next = pc->first_child;
394
- cc->sibling_prev = pc->first_child->child_call->sibling_prev;
395
- cc->sibling_next->child_call->sibling_prev =
396
- cc->sibling_prev->child_call->sibling_next = call;
430
+ cc->sibling_prev = pc->first_child->child->sibling_prev;
431
+ cc->sibling_next->child->sibling_prev =
432
+ cc->sibling_prev->child->sibling_next = call;
397
433
  }
398
434
 
399
435
  gpr_mu_unlock(&pc->child_list_mu);
@@ -410,7 +446,8 @@ grpc_error *grpc_call_create(grpc_exec_ctx *exec_ctx,
410
446
  .path = path,
411
447
  .start_time = call->start_time,
412
448
  .deadline = send_deadline,
413
- .arena = call->arena};
449
+ .arena = call->arena,
450
+ .call_combiner = &call->call_combiner};
414
451
  add_init_error(&error, grpc_call_stack_init(exec_ctx, channel_stack, 1,
415
452
  destroy_call, call, &call_args));
416
453
  if (error != GRPC_ERROR_NONE) {
@@ -475,8 +512,10 @@ void grpc_call_internal_unref(grpc_exec_ctx *exec_ctx, grpc_call *c REF_ARG) {
475
512
 
476
513
  static void release_call(grpc_exec_ctx *exec_ctx, void *call,
477
514
  grpc_error *error) {
478
- grpc_call *c = call;
515
+ grpc_call *c = (grpc_call *)call;
479
516
  grpc_channel *channel = c->channel;
517
+ grpc_call_combiner_destroy(&c->call_combiner);
518
+ gpr_free((char *)c->peer_string);
480
519
  grpc_channel_update_call_size_estimate(channel, gpr_arena_destroy(c->arena));
481
520
  GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, channel, "call");
482
521
  }
@@ -486,7 +525,7 @@ static void destroy_call(grpc_exec_ctx *exec_ctx, void *call,
486
525
  grpc_error *error) {
487
526
  size_t i;
488
527
  int ii;
489
- grpc_call *c = call;
528
+ grpc_call *c = (grpc_call *)call;
490
529
  GPR_TIMER_BEGIN("destroy_call", 0);
491
530
  for (i = 0; i < 2; i++) {
492
531
  grpc_metadata_batch_destroy(
@@ -511,7 +550,7 @@ static void destroy_call(grpc_exec_ctx *exec_ctx, void *call,
511
550
  GRPC_CQ_INTERNAL_UNREF(exec_ctx, c->cq, "bind");
512
551
  }
513
552
 
514
- get_final_status(call, set_status_value_directly, &c->final_info.final_status,
553
+ get_final_status(c, set_status_value_directly, &c->final_info.final_status,
515
554
  NULL);
516
555
  c->final_info.stats.latency =
517
556
  gpr_time_sub(gpr_now(GPR_CLOCK_MONOTONIC), c->start_time);
@@ -532,7 +571,7 @@ void grpc_call_ref(grpc_call *c) { gpr_ref(&c->ext_ref); }
532
571
  void grpc_call_unref(grpc_call *c) {
533
572
  if (!gpr_unref(&c->ext_ref)) return;
534
573
 
535
- child_call *cc = c->child_call;
574
+ child_call *cc = c->child;
536
575
  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
537
576
 
538
577
  GPR_TIMER_BEGIN("grpc_call_unref", 0);
@@ -547,8 +586,8 @@ void grpc_call_unref(grpc_call *c) {
547
586
  pc->first_child = NULL;
548
587
  }
549
588
  }
550
- cc->sibling_prev->child_call->sibling_next = cc->sibling_next;
551
- cc->sibling_next->child_call->sibling_prev = cc->sibling_prev;
589
+ cc->sibling_prev->child->sibling_next = cc->sibling_next;
590
+ cc->sibling_next->child->sibling_prev = cc->sibling_prev;
552
591
  gpr_mu_unlock(&pc->child_list_mu);
553
592
  GRPC_CALL_INTERNAL_UNREF(&exec_ctx, cc->parent, "child");
554
593
  }
@@ -560,6 +599,12 @@ void grpc_call_unref(grpc_call *c) {
560
599
  if (cancel) {
561
600
  cancel_with_error(&exec_ctx, c, STATUS_FROM_API_OVERRIDE,
562
601
  GRPC_ERROR_CANCELLED);
602
+ } else {
603
+ // Unset the call combiner cancellation closure. This has the
604
+ // effect of scheduling the previously set cancellation closure, if
605
+ // any, so that it can release any internal references it may be
606
+ // holding to the call stack.
607
+ grpc_call_combiner_set_notify_on_cancel(&exec_ctx, &c->call_combiner, NULL);
563
608
  }
564
609
  GRPC_CALL_INTERNAL_UNREF(&exec_ctx, c, "destroy");
565
610
  grpc_exec_ctx_finish(&exec_ctx);
@@ -576,30 +621,37 @@ grpc_call_error grpc_call_cancel(grpc_call *call, void *reserved) {
576
621
  return GRPC_CALL_OK;
577
622
  }
578
623
 
579
- static void execute_op(grpc_exec_ctx *exec_ctx, grpc_call *call,
580
- grpc_transport_stream_op_batch *op) {
581
- grpc_call_element *elem;
582
-
583
- GPR_TIMER_BEGIN("execute_op", 0);
584
- elem = CALL_ELEM_FROM_CALL(call, 0);
585
- elem->filter->start_transport_stream_op_batch(exec_ctx, elem, op);
586
- GPR_TIMER_END("execute_op", 0);
624
+ // This is called via the call combiner to start sending a batch down
625
+ // the filter stack.
626
+ static void execute_batch_in_call_combiner(grpc_exec_ctx *exec_ctx, void *arg,
627
+ grpc_error *ignored) {
628
+ grpc_transport_stream_op_batch *batch = (grpc_transport_stream_op_batch *)arg;
629
+ grpc_call *call = (grpc_call *)batch->handler_private.extra_arg;
630
+ GPR_TIMER_BEGIN("execute_batch", 0);
631
+ grpc_call_element *elem = CALL_ELEM_FROM_CALL(call, 0);
632
+ GRPC_CALL_LOG_OP(GPR_INFO, elem, batch);
633
+ elem->filter->start_transport_stream_op_batch(exec_ctx, elem, batch);
634
+ GPR_TIMER_END("execute_batch", 0);
635
+ }
636
+
637
+ // start_batch_closure points to a caller-allocated closure to be used
638
+ // for entering the call combiner.
639
+ static void execute_batch(grpc_exec_ctx *exec_ctx, grpc_call *call,
640
+ grpc_transport_stream_op_batch *batch,
641
+ grpc_closure *start_batch_closure) {
642
+ batch->handler_private.extra_arg = call;
643
+ GRPC_CLOSURE_INIT(start_batch_closure, execute_batch_in_call_combiner, batch,
644
+ grpc_schedule_on_exec_ctx);
645
+ GRPC_CALL_COMBINER_START(exec_ctx, &call->call_combiner, start_batch_closure,
646
+ GRPC_ERROR_NONE, "executing batch");
587
647
  }
588
648
 
589
649
  char *grpc_call_get_peer(grpc_call *call) {
590
- grpc_call_element *elem = CALL_ELEM_FROM_CALL(call, 0);
591
- grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
592
- char *result;
593
- GRPC_API_TRACE("grpc_call_get_peer(%p)", 1, (call));
594
- result = elem->filter->get_peer(&exec_ctx, elem);
595
- if (result == NULL) {
596
- result = grpc_channel_get_target(call->channel);
597
- }
598
- if (result == NULL) {
599
- result = gpr_strdup("unknown");
600
- }
601
- grpc_exec_ctx_finish(&exec_ctx);
602
- return result;
650
+ char *peer_string = (char *)gpr_atm_acq_load(&call->peer_string);
651
+ if (peer_string != NULL) return gpr_strdup(peer_string);
652
+ peer_string = grpc_channel_get_target(call->channel);
653
+ if (peer_string != NULL) return peer_string;
654
+ return gpr_strdup("unknown");
603
655
  }
604
656
 
605
657
  grpc_call *grpc_call_from_top_element(grpc_call_element *elem) {
@@ -626,20 +678,41 @@ grpc_call_error grpc_call_cancel_with_status(grpc_call *c,
626
678
  return GRPC_CALL_OK;
627
679
  }
628
680
 
629
- static void done_termination(grpc_exec_ctx *exec_ctx, void *call,
681
+ typedef struct {
682
+ grpc_call *call;
683
+ grpc_closure start_batch;
684
+ grpc_closure finish_batch;
685
+ } cancel_state;
686
+
687
+ // The on_complete callback used when sending a cancel_stream batch down
688
+ // the filter stack. Yields the call combiner when the batch is done.
689
+ static void done_termination(grpc_exec_ctx *exec_ctx, void *arg,
630
690
  grpc_error *error) {
631
- GRPC_CALL_INTERNAL_UNREF(exec_ctx, call, "termination");
691
+ cancel_state *state = (cancel_state *)arg;
692
+ GRPC_CALL_COMBINER_STOP(exec_ctx, &state->call->call_combiner,
693
+ "on_complete for cancel_stream op");
694
+ GRPC_CALL_INTERNAL_UNREF(exec_ctx, state->call, "termination");
695
+ gpr_free(state);
632
696
  }
633
697
 
634
698
  static void cancel_with_error(grpc_exec_ctx *exec_ctx, grpc_call *c,
635
699
  status_source source, grpc_error *error) {
636
700
  GRPC_CALL_INTERNAL_REF(c, "termination");
701
+ // Inform the call combiner of the cancellation, so that it can cancel
702
+ // any in-flight asynchronous actions that may be holding the call
703
+ // combiner. This ensures that the cancel_stream batch can be sent
704
+ // down the filter stack in a timely manner.
705
+ grpc_call_combiner_cancel(exec_ctx, &c->call_combiner, GRPC_ERROR_REF(error));
637
706
  set_status_from_error(exec_ctx, c, source, GRPC_ERROR_REF(error));
638
- grpc_transport_stream_op_batch *op = grpc_make_transport_stream_op(
639
- GRPC_CLOSURE_CREATE(done_termination, c, grpc_schedule_on_exec_ctx));
707
+ cancel_state *state = (cancel_state *)gpr_malloc(sizeof(*state));
708
+ state->call = c;
709
+ GRPC_CLOSURE_INIT(&state->finish_batch, done_termination, state,
710
+ grpc_schedule_on_exec_ctx);
711
+ grpc_transport_stream_op_batch *op =
712
+ grpc_make_transport_stream_op(&state->finish_batch);
640
713
  op->cancel_stream = true;
641
714
  op->payload->cancel_stream.cancel_error = error;
642
- execute_op(exec_ctx, c, op);
715
+ execute_batch(exec_ctx, c, op, &state->start_batch);
643
716
  }
644
717
 
645
718
  static grpc_error *error_from_status(grpc_status_code status,
@@ -752,6 +825,12 @@ static void set_incoming_compression_algorithm(
752
825
  call->incoming_compression_algorithm = algo;
753
826
  }
754
827
 
828
+ static void set_incoming_stream_compression_algorithm(
829
+ grpc_call *call, grpc_stream_compression_algorithm algo) {
830
+ GPR_ASSERT(algo < GRPC_STREAM_COMPRESS_ALGORITHMS_COUNT);
831
+ call->incoming_stream_compression_algorithm = algo;
832
+ }
833
+
755
834
  grpc_compression_algorithm grpc_call_test_only_get_compression_algorithm(
756
835
  grpc_call *call) {
757
836
  grpc_compression_algorithm algorithm;
@@ -765,6 +844,13 @@ static grpc_compression_algorithm compression_algorithm_for_level_locked(
765
844
  call->encodings_accepted_by_peer);
766
845
  }
767
846
 
847
+ static grpc_stream_compression_algorithm
848
+ stream_compression_algorithm_for_level_locked(
849
+ grpc_call *call, grpc_stream_compression_level level) {
850
+ return grpc_stream_compression_algorithm_for_level(
851
+ level, call->stream_encodings_accepted_by_peer);
852
+ }
853
+
768
854
  uint32_t grpc_call_test_only_get_message_flags(grpc_call *call) {
769
855
  uint32_t flags;
770
856
  flags = call->test_only_last_message_flags;
@@ -819,12 +905,70 @@ static void set_encodings_accepted_by_peer(grpc_exec_ctx *exec_ctx,
819
905
  (void *)(((uintptr_t)call->encodings_accepted_by_peer) + 1));
820
906
  }
821
907
 
908
+ static void set_stream_encodings_accepted_by_peer(grpc_exec_ctx *exec_ctx,
909
+ grpc_call *call,
910
+ grpc_mdelem mdel) {
911
+ size_t i;
912
+ grpc_stream_compression_algorithm algorithm;
913
+ grpc_slice_buffer accept_encoding_parts;
914
+ grpc_slice accept_encoding_slice;
915
+ void *accepted_user_data;
916
+
917
+ accepted_user_data =
918
+ grpc_mdelem_get_user_data(mdel, destroy_encodings_accepted_by_peer);
919
+ if (accepted_user_data != NULL) {
920
+ call->stream_encodings_accepted_by_peer =
921
+ (uint32_t)(((uintptr_t)accepted_user_data) - 1);
922
+ return;
923
+ }
924
+
925
+ accept_encoding_slice = GRPC_MDVALUE(mdel);
926
+ grpc_slice_buffer_init(&accept_encoding_parts);
927
+ grpc_slice_split(accept_encoding_slice, ",", &accept_encoding_parts);
928
+
929
+ /* Always support no compression */
930
+ GPR_BITSET(&call->stream_encodings_accepted_by_peer,
931
+ GRPC_STREAM_COMPRESS_NONE);
932
+ for (i = 0; i < accept_encoding_parts.count; i++) {
933
+ grpc_slice accept_encoding_entry_slice = accept_encoding_parts.slices[i];
934
+ if (grpc_stream_compression_algorithm_parse(accept_encoding_entry_slice,
935
+ &algorithm)) {
936
+ GPR_BITSET(&call->stream_encodings_accepted_by_peer, algorithm);
937
+ } else {
938
+ char *accept_encoding_entry_str =
939
+ grpc_slice_to_c_string(accept_encoding_entry_slice);
940
+ gpr_log(GPR_ERROR,
941
+ "Invalid entry in accept encoding metadata: '%s'. Ignoring.",
942
+ accept_encoding_entry_str);
943
+ gpr_free(accept_encoding_entry_str);
944
+ }
945
+ }
946
+
947
+ grpc_slice_buffer_destroy_internal(exec_ctx, &accept_encoding_parts);
948
+
949
+ grpc_mdelem_set_user_data(
950
+ mdel, destroy_encodings_accepted_by_peer,
951
+ (void *)(((uintptr_t)call->stream_encodings_accepted_by_peer) + 1));
952
+ }
953
+
822
954
  uint32_t grpc_call_test_only_get_encodings_accepted_by_peer(grpc_call *call) {
823
955
  uint32_t encodings_accepted_by_peer;
824
956
  encodings_accepted_by_peer = call->encodings_accepted_by_peer;
825
957
  return encodings_accepted_by_peer;
826
958
  }
827
959
 
960
+ uint32_t grpc_call_test_only_get_stream_encodings_accepted_by_peer(
961
+ grpc_call *call) {
962
+ uint32_t stream_encodings_accepted_by_peer;
963
+ stream_encodings_accepted_by_peer = call->stream_encodings_accepted_by_peer;
964
+ return stream_encodings_accepted_by_peer;
965
+ }
966
+
967
+ grpc_stream_compression_algorithm
968
+ grpc_call_test_only_get_incoming_stream_encodings(grpc_call *call) {
969
+ return call->incoming_stream_compression_algorithm;
970
+ }
971
+
828
972
  static grpc_linked_mdelem *linked_from_md(const grpc_metadata *md) {
829
973
  return (grpc_linked_mdelem *)&md->internal_data;
830
974
  }
@@ -936,6 +1080,22 @@ static grpc_compression_algorithm decode_compression(grpc_mdelem md) {
936
1080
  return algorithm;
937
1081
  }
938
1082
 
1083
+ static grpc_stream_compression_algorithm decode_stream_compression(
1084
+ grpc_mdelem md) {
1085
+ grpc_stream_compression_algorithm algorithm =
1086
+ grpc_stream_compression_algorithm_from_slice(GRPC_MDVALUE(md));
1087
+ if (algorithm == GRPC_STREAM_COMPRESS_ALGORITHMS_COUNT) {
1088
+ char *md_c_str = grpc_slice_to_c_string(GRPC_MDVALUE(md));
1089
+ gpr_log(GPR_ERROR,
1090
+ "Invalid incoming stream compression algorithm: '%s'. Interpreting "
1091
+ "incoming data as uncompressed.",
1092
+ md_c_str);
1093
+ gpr_free(md_c_str);
1094
+ return GRPC_STREAM_COMPRESS_NONE;
1095
+ }
1096
+ return algorithm;
1097
+ }
1098
+
939
1099
  static void publish_app_metadata(grpc_call *call, grpc_metadata_batch *b,
940
1100
  int is_trailing) {
941
1101
  if (b->list.count == 0) return;
@@ -946,8 +1106,8 @@ static void publish_app_metadata(grpc_call *call, grpc_metadata_batch *b,
946
1106
  if (dest->count + b->list.count > dest->capacity) {
947
1107
  dest->capacity =
948
1108
  GPR_MAX(dest->capacity + b->list.count, dest->capacity * 3 / 2);
949
- dest->metadata =
950
- gpr_realloc(dest->metadata, sizeof(grpc_metadata) * dest->capacity);
1109
+ dest->metadata = (grpc_metadata *)gpr_realloc(
1110
+ dest->metadata, sizeof(grpc_metadata) * dest->capacity);
951
1111
  }
952
1112
  for (grpc_linked_mdelem *l = b->list.head; l != NULL; l = l->next) {
953
1113
  mdusr = &dest->metadata[dest->count++];
@@ -960,7 +1120,19 @@ static void publish_app_metadata(grpc_call *call, grpc_metadata_batch *b,
960
1120
 
961
1121
  static void recv_initial_filter(grpc_exec_ctx *exec_ctx, grpc_call *call,
962
1122
  grpc_metadata_batch *b) {
963
- if (b->idx.named.grpc_encoding != NULL) {
1123
+ if (b->idx.named.content_encoding != NULL) {
1124
+ if (b->idx.named.grpc_encoding != NULL) {
1125
+ gpr_log(GPR_ERROR,
1126
+ "Received both content-encoding and grpc-encoding header. "
1127
+ "Ignoring grpc-encoding.");
1128
+ grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.grpc_encoding);
1129
+ }
1130
+ GPR_TIMER_BEGIN("incoming_stream_compression_algorithm", 0);
1131
+ set_incoming_stream_compression_algorithm(
1132
+ call, decode_stream_compression(b->idx.named.content_encoding->md));
1133
+ GPR_TIMER_END("incoming_stream_compression_algorithm", 0);
1134
+ grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.content_encoding);
1135
+ } else if (b->idx.named.grpc_encoding != NULL) {
964
1136
  GPR_TIMER_BEGIN("incoming_compression_algorithm", 0);
965
1137
  set_incoming_compression_algorithm(
966
1138
  call, decode_compression(b->idx.named.grpc_encoding->md));
@@ -974,12 +1146,19 @@ static void recv_initial_filter(grpc_exec_ctx *exec_ctx, grpc_call *call,
974
1146
  grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.grpc_accept_encoding);
975
1147
  GPR_TIMER_END("encodings_accepted_by_peer", 0);
976
1148
  }
1149
+ if (b->idx.named.accept_encoding != NULL) {
1150
+ GPR_TIMER_BEGIN("stream_encodings_accepted_by_peer", 0);
1151
+ set_stream_encodings_accepted_by_peer(exec_ctx, call,
1152
+ b->idx.named.accept_encoding->md);
1153
+ grpc_metadata_batch_remove(exec_ctx, b, b->idx.named.accept_encoding);
1154
+ GPR_TIMER_END("stream_encodings_accepted_by_peer", 0);
1155
+ }
977
1156
  publish_app_metadata(call, b, false);
978
1157
  }
979
1158
 
980
1159
  static void recv_trailing_filter(grpc_exec_ctx *exec_ctx, void *args,
981
1160
  grpc_metadata_batch *b) {
982
- grpc_call *call = args;
1161
+ grpc_call *call = (grpc_call *)args;
983
1162
  if (b->idx.named.grpc_status != NULL) {
984
1163
  uint32_t status_code = decode_status(b->idx.named.grpc_status->md);
985
1164
  grpc_error *error =
@@ -1063,7 +1242,8 @@ static batch_control *allocate_batch_control(grpc_call *call,
1063
1242
  int slot = batch_slot_for_op(ops[0].op);
1064
1243
  batch_control **pslot = &call->active_batches[slot];
1065
1244
  if (*pslot == NULL) {
1066
- *pslot = gpr_arena_alloc(call->arena, sizeof(batch_control));
1245
+ *pslot =
1246
+ (batch_control *)gpr_arena_alloc(call->arena, sizeof(batch_control));
1067
1247
  }
1068
1248
  batch_control *bctl = *pslot;
1069
1249
  if (bctl->call != NULL) {
@@ -1077,7 +1257,7 @@ static batch_control *allocate_batch_control(grpc_call *call,
1077
1257
 
1078
1258
  static void finish_batch_completion(grpc_exec_ctx *exec_ctx, void *user_data,
1079
1259
  grpc_cq_completion *storage) {
1080
- batch_control *bctl = user_data;
1260
+ batch_control *bctl = (batch_control *)user_data;
1081
1261
  grpc_call *call = bctl->call;
1082
1262
  bctl->call = NULL;
1083
1263
  GRPC_CALL_INTERNAL_UNREF(exec_ctx, call, "completion");
@@ -1137,7 +1317,7 @@ static void post_batch_completion(grpc_exec_ctx *exec_ctx,
1137
1317
  child = pc->first_child;
1138
1318
  if (child != NULL) {
1139
1319
  do {
1140
- next_child_call = child->child_call->sibling_next;
1320
+ next_child_call = child->child->sibling_next;
1141
1321
  if (child->cancellation_is_inherited) {
1142
1322
  GRPC_CALL_INTERNAL_REF(child, "propagate_cancel");
1143
1323
  cancel_with_error(exec_ctx, child, STATUS_FROM_API_OVERRIDE,
@@ -1166,7 +1346,8 @@ static void post_batch_completion(grpc_exec_ctx *exec_ctx,
1166
1346
  if (bctl->completion_data.notify_tag.is_closure) {
1167
1347
  /* unrefs bctl->error */
1168
1348
  bctl->call = NULL;
1169
- GRPC_CLOSURE_RUN(exec_ctx, bctl->completion_data.notify_tag.tag, error);
1349
+ GRPC_CLOSURE_RUN(
1350
+ exec_ctx, (grpc_closure *)bctl->completion_data.notify_tag.tag, error);
1170
1351
  GRPC_CALL_INTERNAL_UNREF(exec_ctx, call, "completion");
1171
1352
  } else {
1172
1353
  /* unrefs bctl->error */
@@ -1220,7 +1401,7 @@ static void continue_receiving_slices(grpc_exec_ctx *exec_ctx,
1220
1401
 
1221
1402
  static void receiving_slice_ready(grpc_exec_ctx *exec_ctx, void *bctlp,
1222
1403
  grpc_error *error) {
1223
- batch_control *bctl = bctlp;
1404
+ batch_control *bctl = (batch_control *)bctlp;
1224
1405
  grpc_call *call = bctl->call;
1225
1406
  grpc_byte_stream *bs = call->receiving_stream;
1226
1407
  bool release_error = false;
@@ -1279,7 +1460,7 @@ static void process_data_after_md(grpc_exec_ctx *exec_ctx,
1279
1460
 
1280
1461
  static void receiving_stream_ready(grpc_exec_ctx *exec_ctx, void *bctlp,
1281
1462
  grpc_error *error) {
1282
- batch_control *bctl = bctlp;
1463
+ batch_control *bctl = (batch_control *)bctlp;
1283
1464
  grpc_call *call = bctl->call;
1284
1465
  if (error != GRPC_ERROR_NONE) {
1285
1466
  if (call->receiving_stream != NULL) {
@@ -1290,19 +1471,73 @@ static void receiving_stream_ready(grpc_exec_ctx *exec_ctx, void *bctlp,
1290
1471
  cancel_with_error(exec_ctx, call, STATUS_FROM_SURFACE,
1291
1472
  GRPC_ERROR_REF(error));
1292
1473
  }
1293
- if (call->has_initial_md_been_received || error != GRPC_ERROR_NONE ||
1294
- call->receiving_stream == NULL) {
1295
- process_data_after_md(exec_ctx, bctlp);
1296
- } else {
1297
- call->saved_receiving_stream_ready_bctlp = bctlp;
1474
+ /* If recv_state is RECV_NONE, we will save the batch_control
1475
+ * object with rel_cas, and will not use it after the cas. Its corresponding
1476
+ * acq_load is in receiving_initial_metadata_ready() */
1477
+ if (error != GRPC_ERROR_NONE || call->receiving_stream == NULL ||
1478
+ !gpr_atm_rel_cas(&call->recv_state, RECV_NONE, (gpr_atm)bctlp)) {
1479
+ process_data_after_md(exec_ctx, bctl);
1298
1480
  }
1299
1481
  }
1300
1482
 
1483
+ // The recv_message_ready callback used when sending a batch containing
1484
+ // a recv_message op down the filter stack. Yields the call combiner
1485
+ // before processing the received message.
1486
+ static void receiving_stream_ready_in_call_combiner(grpc_exec_ctx *exec_ctx,
1487
+ void *bctlp,
1488
+ grpc_error *error) {
1489
+ batch_control *bctl = (batch_control *)bctlp;
1490
+ grpc_call *call = bctl->call;
1491
+ GRPC_CALL_COMBINER_STOP(exec_ctx, &call->call_combiner, "recv_message_ready");
1492
+ receiving_stream_ready(exec_ctx, bctlp, error);
1493
+ }
1494
+
1301
1495
  static void validate_filtered_metadata(grpc_exec_ctx *exec_ctx,
1302
1496
  batch_control *bctl) {
1303
1497
  grpc_call *call = bctl->call;
1304
- /* validate call->incoming_compression_algorithm */
1305
- if (call->incoming_compression_algorithm != GRPC_COMPRESS_NONE) {
1498
+ /* validate compression algorithms */
1499
+ if (call->incoming_stream_compression_algorithm !=
1500
+ GRPC_STREAM_COMPRESS_NONE) {
1501
+ const grpc_stream_compression_algorithm algo =
1502
+ call->incoming_stream_compression_algorithm;
1503
+ char *error_msg = NULL;
1504
+ const grpc_compression_options compression_options =
1505
+ grpc_channel_compression_options(call->channel);
1506
+ if (algo >= GRPC_STREAM_COMPRESS_ALGORITHMS_COUNT) {
1507
+ gpr_asprintf(&error_msg,
1508
+ "Invalid stream compression algorithm value '%d'.", algo);
1509
+ gpr_log(GPR_ERROR, "%s", error_msg);
1510
+ cancel_with_status(exec_ctx, call, STATUS_FROM_SURFACE,
1511
+ GRPC_STATUS_UNIMPLEMENTED, error_msg);
1512
+ } else if (grpc_compression_options_is_stream_compression_algorithm_enabled(
1513
+ &compression_options, algo) == 0) {
1514
+ /* check if algorithm is supported by current channel config */
1515
+ const char *algo_name = NULL;
1516
+ grpc_stream_compression_algorithm_name(algo, &algo_name);
1517
+ gpr_asprintf(&error_msg, "Stream compression algorithm '%s' is disabled.",
1518
+ algo_name);
1519
+ gpr_log(GPR_ERROR, "%s", error_msg);
1520
+ cancel_with_status(exec_ctx, call, STATUS_FROM_SURFACE,
1521
+ GRPC_STATUS_UNIMPLEMENTED, error_msg);
1522
+ }
1523
+ gpr_free(error_msg);
1524
+
1525
+ GPR_ASSERT(call->stream_encodings_accepted_by_peer != 0);
1526
+ if (!GPR_BITGET(call->stream_encodings_accepted_by_peer,
1527
+ call->incoming_stream_compression_algorithm)) {
1528
+ if (GRPC_TRACER_ON(grpc_compression_trace)) {
1529
+ const char *algo_name = NULL;
1530
+ grpc_stream_compression_algorithm_name(
1531
+ call->incoming_stream_compression_algorithm, &algo_name);
1532
+ gpr_log(
1533
+ GPR_ERROR,
1534
+ "Stream compression algorithm (content-encoding = '%s') not "
1535
+ "present in the bitset of accepted encodings (accept-encodings: "
1536
+ "'0x%x')",
1537
+ algo_name, call->stream_encodings_accepted_by_peer);
1538
+ }
1539
+ }
1540
+ } else if (call->incoming_compression_algorithm != GRPC_COMPRESS_NONE) {
1306
1541
  const grpc_compression_algorithm algo =
1307
1542
  call->incoming_compression_algorithm;
1308
1543
  char *error_msg = NULL;
@@ -1318,7 +1553,7 @@ static void validate_filtered_metadata(grpc_exec_ctx *exec_ctx,
1318
1553
  } else if (grpc_compression_options_is_algorithm_enabled(
1319
1554
  &compression_options, algo) == 0) {
1320
1555
  /* check if algorithm is supported by current channel config */
1321
- char *algo_name = NULL;
1556
+ const char *algo_name = NULL;
1322
1557
  grpc_compression_algorithm_name(algo, &algo_name);
1323
1558
  gpr_asprintf(&error_msg, "Compression algorithm '%s' is disabled.",
1324
1559
  algo_name);
@@ -1329,22 +1564,20 @@ static void validate_filtered_metadata(grpc_exec_ctx *exec_ctx,
1329
1564
  call->incoming_compression_algorithm = algo;
1330
1565
  }
1331
1566
  gpr_free(error_msg);
1332
- }
1333
1567
 
1334
- /* make sure the received grpc-encoding is amongst the ones listed in
1335
- * grpc-accept-encoding */
1336
- GPR_ASSERT(call->encodings_accepted_by_peer != 0);
1337
- if (!GPR_BITGET(call->encodings_accepted_by_peer,
1338
- call->incoming_compression_algorithm)) {
1339
- if (GRPC_TRACER_ON(grpc_compression_trace)) {
1340
- char *algo_name = NULL;
1341
- grpc_compression_algorithm_name(call->incoming_compression_algorithm,
1342
- &algo_name);
1343
- gpr_log(GPR_ERROR,
1344
- "Compression algorithm (grpc-encoding = '%s') not present in "
1345
- "the bitset of accepted encodings (grpc-accept-encodings: "
1346
- "'0x%x')",
1347
- algo_name, call->encodings_accepted_by_peer);
1568
+ GPR_ASSERT(call->encodings_accepted_by_peer != 0);
1569
+ if (!GPR_BITGET(call->encodings_accepted_by_peer,
1570
+ call->incoming_compression_algorithm)) {
1571
+ if (GRPC_TRACER_ON(grpc_compression_trace)) {
1572
+ const char *algo_name = NULL;
1573
+ grpc_compression_algorithm_name(call->incoming_compression_algorithm,
1574
+ &algo_name);
1575
+ gpr_log(GPR_ERROR,
1576
+ "Compression algorithm (grpc-encoding = '%s') not present in "
1577
+ "the bitset of accepted encodings (grpc-accept-encodings: "
1578
+ "'0x%x')",
1579
+ algo_name, call->encodings_accepted_by_peer);
1580
+ }
1348
1581
  }
1349
1582
  }
1350
1583
  }
@@ -1362,9 +1595,12 @@ static void add_batch_error(grpc_exec_ctx *exec_ctx, batch_control *bctl,
1362
1595
 
1363
1596
  static void receiving_initial_metadata_ready(grpc_exec_ctx *exec_ctx,
1364
1597
  void *bctlp, grpc_error *error) {
1365
- batch_control *bctl = bctlp;
1598
+ batch_control *bctl = (batch_control *)bctlp;
1366
1599
  grpc_call *call = bctl->call;
1367
1600
 
1601
+ GRPC_CALL_COMBINER_STOP(exec_ctx, &call->call_combiner,
1602
+ "recv_initial_metadata_ready");
1603
+
1368
1604
  add_batch_error(exec_ctx, bctl, GRPC_ERROR_REF(error), false);
1369
1605
  if (error == GRPC_ERROR_NONE) {
1370
1606
  grpc_metadata_batch *md =
@@ -1384,12 +1620,31 @@ static void receiving_initial_metadata_ready(grpc_exec_ctx *exec_ctx,
1384
1620
  }
1385
1621
  }
1386
1622
 
1387
- call->has_initial_md_been_received = true;
1388
- if (call->saved_receiving_stream_ready_bctlp != NULL) {
1389
- grpc_closure *saved_rsr_closure = GRPC_CLOSURE_CREATE(
1390
- receiving_stream_ready, call->saved_receiving_stream_ready_bctlp,
1391
- grpc_schedule_on_exec_ctx);
1392
- call->saved_receiving_stream_ready_bctlp = NULL;
1623
+ grpc_closure *saved_rsr_closure = NULL;
1624
+ while (true) {
1625
+ gpr_atm rsr_bctlp = gpr_atm_acq_load(&call->recv_state);
1626
+ /* Should only receive initial metadata once */
1627
+ GPR_ASSERT(rsr_bctlp != 1);
1628
+ if (rsr_bctlp == 0) {
1629
+ /* We haven't seen initial metadata and messages before, thus initial
1630
+ * metadata is received first.
1631
+ * no_barrier_cas is used, as this function won't access the batch_control
1632
+ * object saved by receiving_stream_ready() if the initial metadata is
1633
+ * received first. */
1634
+ if (gpr_atm_no_barrier_cas(&call->recv_state, RECV_NONE,
1635
+ RECV_INITIAL_METADATA_FIRST)) {
1636
+ break;
1637
+ }
1638
+ } else {
1639
+ /* Already received messages */
1640
+ saved_rsr_closure = GRPC_CLOSURE_CREATE(receiving_stream_ready,
1641
+ (batch_control *)rsr_bctlp,
1642
+ grpc_schedule_on_exec_ctx);
1643
+ /* No need to modify recv_state */
1644
+ break;
1645
+ }
1646
+ }
1647
+ if (saved_rsr_closure != NULL) {
1393
1648
  GRPC_CLOSURE_RUN(exec_ctx, saved_rsr_closure, GRPC_ERROR_REF(error));
1394
1649
  }
1395
1650
 
@@ -1398,8 +1653,9 @@ static void receiving_initial_metadata_ready(grpc_exec_ctx *exec_ctx,
1398
1653
 
1399
1654
  static void finish_batch(grpc_exec_ctx *exec_ctx, void *bctlp,
1400
1655
  grpc_error *error) {
1401
- batch_control *bctl = bctlp;
1402
-
1656
+ batch_control *bctl = (batch_control *)bctlp;
1657
+ grpc_call *call = bctl->call;
1658
+ GRPC_CALL_COMBINER_STOP(exec_ctx, &call->call_combiner, "on_complete");
1403
1659
  add_batch_error(exec_ctx, bctl, GRPC_ERROR_REF(error), false);
1404
1660
  finish_batch_step(exec_ctx, bctl);
1405
1661
  }
@@ -1418,9 +1674,8 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx,
1418
1674
  batch_control *bctl;
1419
1675
  int num_completion_callbacks_needed = 1;
1420
1676
  grpc_call_error error = GRPC_CALL_OK;
1421
-
1422
- // sent_initial_metadata guards against variable reuse.
1423
- grpc_metadata compression_md;
1677
+ grpc_transport_stream_op_batch *stream_op;
1678
+ grpc_transport_stream_op_batch_payload *stream_op_payload;
1424
1679
 
1425
1680
  GPR_TIMER_BEGIN("grpc_call_start_batch", 0);
1426
1681
  GRPC_CALL_LOG_BATCH(GPR_INFO, call, ops, nops, notify_tag);
@@ -1428,11 +1683,12 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx,
1428
1683
  if (nops == 0) {
1429
1684
  if (!is_notify_tag_closure) {
1430
1685
  GPR_ASSERT(grpc_cq_begin_op(call->cq, notify_tag));
1431
- grpc_cq_end_op(exec_ctx, call->cq, notify_tag, GRPC_ERROR_NONE,
1432
- free_no_op_completion, NULL,
1433
- gpr_malloc(sizeof(grpc_cq_completion)));
1686
+ grpc_cq_end_op(
1687
+ exec_ctx, call->cq, notify_tag, GRPC_ERROR_NONE,
1688
+ free_no_op_completion, NULL,
1689
+ (grpc_cq_completion *)gpr_malloc(sizeof(grpc_cq_completion)));
1434
1690
  } else {
1435
- GRPC_CLOSURE_SCHED(exec_ctx, notify_tag, GRPC_ERROR_NONE);
1691
+ GRPC_CLOSURE_SCHED(exec_ctx, (grpc_closure *)notify_tag, GRPC_ERROR_NONE);
1436
1692
  }
1437
1693
  error = GRPC_CALL_OK;
1438
1694
  goto done;
@@ -1446,9 +1702,8 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx,
1446
1702
  bctl->completion_data.notify_tag.is_closure =
1447
1703
  (uint8_t)(is_notify_tag_closure != 0);
1448
1704
 
1449
- grpc_transport_stream_op_batch *stream_op = &bctl->op;
1450
- grpc_transport_stream_op_batch_payload *stream_op_payload =
1451
- &call->stream_op_payload;
1705
+ stream_op = &bctl->op;
1706
+ stream_op_payload = &call->stream_op_payload;
1452
1707
 
1453
1708
  /* rewrite batch ops into a transport op */
1454
1709
  for (i = 0; i < nops; i++) {
@@ -1458,7 +1713,7 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx,
1458
1713
  goto done_with_error;
1459
1714
  }
1460
1715
  switch (op->op) {
1461
- case GRPC_OP_SEND_INITIAL_METADATA:
1716
+ case GRPC_OP_SEND_INITIAL_METADATA: {
1462
1717
  /* Flag validation: currently allow no flags */
1463
1718
  if (!are_initial_metadata_flags_valid(op->flags, call->is_client)) {
1464
1719
  error = GRPC_CALL_ERROR_INVALID_FLAGS;
@@ -1469,31 +1724,60 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx,
1469
1724
  goto done_with_error;
1470
1725
  }
1471
1726
  /* process compression level */
1472
- memset(&compression_md, 0, sizeof(compression_md));
1727
+ memset(&call->compression_md, 0, sizeof(call->compression_md));
1473
1728
  size_t additional_metadata_count = 0;
1474
- grpc_compression_level effective_compression_level;
1729
+ grpc_compression_level effective_compression_level =
1730
+ GRPC_COMPRESS_LEVEL_NONE;
1731
+ grpc_stream_compression_level effective_stream_compression_level =
1732
+ GRPC_STREAM_COMPRESS_LEVEL_NONE;
1475
1733
  bool level_set = false;
1476
- if (op->data.send_initial_metadata.maybe_compression_level.is_set) {
1734
+ bool stream_compression = false;
1735
+ if (op->data.send_initial_metadata.maybe_stream_compression_level
1736
+ .is_set) {
1737
+ effective_stream_compression_level =
1738
+ op->data.send_initial_metadata.maybe_stream_compression_level
1739
+ .level;
1740
+ level_set = true;
1741
+ stream_compression = true;
1742
+ } else if (op->data.send_initial_metadata.maybe_compression_level
1743
+ .is_set) {
1477
1744
  effective_compression_level =
1478
1745
  op->data.send_initial_metadata.maybe_compression_level.level;
1479
1746
  level_set = true;
1480
1747
  } else {
1481
1748
  const grpc_compression_options copts =
1482
1749
  grpc_channel_compression_options(call->channel);
1483
- level_set = copts.default_level.is_set;
1484
- if (level_set) {
1750
+ if (copts.default_stream_compression_level.is_set) {
1751
+ level_set = true;
1752
+ effective_stream_compression_level =
1753
+ copts.default_stream_compression_level.level;
1754
+ stream_compression = true;
1755
+ } else if (copts.default_level.is_set) {
1756
+ level_set = true;
1485
1757
  effective_compression_level = copts.default_level.level;
1486
1758
  }
1487
1759
  }
1488
1760
  if (level_set && !call->is_client) {
1489
- const grpc_compression_algorithm calgo =
1490
- compression_algorithm_for_level_locked(
1491
- call, effective_compression_level);
1492
- // the following will be picked up by the compress filter and used as
1493
- // the call's compression algorithm.
1494
- compression_md.key = GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST;
1495
- compression_md.value = grpc_compression_algorithm_slice(calgo);
1496
- additional_metadata_count++;
1761
+ if (stream_compression) {
1762
+ const grpc_stream_compression_algorithm calgo =
1763
+ stream_compression_algorithm_for_level_locked(
1764
+ call, effective_stream_compression_level);
1765
+ call->compression_md.key =
1766
+ GRPC_MDSTR_GRPC_INTERNAL_STREAM_ENCODING_REQUEST;
1767
+ call->compression_md.value =
1768
+ grpc_stream_compression_algorithm_slice(calgo);
1769
+ } else {
1770
+ const grpc_compression_algorithm calgo =
1771
+ compression_algorithm_for_level_locked(
1772
+ call, effective_compression_level);
1773
+ /* the following will be picked up by the compress filter and used
1774
+ * as the call's compression algorithm. */
1775
+ call->compression_md.key =
1776
+ GRPC_MDSTR_GRPC_INTERNAL_ENCODING_REQUEST;
1777
+ call->compression_md.value =
1778
+ grpc_compression_algorithm_slice(calgo);
1779
+ additional_metadata_count++;
1780
+ }
1497
1781
  }
1498
1782
 
1499
1783
  if (op->data.send_initial_metadata.count + additional_metadata_count >
@@ -1506,7 +1790,7 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx,
1506
1790
  if (!prepare_application_metadata(
1507
1791
  exec_ctx, call, (int)op->data.send_initial_metadata.count,
1508
1792
  op->data.send_initial_metadata.metadata, 0, call->is_client,
1509
- &compression_md, (int)additional_metadata_count)) {
1793
+ &call->compression_md, (int)additional_metadata_count)) {
1510
1794
  error = GRPC_CALL_ERROR_INVALID_METADATA;
1511
1795
  goto done_with_error;
1512
1796
  }
@@ -1518,8 +1802,13 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx,
1518
1802
  &call->metadata_batch[0 /* is_receiving */][0 /* is_trailing */];
1519
1803
  stream_op_payload->send_initial_metadata.send_initial_metadata_flags =
1520
1804
  op->flags;
1805
+ if (call->is_client) {
1806
+ stream_op_payload->send_initial_metadata.peer_string =
1807
+ &call->peer_string;
1808
+ }
1521
1809
  break;
1522
- case GRPC_OP_SEND_MESSAGE:
1810
+ }
1811
+ case GRPC_OP_SEND_MESSAGE: {
1523
1812
  if (!are_write_flags_valid(op->flags)) {
1524
1813
  error = GRPC_CALL_ERROR_INVALID_FLAGS;
1525
1814
  goto done_with_error;
@@ -1548,7 +1837,8 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx,
1548
1837
  stream_op_payload->send_message.send_message =
1549
1838
  &call->sending_stream.base;
1550
1839
  break;
1551
- case GRPC_OP_SEND_CLOSE_FROM_CLIENT:
1840
+ }
1841
+ case GRPC_OP_SEND_CLOSE_FROM_CLIENT: {
1552
1842
  /* Flag validation: currently allow no flags */
1553
1843
  if (op->flags != 0) {
1554
1844
  error = GRPC_CALL_ERROR_INVALID_FLAGS;
@@ -1567,7 +1857,8 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx,
1567
1857
  stream_op_payload->send_trailing_metadata.send_trailing_metadata =
1568
1858
  &call->metadata_batch[0 /* is_receiving */][1 /* is_trailing */];
1569
1859
  break;
1570
- case GRPC_OP_SEND_STATUS_FROM_SERVER:
1860
+ }
1861
+ case GRPC_OP_SEND_STATUS_FROM_SERVER: {
1571
1862
  /* Flag validation: currently allow no flags */
1572
1863
  if (op->flags != 0) {
1573
1864
  error = GRPC_CALL_ERROR_INVALID_FLAGS;
@@ -1629,7 +1920,8 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx,
1629
1920
  stream_op_payload->send_trailing_metadata.send_trailing_metadata =
1630
1921
  &call->metadata_batch[0 /* is_receiving */][1 /* is_trailing */];
1631
1922
  break;
1632
- case GRPC_OP_RECV_INITIAL_METADATA:
1923
+ }
1924
+ case GRPC_OP_RECV_INITIAL_METADATA: {
1633
1925
  /* Flag validation: currently allow no flags */
1634
1926
  if (op->flags != 0) {
1635
1927
  error = GRPC_CALL_ERROR_INVALID_FLAGS;
@@ -1650,9 +1942,14 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx,
1650
1942
  &call->metadata_batch[1 /* is_receiving */][0 /* is_trailing */];
1651
1943
  stream_op_payload->recv_initial_metadata.recv_initial_metadata_ready =
1652
1944
  &call->receiving_initial_metadata_ready;
1945
+ if (!call->is_client) {
1946
+ stream_op_payload->recv_initial_metadata.peer_string =
1947
+ &call->peer_string;
1948
+ }
1653
1949
  num_completion_callbacks_needed++;
1654
1950
  break;
1655
- case GRPC_OP_RECV_MESSAGE:
1951
+ }
1952
+ case GRPC_OP_RECV_MESSAGE: {
1656
1953
  /* Flag validation: currently allow no flags */
1657
1954
  if (op->flags != 0) {
1658
1955
  error = GRPC_CALL_ERROR_INVALID_FLAGS;
@@ -1666,13 +1963,15 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx,
1666
1963
  stream_op->recv_message = true;
1667
1964
  call->receiving_buffer = op->data.recv_message.recv_message;
1668
1965
  stream_op_payload->recv_message.recv_message = &call->receiving_stream;
1669
- GRPC_CLOSURE_INIT(&call->receiving_stream_ready, receiving_stream_ready,
1670
- bctl, grpc_schedule_on_exec_ctx);
1966
+ GRPC_CLOSURE_INIT(&call->receiving_stream_ready,
1967
+ receiving_stream_ready_in_call_combiner, bctl,
1968
+ grpc_schedule_on_exec_ctx);
1671
1969
  stream_op_payload->recv_message.recv_message_ready =
1672
1970
  &call->receiving_stream_ready;
1673
1971
  num_completion_callbacks_needed++;
1674
1972
  break;
1675
- case GRPC_OP_RECV_STATUS_ON_CLIENT:
1973
+ }
1974
+ case GRPC_OP_RECV_STATUS_ON_CLIENT: {
1676
1975
  /* Flag validation: currently allow no flags */
1677
1976
  if (op->flags != 0) {
1678
1977
  error = GRPC_CALL_ERROR_INVALID_FLAGS;
@@ -1699,7 +1998,8 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx,
1699
1998
  stream_op_payload->collect_stats.collect_stats =
1700
1999
  &call->final_info.stats.transport_stream_stats;
1701
2000
  break;
1702
- case GRPC_OP_RECV_CLOSE_ON_SERVER:
2001
+ }
2002
+ case GRPC_OP_RECV_CLOSE_ON_SERVER: {
1703
2003
  /* Flag validation: currently allow no flags */
1704
2004
  if (op->flags != 0) {
1705
2005
  error = GRPC_CALL_ERROR_INVALID_FLAGS;
@@ -1723,6 +2023,7 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx,
1723
2023
  stream_op_payload->collect_stats.collect_stats =
1724
2024
  &call->final_info.stats.transport_stream_stats;
1725
2025
  break;
2026
+ }
1726
2027
  }
1727
2028
  }
1728
2029
 
@@ -1737,7 +2038,7 @@ static grpc_call_error call_start_batch(grpc_exec_ctx *exec_ctx,
1737
2038
  stream_op->on_complete = &bctl->finish_batch;
1738
2039
  gpr_atm_rel_store(&call->any_ops_sent_atm, 1);
1739
2040
 
1740
- execute_op(exec_ctx, call, stream_op);
2041
+ execute_batch(exec_ctx, call, stream_op, &bctl->start_batch);
1741
2042
 
1742
2043
  done:
1743
2044
  GPR_TIMER_END("grpc_call_start_batch", 0);