Line data Source code
1 : /*
2 : *
3 : * Copyright 2015, Google Inc.
4 : * All rights reserved.
5 : *
6 : * Redistribution and use in source and binary forms, with or without
7 : * modification, are permitted provided that the following conditions are
8 : * met:
9 : *
10 : * * Redistributions of source code must retain the above copyright
11 : * notice, this list of conditions and the following disclaimer.
12 : * * Redistributions in binary form must reproduce the above
13 : * copyright notice, this list of conditions and the following disclaimer
14 : * in the documentation and/or other materials provided with the
15 : * distribution.
16 : * * Neither the name of Google Inc. nor the names of its
17 : * contributors may be used to endorse or promote products derived from
18 : * this software without specific prior written permission.
19 : *
20 : * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 : * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 : * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 : * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 : * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 : * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 : * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 : *
32 : */
33 :
34 : #include <grpc/support/port_platform.h>
35 : #ifdef GPR_POSIX_SOCKET
36 :
37 : #include "src/core/iomgr/sockaddr.h"
38 : #include "src/core/iomgr/resolve_address.h"
39 :
40 : #include <sys/types.h>
41 : #include <sys/un.h>
42 : #include <string.h>
43 :
44 : #include "src/core/iomgr/executor.h"
45 : #include "src/core/iomgr/iomgr_internal.h"
46 : #include "src/core/iomgr/sockaddr_utils.h"
47 : #include "src/core/support/block_annotate.h"
48 : #include "src/core/support/string.h"
49 : #include <grpc/support/alloc.h>
50 : #include <grpc/support/host_port.h>
51 : #include <grpc/support/log.h>
52 : #include <grpc/support/string_util.h>
53 : #include <grpc/support/thd.h>
54 : #include <grpc/support/time.h>
55 : #include <grpc/support/useful.h>
56 :
57 : typedef struct {
58 : char *name;
59 : char *default_port;
60 : grpc_resolve_cb cb;
61 : grpc_closure request_closure;
62 : void *arg;
63 : } request;
64 :
65 8773 : grpc_resolved_addresses *grpc_blocking_resolve_address(
66 : const char *name, const char *default_port) {
67 : struct addrinfo hints;
68 8773 : struct addrinfo *result = NULL, *resp;
69 : char *host;
70 : char *port;
71 : int s;
72 : size_t i;
73 8698 : grpc_resolved_addresses *addrs = NULL;
74 : struct sockaddr_un *un;
75 :
76 9269 : if (name[0] == 'u' && name[1] == 'n' && name[2] == 'i' && name[3] == 'x' &&
77 992 : name[4] == ':' && name[5] != 0) {
78 496 : addrs = gpr_malloc(sizeof(grpc_resolved_addresses));
79 496 : addrs->naddrs = 1;
80 496 : addrs->addrs = gpr_malloc(sizeof(grpc_resolved_address));
81 496 : un = (struct sockaddr_un *)addrs->addrs->addr;
82 496 : un->sun_family = AF_UNIX;
83 496 : strcpy(un->sun_path, name + 5);
84 496 : addrs->addrs->len = strlen(un->sun_path) + sizeof(un->sun_family) + 1;
85 496 : return addrs;
86 : }
87 :
88 : /* parse name, splitting it into host and port parts */
89 8277 : gpr_split_host_port(name, &host, &port);
90 8277 : if (host == NULL) {
91 7 : gpr_log(GPR_ERROR, "unparseable host:port: '%s'", name);
92 7 : goto done;
93 : }
94 8270 : if (port == NULL) {
95 10 : if (default_port == NULL) {
96 1 : gpr_log(GPR_ERROR, "no port in name '%s'", name);
97 1 : goto done;
98 : }
99 9 : port = gpr_strdup(default_port);
100 : }
101 :
102 : /* Call getaddrinfo */
103 8269 : memset(&hints, 0, sizeof(hints));
104 8194 : hints.ai_family = AF_UNSPEC; /* ipv4 or ipv6 */
105 8269 : hints.ai_socktype = SOCK_STREAM; /* stream socket */
106 8269 : hints.ai_flags = AI_PASSIVE; /* for wildcard IP address */
107 :
108 : GRPC_SCHEDULING_START_BLOCKING_REGION;
109 8269 : s = getaddrinfo(host, port, &hints, &result);
110 : GRPC_SCHEDULING_END_BLOCKING_REGION;
111 :
112 8269 : if (s != 0) {
113 : /* Retry if well-known service name is recognized */
114 5 : char *svc[][2] = {{"http", "80"}, {"https", "443"}};
115 14 : for (i = 0; i < GPR_ARRAY_SIZE(svc); i++) {
116 10 : if (strcmp(port, svc[i][0]) == 0) {
117 : GRPC_SCHEDULING_START_BLOCKING_REGION;
118 1 : s = getaddrinfo(host, svc[i][1], &hints, &result);
119 : GRPC_SCHEDULING_END_BLOCKING_REGION;
120 1 : break;
121 : }
122 : }
123 : }
124 :
125 8269 : if (s != 0) {
126 5 : gpr_log(GPR_ERROR, "getaddrinfo: %s", gai_strerror(s));
127 5 : goto done;
128 : }
129 :
130 : /* Success path: set addrs non-NULL, fill it in */
131 8264 : addrs = gpr_malloc(sizeof(grpc_resolved_addresses));
132 8264 : addrs->naddrs = 0;
133 24180 : for (resp = result; resp != NULL; resp = resp->ai_next) {
134 15916 : addrs->naddrs++;
135 : }
136 8264 : addrs->addrs = gpr_malloc(sizeof(grpc_resolved_address) * addrs->naddrs);
137 8190 : i = 0;
138 24180 : for (resp = result; resp != NULL; resp = resp->ai_next) {
139 15916 : memcpy(&addrs->addrs[i].addr, resp->ai_addr, resp->ai_addrlen);
140 15916 : addrs->addrs[i].len = resp->ai_addrlen;
141 15916 : i++;
142 : }
143 :
144 : done:
145 8277 : gpr_free(host);
146 8277 : gpr_free(port);
147 8277 : if (result) {
148 8264 : freeaddrinfo(result);
149 : }
150 8277 : return addrs;
151 : }
152 :
153 : /* Callback to be passed to grpc_executor to asynch-ify
154 : * grpc_blocking_resolve_address */
155 6016 : static void do_request_thread(grpc_exec_ctx *exec_ctx, void *rp, int success) {
156 5971 : request *r = rp;
157 6016 : grpc_resolved_addresses *resolved =
158 6016 : grpc_blocking_resolve_address(r->name, r->default_port);
159 6016 : void *arg = r->arg;
160 6016 : grpc_resolve_cb cb = r->cb;
161 6016 : gpr_free(r->name);
162 6016 : gpr_free(r->default_port);
163 6016 : cb(exec_ctx, arg, resolved);
164 6016 : gpr_free(r);
165 6016 : }
166 :
167 8760 : void grpc_resolved_addresses_destroy(grpc_resolved_addresses *addrs) {
168 8760 : gpr_free(addrs->addrs);
169 8760 : gpr_free(addrs);
170 8760 : }
171 :
172 6016 : void grpc_resolve_address(const char *name, const char *default_port,
173 : grpc_resolve_cb cb, void *arg) {
174 6016 : request *r = gpr_malloc(sizeof(request));
175 6016 : grpc_closure_init(&r->request_closure, do_request_thread, r);
176 6016 : r->name = gpr_strdup(name);
177 6016 : r->default_port = gpr_strdup(default_port);
178 6016 : r->cb = cb;
179 6016 : r->arg = arg;
180 6016 : grpc_executor_enqueue(&r->request_closure, 1);
181 6016 : }
182 :
183 : #endif
|