202452f1b2b715fe3d89abccb69e508f4c8b49a2
[platform/upstream/grpc.git] / src / core / ext / filters / client_channel / resolver / dns / c_ares / grpc_ares_wrapper_windows.cc
1 /*
2  *
3  * Copyright 2016 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18
19 #include <grpc/support/port_platform.h>
20
21 #include "src/core/lib/iomgr/port.h"
22 #if GRPC_ARES == 1 && defined(GPR_WINDOWS)
23
24 #include <grpc/support/string_util.h>
25
26 #include "src/core/ext/filters/client_channel/parse_address.h"
27 #include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h"
28 #include "src/core/ext/filters/client_channel/server_address.h"
29 #include "src/core/lib/gpr/host_port.h"
30 #include "src/core/lib/gpr/string.h"
31 #include "src/core/lib/iomgr/socket_windows.h"
32
33 bool grpc_ares_query_ipv6() { return grpc_ipv6_loopback_available(); }
34
35 static bool inner_maybe_resolve_localhost_manually_locked(
36     const char* name, const char* default_port,
37     grpc_core::UniquePtr<grpc_core::ServerAddressList>* addrs, char** host,
38     char** port) {
39   gpr_split_host_port(name, host, port);
40   if (*host == nullptr) {
41     gpr_log(GPR_ERROR,
42             "Failed to parse %s into host:port during Windows localhost "
43             "resolution check.",
44             name);
45     return false;
46   }
47   if (*port == nullptr) {
48     if (default_port == nullptr) {
49       gpr_log(GPR_ERROR,
50               "No port or default port for %s during Windows localhost "
51               "resolution check.",
52               name);
53       return false;
54     }
55     *port = gpr_strdup(default_port);
56   }
57   if (gpr_stricmp(*host, "localhost") == 0) {
58     GPR_ASSERT(*addrs == nullptr);
59     *addrs = grpc_core::MakeUnique<grpc_core::ServerAddressList>();
60     uint16_t numeric_port = grpc_strhtons(*port);
61     // Append the ipv6 loopback address.
62     struct sockaddr_in6 ipv6_loopback_addr;
63     memset(&ipv6_loopback_addr, 0, sizeof(ipv6_loopback_addr));
64     ((char*)&ipv6_loopback_addr.sin6_addr)[15] = 1;
65     ipv6_loopback_addr.sin6_family = AF_INET6;
66     ipv6_loopback_addr.sin6_port = numeric_port;
67     (*addrs)->emplace_back(&ipv6_loopback_addr, sizeof(ipv6_loopback_addr),
68                            nullptr /* args */);
69     // Append the ipv4 loopback address.
70     struct sockaddr_in ipv4_loopback_addr;
71     memset(&ipv4_loopback_addr, 0, sizeof(ipv4_loopback_addr));
72     ((char*)&ipv4_loopback_addr.sin_addr)[0] = 0x7f;
73     ((char*)&ipv4_loopback_addr.sin_addr)[3] = 0x01;
74     ipv4_loopback_addr.sin_family = AF_INET;
75     ipv4_loopback_addr.sin_port = numeric_port;
76     (*addrs)->emplace_back(&ipv4_loopback_addr, sizeof(ipv4_loopback_addr),
77                            nullptr /* args */);
78     // Let the address sorter figure out which one should be tried first.
79     grpc_cares_wrapper_address_sorting_sort(addrs->get());
80     return true;
81   }
82   return false;
83 }
84
85 bool grpc_ares_maybe_resolve_localhost_manually_locked(
86     const char* name, const char* default_port,
87     grpc_core::UniquePtr<grpc_core::ServerAddressList>* addrs) {
88   char* host = nullptr;
89   char* port = nullptr;
90   bool out = inner_maybe_resolve_localhost_manually_locked(name, default_port,
91                                                            addrs, &host, &port);
92   gpr_free(host);
93   gpr_free(port);
94   return out;
95 }
96
97 #endif /* GRPC_ARES == 1 && defined(GPR_WINDOWS) */