grpc 1.26.0 → 1.27.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 (209) hide show
  1. checksums.yaml +4 -4
  2. data/Makefile +1654 -1519
  3. data/etc/roots.pem +44 -0
  4. data/include/grpc/grpc_security.h +37 -15
  5. data/include/grpc/grpc_security_constants.h +27 -0
  6. data/include/grpc/impl/codegen/grpc_types.h +14 -0
  7. data/include/grpc/impl/codegen/port_platform.h +1 -1
  8. data/src/core/ext/filters/client_channel/client_channel.cc +0 -20
  9. data/src/core/ext/filters/client_channel/http_proxy.cc +4 -4
  10. data/src/core/ext/filters/client_channel/lb_policy.cc +4 -3
  11. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc +191 -201
  12. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_balancer_addresses.cc +89 -0
  13. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_balancer_addresses.h +40 -0
  14. data/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.cc +3 -2
  15. data/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.cc +88 -121
  16. data/src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h +28 -57
  17. data/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h +0 -7
  18. data/src/core/ext/filters/client_channel/lb_policy/xds/cds.cc +8 -9
  19. data/src/core/ext/filters/client_channel/lb_policy/xds/xds.cc +53 -34
  20. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc +18 -5
  21. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc +24 -19
  22. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h +2 -1
  23. data/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.cc +4 -2
  24. data/src/core/ext/filters/client_channel/server_address.cc +6 -9
  25. data/src/core/ext/filters/client_channel/server_address.h +3 -10
  26. data/src/core/ext/filters/client_channel/xds/xds_api.cc +394 -150
  27. data/src/core/ext/filters/client_channel/xds/xds_api.h +75 -35
  28. data/src/core/ext/filters/client_channel/xds/xds_bootstrap.cc +59 -22
  29. data/src/core/ext/filters/client_channel/xds/xds_bootstrap.h +13 -9
  30. data/src/core/ext/filters/client_channel/xds/xds_channel_secure.cc +8 -6
  31. data/src/core/ext/filters/client_channel/xds/xds_client.cc +456 -175
  32. data/src/core/ext/filters/client_channel/xds/xds_client.h +33 -21
  33. data/src/core/ext/filters/client_channel/xds/xds_client_stats.cc +5 -8
  34. data/src/core/ext/filters/client_channel/xds/xds_client_stats.h +18 -24
  35. data/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +2 -2
  36. data/src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.c +13 -5
  37. data/src/core/ext/upb-generated/src/proto/grpc/lb/v1/load_balancer.upb.h +34 -0
  38. data/src/core/lib/channel/channelz.h +11 -1
  39. data/src/core/lib/gpr/time_precise.cc +1 -1
  40. data/src/core/lib/gprpp/optional.h +26 -0
  41. data/src/core/lib/gprpp/string_view.h +14 -10
  42. data/src/core/lib/iomgr/executor.cc +1 -1
  43. data/src/core/lib/iomgr/fork_posix.cc +4 -0
  44. data/src/core/lib/iomgr/poller/eventmanager_libuv.cc +87 -0
  45. data/src/core/lib/iomgr/poller/eventmanager_libuv.h +88 -0
  46. data/src/core/lib/iomgr/socket_utils_common_posix.cc +14 -0
  47. data/src/core/lib/iomgr/socket_utils_posix.h +12 -0
  48. data/src/core/lib/iomgr/tcp_custom.h +3 -0
  49. data/src/core/lib/iomgr/tcp_posix.cc +607 -56
  50. data/src/core/lib/iomgr/tcp_server_custom.cc +15 -2
  51. data/src/core/lib/iomgr/tcp_server_utils_posix_common.cc +8 -0
  52. data/src/core/lib/json/json.h +11 -1
  53. data/src/core/lib/json/json_reader.cc +206 -28
  54. data/src/core/lib/json/json_writer.cc +111 -24
  55. data/src/core/lib/security/credentials/composite/composite_credentials.cc +7 -0
  56. data/src/core/lib/security/credentials/composite/composite_credentials.h +5 -1
  57. data/src/core/lib/security/credentials/credentials.h +10 -1
  58. data/src/core/lib/security/credentials/fake/fake_credentials.h +2 -1
  59. data/src/core/lib/security/credentials/oauth2/oauth2_credentials.cc +1 -1
  60. data/src/core/lib/security/credentials/plugin/plugin_credentials.cc +6 -4
  61. data/src/core/lib/security/credentials/plugin/plugin_credentials.h +2 -1
  62. data/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.cc +20 -0
  63. data/src/core/lib/security/credentials/tls/grpc_tls_credentials_options.h +8 -0
  64. data/src/core/lib/security/credentials/tls/{spiffe_credentials.cc → tls_credentials.cc} +23 -24
  65. data/src/core/lib/security/credentials/tls/{spiffe_credentials.h → tls_credentials.h} +9 -9
  66. data/src/core/lib/security/security_connector/alts/alts_security_connector.cc +13 -0
  67. data/src/core/lib/security/security_connector/fake/fake_security_connector.cc +22 -2
  68. data/src/core/lib/security/security_connector/load_system_roots_fallback.cc +2 -2
  69. data/src/core/lib/security/security_connector/load_system_roots_linux.cc +2 -2
  70. data/src/core/lib/security/security_connector/local/local_security_connector.cc +30 -3
  71. data/src/core/lib/security/security_connector/ssl_utils.cc +45 -3
  72. data/src/core/lib/security/security_connector/ssl_utils.h +12 -0
  73. data/src/core/lib/security/security_connector/tls/{spiffe_security_connector.cc → tls_security_connector.cc} +82 -69
  74. data/src/core/lib/security/security_connector/tls/{spiffe_security_connector.h → tls_security_connector.h} +17 -18
  75. data/src/core/lib/security/transport/client_auth_filter.cc +33 -0
  76. data/src/core/lib/surface/completion_queue.cc +22 -1
  77. data/src/core/lib/surface/version.cc +1 -1
  78. data/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc +11 -1
  79. data/src/core/tsi/alts/handshaker/alts_tsi_handshaker.h +1 -1
  80. data/src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.cc +3 -3
  81. data/src/core/tsi/fake_transport_security.cc +7 -3
  82. data/src/core/tsi/fake_transport_security.h +2 -0
  83. data/src/core/tsi/ssl_transport_security.cc +144 -8
  84. data/src/core/tsi/ssl_transport_security.h +15 -1
  85. data/src/core/tsi/transport_security.cc +13 -0
  86. data/src/core/tsi/transport_security_grpc.cc +2 -2
  87. data/src/core/tsi/transport_security_grpc.h +2 -2
  88. data/src/core/tsi/transport_security_interface.h +12 -0
  89. data/src/ruby/bin/math_pb.rb +5 -5
  90. data/src/ruby/ext/grpc/rb_call_credentials.c +4 -1
  91. data/src/ruby/ext/grpc/rb_grpc_imports.generated.c +2 -0
  92. data/src/ruby/ext/grpc/rb_grpc_imports.generated.h +4 -1
  93. data/src/ruby/lib/grpc/version.rb +1 -1
  94. data/src/ruby/pb/grpc/health/v1/health_pb.rb +3 -3
  95. data/src/ruby/pb/src/proto/grpc/testing/empty_pb.rb +1 -1
  96. data/src/ruby/pb/src/proto/grpc/testing/messages_pb.rb +23 -13
  97. data/third_party/abseil-cpp/absl/algorithm/algorithm.h +159 -0
  98. data/third_party/abseil-cpp/absl/base/attributes.h +609 -0
  99. data/third_party/abseil-cpp/absl/base/call_once.h +226 -0
  100. data/third_party/abseil-cpp/absl/base/casts.h +184 -0
  101. data/third_party/abseil-cpp/absl/base/config.h +622 -0
  102. data/third_party/abseil-cpp/absl/base/const_init.h +76 -0
  103. data/third_party/abseil-cpp/absl/base/dynamic_annotations.cc +129 -0
  104. data/third_party/abseil-cpp/absl/base/dynamic_annotations.h +389 -0
  105. data/third_party/abseil-cpp/absl/base/internal/atomic_hook.h +179 -0
  106. data/third_party/abseil-cpp/absl/base/internal/bits.h +218 -0
  107. data/third_party/abseil-cpp/absl/base/internal/cycleclock.cc +107 -0
  108. data/third_party/abseil-cpp/absl/base/internal/cycleclock.h +94 -0
  109. data/third_party/abseil-cpp/absl/base/internal/endian.h +266 -0
  110. data/third_party/abseil-cpp/absl/base/internal/hide_ptr.h +51 -0
  111. data/third_party/abseil-cpp/absl/base/internal/identity.h +37 -0
  112. data/third_party/abseil-cpp/absl/base/internal/inline_variable.h +107 -0
  113. data/third_party/abseil-cpp/absl/base/internal/invoke.h +187 -0
  114. data/third_party/abseil-cpp/absl/base/internal/low_level_scheduling.h +107 -0
  115. data/third_party/abseil-cpp/absl/base/internal/per_thread_tls.h +52 -0
  116. data/third_party/abseil-cpp/absl/base/internal/raw_logging.cc +237 -0
  117. data/third_party/abseil-cpp/absl/base/internal/raw_logging.h +179 -0
  118. data/third_party/abseil-cpp/absl/base/internal/scheduling_mode.h +58 -0
  119. data/third_party/abseil-cpp/absl/base/internal/spinlock.cc +233 -0
  120. data/third_party/abseil-cpp/absl/base/internal/spinlock.h +243 -0
  121. data/third_party/abseil-cpp/absl/base/internal/spinlock_akaros.inc +35 -0
  122. data/third_party/abseil-cpp/absl/base/internal/spinlock_linux.inc +67 -0
  123. data/third_party/abseil-cpp/absl/base/internal/spinlock_posix.inc +46 -0
  124. data/third_party/abseil-cpp/absl/base/internal/spinlock_wait.cc +81 -0
  125. data/third_party/abseil-cpp/absl/base/internal/spinlock_wait.h +93 -0
  126. data/third_party/abseil-cpp/absl/base/internal/spinlock_win32.inc +37 -0
  127. data/third_party/abseil-cpp/absl/base/internal/sysinfo.cc +414 -0
  128. data/third_party/abseil-cpp/absl/base/internal/sysinfo.h +66 -0
  129. data/third_party/abseil-cpp/absl/base/internal/thread_annotations.h +271 -0
  130. data/third_party/abseil-cpp/absl/base/internal/thread_identity.cc +140 -0
  131. data/third_party/abseil-cpp/absl/base/internal/thread_identity.h +250 -0
  132. data/third_party/abseil-cpp/absl/base/internal/throw_delegate.cc +108 -0
  133. data/third_party/abseil-cpp/absl/base/internal/throw_delegate.h +75 -0
  134. data/third_party/abseil-cpp/absl/base/internal/tsan_mutex_interface.h +66 -0
  135. data/third_party/abseil-cpp/absl/base/internal/unaligned_access.h +158 -0
  136. data/third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.cc +103 -0
  137. data/third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.h +124 -0
  138. data/third_party/abseil-cpp/absl/base/log_severity.cc +27 -0
  139. data/third_party/abseil-cpp/absl/base/log_severity.h +121 -0
  140. data/third_party/abseil-cpp/absl/base/macros.h +220 -0
  141. data/third_party/abseil-cpp/absl/base/optimization.h +181 -0
  142. data/third_party/abseil-cpp/absl/base/options.h +214 -0
  143. data/third_party/abseil-cpp/absl/base/policy_checks.h +111 -0
  144. data/third_party/abseil-cpp/absl/base/port.h +26 -0
  145. data/third_party/abseil-cpp/absl/base/thread_annotations.h +280 -0
  146. data/third_party/abseil-cpp/absl/container/inlined_vector.h +848 -0
  147. data/third_party/abseil-cpp/absl/container/internal/compressed_tuple.h +265 -0
  148. data/third_party/abseil-cpp/absl/container/internal/inlined_vector.h +892 -0
  149. data/third_party/abseil-cpp/absl/memory/memory.h +695 -0
  150. data/third_party/abseil-cpp/absl/meta/type_traits.h +759 -0
  151. data/third_party/abseil-cpp/absl/numeric/int128.cc +404 -0
  152. data/third_party/abseil-cpp/absl/numeric/int128.h +1091 -0
  153. data/third_party/abseil-cpp/absl/numeric/int128_have_intrinsic.inc +302 -0
  154. data/third_party/abseil-cpp/absl/numeric/int128_no_intrinsic.inc +308 -0
  155. data/third_party/abseil-cpp/absl/strings/ascii.cc +200 -0
  156. data/third_party/abseil-cpp/absl/strings/ascii.h +241 -0
  157. data/third_party/abseil-cpp/absl/strings/charconv.cc +985 -0
  158. data/third_party/abseil-cpp/absl/strings/charconv.h +119 -0
  159. data/third_party/abseil-cpp/absl/strings/escaping.cc +949 -0
  160. data/third_party/abseil-cpp/absl/strings/escaping.h +164 -0
  161. data/third_party/abseil-cpp/absl/strings/internal/char_map.h +156 -0
  162. data/third_party/abseil-cpp/absl/strings/internal/charconv_bigint.cc +359 -0
  163. data/third_party/abseil-cpp/absl/strings/internal/charconv_bigint.h +421 -0
  164. data/third_party/abseil-cpp/absl/strings/internal/charconv_parse.cc +504 -0
  165. data/third_party/abseil-cpp/absl/strings/internal/charconv_parse.h +99 -0
  166. data/third_party/abseil-cpp/absl/strings/internal/escaping.cc +180 -0
  167. data/third_party/abseil-cpp/absl/strings/internal/escaping.h +58 -0
  168. data/third_party/abseil-cpp/absl/strings/internal/memutil.cc +112 -0
  169. data/third_party/abseil-cpp/absl/strings/internal/memutil.h +148 -0
  170. data/third_party/abseil-cpp/absl/strings/internal/ostringstream.cc +36 -0
  171. data/third_party/abseil-cpp/absl/strings/internal/ostringstream.h +89 -0
  172. data/third_party/abseil-cpp/absl/strings/internal/resize_uninitialized.h +73 -0
  173. data/third_party/abseil-cpp/absl/strings/internal/stl_type_traits.h +248 -0
  174. data/third_party/abseil-cpp/absl/strings/internal/str_join_internal.h +314 -0
  175. data/third_party/abseil-cpp/absl/strings/internal/str_split_internal.h +455 -0
  176. data/third_party/abseil-cpp/absl/strings/internal/utf8.cc +53 -0
  177. data/third_party/abseil-cpp/absl/strings/internal/utf8.h +50 -0
  178. data/third_party/abseil-cpp/absl/strings/match.cc +40 -0
  179. data/third_party/abseil-cpp/absl/strings/match.h +90 -0
  180. data/third_party/abseil-cpp/absl/strings/numbers.cc +916 -0
  181. data/third_party/abseil-cpp/absl/strings/numbers.h +263 -0
  182. data/third_party/abseil-cpp/absl/strings/str_cat.cc +246 -0
  183. data/third_party/abseil-cpp/absl/strings/str_cat.h +408 -0
  184. data/third_party/abseil-cpp/absl/strings/str_join.h +293 -0
  185. data/third_party/abseil-cpp/absl/strings/str_replace.cc +82 -0
  186. data/third_party/abseil-cpp/absl/strings/str_replace.h +219 -0
  187. data/third_party/abseil-cpp/absl/strings/str_split.cc +139 -0
  188. data/third_party/abseil-cpp/absl/strings/str_split.h +513 -0
  189. data/third_party/abseil-cpp/absl/strings/string_view.cc +235 -0
  190. data/third_party/abseil-cpp/absl/strings/string_view.h +615 -0
  191. data/third_party/abseil-cpp/absl/strings/strip.h +91 -0
  192. data/third_party/abseil-cpp/absl/strings/substitute.cc +171 -0
  193. data/third_party/abseil-cpp/absl/strings/substitute.h +693 -0
  194. data/third_party/abseil-cpp/absl/types/bad_optional_access.cc +48 -0
  195. data/third_party/abseil-cpp/absl/types/bad_optional_access.h +78 -0
  196. data/third_party/abseil-cpp/absl/types/internal/optional.h +396 -0
  197. data/third_party/abseil-cpp/absl/types/internal/span.h +128 -0
  198. data/third_party/abseil-cpp/absl/types/optional.h +776 -0
  199. data/third_party/abseil-cpp/absl/types/span.h +713 -0
  200. data/third_party/abseil-cpp/absl/utility/utility.h +350 -0
  201. data/third_party/upb/upb/decode.c +4 -0
  202. data/third_party/upb/upb/port.c +0 -1
  203. data/third_party/upb/upb/port_def.inc +1 -3
  204. data/third_party/upb/upb/table.c +2 -1
  205. metadata +147 -43
  206. data/src/core/lib/json/json_common.h +0 -34
  207. data/src/core/lib/json/json_reader.h +0 -146
  208. data/src/core/lib/json/json_string.cc +0 -367
  209. data/src/core/lib/json/json_writer.h +0 -84
@@ -63,7 +63,8 @@ extern void (*grpc_resolve_address_ares)(const char* name,
63
63
  extern grpc_ares_request* (*grpc_dns_lookup_ares_locked)(
64
64
  const char* dns_server, const char* name, const char* default_port,
65
65
  grpc_pollset_set* interested_parties, grpc_closure* on_done,
66
- std::unique_ptr<grpc_core::ServerAddressList>* addresses, bool check_grpclb,
66
+ std::unique_ptr<grpc_core::ServerAddressList>* addresses,
67
+ std::unique_ptr<grpc_core::ServerAddressList>* balancer_addresses,
67
68
  char** service_config_json, int query_timeout_ms,
68
69
  grpc_core::Combiner* combiner);
69
70
 
@@ -29,7 +29,8 @@ struct grpc_ares_request {
29
29
  static grpc_ares_request* grpc_dns_lookup_ares_locked_impl(
30
30
  const char* dns_server, const char* name, const char* default_port,
31
31
  grpc_pollset_set* interested_parties, grpc_closure* on_done,
32
- std::unique_ptr<grpc_core::ServerAddressList>* addrs, bool check_grpclb,
32
+ std::unique_ptr<grpc_core::ServerAddressList>* addrs,
33
+ std::unique_ptr<grpc_core::ServerAddressList>* balancer_addrs,
33
34
  char** service_config_json, int query_timeout_ms,
34
35
  grpc_core::Combiner* combiner) {
35
36
  return NULL;
@@ -38,7 +39,8 @@ static grpc_ares_request* grpc_dns_lookup_ares_locked_impl(
38
39
  grpc_ares_request* (*grpc_dns_lookup_ares_locked)(
39
40
  const char* dns_server, const char* name, const char* default_port,
40
41
  grpc_pollset_set* interested_parties, grpc_closure* on_done,
41
- std::unique_ptr<grpc_core::ServerAddressList>* addrs, bool check_grpclb,
42
+ std::unique_ptr<grpc_core::ServerAddressList>* addrs,
43
+ std::unique_ptr<grpc_core::ServerAddressList>* balancer_addrs,
42
44
  char** service_config_json, int query_timeout_ms,
43
45
  grpc_core::Combiner* combiner) = grpc_dns_lookup_ares_locked_impl;
44
46
 
@@ -37,15 +37,12 @@ ServerAddress::ServerAddress(const void* address, size_t address_len,
37
37
  address_.len = static_cast<socklen_t>(address_len);
38
38
  }
39
39
 
40
- bool ServerAddress::operator==(const ServerAddress& other) const {
41
- return address_.len == other.address_.len &&
42
- memcmp(address_.addr, other.address_.addr, address_.len) == 0 &&
43
- grpc_channel_args_compare(args_, other.args_) == 0;
44
- }
45
-
46
- bool ServerAddress::IsBalancer() const {
47
- return grpc_channel_arg_get_bool(
48
- grpc_channel_args_find(args_, GRPC_ARG_ADDRESS_IS_BALANCER), false);
40
+ int ServerAddress::Cmp(const ServerAddress& other) const {
41
+ if (address_.len > other.address_.len) return 1;
42
+ if (address_.len < other.address_.len) return -1;
43
+ int retval = memcmp(address_.addr, other.address_.addr, address_.len);
44
+ if (retval != 0) return retval;
45
+ return grpc_channel_args_compare(args_, other.args_);
49
46
  }
50
47
 
51
48
  } // namespace grpc_core
@@ -25,13 +25,6 @@
25
25
  #include "src/core/lib/gprpp/inlined_vector.h"
26
26
  #include "src/core/lib/iomgr/resolve_address.h"
27
27
 
28
- // Channel arg key for a bool indicating whether an address is a grpclb
29
- // load balancer (as opposed to a backend).
30
- #define GRPC_ARG_ADDRESS_IS_BALANCER "grpc.address_is_balancer"
31
-
32
- // Channel arg key for a string indicating an address's balancer name.
33
- #define GRPC_ARG_ADDRESS_BALANCER_NAME "grpc.address_balancer_name"
34
-
35
28
  namespace grpc_core {
36
29
 
37
30
  //
@@ -73,13 +66,13 @@ class ServerAddress {
73
66
  return *this;
74
67
  }
75
68
 
76
- bool operator==(const ServerAddress& other) const;
69
+ bool operator==(const ServerAddress& other) const { return Cmp(other) == 0; }
70
+
71
+ int Cmp(const ServerAddress& other) const;
77
72
 
78
73
  const grpc_resolved_address& address() const { return address_; }
79
74
  const grpc_channel_args* args() const { return args_; }
80
75
 
81
- bool IsBalancer() const;
82
-
83
76
  private:
84
77
  grpc_resolved_address address_;
85
78
  grpc_channel_args* args_;
@@ -25,11 +25,14 @@
25
25
  #include <grpc/support/string_util.h>
26
26
 
27
27
  #include "src/core/ext/filters/client_channel/xds/xds_api.h"
28
+ #include "src/core/lib/gprpp/inlined_vector.h"
28
29
  #include "src/core/lib/iomgr/error.h"
29
30
  #include "src/core/lib/iomgr/sockaddr_utils.h"
30
31
 
32
+ #include "envoy/api/v2/cds.upb.h"
31
33
  #include "envoy/api/v2/core/address.upb.h"
32
34
  #include "envoy/api/v2/core/base.upb.h"
35
+ #include "envoy/api/v2/core/config_source.upb.h"
33
36
  #include "envoy/api/v2/core/health_check.upb.h"
34
37
  #include "envoy/api/v2/discovery.upb.h"
35
38
  #include "envoy/api/v2/eds.upb.h"
@@ -40,19 +43,12 @@
40
43
  #include "google/protobuf/any.upb.h"
41
44
  #include "google/protobuf/duration.upb.h"
42
45
  #include "google/protobuf/struct.upb.h"
43
- #include "google/protobuf/timestamp.upb.h"
44
46
  #include "google/protobuf/wrappers.upb.h"
47
+ #include "google/rpc/status.upb.h"
45
48
  #include "upb/upb.h"
46
49
 
47
50
  namespace grpc_core {
48
51
 
49
- namespace {
50
-
51
- constexpr char kEdsTypeUrl[] =
52
- "type.googleapis.com/envoy.api.v2.ClusterLoadAssignment";
53
-
54
- } // namespace
55
-
56
52
  bool XdsPriorityListUpdate::operator==(
57
53
  const XdsPriorityListUpdate& other) const {
58
54
  if (priorities_.size() != other.priorities_.size()) return false;
@@ -88,8 +84,7 @@ bool XdsPriorityListUpdate::Contains(
88
84
  return false;
89
85
  }
90
86
 
91
- bool XdsDropConfig::ShouldDrop(
92
- const grpc_core::UniquePtr<char>** category_name) const {
87
+ bool XdsDropConfig::ShouldDrop(const std::string** category_name) const {
93
88
  for (size_t i = 0; i < drop_category_list_.size(); ++i) {
94
89
  const auto& drop_category = drop_category_list_[i];
95
90
  // Generate a random number in [0, 1000000).
@@ -199,20 +194,141 @@ void PopulateNode(upb_arena* arena, const XdsBootstrap::Node* node,
199
194
 
200
195
  } // namespace
201
196
 
202
- grpc_slice XdsEdsRequestCreateAndEncode(const char* server_name,
203
- const XdsBootstrap::Node* node,
204
- const char* build_version) {
197
+ grpc_slice XdsUnsupportedTypeNackRequestCreateAndEncode(
198
+ const std::string& type_url, const std::string& nonce, grpc_error* error) {
205
199
  upb::Arena arena;
206
200
  // Create a request.
207
201
  envoy_api_v2_DiscoveryRequest* request =
208
202
  envoy_api_v2_DiscoveryRequest_new(arena.ptr());
209
- envoy_api_v2_core_Node* node_msg =
210
- envoy_api_v2_DiscoveryRequest_mutable_node(request, arena.ptr());
211
- PopulateNode(arena.ptr(), node, build_version, node_msg);
212
- envoy_api_v2_DiscoveryRequest_add_resource_names(
213
- request, upb_strview_makez(server_name), arena.ptr());
203
+ // Set type_url.
204
+ envoy_api_v2_DiscoveryRequest_set_type_url(
205
+ request, upb_strview_makez(type_url.c_str()));
206
+ // Set nonce.
207
+ envoy_api_v2_DiscoveryRequest_set_response_nonce(
208
+ request, upb_strview_makez(nonce.c_str()));
209
+ // Set error_detail.
210
+ grpc_slice error_description_slice;
211
+ GPR_ASSERT(grpc_error_get_str(error, GRPC_ERROR_STR_DESCRIPTION,
212
+ &error_description_slice));
213
+ upb_strview error_description_strview =
214
+ upb_strview_make(reinterpret_cast<const char*>(
215
+ GPR_SLICE_START_PTR(error_description_slice)),
216
+ GPR_SLICE_LENGTH(error_description_slice));
217
+ google_rpc_Status* error_detail =
218
+ envoy_api_v2_DiscoveryRequest_mutable_error_detail(request, arena.ptr());
219
+ google_rpc_Status_set_message(error_detail, error_description_strview);
220
+ GRPC_ERROR_UNREF(error);
221
+ // Encode the request.
222
+ size_t output_length;
223
+ char* output = envoy_api_v2_DiscoveryRequest_serialize(request, arena.ptr(),
224
+ &output_length);
225
+ return grpc_slice_from_copied_buffer(output, output_length);
226
+ }
227
+
228
+ grpc_slice XdsCdsRequestCreateAndEncode(
229
+ const std::set<StringView>& cluster_names, const XdsBootstrap::Node* node,
230
+ const char* build_version, const std::string& version,
231
+ const std::string& nonce, grpc_error* error) {
232
+ upb::Arena arena;
233
+ // Create a request.
234
+ envoy_api_v2_DiscoveryRequest* request =
235
+ envoy_api_v2_DiscoveryRequest_new(arena.ptr());
236
+ // Set version_info.
237
+ if (!version.empty()) {
238
+ envoy_api_v2_DiscoveryRequest_set_version_info(
239
+ request, upb_strview_makez(version.c_str()));
240
+ }
241
+ // Populate node.
242
+ if (build_version != nullptr) {
243
+ envoy_api_v2_core_Node* node_msg =
244
+ envoy_api_v2_DiscoveryRequest_mutable_node(request, arena.ptr());
245
+ PopulateNode(arena.ptr(), node, build_version, node_msg);
246
+ }
247
+ // Add resource_names.
248
+ for (const auto& cluster_name : cluster_names) {
249
+ envoy_api_v2_DiscoveryRequest_add_resource_names(
250
+ request, upb_strview_make(cluster_name.data(), cluster_name.size()),
251
+ arena.ptr());
252
+ }
253
+ // Set type_url.
254
+ envoy_api_v2_DiscoveryRequest_set_type_url(request,
255
+ upb_strview_makez(kCdsTypeUrl));
256
+ // Set nonce.
257
+ if (!nonce.empty()) {
258
+ envoy_api_v2_DiscoveryRequest_set_response_nonce(
259
+ request, upb_strview_makez(nonce.c_str()));
260
+ }
261
+ // Set error_detail if it's a NACK.
262
+ if (error != GRPC_ERROR_NONE) {
263
+ grpc_slice error_description_slice;
264
+ GPR_ASSERT(grpc_error_get_str(error, GRPC_ERROR_STR_DESCRIPTION,
265
+ &error_description_slice));
266
+ upb_strview error_description_strview =
267
+ upb_strview_make(reinterpret_cast<const char*>(
268
+ GPR_SLICE_START_PTR(error_description_slice)),
269
+ GPR_SLICE_LENGTH(error_description_slice));
270
+ google_rpc_Status* error_detail =
271
+ envoy_api_v2_DiscoveryRequest_mutable_error_detail(request,
272
+ arena.ptr());
273
+ google_rpc_Status_set_message(error_detail, error_description_strview);
274
+ GRPC_ERROR_UNREF(error);
275
+ }
276
+ // Encode the request.
277
+ size_t output_length;
278
+ char* output = envoy_api_v2_DiscoveryRequest_serialize(request, arena.ptr(),
279
+ &output_length);
280
+ return grpc_slice_from_copied_buffer(output, output_length);
281
+ }
282
+
283
+ grpc_slice XdsEdsRequestCreateAndEncode(
284
+ const std::set<StringView>& eds_service_names,
285
+ const XdsBootstrap::Node* node, const char* build_version,
286
+ const std::string& version, const std::string& nonce, grpc_error* error) {
287
+ upb::Arena arena;
288
+ // Create a request.
289
+ envoy_api_v2_DiscoveryRequest* request =
290
+ envoy_api_v2_DiscoveryRequest_new(arena.ptr());
291
+ // Set version_info.
292
+ if (!version.empty()) {
293
+ envoy_api_v2_DiscoveryRequest_set_version_info(
294
+ request, upb_strview_makez(version.c_str()));
295
+ }
296
+ // Populate node.
297
+ if (build_version != nullptr) {
298
+ envoy_api_v2_core_Node* node_msg =
299
+ envoy_api_v2_DiscoveryRequest_mutable_node(request, arena.ptr());
300
+ PopulateNode(arena.ptr(), node, build_version, node_msg);
301
+ }
302
+ // Add resource_names.
303
+ for (const auto& eds_service_name : eds_service_names) {
304
+ envoy_api_v2_DiscoveryRequest_add_resource_names(
305
+ request,
306
+ upb_strview_make(eds_service_name.data(), eds_service_name.size()),
307
+ arena.ptr());
308
+ }
309
+ // Set type_url.
214
310
  envoy_api_v2_DiscoveryRequest_set_type_url(request,
215
311
  upb_strview_makez(kEdsTypeUrl));
312
+ // Set nonce.
313
+ if (!nonce.empty()) {
314
+ envoy_api_v2_DiscoveryRequest_set_response_nonce(
315
+ request, upb_strview_makez(nonce.c_str()));
316
+ }
317
+ // Set error_detail if it's a NACK.
318
+ if (error != GRPC_ERROR_NONE) {
319
+ grpc_slice error_description_slice;
320
+ GPR_ASSERT(grpc_error_get_str(error, GRPC_ERROR_STR_DESCRIPTION,
321
+ &error_description_slice));
322
+ upb_strview error_description_strview =
323
+ upb_strview_make(reinterpret_cast<const char*>(
324
+ GPR_SLICE_START_PTR(error_description_slice)),
325
+ GPR_SLICE_LENGTH(error_description_slice));
326
+ google_rpc_Status* error_detail =
327
+ envoy_api_v2_DiscoveryRequest_mutable_error_detail(request,
328
+ arena.ptr());
329
+ google_rpc_Status_set_message(error_detail, error_description_strview);
330
+ GRPC_ERROR_UNREF(error);
331
+ }
216
332
  // Encode the request.
217
333
  size_t output_length;
218
334
  char* output = envoy_api_v2_DiscoveryRequest_serialize(request, arena.ptr(),
@@ -220,6 +336,76 @@ grpc_slice XdsEdsRequestCreateAndEncode(const char* server_name,
220
336
  return grpc_slice_from_copied_buffer(output, output_length);
221
337
  }
222
338
 
339
+ grpc_error* CdsResponseParse(const envoy_api_v2_DiscoveryResponse* response,
340
+ CdsUpdateMap* cds_update_map, upb_arena* arena) {
341
+ // Get the resources from the response.
342
+ size_t size;
343
+ const google_protobuf_Any* const* resources =
344
+ envoy_api_v2_DiscoveryResponse_resources(response, &size);
345
+ if (size < 1) {
346
+ return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
347
+ "CDS response contains 0 resource.");
348
+ }
349
+ // Parse all the resources in the CDS response.
350
+ for (size_t i = 0; i < size; ++i) {
351
+ CdsUpdate cds_update;
352
+ // Check the type_url of the resource.
353
+ const upb_strview type_url = google_protobuf_Any_type_url(resources[i]);
354
+ if (!upb_strview_eql(type_url, upb_strview_makez(kCdsTypeUrl))) {
355
+ return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Resource is not CDS.");
356
+ }
357
+ // Decode the cluster.
358
+ const upb_strview encoded_cluster = google_protobuf_Any_value(resources[i]);
359
+ const envoy_api_v2_Cluster* cluster = envoy_api_v2_Cluster_parse(
360
+ encoded_cluster.data, encoded_cluster.size, arena);
361
+ if (cluster == nullptr) {
362
+ return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Can't decode cluster.");
363
+ }
364
+ // Check the cluster_discovery_type.
365
+ if (!envoy_api_v2_Cluster_has_type(cluster)) {
366
+ return GRPC_ERROR_CREATE_FROM_STATIC_STRING("DiscoveryType not found.");
367
+ }
368
+ if (envoy_api_v2_Cluster_type(cluster) != envoy_api_v2_Cluster_EDS) {
369
+ return GRPC_ERROR_CREATE_FROM_STATIC_STRING("DiscoveryType is not EDS.");
370
+ }
371
+ // Check the EDS config source.
372
+ const envoy_api_v2_Cluster_EdsClusterConfig* eds_cluster_config =
373
+ envoy_api_v2_Cluster_eds_cluster_config(cluster);
374
+ const envoy_api_v2_core_ConfigSource* eds_config =
375
+ envoy_api_v2_Cluster_EdsClusterConfig_eds_config(eds_cluster_config);
376
+ if (!envoy_api_v2_core_ConfigSource_has_ads(eds_config)) {
377
+ return GRPC_ERROR_CREATE_FROM_STATIC_STRING("ConfigSource is not ADS.");
378
+ }
379
+ // Record EDS service_name (if any).
380
+ upb_strview service_name =
381
+ envoy_api_v2_Cluster_EdsClusterConfig_service_name(eds_cluster_config);
382
+ if (service_name.size != 0) {
383
+ cds_update.eds_service_name =
384
+ std::string(service_name.data, service_name.size);
385
+ }
386
+ // Check the LB policy.
387
+ if (envoy_api_v2_Cluster_lb_policy(cluster) !=
388
+ envoy_api_v2_Cluster_ROUND_ROBIN) {
389
+ return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
390
+ "LB policy is not ROUND_ROBIN.");
391
+ }
392
+ // Record LRS server name (if any).
393
+ const envoy_api_v2_core_ConfigSource* lrs_server =
394
+ envoy_api_v2_Cluster_lrs_server(cluster);
395
+ if (lrs_server != nullptr) {
396
+ if (!envoy_api_v2_core_ConfigSource_has_self(lrs_server)) {
397
+ return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
398
+ "ConfigSource is not self.");
399
+ }
400
+ cds_update.lrs_load_reporting_server_name.set("");
401
+ }
402
+ upb_strview cluster_name = envoy_api_v2_Cluster_name(cluster);
403
+ cds_update_map->emplace(std::string(cluster_name.data, cluster_name.size),
404
+ std::move(cds_update));
405
+ }
406
+ return GRPC_ERROR_NONE;
407
+ }
408
+
223
409
  namespace {
224
410
 
225
411
  grpc_error* ServerAddressParseAndAppend(
@@ -257,17 +443,6 @@ grpc_error* ServerAddressParseAndAppend(
257
443
  return GRPC_ERROR_NONE;
258
444
  }
259
445
 
260
- namespace {
261
-
262
- grpc_core::UniquePtr<char> StringCopy(const upb_strview& strview) {
263
- char* str = static_cast<char*>(gpr_malloc(strview.size + 1));
264
- memcpy(str, strview.data, strview.size);
265
- str[strview.size] = '\0';
266
- return grpc_core::UniquePtr<char>(str);
267
- }
268
-
269
- } // namespace
270
-
271
446
  grpc_error* LocalityParse(
272
447
  const envoy_api_v2_endpoint_LocalityLbEndpoints* locality_lb_endpoints,
273
448
  XdsPriorityListUpdate::LocalityMap::Locality* output_locality) {
@@ -284,10 +459,12 @@ grpc_error* LocalityParse(
284
459
  // Parse locality name.
285
460
  const envoy_api_v2_core_Locality* locality =
286
461
  envoy_api_v2_endpoint_LocalityLbEndpoints_locality(locality_lb_endpoints);
462
+ upb_strview region = envoy_api_v2_core_Locality_region(locality);
463
+ upb_strview zone = envoy_api_v2_core_Locality_region(locality);
464
+ upb_strview sub_zone = envoy_api_v2_core_Locality_sub_zone(locality);
287
465
  output_locality->name = MakeRefCounted<XdsLocalityName>(
288
- StringCopy(envoy_api_v2_core_Locality_region(locality)),
289
- StringCopy(envoy_api_v2_core_Locality_zone(locality)),
290
- StringCopy(envoy_api_v2_core_Locality_sub_zone(locality)));
466
+ std::string(region.data, region.size), std::string(zone.data, zone.size),
467
+ std::string(sub_zone.data, sub_zone.size));
291
468
  // Parse the addresses.
292
469
  size_t size;
293
470
  const envoy_api_v2_endpoint_LbEndpoint* const* lb_endpoints =
@@ -338,30 +515,15 @@ grpc_error* DropParseAndAppend(
338
515
  // Cap numerator to 1000000.
339
516
  numerator = GPR_MIN(numerator, 1000000);
340
517
  if (numerator == 1000000) *drop_all = true;
341
- drop_config->AddCategory(StringCopy(category), numerator);
518
+ drop_config->AddCategory(std::string(category.data, category.size),
519
+ numerator);
342
520
  return GRPC_ERROR_NONE;
343
521
  }
344
522
 
345
- } // namespace
346
-
347
- grpc_error* XdsEdsResponseDecodeAndParse(const grpc_slice& encoded_response,
348
- EdsUpdate* update) {
349
- upb::Arena arena;
350
- // Decode the response.
351
- const envoy_api_v2_DiscoveryResponse* response =
352
- envoy_api_v2_DiscoveryResponse_parse(
353
- reinterpret_cast<const char*>(GRPC_SLICE_START_PTR(encoded_response)),
354
- GRPC_SLICE_LENGTH(encoded_response), arena.ptr());
355
- // Parse the response.
356
- if (response == nullptr) {
357
- return GRPC_ERROR_CREATE_FROM_STATIC_STRING("No response found.");
358
- }
359
- // Check the type_url of the response.
360
- upb_strview type_url = envoy_api_v2_DiscoveryResponse_type_url(response);
361
- upb_strview expected_type_url = upb_strview_makez(kEdsTypeUrl);
362
- if (!upb_strview_eql(type_url, expected_type_url)) {
363
- return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Resource is not EDS.");
364
- }
523
+ grpc_error* EdsResponsedParse(
524
+ const envoy_api_v2_DiscoveryResponse* response,
525
+ const std::set<StringView>& expected_eds_service_names,
526
+ EdsUpdateMap* eds_update_map, upb_arena* arena) {
365
527
  // Get the resources from the response.
366
528
  size_t size;
367
529
  const google_protobuf_Any* const* resources =
@@ -370,48 +532,115 @@ grpc_error* XdsEdsResponseDecodeAndParse(const grpc_slice& encoded_response,
370
532
  return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
371
533
  "EDS response contains 0 resource.");
372
534
  }
373
- // Check the type_url of the resource.
374
- type_url = google_protobuf_Any_type_url(resources[0]);
375
- if (!upb_strview_eql(type_url, expected_type_url)) {
376
- return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Resource is not EDS.");
377
- }
378
- // Get the cluster_load_assignment.
379
- upb_strview encoded_cluster_load_assignment =
380
- google_protobuf_Any_value(resources[0]);
381
- envoy_api_v2_ClusterLoadAssignment* cluster_load_assignment =
382
- envoy_api_v2_ClusterLoadAssignment_parse(
383
- encoded_cluster_load_assignment.data,
384
- encoded_cluster_load_assignment.size, arena.ptr());
385
- // Get the endpoints.
386
- const envoy_api_v2_endpoint_LocalityLbEndpoints* const* endpoints =
387
- envoy_api_v2_ClusterLoadAssignment_endpoints(cluster_load_assignment,
388
- &size);
389
535
  for (size_t i = 0; i < size; ++i) {
390
- XdsPriorityListUpdate::LocalityMap::Locality locality;
391
- grpc_error* error = LocalityParse(endpoints[i], &locality);
392
- if (error != GRPC_ERROR_NONE) return error;
393
- // Filter out locality with weight 0.
394
- if (locality.lb_weight == 0) continue;
395
- update->priority_list_update.Add(locality);
396
- }
397
- // Get the drop config.
398
- update->drop_config = MakeRefCounted<XdsDropConfig>();
399
- const envoy_api_v2_ClusterLoadAssignment_Policy* policy =
400
- envoy_api_v2_ClusterLoadAssignment_policy(cluster_load_assignment);
401
- if (policy != nullptr) {
402
- const envoy_api_v2_ClusterLoadAssignment_Policy_DropOverload* const*
403
- drop_overload =
404
- envoy_api_v2_ClusterLoadAssignment_Policy_drop_overloads(policy,
405
- &size);
406
- for (size_t i = 0; i < size; ++i) {
407
- grpc_error* error = DropParseAndAppend(
408
- drop_overload[i], update->drop_config.get(), &update->drop_all);
536
+ EdsUpdate eds_update;
537
+ // Check the type_url of the resource.
538
+ upb_strview type_url = google_protobuf_Any_type_url(resources[i]);
539
+ if (!upb_strview_eql(type_url, upb_strview_makez(kEdsTypeUrl))) {
540
+ return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Resource is not EDS.");
541
+ }
542
+ // Get the cluster_load_assignment.
543
+ upb_strview encoded_cluster_load_assignment =
544
+ google_protobuf_Any_value(resources[i]);
545
+ envoy_api_v2_ClusterLoadAssignment* cluster_load_assignment =
546
+ envoy_api_v2_ClusterLoadAssignment_parse(
547
+ encoded_cluster_load_assignment.data,
548
+ encoded_cluster_load_assignment.size, arena);
549
+ if (cluster_load_assignment == nullptr) {
550
+ return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
551
+ "Can't parse cluster_load_assignment.");
552
+ }
553
+ // Check the cluster name (which actually means eds_service_name). Ignore
554
+ // unexpected names.
555
+ upb_strview cluster_name = envoy_api_v2_ClusterLoadAssignment_cluster_name(
556
+ cluster_load_assignment);
557
+ StringView cluster_name_strview(cluster_name.data, cluster_name.size);
558
+ if (expected_eds_service_names.find(cluster_name_strview) ==
559
+ expected_eds_service_names.end()) {
560
+ continue;
561
+ }
562
+ // Get the endpoints.
563
+ size_t locality_size;
564
+ const envoy_api_v2_endpoint_LocalityLbEndpoints* const* endpoints =
565
+ envoy_api_v2_ClusterLoadAssignment_endpoints(cluster_load_assignment,
566
+ &locality_size);
567
+ for (size_t j = 0; j < locality_size; ++j) {
568
+ XdsPriorityListUpdate::LocalityMap::Locality locality;
569
+ grpc_error* error = LocalityParse(endpoints[j], &locality);
409
570
  if (error != GRPC_ERROR_NONE) return error;
571
+ // Filter out locality with weight 0.
572
+ if (locality.lb_weight == 0) continue;
573
+ eds_update.priority_list_update.Add(locality);
574
+ }
575
+ // Get the drop config.
576
+ eds_update.drop_config = MakeRefCounted<XdsDropConfig>();
577
+ const envoy_api_v2_ClusterLoadAssignment_Policy* policy =
578
+ envoy_api_v2_ClusterLoadAssignment_policy(cluster_load_assignment);
579
+ if (policy != nullptr) {
580
+ size_t drop_size;
581
+ const envoy_api_v2_ClusterLoadAssignment_Policy_DropOverload* const*
582
+ drop_overload =
583
+ envoy_api_v2_ClusterLoadAssignment_Policy_drop_overloads(
584
+ policy, &drop_size);
585
+ for (size_t j = 0; j < drop_size; ++j) {
586
+ grpc_error* error =
587
+ DropParseAndAppend(drop_overload[j], eds_update.drop_config.get(),
588
+ &eds_update.drop_all);
589
+ if (error != GRPC_ERROR_NONE) return error;
590
+ }
591
+ }
592
+ // Validate the update content.
593
+ if (eds_update.priority_list_update.empty() && !eds_update.drop_all) {
594
+ return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
595
+ "EDS response doesn't contain any valid "
596
+ "locality but doesn't require to drop all calls.");
410
597
  }
598
+ eds_update_map->emplace(std::string(cluster_name.data, cluster_name.size),
599
+ std::move(eds_update));
411
600
  }
412
601
  return GRPC_ERROR_NONE;
413
602
  }
414
603
 
604
+ } // namespace
605
+
606
+ grpc_error* XdsAdsResponseDecodeAndParse(
607
+ const grpc_slice& encoded_response,
608
+ const std::set<StringView>& expected_eds_service_names,
609
+ CdsUpdateMap* cds_update_map, EdsUpdateMap* eds_update_map,
610
+ std::string* version, std::string* nonce, std::string* type_url) {
611
+ upb::Arena arena;
612
+ // Decode the response.
613
+ const envoy_api_v2_DiscoveryResponse* response =
614
+ envoy_api_v2_DiscoveryResponse_parse(
615
+ reinterpret_cast<const char*>(GRPC_SLICE_START_PTR(encoded_response)),
616
+ GRPC_SLICE_LENGTH(encoded_response), arena.ptr());
617
+ // If decoding fails, output an empty type_url and return.
618
+ if (response == nullptr) {
619
+ *type_url = "";
620
+ return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
621
+ "Can't decode the whole response.");
622
+ }
623
+ // Record the type_url, the version_info, and the nonce of the response.
624
+ upb_strview type_url_strview =
625
+ envoy_api_v2_DiscoveryResponse_type_url(response);
626
+ *type_url = std::string(type_url_strview.data, type_url_strview.size);
627
+ upb_strview version_info =
628
+ envoy_api_v2_DiscoveryResponse_version_info(response);
629
+ *version = std::string(version_info.data, version_info.size);
630
+ upb_strview nonce_strview = envoy_api_v2_DiscoveryResponse_nonce(response);
631
+ *nonce = std::string(nonce_strview.data, nonce_strview.size);
632
+ // Parse the response according to the resource type.
633
+ if (*type_url == kCdsTypeUrl) {
634
+ return CdsResponseParse(response, cds_update_map, arena.ptr());
635
+ } else if (*type_url == kEdsTypeUrl) {
636
+ return EdsResponsedParse(response, expected_eds_service_names,
637
+ eds_update_map, arena.ptr());
638
+ } else {
639
+ return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
640
+ "Unsupported ADS resource type.");
641
+ }
642
+ }
643
+
415
644
  namespace {
416
645
 
417
646
  grpc_slice LrsRequestEncode(
@@ -425,7 +654,7 @@ grpc_slice LrsRequestEncode(
425
654
 
426
655
  } // namespace
427
656
 
428
- grpc_slice XdsLrsRequestCreateAndEncode(const char* server_name,
657
+ grpc_slice XdsLrsRequestCreateAndEncode(const std::string& server_name,
429
658
  const XdsBootstrap::Node* node,
430
659
  const char* build_version) {
431
660
  upb::Arena arena;
@@ -444,7 +673,7 @@ grpc_slice XdsLrsRequestCreateAndEncode(const char* server_name,
444
673
  request, arena.ptr());
445
674
  // Set the cluster name.
446
675
  envoy_api_v2_endpoint_ClusterStats_set_cluster_name(
447
- cluster_stats, upb_strview_makez(server_name));
676
+ cluster_stats, upb_strview_makez(server_name.c_str()));
448
677
  return LrsRequestEncode(request, arena.ptr());
449
678
  }
450
679
 
@@ -452,17 +681,17 @@ namespace {
452
681
 
453
682
  void LocalityStatsPopulate(
454
683
  envoy_api_v2_endpoint_UpstreamLocalityStats* output,
455
- std::pair<const RefCountedPtr<XdsLocalityName>,
456
- XdsClientStats::LocalityStats::Snapshot>& input,
684
+ const std::pair<const RefCountedPtr<XdsLocalityName>,
685
+ XdsClientStats::LocalityStats::Snapshot>& input,
457
686
  upb_arena* arena) {
458
687
  // Set sub_zone.
459
688
  envoy_api_v2_core_Locality* locality =
460
689
  envoy_api_v2_endpoint_UpstreamLocalityStats_mutable_locality(output,
461
690
  arena);
462
691
  envoy_api_v2_core_Locality_set_sub_zone(
463
- locality, upb_strview_makez(input.first->sub_zone()));
692
+ locality, upb_strview_makez(input.first->sub_zone().c_str()));
464
693
  // Set total counts.
465
- XdsClientStats::LocalityStats::Snapshot& snapshot = input.second;
694
+ const XdsClientStats::LocalityStats::Snapshot& snapshot = input.second;
466
695
  envoy_api_v2_endpoint_UpstreamLocalityStats_set_total_successful_requests(
467
696
  output, snapshot.total_successful_requests);
468
697
  envoy_api_v2_endpoint_UpstreamLocalityStats_set_total_requests_in_progress(
@@ -473,7 +702,7 @@ void LocalityStatsPopulate(
473
702
  output, snapshot.total_issued_requests);
474
703
  // Add load metric stats.
475
704
  for (auto& p : snapshot.load_metric_stats) {
476
- const char* metric_name = p.first.get();
705
+ const char* metric_name = p.first.c_str();
477
706
  const XdsClientStats::LocalityStats::LoadMetric::Snapshot& metric_value =
478
707
  p.second;
479
708
  envoy_api_v2_endpoint_EndpointLoadMetricStats* load_metric =
@@ -490,62 +719,80 @@ void LocalityStatsPopulate(
490
719
 
491
720
  } // namespace
492
721
 
493
- grpc_slice XdsLrsRequestCreateAndEncode(const char* server_name,
494
- XdsClientStats* client_stats) {
722
+ grpc_slice XdsLrsRequestCreateAndEncode(
723
+ std::map<StringView, std::set<XdsClientStats*>> client_stats_map) {
495
724
  upb::Arena arena;
496
- XdsClientStats::Snapshot snapshot = client_stats->GetSnapshotAndReset();
497
- // Prune unused locality stats.
498
- client_stats->PruneLocalityStats();
725
+ // Get the snapshots.
726
+ std::map<StringView, grpc_core::InlinedVector<XdsClientStats::Snapshot, 1>>
727
+ snapshot_map;
728
+ for (auto& p : client_stats_map) {
729
+ const StringView& cluster_name = p.first;
730
+ for (auto* client_stats : p.second) {
731
+ XdsClientStats::Snapshot snapshot = client_stats->GetSnapshotAndReset();
732
+ // Prune unused locality stats.
733
+ client_stats->PruneLocalityStats();
734
+ if (snapshot.IsAllZero()) continue;
735
+ snapshot_map[cluster_name].emplace_back(std::move(snapshot));
736
+ }
737
+ }
499
738
  // When all the counts are zero, return empty slice.
500
- if (snapshot.IsAllZero()) return grpc_empty_slice();
739
+ if (snapshot_map.empty()) return grpc_empty_slice();
501
740
  // Create a request.
502
741
  envoy_service_load_stats_v2_LoadStatsRequest* request =
503
742
  envoy_service_load_stats_v2_LoadStatsRequest_new(arena.ptr());
504
- // Add cluster stats. There is only one because we only use one server name in
505
- // one channel.
506
- envoy_api_v2_endpoint_ClusterStats* cluster_stats =
507
- envoy_service_load_stats_v2_LoadStatsRequest_add_cluster_stats(
508
- request, arena.ptr());
509
- // Set the cluster name.
510
- envoy_api_v2_endpoint_ClusterStats_set_cluster_name(
511
- cluster_stats, upb_strview_makez(server_name));
512
- // Add locality stats.
513
- for (auto& p : snapshot.upstream_locality_stats) {
514
- envoy_api_v2_endpoint_UpstreamLocalityStats* locality_stats =
515
- envoy_api_v2_endpoint_ClusterStats_add_upstream_locality_stats(
516
- cluster_stats, arena.ptr());
517
- LocalityStatsPopulate(locality_stats, p, arena.ptr());
518
- }
519
- // Add dropped requests.
520
- for (auto& p : snapshot.dropped_requests) {
521
- const char* category = p.first.get();
522
- const uint64_t count = p.second;
523
- envoy_api_v2_endpoint_ClusterStats_DroppedRequests* dropped_requests =
524
- envoy_api_v2_endpoint_ClusterStats_add_dropped_requests(cluster_stats,
525
- arena.ptr());
526
- envoy_api_v2_endpoint_ClusterStats_DroppedRequests_set_category(
527
- dropped_requests, upb_strview_makez(category));
528
- envoy_api_v2_endpoint_ClusterStats_DroppedRequests_set_dropped_count(
529
- dropped_requests, count);
530
- }
531
- // Set total dropped requests.
532
- envoy_api_v2_endpoint_ClusterStats_set_total_dropped_requests(
533
- cluster_stats, snapshot.total_dropped_requests);
534
- // Set real load report interval.
535
- gpr_timespec timespec =
536
- grpc_millis_to_timespec(snapshot.load_report_interval, GPR_TIMESPAN);
537
- google_protobuf_Duration* load_report_interval =
538
- envoy_api_v2_endpoint_ClusterStats_mutable_load_report_interval(
539
- cluster_stats, arena.ptr());
540
- google_protobuf_Duration_set_seconds(load_report_interval, timespec.tv_sec);
541
- google_protobuf_Duration_set_nanos(load_report_interval, timespec.tv_nsec);
743
+ for (auto& p : snapshot_map) {
744
+ const StringView& cluster_name = p.first;
745
+ const auto& snapshot_list = p.second;
746
+ for (size_t i = 0; i < snapshot_list.size(); ++i) {
747
+ const auto& snapshot = snapshot_list[i];
748
+ // Add cluster stats.
749
+ envoy_api_v2_endpoint_ClusterStats* cluster_stats =
750
+ envoy_service_load_stats_v2_LoadStatsRequest_add_cluster_stats(
751
+ request, arena.ptr());
752
+ // Set the cluster name.
753
+ envoy_api_v2_endpoint_ClusterStats_set_cluster_name(
754
+ cluster_stats,
755
+ upb_strview_make(cluster_name.data(), cluster_name.size()));
756
+ // Add locality stats.
757
+ for (auto& p : snapshot.upstream_locality_stats) {
758
+ envoy_api_v2_endpoint_UpstreamLocalityStats* locality_stats =
759
+ envoy_api_v2_endpoint_ClusterStats_add_upstream_locality_stats(
760
+ cluster_stats, arena.ptr());
761
+ LocalityStatsPopulate(locality_stats, p, arena.ptr());
762
+ }
763
+ // Add dropped requests.
764
+ for (auto& p : snapshot.dropped_requests) {
765
+ const char* category = p.first.c_str();
766
+ const uint64_t count = p.second;
767
+ envoy_api_v2_endpoint_ClusterStats_DroppedRequests* dropped_requests =
768
+ envoy_api_v2_endpoint_ClusterStats_add_dropped_requests(
769
+ cluster_stats, arena.ptr());
770
+ envoy_api_v2_endpoint_ClusterStats_DroppedRequests_set_category(
771
+ dropped_requests, upb_strview_makez(category));
772
+ envoy_api_v2_endpoint_ClusterStats_DroppedRequests_set_dropped_count(
773
+ dropped_requests, count);
774
+ }
775
+ // Set total dropped requests.
776
+ envoy_api_v2_endpoint_ClusterStats_set_total_dropped_requests(
777
+ cluster_stats, snapshot.total_dropped_requests);
778
+ // Set real load report interval.
779
+ gpr_timespec timespec =
780
+ grpc_millis_to_timespec(snapshot.load_report_interval, GPR_TIMESPAN);
781
+ google_protobuf_Duration* load_report_interval =
782
+ envoy_api_v2_endpoint_ClusterStats_mutable_load_report_interval(
783
+ cluster_stats, arena.ptr());
784
+ google_protobuf_Duration_set_seconds(load_report_interval,
785
+ timespec.tv_sec);
786
+ google_protobuf_Duration_set_nanos(load_report_interval,
787
+ timespec.tv_nsec);
788
+ }
789
+ }
542
790
  return LrsRequestEncode(request, arena.ptr());
543
791
  }
544
792
 
545
- grpc_error* XdsLrsResponseDecodeAndParse(
546
- const grpc_slice& encoded_response,
547
- grpc_core::UniquePtr<char>* cluster_name,
548
- grpc_millis* load_reporting_interval) {
793
+ grpc_error* XdsLrsResponseDecodeAndParse(const grpc_slice& encoded_response,
794
+ std::set<std::string>* cluster_names,
795
+ grpc_millis* load_reporting_interval) {
549
796
  upb::Arena arena;
550
797
  // Decode the response.
551
798
  const envoy_service_load_stats_v2_LoadStatsResponse* decoded_response =
@@ -554,19 +801,16 @@ grpc_error* XdsLrsResponseDecodeAndParse(
554
801
  GRPC_SLICE_LENGTH(encoded_response), arena.ptr());
555
802
  // Parse the response.
556
803
  if (decoded_response == nullptr) {
557
- return GRPC_ERROR_CREATE_FROM_STATIC_STRING("No response found.");
804
+ return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Can't decode response.");
558
805
  }
559
- // Check the cluster size in the response.
806
+ // Store the cluster names.
560
807
  size_t size;
561
808
  const upb_strview* clusters =
562
809
  envoy_service_load_stats_v2_LoadStatsResponse_clusters(decoded_response,
563
810
  &size);
564
- if (size != 1) {
565
- return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
566
- "The number of clusters (server names) is not 1.");
811
+ for (size_t i = 0; i < size; ++i) {
812
+ cluster_names->emplace(clusters[i].data, clusters[i].size);
567
813
  }
568
- // Get the cluster name for reporting loads.
569
- *cluster_name = StringCopy(clusters[0]);
570
814
  // Get the load report interval.
571
815
  const google_protobuf_Duration* load_reporting_interval_duration =
572
816
  envoy_service_load_stats_v2_LoadStatsResponse_load_reporting_interval(