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
@@ -24,73 +24,33 @@
24
24
 
25
25
  namespace grpc_core {
26
26
 
27
- LocalSubchannelPool::LocalSubchannelPool() {
28
- subchannel_map_ = grpc_avl_create(&subchannel_avl_vtable_);
27
+ RefCountedPtr<Subchannel> LocalSubchannelPool::RegisterSubchannel(
28
+ const SubchannelKey& key, RefCountedPtr<Subchannel> constructed) {
29
+ auto it = subchannel_map_.find(key);
30
+ // Because this pool is only accessed under the client channel's work
31
+ // serializer, and because FindSubchannel is checked before invoking
32
+ // RegisterSubchannel, no such subchannel should exist in the map.
33
+ GPR_ASSERT(it == subchannel_map_.end());
34
+ subchannel_map_[key] = constructed.get();
35
+ return constructed;
36
+ }
37
+
38
+ void LocalSubchannelPool::UnregisterSubchannel(const SubchannelKey& key,
39
+ Subchannel* subchannel) {
40
+ auto it = subchannel_map_.find(key);
41
+ // Because this subchannel pool is accessed only under the client
42
+ // channel's work serializer, any subchannel created by RegisterSubchannel
43
+ // will be deleted from the map in UnregisterSubchannel.
44
+ GPR_ASSERT(it != subchannel_map_.end());
45
+ GPR_ASSERT(it->second == subchannel);
46
+ subchannel_map_.erase(it);
47
+ }
48
+
49
+ RefCountedPtr<Subchannel> LocalSubchannelPool::FindSubchannel(
50
+ const SubchannelKey& key) {
51
+ auto it = subchannel_map_.find(key);
52
+ if (it == subchannel_map_.end()) return nullptr;
53
+ return it->second->Ref();
29
54
  }
30
55
 
31
- LocalSubchannelPool::~LocalSubchannelPool() {
32
- grpc_avl_unref(subchannel_map_, nullptr);
33
- }
34
-
35
- Subchannel* LocalSubchannelPool::RegisterSubchannel(SubchannelKey* key,
36
- Subchannel* constructed) {
37
- // Check to see if a subchannel already exists.
38
- Subchannel* c =
39
- static_cast<Subchannel*>(grpc_avl_get(subchannel_map_, key, nullptr));
40
- if (c != nullptr) {
41
- // The subchannel already exists. Reuse it.
42
- c = GRPC_SUBCHANNEL_REF(c, "subchannel_register+reuse");
43
- GRPC_SUBCHANNEL_UNREF(constructed, "subchannel_register+found_existing");
44
- } else {
45
- // There hasn't been such subchannel. Add one.
46
- subchannel_map_ = grpc_avl_add(subchannel_map_, new SubchannelKey(*key),
47
- constructed, nullptr);
48
- c = constructed;
49
- }
50
- return c;
51
- }
52
-
53
- void LocalSubchannelPool::UnregisterSubchannel(SubchannelKey* key) {
54
- subchannel_map_ = grpc_avl_remove(subchannel_map_, key, nullptr);
55
- }
56
-
57
- Subchannel* LocalSubchannelPool::FindSubchannel(SubchannelKey* key) {
58
- Subchannel* c =
59
- static_cast<Subchannel*>(grpc_avl_get(subchannel_map_, key, nullptr));
60
- return c == nullptr ? c : GRPC_SUBCHANNEL_REF(c, "found_from_pool");
61
- }
62
-
63
- namespace {
64
-
65
- void sck_avl_destroy(void* p, void* /*user_data*/) {
66
- SubchannelKey* key = static_cast<SubchannelKey*>(p);
67
- delete key;
68
- }
69
-
70
- void* sck_avl_copy(void* p, void* /*unused*/) {
71
- const SubchannelKey* key = static_cast<const SubchannelKey*>(p);
72
- auto new_key = new SubchannelKey(*key);
73
- return static_cast<void*>(new_key);
74
- }
75
-
76
- long sck_avl_compare(void* a, void* b, void* /*unused*/) {
77
- const SubchannelKey* key_a = static_cast<const SubchannelKey*>(a);
78
- const SubchannelKey* key_b = static_cast<const SubchannelKey*>(b);
79
- return key_a->Cmp(*key_b);
80
- }
81
-
82
- void scv_avl_destroy(void* /*p*/, void* /*user_data*/) {}
83
-
84
- void* scv_avl_copy(void* p, void* /*unused*/) { return p; }
85
-
86
- } // namespace
87
-
88
- const grpc_avl_vtable LocalSubchannelPool::subchannel_avl_vtable_ = {
89
- sck_avl_destroy, // destroy_key
90
- sck_avl_copy, // copy_key
91
- sck_avl_compare, // compare_keys
92
- scv_avl_destroy, // destroy_value
93
- scv_avl_copy // copy_value
94
- };
95
-
96
56
  } // namespace grpc_core
@@ -21,6 +21,8 @@
21
21
 
22
22
  #include <grpc/support/port_platform.h>
23
23
 
24
+ #include <map>
25
+
24
26
  #include "src/core/ext/filters/client_channel/subchannel_pool_interface.h"
25
27
 
26
28
  namespace grpc_core {
@@ -34,22 +36,21 @@ namespace grpc_core {
34
36
  // Thread-unsafe.
35
37
  class LocalSubchannelPool final : public SubchannelPoolInterface {
36
38
  public:
37
- LocalSubchannelPool();
38
- ~LocalSubchannelPool() override;
39
+ LocalSubchannelPool() {}
40
+ ~LocalSubchannelPool() override {}
39
41
 
40
42
  // Implements interface methods.
41
43
  // Thread-unsafe. Intended to be invoked within the client_channel work
42
44
  // serializer.
43
- Subchannel* RegisterSubchannel(SubchannelKey* key,
44
- Subchannel* constructed) override;
45
- void UnregisterSubchannel(SubchannelKey* key) override;
46
- Subchannel* FindSubchannel(SubchannelKey* key) override;
45
+ RefCountedPtr<Subchannel> RegisterSubchannel(
46
+ const SubchannelKey& key, RefCountedPtr<Subchannel> constructed) override;
47
+ void UnregisterSubchannel(const SubchannelKey& key,
48
+ Subchannel* subchannel) override;
49
+ RefCountedPtr<Subchannel> FindSubchannel(const SubchannelKey& key) override;
47
50
 
48
51
  private:
49
- // The vtable for subchannel operations in an AVL tree.
50
- static const grpc_avl_vtable subchannel_avl_vtable_;
51
52
  // A map from subchannel key to subchannel.
52
- grpc_avl subchannel_map_;
53
+ std::map<SubchannelKey, Subchannel*> subchannel_map_;
53
54
  };
54
55
 
55
56
  } // namespace grpc_core
@@ -60,6 +60,9 @@ Resolver::Result::Result(Result&& other) noexcept {
60
60
  }
61
61
 
62
62
  Resolver::Result& Resolver::Result::operator=(const Result& other) {
63
+ if (&other == this) {
64
+ return *this;
65
+ }
63
66
  addresses = other.addresses;
64
67
  service_config = other.service_config;
65
68
  GRPC_ERROR_UNREF(service_config_error);
@@ -54,8 +54,8 @@ class GrpcPolledFdPosix : public GrpcPolledFd {
54
54
  /* c-ares library will close the fd inside grpc_fd. This fd may be picked up
55
55
  immediately by another thread, and should not be closed by the following
56
56
  grpc_fd_orphan. */
57
- int dummy_release_fd;
58
- grpc_fd_orphan(fd_, nullptr, &dummy_release_fd, "c-ares query finished");
57
+ int phony_release_fd;
58
+ grpc_fd_orphan(fd_, nullptr, &phony_release_fd, "c-ares query finished");
59
59
  }
60
60
 
61
61
  void RegisterForOnReadableLocked(grpc_closure* read_closure) override {
@@ -251,7 +251,7 @@ class GrpcPolledFdWindows {
251
251
  }
252
252
  }
253
253
 
254
- bool IsFdStillReadableLocked() { return GRPC_SLICE_LENGTH(read_buf_) > 0; }
254
+ bool IsFdStillReadableLocked() { return read_buf_has_data_; }
255
255
 
256
256
  void ShutdownLocked(grpc_error* error) {
257
257
  grpc_winsocket_shutdown(winsocket_);
@@ -362,6 +362,8 @@ class GrpcPolledFdWindows {
362
362
  DWORD bytes_sent = 0;
363
363
  int wsa_error_code = 0;
364
364
  if (SendWriteBuf(&bytes_sent, nullptr, &wsa_error_code) != 0) {
365
+ grpc_slice_unref_internal(write_buf_);
366
+ write_buf_ = grpc_empty_slice();
365
367
  wsa_error_ctx->SetWSAError(wsa_error_code);
366
368
  char* msg = gpr_format_message(wsa_error_code);
367
369
  GRPC_CARES_TRACE_LOG(
@@ -238,14 +238,14 @@ void grpc_ares_ev_driver_shutdown_locked(grpc_ares_ev_driver* ev_driver) {
238
238
  // Search fd in the fd_node list head. This is an O(n) search, the max possible
239
239
  // value of n is ARES_GETSOCK_MAXNUM (16). n is typically 1 - 2 in our tests.
240
240
  static fd_node* pop_fd_node_locked(fd_node** head, ares_socket_t as) {
241
- fd_node dummy_head;
242
- dummy_head.next = *head;
243
- fd_node* node = &dummy_head;
241
+ fd_node phony_head;
242
+ phony_head.next = *head;
243
+ fd_node* node = &phony_head;
244
244
  while (node->next != nullptr) {
245
245
  if (node->next->grpc_polled_fd->GetWrappedAresSocketLocked() == as) {
246
246
  fd_node* ret = node->next;
247
247
  node->next = node->next->next;
248
- *head = dummy_head.next;
248
+ *head = phony_head.next;
249
249
  return ret;
250
250
  }
251
251
  node = node->next;
@@ -971,11 +971,7 @@ static bool target_matches_localhost_inner(const char* name, std::string* host,
971
971
  gpr_log(GPR_ERROR, "Unable to split host and port for name: %s", name);
972
972
  return false;
973
973
  }
974
- if (gpr_stricmp(host->c_str(), "localhost") == 0) {
975
- return true;
976
- } else {
977
- return false;
978
- }
974
+ return gpr_stricmp(host->c_str(), "localhost") == 0;
979
975
  }
980
976
 
981
977
  static bool target_matches_localhost(const char* name) {
@@ -19,6 +19,7 @@
19
19
  #include "src/core/ext/filters/client_channel/resolver_registry.h"
20
20
  #include "src/core/ext/xds/xds_client.h"
21
21
  #include "src/core/lib/gpr/env.h"
22
+ #include "src/core/lib/gpr/string.h"
22
23
  #include "src/core/lib/http/httpcli.h"
23
24
  #include "src/core/lib/iomgr/polling_entity.h"
24
25
  #include "src/core/lib/security/credentials/alts/check_gcp_environment.h"
@@ -307,17 +308,25 @@ void GoogleCloud2ProdResolver::StartXdsResolver() {
307
308
  {"TRAFFICDIRECTOR_DIRECTPATH_C2P_IPV6_CAPABLE", true},
308
309
  };
309
310
  }
311
+ // Allow the TD server uri to be overridden for testing purposes.
312
+ UniquePtr<char> override_server(
313
+ gpr_getenv("GRPC_TEST_ONLY_GOOGLE_C2P_RESOLVER_TRAFFIC_DIRECTOR_URI"));
314
+ const char* server_uri =
315
+ override_server != nullptr && strlen(override_server.get()) > 0
316
+ ? override_server.get()
317
+ : "directpath-trafficdirector.googleapis.com";
310
318
  Json bootstrap = Json::Object{
311
319
  {"xds_servers",
312
320
  Json::Array{
313
321
  Json::Object{
314
- {"server_uri", "directpath-trafficdirector.googleapis.com"},
322
+ {"server_uri", server_uri},
315
323
  {"channel_creds",
316
324
  Json::Array{
317
325
  Json::Object{
318
326
  {"type", "google_default"},
319
327
  },
320
328
  }},
329
+ {"server_features", Json::Array{"xds_v3"}},
321
330
  },
322
331
  }},
323
332
  {"node", std::move(node)},
@@ -353,8 +362,14 @@ class GoogleCloud2ProdResolverFactory : public ResolverFactory {
353
362
  } // namespace
354
363
 
355
364
  void GoogleCloud2ProdResolverInit() {
356
- ResolverRegistry::Builder::RegisterResolverFactory(
357
- absl::make_unique<GoogleCloud2ProdResolverFactory>());
365
+ // TODO(roth): Remove env var protection once this code is proven stable.
366
+ UniquePtr<char> value(gpr_getenv("GRPC_EXPERIMENTAL_GOOGLE_C2P_RESOLVER"));
367
+ bool parsed_value;
368
+ bool parse_succeeded = gpr_parse_bool_value(value.get(), &parsed_value);
369
+ if (parse_succeeded && parsed_value) {
370
+ ResolverRegistry::Builder::RegisterResolverFactory(
371
+ absl::make_unique<GoogleCloud2ProdResolverFactory>());
372
+ }
358
373
  }
359
374
 
360
375
  void GoogleCloud2ProdResolverShutdown() {}
@@ -22,13 +22,18 @@
22
22
  #include "absl/strings/str_join.h"
23
23
  #include "absl/strings/str_split.h"
24
24
  #include "re2/re2.h"
25
+ #define XXH_INLINE_ALL
26
+ #include "xxhash.h"
25
27
 
26
28
  #include "src/core/ext/filters/client_channel/config_selector.h"
29
+ #include "src/core/ext/filters/client_channel/lb_policy/ring_hash/ring_hash.h"
27
30
  #include "src/core/ext/filters/client_channel/resolver_registry.h"
28
31
  #include "src/core/ext/xds/xds_client.h"
32
+ #include "src/core/ext/xds/xds_http_filters.h"
29
33
  #include "src/core/lib/channel/channel_args.h"
30
34
  #include "src/core/lib/iomgr/closure.h"
31
35
  #include "src/core/lib/iomgr/exec_ctx.h"
36
+ #include "src/core/lib/surface/lame_client.h"
32
37
  #include "src/core/lib/transport/timeout_encoding.h"
33
38
 
34
39
  namespace grpc_core {
@@ -135,9 +140,7 @@ class XdsResolver : public Resolver {
135
140
 
136
141
  class XdsConfigSelector : public ConfigSelector {
137
142
  public:
138
- XdsConfigSelector(RefCountedPtr<XdsResolver> resolver,
139
- const std::vector<XdsApi::Route>& routes,
140
- grpc_error* error);
143
+ XdsConfigSelector(RefCountedPtr<XdsResolver> resolver, grpc_error** error);
141
144
  ~XdsConfigSelector() override;
142
145
 
143
146
  const char* name() const override { return "XdsConfigSelector"; }
@@ -151,26 +154,41 @@ class XdsResolver : public Resolver {
151
154
 
152
155
  CallConfig GetCallConfig(GetCallConfigArgs args) override;
153
156
 
157
+ std::vector<const grpc_channel_filter*> GetFilters() override {
158
+ return filters_;
159
+ }
160
+
161
+ grpc_channel_args* ModifyChannelArgs(grpc_channel_args* args) override;
162
+
154
163
  private:
155
164
  struct Route {
165
+ struct ClusterWeightState {
166
+ uint32_t range_end;
167
+ absl::string_view cluster;
168
+ RefCountedPtr<ServiceConfig> method_config;
169
+
170
+ bool operator==(const ClusterWeightState& other) const;
171
+ };
172
+
156
173
  XdsApi::Route route;
157
- absl::InlinedVector<std::pair<uint32_t, absl::string_view>, 2>
158
- weighted_cluster_state;
159
174
  RefCountedPtr<ServiceConfig> method_config;
160
- bool operator==(const Route& other) const {
161
- return route == other.route &&
162
- weighted_cluster_state == other.weighted_cluster_state;
163
- }
175
+ absl::InlinedVector<ClusterWeightState, 2> weighted_cluster_state;
176
+
177
+ bool operator==(const Route& other) const;
164
178
  };
165
179
  using RouteTable = std::vector<Route>;
166
180
 
167
181
  void MaybeAddCluster(const std::string& name);
168
- grpc_error* CreateMethodConfig(RefCountedPtr<ServiceConfig>* method_config,
169
- const XdsApi::Route& route);
182
+ grpc_error* CreateMethodConfig(
183
+ const XdsApi::Route& route,
184
+ const XdsApi::Route::ClusterWeight* cluster_weight,
185
+ RefCountedPtr<ServiceConfig>* method_config);
170
186
 
171
187
  RefCountedPtr<XdsResolver> resolver_;
172
188
  RouteTable route_table_;
173
189
  std::map<absl::string_view, RefCountedPtr<ClusterState>> clusters_;
190
+ std::vector<const grpc_channel_filter*> filters_;
191
+ grpc_error* filter_error_ = GRPC_ERROR_NONE;
174
192
  };
175
193
 
176
194
  void OnListenerUpdate(XdsApi::LdsUpdate listener);
@@ -187,13 +205,20 @@ class XdsResolver : public Resolver {
187
205
  std::string server_name_;
188
206
  const grpc_channel_args* args_;
189
207
  grpc_pollset_set* interested_parties_;
208
+
190
209
  RefCountedPtr<XdsClient> xds_client_;
210
+
191
211
  XdsClient::ListenerWatcherInterface* listener_watcher_ = nullptr;
212
+ // This will not contain the RouteConfiguration, even if it comes with the
213
+ // LDS response; instead, the relevant VirtualHost from the
214
+ // RouteConfiguration will be saved in current_virtual_host_.
215
+ XdsApi::LdsUpdate current_listener_;
216
+
192
217
  std::string route_config_name_;
193
218
  XdsClient::RouteConfigWatcherInterface* route_config_watcher_ = nullptr;
219
+ XdsApi::RdsUpdate::VirtualHost current_virtual_host_;
220
+
194
221
  ClusterState::ClusterStateMap cluster_state_map_;
195
- std::vector<XdsApi::Route> current_update_;
196
- XdsApi::Duration http_max_stream_duration_;
197
222
  };
198
223
 
199
224
  //
@@ -212,7 +237,7 @@ XdsResolver::Notifier::Notifier(RefCountedPtr<XdsResolver> resolver,
212
237
  XdsResolver::Notifier::Notifier(RefCountedPtr<XdsResolver> resolver,
213
238
  XdsApi::RdsUpdate update)
214
239
  : resolver_(std::move(resolver)), type_(kRdsUpdate) {
215
- update_.rds_update = std::move(update);
240
+ update_.http_connection_manager.rds_update = std::move(update);
216
241
  GRPC_CLOSURE_INIT(&closure_, &RunInExecCtx, this, nullptr);
217
242
  ExecCtx::Run(DEBUG_LOCATION, &closure_, GRPC_ERROR_NONE);
218
243
  }
@@ -248,7 +273,8 @@ void XdsResolver::Notifier::RunInWorkSerializer(grpc_error* error) {
248
273
  resolver_->OnListenerUpdate(std::move(update_));
249
274
  break;
250
275
  case kRdsUpdate:
251
- resolver_->OnRouteConfigUpdate(std::move(*update_.rds_update));
276
+ resolver_->OnRouteConfigUpdate(
277
+ std::move(*update_.http_connection_manager.rds_update));
252
278
  break;
253
279
  case kError:
254
280
  resolver_->OnError(error);
@@ -260,13 +286,35 @@ void XdsResolver::Notifier::RunInWorkSerializer(grpc_error* error) {
260
286
  delete this;
261
287
  }
262
288
 
289
+ //
290
+ // XdsResolver::XdsConfigSelector::Route
291
+ //
292
+
293
+ bool MethodConfigsEqual(const ServiceConfig* sc1, const ServiceConfig* sc2) {
294
+ if (sc1 == nullptr) return sc2 == nullptr;
295
+ if (sc2 == nullptr) return false;
296
+ return sc1->json_string() == sc2->json_string();
297
+ }
298
+
299
+ bool XdsResolver::XdsConfigSelector::Route::ClusterWeightState::operator==(
300
+ const ClusterWeightState& other) const {
301
+ return range_end == other.range_end && cluster == other.cluster &&
302
+ MethodConfigsEqual(method_config.get(), other.method_config.get());
303
+ }
304
+
305
+ bool XdsResolver::XdsConfigSelector::Route::operator==(
306
+ const Route& other) const {
307
+ return route == other.route &&
308
+ weighted_cluster_state == other.weighted_cluster_state &&
309
+ MethodConfigsEqual(method_config.get(), other.method_config.get());
310
+ }
311
+
263
312
  //
264
313
  // XdsResolver::XdsConfigSelector
265
314
  //
266
315
 
267
316
  XdsResolver::XdsConfigSelector::XdsConfigSelector(
268
- RefCountedPtr<XdsResolver> resolver,
269
- const std::vector<XdsApi::Route>& routes, grpc_error* error)
317
+ RefCountedPtr<XdsResolver> resolver, grpc_error** error)
270
318
  : resolver_(std::move(resolver)) {
271
319
  if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_resolver_trace)) {
272
320
  gpr_log(GPR_INFO, "[xds_resolver %p] creating XdsConfigSelector %p",
@@ -281,8 +329,8 @@ XdsResolver::XdsConfigSelector::XdsConfigSelector(
281
329
  // weighted_cluster_state field points to the memory in the route field, so
282
330
  // moving the entry in a reallocation will cause the string_view to point to
283
331
  // invalid data.
284
- route_table_.reserve(routes.size());
285
- for (auto& route : routes) {
332
+ route_table_.reserve(resolver_->current_virtual_host_.routes.size());
333
+ for (auto& route : resolver_->current_virtual_host_.routes) {
286
334
  if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_resolver_trace)) {
287
335
  gpr_log(GPR_INFO, "[xds_resolver %p] XdsConfigSelector %p: route: %s",
288
336
  resolver_.get(), this, route.ToString().c_str());
@@ -294,27 +342,95 @@ XdsResolver::XdsConfigSelector::XdsConfigSelector(
294
342
  // one.
295
343
  if (!route.max_stream_duration.has_value()) {
296
344
  route_entry.route.max_stream_duration =
297
- resolver_->http_max_stream_duration_;
345
+ resolver_->current_listener_.http_connection_manager
346
+ .http_max_stream_duration;
298
347
  }
299
- error = CreateMethodConfig(&route_entry.method_config, route_entry.route);
300
348
  if (route.weighted_clusters.empty()) {
349
+ *error = CreateMethodConfig(route_entry.route, nullptr,
350
+ &route_entry.method_config);
301
351
  MaybeAddCluster(route.cluster_name);
302
352
  } else {
303
353
  uint32_t end = 0;
304
354
  for (const auto& weighted_cluster : route_entry.route.weighted_clusters) {
305
- MaybeAddCluster(weighted_cluster.name);
355
+ Route::ClusterWeightState cluster_weight_state;
356
+ *error = CreateMethodConfig(route_entry.route, &weighted_cluster,
357
+ &cluster_weight_state.method_config);
358
+ if (*error != GRPC_ERROR_NONE) return;
306
359
  end += weighted_cluster.weight;
307
- route_entry.weighted_cluster_state.emplace_back(end,
308
- weighted_cluster.name);
360
+ cluster_weight_state.range_end = end;
361
+ cluster_weight_state.cluster = weighted_cluster.name;
362
+ route_entry.weighted_cluster_state.push_back(
363
+ std::move(cluster_weight_state));
364
+ MaybeAddCluster(weighted_cluster.name);
309
365
  }
310
366
  }
311
367
  }
368
+ // Populate filter list.
369
+ bool found_router = false;
370
+ for (const auto& http_filter :
371
+ resolver_->current_listener_.http_connection_manager.http_filters) {
372
+ // Stop at the router filter. It's a no-op for us, and we ignore
373
+ // anything that may come after it, for compatibility with Envoy.
374
+ if (http_filter.config.config_proto_type_name ==
375
+ kXdsHttpRouterFilterConfigName) {
376
+ found_router = true;
377
+ break;
378
+ }
379
+ // Find filter. This is guaranteed to succeed, because it's checked
380
+ // at config validation time in the XdsApi code.
381
+ const XdsHttpFilterImpl* filter_impl =
382
+ XdsHttpFilterRegistry::GetFilterForType(
383
+ http_filter.config.config_proto_type_name);
384
+ GPR_ASSERT(filter_impl != nullptr);
385
+ // Add C-core filter to list.
386
+ filters_.push_back(filter_impl->channel_filter());
387
+ }
388
+ // For compatibility with Envoy, if the router filter is not
389
+ // configured, we fail all RPCs.
390
+ if (!found_router) {
391
+ filter_error_ =
392
+ grpc_error_set_int(GRPC_ERROR_CREATE_FROM_STATIC_STRING(
393
+ "no xDS HTTP router filter configured"),
394
+ GRPC_ERROR_INT_GRPC_STATUS, GRPC_STATUS_UNAVAILABLE);
395
+ filters_.push_back(&grpc_lame_filter);
396
+ }
397
+ }
398
+
399
+ XdsResolver::XdsConfigSelector::~XdsConfigSelector() {
400
+ if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_resolver_trace)) {
401
+ gpr_log(GPR_INFO, "[xds_resolver %p] destroying XdsConfigSelector %p",
402
+ resolver_.get(), this);
403
+ }
404
+ clusters_.clear();
405
+ resolver_->MaybeRemoveUnusedClusters();
406
+ GRPC_ERROR_UNREF(filter_error_);
407
+ }
408
+
409
+ const XdsHttpFilterImpl::FilterConfig* FindFilterConfigOverride(
410
+ const std::string& instance_name,
411
+ const XdsApi::RdsUpdate::VirtualHost& vhost, const XdsApi::Route& route,
412
+ const XdsApi::Route::ClusterWeight* cluster_weight) {
413
+ // Check ClusterWeight, if any.
414
+ if (cluster_weight != nullptr) {
415
+ auto it = cluster_weight->typed_per_filter_config.find(instance_name);
416
+ if (it != cluster_weight->typed_per_filter_config.end()) return &it->second;
417
+ }
418
+ // Check Route.
419
+ auto it = route.typed_per_filter_config.find(instance_name);
420
+ if (it != route.typed_per_filter_config.end()) return &it->second;
421
+ // Check VirtualHost.
422
+ it = vhost.typed_per_filter_config.find(instance_name);
423
+ if (it != vhost.typed_per_filter_config.end()) return &it->second;
424
+ // Not found.
425
+ return nullptr;
312
426
  }
313
427
 
314
428
  grpc_error* XdsResolver::XdsConfigSelector::CreateMethodConfig(
315
- RefCountedPtr<ServiceConfig>* method_config, const XdsApi::Route& route) {
316
- grpc_error* error = GRPC_ERROR_NONE;
429
+ const XdsApi::Route& route,
430
+ const XdsApi::Route::ClusterWeight* cluster_weight,
431
+ RefCountedPtr<ServiceConfig>* method_config) {
317
432
  std::vector<std::string> fields;
433
+ // Set timeout.
318
434
  if (route.max_stream_duration.has_value() &&
319
435
  (route.max_stream_duration->seconds != 0 ||
320
436
  route.max_stream_duration->nanos != 0)) {
@@ -322,6 +438,51 @@ grpc_error* XdsResolver::XdsConfigSelector::CreateMethodConfig(
322
438
  route.max_stream_duration->seconds,
323
439
  route.max_stream_duration->nanos));
324
440
  }
441
+ // Handle xDS HTTP filters.
442
+ std::map<std::string, std::vector<std::string>> per_filter_configs;
443
+ grpc_channel_args* args = grpc_channel_args_copy(resolver_->args_);
444
+ for (const auto& http_filter :
445
+ resolver_->current_listener_.http_connection_manager.http_filters) {
446
+ // Stop at the router filter. It's a no-op for us, and we ignore
447
+ // anything that may come after it, for compatibility with Envoy.
448
+ if (http_filter.config.config_proto_type_name ==
449
+ kXdsHttpRouterFilterConfigName) {
450
+ break;
451
+ }
452
+ // Find filter. This is guaranteed to succeed, because it's checked
453
+ // at config validation time in the XdsApi code.
454
+ const XdsHttpFilterImpl* filter_impl =
455
+ XdsHttpFilterRegistry::GetFilterForType(
456
+ http_filter.config.config_proto_type_name);
457
+ GPR_ASSERT(filter_impl != nullptr);
458
+ // Allow filter to add channel args that may affect service config
459
+ // parsing.
460
+ args = filter_impl->ModifyChannelArgs(args);
461
+ // Find config override, if any.
462
+ const XdsHttpFilterImpl::FilterConfig* config_override =
463
+ FindFilterConfigOverride(http_filter.name,
464
+ resolver_->current_virtual_host_, route,
465
+ cluster_weight);
466
+ // Generate service config for filter.
467
+ auto method_config_field =
468
+ filter_impl->GenerateServiceConfig(http_filter.config, config_override);
469
+ if (!method_config_field.ok()) {
470
+ return GRPC_ERROR_CREATE_FROM_COPIED_STRING(
471
+ absl::StrCat("failed to generate method config for HTTP filter ",
472
+ http_filter.name, ": ",
473
+ method_config_field.status().ToString())
474
+ .c_str());
475
+ }
476
+ per_filter_configs[method_config_field->service_config_field_name]
477
+ .push_back(method_config_field->element);
478
+ }
479
+ for (const auto& p : per_filter_configs) {
480
+ fields.emplace_back(absl::StrCat(" \"", p.first, "\": [\n",
481
+ absl::StrJoin(p.second, ",\n"),
482
+ "\n ]"));
483
+ }
484
+ // Construct service config.
485
+ grpc_error* error = GRPC_ERROR_NONE;
325
486
  if (!fields.empty()) {
326
487
  std::string json = absl::StrCat(
327
488
  "{\n"
@@ -333,19 +494,20 @@ grpc_error* XdsResolver::XdsConfigSelector::CreateMethodConfig(
333
494
  absl::StrJoin(fields, ",\n"),
334
495
  "\n } ]\n"
335
496
  "}");
336
- *method_config =
337
- ServiceConfig::Create(resolver_->args_, json.c_str(), &error);
497
+ *method_config = ServiceConfig::Create(args, json.c_str(), &error);
338
498
  }
499
+ grpc_channel_args_destroy(args);
339
500
  return error;
340
501
  }
341
502
 
342
- XdsResolver::XdsConfigSelector::~XdsConfigSelector() {
343
- if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_resolver_trace)) {
344
- gpr_log(GPR_INFO, "[xds_resolver %p] destroying XdsConfigSelector %p",
345
- resolver_.get(), this);
346
- }
347
- clusters_.clear();
348
- resolver_->MaybeRemoveUnusedClusters();
503
+ grpc_channel_args* XdsResolver::XdsConfigSelector::ModifyChannelArgs(
504
+ grpc_channel_args* args) {
505
+ if (filter_error_ == GRPC_ERROR_NONE) return args;
506
+ grpc_arg error_arg = MakeLameClientErrorArg(filter_error_);
507
+ grpc_channel_args* new_args =
508
+ grpc_channel_args_copy_and_add(args, &error_arg, 1);
509
+ grpc_channel_args_destroy(args);
510
+ return new_args;
349
511
  }
350
512
 
351
513
  void XdsResolver::XdsConfigSelector::MaybeAddCluster(const std::string& name) {
@@ -361,56 +523,52 @@ void XdsResolver::XdsConfigSelector::MaybeAddCluster(const std::string& name) {
361
523
  }
362
524
  }
363
525
 
364
- absl::optional<absl::string_view> GetMetadataValue(
365
- const std::string& target_key, grpc_metadata_batch* initial_metadata,
526
+ absl::optional<absl::string_view> GetHeaderValue(
527
+ grpc_metadata_batch* initial_metadata, absl::string_view header_name,
366
528
  std::string* concatenated_value) {
367
- // Find all values for the specified key.
368
- GPR_DEBUG_ASSERT(initial_metadata != nullptr);
369
- absl::InlinedVector<absl::string_view, 1> values;
370
- for (grpc_linked_mdelem* md = initial_metadata->list.head; md != nullptr;
371
- md = md->next) {
372
- absl::string_view key = StringViewFromSlice(GRPC_MDKEY(md->md));
373
- absl::string_view value = StringViewFromSlice(GRPC_MDVALUE(md->md));
374
- if (target_key == key) values.push_back(value);
375
- }
376
- // If none found, no match.
377
- if (values.empty()) return absl::nullopt;
378
- // If exactly one found, return it as-is.
379
- if (values.size() == 1) return values.front();
380
- // If more than one found, concatenate the values, using
381
- // *concatenated_values as a temporary holding place for the
382
- // concatenated string.
383
- *concatenated_value = absl::StrJoin(values, ",");
384
- return *concatenated_value;
385
- }
386
-
387
- bool HeaderMatchHelper(const HeaderMatcher& header_matcher,
388
- grpc_metadata_batch* initial_metadata) {
389
- std::string concatenated_value;
390
- absl::optional<absl::string_view> value;
391
529
  // Note: If we ever allow binary headers here, we still need to
392
530
  // special-case ignore "grpc-tags-bin" and "grpc-trace-bin", since
393
531
  // they are not visible to the LB policy in grpc-go.
394
- if (absl::EndsWith(header_matcher.name(), "-bin") ||
395
- header_matcher.name() == "grpc-previous-rpc-attempts") {
396
- value = absl::nullopt;
397
- } else if (header_matcher.name() == "content-type") {
398
- value = "application/grpc";
399
- } else {
400
- value = GetMetadataValue(header_matcher.name(), initial_metadata,
401
- &concatenated_value);
532
+ if (absl::EndsWith(header_name, "-bin")) {
533
+ return absl::nullopt;
534
+ } else if (header_name == "content-type") {
535
+ return "application/grpc";
402
536
  }
403
- return header_matcher.Match(value);
537
+ return grpc_metadata_batch_get_value(initial_metadata, header_name,
538
+ concatenated_value);
404
539
  }
405
540
 
406
541
  bool HeadersMatch(const std::vector<HeaderMatcher>& header_matchers,
407
542
  grpc_metadata_batch* initial_metadata) {
408
543
  for (const auto& header_matcher : header_matchers) {
409
- if (!HeaderMatchHelper(header_matcher, initial_metadata)) return false;
544
+ std::string concatenated_value;
545
+ if (!header_matcher.Match(GetHeaderValue(
546
+ initial_metadata, header_matcher.name(), &concatenated_value))) {
547
+ return false;
548
+ }
410
549
  }
411
550
  return true;
412
551
  }
413
552
 
553
+ absl::optional<uint64_t> HeaderHashHelper(
554
+ const XdsApi::Route::HashPolicy& policy,
555
+ grpc_metadata_batch* initial_metadata) {
556
+ GPR_ASSERT(policy.type == XdsApi::Route::HashPolicy::HEADER);
557
+ std::string value_buffer;
558
+ absl::optional<absl::string_view> header_value =
559
+ GetHeaderValue(initial_metadata, policy.header_name, &value_buffer);
560
+ if (policy.regex != nullptr) {
561
+ // If GetHeaderValue() did not already store the value in
562
+ // value_buffer, copy it there now, so we can modify it.
563
+ if (header_value->data() != value_buffer.data()) {
564
+ value_buffer = std::string(*header_value);
565
+ }
566
+ RE2::GlobalReplace(&value_buffer, *policy.regex, policy.regex_substitution);
567
+ header_value = value_buffer;
568
+ }
569
+ return XXH64(header_value->data(), header_value->size(), 0);
570
+ }
571
+
414
572
  bool UnderFraction(const uint32_t fraction_per_million) {
415
573
  // Generate a random number in [0, 1000000).
416
574
  const uint32_t random_number = rand() % 1000000;
@@ -437,13 +595,15 @@ ConfigSelector::CallConfig XdsResolver::XdsConfigSelector::GetCallConfig(
437
595
  }
438
596
  // Found a route match
439
597
  absl::string_view cluster_name;
598
+ RefCountedPtr<ServiceConfig> method_config;
440
599
  if (entry.route.weighted_clusters.empty()) {
441
600
  cluster_name = entry.route.cluster_name;
601
+ method_config = entry.method_config;
442
602
  } else {
443
603
  const uint32_t key =
444
604
  rand() %
445
605
  entry.weighted_cluster_state[entry.weighted_cluster_state.size() - 1]
446
- .first;
606
+ .range_end;
447
607
  // Find the index in weighted clusters corresponding to key.
448
608
  size_t mid = 0;
449
609
  size_t start_index = 0;
@@ -451,9 +611,9 @@ ConfigSelector::CallConfig XdsResolver::XdsConfigSelector::GetCallConfig(
451
611
  size_t index = 0;
452
612
  while (end_index > start_index) {
453
613
  mid = (start_index + end_index) / 2;
454
- if (entry.weighted_cluster_state[mid].first > key) {
614
+ if (entry.weighted_cluster_state[mid].range_end > key) {
455
615
  end_index = mid;
456
- } else if (entry.weighted_cluster_state[mid].first < key) {
616
+ } else if (entry.weighted_cluster_state[mid].range_end < key) {
457
617
  start_index = mid + 1;
458
618
  } else {
459
619
  index = mid + 1;
@@ -461,21 +621,56 @@ ConfigSelector::CallConfig XdsResolver::XdsConfigSelector::GetCallConfig(
461
621
  }
462
622
  }
463
623
  if (index == 0) index = start_index;
464
- GPR_ASSERT(entry.weighted_cluster_state[index].first > key);
465
- cluster_name = entry.weighted_cluster_state[index].second;
624
+ GPR_ASSERT(entry.weighted_cluster_state[index].range_end > key);
625
+ cluster_name = entry.weighted_cluster_state[index].cluster;
626
+ method_config = entry.weighted_cluster_state[index].method_config;
466
627
  }
467
628
  auto it = clusters_.find(cluster_name);
468
629
  GPR_ASSERT(it != clusters_.end());
469
630
  XdsResolver* resolver =
470
631
  static_cast<XdsResolver*>(resolver_->Ref().release());
471
632
  ClusterState* cluster_state = it->second->Ref().release();
633
+ // Generate a hash
634
+ absl::optional<uint64_t> hash;
635
+ for (const auto& hash_policy : entry.route.hash_policies) {
636
+ absl::optional<uint64_t> new_hash;
637
+ switch (hash_policy.type) {
638
+ case XdsApi::Route::HashPolicy::HEADER:
639
+ new_hash = HeaderHashHelper(hash_policy, args.initial_metadata);
640
+ break;
641
+ case XdsApi::Route::HashPolicy::CHANNEL_ID:
642
+ new_hash =
643
+ static_cast<uint64_t>(reinterpret_cast<uintptr_t>(resolver));
644
+ break;
645
+ default:
646
+ GPR_ASSERT(0);
647
+ }
648
+ if (new_hash.has_value()) {
649
+ // Rotating the old value prevents duplicate hash rules from cancelling
650
+ // each other out and preserves all of the entropy
651
+ const uint64_t old_value =
652
+ hash.has_value() ? ((hash.value() << 1) | (hash.value() >> 63)) : 0;
653
+ hash = old_value ^ new_hash.value();
654
+ }
655
+ // If the policy is a terminal policy and a hash has been generated,
656
+ // ignore the rest of the hash policies.
657
+ if (hash_policy.terminal && hash.has_value()) {
658
+ break;
659
+ }
660
+ }
661
+ if (!hash.has_value()) {
662
+ // If there is no hash, we just choose a random value as a default.
663
+ hash = rand();
664
+ }
472
665
  CallConfig call_config;
473
- if (entry.method_config != nullptr) {
474
- call_config.service_config = entry.method_config;
666
+ if (method_config != nullptr) {
475
667
  call_config.method_configs =
476
- entry.method_config->GetMethodParsedConfigVector(grpc_empty_slice());
668
+ method_config->GetMethodParsedConfigVector(grpc_empty_slice());
669
+ call_config.service_config = std::move(method_config);
477
670
  }
478
671
  call_config.call_attributes[kXdsClusterAttribute] = it->first;
672
+ call_config.call_attributes[kRequestRingHashAttribute] =
673
+ absl::StrFormat("%" PRIu64, hash.value());
479
674
  call_config.on_call_committed = [resolver, cluster_state]() {
480
675
  cluster_state->Unref();
481
676
  ExecCtx::Run(
@@ -563,24 +758,34 @@ void XdsResolver::OnListenerUpdate(XdsApi::LdsUpdate listener) {
563
758
  if (GRPC_TRACE_FLAG_ENABLED(grpc_xds_resolver_trace)) {
564
759
  gpr_log(GPR_INFO, "[xds_resolver %p] received updated listener data", this);
565
760
  }
566
- if (listener.route_config_name != route_config_name_) {
761
+ if (listener.http_connection_manager.route_config_name !=
762
+ route_config_name_) {
567
763
  if (route_config_watcher_ != nullptr) {
568
764
  xds_client_->CancelRouteConfigDataWatch(
569
765
  route_config_name_, route_config_watcher_,
570
- /*delay_unsubscription=*/!listener.route_config_name.empty());
766
+ /*delay_unsubscription=*/
767
+ !listener.http_connection_manager.route_config_name.empty());
571
768
  route_config_watcher_ = nullptr;
572
769
  }
573
- route_config_name_ = std::move(listener.route_config_name);
770
+ route_config_name_ =
771
+ std::move(listener.http_connection_manager.route_config_name);
574
772
  if (!route_config_name_.empty()) {
773
+ current_virtual_host_.routes.clear();
575
774
  auto watcher = absl::make_unique<RouteConfigWatcher>(Ref());
576
775
  route_config_watcher_ = watcher.get();
577
776
  xds_client_->WatchRouteConfigData(route_config_name_, std::move(watcher));
578
777
  }
579
778
  }
580
- http_max_stream_duration_ = listener.http_max_stream_duration;
779
+ current_listener_ = std::move(listener);
581
780
  if (route_config_name_.empty()) {
582
- GPR_ASSERT(listener.rds_update.has_value());
583
- OnRouteConfigUpdate(std::move(*listener.rds_update));
781
+ GPR_ASSERT(
782
+ current_listener_.http_connection_manager.rds_update.has_value());
783
+ OnRouteConfigUpdate(
784
+ std::move(*current_listener_.http_connection_manager.rds_update));
785
+ } else {
786
+ // HCM may contain newer filter config. We need to propagate the update as
787
+ // config selector to the channel
788
+ GenerateResult();
584
789
  }
585
790
  }
586
791
 
@@ -598,8 +803,8 @@ void XdsResolver::OnRouteConfigUpdate(XdsApi::RdsUpdate rds_update) {
598
803
  .c_str()));
599
804
  return;
600
805
  }
601
- // Save the list of routes in the resolver.
602
- current_update_ = std::move(vhost->routes);
806
+ // Save the virtual host in the resolver.
807
+ current_virtual_host_ = std::move(*vhost);
603
808
  // Send a new result to the channel.
604
809
  GenerateResult();
605
810
  }
@@ -618,7 +823,7 @@ void XdsResolver::OnResourceDoesNotExist() {
618
823
  "[xds_resolver %p] LDS/RDS resource does not exist -- clearing "
619
824
  "update and returning empty service config",
620
825
  this);
621
- current_update_.clear();
826
+ current_virtual_host_.routes.clear();
622
827
  Result result;
623
828
  result.service_config =
624
829
  ServiceConfig::Create(args_, "{}", &result.service_config_error);
@@ -660,12 +865,11 @@ grpc_error* XdsResolver::CreateServiceConfig(
660
865
  }
661
866
 
662
867
  void XdsResolver::GenerateResult() {
663
- if (current_update_.empty()) return;
868
+ if (current_virtual_host_.routes.empty()) return;
664
869
  // First create XdsConfigSelector, which may add new entries to the cluster
665
870
  // state map, and then CreateServiceConfig for LB policies.
666
871
  grpc_error* error = GRPC_ERROR_NONE;
667
- auto config_selector =
668
- MakeRefCounted<XdsConfigSelector>(Ref(), current_update_, error);
872
+ auto config_selector = MakeRefCounted<XdsConfigSelector>(Ref(), &error);
669
873
  if (error != GRPC_ERROR_NONE) {
670
874
  OnError(error);
671
875
  return;