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/grpc.h>
35 :
36 : #include <stdlib.h>
37 : #include <string.h>
38 :
39 : #include <grpc/support/alloc.h>
40 :
41 : #include "src/core/census/grpc_filter.h"
42 : #include "src/core/channel/channel_args.h"
43 : #include "src/core/channel/client_channel.h"
44 : #include "src/core/channel/compress_filter.h"
45 : #include "src/core/channel/http_client_filter.h"
46 : #include "src/core/client_config/resolver_registry.h"
47 : #include "src/core/iomgr/tcp_client.h"
48 : #include "src/core/security/auth_filters.h"
49 : #include "src/core/security/credentials.h"
50 : #include "src/core/surface/api_trace.h"
51 : #include "src/core/surface/channel.h"
52 : #include "src/core/transport/chttp2_transport.h"
53 : #include "src/core/tsi/transport_security_interface.h"
54 :
55 : typedef struct {
56 : grpc_connector base;
57 : gpr_refcount refs;
58 :
59 : grpc_channel_security_connector *security_connector;
60 :
61 : grpc_closure *notify;
62 : grpc_connect_in_args args;
63 : grpc_connect_out_args *result;
64 :
65 : gpr_mu mu;
66 : grpc_endpoint *connecting_endpoint;
67 : grpc_endpoint *newly_connecting_endpoint;
68 :
69 : grpc_closure connected_closure;
70 :
71 : grpc_mdctx *mdctx;
72 : } connector;
73 :
74 419 : static void connector_ref(grpc_connector *con) {
75 419 : connector *c = (connector *)con;
76 419 : gpr_ref(&c->refs);
77 419 : }
78 :
79 838 : static void connector_unref(grpc_exec_ctx *exec_ctx, grpc_connector *con) {
80 838 : connector *c = (connector *)con;
81 838 : if (gpr_unref(&c->refs)) {
82 419 : grpc_mdctx_unref(c->mdctx);
83 419 : gpr_free(c);
84 : }
85 838 : }
86 :
87 446 : static void on_secure_handshake_done(grpc_exec_ctx *exec_ctx, void *arg,
88 : grpc_security_status status,
89 : grpc_endpoint *wrapped_endpoint,
90 : grpc_endpoint *secure_endpoint) {
91 446 : connector *c = arg;
92 : grpc_closure *notify;
93 446 : gpr_mu_lock(&c->mu);
94 446 : if (c->connecting_endpoint == NULL) {
95 8 : memset(c->result, 0, sizeof(*c->result));
96 8 : gpr_mu_unlock(&c->mu);
97 438 : } else if (status != GRPC_SECURITY_OK) {
98 0 : GPR_ASSERT(c->connecting_endpoint == wrapped_endpoint);
99 0 : gpr_log(GPR_ERROR, "Secure handshake failed with error %d.", status);
100 0 : memset(c->result, 0, sizeof(*c->result));
101 0 : c->connecting_endpoint = NULL;
102 0 : gpr_mu_unlock(&c->mu);
103 : } else {
104 438 : GPR_ASSERT(c->connecting_endpoint == wrapped_endpoint);
105 438 : c->connecting_endpoint = NULL;
106 438 : gpr_mu_unlock(&c->mu);
107 438 : c->result->transport = grpc_create_chttp2_transport(
108 : exec_ctx, c->args.channel_args, secure_endpoint, c->mdctx, 1);
109 438 : grpc_chttp2_transport_start_reading(exec_ctx, c->result->transport, NULL,
110 : 0);
111 438 : c->result->filters = gpr_malloc(sizeof(grpc_channel_filter *) * 2);
112 438 : c->result->filters[0] = &grpc_http_client_filter;
113 438 : c->result->filters[1] = &grpc_client_auth_filter;
114 438 : c->result->num_filters = 2;
115 : }
116 446 : notify = c->notify;
117 446 : c->notify = NULL;
118 446 : notify->cb(exec_ctx, notify->cb_arg, 1);
119 446 : }
120 :
121 531 : static void connected(grpc_exec_ctx *exec_ctx, void *arg, int success) {
122 531 : connector *c = arg;
123 : grpc_closure *notify;
124 531 : grpc_endpoint *tcp = c->newly_connecting_endpoint;
125 531 : if (tcp != NULL) {
126 446 : gpr_mu_lock(&c->mu);
127 446 : GPR_ASSERT(c->connecting_endpoint == NULL);
128 446 : c->connecting_endpoint = tcp;
129 446 : gpr_mu_unlock(&c->mu);
130 446 : grpc_security_connector_do_handshake(exec_ctx, &c->security_connector->base,
131 : tcp, on_secure_handshake_done, c);
132 : } else {
133 85 : memset(c->result, 0, sizeof(*c->result));
134 85 : notify = c->notify;
135 85 : c->notify = NULL;
136 85 : notify->cb(exec_ctx, notify->cb_arg, 1);
137 : }
138 531 : }
139 :
140 399 : static void connector_shutdown(grpc_exec_ctx *exec_ctx, grpc_connector *con) {
141 399 : connector *c = (connector *)con;
142 : grpc_endpoint *ep;
143 399 : gpr_mu_lock(&c->mu);
144 399 : ep = c->connecting_endpoint;
145 399 : c->connecting_endpoint = NULL;
146 399 : gpr_mu_unlock(&c->mu);
147 399 : if (ep) {
148 8 : grpc_endpoint_shutdown(exec_ctx, ep);
149 : }
150 399 : }
151 :
152 531 : static void connector_connect(grpc_exec_ctx *exec_ctx, grpc_connector *con,
153 : const grpc_connect_in_args *args,
154 : grpc_connect_out_args *result,
155 : grpc_closure *notify) {
156 531 : connector *c = (connector *)con;
157 531 : GPR_ASSERT(c->notify == NULL);
158 531 : GPR_ASSERT(notify->cb);
159 531 : c->notify = notify;
160 531 : c->args = *args;
161 531 : c->result = result;
162 531 : gpr_mu_lock(&c->mu);
163 531 : GPR_ASSERT(c->connecting_endpoint == NULL);
164 531 : gpr_mu_unlock(&c->mu);
165 531 : grpc_closure_init(&c->connected_closure, connected, c);
166 531 : grpc_tcp_client_connect(
167 : exec_ctx, &c->connected_closure, &c->newly_connecting_endpoint,
168 : args->interested_parties, args->addr, args->addr_len, args->deadline);
169 531 : }
170 :
171 : static const grpc_connector_vtable connector_vtable = {
172 : connector_ref, connector_unref, connector_shutdown, connector_connect};
173 :
174 : typedef struct {
175 : grpc_subchannel_factory base;
176 : gpr_refcount refs;
177 : grpc_mdctx *mdctx;
178 : grpc_channel_args *merge_args;
179 : grpc_channel_security_connector *security_connector;
180 : grpc_channel *master;
181 : } subchannel_factory;
182 :
183 518 : static void subchannel_factory_ref(grpc_subchannel_factory *scf) {
184 518 : subchannel_factory *f = (subchannel_factory *)scf;
185 518 : gpr_ref(&f->refs);
186 518 : }
187 :
188 1036 : static void subchannel_factory_unref(grpc_exec_ctx *exec_ctx,
189 : grpc_subchannel_factory *scf) {
190 1036 : subchannel_factory *f = (subchannel_factory *)scf;
191 1036 : if (gpr_unref(&f->refs)) {
192 518 : GRPC_SECURITY_CONNECTOR_UNREF(&f->security_connector->base,
193 : "subchannel_factory");
194 518 : GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, f->master, "subchannel_factory");
195 518 : grpc_channel_args_destroy(f->merge_args);
196 518 : grpc_mdctx_unref(f->mdctx);
197 518 : gpr_free(f);
198 : }
199 1036 : }
200 :
201 419 : static grpc_subchannel *subchannel_factory_create_subchannel(
202 : grpc_exec_ctx *exec_ctx, grpc_subchannel_factory *scf,
203 : grpc_subchannel_args *args) {
204 419 : subchannel_factory *f = (subchannel_factory *)scf;
205 419 : connector *c = gpr_malloc(sizeof(*c));
206 419 : grpc_channel_args *final_args =
207 419 : grpc_channel_args_merge(args->args, f->merge_args);
208 : grpc_subchannel *s;
209 419 : memset(c, 0, sizeof(*c));
210 419 : c->base.vtable = &connector_vtable;
211 419 : c->security_connector = f->security_connector;
212 419 : c->mdctx = f->mdctx;
213 419 : gpr_mu_init(&c->mu);
214 419 : grpc_mdctx_ref(c->mdctx);
215 419 : gpr_ref_init(&c->refs, 1);
216 419 : args->args = final_args;
217 419 : args->master = f->master;
218 419 : args->mdctx = f->mdctx;
219 419 : s = grpc_subchannel_create(&c->base, args);
220 419 : grpc_connector_unref(exec_ctx, &c->base);
221 419 : grpc_channel_args_destroy(final_args);
222 419 : return s;
223 : }
224 :
225 : static const grpc_subchannel_factory_vtable subchannel_factory_vtable = {
226 : subchannel_factory_ref, subchannel_factory_unref,
227 : subchannel_factory_create_subchannel};
228 :
229 : /* Create a secure client channel:
230 : Asynchronously: - resolve target
231 : - connect to it (trying alternatives as presented)
232 : - perform handshakes */
233 518 : grpc_channel *grpc_secure_channel_create(grpc_credentials *creds,
234 : const char *target,
235 : const grpc_channel_args *args,
236 : void *reserved) {
237 : grpc_channel *channel;
238 : grpc_arg connector_arg;
239 : grpc_channel_args *args_copy;
240 : grpc_channel_args *new_args_from_connector;
241 : grpc_channel_security_connector *security_connector;
242 : grpc_mdctx *mdctx;
243 : grpc_resolver *resolver;
244 : subchannel_factory *f;
245 : #define MAX_FILTERS 3
246 : const grpc_channel_filter *filters[MAX_FILTERS];
247 518 : grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
248 518 : size_t n = 0;
249 :
250 518 : GRPC_API_TRACE(
251 : "grpc_secure_channel_create(creds=%p, target=%s, args=%p, "
252 : "reserved=%p)",
253 : 4, (creds, target, args, reserved));
254 518 : GPR_ASSERT(reserved == NULL);
255 :
256 518 : if (grpc_find_security_connector_in_args(args) != NULL) {
257 0 : gpr_log(GPR_ERROR, "Cannot set security context in channel args.");
258 0 : grpc_exec_ctx_finish(&exec_ctx);
259 0 : return grpc_lame_client_channel_create(
260 : target, GRPC_STATUS_INVALID_ARGUMENT,
261 : "Security connector exists in channel args.");
262 : }
263 :
264 518 : if (grpc_credentials_create_security_connector(
265 : creds, target, args, NULL, &security_connector,
266 : &new_args_from_connector) != GRPC_SECURITY_OK) {
267 0 : grpc_exec_ctx_finish(&exec_ctx);
268 0 : return grpc_lame_client_channel_create(
269 : target, GRPC_STATUS_INVALID_ARGUMENT,
270 : "Failed to create security connector.");
271 : }
272 518 : mdctx = grpc_mdctx_create();
273 :
274 518 : connector_arg = grpc_security_connector_to_arg(&security_connector->base);
275 518 : args_copy = grpc_channel_args_copy_and_add(
276 518 : new_args_from_connector != NULL ? new_args_from_connector : args,
277 : &connector_arg, 1);
278 518 : if (grpc_channel_args_is_census_enabled(args)) {
279 5 : filters[n++] = &grpc_client_census_filter;
280 : }
281 518 : filters[n++] = &grpc_compress_filter;
282 518 : filters[n++] = &grpc_client_channel_filter;
283 518 : GPR_ASSERT(n <= MAX_FILTERS);
284 :
285 518 : channel = grpc_channel_create_from_filters(&exec_ctx, target, filters, n,
286 : args_copy, mdctx, 1);
287 :
288 518 : f = gpr_malloc(sizeof(*f));
289 518 : f->base.vtable = &subchannel_factory_vtable;
290 518 : gpr_ref_init(&f->refs, 1);
291 518 : grpc_mdctx_ref(mdctx);
292 518 : f->mdctx = mdctx;
293 518 : GRPC_SECURITY_CONNECTOR_REF(&security_connector->base, "subchannel_factory");
294 518 : f->security_connector = security_connector;
295 518 : f->merge_args = grpc_channel_args_copy(args_copy);
296 518 : f->master = channel;
297 518 : GRPC_CHANNEL_INTERNAL_REF(channel, "subchannel_factory");
298 518 : resolver = grpc_resolver_create(target, &f->base);
299 518 : if (!resolver) {
300 0 : grpc_exec_ctx_finish(&exec_ctx);
301 0 : return NULL;
302 : }
303 :
304 518 : grpc_client_channel_set_resolver(
305 : &exec_ctx, grpc_channel_get_channel_stack(channel), resolver);
306 518 : GRPC_RESOLVER_UNREF(&exec_ctx, resolver, "create");
307 518 : grpc_subchannel_factory_unref(&exec_ctx, &f->base);
308 518 : GRPC_SECURITY_CONNECTOR_UNREF(&security_connector->base, "channel_create");
309 :
310 518 : grpc_channel_args_destroy(args_copy);
311 518 : if (new_args_from_connector != NULL) {
312 434 : grpc_channel_args_destroy(new_args_from_connector);
313 : }
314 :
315 518 : grpc_exec_ctx_finish(&exec_ctx);
316 :
317 518 : return channel;
318 : }
|