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
@@ -31,7 +31,8 @@ typedef enum grpc_deadline_timer_state {
31
31
  typedef struct grpc_deadline_state {
32
32
  // We take a reference to the call stack for the timer callback.
33
33
  grpc_call_stack* call_stack;
34
- gpr_atm timer_state;
34
+ grpc_call_combiner* call_combiner;
35
+ grpc_deadline_timer_state timer_state;
35
36
  grpc_timer timer;
36
37
  grpc_closure timer_callback;
37
38
  // Closure to invoke when the call is complete.
@@ -50,6 +51,7 @@ typedef struct grpc_deadline_state {
50
51
  // assumes elem->call_data is zero'd
51
52
  void grpc_deadline_state_init(grpc_exec_ctx* exec_ctx, grpc_call_element* elem,
52
53
  grpc_call_stack* call_stack,
54
+ grpc_call_combiner* call_combiner,
53
55
  gpr_timespec deadline);
54
56
  void grpc_deadline_state_destroy(grpc_exec_ctx* exec_ctx,
55
57
  grpc_call_element* elem);
@@ -61,6 +63,8 @@ void grpc_deadline_state_destroy(grpc_exec_ctx* exec_ctx,
61
63
  // to ensure that the timer callback is not invoked while it is in the
62
64
  // process of being reset, which means that attempting to increase the
63
65
  // deadline may result in the timer being called twice.
66
+ //
67
+ // Note: Must be called while holding the call combiner.
64
68
  void grpc_deadline_state_reset(grpc_exec_ctx* exec_ctx, grpc_call_element* elem,
65
69
  gpr_timespec new_deadline);
66
70
 
@@ -70,6 +74,8 @@ void grpc_deadline_state_reset(grpc_exec_ctx* exec_ctx, grpc_call_element* elem,
70
74
  //
71
75
  // Note: It is the caller's responsibility to chain to the next filter if
72
76
  // necessary after this function returns.
77
+ //
78
+ // Note: Must be called while holding the call combiner.
73
79
  void grpc_deadline_state_client_start_transport_stream_op_batch(
74
80
  grpc_exec_ctx* exec_ctx, grpc_call_element* elem,
75
81
  grpc_transport_stream_op_batch* op);
@@ -36,6 +36,7 @@
36
36
  static const size_t kMaxPayloadSizeForGet = 2048;
37
37
 
38
38
  typedef struct call_data {
39
+ grpc_call_combiner *call_combiner;
39
40
  // State for handling send_initial_metadata ops.
40
41
  grpc_linked_mdelem method;
41
42
  grpc_linked_mdelem scheme;
@@ -138,8 +139,8 @@ static grpc_error *client_filter_incoming_metadata(grpc_exec_ctx *exec_ctx,
138
139
 
139
140
  static void recv_initial_metadata_ready(grpc_exec_ctx *exec_ctx,
140
141
  void *user_data, grpc_error *error) {
141
- grpc_call_element *elem = user_data;
142
- call_data *calld = elem->call_data;
142
+ grpc_call_element *elem = (grpc_call_element *)user_data;
143
+ call_data *calld = (call_data *)elem->call_data;
143
144
  if (error == GRPC_ERROR_NONE) {
144
145
  error = client_filter_incoming_metadata(exec_ctx, elem,
145
146
  calld->recv_initial_metadata);
@@ -153,8 +154,8 @@ static void recv_initial_metadata_ready(grpc_exec_ctx *exec_ctx,
153
154
  static void recv_trailing_metadata_on_complete(grpc_exec_ctx *exec_ctx,
154
155
  void *user_data,
155
156
  grpc_error *error) {
156
- grpc_call_element *elem = user_data;
157
- call_data *calld = elem->call_data;
157
+ grpc_call_element *elem = (grpc_call_element *)user_data;
158
+ call_data *calld = (call_data *)elem->call_data;
158
159
  if (error == GRPC_ERROR_NONE) {
159
160
  error = client_filter_incoming_metadata(exec_ctx, elem,
160
161
  calld->recv_trailing_metadata);
@@ -215,13 +216,13 @@ static void on_send_message_next_done(grpc_exec_ctx *exec_ctx, void *arg,
215
216
  call_data *calld = (call_data *)elem->call_data;
216
217
  if (error != GRPC_ERROR_NONE) {
217
218
  grpc_transport_stream_op_batch_finish_with_failure(
218
- exec_ctx, calld->send_message_batch, error);
219
+ exec_ctx, calld->send_message_batch, error, calld->call_combiner);
219
220
  return;
220
221
  }
221
222
  error = pull_slice_from_send_message(exec_ctx, calld);
222
223
  if (error != GRPC_ERROR_NONE) {
223
224
  grpc_transport_stream_op_batch_finish_with_failure(
224
- exec_ctx, calld->send_message_batch, error);
225
+ exec_ctx, calld->send_message_batch, error, calld->call_combiner);
225
226
  return;
226
227
  }
227
228
  // There may or may not be more to read, but we don't care. If we got
@@ -233,7 +234,7 @@ static void on_send_message_next_done(grpc_exec_ctx *exec_ctx, void *arg,
233
234
  }
234
235
 
235
236
  static char *slice_buffer_to_string(grpc_slice_buffer *slice_buffer) {
236
- char *payload_bytes = gpr_malloc(slice_buffer->length + 1);
237
+ char *payload_bytes = (char *)gpr_malloc(slice_buffer->length + 1);
237
238
  size_t offset = 0;
238
239
  for (size_t i = 0; i < slice_buffer->count; ++i) {
239
240
  memcpy(payload_bytes + offset,
@@ -299,10 +300,9 @@ static void remove_if_present(grpc_exec_ctx *exec_ctx,
299
300
  static void hc_start_transport_stream_op_batch(
300
301
  grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
301
302
  grpc_transport_stream_op_batch *batch) {
302
- call_data *calld = elem->call_data;
303
- channel_data *channeld = elem->channel_data;
303
+ call_data *calld = (call_data *)elem->call_data;
304
+ channel_data *channeld = (channel_data *)elem->channel_data;
304
305
  GPR_TIMER_BEGIN("hc_start_transport_stream_op_batch", 0);
305
- GRPC_CALL_LOG_OP(GPR_INFO, elem, batch);
306
306
 
307
307
  if (batch->recv_initial_metadata) {
308
308
  /* substitute our callback for the higher callback */
@@ -414,7 +414,7 @@ static void hc_start_transport_stream_op_batch(
414
414
  done:
415
415
  if (error != GRPC_ERROR_NONE) {
416
416
  grpc_transport_stream_op_batch_finish_with_failure(
417
- exec_ctx, calld->send_message_batch, error);
417
+ exec_ctx, calld->send_message_batch, error, calld->call_combiner);
418
418
  } else if (!batch_will_be_handled_asynchronously) {
419
419
  grpc_call_next_op(exec_ctx, elem, batch);
420
420
  }
@@ -426,6 +426,7 @@ static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
426
426
  grpc_call_element *elem,
427
427
  const grpc_call_element_args *args) {
428
428
  call_data *calld = (call_data *)elem->call_data;
429
+ calld->call_combiner = args->call_combiner;
429
430
  GRPC_CLOSURE_INIT(&calld->recv_initial_metadata_ready,
430
431
  recv_initial_metadata_ready, elem,
431
432
  grpc_schedule_on_exec_ctx);
@@ -535,7 +536,7 @@ static grpc_slice user_agent_from_args(const grpc_channel_args *args,
535
536
  static grpc_error *init_channel_elem(grpc_exec_ctx *exec_ctx,
536
537
  grpc_channel_element *elem,
537
538
  grpc_channel_element_args *args) {
538
- channel_data *chand = elem->channel_data;
539
+ channel_data *chand = (channel_data *)elem->channel_data;
539
540
  GPR_ASSERT(!args->is_last);
540
541
  GPR_ASSERT(args->optional_transport != NULL);
541
542
  chand->static_scheme = scheme_from_args(args->channel_args);
@@ -551,7 +552,7 @@ static grpc_error *init_channel_elem(grpc_exec_ctx *exec_ctx,
551
552
  /* Destructor for channel data */
552
553
  static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
553
554
  grpc_channel_element *elem) {
554
- channel_data *chand = elem->channel_data;
555
+ channel_data *chand = (channel_data *)elem->channel_data;
555
556
  GRPC_MDELEM_UNREF(exec_ctx, chand->user_agent);
556
557
  }
557
558
 
@@ -565,6 +566,5 @@ const grpc_channel_filter grpc_http_client_filter = {
565
566
  sizeof(channel_data),
566
567
  init_channel_elem,
567
568
  destroy_channel_elem,
568
- grpc_call_next_get_peer,
569
569
  grpc_channel_next_get_info,
570
570
  "http-client"};
@@ -44,7 +44,7 @@ static bool maybe_add_optional_filter(grpc_exec_ctx *exec_ctx,
44
44
  grpc_channel_stack_builder *builder,
45
45
  void *arg) {
46
46
  if (!is_building_http_like_transport(builder)) return true;
47
- optional_filter *filtarg = arg;
47
+ optional_filter *filtarg = (optional_filter *)arg;
48
48
  const grpc_channel_args *channel_args =
49
49
  grpc_channel_stack_builder_get_channel_arguments(builder);
50
50
  bool enable = grpc_channel_arg_get_bool(
@@ -35,33 +35,29 @@
35
35
  #include "src/core/lib/surface/call.h"
36
36
  #include "src/core/lib/transport/static_metadata.h"
37
37
 
38
- #define INITIAL_METADATA_UNSEEN 0
39
- #define HAS_COMPRESSION_ALGORITHM 2
40
- #define NO_COMPRESSION_ALGORITHM 4
41
-
42
- #define CANCELLED_BIT ((gpr_atm)1)
38
+ typedef enum {
39
+ // Initial metadata not yet seen.
40
+ INITIAL_METADATA_UNSEEN = 0,
41
+ // Initial metadata seen; compression algorithm set.
42
+ HAS_COMPRESSION_ALGORITHM,
43
+ // Initial metadata seen; no compression algorithm set.
44
+ NO_COMPRESSION_ALGORITHM,
45
+ } initial_metadata_state;
43
46
 
44
47
  typedef struct call_data {
45
- grpc_slice_buffer slices; /**< Buffers up input slices to be compressed */
48
+ grpc_call_combiner *call_combiner;
46
49
  grpc_linked_mdelem compression_algorithm_storage;
50
+ grpc_linked_mdelem stream_compression_algorithm_storage;
47
51
  grpc_linked_mdelem accept_encoding_storage;
48
- uint32_t remaining_slice_bytes;
52
+ grpc_linked_mdelem accept_stream_encoding_storage;
49
53
  /** Compression algorithm we'll try to use. It may be given by incoming
50
54
  * metadata, or by the channel's default compression settings. */
51
55
  grpc_compression_algorithm compression_algorithm;
52
-
53
- /* Atomic recording the state of initial metadata; allowed values:
54
- INITIAL_METADATA_UNSEEN - initial metadata op not seen
55
- HAS_COMPRESSION_ALGORITHM - initial metadata seen; compression algorithm
56
- set
57
- NO_COMPRESSION_ALGORITHM - initial metadata seen; no compression algorithm
58
- set
59
- pointer - a stalled op containing a send_message that's waiting on initial
60
- metadata
61
- pointer | CANCELLED_BIT - request was cancelled with error pointed to */
62
- gpr_atm send_initial_metadata_state;
63
-
56
+ initial_metadata_state send_initial_metadata_state;
57
+ grpc_error *cancel_error;
58
+ grpc_closure start_send_message_batch_in_call_combiner;
64
59
  grpc_transport_stream_op_batch *send_message_batch;
60
+ grpc_slice_buffer slices; /**< Buffers up input slices to be compressed */
65
61
  grpc_slice_buffer_stream replacement_stream;
66
62
  grpc_closure *original_send_message_on_complete;
67
63
  grpc_closure send_message_on_complete;
@@ -75,21 +71,28 @@ typedef struct channel_data {
75
71
  uint32_t enabled_algorithms_bitset;
76
72
  /** Supported compression algorithms */
77
73
  uint32_t supported_compression_algorithms;
74
+
75
+ /** The default, channel-level, stream compression algorithm */
76
+ grpc_stream_compression_algorithm default_stream_compression_algorithm;
77
+ /** Bitset of enabled stream compression algorithms */
78
+ uint32_t enabled_stream_compression_algorithms_bitset;
79
+ /** Supported stream compression algorithms */
80
+ uint32_t supported_stream_compression_algorithms;
78
81
  } channel_data;
79
82
 
80
83
  static bool skip_compression(grpc_call_element *elem, uint32_t flags,
81
84
  bool has_compression_algorithm) {
82
- call_data *calld = elem->call_data;
83
- channel_data *channeld = elem->channel_data;
85
+ call_data *calld = (call_data *)elem->call_data;
86
+ channel_data *channeld = (channel_data *)elem->channel_data;
84
87
 
85
88
  if (flags & (GRPC_WRITE_NO_COMPRESS | GRPC_WRITE_INTERNAL_COMPRESS)) {
86
- return 1;
89
+ return true;
87
90
  }
88
91
  if (has_compression_algorithm) {
89
92
  if (calld->compression_algorithm == GRPC_COMPRESS_NONE) {
90
- return 1;
93
+ return true;
91
94
  }
92
- return 0; /* we have an actual call-specific algorithm */
95
+ return false; /* we have an actual call-specific algorithm */
93
96
  }
94
97
  /* no per-call compression override */
95
98
  return channeld->default_compression_algorithm == GRPC_COMPRESS_NONE;
@@ -103,34 +106,59 @@ static grpc_error *process_send_initial_metadata(
103
106
  static grpc_error *process_send_initial_metadata(
104
107
  grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
105
108
  grpc_metadata_batch *initial_metadata, bool *has_compression_algorithm) {
106
- call_data *calld = elem->call_data;
107
- channel_data *channeld = elem->channel_data;
109
+ call_data *calld = (call_data *)elem->call_data;
110
+ channel_data *channeld = (channel_data *)elem->channel_data;
108
111
  *has_compression_algorithm = false;
109
- /* Parse incoming request for compression. If any, it'll be available
110
- * at calld->compression_algorithm */
111
- if (initial_metadata->idx.named.grpc_internal_encoding_request != NULL) {
112
+ grpc_stream_compression_algorithm stream_compression_algorithm =
113
+ GRPC_STREAM_COMPRESS_NONE;
114
+ if (initial_metadata->idx.named.grpc_internal_stream_encoding_request !=
115
+ NULL) {
112
116
  grpc_mdelem md =
113
- initial_metadata->idx.named.grpc_internal_encoding_request->md;
114
- if (!grpc_compression_algorithm_parse(GRPC_MDVALUE(md),
115
- &calld->compression_algorithm)) {
117
+ initial_metadata->idx.named.grpc_internal_stream_encoding_request->md;
118
+ if (!grpc_stream_compression_algorithm_parse(
119
+ GRPC_MDVALUE(md), &stream_compression_algorithm)) {
116
120
  char *val = grpc_slice_to_c_string(GRPC_MDVALUE(md));
117
121
  gpr_log(GPR_ERROR,
118
- "Invalid compression algorithm: '%s' (unknown). Ignoring.", val);
122
+ "Invalid stream compression algorithm: '%s' (unknown). Ignoring.",
123
+ val);
119
124
  gpr_free(val);
120
- calld->compression_algorithm = GRPC_COMPRESS_NONE;
125
+ stream_compression_algorithm = GRPC_STREAM_COMPRESS_NONE;
126
+ }
127
+ if (!GPR_BITGET(channeld->enabled_stream_compression_algorithms_bitset,
128
+ stream_compression_algorithm)) {
129
+ char *val = grpc_slice_to_c_string(GRPC_MDVALUE(md));
130
+ gpr_log(
131
+ GPR_ERROR,
132
+ "Invalid stream compression algorithm: '%s' (previously disabled). "
133
+ "Ignoring.",
134
+ val);
135
+ gpr_free(val);
136
+ stream_compression_algorithm = GRPC_STREAM_COMPRESS_NONE;
137
+ }
138
+ *has_compression_algorithm = true;
139
+ grpc_metadata_batch_remove(
140
+ exec_ctx, initial_metadata,
141
+ initial_metadata->idx.named.grpc_internal_stream_encoding_request);
142
+ /* Disable message-wise compression */
143
+ calld->compression_algorithm = GRPC_COMPRESS_NONE;
144
+ if (initial_metadata->idx.named.grpc_internal_encoding_request != NULL) {
145
+ grpc_metadata_batch_remove(
146
+ exec_ctx, initial_metadata,
147
+ initial_metadata->idx.named.grpc_internal_encoding_request);
121
148
  }
122
- if (!GPR_BITGET(channeld->enabled_algorithms_bitset,
123
- calld->compression_algorithm)) {
149
+ } else if (initial_metadata->idx.named.grpc_internal_encoding_request !=
150
+ NULL) {
151
+ grpc_mdelem md =
152
+ initial_metadata->idx.named.grpc_internal_encoding_request->md;
153
+ if (!grpc_compression_algorithm_parse(GRPC_MDVALUE(md),
154
+ &calld->compression_algorithm)) {
124
155
  char *val = grpc_slice_to_c_string(GRPC_MDVALUE(md));
125
156
  gpr_log(GPR_ERROR,
126
- "Invalid compression algorithm: '%s' (previously disabled). "
127
- "Ignoring.",
128
- val);
157
+ "Invalid compression algorithm: '%s' (unknown). Ignoring.", val);
129
158
  gpr_free(val);
130
159
  calld->compression_algorithm = GRPC_COMPRESS_NONE;
131
160
  }
132
161
  *has_compression_algorithm = true;
133
-
134
162
  grpc_metadata_batch_remove(
135
163
  exec_ctx, initial_metadata,
136
164
  initial_metadata->idx.named.grpc_internal_encoding_request);
@@ -138,13 +166,25 @@ static grpc_error *process_send_initial_metadata(
138
166
  /* If no algorithm was found in the metadata and we aren't
139
167
  * exceptionally skipping compression, fall back to the channel
140
168
  * default */
141
- calld->compression_algorithm = channeld->default_compression_algorithm;
169
+ if (channeld->default_stream_compression_algorithm !=
170
+ GRPC_STREAM_COMPRESS_NONE) {
171
+ stream_compression_algorithm =
172
+ channeld->default_stream_compression_algorithm;
173
+ calld->compression_algorithm = GRPC_COMPRESS_NONE;
174
+ } else {
175
+ calld->compression_algorithm = channeld->default_compression_algorithm;
176
+ }
142
177
  *has_compression_algorithm = true;
143
178
  }
144
179
 
145
180
  grpc_error *error = GRPC_ERROR_NONE;
146
181
  /* hint compression algorithm */
147
- if (calld->compression_algorithm != GRPC_COMPRESS_NONE) {
182
+ if (stream_compression_algorithm != GRPC_STREAM_COMPRESS_NONE) {
183
+ error = grpc_metadata_batch_add_tail(
184
+ exec_ctx, initial_metadata,
185
+ &calld->stream_compression_algorithm_storage,
186
+ grpc_stream_compression_encoding_mdelem(stream_compression_algorithm));
187
+ } else if (calld->compression_algorithm != GRPC_COMPRESS_NONE) {
148
188
  error = grpc_metadata_batch_add_tail(
149
189
  exec_ctx, initial_metadata, &calld->compression_algorithm_storage,
150
190
  grpc_compression_encoding_mdelem(calld->compression_algorithm));
@@ -158,6 +198,16 @@ static grpc_error *process_send_initial_metadata(
158
198
  GRPC_MDELEM_ACCEPT_ENCODING_FOR_ALGORITHMS(
159
199
  channeld->supported_compression_algorithms));
160
200
 
201
+ if (error != GRPC_ERROR_NONE) return error;
202
+
203
+ /* Do not overwrite accept-encoding header if it already presents. */
204
+ if (!initial_metadata->idx.named.accept_encoding) {
205
+ error = grpc_metadata_batch_add_tail(
206
+ exec_ctx, initial_metadata, &calld->accept_stream_encoding_storage,
207
+ GRPC_MDELEM_ACCEPT_STREAM_ENCODING_FOR_ALGORITHMS(
208
+ channeld->supported_stream_compression_algorithms));
209
+ }
210
+
161
211
  return error;
162
212
  }
163
213
 
@@ -170,6 +220,18 @@ static void send_message_on_complete(grpc_exec_ctx *exec_ctx, void *arg,
170
220
  GRPC_ERROR_REF(error));
171
221
  }
172
222
 
223
+ static void send_message_batch_continue(grpc_exec_ctx *exec_ctx,
224
+ grpc_call_element *elem) {
225
+ call_data *calld = (call_data *)elem->call_data;
226
+ // Note: The call to grpc_call_next_op() results in yielding the
227
+ // call combiner, so we need to clear calld->send_message_batch
228
+ // before we do that.
229
+ grpc_transport_stream_op_batch *send_message_batch =
230
+ calld->send_message_batch;
231
+ calld->send_message_batch = NULL;
232
+ grpc_call_next_op(exec_ctx, elem, send_message_batch);
233
+ }
234
+
173
235
  static void finish_send_message(grpc_exec_ctx *exec_ctx,
174
236
  grpc_call_element *elem) {
175
237
  call_data *calld = (call_data *)elem->call_data;
@@ -178,11 +240,11 @@ static void finish_send_message(grpc_exec_ctx *exec_ctx,
178
240
  grpc_slice_buffer_init(&tmp);
179
241
  uint32_t send_flags =
180
242
  calld->send_message_batch->payload->send_message.send_message->flags;
181
- const bool did_compress = grpc_msg_compress(
182
- exec_ctx, calld->compression_algorithm, &calld->slices, &tmp);
243
+ bool did_compress = grpc_msg_compress(exec_ctx, calld->compression_algorithm,
244
+ &calld->slices, &tmp);
183
245
  if (did_compress) {
184
246
  if (GRPC_TRACER_ON(grpc_compression_trace)) {
185
- char *algo_name;
247
+ const char *algo_name;
186
248
  const size_t before_size = calld->slices.length;
187
249
  const size_t after_size = tmp.length;
188
250
  const float savings_ratio = 1.0f - (float)after_size / (float)before_size;
@@ -196,7 +258,7 @@ static void finish_send_message(grpc_exec_ctx *exec_ctx,
196
258
  send_flags |= GRPC_WRITE_INTERNAL_COMPRESS;
197
259
  } else {
198
260
  if (GRPC_TRACER_ON(grpc_compression_trace)) {
199
- char *algo_name;
261
+ const char *algo_name;
200
262
  GPR_ASSERT(grpc_compression_algorithm_name(calld->compression_algorithm,
201
263
  &algo_name));
202
264
  gpr_log(GPR_DEBUG,
@@ -217,7 +279,19 @@ static void finish_send_message(grpc_exec_ctx *exec_ctx,
217
279
  calld->original_send_message_on_complete =
218
280
  calld->send_message_batch->on_complete;
219
281
  calld->send_message_batch->on_complete = &calld->send_message_on_complete;
220
- grpc_call_next_op(exec_ctx, elem, calld->send_message_batch);
282
+ send_message_batch_continue(exec_ctx, elem);
283
+ }
284
+
285
+ static void fail_send_message_batch_in_call_combiner(grpc_exec_ctx *exec_ctx,
286
+ void *arg,
287
+ grpc_error *error) {
288
+ call_data *calld = (call_data *)arg;
289
+ if (calld->send_message_batch != NULL) {
290
+ grpc_transport_stream_op_batch_finish_with_failure(
291
+ exec_ctx, calld->send_message_batch, GRPC_ERROR_REF(error),
292
+ calld->call_combiner);
293
+ calld->send_message_batch = NULL;
294
+ }
221
295
  }
222
296
 
223
297
  // Pulls a slice from the send_message byte stream and adds it to calld->slices.
@@ -237,21 +311,25 @@ static grpc_error *pull_slice_from_send_message(grpc_exec_ctx *exec_ctx,
237
311
  // If all data has been read, invokes finish_send_message(). Otherwise,
238
312
  // an async call to grpc_byte_stream_next() has been started, which will
239
313
  // eventually result in calling on_send_message_next_done().
240
- static grpc_error *continue_reading_send_message(grpc_exec_ctx *exec_ctx,
241
- grpc_call_element *elem) {
314
+ static void continue_reading_send_message(grpc_exec_ctx *exec_ctx,
315
+ grpc_call_element *elem) {
242
316
  call_data *calld = (call_data *)elem->call_data;
243
317
  while (grpc_byte_stream_next(
244
318
  exec_ctx, calld->send_message_batch->payload->send_message.send_message,
245
319
  ~(size_t)0, &calld->on_send_message_next_done)) {
246
320
  grpc_error *error = pull_slice_from_send_message(exec_ctx, calld);
247
- if (error != GRPC_ERROR_NONE) return error;
321
+ if (error != GRPC_ERROR_NONE) {
322
+ // Closure callback; does not take ownership of error.
323
+ fail_send_message_batch_in_call_combiner(exec_ctx, calld, error);
324
+ GRPC_ERROR_UNREF(error);
325
+ return;
326
+ }
248
327
  if (calld->slices.length ==
249
328
  calld->send_message_batch->payload->send_message.send_message->length) {
250
329
  finish_send_message(exec_ctx, elem);
251
330
  break;
252
331
  }
253
332
  }
254
- return GRPC_ERROR_NONE;
255
333
  }
256
334
 
257
335
  // Async callback for grpc_byte_stream_next().
@@ -259,142 +337,118 @@ static void on_send_message_next_done(grpc_exec_ctx *exec_ctx, void *arg,
259
337
  grpc_error *error) {
260
338
  grpc_call_element *elem = (grpc_call_element *)arg;
261
339
  call_data *calld = (call_data *)elem->call_data;
262
- if (error != GRPC_ERROR_NONE) goto fail;
340
+ if (error != GRPC_ERROR_NONE) {
341
+ // Closure callback; does not take ownership of error.
342
+ fail_send_message_batch_in_call_combiner(exec_ctx, calld, error);
343
+ return;
344
+ }
263
345
  error = pull_slice_from_send_message(exec_ctx, calld);
264
- if (error != GRPC_ERROR_NONE) goto fail;
346
+ if (error != GRPC_ERROR_NONE) {
347
+ // Closure callback; does not take ownership of error.
348
+ fail_send_message_batch_in_call_combiner(exec_ctx, calld, error);
349
+ GRPC_ERROR_UNREF(error);
350
+ return;
351
+ }
265
352
  if (calld->slices.length ==
266
353
  calld->send_message_batch->payload->send_message.send_message->length) {
267
354
  finish_send_message(exec_ctx, elem);
268
355
  } else {
269
- // This will either finish reading all of the data and invoke
270
- // finish_send_message(), or else it will make an async call to
271
- // grpc_byte_stream_next(), which will eventually result in calling
272
- // this function again.
273
- error = continue_reading_send_message(exec_ctx, elem);
274
- if (error != GRPC_ERROR_NONE) goto fail;
356
+ continue_reading_send_message(exec_ctx, elem);
275
357
  }
276
- return;
277
- fail:
278
- grpc_transport_stream_op_batch_finish_with_failure(
279
- exec_ctx, calld->send_message_batch, error);
280
358
  }
281
359
 
282
- static void start_send_message_batch(grpc_exec_ctx *exec_ctx,
283
- grpc_call_element *elem,
284
- grpc_transport_stream_op_batch *batch,
285
- bool has_compression_algorithm) {
360
+ static void start_send_message_batch(grpc_exec_ctx *exec_ctx, void *arg,
361
+ grpc_error *unused) {
362
+ grpc_call_element *elem = (grpc_call_element *)arg;
286
363
  call_data *calld = (call_data *)elem->call_data;
287
- if (!skip_compression(elem, batch->payload->send_message.send_message->flags,
288
- has_compression_algorithm)) {
289
- calld->send_message_batch = batch;
290
- // This will either finish reading all of the data and invoke
291
- // finish_send_message(), or else it will make an async call to
292
- // grpc_byte_stream_next(), which will eventually result in calling
293
- // on_send_message_next_done().
294
- grpc_error *error = continue_reading_send_message(exec_ctx, elem);
295
- if (error != GRPC_ERROR_NONE) {
296
- grpc_transport_stream_op_batch_finish_with_failure(
297
- exec_ctx, calld->send_message_batch, error);
298
- }
364
+ if (skip_compression(
365
+ elem,
366
+ calld->send_message_batch->payload->send_message.send_message->flags,
367
+ calld->send_initial_metadata_state == HAS_COMPRESSION_ALGORITHM)) {
368
+ send_message_batch_continue(exec_ctx, elem);
299
369
  } else {
300
- /* pass control down the stack */
301
- grpc_call_next_op(exec_ctx, elem, batch);
370
+ continue_reading_send_message(exec_ctx, elem);
302
371
  }
303
372
  }
304
373
 
305
374
  static void compress_start_transport_stream_op_batch(
306
375
  grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
307
376
  grpc_transport_stream_op_batch *batch) {
308
- call_data *calld = elem->call_data;
309
-
377
+ call_data *calld = (call_data *)elem->call_data;
310
378
  GPR_TIMER_BEGIN("compress_start_transport_stream_op_batch", 0);
311
-
379
+ // Handle cancel_stream.
312
380
  if (batch->cancel_stream) {
313
- // TODO(roth): As part of the upcoming call combiner work, change
314
- // this to call grpc_byte_stream_shutdown() on the incoming byte
315
- // stream, to cancel any in-flight calls to grpc_byte_stream_next().
316
- GRPC_ERROR_REF(batch->payload->cancel_stream.cancel_error);
317
- gpr_atm cur = gpr_atm_full_xchg(
318
- &calld->send_initial_metadata_state,
319
- CANCELLED_BIT | (gpr_atm)batch->payload->cancel_stream.cancel_error);
320
- switch (cur) {
321
- case HAS_COMPRESSION_ALGORITHM:
322
- case NO_COMPRESSION_ALGORITHM:
323
- case INITIAL_METADATA_UNSEEN:
324
- break;
325
- default:
326
- if ((cur & CANCELLED_BIT) == 0) {
327
- grpc_transport_stream_op_batch_finish_with_failure(
328
- exec_ctx, (grpc_transport_stream_op_batch *)cur,
329
- GRPC_ERROR_REF(batch->payload->cancel_stream.cancel_error));
330
- } else {
331
- GRPC_ERROR_UNREF((grpc_error *)(cur & ~CANCELLED_BIT));
332
- }
333
- break;
381
+ GRPC_ERROR_UNREF(calld->cancel_error);
382
+ calld->cancel_error =
383
+ GRPC_ERROR_REF(batch->payload->cancel_stream.cancel_error);
384
+ if (calld->send_message_batch != NULL) {
385
+ if (calld->send_initial_metadata_state == INITIAL_METADATA_UNSEEN) {
386
+ GRPC_CALL_COMBINER_START(
387
+ exec_ctx, calld->call_combiner,
388
+ GRPC_CLOSURE_CREATE(fail_send_message_batch_in_call_combiner, calld,
389
+ grpc_schedule_on_exec_ctx),
390
+ GRPC_ERROR_REF(calld->cancel_error), "failing send_message op");
391
+ } else {
392
+ grpc_byte_stream_shutdown(
393
+ exec_ctx,
394
+ calld->send_message_batch->payload->send_message.send_message,
395
+ GRPC_ERROR_REF(calld->cancel_error));
396
+ }
334
397
  }
398
+ } else if (calld->cancel_error != GRPC_ERROR_NONE) {
399
+ grpc_transport_stream_op_batch_finish_with_failure(
400
+ exec_ctx, batch, GRPC_ERROR_REF(calld->cancel_error),
401
+ calld->call_combiner);
402
+ goto done;
335
403
  }
336
-
404
+ // Handle send_initial_metadata.
337
405
  if (batch->send_initial_metadata) {
406
+ GPR_ASSERT(calld->send_initial_metadata_state == INITIAL_METADATA_UNSEEN);
338
407
  bool has_compression_algorithm;
339
408
  grpc_error *error = process_send_initial_metadata(
340
409
  exec_ctx, elem,
341
410
  batch->payload->send_initial_metadata.send_initial_metadata,
342
411
  &has_compression_algorithm);
343
412
  if (error != GRPC_ERROR_NONE) {
344
- grpc_transport_stream_op_batch_finish_with_failure(exec_ctx, batch,
345
- error);
346
- return;
413
+ grpc_transport_stream_op_batch_finish_with_failure(exec_ctx, batch, error,
414
+ calld->call_combiner);
415
+ goto done;
347
416
  }
348
- gpr_atm cur;
349
- retry_send_im:
350
- cur = gpr_atm_acq_load(&calld->send_initial_metadata_state);
351
- GPR_ASSERT(cur != HAS_COMPRESSION_ALGORITHM &&
352
- cur != NO_COMPRESSION_ALGORITHM);
353
- if ((cur & CANCELLED_BIT) == 0) {
354
- if (!gpr_atm_rel_cas(&calld->send_initial_metadata_state, cur,
355
- has_compression_algorithm
356
- ? HAS_COMPRESSION_ALGORITHM
357
- : NO_COMPRESSION_ALGORITHM)) {
358
- goto retry_send_im;
359
- }
360
- if (cur != INITIAL_METADATA_UNSEEN) {
361
- start_send_message_batch(exec_ctx, elem,
362
- (grpc_transport_stream_op_batch *)cur,
363
- has_compression_algorithm);
364
- }
417
+ calld->send_initial_metadata_state = has_compression_algorithm
418
+ ? HAS_COMPRESSION_ALGORITHM
419
+ : NO_COMPRESSION_ALGORITHM;
420
+ // If we had previously received a batch containing a send_message op,
421
+ // handle it now. Note that we need to re-enter the call combiner
422
+ // for this, since we can't send two batches down while holding the
423
+ // call combiner, since the connected_channel filter (at the bottom of
424
+ // the call stack) will release the call combiner for each batch it sees.
425
+ if (calld->send_message_batch != NULL) {
426
+ GRPC_CALL_COMBINER_START(
427
+ exec_ctx, calld->call_combiner,
428
+ &calld->start_send_message_batch_in_call_combiner, GRPC_ERROR_NONE,
429
+ "starting send_message after send_initial_metadata");
365
430
  }
366
431
  }
432
+ // Handle send_message.
367
433
  if (batch->send_message) {
368
- gpr_atm cur;
369
- retry_send:
370
- cur = gpr_atm_acq_load(&calld->send_initial_metadata_state);
371
- switch (cur) {
372
- case INITIAL_METADATA_UNSEEN:
373
- if (!gpr_atm_rel_cas(&calld->send_initial_metadata_state, cur,
374
- (gpr_atm)batch)) {
375
- goto retry_send;
376
- }
377
- break;
378
- case HAS_COMPRESSION_ALGORITHM:
379
- case NO_COMPRESSION_ALGORITHM:
380
- start_send_message_batch(exec_ctx, elem, batch,
381
- cur == HAS_COMPRESSION_ALGORITHM);
382
- break;
383
- default:
384
- if (cur & CANCELLED_BIT) {
385
- grpc_transport_stream_op_batch_finish_with_failure(
386
- exec_ctx, batch,
387
- GRPC_ERROR_REF((grpc_error *)(cur & ~CANCELLED_BIT)));
388
- } else {
389
- /* >1 send_message concurrently */
390
- GPR_UNREACHABLE_CODE(break);
391
- }
434
+ GPR_ASSERT(calld->send_message_batch == NULL);
435
+ calld->send_message_batch = batch;
436
+ // If we have not yet seen send_initial_metadata, then we have to
437
+ // wait. We save the batch in calld and then drop the call
438
+ // combiner, which we'll have to pick up again later when we get
439
+ // send_initial_metadata.
440
+ if (calld->send_initial_metadata_state == INITIAL_METADATA_UNSEEN) {
441
+ GRPC_CALL_COMBINER_STOP(
442
+ exec_ctx, calld->call_combiner,
443
+ "send_message batch pending send_initial_metadata");
444
+ goto done;
392
445
  }
446
+ start_send_message_batch(exec_ctx, elem, GRPC_ERROR_NONE);
393
447
  } else {
394
- /* pass control down the stack */
448
+ // Pass control down the stack.
395
449
  grpc_call_next_op(exec_ctx, elem, batch);
396
450
  }
397
-
451
+ done:
398
452
  GPR_TIMER_END("compress_start_transport_stream_op_batch", 0);
399
453
  }
400
454
 
@@ -402,16 +456,16 @@ static void compress_start_transport_stream_op_batch(
402
456
  static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
403
457
  grpc_call_element *elem,
404
458
  const grpc_call_element_args *args) {
405
- /* grab pointers to our data from the call element */
406
- call_data *calld = elem->call_data;
407
-
408
- /* initialize members */
459
+ call_data *calld = (call_data *)elem->call_data;
460
+ calld->call_combiner = args->call_combiner;
461
+ calld->cancel_error = GRPC_ERROR_NONE;
409
462
  grpc_slice_buffer_init(&calld->slices);
463
+ GRPC_CLOSURE_INIT(&calld->start_send_message_batch_in_call_combiner,
464
+ start_send_message_batch, elem, grpc_schedule_on_exec_ctx);
410
465
  GRPC_CLOSURE_INIT(&calld->on_send_message_next_done,
411
466
  on_send_message_next_done, elem, grpc_schedule_on_exec_ctx);
412
467
  GRPC_CLOSURE_INIT(&calld->send_message_on_complete, send_message_on_complete,
413
468
  elem, grpc_schedule_on_exec_ctx);
414
-
415
469
  return GRPC_ERROR_NONE;
416
470
  }
417
471
 
@@ -419,22 +473,18 @@ static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
419
473
  static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
420
474
  const grpc_call_final_info *final_info,
421
475
  grpc_closure *ignored) {
422
- /* grab pointers to our data from the call element */
423
- call_data *calld = elem->call_data;
476
+ call_data *calld = (call_data *)elem->call_data;
424
477
  grpc_slice_buffer_destroy_internal(exec_ctx, &calld->slices);
425
- gpr_atm imstate =
426
- gpr_atm_no_barrier_load(&calld->send_initial_metadata_state);
427
- if (imstate & CANCELLED_BIT) {
428
- GRPC_ERROR_UNREF((grpc_error *)(imstate & ~CANCELLED_BIT));
429
- }
478
+ GRPC_ERROR_UNREF(calld->cancel_error);
430
479
  }
431
480
 
432
481
  /* Constructor for channel_data */
433
482
  static grpc_error *init_channel_elem(grpc_exec_ctx *exec_ctx,
434
483
  grpc_channel_element *elem,
435
484
  grpc_channel_element_args *args) {
436
- channel_data *channeld = elem->channel_data;
485
+ channel_data *channeld = (channel_data *)elem->channel_data;
437
486
 
487
+ /* Configuration for message compression */
438
488
  channeld->enabled_algorithms_bitset =
439
489
  grpc_channel_args_compression_algorithm_get_states(args->channel_args);
440
490
 
@@ -449,16 +499,32 @@ static grpc_error *init_channel_elem(grpc_exec_ctx *exec_ctx,
449
499
  channeld->default_compression_algorithm = GRPC_COMPRESS_NONE;
450
500
  }
451
501
 
452
- channeld->supported_compression_algorithms = 1; /* always support identity */
453
- for (grpc_compression_algorithm algo_idx = 1;
454
- algo_idx < GRPC_COMPRESS_ALGORITHMS_COUNT; ++algo_idx) {
455
- /* skip disabled algorithms */
456
- if (!GPR_BITGET(channeld->enabled_algorithms_bitset, algo_idx)) {
457
- continue;
458
- }
459
- channeld->supported_compression_algorithms |= 1u << algo_idx;
502
+ channeld->supported_compression_algorithms =
503
+ (((1u << GRPC_COMPRESS_ALGORITHMS_COUNT) - 1) &
504
+ channeld->enabled_algorithms_bitset) |
505
+ 1u;
506
+
507
+ /* Configuration for stream compression */
508
+ channeld->enabled_stream_compression_algorithms_bitset =
509
+ grpc_channel_args_stream_compression_algorithm_get_states(
510
+ args->channel_args);
511
+
512
+ channeld->default_stream_compression_algorithm =
513
+ grpc_channel_args_get_stream_compression_algorithm(args->channel_args);
514
+
515
+ if (!GPR_BITGET(channeld->enabled_stream_compression_algorithms_bitset,
516
+ channeld->default_stream_compression_algorithm)) {
517
+ gpr_log(GPR_DEBUG,
518
+ "stream compression algorithm %d not enabled: switching to none",
519
+ channeld->default_stream_compression_algorithm);
520
+ channeld->default_stream_compression_algorithm = GRPC_STREAM_COMPRESS_NONE;
460
521
  }
461
522
 
523
+ channeld->supported_stream_compression_algorithms =
524
+ (((1u << GRPC_STREAM_COMPRESS_ALGORITHMS_COUNT) - 1) &
525
+ channeld->enabled_stream_compression_algorithms_bitset) |
526
+ 1u;
527
+
462
528
  GPR_ASSERT(!args->is_last);
463
529
  return GRPC_ERROR_NONE;
464
530
  }
@@ -477,6 +543,5 @@ const grpc_channel_filter grpc_message_compress_filter = {
477
543
  sizeof(channel_data),
478
544
  init_channel_elem,
479
545
  destroy_channel_elem,
480
- grpc_call_next_get_peer,
481
546
  grpc_channel_next_get_info,
482
- "compress"};
547
+ "message_compress"};