grpc 1.36.0 → 1.37.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 (221) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +65 -37
  3. data/include/grpc/grpc.h +15 -1
  4. data/include/grpc/impl/codegen/port_platform.h +2 -0
  5. data/src/core/ext/filters/client_channel/client_channel.cc +327 -305
  6. data/src/core/ext/filters/client_channel/client_channel_factory.h +2 -1
  7. data/src/core/ext/filters/client_channel/config_selector.h +8 -0
  8. data/src/core/ext/filters/client_channel/dynamic_filters.cc +9 -4
  9. data/src/core/ext/filters/client_channel/global_subchannel_pool.cc +24 -142
  10. data/src/core/ext/filters/client_channel/global_subchannel_pool.h +15 -10
  11. data/src/core/ext/filters/client_channel/lb_policy.cc +3 -0
  12. data/src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.cc +23 -0
  13. data/src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.h +27 -0
  14. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_impl.cc +7 -22
  15. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_manager.cc +1 -1
  16. data/src/core/ext/filters/client_channel/lb_policy/xds/xds_cluster_resolver.cc +2 -2
  17. data/src/core/ext/filters/client_channel/local_subchannel_pool.cc +27 -67
  18. data/src/core/ext/filters/client_channel/local_subchannel_pool.h +10 -9
  19. data/src/core/ext/filters/client_channel/resolver.cc +3 -0
  20. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc +2 -2
  21. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_windows.cc +3 -1
  22. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc +5 -9
  23. data/src/core/ext/filters/client_channel/resolver/google_c2p/google_c2p_resolver.cc +18 -3
  24. data/src/core/ext/filters/client_channel/resolver/xds/xds_resolver.cc +295 -91
  25. data/src/core/ext/filters/client_channel/server_address.cc +3 -0
  26. data/src/core/ext/filters/client_channel/subchannel.cc +69 -146
  27. data/src/core/ext/filters/client_channel/subchannel.h +63 -95
  28. data/src/core/ext/filters/client_channel/subchannel_pool_interface.cc +16 -2
  29. data/src/core/ext/filters/client_channel/subchannel_pool_interface.h +10 -8
  30. data/src/core/ext/filters/client_idle/client_idle_filter.cc +1 -1
  31. data/src/core/ext/filters/fault_injection/fault_injection_filter.cc +495 -0
  32. data/src/core/ext/filters/fault_injection/fault_injection_filter.h +39 -0
  33. data/src/core/ext/filters/fault_injection/service_config_parser.cc +189 -0
  34. data/src/core/ext/filters/fault_injection/service_config_parser.h +85 -0
  35. data/src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc +1 -1
  36. data/src/core/ext/transport/chttp2/client/chttp2_connector.cc +1 -1
  37. data/src/core/ext/transport/chttp2/client/insecure/channel_create.cc +3 -2
  38. data/src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc +1 -1
  39. data/src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc +3 -2
  40. data/src/core/ext/transport/chttp2/server/chttp2_server.cc +457 -170
  41. data/src/core/ext/transport/chttp2/server/insecure/server_chttp2_posix.cc +1 -1
  42. data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +39 -7
  43. data/src/core/ext/transport/chttp2/transport/chttp2_transport.h +12 -1
  44. data/src/core/ext/transport/chttp2/transport/frame_data.cc +5 -1
  45. data/src/core/ext/transport/chttp2/transport/hpack_encoder.cc +1 -1
  46. data/src/core/ext/transport/chttp2/transport/internal.h +1 -0
  47. data/src/core/ext/upb-generated/envoy/admin/v3/config_dump.upb.c +406 -0
  48. data/src/core/ext/upb-generated/envoy/admin/v3/config_dump.upb.h +1459 -0
  49. data/src/core/ext/upb-generated/envoy/config/bootstrap/v3/bootstrap.upb.c +350 -0
  50. data/src/core/ext/upb-generated/envoy/config/bootstrap/v3/bootstrap.upb.h +1348 -0
  51. data/src/core/ext/upb-generated/envoy/config/core/v3/protocol.upb.c +6 -0
  52. data/src/core/ext/upb-generated/envoy/config/core/v3/protocol.upb.h +25 -0
  53. data/src/core/ext/upb-generated/envoy/config/metrics/v3/stats.upb.c +144 -0
  54. data/src/core/ext/upb-generated/envoy/config/metrics/v3/stats.upb.h +488 -0
  55. data/src/core/ext/upb-generated/envoy/config/overload/v3/overload.upb.c +141 -0
  56. data/src/core/ext/upb-generated/envoy/config/overload/v3/overload.upb.h +452 -0
  57. data/src/core/ext/upb-generated/envoy/config/route/v3/route_components.upb.c +15 -0
  58. data/src/core/ext/upb-generated/envoy/config/route/v3/route_components.upb.h +44 -0
  59. data/src/core/ext/upb-generated/envoy/extensions/filters/common/fault/v3/fault.upb.c +79 -0
  60. data/src/core/ext/upb-generated/envoy/extensions/filters/common/fault/v3/fault.upb.h +268 -0
  61. data/src/core/ext/upb-generated/envoy/extensions/filters/http/fault/v3/fault.upb.c +78 -0
  62. data/src/core/ext/upb-generated/envoy/extensions/filters/http/fault/v3/fault.upb.h +281 -0
  63. data/src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.c +41 -0
  64. data/src/core/ext/upb-generated/envoy/extensions/filters/http/router/v3/router.upb.h +113 -0
  65. data/src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.c +6 -5
  66. data/src/core/ext/upb-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upb.h +13 -9
  67. data/src/core/ext/upb-generated/envoy/service/status/v3/csds.upb.c +93 -0
  68. data/src/core/ext/upb-generated/envoy/service/status/v3/csds.upb.h +323 -0
  69. data/src/core/ext/upb-generated/envoy/type/matcher/v3/node.upb.c +36 -0
  70. data/src/core/ext/upb-generated/envoy/type/matcher/v3/node.upb.h +90 -0
  71. data/src/core/ext/upb-generated/envoy/type/matcher/v3/struct.upb.c +46 -0
  72. data/src/core/ext/upb-generated/envoy/type/matcher/v3/struct.upb.h +124 -0
  73. data/src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.c +33 -0
  74. data/src/core/ext/upb-generated/udpa/type/v1/typed_struct.upb.h +77 -0
  75. data/src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.c +354 -0
  76. data/src/core/ext/upbdefs-generated/envoy/admin/v3/config_dump.upbdefs.h +140 -0
  77. data/src/core/ext/upbdefs-generated/envoy/config/bootstrap/v3/bootstrap.upbdefs.c +383 -0
  78. data/src/core/ext/upbdefs-generated/envoy/config/bootstrap/v3/bootstrap.upbdefs.h +115 -0
  79. data/src/core/ext/upbdefs-generated/envoy/config/core/v3/protocol.upbdefs.c +10 -7
  80. data/src/core/ext/upbdefs-generated/envoy/config/core/v3/protocol.upbdefs.h +5 -0
  81. data/src/core/ext/upbdefs-generated/envoy/config/metrics/v3/stats.upbdefs.c +141 -0
  82. data/src/core/ext/upbdefs-generated/envoy/config/metrics/v3/stats.upbdefs.h +70 -0
  83. data/src/core/ext/upbdefs-generated/envoy/config/overload/v3/overload.upbdefs.c +141 -0
  84. data/src/core/ext/upbdefs-generated/envoy/config/overload/v3/overload.upbdefs.h +70 -0
  85. data/src/core/ext/upbdefs-generated/envoy/config/route/v3/route_components.upbdefs.c +13 -7
  86. data/src/core/ext/upbdefs-generated/envoy/config/route/v3/route_components.upbdefs.h +5 -0
  87. data/src/core/ext/upbdefs-generated/envoy/extensions/filters/common/fault/v3/fault.upbdefs.c +102 -0
  88. data/src/core/ext/upbdefs-generated/envoy/extensions/filters/common/fault/v3/fault.upbdefs.h +55 -0
  89. data/src/core/ext/upbdefs-generated/envoy/extensions/filters/http/fault/v3/fault.upbdefs.c +120 -0
  90. data/src/core/ext/upbdefs-generated/envoy/extensions/filters/http/fault/v3/fault.upbdefs.h +45 -0
  91. data/src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.c +76 -0
  92. data/src/core/ext/upbdefs-generated/envoy/extensions/filters/http/router/v3/router.upbdefs.h +35 -0
  93. data/src/core/ext/upbdefs-generated/envoy/extensions/filters/network/http_connection_manager/v3/http_connection_manager.upbdefs.c +21 -20
  94. data/src/core/ext/upbdefs-generated/envoy/service/status/v3/csds.upbdefs.c +130 -0
  95. data/src/core/ext/upbdefs-generated/envoy/service/status/v3/csds.upbdefs.h +50 -0
  96. data/src/core/ext/upbdefs-generated/envoy/type/matcher/v3/node.upbdefs.c +56 -0
  97. data/src/core/ext/upbdefs-generated/envoy/type/matcher/v3/node.upbdefs.h +35 -0
  98. data/src/core/ext/upbdefs-generated/envoy/type/matcher/v3/struct.upbdefs.c +63 -0
  99. data/src/core/ext/upbdefs-generated/envoy/type/matcher/v3/struct.upbdefs.h +40 -0
  100. data/src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.c +44 -0
  101. data/src/core/ext/upbdefs-generated/udpa/type/v1/typed_struct.upbdefs.h +35 -0
  102. data/src/core/ext/xds/xds_api.cc +1591 -279
  103. data/src/core/ext/xds/xds_api.h +279 -39
  104. data/src/core/ext/xds/xds_bootstrap.cc +21 -5
  105. data/src/core/ext/xds/xds_bootstrap.h +5 -1
  106. data/src/core/ext/xds/xds_client.cc +168 -23
  107. data/src/core/ext/xds/xds_client.h +26 -0
  108. data/src/core/ext/xds/xds_client_stats.h +2 -2
  109. data/src/core/ext/xds/xds_http_fault_filter.cc +226 -0
  110. data/src/core/ext/xds/xds_http_fault_filter.h +63 -0
  111. data/src/core/ext/xds/xds_http_filters.cc +114 -0
  112. data/src/core/ext/xds/xds_http_filters.h +130 -0
  113. data/src/core/ext/xds/xds_server_config_fetcher.cc +391 -126
  114. data/src/core/lib/channel/channel_stack.cc +12 -0
  115. data/src/core/lib/channel/channel_stack.h +7 -0
  116. data/src/core/lib/channel/channelz.cc +92 -4
  117. data/src/core/lib/channel/channelz.h +30 -1
  118. data/src/core/lib/channel/channelz_registry.cc +14 -0
  119. data/src/core/lib/channel/handshaker.cc +0 -39
  120. data/src/core/lib/channel/handshaker.h +0 -17
  121. data/src/core/lib/channel/status_util.cc +12 -2
  122. data/src/core/lib/channel/status_util.h +5 -0
  123. data/src/core/lib/gpr/sync_abseil.cc +3 -6
  124. data/src/core/lib/gpr/sync_windows.cc +2 -2
  125. data/src/core/lib/gprpp/atomic.h +3 -3
  126. data/src/core/lib/gprpp/dual_ref_counted.h +3 -3
  127. data/src/core/lib/gprpp/ref_counted_ptr.h +2 -0
  128. data/src/core/lib/gprpp/thd.h +1 -1
  129. data/src/core/lib/iomgr/buffer_list.h +1 -1
  130. data/src/core/lib/iomgr/cfstream_handle.cc +2 -2
  131. data/src/core/lib/iomgr/error.h +1 -1
  132. data/src/core/lib/iomgr/ev_apple.cc +1 -1
  133. data/src/core/lib/iomgr/ev_epoll1_linux.cc +3 -3
  134. data/src/core/lib/iomgr/ev_posix.cc +3 -3
  135. data/src/core/lib/iomgr/exec_ctx.cc +6 -2
  136. data/src/core/lib/iomgr/resource_quota.cc +1 -1
  137. data/src/core/lib/iomgr/sockaddr_utils.cc +120 -0
  138. data/src/core/lib/iomgr/sockaddr_utils.h +25 -0
  139. data/src/core/lib/iomgr/tcp_posix.cc +1 -4
  140. data/src/core/lib/iomgr/tcp_uv.cc +2 -2
  141. data/src/core/lib/iomgr/timer_generic.cc +2 -2
  142. data/src/core/lib/iomgr/timer_manager.cc +1 -1
  143. data/src/core/lib/iomgr/wakeup_fd_nospecial.cc +1 -1
  144. data/src/core/lib/{security/authorization → matchers}/matchers.cc +8 -8
  145. data/src/core/lib/{security/authorization → matchers}/matchers.h +14 -12
  146. data/src/core/lib/security/security_connector/ssl_utils.cc +6 -4
  147. data/src/core/lib/security/security_connector/tls/tls_security_connector.cc +6 -0
  148. data/src/core/lib/security/transport/security_handshaker.cc +32 -2
  149. data/src/core/lib/slice/slice_intern.cc +6 -7
  150. data/src/core/lib/surface/channel.h +3 -3
  151. data/src/core/lib/surface/completion_queue.cc +1 -1
  152. data/src/core/lib/surface/lame_client.cc +38 -19
  153. data/src/core/lib/surface/lame_client.h +4 -3
  154. data/src/core/lib/surface/server.cc +40 -33
  155. data/src/core/lib/surface/server.h +74 -15
  156. data/src/core/lib/surface/version.cc +1 -1
  157. data/src/core/lib/transport/metadata_batch.cc +27 -0
  158. data/src/core/lib/transport/metadata_batch.h +14 -0
  159. data/src/core/plugin_registry/grpc_plugin_registry.cc +6 -0
  160. data/src/core/tsi/alts/handshaker/alts_handshaker_client.cc +1 -4
  161. data/src/core/tsi/alts/handshaker/alts_tsi_handshaker.h +1 -1
  162. data/src/core/tsi/alts/handshaker/transport_security_common_api.cc +1 -3
  163. data/src/core/tsi/fake_transport_security.cc +10 -1
  164. data/src/ruby/ext/grpc/extconf.rb +9 -1
  165. data/src/ruby/ext/grpc/rb_channel.c +10 -1
  166. data/src/ruby/ext/grpc/rb_channel_credentials.c +11 -1
  167. data/src/ruby/ext/grpc/rb_channel_credentials.h +4 -0
  168. data/src/ruby/ext/grpc/rb_compression_options.c +1 -1
  169. data/src/ruby/ext/grpc/rb_enable_cpp.cc +1 -1
  170. data/src/ruby/ext/grpc/rb_grpc.c +4 -0
  171. data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +2 -0
  172. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +4 -1
  173. data/src/ruby/ext/grpc/rb_server.c +13 -1
  174. data/src/ruby/ext/grpc/rb_server_credentials.c +19 -3
  175. data/src/ruby/ext/grpc/rb_server_credentials.h +4 -0
  176. data/src/ruby/ext/grpc/rb_xds_channel_credentials.c +215 -0
  177. data/src/ruby/ext/grpc/rb_xds_channel_credentials.h +35 -0
  178. data/src/ruby/ext/grpc/rb_xds_server_credentials.c +169 -0
  179. data/src/ruby/ext/grpc/rb_xds_server_credentials.h +35 -0
  180. data/src/ruby/lib/grpc/generic/client_stub.rb +4 -2
  181. data/src/ruby/lib/grpc/version.rb +1 -1
  182. data/src/ruby/spec/call_spec.rb +1 -1
  183. data/src/ruby/spec/channel_credentials_spec.rb +32 -0
  184. data/src/ruby/spec/channel_spec.rb +17 -6
  185. data/src/ruby/spec/client_auth_spec.rb +27 -1
  186. data/src/ruby/spec/errors_spec.rb +1 -1
  187. data/src/ruby/spec/generic/active_call_spec.rb +2 -2
  188. data/src/ruby/spec/generic/client_stub_spec.rb +4 -4
  189. data/src/ruby/spec/generic/rpc_server_spec.rb +1 -1
  190. data/src/ruby/spec/server_credentials_spec.rb +25 -0
  191. data/src/ruby/spec/server_spec.rb +22 -0
  192. data/third_party/boringssl-with-bazel/err_data.c +255 -255
  193. data/third_party/boringssl-with-bazel/src/crypto/cpu-arm-linux.c +11 -2
  194. data/third_party/boringssl-with-bazel/src/crypto/cpu-arm.c +3 -3
  195. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/cipher/cipher.c +21 -13
  196. data/third_party/boringssl-with-bazel/src/crypto/fipsmodule/rand/rand.c +7 -5
  197. data/third_party/boringssl-with-bazel/src/crypto/x509/x509_cmp.c +0 -28
  198. data/third_party/boringssl-with-bazel/src/crypto/x509/x_attrib.c +22 -17
  199. data/third_party/boringssl-with-bazel/src/crypto/x509/x_x509.c +3 -1
  200. data/third_party/boringssl-with-bazel/src/include/openssl/cipher.h +4 -0
  201. data/third_party/boringssl-with-bazel/src/include/openssl/cpu.h +22 -32
  202. data/third_party/boringssl-with-bazel/src/include/openssl/ssl.h +25 -9
  203. data/third_party/boringssl-with-bazel/src/include/openssl/x509.h +0 -1
  204. data/third_party/boringssl-with-bazel/src/ssl/t1_lib.cc +33 -19
  205. data/third_party/xxhash/xxhash.h +5443 -0
  206. metadata +93 -49
  207. data/src/core/lib/security/authorization/authorization_engine.cc +0 -177
  208. data/src/core/lib/security/authorization/authorization_engine.h +0 -84
  209. data/src/core/lib/security/authorization/evaluate_args.cc +0 -148
  210. data/src/core/lib/security/authorization/evaluate_args.h +0 -59
  211. data/src/core/lib/security/authorization/mock_cel/activation.h +0 -57
  212. data/src/core/lib/security/authorization/mock_cel/cel_expr_builder_factory.h +0 -44
  213. data/src/core/lib/security/authorization/mock_cel/cel_expression.h +0 -69
  214. data/src/core/lib/security/authorization/mock_cel/cel_value.h +0 -99
  215. data/src/core/lib/security/authorization/mock_cel/evaluator_core.h +0 -67
  216. data/src/core/lib/security/authorization/mock_cel/flat_expr_builder.h +0 -57
  217. data/third_party/abseil-cpp/absl/container/flat_hash_set.h +0 -504
  218. data/third_party/upb/upb/json_decode.c +0 -1443
  219. data/third_party/upb/upb/json_decode.h +0 -23
  220. data/third_party/upb/upb/json_encode.c +0 -713
  221. data/third_party/upb/upb/json_encode.h +0 -36
@@ -44,13 +44,27 @@ SubchannelKey::SubchannelKey(const SubchannelKey& other) {
44
44
  }
45
45
 
46
46
  SubchannelKey& SubchannelKey::operator=(const SubchannelKey& other) {
47
+ if (&other == this) {
48
+ return *this;
49
+ }
47
50
  grpc_channel_args_destroy(const_cast<grpc_channel_args*>(args_));
48
51
  Init(other.args_, grpc_channel_args_copy);
49
52
  return *this;
50
53
  }
51
54
 
52
- int SubchannelKey::Cmp(const SubchannelKey& other) const {
53
- return grpc_channel_args_compare(args_, other.args_);
55
+ SubchannelKey::SubchannelKey(SubchannelKey&& other) noexcept {
56
+ args_ = other.args_;
57
+ other.args_ = nullptr;
58
+ }
59
+
60
+ SubchannelKey& SubchannelKey::operator=(SubchannelKey&& other) noexcept {
61
+ args_ = other.args_;
62
+ other.args_ = nullptr;
63
+ return *this;
64
+ }
65
+
66
+ bool SubchannelKey::operator<(const SubchannelKey& other) const {
67
+ return grpc_channel_args_compare(args_, other.args_) < 0;
54
68
  }
55
69
 
56
70
  void SubchannelKey::Init(
@@ -41,11 +41,11 @@ class SubchannelKey {
41
41
  // Copyable.
42
42
  SubchannelKey(const SubchannelKey& other);
43
43
  SubchannelKey& operator=(const SubchannelKey& other);
44
- // Not movable.
45
- SubchannelKey(SubchannelKey&&) = delete;
46
- SubchannelKey& operator=(SubchannelKey&&) = delete;
44
+ // Movable
45
+ SubchannelKey(SubchannelKey&&) noexcept;
46
+ SubchannelKey& operator=(SubchannelKey&&) noexcept;
47
47
 
48
- int Cmp(const SubchannelKey& other) const;
48
+ bool operator<(const SubchannelKey& other) const;
49
49
 
50
50
  private:
51
51
  // Initializes the subchannel key with the given \a args and the function to
@@ -72,15 +72,17 @@ class SubchannelPoolInterface : public RefCounted<SubchannelPoolInterface> {
72
72
  // Registers a subchannel against a key. Returns the subchannel registered
73
73
  // with \a key, which may be different from \a constructed because we reuse
74
74
  // (instead of update) any existing subchannel already registered with \a key.
75
- virtual Subchannel* RegisterSubchannel(SubchannelKey* key,
76
- Subchannel* constructed) = 0;
75
+ virtual RefCountedPtr<Subchannel> RegisterSubchannel(
76
+ const SubchannelKey& key, RefCountedPtr<Subchannel> constructed) = 0;
77
77
 
78
78
  // Removes the registered subchannel found by \a key.
79
- virtual void UnregisterSubchannel(SubchannelKey* key) = 0;
79
+ virtual void UnregisterSubchannel(const SubchannelKey& key,
80
+ Subchannel* subchannel) = 0;
80
81
 
81
82
  // Finds the subchannel registered for the given subchannel key. Returns NULL
82
83
  // if no such channel exists. Thread-safe.
83
- virtual Subchannel* FindSubchannel(SubchannelKey* key) = 0;
84
+ virtual RefCountedPtr<Subchannel> FindSubchannel(
85
+ const SubchannelKey& key) = 0;
84
86
 
85
87
  // Creates a channel arg from \a subchannel pool.
86
88
  static grpc_arg CreateChannelArg(SubchannelPoolInterface* subchannel_pool);
@@ -187,7 +187,7 @@ void ChannelData::StartTransportOp(grpc_channel_element* elem,
187
187
  ChannelData* chand = static_cast<ChannelData*>(elem->channel_data);
188
188
  // Catch the disconnect_with_error transport op.
189
189
  if (op->disconnect_with_error != nullptr) {
190
- // IncreaseCallCount() introduces a dummy call and prevent the timer from
190
+ // IncreaseCallCount() introduces a phony call and prevent the timer from
191
191
  // being reset by other threads.
192
192
  chand->IncreaseCallCount();
193
193
  // If the timer has been set, cancel the timer.
@@ -0,0 +1,495 @@
1
+ //
2
+ // Copyright 2021 gRPC authors.
3
+ //
4
+ // Licensed under the Apache License, Version 2.0 (the "License");
5
+ // you may not use this file except in compliance with the License.
6
+ // You may obtain a copy of the License at
7
+ //
8
+ // http://www.apache.org/licenses/LICENSE-2.0
9
+ //
10
+ // Unless required by applicable law or agreed to in writing, software
11
+ // distributed under the License is distributed on an "AS IS" BASIS,
12
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ // See the License for the specific language governing permissions and
14
+ // limitations under the License.
15
+ //
16
+
17
+ #include <grpc/support/port_platform.h>
18
+
19
+ #include "src/core/ext/filters/fault_injection/fault_injection_filter.h"
20
+
21
+ #include "absl/strings/numbers.h"
22
+
23
+ #include <grpc/support/alloc.h>
24
+ #include <grpc/support/log.h>
25
+
26
+ #include "src/core/ext/filters/client_channel/service_config.h"
27
+ #include "src/core/ext/filters/client_channel/service_config_call_data.h"
28
+ #include "src/core/ext/filters/fault_injection/service_config_parser.h"
29
+ #include "src/core/lib/channel/channel_stack.h"
30
+ #include "src/core/lib/channel/status_util.h"
31
+ #include "src/core/lib/gprpp/atomic.h"
32
+ #include "src/core/lib/gprpp/sync.h"
33
+ #include "src/core/lib/iomgr/closure.h"
34
+ #include "src/core/lib/iomgr/timer.h"
35
+ #include "src/core/lib/transport/status_conversion.h"
36
+
37
+ namespace grpc_core {
38
+
39
+ TraceFlag grpc_fault_injection_filter_trace(false, "fault_injection_filter");
40
+
41
+ namespace {
42
+
43
+ Atomic<uint32_t> g_active_faults{0};
44
+ static_assert(
45
+ std::is_trivially_destructible<Atomic<uint32_t>>::value,
46
+ "the active fault counter needs to have a trivially destructible type");
47
+
48
+ inline int GetLinkedMetadatumValueInt(grpc_linked_mdelem* md) {
49
+ int res;
50
+ if (absl::SimpleAtoi(StringViewFromSlice(GRPC_MDVALUE(md->md)), &res)) {
51
+ return res;
52
+ } else {
53
+ return -1;
54
+ }
55
+ }
56
+
57
+ inline uint32_t GetLinkedMetadatumValueUnsignedInt(grpc_linked_mdelem* md) {
58
+ uint32_t res;
59
+ if (absl::SimpleAtoi(StringViewFromSlice(GRPC_MDVALUE(md->md)), &res)) {
60
+ return res;
61
+ } else {
62
+ return -1;
63
+ }
64
+ }
65
+
66
+ inline int64_t GetLinkedMetadatumValueInt64(grpc_linked_mdelem* md) {
67
+ int64_t res;
68
+ if (absl::SimpleAtoi(StringViewFromSlice(GRPC_MDVALUE(md->md)), &res)) {
69
+ return res;
70
+ } else {
71
+ return -1;
72
+ }
73
+ }
74
+
75
+ inline bool UnderFraction(const uint32_t numerator,
76
+ const uint32_t denominator) {
77
+ if (numerator <= 0) return false;
78
+ if (numerator >= denominator) return true;
79
+ // Generate a random number in [0, denominator).
80
+ const uint32_t random_number = rand() % denominator;
81
+ return random_number < numerator;
82
+ }
83
+
84
+ class ChannelData {
85
+ public:
86
+ static grpc_error* Init(grpc_channel_element* elem,
87
+ grpc_channel_element_args* args);
88
+ static void Destroy(grpc_channel_element* elem);
89
+
90
+ int index() const { return index_; }
91
+
92
+ private:
93
+ ChannelData(grpc_channel_element* elem, grpc_channel_element_args* args);
94
+ ~ChannelData() = default;
95
+
96
+ // The relative index of instances of the same filter.
97
+ int index_;
98
+ };
99
+
100
+ class CallData {
101
+ public:
102
+ static grpc_error* Init(grpc_call_element* elem,
103
+ const grpc_call_element_args* args);
104
+
105
+ static void Destroy(grpc_call_element* elem,
106
+ const grpc_call_final_info* /*final_info*/,
107
+ grpc_closure* /*then_schedule_closure*/);
108
+
109
+ static void StartTransportStreamOpBatch(
110
+ grpc_call_element* elem, grpc_transport_stream_op_batch* batch);
111
+
112
+ private:
113
+ class ResumeBatchCanceller;
114
+
115
+ CallData(grpc_call_element* elem, const grpc_call_element_args* args);
116
+ ~CallData();
117
+
118
+ void DecideWhetherToInjectFaults(grpc_metadata_batch* initial_metadata);
119
+
120
+ // Checks if current active faults exceed the allowed max faults.
121
+ bool HaveActiveFaultsQuota(bool increment);
122
+
123
+ // Returns true if this RPC needs to be delayed. If so, this call will be
124
+ // counted as an active fault.
125
+ bool MaybeDelay();
126
+
127
+ // Returns the aborted RPC status if this RPC needs to be aborted. If so,
128
+ // this call will be counted as an active fault. Otherwise, it returns
129
+ // GRPC_ERROR_NONE.
130
+ // If this call is already been delay injected, skip the active faults
131
+ // quota check.
132
+ grpc_error* MaybeAbort();
133
+
134
+ // Delays the stream operations batch.
135
+ void DelayBatch(grpc_call_element* elem,
136
+ grpc_transport_stream_op_batch* batch);
137
+
138
+ // Cancels the delay timer.
139
+ void CancelDelayTimer() { grpc_timer_cancel(&delay_timer_); }
140
+
141
+ // Finishes the fault injection, should only be called once.
142
+ void FaultInjectionFinished() {
143
+ g_active_faults.FetchSub(1, MemoryOrder::RELAXED);
144
+ }
145
+
146
+ // This is a callback that will be invoked after the delay timer is up.
147
+ static void ResumeBatch(void* arg, grpc_error* error);
148
+
149
+ // This is a callback invoked upon completion of recv_trailing_metadata.
150
+ // Injects the abort_error_ to the recv_trailing_metadata batch if needed.
151
+ static void HijackedRecvTrailingMetadataReady(void* arg, grpc_error*);
152
+
153
+ // Used to track the policy structs that needs to be destroyed in dtor.
154
+ bool fi_policy_owned_ = false;
155
+ const FaultInjectionMethodParsedConfig::FaultInjectionPolicy* fi_policy_;
156
+ grpc_call_stack* owning_call_;
157
+ Arena* arena_;
158
+ CallCombiner* call_combiner_;
159
+
160
+ // Indicates whether we are doing a delay and/or an abort for this call.
161
+ bool delay_request_ = false;
162
+ bool abort_request_ = false;
163
+
164
+ // Delay states
165
+ grpc_timer delay_timer_ ABSL_GUARDED_BY(delay_mu_);
166
+ ResumeBatchCanceller* resume_batch_canceller_ ABSL_GUARDED_BY(delay_mu_);
167
+ grpc_transport_stream_op_batch* delayed_batch_ ABSL_GUARDED_BY(delay_mu_);
168
+ // Abort states
169
+ grpc_error* abort_error_ = GRPC_ERROR_NONE;
170
+ grpc_closure recv_trailing_metadata_ready_;
171
+ grpc_closure* original_recv_trailing_metadata_ready_;
172
+ // Protects the asynchronous delay, resume, and cancellation.
173
+ Mutex delay_mu_;
174
+ };
175
+
176
+ // ChannelData
177
+
178
+ grpc_error* ChannelData::Init(grpc_channel_element* elem,
179
+ grpc_channel_element_args* args) {
180
+ GPR_ASSERT(elem->filter == &FaultInjectionFilterVtable);
181
+ new (elem->channel_data) ChannelData(elem, args);
182
+ return GRPC_ERROR_NONE;
183
+ }
184
+
185
+ void ChannelData::Destroy(grpc_channel_element* elem) {
186
+ auto* chand = static_cast<ChannelData*>(elem->channel_data);
187
+ chand->~ChannelData();
188
+ }
189
+
190
+ ChannelData::ChannelData(grpc_channel_element* elem,
191
+ grpc_channel_element_args* args)
192
+ : index_(grpc_channel_stack_filter_instance_number(args->channel_stack,
193
+ elem)) {}
194
+
195
+ // CallData::ResumeBatchCanceller
196
+
197
+ class CallData::ResumeBatchCanceller {
198
+ public:
199
+ explicit ResumeBatchCanceller(grpc_call_element* elem) : elem_(elem) {
200
+ auto* calld = static_cast<CallData*>(elem->call_data);
201
+ GRPC_CALL_STACK_REF(calld->owning_call_, "ResumeBatchCanceller");
202
+ GRPC_CLOSURE_INIT(&closure_, &Cancel, this, grpc_schedule_on_exec_ctx);
203
+ calld->call_combiner_->SetNotifyOnCancel(&closure_);
204
+ }
205
+
206
+ private:
207
+ static void Cancel(void* arg, grpc_error* error) {
208
+ auto* self = static_cast<ResumeBatchCanceller*>(arg);
209
+ auto* chand = static_cast<ChannelData*>(self->elem_->channel_data);
210
+ auto* calld = static_cast<CallData*>(self->elem_->call_data);
211
+ MutexLock lock(&calld->delay_mu_);
212
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_fault_injection_filter_trace)) {
213
+ gpr_log(GPR_INFO,
214
+ "chand=%p calld=%p: cancelling schdueled pick: "
215
+ "error=%s self=%p calld->resume_batch_canceller_=%p",
216
+ chand, calld, grpc_error_string(error), self,
217
+ calld->resume_batch_canceller_);
218
+ }
219
+ if (error != GRPC_ERROR_NONE && calld->resume_batch_canceller_ == self) {
220
+ // Cancel the delayed pick.
221
+ calld->CancelDelayTimer();
222
+ calld->FaultInjectionFinished();
223
+ // Fail pending batches on the call.
224
+ grpc_transport_stream_op_batch_finish_with_failure(
225
+ calld->delayed_batch_, GRPC_ERROR_REF(error), calld->call_combiner_);
226
+ }
227
+ GRPC_CALL_STACK_UNREF(calld->owning_call_, "ResumeBatchCanceller");
228
+ delete self;
229
+ }
230
+
231
+ grpc_call_element* elem_;
232
+ grpc_closure closure_;
233
+ };
234
+
235
+ // CallData
236
+
237
+ grpc_error* CallData::Init(grpc_call_element* elem,
238
+ const grpc_call_element_args* args) {
239
+ auto* calld = new (elem->call_data) CallData(elem, args);
240
+ if (calld->fi_policy_ == nullptr) {
241
+ return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
242
+ "failed to find fault injection policy");
243
+ }
244
+ return GRPC_ERROR_NONE;
245
+ }
246
+
247
+ void CallData::Destroy(grpc_call_element* elem,
248
+ const grpc_call_final_info* /*final_info*/,
249
+ grpc_closure* /*then_schedule_closure*/) {
250
+ auto* calld = static_cast<CallData*>(elem->call_data);
251
+ calld->~CallData();
252
+ }
253
+
254
+ void CallData::StartTransportStreamOpBatch(
255
+ grpc_call_element* elem, grpc_transport_stream_op_batch* batch) {
256
+ auto* calld = static_cast<CallData*>(elem->call_data);
257
+ // There should only be one send_initial_metdata op, and fault injection also
258
+ // only need to be enforced once.
259
+ if (batch->send_initial_metadata) {
260
+ calld->DecideWhetherToInjectFaults(
261
+ batch->payload->send_initial_metadata.send_initial_metadata);
262
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_fault_injection_filter_trace)) {
263
+ gpr_log(GPR_INFO,
264
+ "chand=%p calld=%p: Fault injection triggered delay=%d abort=%d",
265
+ elem->channel_data, calld, calld->delay_request_,
266
+ calld->abort_request_);
267
+ }
268
+ if (calld->MaybeDelay()) {
269
+ // Delay the batch, and pass down the batch in the scheduled closure.
270
+ calld->DelayBatch(elem, batch);
271
+ return;
272
+ }
273
+ grpc_error* abort_error = calld->MaybeAbort();
274
+ if (abort_error != GRPC_ERROR_NONE) {
275
+ calld->abort_error_ = abort_error;
276
+ grpc_transport_stream_op_batch_finish_with_failure(
277
+ batch, GRPC_ERROR_REF(calld->abort_error_), calld->call_combiner_);
278
+ return;
279
+ }
280
+ } else {
281
+ if (batch->recv_trailing_metadata) {
282
+ // Intercept recv_trailing_metadata callback so that we can inject the
283
+ // failure when aborting streaming calls, because their
284
+ // recv_trailing_metatdata op may not be on the same batch as the
285
+ // send_initial_metadata op.
286
+ calld->original_recv_trailing_metadata_ready_ =
287
+ batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready;
288
+ batch->payload->recv_trailing_metadata.recv_trailing_metadata_ready =
289
+ &calld->recv_trailing_metadata_ready_;
290
+ }
291
+ if (calld->abort_error_ != GRPC_ERROR_NONE) {
292
+ // If we already decided to abort, then immediately fail this batch.
293
+ grpc_transport_stream_op_batch_finish_with_failure(
294
+ batch, GRPC_ERROR_REF(calld->abort_error_), calld->call_combiner_);
295
+ return;
296
+ }
297
+ }
298
+ // Chain to the next filter.
299
+ grpc_call_next_op(elem, batch);
300
+ }
301
+
302
+ CallData::CallData(grpc_call_element* elem, const grpc_call_element_args* args)
303
+ : owning_call_(args->call_stack),
304
+ arena_(args->arena),
305
+ call_combiner_(args->call_combiner) {
306
+ auto* chand = static_cast<ChannelData*>(elem->channel_data);
307
+ // Fetch the fault injection policy from the service config, based on the
308
+ // relative index for which policy should this CallData use.
309
+ auto* service_config_call_data = static_cast<ServiceConfigCallData*>(
310
+ args->context[GRPC_CONTEXT_SERVICE_CONFIG_CALL_DATA].value);
311
+ auto* method_params = static_cast<FaultInjectionMethodParsedConfig*>(
312
+ service_config_call_data->GetMethodParsedConfig(
313
+ FaultInjectionServiceConfigParser::ParserIndex()));
314
+ if (method_params != nullptr) {
315
+ fi_policy_ = method_params->fault_injection_policy(chand->index());
316
+ }
317
+ GRPC_CLOSURE_INIT(&recv_trailing_metadata_ready_,
318
+ HijackedRecvTrailingMetadataReady, elem,
319
+ grpc_schedule_on_exec_ctx);
320
+ }
321
+
322
+ CallData::~CallData() {
323
+ if (fi_policy_owned_) {
324
+ fi_policy_->~FaultInjectionPolicy();
325
+ }
326
+ GRPC_ERROR_UNREF(abort_error_);
327
+ }
328
+
329
+ void CallData::DecideWhetherToInjectFaults(
330
+ grpc_metadata_batch* initial_metadata) {
331
+ FaultInjectionMethodParsedConfig::FaultInjectionPolicy* copied_policy =
332
+ nullptr;
333
+ // Update the policy with values in initial metadata.
334
+ if (!fi_policy_->abort_code_header.empty() ||
335
+ !fi_policy_->abort_percentage_header.empty() ||
336
+ !fi_policy_->delay_header.empty() ||
337
+ !fi_policy_->delay_percentage_header.empty()) {
338
+ // Defer the actual copy until the first matched header.
339
+ auto maybe_copy_policy_func = [this, &copied_policy]() {
340
+ if (copied_policy == nullptr) {
341
+ copied_policy =
342
+ arena_->New<FaultInjectionMethodParsedConfig::FaultInjectionPolicy>(
343
+ *fi_policy_);
344
+ }
345
+ };
346
+ for (grpc_linked_mdelem* md = initial_metadata->list.head; md != nullptr;
347
+ md = md->next) {
348
+ absl::string_view key = StringViewFromSlice(GRPC_MDKEY(md->md));
349
+ // Only perform string comparison if:
350
+ // 1. Needs to check this header;
351
+ // 2. The value is not been filled before.
352
+ if (!fi_policy_->abort_code_header.empty() &&
353
+ (copied_policy == nullptr ||
354
+ copied_policy->abort_code == GRPC_STATUS_OK) &&
355
+ key == fi_policy_->abort_code_header) {
356
+ maybe_copy_policy_func();
357
+ grpc_status_code_from_int(GetLinkedMetadatumValueInt(md),
358
+ &copied_policy->abort_code);
359
+ }
360
+ if (!fi_policy_->abort_percentage_header.empty() &&
361
+ key == fi_policy_->abort_percentage_header) {
362
+ maybe_copy_policy_func();
363
+ copied_policy->abort_percentage_numerator =
364
+ GPR_MIN(GetLinkedMetadatumValueUnsignedInt(md),
365
+ fi_policy_->abort_percentage_numerator);
366
+ }
367
+ if (!fi_policy_->delay_header.empty() &&
368
+ (copied_policy == nullptr || copied_policy->delay == 0) &&
369
+ key == fi_policy_->delay_header) {
370
+ maybe_copy_policy_func();
371
+ copied_policy->delay = static_cast<grpc_millis>(
372
+ GPR_MAX(GetLinkedMetadatumValueInt64(md), 0));
373
+ }
374
+ if (!fi_policy_->delay_percentage_header.empty() &&
375
+ key == fi_policy_->delay_percentage_header) {
376
+ maybe_copy_policy_func();
377
+ copied_policy->delay_percentage_numerator =
378
+ GPR_MIN(GetLinkedMetadatumValueUnsignedInt(md),
379
+ fi_policy_->delay_percentage_numerator);
380
+ }
381
+ }
382
+ if (copied_policy != nullptr) fi_policy_ = copied_policy;
383
+ }
384
+ // Roll the dice
385
+ delay_request_ = fi_policy_->delay != 0 &&
386
+ UnderFraction(fi_policy_->delay_percentage_numerator,
387
+ fi_policy_->delay_percentage_denominator);
388
+ abort_request_ = fi_policy_->abort_code != GRPC_STATUS_OK &&
389
+ UnderFraction(fi_policy_->abort_percentage_numerator,
390
+ fi_policy_->abort_percentage_denominator);
391
+ if (!delay_request_ && !abort_request_) {
392
+ if (copied_policy != nullptr) copied_policy->~FaultInjectionPolicy();
393
+ // No fault injection for this call
394
+ } else {
395
+ fi_policy_owned_ = copied_policy != nullptr;
396
+ }
397
+ }
398
+
399
+ bool CallData::HaveActiveFaultsQuota(bool increment) {
400
+ if (g_active_faults.Load(MemoryOrder::ACQUIRE) >= fi_policy_->max_faults) {
401
+ return false;
402
+ }
403
+ if (increment) g_active_faults.FetchAdd(1, MemoryOrder::RELAXED);
404
+ return true;
405
+ }
406
+
407
+ bool CallData::MaybeDelay() {
408
+ if (delay_request_) {
409
+ return HaveActiveFaultsQuota(true);
410
+ }
411
+ return false;
412
+ }
413
+
414
+ grpc_error* CallData::MaybeAbort() {
415
+ if (abort_request_ && (delay_request_ || HaveActiveFaultsQuota(false))) {
416
+ return grpc_error_set_int(
417
+ GRPC_ERROR_CREATE_FROM_COPIED_STRING(fi_policy_->abort_message.c_str()),
418
+ GRPC_ERROR_INT_GRPC_STATUS, fi_policy_->abort_code);
419
+ }
420
+ return GRPC_ERROR_NONE;
421
+ }
422
+
423
+ void CallData::DelayBatch(grpc_call_element* elem,
424
+ grpc_transport_stream_op_batch* batch) {
425
+ MutexLock lock(&delay_mu_);
426
+ delayed_batch_ = batch;
427
+ resume_batch_canceller_ = new ResumeBatchCanceller(elem);
428
+ grpc_millis resume_time = ExecCtx::Get()->Now() + fi_policy_->delay;
429
+ GRPC_CLOSURE_INIT(&batch->handler_private.closure, ResumeBatch, elem,
430
+ grpc_schedule_on_exec_ctx);
431
+ grpc_timer_init(&delay_timer_, resume_time, &batch->handler_private.closure);
432
+ }
433
+
434
+ void CallData::ResumeBatch(void* arg, grpc_error* error) {
435
+ grpc_call_element* elem = static_cast<grpc_call_element*>(arg);
436
+ auto* calld = static_cast<CallData*>(elem->call_data);
437
+ MutexLock lock(&calld->delay_mu_);
438
+ // Cancelled or canceller has already run
439
+ if (error == GRPC_ERROR_CANCELLED ||
440
+ calld->resume_batch_canceller_ == nullptr) {
441
+ return;
442
+ }
443
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_fault_injection_filter_trace)) {
444
+ gpr_log(GPR_INFO, "chand=%p calld=%p: Resuming delayed stream op batch %p",
445
+ elem->channel_data, calld, calld->delayed_batch_);
446
+ }
447
+ // Lame the canceller
448
+ calld->resume_batch_canceller_ = nullptr;
449
+ // Finish fault injection.
450
+ calld->FaultInjectionFinished();
451
+ // Abort if needed.
452
+ error = calld->MaybeAbort();
453
+ if (error != GRPC_ERROR_NONE) {
454
+ grpc_transport_stream_op_batch_finish_with_failure(
455
+ calld->delayed_batch_, error, calld->call_combiner_);
456
+ return;
457
+ }
458
+ // Chain to the next filter.
459
+ grpc_call_next_op(elem, calld->delayed_batch_);
460
+ }
461
+
462
+ void CallData::HijackedRecvTrailingMetadataReady(void* arg, grpc_error* error) {
463
+ grpc_call_element* elem = static_cast<grpc_call_element*>(arg);
464
+ auto* calld = static_cast<CallData*>(elem->call_data);
465
+ if (calld->abort_error_ != GRPC_ERROR_NONE) {
466
+ error = grpc_error_add_child(GRPC_ERROR_REF(error),
467
+ GRPC_ERROR_REF(calld->abort_error_));
468
+ Closure::Run(DEBUG_LOCATION, calld->original_recv_trailing_metadata_ready_,
469
+ error);
470
+ }
471
+ }
472
+
473
+ } // namespace
474
+
475
+ extern const grpc_channel_filter FaultInjectionFilterVtable = {
476
+ CallData::StartTransportStreamOpBatch,
477
+ grpc_channel_next_op,
478
+ sizeof(CallData),
479
+ CallData::Init,
480
+ grpc_call_stack_ignore_set_pollset_or_pollset_set,
481
+ CallData::Destroy,
482
+ sizeof(ChannelData),
483
+ ChannelData::Init,
484
+ ChannelData::Destroy,
485
+ grpc_channel_next_get_info,
486
+ "fault_injection_filter",
487
+ };
488
+
489
+ void FaultInjectionFilterInit(void) {
490
+ grpc_core::FaultInjectionServiceConfigParser::Register();
491
+ }
492
+
493
+ void FaultInjectionFilterShutdown(void) {}
494
+
495
+ } // namespace grpc_core