grpc 1.3.4 → 1.4.0

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 (286) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +581 -450
  3. data/include/grpc/census.h +49 -49
  4. data/include/grpc/grpc.h +16 -70
  5. data/include/grpc/grpc_security.h +59 -59
  6. data/include/grpc/grpc_security_constants.h +9 -9
  7. data/include/grpc/impl/codegen/atm.h +1 -1
  8. data/include/grpc/impl/codegen/atm_windows.h +4 -4
  9. data/include/grpc/impl/codegen/byte_buffer_reader.h +2 -2
  10. data/include/grpc/impl/codegen/compression_types.h +4 -5
  11. data/include/grpc/impl/codegen/gpr_slice.h +5 -5
  12. data/include/grpc/impl/codegen/gpr_types.h +6 -7
  13. data/include/grpc/impl/codegen/grpc_types.h +128 -59
  14. data/include/grpc/impl/codegen/port_platform.h +6 -0
  15. data/include/grpc/impl/codegen/propagation_bits.h +2 -2
  16. data/include/grpc/impl/codegen/slice.h +13 -12
  17. data/include/grpc/impl/codegen/status.h +23 -18
  18. data/include/grpc/impl/codegen/sync.h +1 -1
  19. data/include/grpc/load_reporting.h +6 -6
  20. data/include/grpc/slice.h +47 -25
  21. data/include/grpc/slice_buffer.h +18 -14
  22. data/include/grpc/support/alloc.h +7 -7
  23. data/include/grpc/support/cmdline.h +10 -10
  24. data/include/grpc/support/cpu.h +3 -3
  25. data/include/grpc/support/histogram.h +1 -1
  26. data/include/grpc/support/host_port.h +2 -2
  27. data/include/grpc/support/log.h +9 -9
  28. data/include/grpc/support/log_windows.h +1 -1
  29. data/include/grpc/support/string_util.h +3 -3
  30. data/include/grpc/support/subprocess.h +3 -3
  31. data/include/grpc/support/sync.h +31 -31
  32. data/include/grpc/support/thd.h +11 -11
  33. data/include/grpc/support/time.h +12 -12
  34. data/include/grpc/support/tls.h +1 -1
  35. data/include/grpc/support/tls_gcc.h +2 -2
  36. data/include/grpc/support/tls_msvc.h +1 -1
  37. data/include/grpc/support/tls_pthread.h +1 -1
  38. data/include/grpc/support/useful.h +2 -2
  39. data/include/grpc/support/workaround_list.h +46 -0
  40. data/src/core/ext/census/context.c +1 -1
  41. data/src/core/ext/census/intrusive_hash_map.c +319 -0
  42. data/src/core/ext/census/intrusive_hash_map.h +167 -0
  43. data/src/core/ext/census/intrusive_hash_map_internal.h +63 -0
  44. data/src/core/ext/census/resource.c +3 -1
  45. data/src/core/ext/filters/client_channel/channel_connectivity.c +1 -1
  46. data/src/core/ext/filters/client_channel/client_channel.c +173 -103
  47. data/src/core/ext/filters/client_channel/client_channel_plugin.c +3 -2
  48. data/src/core/ext/filters/client_channel/lb_policy.c +2 -1
  49. data/src/core/ext/filters/client_channel/lb_policy.h +8 -7
  50. data/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.c +153 -0
  51. data/src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.h +42 -0
  52. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.c +405 -102
  53. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.c +133 -0
  54. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h +65 -0
  55. data/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.c +90 -51
  56. data/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h +7 -1
  57. data/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c +19 -8
  58. data/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h +63 -34
  59. data/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.c +2 -1
  60. data/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.c +188 -294
  61. data/src/core/ext/filters/client_channel/lb_policy_factory.c +28 -5
  62. data/src/core/ext/filters/client_channel/lb_policy_factory.h +18 -4
  63. data/src/core/ext/filters/client_channel/parse_address.c +90 -59
  64. data/src/core/ext/filters/client_channel/parse_address.h +17 -8
  65. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.c +11 -7
  66. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.c +59 -14
  67. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h +6 -0
  68. data/src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.c +3 -3
  69. data/src/core/ext/filters/client_channel/subchannel.c +20 -17
  70. data/src/core/ext/filters/client_channel/subchannel.h +1 -0
  71. data/src/core/ext/filters/client_channel/subchannel_index.c +11 -1
  72. data/src/core/ext/filters/client_channel/uri_parser.c +36 -22
  73. data/src/core/ext/filters/client_channel/uri_parser.h +1 -1
  74. data/src/core/{lib/channel → ext/filters/deadline}/deadline_filter.c +42 -17
  75. data/src/core/{lib/channel → ext/filters/deadline}/deadline_filter.h +8 -9
  76. data/src/core/{lib/channel → ext/filters/http/client}/http_client_filter.c +19 -11
  77. data/src/core/{lib/channel → ext/filters/http/client}/http_client_filter.h +3 -6
  78. data/src/core/ext/filters/http/http_filters_plugin.c +104 -0
  79. data/src/core/{lib/channel/compress_filter.c → ext/filters/http/message_compress/message_compress_filter.c} +124 -23
  80. data/src/core/{lib/channel/compress_filter.h → ext/filters/http/message_compress/message_compress_filter.h} +5 -6
  81. data/src/core/{lib/channel → ext/filters/http/server}/http_server_filter.c +4 -6
  82. data/src/core/{lib/channel → ext/filters/http/server}/http_server_filter.h +3 -3
  83. data/src/core/ext/filters/load_reporting/load_reporting.c +2 -25
  84. data/src/core/ext/filters/load_reporting/load_reporting_filter.c +26 -1
  85. data/src/core/ext/filters/max_age/max_age_filter.c +14 -14
  86. data/src/core/{lib/channel → ext/filters/message_size}/message_size_filter.c +91 -47
  87. data/src/core/{lib/channel → ext/filters/message_size}/message_size_filter.h +3 -3
  88. data/src/core/ext/filters/workarounds/workaround_cronet_compression_filter.c +223 -0
  89. data/src/core/ext/filters/workarounds/workaround_cronet_compression_filter.h +40 -0
  90. data/src/core/ext/filters/workarounds/workaround_utils.c +65 -0
  91. data/src/core/ext/filters/workarounds/workaround_utils.h +52 -0
  92. data/src/core/ext/transport/chttp2/client/insecure/channel_create.c +1 -1
  93. data/src/core/ext/transport/chttp2/server/chttp2_server.c +3 -2
  94. data/src/core/ext/transport/chttp2/transport/bin_decoder.c +2 -2
  95. data/src/core/ext/transport/chttp2/transport/bin_encoder.c +3 -3
  96. data/src/core/ext/transport/chttp2/transport/chttp2_transport.c +319 -175
  97. data/src/core/ext/transport/chttp2/transport/chttp2_transport.h +3 -2
  98. data/src/core/ext/transport/chttp2/transport/frame_data.c +203 -164
  99. data/src/core/ext/transport/chttp2/transport/frame_data.h +8 -14
  100. data/src/core/ext/transport/chttp2/transport/frame_goaway.c +1 -1
  101. data/src/core/ext/transport/chttp2/transport/frame_ping.c +1 -1
  102. data/src/core/ext/transport/chttp2/transport/frame_rst_stream.c +1 -1
  103. data/src/core/ext/transport/chttp2/transport/frame_settings.c +5 -5
  104. data/src/core/ext/transport/chttp2/transport/frame_window_update.c +1 -1
  105. data/src/core/ext/transport/chttp2/transport/hpack_encoder.c +4 -4
  106. data/src/core/ext/transport/chttp2/transport/hpack_parser.c +2 -4
  107. data/src/core/ext/transport/chttp2/transport/hpack_table.c +4 -3
  108. data/src/core/ext/transport/chttp2/transport/internal.h +50 -33
  109. data/src/core/ext/transport/chttp2/transport/parsing.c +10 -11
  110. data/src/core/ext/transport/chttp2/transport/writing.c +32 -13
  111. data/src/core/lib/channel/channel_args.c +30 -9
  112. data/src/core/lib/channel/channel_args.h +5 -1
  113. data/src/core/lib/channel/channel_stack.c +1 -1
  114. data/src/core/lib/channel/channel_stack.h +2 -2
  115. data/src/core/lib/channel/channel_stack_builder.c +13 -1
  116. data/src/core/lib/channel/channel_stack_builder.h +5 -1
  117. data/src/core/lib/channel/connected_channel.c +3 -1
  118. data/src/core/lib/channel/context.h +2 -2
  119. data/src/core/lib/compression/message_compress.c +2 -2
  120. data/src/core/lib/debug/trace.c +13 -6
  121. data/src/core/lib/debug/trace.h +27 -1
  122. data/src/core/lib/http/httpcli.c +1 -1
  123. data/src/core/lib/http/httpcli_security_connector.c +9 -11
  124. data/src/core/lib/http/parser.c +2 -2
  125. data/src/core/lib/http/parser.h +2 -1
  126. data/src/core/lib/iomgr/combiner.c +6 -6
  127. data/src/core/lib/iomgr/combiner.h +2 -1
  128. data/src/core/lib/iomgr/error.c +12 -5
  129. data/src/core/lib/iomgr/error.h +13 -13
  130. data/src/core/lib/iomgr/ev_epoll1_linux.c +984 -0
  131. data/src/core/lib/iomgr/ev_epoll1_linux.h +44 -0
  132. data/src/core/lib/iomgr/ev_epoll_limited_pollers_linux.c +2146 -0
  133. data/src/core/lib/iomgr/ev_epoll_limited_pollers_linux.h +43 -0
  134. data/src/core/lib/iomgr/ev_epoll_thread_pool_linux.c +1337 -0
  135. data/src/core/lib/iomgr/ev_epoll_thread_pool_linux.h +43 -0
  136. data/src/core/lib/iomgr/ev_epollex_linux.c +1511 -0
  137. data/src/core/lib/iomgr/ev_epollex_linux.h +43 -0
  138. data/src/core/lib/iomgr/{ev_epoll_linux.c → ev_epollsig_linux.c} +41 -33
  139. data/src/core/lib/iomgr/{ev_epoll_linux.h → ev_epollsig_linux.h} +4 -4
  140. data/src/core/lib/iomgr/ev_poll_posix.c +12 -27
  141. data/src/core/lib/iomgr/ev_poll_posix.h +2 -2
  142. data/src/core/lib/iomgr/ev_posix.c +22 -8
  143. data/src/core/lib/iomgr/ev_posix.h +4 -3
  144. data/src/core/lib/iomgr/ev_windows.c +43 -0
  145. data/src/core/lib/iomgr/exec_ctx.c +5 -0
  146. data/src/core/lib/iomgr/exec_ctx.h +2 -0
  147. data/src/core/lib/iomgr/iomgr.c +4 -0
  148. data/src/core/lib/iomgr/iomgr.h +3 -0
  149. data/src/core/lib/iomgr/is_epollexclusive_available.c +116 -0
  150. data/src/core/lib/iomgr/is_epollexclusive_available.h +41 -0
  151. data/src/core/lib/iomgr/lockfree_event.c +16 -0
  152. data/src/core/lib/iomgr/pollset.h +2 -5
  153. data/src/core/lib/iomgr/pollset_uv.c +1 -1
  154. data/src/core/lib/iomgr/pollset_windows.c +3 -3
  155. data/src/core/lib/iomgr/resource_quota.c +9 -8
  156. data/src/core/lib/iomgr/resource_quota.h +2 -1
  157. data/src/core/lib/iomgr/sockaddr_utils.h +1 -1
  158. data/src/core/lib/iomgr/socket_mutator.h +2 -0
  159. data/src/core/lib/iomgr/sys_epoll_wrapper.h +43 -0
  160. data/src/core/lib/iomgr/tcp_client_posix.c +6 -6
  161. data/src/core/lib/iomgr/tcp_client_uv.c +3 -3
  162. data/src/core/lib/iomgr/tcp_posix.c +7 -7
  163. data/src/core/lib/iomgr/tcp_posix.h +2 -1
  164. data/src/core/lib/iomgr/tcp_server_posix.c +1 -1
  165. data/src/core/lib/iomgr/tcp_uv.c +6 -6
  166. data/src/core/lib/iomgr/tcp_uv.h +2 -1
  167. data/src/core/lib/iomgr/tcp_windows.c +1 -1
  168. data/src/core/lib/iomgr/timer_generic.c +24 -25
  169. data/src/core/lib/iomgr/timer_manager.c +276 -0
  170. data/src/core/lib/iomgr/timer_manager.h +52 -0
  171. data/src/core/lib/iomgr/timer_uv.c +6 -0
  172. data/src/core/lib/iomgr/udp_server.c +42 -9
  173. data/src/core/lib/iomgr/udp_server.h +3 -1
  174. data/src/core/lib/security/credentials/credentials.c +0 -1
  175. data/src/core/lib/security/credentials/fake/fake_credentials.c +23 -0
  176. data/src/core/lib/security/credentials/fake/fake_credentials.h +12 -9
  177. data/src/core/lib/security/credentials/google_default/google_default_credentials.c +1 -1
  178. data/src/core/lib/security/credentials/jwt/jwt_credentials.c +1 -1
  179. data/src/core/lib/security/credentials/oauth2/oauth2_credentials.c +1 -1
  180. data/src/core/lib/security/credentials/ssl/ssl_credentials.c +24 -53
  181. data/src/core/lib/security/transport/client_auth_filter.c +9 -3
  182. data/src/core/lib/security/transport/secure_endpoint.c +7 -7
  183. data/src/core/lib/security/transport/secure_endpoint.h +1 -1
  184. data/src/core/lib/security/transport/security_connector.c +45 -57
  185. data/src/core/lib/security/transport/security_connector.h +10 -14
  186. data/src/core/lib/security/transport/security_handshaker.c +123 -97
  187. data/src/core/lib/slice/b64.c +1 -1
  188. data/src/core/lib/slice/percent_encoding.c +3 -3
  189. data/src/core/lib/slice/slice.c +66 -33
  190. data/src/core/lib/slice/slice_buffer.c +25 -6
  191. data/src/core/lib/slice/slice_hash_table.c +33 -35
  192. data/src/core/lib/slice/slice_hash_table.h +7 -12
  193. data/src/core/lib/support/atomic.h +45 -0
  194. data/src/core/lib/support/atomic_with_atm.h +70 -0
  195. data/src/core/lib/support/atomic_with_std.h +48 -0
  196. data/src/core/lib/support/avl.c +14 -14
  197. data/src/core/lib/support/cmdline.c +3 -3
  198. data/src/core/lib/support/histogram.c +2 -2
  199. data/src/core/lib/support/host_port.c +1 -1
  200. data/src/core/lib/support/memory.h +74 -0
  201. data/src/core/lib/support/mpscq.c +36 -2
  202. data/src/core/lib/support/mpscq.h +28 -1
  203. data/src/core/lib/support/stack_lockfree.c +3 -36
  204. data/src/core/lib/support/string.c +12 -12
  205. data/src/core/lib/support/string_posix.c +1 -1
  206. data/src/core/lib/support/subprocess_posix.c +2 -2
  207. data/src/core/lib/support/thd_posix.c +1 -1
  208. data/src/core/lib/support/time_posix.c +8 -0
  209. data/src/core/lib/support/tmpfile_posix.c +10 -10
  210. data/src/core/lib/surface/alarm.c +3 -1
  211. data/src/core/lib/surface/api_trace.c +2 -1
  212. data/src/core/lib/surface/api_trace.h +2 -2
  213. data/src/core/lib/surface/byte_buffer_reader.c +1 -1
  214. data/src/core/lib/surface/call.c +65 -22
  215. data/src/core/lib/surface/call.h +4 -2
  216. data/src/core/lib/surface/channel_init.c +2 -19
  217. data/src/core/lib/surface/channel_stack_type.c +18 -0
  218. data/src/core/lib/surface/channel_stack_type.h +2 -0
  219. data/src/core/lib/surface/completion_queue.c +694 -247
  220. data/src/core/lib/surface/completion_queue.h +30 -13
  221. data/src/core/lib/surface/completion_queue_factory.c +24 -9
  222. data/src/core/lib/surface/init.c +1 -52
  223. data/src/core/lib/surface/{lame_client.c → lame_client.cc} +37 -26
  224. data/src/core/lib/surface/server.c +79 -110
  225. data/src/core/lib/surface/server.h +2 -1
  226. data/src/core/lib/surface/version.c +2 -2
  227. data/src/core/lib/transport/bdp_estimator.c +25 -9
  228. data/src/core/lib/transport/bdp_estimator.h +7 -1
  229. data/src/core/lib/transport/byte_stream.c +23 -9
  230. data/src/core/lib/transport/byte_stream.h +15 -6
  231. data/src/core/lib/transport/connectivity_state.c +6 -6
  232. data/src/core/lib/transport/connectivity_state.h +2 -1
  233. data/src/core/lib/transport/service_config.c +6 -13
  234. data/src/core/lib/transport/service_config.h +2 -2
  235. data/src/core/lib/transport/static_metadata.c +403 -389
  236. data/src/core/lib/transport/static_metadata.h +127 -114
  237. data/src/core/plugin_registry/grpc_plugin_registry.c +16 -0
  238. data/src/core/tsi/fake_transport_security.c +5 -4
  239. data/src/core/tsi/ssl_transport_security.c +71 -82
  240. data/src/core/tsi/ssl_transport_security.h +39 -61
  241. data/src/core/tsi/transport_security.c +83 -2
  242. data/src/core/tsi/transport_security.h +27 -2
  243. data/src/core/tsi/transport_security_adapter.c +236 -0
  244. data/src/core/tsi/transport_security_adapter.h +62 -0
  245. data/src/core/tsi/transport_security_interface.h +179 -66
  246. data/src/ruby/ext/grpc/extconf.rb +2 -1
  247. data/src/ruby/ext/grpc/rb_byte_buffer.c +8 -6
  248. data/src/ruby/ext/grpc/rb_call.c +56 -48
  249. data/src/ruby/ext/grpc/rb_call.h +3 -4
  250. data/src/ruby/ext/grpc/rb_call_credentials.c +23 -22
  251. data/src/ruby/ext/grpc/rb_channel.c +2 -3
  252. data/src/ruby/ext/grpc/rb_channel_args.c +11 -9
  253. data/src/ruby/ext/grpc/rb_channel_credentials.c +16 -12
  254. data/src/ruby/ext/grpc/rb_completion_queue.c +7 -9
  255. data/src/ruby/ext/grpc/rb_compression_options.c +7 -6
  256. data/src/ruby/ext/grpc/rb_event_thread.c +10 -12
  257. data/src/ruby/ext/grpc/rb_event_thread.h +1 -2
  258. data/src/ruby/ext/grpc/rb_grpc.c +11 -15
  259. data/src/ruby/ext/grpc/rb_grpc.h +2 -2
  260. data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +16 -6
  261. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +25 -10
  262. data/src/ruby/ext/grpc/rb_server.c +26 -28
  263. data/src/ruby/lib/grpc/grpc.rb +1 -1
  264. data/src/ruby/lib/grpc/version.rb +1 -1
  265. data/third_party/cares/config_linux/ares_config.h +36 -2
  266. data/third_party/zlib/adler32.c +14 -7
  267. data/third_party/zlib/compress.c +24 -18
  268. data/third_party/zlib/crc32.c +29 -12
  269. data/third_party/zlib/deflate.c +499 -303
  270. data/third_party/zlib/deflate.h +19 -16
  271. data/third_party/zlib/gzguts.h +16 -7
  272. data/third_party/zlib/gzlib.c +17 -14
  273. data/third_party/zlib/gzread.c +108 -48
  274. data/third_party/zlib/gzwrite.c +210 -122
  275. data/third_party/zlib/infback.c +2 -2
  276. data/third_party/zlib/inffast.c +34 -51
  277. data/third_party/zlib/inflate.c +86 -37
  278. data/third_party/zlib/inflate.h +7 -4
  279. data/third_party/zlib/inftrees.c +12 -14
  280. data/third_party/zlib/trees.c +38 -61
  281. data/third_party/zlib/uncompr.c +66 -32
  282. data/third_party/zlib/zconf.h +32 -9
  283. data/third_party/zlib/zlib.h +298 -154
  284. data/third_party/zlib/zutil.c +25 -24
  285. data/third_party/zlib/zutil.h +35 -17
  286. metadata +63 -30
@@ -31,12 +31,12 @@
31
31
  *
32
32
  */
33
33
 
34
- #ifndef GRPC_CORE_LIB_CHANNEL_HTTP_SERVER_FILTER_H
35
- #define GRPC_CORE_LIB_CHANNEL_HTTP_SERVER_FILTER_H
34
+ #ifndef GRPC_CORE_EXT_FILTERS_HTTP_SERVER_HTTP_SERVER_FILTER_H
35
+ #define GRPC_CORE_EXT_FILTERS_HTTP_SERVER_HTTP_SERVER_FILTER_H
36
36
 
37
37
  #include "src/core/lib/channel/channel_stack.h"
38
38
 
39
39
  /* Processes metadata on the client side for HTTP2 transports */
40
40
  extern const grpc_channel_filter grpc_http_server_filter;
41
41
 
42
- #endif /* GRPC_CORE_LIB_CHANNEL_HTTP_SERVER_FILTER_H */
42
+ #endif /* GRPC_CORE_EXT_FILTERS_HTTP_SERVER_HTTP_SERVER_FILTER_H */
@@ -47,32 +47,9 @@
47
47
  #include "src/core/lib/surface/call.h"
48
48
  #include "src/core/lib/surface/channel_init.h"
49
49
 
50
- static void destroy_lr_cost_context(void *c) {
51
- grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
52
- grpc_load_reporting_cost_context *cost_ctx = c;
53
- for (size_t i = 0; i < cost_ctx->values_count; ++i) {
54
- grpc_slice_unref_internal(&exec_ctx, cost_ctx->values[i]);
55
- }
56
- grpc_exec_ctx_finish(&exec_ctx);
57
- gpr_free(cost_ctx->values);
58
- gpr_free(cost_ctx);
59
- }
60
-
61
- void grpc_call_set_load_reporting_cost_context(
62
- grpc_call *call, grpc_load_reporting_cost_context *ctx) {
63
- grpc_call_context_set(call, GRPC_CONTEXT_LR_COST, ctx,
64
- destroy_lr_cost_context);
65
- }
66
-
67
50
  static bool is_load_reporting_enabled(const grpc_channel_args *a) {
68
- if (a == NULL) return false;
69
- for (size_t i = 0; i < a->num_args; i++) {
70
- if (0 == strcmp(a->args[i].key, GRPC_ARG_ENABLE_LOAD_REPORTING)) {
71
- return a->args[i].type == GRPC_ARG_INTEGER &&
72
- a->args[i].value.integer != 0;
73
- }
74
- }
75
- return false;
51
+ return grpc_channel_arg_get_bool(
52
+ grpc_channel_args_find(a, GRPC_ARG_ENABLE_LOAD_REPORTING), false);
76
53
  }
77
54
 
78
55
  static bool maybe_add_load_reporting_filter(grpc_exec_ctx *exec_ctx,
@@ -48,6 +48,8 @@
48
48
 
49
49
  typedef struct call_data {
50
50
  intptr_t id; /**< an id unique to the call */
51
+ bool have_trailing_md_string;
52
+ grpc_slice trailing_md_string;
51
53
  bool have_initial_md_string;
52
54
  grpc_slice initial_md_string;
53
55
  bool have_service_method;
@@ -140,6 +142,9 @@ static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
140
142
  if (calld->have_initial_md_string) {
141
143
  grpc_slice_unref_internal(exec_ctx, calld->initial_md_string);
142
144
  }
145
+ if (calld->have_trailing_md_string) {
146
+ grpc_slice_unref_internal(exec_ctx, calld->trailing_md_string);
147
+ }
143
148
  if (calld->have_service_method) {
144
149
  grpc_slice_unref_internal(exec_ctx, calld->service_method);
145
150
  }
@@ -183,6 +188,18 @@ static void destroy_channel_elem(grpc_exec_ctx *exec_ctx,
183
188
  */
184
189
  }
185
190
 
191
+ static grpc_filtered_mdelem lr_trailing_md_filter(grpc_exec_ctx *exec_ctx,
192
+ void *user_data,
193
+ grpc_mdelem md) {
194
+ grpc_call_element *elem = user_data;
195
+ call_data *calld = elem->call_data;
196
+ if (grpc_slice_eq(GRPC_MDKEY(md), GRPC_MDSTR_LB_COST_BIN)) {
197
+ calld->trailing_md_string = GRPC_MDVALUE(md);
198
+ return GRPC_FILTERED_REMOVE();
199
+ }
200
+ return GRPC_FILTERED_MDELEM(md);
201
+ }
202
+
186
203
  static void lr_start_transport_stream_op_batch(
187
204
  grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
188
205
  grpc_transport_stream_op_batch *op) {
@@ -190,13 +207,21 @@ static void lr_start_transport_stream_op_batch(
190
207
  call_data *calld = elem->call_data;
191
208
 
192
209
  if (op->recv_initial_metadata) {
210
+ /* substitute our callback for the higher callback */
193
211
  calld->recv_initial_metadata =
194
212
  op->payload->recv_initial_metadata.recv_initial_metadata;
195
- /* substitute our callback for the higher callback */
196
213
  calld->ops_recv_initial_metadata_ready =
197
214
  op->payload->recv_initial_metadata.recv_initial_metadata_ready;
198
215
  op->payload->recv_initial_metadata.recv_initial_metadata_ready =
199
216
  &calld->on_initial_md_ready;
217
+ } else if (op->send_trailing_metadata) {
218
+ GRPC_LOG_IF_ERROR(
219
+ "grpc_metadata_batch_filter",
220
+ grpc_metadata_batch_filter(
221
+ exec_ctx,
222
+ op->payload->send_trailing_metadata.send_trailing_metadata,
223
+ lr_trailing_md_filter, elem,
224
+ "LR trailing metadata filtering error"));
200
225
  }
201
226
  grpc_call_next_op(exec_ctx, elem, op);
202
227
 
@@ -47,6 +47,11 @@
47
47
  #define DEFAULT_MAX_CONNECTION_IDLE_MS INT_MAX
48
48
  #define MAX_CONNECTION_AGE_JITTER 0.1
49
49
 
50
+ #define MAX_CONNECTION_AGE_INTEGER_OPTIONS \
51
+ (grpc_integer_options) { DEFAULT_MAX_CONNECTION_AGE_MS, 1, INT_MAX }
52
+ #define MAX_CONNECTION_IDLE_INTEGER_OPTIONS \
53
+ (grpc_integer_options) { DEFAULT_MAX_CONNECTION_IDLE_MS, 1, INT_MAX }
54
+
50
55
  typedef struct channel_data {
51
56
  /* We take a reference to the channel stack for the timer callback */
52
57
  grpc_channel_stack* channel_stack;
@@ -315,8 +320,7 @@ static grpc_error* init_channel_elem(grpc_exec_ctx* exec_ctx,
315
320
  if (0 == strcmp(args->channel_args->args[i].key,
316
321
  GRPC_ARG_MAX_CONNECTION_AGE_MS)) {
317
322
  const int value = grpc_channel_arg_get_integer(
318
- &args->channel_args->args[i],
319
- (grpc_integer_options){DEFAULT_MAX_CONNECTION_AGE_MS, 1, INT_MAX});
323
+ &args->channel_args->args[i], MAX_CONNECTION_AGE_INTEGER_OPTIONS);
320
324
  chand->max_connection_age =
321
325
  value == INT_MAX
322
326
  ? gpr_inf_future(GPR_TIMESPAN)
@@ -334,8 +338,7 @@ static grpc_error* init_channel_elem(grpc_exec_ctx* exec_ctx,
334
338
  } else if (0 == strcmp(args->channel_args->args[i].key,
335
339
  GRPC_ARG_MAX_CONNECTION_IDLE_MS)) {
336
340
  const int value = grpc_channel_arg_get_integer(
337
- &args->channel_args->args[i],
338
- (grpc_integer_options){DEFAULT_MAX_CONNECTION_IDLE_MS, 1, INT_MAX});
341
+ &args->channel_args->args[i], MAX_CONNECTION_IDLE_INTEGER_OPTIONS);
339
342
  chand->max_connection_idle =
340
343
  value == INT_MAX ? gpr_inf_future(GPR_TIMESPAN)
341
344
  : gpr_time_from_millis(value, GPR_TIMESPAN);
@@ -412,16 +415,13 @@ static bool maybe_add_max_age_filter(grpc_exec_ctx* exec_ctx,
412
415
  void* arg) {
413
416
  const grpc_channel_args* channel_args =
414
417
  grpc_channel_stack_builder_get_channel_arguments(builder);
415
- const grpc_arg* a =
416
- grpc_channel_args_find(channel_args, GRPC_ARG_MAX_CONNECTION_AGE_MS);
417
- bool enable = false;
418
- if (a != NULL && a->type == GRPC_ARG_INTEGER && a->value.integer != INT_MAX) {
419
- enable = true;
420
- }
421
- a = grpc_channel_args_find(channel_args, GRPC_ARG_MAX_CONNECTION_IDLE_MS);
422
- if (a != NULL && a->type == GRPC_ARG_INTEGER && a->value.integer != INT_MAX) {
423
- enable = true;
424
- }
418
+ bool enable =
419
+ grpc_channel_arg_get_integer(
420
+ grpc_channel_args_find(channel_args, GRPC_ARG_MAX_CONNECTION_AGE_MS),
421
+ MAX_CONNECTION_AGE_INTEGER_OPTIONS) != INT_MAX &&
422
+ grpc_channel_arg_get_integer(
423
+ grpc_channel_args_find(channel_args, GRPC_ARG_MAX_CONNECTION_IDLE_MS),
424
+ MAX_CONNECTION_IDLE_INTEGER_OPTIONS) != INT_MAX;
425
425
  if (enable) {
426
426
  return grpc_channel_stack_builder_prepend_filter(
427
427
  builder, &grpc_max_age_filter, NULL, NULL);
@@ -29,7 +29,7 @@
29
29
  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
30
  //
31
31
 
32
- #include "src/core/lib/channel/message_size_filter.h"
32
+ #include "src/core/ext/filters/message_size/message_size_filter.h"
33
33
 
34
34
  #include <limits.h>
35
35
  #include <string.h>
@@ -40,7 +40,9 @@
40
40
  #include <grpc/support/string_util.h>
41
41
 
42
42
  #include "src/core/lib/channel/channel_args.h"
43
+ #include "src/core/lib/channel/channel_stack_builder.h"
43
44
  #include "src/core/lib/support/string.h"
45
+ #include "src/core/lib/surface/channel_init.h"
44
46
  #include "src/core/lib/transport/service_config.h"
45
47
 
46
48
  typedef struct message_size_limits {
@@ -48,19 +50,10 @@ typedef struct message_size_limits {
48
50
  int max_recv_size;
49
51
  } message_size_limits;
50
52
 
51
- static void* message_size_limits_copy(void* value) {
52
- void* new_value = gpr_malloc(sizeof(message_size_limits));
53
- memcpy(new_value, value, sizeof(message_size_limits));
54
- return new_value;
55
- }
56
-
57
53
  static void message_size_limits_free(grpc_exec_ctx* exec_ctx, void* value) {
58
54
  gpr_free(value);
59
55
  }
60
56
 
61
- static const grpc_slice_hash_table_vtable message_size_limits_vtable = {
62
- message_size_limits_free, message_size_limits_copy};
63
-
64
57
  static void* message_size_limits_create_from_json(const grpc_json* json) {
65
58
  int max_request_message_bytes = -1;
66
59
  int max_response_message_bytes = -1;
@@ -89,8 +82,7 @@ static void* message_size_limits_create_from_json(const grpc_json* json) {
89
82
  }
90
83
 
91
84
  typedef struct call_data {
92
- int max_send_size;
93
- int max_recv_size;
85
+ message_size_limits limits;
94
86
  // Receive closures are chained: we inject this closure as the
95
87
  // recv_message_ready up-call on transport_stream_op, and remember to
96
88
  // call our next_recv_message_ready member after handling it.
@@ -102,8 +94,7 @@ typedef struct call_data {
102
94
  } call_data;
103
95
 
104
96
  typedef struct channel_data {
105
- int max_send_size;
106
- int max_recv_size;
97
+ message_size_limits limits;
107
98
  // Maps path names to message_size_limits structs.
108
99
  grpc_slice_hash_table* method_limit_table;
109
100
  } channel_data;
@@ -114,12 +105,12 @@ static void recv_message_ready(grpc_exec_ctx* exec_ctx, void* user_data,
114
105
  grpc_error* error) {
115
106
  grpc_call_element* elem = user_data;
116
107
  call_data* calld = elem->call_data;
117
- if (*calld->recv_message != NULL && calld->max_recv_size >= 0 &&
118
- (*calld->recv_message)->length > (size_t)calld->max_recv_size) {
108
+ if (*calld->recv_message != NULL && calld->limits.max_recv_size >= 0 &&
109
+ (*calld->recv_message)->length > (size_t)calld->limits.max_recv_size) {
119
110
  char* message_string;
120
111
  gpr_asprintf(&message_string,
121
112
  "Received message larger than max (%u vs. %d)",
122
- (*calld->recv_message)->length, calld->max_recv_size);
113
+ (*calld->recv_message)->length, calld->limits.max_recv_size);
123
114
  grpc_error* new_error = grpc_error_set_int(
124
115
  GRPC_ERROR_CREATE_FROM_COPIED_STRING(message_string),
125
116
  GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_RESOURCE_EXHAUSTED);
@@ -130,6 +121,8 @@ static void recv_message_ready(grpc_exec_ctx* exec_ctx, void* user_data,
130
121
  GRPC_ERROR_UNREF(new_error);
131
122
  }
132
123
  gpr_free(message_string);
124
+ } else {
125
+ GRPC_ERROR_REF(error);
133
126
  }
134
127
  // Invoke the next callback.
135
128
  grpc_closure_run(exec_ctx, calld->next_recv_message_ready, error);
@@ -141,13 +134,13 @@ static void start_transport_stream_op_batch(
141
134
  grpc_transport_stream_op_batch* op) {
142
135
  call_data* calld = elem->call_data;
143
136
  // Check max send message size.
144
- if (op->send_message && calld->max_send_size >= 0 &&
137
+ if (op->send_message && calld->limits.max_send_size >= 0 &&
145
138
  op->payload->send_message.send_message->length >
146
- (size_t)calld->max_send_size) {
139
+ (size_t)calld->limits.max_send_size) {
147
140
  char* message_string;
148
141
  gpr_asprintf(&message_string, "Sent message larger than max (%u vs. %d)",
149
142
  op->payload->send_message.send_message->length,
150
- calld->max_send_size);
143
+ calld->limits.max_send_size);
151
144
  grpc_transport_stream_op_batch_finish_with_failure(
152
145
  exec_ctx, op,
153
146
  grpc_error_set_int(GRPC_ERROR_CREATE_FROM_COPIED_STRING(message_string),
@@ -180,21 +173,20 @@ static grpc_error* init_call_elem(grpc_exec_ctx* exec_ctx,
180
173
  // Note: Per-method config is only available on the client, so we
181
174
  // apply the max request size to the send limit and the max response
182
175
  // size to the receive limit.
183
- calld->max_send_size = chand->max_send_size;
184
- calld->max_recv_size = chand->max_recv_size;
176
+ calld->limits = chand->limits;
185
177
  if (chand->method_limit_table != NULL) {
186
178
  message_size_limits* limits = grpc_method_config_table_get(
187
179
  exec_ctx, chand->method_limit_table, args->path);
188
180
  if (limits != NULL) {
189
181
  if (limits->max_send_size >= 0 &&
190
- (limits->max_send_size < calld->max_send_size ||
191
- calld->max_send_size < 0)) {
192
- calld->max_send_size = limits->max_send_size;
182
+ (limits->max_send_size < calld->limits.max_send_size ||
183
+ calld->limits.max_send_size < 0)) {
184
+ calld->limits.max_send_size = limits->max_send_size;
193
185
  }
194
186
  if (limits->max_recv_size >= 0 &&
195
- (limits->max_recv_size < calld->max_recv_size ||
196
- calld->max_recv_size < 0)) {
197
- calld->max_recv_size = limits->max_recv_size;
187
+ (limits->max_recv_size < calld->limits.max_recv_size ||
188
+ calld->limits.max_recv_size < 0)) {
189
+ calld->limits.max_recv_size = limits->max_recv_size;
198
190
  }
199
191
  }
200
192
  }
@@ -206,30 +198,45 @@ static void destroy_call_elem(grpc_exec_ctx* exec_ctx, grpc_call_element* elem,
206
198
  const grpc_call_final_info* final_info,
207
199
  grpc_closure* ignored) {}
208
200
 
201
+ static int default_size(const grpc_channel_args* args,
202
+ int without_minimal_stack) {
203
+ if (grpc_channel_args_want_minimal_stack(args)) {
204
+ return -1;
205
+ }
206
+ return without_minimal_stack;
207
+ }
208
+
209
+ message_size_limits get_message_size_limits(
210
+ const grpc_channel_args* channel_args) {
211
+ message_size_limits lim;
212
+ lim.max_send_size =
213
+ default_size(channel_args, GRPC_DEFAULT_MAX_SEND_MESSAGE_LENGTH);
214
+ lim.max_recv_size =
215
+ default_size(channel_args, GRPC_DEFAULT_MAX_RECV_MESSAGE_LENGTH);
216
+ for (size_t i = 0; i < channel_args->num_args; ++i) {
217
+ if (strcmp(channel_args->args[i].key, GRPC_ARG_MAX_SEND_MESSAGE_LENGTH) ==
218
+ 0) {
219
+ const grpc_integer_options options = {lim.max_send_size, -1, INT_MAX};
220
+ lim.max_send_size =
221
+ grpc_channel_arg_get_integer(&channel_args->args[i], options);
222
+ }
223
+ if (strcmp(channel_args->args[i].key,
224
+ GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH) == 0) {
225
+ const grpc_integer_options options = {lim.max_recv_size, -1, INT_MAX};
226
+ lim.max_recv_size =
227
+ grpc_channel_arg_get_integer(&channel_args->args[i], options);
228
+ }
229
+ }
230
+ return lim;
231
+ }
232
+
209
233
  // Constructor for channel_data.
210
234
  static grpc_error* init_channel_elem(grpc_exec_ctx* exec_ctx,
211
235
  grpc_channel_element* elem,
212
236
  grpc_channel_element_args* args) {
213
237
  GPR_ASSERT(!args->is_last);
214
238
  channel_data* chand = elem->channel_data;
215
- chand->max_send_size = GRPC_DEFAULT_MAX_SEND_MESSAGE_LENGTH;
216
- chand->max_recv_size = GRPC_DEFAULT_MAX_RECV_MESSAGE_LENGTH;
217
- for (size_t i = 0; i < args->channel_args->num_args; ++i) {
218
- if (strcmp(args->channel_args->args[i].key,
219
- GRPC_ARG_MAX_SEND_MESSAGE_LENGTH) == 0) {
220
- const grpc_integer_options options = {
221
- GRPC_DEFAULT_MAX_SEND_MESSAGE_LENGTH, -1, INT_MAX};
222
- chand->max_send_size =
223
- grpc_channel_arg_get_integer(&args->channel_args->args[i], options);
224
- }
225
- if (strcmp(args->channel_args->args[i].key,
226
- GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH) == 0) {
227
- const grpc_integer_options options = {
228
- GRPC_DEFAULT_MAX_RECV_MESSAGE_LENGTH, -1, INT_MAX};
229
- chand->max_recv_size =
230
- grpc_channel_arg_get_integer(&args->channel_args->args[i], options);
231
- }
232
- }
239
+ chand->limits = get_message_size_limits(args->channel_args);
233
240
  // Get method config table from channel args.
234
241
  const grpc_arg* channel_arg =
235
242
  grpc_channel_args_find(args->channel_args, GRPC_ARG_SERVICE_CONFIG);
@@ -241,7 +248,7 @@ static grpc_error* init_channel_elem(grpc_exec_ctx* exec_ctx,
241
248
  chand->method_limit_table =
242
249
  grpc_service_config_create_method_config_table(
243
250
  exec_ctx, service_config, message_size_limits_create_from_json,
244
- &message_size_limits_vtable);
251
+ message_size_limits_free);
245
252
  grpc_service_config_destroy(service_config);
246
253
  }
247
254
  }
@@ -268,3 +275,40 @@ const grpc_channel_filter grpc_message_size_filter = {
268
275
  grpc_call_next_get_peer,
269
276
  grpc_channel_next_get_info,
270
277
  "message_size"};
278
+
279
+ static bool maybe_add_message_size_filter(grpc_exec_ctx* exec_ctx,
280
+ grpc_channel_stack_builder* builder,
281
+ void* arg) {
282
+ const grpc_channel_args* channel_args =
283
+ grpc_channel_stack_builder_get_channel_arguments(builder);
284
+ bool enable = false;
285
+ message_size_limits lim = get_message_size_limits(channel_args);
286
+ if (lim.max_send_size != -1 || lim.max_recv_size != -1) {
287
+ enable = true;
288
+ }
289
+ const grpc_arg* a =
290
+ grpc_channel_args_find(channel_args, GRPC_ARG_SERVICE_CONFIG);
291
+ if (a != NULL) {
292
+ enable = true;
293
+ }
294
+ if (enable) {
295
+ return grpc_channel_stack_builder_prepend_filter(
296
+ builder, &grpc_message_size_filter, NULL, NULL);
297
+ } else {
298
+ return true;
299
+ }
300
+ }
301
+
302
+ void grpc_message_size_filter_init(void) {
303
+ grpc_channel_init_register_stage(GRPC_CLIENT_SUBCHANNEL,
304
+ GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
305
+ maybe_add_message_size_filter, NULL);
306
+ grpc_channel_init_register_stage(GRPC_CLIENT_DIRECT_CHANNEL,
307
+ GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
308
+ maybe_add_message_size_filter, NULL);
309
+ grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL,
310
+ GRPC_CHANNEL_INIT_BUILTIN_PRIORITY,
311
+ maybe_add_message_size_filter, NULL);
312
+ }
313
+
314
+ void grpc_message_size_filter_shutdown(void) {}
@@ -29,11 +29,11 @@
29
29
  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
30
  //
31
31
 
32
- #ifndef GRPC_CORE_LIB_CHANNEL_MESSAGE_SIZE_FILTER_H
33
- #define GRPC_CORE_LIB_CHANNEL_MESSAGE_SIZE_FILTER_H
32
+ #ifndef GRPC_CORE_EXT_FILTERS_MESSAGE_SIZE_MESSAGE_SIZE_FILTER_H
33
+ #define GRPC_CORE_EXT_FILTERS_MESSAGE_SIZE_MESSAGE_SIZE_FILTER_H
34
34
 
35
35
  #include "src/core/lib/channel/channel_stack.h"
36
36
 
37
37
  extern const grpc_channel_filter grpc_message_size_filter;
38
38
 
39
- #endif /* GRPC_CORE_LIB_CHANNEL_MESSAGE_SIZE_FILTER_H */
39
+ #endif /* GRPC_CORE_EXT_FILTERS_MESSAGE_SIZE_MESSAGE_SIZE_FILTER_H */
@@ -0,0 +1,223 @@
1
+ //
2
+ // Copyright 2017, Google Inc.
3
+ // All rights reserved.
4
+ //
5
+ // Redistribution and use in source and binary forms, with or without
6
+ // modification, are permitted provided that the following conditions are
7
+ // met:
8
+ //
9
+ // * Redistributions of source code must retain the above copyright
10
+ // notice, this list of conditions and the following disclaimer.
11
+ // * Redistributions in binary form must reproduce the above
12
+ // copyright notice, this list of conditions and the following disclaimer
13
+ // in the documentation and/or other materials provided with the
14
+ // distribution.
15
+ // * Neither the name of Google Inc. nor the names of its
16
+ // contributors may be used to endorse or promote products derived from
17
+ // this software without specific prior written permission.
18
+ //
19
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20
+ // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21
+ // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22
+ // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23
+ // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24
+ // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25
+ // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26
+ // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27
+ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28
+ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+ //
31
+
32
+ #include "src/core/ext/filters/workarounds/workaround_cronet_compression_filter.h"
33
+
34
+ #include <string.h>
35
+
36
+ #include <grpc/support/alloc.h>
37
+
38
+ #include "src/core/ext/filters/workarounds/workaround_utils.h"
39
+ #include "src/core/lib/channel/channel_stack_builder.h"
40
+ #include "src/core/lib/surface/channel_init.h"
41
+ #include "src/core/lib/transport/metadata.h"
42
+
43
+ typedef struct call_data {
44
+ // Receive closures are chained: we inject this closure as the
45
+ // recv_initial_metadata_ready up-call on transport_stream_op, and remember to
46
+ // call our next_recv_initial_metadata_ready member after handling it.
47
+ grpc_closure recv_initial_metadata_ready;
48
+ // Used by recv_initial_metadata_ready.
49
+ grpc_metadata_batch* recv_initial_metadata;
50
+ // Original recv_initial_metadata_ready callback, invoked after our own.
51
+ grpc_closure* next_recv_initial_metadata_ready;
52
+
53
+ // Marks whether the workaround is active
54
+ bool workaround_active;
55
+ } call_data;
56
+
57
+ // Find the user agent metadata element in the batch
58
+ static bool get_user_agent_mdelem(const grpc_metadata_batch* batch,
59
+ grpc_mdelem* md) {
60
+ if (batch->idx.named.user_agent != NULL) {
61
+ *md = batch->idx.named.user_agent->md;
62
+ return true;
63
+ }
64
+ return false;
65
+ }
66
+
67
+ // Callback invoked when we receive an initial metadata.
68
+ static void recv_initial_metadata_ready(grpc_exec_ctx* exec_ctx,
69
+ void* user_data, grpc_error* error) {
70
+ grpc_call_element* elem = user_data;
71
+ call_data* calld = elem->call_data;
72
+
73
+ if (GRPC_ERROR_NONE == error) {
74
+ grpc_mdelem md;
75
+ if (get_user_agent_mdelem(calld->recv_initial_metadata, &md)) {
76
+ grpc_workaround_user_agent_md* user_agent_md = grpc_parse_user_agent(md);
77
+ if (user_agent_md
78
+ ->workaround_active[GRPC_WORKAROUND_ID_CRONET_COMPRESSION]) {
79
+ calld->workaround_active = true;
80
+ }
81
+ }
82
+ }
83
+
84
+ // Invoke the next callback.
85
+ grpc_closure_run(exec_ctx, calld->next_recv_initial_metadata_ready,
86
+ GRPC_ERROR_REF(error));
87
+ }
88
+
89
+ // Start transport stream op.
90
+ static void start_transport_stream_op_batch(
91
+ grpc_exec_ctx* exec_ctx, grpc_call_element* elem,
92
+ grpc_transport_stream_op_batch* op) {
93
+ call_data* calld = elem->call_data;
94
+
95
+ // Inject callback for receiving initial metadata
96
+ if (op->recv_initial_metadata) {
97
+ calld->next_recv_initial_metadata_ready =
98
+ op->payload->recv_initial_metadata.recv_initial_metadata_ready;
99
+ op->payload->recv_initial_metadata.recv_initial_metadata_ready =
100
+ &calld->recv_initial_metadata_ready;
101
+ calld->recv_initial_metadata =
102
+ op->payload->recv_initial_metadata.recv_initial_metadata;
103
+ }
104
+
105
+ if (op->send_message) {
106
+ /* Send message happens after client's user-agent (initial metadata) is
107
+ * received, so workaround_active must be set already */
108
+ if (calld->workaround_active) {
109
+ op->payload->send_message.send_message->flags |= GRPC_WRITE_NO_COMPRESS;
110
+ }
111
+ }
112
+
113
+ // Chain to the next filter.
114
+ grpc_call_next_op(exec_ctx, elem, op);
115
+ }
116
+
117
+ // Constructor for call_data.
118
+ static grpc_error* init_call_elem(grpc_exec_ctx* exec_ctx,
119
+ grpc_call_element* elem,
120
+ const grpc_call_element_args* args) {
121
+ call_data* calld = elem->call_data;
122
+ calld->next_recv_initial_metadata_ready = NULL;
123
+ calld->workaround_active = false;
124
+ grpc_closure_init(&calld->recv_initial_metadata_ready,
125
+ recv_initial_metadata_ready, elem,
126
+ grpc_schedule_on_exec_ctx);
127
+ return GRPC_ERROR_NONE;
128
+ }
129
+
130
+ // Destructor for call_data.
131
+ static void destroy_call_elem(grpc_exec_ctx* exec_ctx, grpc_call_element* elem,
132
+ const grpc_call_final_info* final_info,
133
+ grpc_closure* ignored) {}
134
+
135
+ // Constructor for channel_data.
136
+ static grpc_error* init_channel_elem(grpc_exec_ctx* exec_ctx,
137
+ grpc_channel_element* elem,
138
+ grpc_channel_element_args* args) {
139
+ return GRPC_ERROR_NONE;
140
+ }
141
+
142
+ // Destructor for channel_data.
143
+ static void destroy_channel_elem(grpc_exec_ctx* exec_ctx,
144
+ grpc_channel_element* elem) {}
145
+
146
+ // Parse the user agent
147
+ static bool parse_user_agent(grpc_mdelem md) {
148
+ const char grpc_objc_specifier[] = "grpc-objc/";
149
+ const size_t grpc_objc_specifier_len = sizeof(grpc_objc_specifier) - 1;
150
+ const char cronet_specifier[] = "cronet_http";
151
+ const size_t cronet_specifier_len = sizeof(cronet_specifier) - 1;
152
+
153
+ char* user_agent_str = grpc_slice_to_c_string(GRPC_MDVALUE(md));
154
+ bool grpc_objc_specifier_seen = false;
155
+ bool cronet_specifier_seen = false;
156
+ char *major_version_str = user_agent_str, *minor_version_str;
157
+ long major_version, minor_version;
158
+
159
+ char* head = strtok(user_agent_str, " ");
160
+ while (head != NULL) {
161
+ if (!grpc_objc_specifier_seen &&
162
+ 0 == strncmp(head, grpc_objc_specifier, grpc_objc_specifier_len)) {
163
+ major_version_str = head + grpc_objc_specifier_len;
164
+ grpc_objc_specifier_seen = true;
165
+ } else if (grpc_objc_specifier_seen &&
166
+ 0 == strncmp(head, cronet_specifier, cronet_specifier_len)) {
167
+ cronet_specifier_seen = true;
168
+ break;
169
+ }
170
+
171
+ head = strtok(NULL, " ");
172
+ }
173
+ if (grpc_objc_specifier_seen) {
174
+ major_version_str = strtok(major_version_str, ".");
175
+ minor_version_str = strtok(NULL, ".");
176
+ major_version = atol(major_version_str);
177
+ minor_version = atol(minor_version_str);
178
+ }
179
+
180
+ gpr_free(user_agent_str);
181
+ return (grpc_objc_specifier_seen && cronet_specifier_seen &&
182
+ (major_version < 1 || (major_version == 1 && minor_version <= 3)));
183
+ }
184
+
185
+ const grpc_channel_filter grpc_workaround_cronet_compression_filter = {
186
+ start_transport_stream_op_batch,
187
+ grpc_channel_next_op,
188
+ sizeof(call_data),
189
+ init_call_elem,
190
+ grpc_call_stack_ignore_set_pollset_or_pollset_set,
191
+ destroy_call_elem,
192
+ 0,
193
+ init_channel_elem,
194
+ destroy_channel_elem,
195
+ grpc_call_next_get_peer,
196
+ grpc_channel_next_get_info,
197
+ "workaround_cronet_compression"};
198
+
199
+ static bool register_workaround_cronet_compression(
200
+ grpc_exec_ctx* exec_ctx, grpc_channel_stack_builder* builder, void* arg) {
201
+ const grpc_channel_args* channel_args =
202
+ grpc_channel_stack_builder_get_channel_arguments(builder);
203
+ const grpc_arg* a = grpc_channel_args_find(
204
+ channel_args, GRPC_ARG_WORKAROUND_CRONET_COMPRESSION);
205
+ if (a == NULL) {
206
+ return true;
207
+ }
208
+ if (grpc_channel_arg_get_bool(a, false) == false) {
209
+ return true;
210
+ }
211
+ return grpc_channel_stack_builder_prepend_filter(
212
+ builder, &grpc_workaround_cronet_compression_filter, NULL, NULL);
213
+ }
214
+
215
+ void grpc_workaround_cronet_compression_filter_init(void) {
216
+ grpc_channel_init_register_stage(
217
+ GRPC_SERVER_CHANNEL, GRPC_WORKAROUND_PRIORITY_HIGH,
218
+ register_workaround_cronet_compression, NULL);
219
+ grpc_register_workaround(GRPC_WORKAROUND_ID_CRONET_COMPRESSION,
220
+ parse_user_agent);
221
+ }
222
+
223
+ void grpc_workaround_cronet_compression_filter_shutdown(void) {}