|  | @@ -24,6 +24,7 @@
 | 
	
		
			
				|  |  |  #include <cstdlib>
 | 
	
		
			
				|  |  |  #include <string>
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +#include "absl/strings/numbers.h"
 | 
	
		
			
				|  |  |  #include "absl/strings/str_cat.h"
 | 
	
		
			
				|  |  |  #include "absl/strings/str_format.h"
 | 
	
		
			
				|  |  |  #include "absl/strings/str_join.h"
 | 
	
	
		
			
				|  | @@ -39,6 +40,7 @@
 | 
	
		
			
				|  |  |  #include "src/core/lib/gpr/env.h"
 | 
	
		
			
				|  |  |  #include "src/core/lib/gpr/string.h"
 | 
	
		
			
				|  |  |  #include "src/core/lib/gpr/useful.h"
 | 
	
		
			
				|  |  | +#include "src/core/lib/gprpp/host_port.h"
 | 
	
		
			
				|  |  |  #include "src/core/lib/iomgr/error.h"
 | 
	
		
			
				|  |  |  #include "src/core/lib/iomgr/sockaddr_utils.h"
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -463,6 +465,7 @@ void PopulateNode(upb_arena* arena, const XdsBootstrap* bootstrap,
 | 
	
		
			
				|  |  |                    const std::string& build_version,
 | 
	
		
			
				|  |  |                    const std::string& user_agent_name,
 | 
	
		
			
				|  |  |                    const std::string& server_name,
 | 
	
		
			
				|  |  | +                  const std::vector<grpc_resolved_address>& listening_addresses,
 | 
	
		
			
				|  |  |                    envoy_config_core_v3_Node* node_msg) {
 | 
	
		
			
				|  |  |    const XdsBootstrap::Node* node = bootstrap->node();
 | 
	
		
			
				|  |  |    if (node != nullptr) {
 | 
	
	
		
			
				|  | @@ -510,6 +513,21 @@ void PopulateNode(upb_arena* arena, const XdsBootstrap* bootstrap,
 | 
	
		
			
				|  |  |    if (!bootstrap->server().ShouldUseV3()) {
 | 
	
		
			
				|  |  |      PopulateBuildVersion(arena, node_msg, build_version);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | +  for (const grpc_resolved_address& address : listening_addresses) {
 | 
	
		
			
				|  |  | +    std::string address_str = grpc_sockaddr_to_string(&address, false);
 | 
	
		
			
				|  |  | +    absl::string_view addr_str;
 | 
	
		
			
				|  |  | +    absl::string_view port_str;
 | 
	
		
			
				|  |  | +    GPR_ASSERT(SplitHostPort(address_str, &addr_str, &port_str));
 | 
	
		
			
				|  |  | +    uint32_t port;
 | 
	
		
			
				|  |  | +    GPR_ASSERT(absl::SimpleAtoi(port_str, &port));
 | 
	
		
			
				|  |  | +    auto* addr_msg =
 | 
	
		
			
				|  |  | +        envoy_config_core_v3_Node_add_listening_addresses(node_msg, arena);
 | 
	
		
			
				|  |  | +    auto* socket_addr_msg =
 | 
	
		
			
				|  |  | +        envoy_config_core_v3_Address_mutable_socket_address(addr_msg, arena);
 | 
	
		
			
				|  |  | +    envoy_config_core_v3_SocketAddress_set_address(
 | 
	
		
			
				|  |  | +        socket_addr_msg, upb_strview_make(addr_str.data(), addr_str.size()));
 | 
	
		
			
				|  |  | +    envoy_config_core_v3_SocketAddress_set_port_value(socket_addr_msg, port);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  |    envoy_config_core_v3_Node_set_user_agent_name(
 | 
	
		
			
				|  |  |        node_msg,
 | 
	
		
			
				|  |  |        upb_strview_make(user_agent_name.data(), user_agent_name.size()));
 | 
	
	
		
			
				|  | @@ -628,6 +646,29 @@ void AddNodeLogFields(const envoy_config_core_v3_Node* node,
 | 
	
		
			
				|  |  |      fields->emplace_back(
 | 
	
		
			
				|  |  |          absl::StrCat("  build_version: \"", build_version, "\""));
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | +  // listening_addresses
 | 
	
		
			
				|  |  | +  size_t num_listening_addresses;
 | 
	
		
			
				|  |  | +  const envoy_config_core_v3_Address* const* listening_addresses =
 | 
	
		
			
				|  |  | +      envoy_config_core_v3_Node_listening_addresses(node,
 | 
	
		
			
				|  |  | +                                                    &num_listening_addresses);
 | 
	
		
			
				|  |  | +  for (size_t i = 0; i < num_listening_addresses; ++i) {
 | 
	
		
			
				|  |  | +    fields->emplace_back("  listening_address {");
 | 
	
		
			
				|  |  | +    const auto* socket_addr_msg =
 | 
	
		
			
				|  |  | +        envoy_config_core_v3_Address_socket_address(listening_addresses[i]);
 | 
	
		
			
				|  |  | +    if (socket_addr_msg != nullptr) {
 | 
	
		
			
				|  |  | +      fields->emplace_back("    socket_address {");
 | 
	
		
			
				|  |  | +      AddStringField(
 | 
	
		
			
				|  |  | +          "      address",
 | 
	
		
			
				|  |  | +          envoy_config_core_v3_SocketAddress_address(socket_addr_msg), fields);
 | 
	
		
			
				|  |  | +      if (envoy_config_core_v3_SocketAddress_has_port_value(socket_addr_msg)) {
 | 
	
		
			
				|  |  | +        fields->emplace_back(absl::StrCat(
 | 
	
		
			
				|  |  | +            "      port_value: ",
 | 
	
		
			
				|  |  | +            envoy_config_core_v3_SocketAddress_port_value(socket_addr_msg)));
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      fields->emplace_back("    }");
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    fields->emplace_back("  }");
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  |    // user_agent_name
 | 
	
		
			
				|  |  |    AddStringField("  user_agent_name",
 | 
	
		
			
				|  |  |                   envoy_config_core_v3_Node_user_agent_name(node), fields);
 | 
	
	
		
			
				|  | @@ -730,7 +771,8 @@ grpc_slice XdsApi::CreateAdsRequest(
 | 
	
		
			
				|  |  |      const std::string& type_url,
 | 
	
		
			
				|  |  |      const std::set<absl::string_view>& resource_names,
 | 
	
		
			
				|  |  |      const std::string& version, const std::string& nonce, grpc_error* error,
 | 
	
		
			
				|  |  | -    bool populate_node) {
 | 
	
		
			
				|  |  | +    bool populate_node,
 | 
	
		
			
				|  |  | +    const std::vector<grpc_resolved_address>& listening_addresses) {
 | 
	
		
			
				|  |  |    upb::Arena arena;
 | 
	
		
			
				|  |  |    // Create a request.
 | 
	
		
			
				|  |  |    envoy_service_discovery_v3_DiscoveryRequest* request =
 | 
	
	
		
			
				|  | @@ -771,7 +813,7 @@ grpc_slice XdsApi::CreateAdsRequest(
 | 
	
		
			
				|  |  |          envoy_service_discovery_v3_DiscoveryRequest_mutable_node(request,
 | 
	
		
			
				|  |  |                                                                   arena.ptr());
 | 
	
		
			
				|  |  |      PopulateNode(arena.ptr(), bootstrap_, build_version_, user_agent_name_, "",
 | 
	
		
			
				|  |  | -                 node_msg);
 | 
	
		
			
				|  |  | +                 listening_addresses, node_msg);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    // Add resource_names.
 | 
	
		
			
				|  |  |    for (const auto& resource_name : resource_names) {
 | 
	
	
		
			
				|  | @@ -2197,7 +2239,7 @@ grpc_slice XdsApi::CreateLrsInitialRequest(const std::string& server_name) {
 | 
	
		
			
				|  |  |        envoy_service_load_stats_v3_LoadStatsRequest_mutable_node(request,
 | 
	
		
			
				|  |  |                                                                  arena.ptr());
 | 
	
		
			
				|  |  |    PopulateNode(arena.ptr(), bootstrap_, build_version_, user_agent_name_,
 | 
	
		
			
				|  |  | -               server_name, node_msg);
 | 
	
		
			
				|  |  | +               server_name, {}, node_msg);
 | 
	
		
			
				|  |  |    envoy_config_core_v3_Node_add_client_features(
 | 
	
		
			
				|  |  |        node_msg, upb_strview_makez("envoy.lrs.supports_send_all_clusters"),
 | 
	
		
			
				|  |  |        arena.ptr());
 |