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
@@ -18,12 +18,19 @@
18
18
 
19
19
  #include <grpc/support/port_platform.h>
20
20
 
21
+ #include "absl/strings/str_replace.h"
22
+
21
23
  #include "src/core/ext/xds/xds_certificate_provider.h"
22
24
  #include "src/core/ext/xds/xds_client.h"
23
25
  #include "src/core/lib/channel/channel_args.h"
26
+ #include "src/core/lib/gprpp/host_port.h"
27
+ #include "src/core/lib/iomgr/sockaddr.h"
28
+ #include "src/core/lib/iomgr/sockaddr_utils.h"
29
+ #include "src/core/lib/iomgr/socket_utils.h"
24
30
  #include "src/core/lib/security/credentials/xds/xds_credentials.h"
25
31
  #include "src/core/lib/surface/api_trace.h"
26
32
  #include "src/core/lib/surface/server.h"
33
+ #include "src/core/lib/uri/uri_parser.h"
27
34
 
28
35
  namespace grpc_core {
29
36
 
@@ -32,10 +39,305 @@ TraceFlag grpc_xds_server_config_fetcher_trace(false,
32
39
 
33
40
  namespace {
34
41
 
42
+ class FilterChainMatchManager
43
+ : public grpc_server_config_fetcher::ConnectionManager {
44
+ public:
45
+ FilterChainMatchManager(
46
+ RefCountedPtr<XdsClient> xds_client,
47
+ XdsApi::LdsUpdate::FilterChainMap filter_chain_map,
48
+ absl::optional<XdsApi::LdsUpdate::FilterChainData> default_filter_chain)
49
+ : xds_client_(xds_client),
50
+ filter_chain_map_(std::move(filter_chain_map)),
51
+ default_filter_chain_(std::move(default_filter_chain)) {}
52
+
53
+ absl::StatusOr<grpc_channel_args*> UpdateChannelArgsForConnection(
54
+ grpc_channel_args* args, grpc_endpoint* tcp) override;
55
+
56
+ const XdsApi::LdsUpdate::FilterChainMap& filter_chain_map() const {
57
+ return filter_chain_map_;
58
+ }
59
+
60
+ const absl::optional<XdsApi::LdsUpdate::FilterChainData>&
61
+ default_filter_chain() const {
62
+ return default_filter_chain_;
63
+ }
64
+
65
+ private:
66
+ struct CertificateProviders {
67
+ // We need to save our own refs to the root and instance certificate
68
+ // providers since the xds certificate provider just stores a ref to their
69
+ // distributors.
70
+ RefCountedPtr<grpc_tls_certificate_provider> root;
71
+ RefCountedPtr<grpc_tls_certificate_provider> instance;
72
+ RefCountedPtr<XdsCertificateProvider> xds;
73
+ };
74
+
75
+ absl::StatusOr<RefCountedPtr<XdsCertificateProvider>>
76
+ CreateOrGetXdsCertificateProviderFromFilterChainData(
77
+ const XdsApi::LdsUpdate::FilterChainData* filter_chain);
78
+
79
+ const RefCountedPtr<XdsClient> xds_client_;
80
+ const XdsApi::LdsUpdate::FilterChainMap filter_chain_map_;
81
+ const absl::optional<XdsApi::LdsUpdate::FilterChainData>
82
+ default_filter_chain_;
83
+ Mutex mu_;
84
+ std::map<const XdsApi::LdsUpdate::FilterChainData*, CertificateProviders>
85
+ certificate_providers_map_ ABSL_GUARDED_BY(mu_);
86
+ };
87
+
88
+ bool IsLoopbackIp(const grpc_resolved_address* address) {
89
+ const grpc_sockaddr* sock_addr =
90
+ reinterpret_cast<const grpc_sockaddr*>(&address->addr);
91
+ if (sock_addr->sa_family == GRPC_AF_INET) {
92
+ const grpc_sockaddr_in* addr4 =
93
+ reinterpret_cast<const grpc_sockaddr_in*>(sock_addr);
94
+ if (addr4->sin_addr.s_addr == grpc_htonl(INADDR_LOOPBACK)) {
95
+ return true;
96
+ }
97
+ } else if (sock_addr->sa_family == GRPC_AF_INET6) {
98
+ const grpc_sockaddr_in6* addr6 =
99
+ reinterpret_cast<const grpc_sockaddr_in6*>(sock_addr);
100
+ if (memcmp(&addr6->sin6_addr, &in6addr_loopback,
101
+ sizeof(in6addr_loopback)) == 0) {
102
+ return true;
103
+ }
104
+ }
105
+ return false;
106
+ }
107
+
108
+ const XdsApi::LdsUpdate::FilterChainData* FindFilterChainDataForSourcePort(
109
+ const XdsApi::LdsUpdate::FilterChainMap::SourcePortsMap& source_ports_map,
110
+ absl::string_view port_str) {
111
+ int port = 0;
112
+ if (!absl::SimpleAtoi(port_str, &port)) return nullptr;
113
+ auto it = source_ports_map.find(port);
114
+ if (it != source_ports_map.end()) {
115
+ return it->second.data.get();
116
+ }
117
+ // Search for the catch-all port 0 since we didn't get a direct match
118
+ it = source_ports_map.find(0);
119
+ if (it != source_ports_map.end()) {
120
+ return it->second.data.get();
121
+ }
122
+ return nullptr;
123
+ }
124
+
125
+ const XdsApi::LdsUpdate::FilterChainData* FindFilterChainDataForSourceIp(
126
+ const XdsApi::LdsUpdate::FilterChainMap::SourceIpVector& source_ip_vector,
127
+ const grpc_resolved_address* source_ip, absl::string_view port) {
128
+ const XdsApi::LdsUpdate::FilterChainMap::SourceIp* best_match = nullptr;
129
+ for (const auto& entry : source_ip_vector) {
130
+ // Special case for catch-all
131
+ if (!entry.prefix_range.has_value()) {
132
+ if (best_match == nullptr) {
133
+ best_match = &entry;
134
+ }
135
+ continue;
136
+ }
137
+ if (best_match != nullptr && best_match->prefix_range.has_value() &&
138
+ best_match->prefix_range->prefix_len >=
139
+ entry.prefix_range->prefix_len) {
140
+ continue;
141
+ }
142
+ if (grpc_sockaddr_match_subnet(source_ip, &entry.prefix_range->address,
143
+ entry.prefix_range->prefix_len)) {
144
+ best_match = &entry;
145
+ }
146
+ }
147
+ if (best_match == nullptr) return nullptr;
148
+ return FindFilterChainDataForSourcePort(best_match->ports_map, port);
149
+ }
150
+
151
+ const XdsApi::LdsUpdate::FilterChainData* FindFilterChainDataForSourceType(
152
+ const XdsApi::LdsUpdate::FilterChainMap::ConnectionSourceTypesArray&
153
+ source_types_array,
154
+ grpc_endpoint* tcp, absl::string_view destination_ip) {
155
+ auto source_uri = URI::Parse(grpc_endpoint_get_peer(tcp));
156
+ if (!source_uri.ok() ||
157
+ (source_uri->scheme() != "ipv4" && source_uri->scheme() != "ipv6")) {
158
+ return nullptr;
159
+ }
160
+ std::string host;
161
+ std::string port;
162
+ if (!SplitHostPort(source_uri->path(), &host, &port)) {
163
+ return nullptr;
164
+ }
165
+ grpc_resolved_address source_addr;
166
+ grpc_string_to_sockaddr(&source_addr, host.c_str(),
167
+ 0 /* port doesn't matter here */);
168
+ // Use kAny only if kSameIporLoopback and kExternal are empty
169
+ if (source_types_array[static_cast<int>(
170
+ XdsApi::LdsUpdate::FilterChainMap::
171
+ ConnectionSourceType::kSameIpOrLoopback)]
172
+ .empty() &&
173
+ source_types_array[static_cast<int>(XdsApi::LdsUpdate::FilterChainMap::
174
+ ConnectionSourceType::kExternal)]
175
+ .empty()) {
176
+ return FindFilterChainDataForSourceIp(
177
+ source_types_array[static_cast<int>(
178
+ XdsApi::LdsUpdate::FilterChainMap::ConnectionSourceType::kAny)],
179
+ &source_addr, port);
180
+ }
181
+ if (IsLoopbackIp(&source_addr) || host == destination_ip) {
182
+ return FindFilterChainDataForSourceIp(
183
+ source_types_array[static_cast<int>(
184
+ XdsApi::LdsUpdate::FilterChainMap::ConnectionSourceType::
185
+ kSameIpOrLoopback)],
186
+ &source_addr, port);
187
+ } else {
188
+ return FindFilterChainDataForSourceIp(
189
+ source_types_array[static_cast<int>(
190
+ XdsApi::LdsUpdate::FilterChainMap::ConnectionSourceType::
191
+ kExternal)],
192
+ &source_addr, port);
193
+ }
194
+ }
195
+
196
+ const XdsApi::LdsUpdate::FilterChainData* FindFilterChainDataForDestinationIp(
197
+ const XdsApi::LdsUpdate::FilterChainMap::DestinationIpVector
198
+ destination_ip_vector,
199
+ grpc_endpoint* tcp) {
200
+ auto destination_uri = URI::Parse(grpc_endpoint_get_local_address(tcp));
201
+ if (!destination_uri.ok() || (destination_uri->scheme() != "ipv4" &&
202
+ destination_uri->scheme() != "ipv6")) {
203
+ return nullptr;
204
+ }
205
+ std::string host;
206
+ std::string port;
207
+ if (!SplitHostPort(destination_uri->path(), &host, &port)) {
208
+ return nullptr;
209
+ }
210
+ grpc_resolved_address destination_addr;
211
+ grpc_string_to_sockaddr(&destination_addr, host.c_str(),
212
+ 0 /* port doesn't matter here */);
213
+ const XdsApi::LdsUpdate::FilterChainMap::DestinationIp* best_match = nullptr;
214
+ for (const auto& entry : destination_ip_vector) {
215
+ // Special case for catch-all
216
+ if (!entry.prefix_range.has_value()) {
217
+ if (best_match == nullptr) {
218
+ best_match = &entry;
219
+ }
220
+ continue;
221
+ }
222
+ if (best_match != nullptr && best_match->prefix_range.has_value() &&
223
+ best_match->prefix_range->prefix_len >=
224
+ entry.prefix_range->prefix_len) {
225
+ continue;
226
+ }
227
+ if (grpc_sockaddr_match_subnet(&destination_addr,
228
+ &entry.prefix_range->address,
229
+ entry.prefix_range->prefix_len)) {
230
+ best_match = &entry;
231
+ }
232
+ }
233
+ if (best_match == nullptr) return nullptr;
234
+ return FindFilterChainDataForSourceType(best_match->source_types_array, tcp,
235
+ host);
236
+ }
237
+
238
+ absl::StatusOr<RefCountedPtr<XdsCertificateProvider>>
239
+ FilterChainMatchManager::CreateOrGetXdsCertificateProviderFromFilterChainData(
240
+ const XdsApi::LdsUpdate::FilterChainData* filter_chain) {
241
+ MutexLock lock(&mu_);
242
+ auto it = certificate_providers_map_.find(filter_chain);
243
+ if (it != certificate_providers_map_.end()) {
244
+ return it->second.xds;
245
+ }
246
+ CertificateProviders certificate_providers;
247
+ // Configure root cert.
248
+ absl::string_view root_provider_instance_name =
249
+ filter_chain->downstream_tls_context.common_tls_context
250
+ .combined_validation_context
251
+ .validation_context_certificate_provider_instance.instance_name;
252
+ absl::string_view root_provider_cert_name =
253
+ filter_chain->downstream_tls_context.common_tls_context
254
+ .combined_validation_context
255
+ .validation_context_certificate_provider_instance.certificate_name;
256
+ if (!root_provider_instance_name.empty()) {
257
+ certificate_providers.root =
258
+ xds_client_->certificate_provider_store()
259
+ .CreateOrGetCertificateProvider(root_provider_instance_name);
260
+ if (certificate_providers.root == nullptr) {
261
+ return absl::NotFoundError(
262
+ absl::StrCat("Certificate provider instance name: \"",
263
+ root_provider_instance_name, "\" not recognized."));
264
+ }
265
+ }
266
+ // Configure identity cert.
267
+ absl::string_view identity_provider_instance_name =
268
+ filter_chain->downstream_tls_context.common_tls_context
269
+ .tls_certificate_certificate_provider_instance.instance_name;
270
+ absl::string_view identity_provider_cert_name =
271
+ filter_chain->downstream_tls_context.common_tls_context
272
+ .tls_certificate_certificate_provider_instance.certificate_name;
273
+ if (!identity_provider_instance_name.empty()) {
274
+ certificate_providers.instance =
275
+ xds_client_->certificate_provider_store()
276
+ .CreateOrGetCertificateProvider(identity_provider_instance_name);
277
+ if (certificate_providers.instance == nullptr) {
278
+ return absl::NotFoundError(
279
+ absl::StrCat("Certificate provider instance name: \"",
280
+ identity_provider_instance_name, "\" not recognized."));
281
+ }
282
+ }
283
+ certificate_providers.xds = MakeRefCounted<XdsCertificateProvider>();
284
+ certificate_providers.xds->UpdateRootCertNameAndDistributor(
285
+ "", root_provider_cert_name,
286
+ certificate_providers.root == nullptr
287
+ ? nullptr
288
+ : certificate_providers.root->distributor());
289
+ certificate_providers.xds->UpdateIdentityCertNameAndDistributor(
290
+ "", identity_provider_cert_name,
291
+ certificate_providers.instance == nullptr
292
+ ? nullptr
293
+ : certificate_providers.instance->distributor());
294
+ certificate_providers.xds->UpdateRequireClientCertificate(
295
+ "", filter_chain->downstream_tls_context.require_client_certificate);
296
+ auto xds_certificate_provider = certificate_providers.xds;
297
+ certificate_providers_map_.emplace(filter_chain,
298
+ std::move(certificate_providers));
299
+ return xds_certificate_provider;
300
+ }
301
+
302
+ absl::StatusOr<grpc_channel_args*>
303
+ FilterChainMatchManager::UpdateChannelArgsForConnection(grpc_channel_args* args,
304
+ grpc_endpoint* tcp) {
305
+ const auto* filter_chain = FindFilterChainDataForDestinationIp(
306
+ filter_chain_map_.destination_ip_vector, tcp);
307
+ if (filter_chain == nullptr && default_filter_chain_.has_value()) {
308
+ filter_chain = &default_filter_chain_.value();
309
+ }
310
+ if (filter_chain == nullptr) {
311
+ grpc_channel_args_destroy(args);
312
+ return absl::UnavailableError("No matching filter chain found");
313
+ }
314
+ // Nothing to update if credentials are not xDS.
315
+ grpc_server_credentials* server_creds =
316
+ grpc_find_server_credentials_in_args(args);
317
+ if (server_creds == nullptr || server_creds->type() != kCredentialsTypeXds) {
318
+ return args;
319
+ }
320
+ absl::StatusOr<RefCountedPtr<XdsCertificateProvider>> result =
321
+ CreateOrGetXdsCertificateProviderFromFilterChainData(filter_chain);
322
+ if (!result.ok()) {
323
+ grpc_channel_args_destroy(args);
324
+ return result.status();
325
+ }
326
+ RefCountedPtr<XdsCertificateProvider> xds_certificate_provider =
327
+ std::move(*result);
328
+ GPR_ASSERT(xds_certificate_provider != nullptr);
329
+ grpc_arg arg_to_add = xds_certificate_provider->MakeChannelArg();
330
+ grpc_channel_args* updated_args =
331
+ grpc_channel_args_copy_and_add(args, &arg_to_add, 1);
332
+ grpc_channel_args_destroy(args);
333
+ return updated_args;
334
+ }
335
+
35
336
  class XdsServerConfigFetcher : public grpc_server_config_fetcher {
36
337
  public:
37
- explicit XdsServerConfigFetcher(RefCountedPtr<XdsClient> xds_client)
38
- : xds_client_(std::move(xds_client)) {
338
+ explicit XdsServerConfigFetcher(RefCountedPtr<XdsClient> xds_client,
339
+ grpc_server_xds_status_notifier notifier)
340
+ : xds_client_(std::move(xds_client)), serving_status_notifier_(notifier) {
39
341
  GPR_ASSERT(xds_client_ != nullptr);
40
342
  }
41
343
 
@@ -44,11 +346,12 @@ class XdsServerConfigFetcher : public grpc_server_config_fetcher {
44
346
  watcher) override {
45
347
  grpc_server_config_fetcher::WatcherInterface* watcher_ptr = watcher.get();
46
348
  auto listener_watcher = absl::make_unique<ListenerWatcher>(
47
- std::move(watcher), args, xds_client_);
349
+ std::move(watcher), args, xds_client_, serving_status_notifier_,
350
+ listening_address);
48
351
  auto* listener_watcher_ptr = listener_watcher.get();
49
- // TODO(yashykt): Get the resource name id from bootstrap
50
- listening_address = absl::StrCat(
51
- "grpc/server?xds.resource.listening_address=", listening_address);
352
+ listening_address = absl::StrReplaceAll(
353
+ xds_client_->bootstrap().server_listener_resource_name_template(),
354
+ {{"%s", listening_address}});
52
355
  xds_client_->WatchListenerData(listening_address,
53
356
  std::move(listener_watcher));
54
357
  MutexLock lock(&mu_);
@@ -81,10 +384,14 @@ class XdsServerConfigFetcher : public grpc_server_config_fetcher {
81
384
  explicit ListenerWatcher(
82
385
  std::unique_ptr<grpc_server_config_fetcher::WatcherInterface>
83
386
  server_config_watcher,
84
- grpc_channel_args* args, RefCountedPtr<XdsClient> xds_client)
387
+ grpc_channel_args* args, RefCountedPtr<XdsClient> xds_client,
388
+ grpc_server_xds_status_notifier serving_status_notifier,
389
+ std::string listening_address)
85
390
  : server_config_watcher_(std::move(server_config_watcher)),
86
391
  args_(args),
87
- xds_client_(std::move(xds_client)) {}
392
+ xds_client_(std::move(xds_client)),
393
+ serving_status_notifier_(serving_status_notifier),
394
+ listening_address_(std::move(listening_address)) {}
88
395
 
89
396
  ~ListenerWatcher() override { grpc_channel_args_destroy(args_); }
90
397
 
@@ -100,140 +407,88 @@ class XdsServerConfigFetcher : public grpc_server_config_fetcher {
100
407
  "[ListenerWatcher %p] Received LDS update from xds client %p: %s",
101
408
  this, xds_client_.get(), listener.ToString().c_str());
102
409
  }
103
- grpc_error* error = GRPC_ERROR_NONE;
104
- bool update_needed = UpdateXdsCertificateProvider(listener, &error);
105
- if (error != GRPC_ERROR_NONE) {
106
- OnError(error);
410
+ if (listener.address != listening_address_) {
411
+ OnFatalError(absl::FailedPreconditionError(
412
+ "Address in LDS update does not match listening address"));
107
413
  return;
108
414
  }
109
- // Only send an update, if something changed.
110
- if (updated_once_ && !update_needed) {
111
- return;
415
+ if (filter_chain_match_manager_ == nullptr) {
416
+ if (serving_status_notifier_.on_serving_status_change != nullptr) {
417
+ serving_status_notifier_.on_serving_status_change(
418
+ serving_status_notifier_.user_data, listening_address_.c_str(),
419
+ GRPC_STATUS_OK, "");
420
+ } else {
421
+ gpr_log(GPR_INFO,
422
+ "xDS Listener resource obtained; will start serving on %s",
423
+ listening_address_.c_str());
424
+ }
112
425
  }
113
- updated_once_ = true;
114
- grpc_channel_args* updated_args = nullptr;
115
- if (xds_certificate_provider_ != nullptr) {
116
- grpc_arg arg_to_add = xds_certificate_provider_->MakeChannelArg();
117
- updated_args = grpc_channel_args_copy_and_add(args_, &arg_to_add, 1);
118
- } else {
119
- updated_args = grpc_channel_args_copy(args_);
426
+ if (filter_chain_match_manager_ == nullptr ||
427
+ !(listener.filter_chain_map ==
428
+ filter_chain_match_manager_->filter_chain_map() &&
429
+ listener.default_filter_chain ==
430
+ filter_chain_match_manager_->default_filter_chain())) {
431
+ filter_chain_match_manager_ = MakeRefCounted<FilterChainMatchManager>(
432
+ xds_client_, std::move(listener.filter_chain_map),
433
+ std::move(listener.default_filter_chain));
434
+ server_config_watcher_->UpdateConnectionManager(
435
+ filter_chain_match_manager_);
120
436
  }
121
- server_config_watcher_->UpdateConfig(updated_args);
122
437
  }
123
438
 
124
439
  void OnError(grpc_error* error) override {
125
- gpr_log(GPR_ERROR, "ListenerWatcher:%p XdsClient reports error: %s", this,
126
- grpc_error_string(error));
440
+ if (filter_chain_match_manager_ != nullptr) {
441
+ gpr_log(GPR_ERROR,
442
+ "ListenerWatcher:%p XdsClient reports error: %s for %s; "
443
+ "ignoring in favor of existing resource",
444
+ this, grpc_error_string(error), listening_address_.c_str());
445
+ } else {
446
+ if (serving_status_notifier_.on_serving_status_change != nullptr) {
447
+ serving_status_notifier_.on_serving_status_change(
448
+ serving_status_notifier_.user_data, listening_address_.c_str(),
449
+ GRPC_STATUS_UNAVAILABLE, grpc_error_string(error));
450
+ } else {
451
+ gpr_log(
452
+ GPR_ERROR,
453
+ "ListenerWatcher:%p error obtaining xDS Listener resource: %s; "
454
+ "not serving on %s",
455
+ this, grpc_error_string(error), listening_address_.c_str());
456
+ }
457
+ }
127
458
  GRPC_ERROR_UNREF(error);
128
- // TODO(yashykt): We might want to bubble this error to the application.
129
459
  }
130
460
 
131
- void OnResourceDoesNotExist() override {
132
- gpr_log(GPR_ERROR,
133
- "ListenerWatcher:%p XdsClient reports requested listener does "
134
- "not exist",
135
- this);
136
- // TODO(yashykt): We might want to bubble this error to the application.
137
- }
138
-
139
- private:
140
- // Returns true if the xds certificate provider changed in a way that
141
- // required a new security connector to be created, false otherwise.
142
- bool UpdateXdsCertificateProvider(const XdsApi::LdsUpdate& listener,
143
- grpc_error** error) {
144
- // Early out if channel is not configured to use xDS security.
145
- grpc_server_credentials* server_creds =
146
- grpc_find_server_credentials_in_args(args_);
147
- if (server_creds == nullptr ||
148
- server_creds->type() != kCredentialsTypeXds) {
149
- xds_certificate_provider_ = nullptr;
150
- return false;
461
+ void OnFatalError(absl::Status status) {
462
+ gpr_log(
463
+ GPR_ERROR,
464
+ "ListenerWatcher:%p Encountered fatal error %s; not serving on %s",
465
+ this, status.ToString().c_str(), listening_address_.c_str());
466
+ if (filter_chain_match_manager_ != nullptr) {
467
+ // The server has started listening already, so we need to gracefully
468
+ // stop serving.
469
+ server_config_watcher_->StopServing();
470
+ filter_chain_match_manager_.reset();
151
471
  }
152
- if (xds_certificate_provider_ == nullptr) {
153
- xds_certificate_provider_ = MakeRefCounted<XdsCertificateProvider>();
472
+ if (serving_status_notifier_.on_serving_status_change != nullptr) {
473
+ serving_status_notifier_.on_serving_status_change(
474
+ serving_status_notifier_.user_data, listening_address_.c_str(),
475
+ static_cast<grpc_status_code>(status.raw_code()),
476
+ std::string(status.message()).c_str());
154
477
  }
155
- // Configure root cert.
156
- absl::string_view root_provider_instance_name =
157
- listener.downstream_tls_context.common_tls_context
158
- .combined_validation_context
159
- .validation_context_certificate_provider_instance.instance_name;
160
- absl::string_view root_provider_cert_name =
161
- listener.downstream_tls_context.common_tls_context
162
- .combined_validation_context
163
- .validation_context_certificate_provider_instance
164
- .certificate_name;
165
- RefCountedPtr<grpc_tls_certificate_provider> new_root_provider;
166
- if (!root_provider_instance_name.empty()) {
167
- new_root_provider =
168
- xds_client_->certificate_provider_store()
169
- .CreateOrGetCertificateProvider(root_provider_instance_name);
170
- if (new_root_provider == nullptr) {
171
- *error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(
172
- absl::StrCat("Certificate provider instance name: \"",
173
- root_provider_instance_name, "\" not recognized.")
174
- .c_str());
175
- return false;
176
- }
177
- }
178
- // Configure identity cert.
179
- absl::string_view identity_provider_instance_name =
180
- listener.downstream_tls_context.common_tls_context
181
- .tls_certificate_certificate_provider_instance.instance_name;
182
- absl::string_view identity_provider_cert_name =
183
- listener.downstream_tls_context.common_tls_context
184
- .tls_certificate_certificate_provider_instance.certificate_name;
185
- RefCountedPtr<grpc_tls_certificate_provider> new_identity_provider;
186
- if (!identity_provider_instance_name.empty()) {
187
- new_identity_provider = xds_client_->certificate_provider_store()
188
- .CreateOrGetCertificateProvider(
189
- identity_provider_instance_name);
190
- if (new_identity_provider == nullptr) {
191
- *error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(
192
- absl::StrCat("Certificate provider instance name: \"",
193
- identity_provider_instance_name,
194
- "\" not recognized.")
195
- .c_str());
196
- return false;
197
- }
198
- }
199
- bool security_connector_update_required = false;
200
- if (((new_root_provider == nullptr) !=
201
- (root_certificate_provider_ == nullptr)) ||
202
- ((new_identity_provider == nullptr) !=
203
- (identity_certificate_provider_ == nullptr)) ||
204
- (listener.downstream_tls_context.require_client_certificate !=
205
- xds_certificate_provider_->GetRequireClientCertificate(""))) {
206
- security_connector_update_required = true;
207
- }
208
- if (root_certificate_provider_ != new_root_provider) {
209
- root_certificate_provider_ = std::move(new_root_provider);
210
- }
211
- if (identity_certificate_provider_ != new_identity_provider) {
212
- identity_certificate_provider_ = std::move(new_identity_provider);
213
- }
214
- xds_certificate_provider_->UpdateRootCertNameAndDistributor(
215
- "", root_provider_cert_name,
216
- root_certificate_provider_ == nullptr
217
- ? nullptr
218
- : root_certificate_provider_->distributor());
219
- xds_certificate_provider_->UpdateIdentityCertNameAndDistributor(
220
- "", identity_provider_cert_name,
221
- identity_certificate_provider_ == nullptr
222
- ? nullptr
223
- : identity_certificate_provider_->distributor());
224
- xds_certificate_provider_->UpdateRequireClientCertificate(
225
- "", listener.downstream_tls_context.require_client_certificate);
226
- return security_connector_update_required;
227
478
  }
228
479
 
480
+ void OnResourceDoesNotExist() override {
481
+ OnFatalError(absl::NotFoundError("Requested listener does not exist"));
482
+ }
483
+
484
+ private:
229
485
  std::unique_ptr<grpc_server_config_fetcher::WatcherInterface>
230
486
  server_config_watcher_;
231
487
  grpc_channel_args* args_;
232
488
  RefCountedPtr<XdsClient> xds_client_;
233
- RefCountedPtr<grpc_tls_certificate_provider> root_certificate_provider_;
234
- RefCountedPtr<grpc_tls_certificate_provider> identity_certificate_provider_;
235
- RefCountedPtr<XdsCertificateProvider> xds_certificate_provider_;
236
- bool updated_once_ = false;
489
+ grpc_server_xds_status_notifier serving_status_notifier_;
490
+ std::string listening_address_;
491
+ RefCountedPtr<FilterChainMatchManager> filter_chain_match_manager_;
237
492
  };
238
493
 
239
494
  struct WatcherState {
@@ -242,6 +497,7 @@ class XdsServerConfigFetcher : public grpc_server_config_fetcher {
242
497
  };
243
498
 
244
499
  RefCountedPtr<XdsClient> xds_client_;
500
+ grpc_server_xds_status_notifier serving_status_notifier_;
245
501
  Mutex mu_;
246
502
  std::map<grpc_server_config_fetcher::WatcherInterface*, WatcherState>
247
503
  watchers_;
@@ -250,7 +506,8 @@ class XdsServerConfigFetcher : public grpc_server_config_fetcher {
250
506
  } // namespace
251
507
  } // namespace grpc_core
252
508
 
253
- grpc_server_config_fetcher* grpc_server_config_fetcher_xds_create() {
509
+ grpc_server_config_fetcher* grpc_server_config_fetcher_xds_create(
510
+ grpc_server_xds_status_notifier notifier) {
254
511
  grpc_core::ApplicationCallbackExecCtx callback_exec_ctx;
255
512
  grpc_core::ExecCtx exec_ctx;
256
513
  GRPC_API_TRACE("grpc_server_config_fetcher_xds_create()", 0, ());
@@ -263,5 +520,13 @@ grpc_server_config_fetcher* grpc_server_config_fetcher_xds_create() {
263
520
  GRPC_ERROR_UNREF(error);
264
521
  return nullptr;
265
522
  }
266
- return new grpc_core::XdsServerConfigFetcher(std::move(xds_client));
523
+ if (xds_client->bootstrap()
524
+ .server_listener_resource_name_template()
525
+ .empty()) {
526
+ gpr_log(GPR_ERROR,
527
+ "server_listener_resource_name_template not provided in bootstrap "
528
+ "file.");
529
+ return nullptr;
530
+ }
531
+ return new grpc_core::XdsServerConfigFetcher(std::move(xds_client), notifier);
267
532
  }