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/iomgr_internal.h"
45 : #include "src/core/iomgr/sockaddr_utils.h"
46 : #include "src/core/support/block_annotate.h"
47 : #include "src/core/support/string.h"
48 : #include <grpc/support/alloc.h>
49 : #include <grpc/support/host_port.h>
50 : #include <grpc/support/log.h>
51 : #include <grpc/support/string_util.h>
52 : #include <grpc/support/thd.h>
53 : #include <grpc/support/time.h>
54 : #include <grpc/support/useful.h>
55 :
56 : typedef struct {
57 : char *name;
58 : char *default_port;
59 : grpc_resolve_cb cb;
60 : void *arg;
61 : grpc_iomgr_object iomgr_object;
62 : } request;
63 :
64 5861 : grpc_resolved_addresses *grpc_blocking_resolve_address(
65 : const char *name, const char *default_port) {
66 : struct addrinfo hints;
67 5861 : struct addrinfo *result = NULL, *resp;
68 : char *host;
69 : char *port;
70 : int s;
71 : size_t i;
72 5861 : grpc_resolved_addresses *addrs = NULL;
73 : struct sockaddr_un *un;
74 :
75 6181 : if (name[0] == 'u' && name[1] == 'n' && name[2] == 'i' && name[3] == 'x' &&
76 640 : name[4] == ':' && name[5] != 0) {
77 320 : addrs = gpr_malloc(sizeof(grpc_resolved_addresses));
78 320 : addrs->naddrs = 1;
79 320 : addrs->addrs = gpr_malloc(sizeof(grpc_resolved_address));
80 320 : un = (struct sockaddr_un *)addrs->addrs->addr;
81 320 : un->sun_family = AF_UNIX;
82 320 : strcpy(un->sun_path, name + 5);
83 320 : addrs->addrs->len = strlen(un->sun_path) + sizeof(un->sun_family) + 1;
84 320 : return addrs;
85 : }
86 :
87 : /* parse name, splitting it into host and port parts */
88 5541 : gpr_split_host_port(name, &host, &port);
89 5541 : if (host == NULL) {
90 6 : gpr_log(GPR_ERROR, "unparseable host:port: '%s'", name);
91 6 : goto done;
92 : }
93 5535 : if (port == NULL) {
94 7 : if (default_port == NULL) {
95 1 : gpr_log(GPR_ERROR, "no port in name '%s'", name);
96 1 : goto done;
97 : }
98 6 : port = gpr_strdup(default_port);
99 : }
100 :
101 : /* Call getaddrinfo */
102 5534 : memset(&hints, 0, sizeof(hints));
103 5534 : hints.ai_family = AF_UNSPEC; /* ipv4 or ipv6 */
104 5534 : hints.ai_socktype = SOCK_STREAM; /* stream socket */
105 5534 : hints.ai_flags = AI_PASSIVE; /* for wildcard IP address */
106 :
107 : GRPC_SCHEDULING_START_BLOCKING_REGION;
108 5534 : s = getaddrinfo(host, port, &hints, &result);
109 : GRPC_SCHEDULING_END_BLOCKING_REGION;
110 :
111 5534 : if (s != 0) {
112 : /* Retry if well-known service name is recognized */
113 3 : char *svc[][2] = {{"http", "80"}, {"https", "443"}};
114 9 : for (i = 0; i < GPR_ARRAY_SIZE(svc); i++) {
115 6 : if (strcmp(port, svc[i][0]) == 0) {
116 : GRPC_SCHEDULING_START_BLOCKING_REGION;
117 0 : s = getaddrinfo(host, svc[i][1], &hints, &result);
118 : GRPC_SCHEDULING_END_BLOCKING_REGION;
119 0 : break;
120 : }
121 : }
122 : }
123 :
124 5534 : if (s != 0) {
125 3 : gpr_log(GPR_ERROR, "getaddrinfo: %s", gai_strerror(s));
126 3 : goto done;
127 : }
128 :
129 : /* Success path: set addrs non-NULL, fill it in */
130 5531 : addrs = gpr_malloc(sizeof(grpc_resolved_addresses));
131 5531 : addrs->naddrs = 0;
132 11072 : for (resp = result; resp != NULL; resp = resp->ai_next) {
133 5541 : addrs->naddrs++;
134 : }
135 5531 : addrs->addrs = gpr_malloc(sizeof(grpc_resolved_address) * addrs->naddrs);
136 5531 : i = 0;
137 11072 : for (resp = result; resp != NULL; resp = resp->ai_next) {
138 5541 : memcpy(&addrs->addrs[i].addr, resp->ai_addr, resp->ai_addrlen);
139 5541 : addrs->addrs[i].len = resp->ai_addrlen;
140 5541 : i++;
141 : }
142 :
143 : done:
144 5541 : gpr_free(host);
145 5541 : gpr_free(port);
146 5541 : if (result) {
147 5531 : freeaddrinfo(result);
148 : }
149 5541 : return addrs;
150 : }
151 :
152 : /* Thread function to asynch-ify grpc_blocking_resolve_address */
153 4086 : static void do_request_thread(void *rp) {
154 4086 : request *r = rp;
155 4086 : grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
156 4086 : grpc_resolved_addresses *resolved =
157 4086 : grpc_blocking_resolve_address(r->name, r->default_port);
158 4086 : void *arg = r->arg;
159 4086 : grpc_resolve_cb cb = r->cb;
160 4086 : gpr_free(r->name);
161 4086 : gpr_free(r->default_port);
162 4086 : cb(&exec_ctx, arg, resolved);
163 4086 : grpc_iomgr_unregister_object(&r->iomgr_object);
164 4086 : gpr_free(r);
165 4086 : grpc_exec_ctx_finish(&exec_ctx);
166 4086 : }
167 :
168 5851 : void grpc_resolved_addresses_destroy(grpc_resolved_addresses *addrs) {
169 5851 : gpr_free(addrs->addrs);
170 5851 : gpr_free(addrs);
171 5851 : }
172 :
173 4086 : void grpc_resolve_address(const char *name, const char *default_port,
174 : grpc_resolve_cb cb, void *arg) {
175 4086 : request *r = gpr_malloc(sizeof(request));
176 : gpr_thd_id id;
177 : char *tmp;
178 4086 : gpr_asprintf(&tmp, "resolve_address:name='%s':default_port='%s'", name,
179 : default_port);
180 4086 : grpc_iomgr_register_object(&r->iomgr_object, tmp);
181 4086 : gpr_free(tmp);
182 4086 : r->name = gpr_strdup(name);
183 4086 : r->default_port = gpr_strdup(default_port);
184 4086 : r->cb = cb;
185 4086 : r->arg = arg;
186 4086 : gpr_thd_new(&id, do_request_thread, r, NULL);
187 4086 : }
188 :
189 : #endif
|