|  | @@ -0,0 +1,83 @@
 | 
	
		
			
				|  |  | +/*
 | 
	
		
			
				|  |  | + *
 | 
	
		
			
				|  |  | + * Copyright 2019 gRPC authors.
 | 
	
		
			
				|  |  | + *
 | 
	
		
			
				|  |  | + * Licensed under the Apache License, Version 2.0 (the "License");
 | 
	
		
			
				|  |  | + * you may not use this file except in compliance with the License.
 | 
	
		
			
				|  |  | + * You may obtain a copy of the License at
 | 
	
		
			
				|  |  | + *
 | 
	
		
			
				|  |  | + *     http://www.apache.org/licenses/LICENSE-2.0
 | 
	
		
			
				|  |  | + *
 | 
	
		
			
				|  |  | + * Unless required by applicable law or agreed to in writing, software
 | 
	
		
			
				|  |  | + * distributed under the License is distributed on an "AS IS" BASIS,
 | 
	
		
			
				|  |  | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
	
		
			
				|  |  | + * See the License for the specific language governing permissions and
 | 
	
		
			
				|  |  | + * limitations under the License.
 | 
	
		
			
				|  |  | + *
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#include <grpc/support/port_platform.h>
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#include "src/core/lib/iomgr/port.h"
 | 
	
		
			
				|  |  | +#if GRPC_ARES == 1 && (defined(GRPC_UV) || defined(GPR_WINDOWS))
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#include <grpc/support/string_util.h>
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#include "src/core/ext/filters/client_channel/parse_address.h"
 | 
	
		
			
				|  |  | +#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h"
 | 
	
		
			
				|  |  | +#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_windows_inner.h"
 | 
	
		
			
				|  |  | +#include "src/core/ext/filters/client_channel/server_address.h"
 | 
	
		
			
				|  |  | +#include "src/core/lib/gpr/host_port.h"
 | 
	
		
			
				|  |  | +#include "src/core/lib/gpr/string.h"
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +bool inner_maybe_resolve_localhost_manually_locked(
 | 
	
		
			
				|  |  | +    const char* name, const char* default_port,
 | 
	
		
			
				|  |  | +    grpc_core::UniquePtr<grpc_core::ServerAddressList>* addrs, char** host,
 | 
	
		
			
				|  |  | +    char** port) {
 | 
	
		
			
				|  |  | +  gpr_split_host_port(name, host, port);
 | 
	
		
			
				|  |  | +  if (*host == nullptr) {
 | 
	
		
			
				|  |  | +    gpr_log(GPR_ERROR,
 | 
	
		
			
				|  |  | +            "Failed to parse %s into host:port during manual localhost "
 | 
	
		
			
				|  |  | +            "resolution check.",
 | 
	
		
			
				|  |  | +            name);
 | 
	
		
			
				|  |  | +    return false;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  if (*port == nullptr) {
 | 
	
		
			
				|  |  | +    if (default_port == nullptr) {
 | 
	
		
			
				|  |  | +      gpr_log(GPR_ERROR,
 | 
	
		
			
				|  |  | +              "No port or default port for %s during manual localhost "
 | 
	
		
			
				|  |  | +              "resolution check.",
 | 
	
		
			
				|  |  | +              name);
 | 
	
		
			
				|  |  | +      return false;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    *port = gpr_strdup(default_port);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  if (gpr_stricmp(*host, "localhost") == 0) {
 | 
	
		
			
				|  |  | +    GPR_ASSERT(*addrs == nullptr);
 | 
	
		
			
				|  |  | +    *addrs = grpc_core::MakeUnique<grpc_core::ServerAddressList>();
 | 
	
		
			
				|  |  | +    uint16_t numeric_port = grpc_strhtons(*port);
 | 
	
		
			
				|  |  | +    // Append the ipv6 loopback address.
 | 
	
		
			
				|  |  | +    struct sockaddr_in6 ipv6_loopback_addr;
 | 
	
		
			
				|  |  | +    memset(&ipv6_loopback_addr, 0, sizeof(ipv6_loopback_addr));
 | 
	
		
			
				|  |  | +    ((char*)&ipv6_loopback_addr.sin6_addr)[15] = 1;
 | 
	
		
			
				|  |  | +    ipv6_loopback_addr.sin6_family = AF_INET6;
 | 
	
		
			
				|  |  | +    ipv6_loopback_addr.sin6_port = numeric_port;
 | 
	
		
			
				|  |  | +    (*addrs)->emplace_back(&ipv6_loopback_addr, sizeof(ipv6_loopback_addr),
 | 
	
		
			
				|  |  | +                           nullptr /* args */);
 | 
	
		
			
				|  |  | +    // Append the ipv4 loopback address.
 | 
	
		
			
				|  |  | +    struct sockaddr_in ipv4_loopback_addr;
 | 
	
		
			
				|  |  | +    memset(&ipv4_loopback_addr, 0, sizeof(ipv4_loopback_addr));
 | 
	
		
			
				|  |  | +    ((char*)&ipv4_loopback_addr.sin_addr)[0] = 0x7f;
 | 
	
		
			
				|  |  | +    ((char*)&ipv4_loopback_addr.sin_addr)[3] = 0x01;
 | 
	
		
			
				|  |  | +    ipv4_loopback_addr.sin_family = AF_INET;
 | 
	
		
			
				|  |  | +    ipv4_loopback_addr.sin_port = numeric_port;
 | 
	
		
			
				|  |  | +    (*addrs)->emplace_back(&ipv4_loopback_addr, sizeof(ipv4_loopback_addr),
 | 
	
		
			
				|  |  | +                           nullptr /* args */);
 | 
	
		
			
				|  |  | +    // Let the address sorter figure out which one should be tried first.
 | 
	
		
			
				|  |  | +    grpc_cares_wrapper_address_sorting_sort(addrs->get());
 | 
	
		
			
				|  |  | +    return true;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  return false;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#endif /* GRPC_ARES == 1 && (defined(GRPC_UV) || defined(GPR_WINDOWS)) */
 |