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/surface/api_trace.h"
49 : #include "src/core/surface/channel.h"
50 : #include "src/core/transport/chttp2_transport.h"
51 :
52 : typedef struct {
53 : grpc_connector base;
54 : gpr_refcount refs;
55 :
56 : grpc_closure *notify;
57 : grpc_connect_in_args args;
58 : grpc_connect_out_args *result;
59 :
60 : grpc_endpoint *tcp;
61 :
62 : grpc_mdctx *mdctx;
63 :
64 : grpc_closure connected;
65 : } connector;
66 :
67 1051 : static void connector_ref(grpc_connector *con) {
68 1051 : connector *c = (connector *)con;
69 1051 : gpr_ref(&c->refs);
70 1051 : }
71 :
72 2102 : static void connector_unref(grpc_exec_ctx *exec_ctx, grpc_connector *con) {
73 2102 : connector *c = (connector *)con;
74 2102 : if (gpr_unref(&c->refs)) {
75 1051 : grpc_mdctx_unref(c->mdctx);
76 1051 : gpr_free(c);
77 : }
78 2102 : }
79 :
80 1390 : static void connected(grpc_exec_ctx *exec_ctx, void *arg, int success) {
81 1390 : connector *c = arg;
82 : grpc_closure *notify;
83 1390 : grpc_endpoint *tcp = c->tcp;
84 1390 : if (tcp != NULL) {
85 1110 : c->result->transport = grpc_create_chttp2_transport(
86 : exec_ctx, c->args.channel_args, tcp, c->mdctx, 1);
87 1110 : grpc_chttp2_transport_start_reading(exec_ctx, c->result->transport, NULL,
88 : 0);
89 1110 : GPR_ASSERT(c->result->transport);
90 1110 : c->result->filters = gpr_malloc(sizeof(grpc_channel_filter *));
91 1110 : c->result->filters[0] = &grpc_http_client_filter;
92 1110 : c->result->num_filters = 1;
93 : } else {
94 280 : memset(c->result, 0, sizeof(*c->result));
95 : }
96 1390 : notify = c->notify;
97 1390 : c->notify = NULL;
98 1390 : notify->cb(exec_ctx, notify->cb_arg, 1);
99 1390 : }
100 :
101 1012 : static void connector_shutdown(grpc_exec_ctx *exec_ctx, grpc_connector *con) {}
102 :
103 1390 : static void connector_connect(grpc_exec_ctx *exec_ctx, grpc_connector *con,
104 : const grpc_connect_in_args *args,
105 : grpc_connect_out_args *result,
106 : grpc_closure *notify) {
107 1390 : connector *c = (connector *)con;
108 1390 : GPR_ASSERT(c->notify == NULL);
109 1390 : GPR_ASSERT(notify->cb);
110 1390 : c->notify = notify;
111 1390 : c->args = *args;
112 1390 : c->result = result;
113 1390 : c->tcp = NULL;
114 1390 : grpc_closure_init(&c->connected, connected, c);
115 1390 : grpc_tcp_client_connect(exec_ctx, &c->connected, &c->tcp,
116 : args->interested_parties, args->addr, args->addr_len,
117 : args->deadline);
118 1390 : }
119 :
120 : static const grpc_connector_vtable connector_vtable = {
121 : connector_ref, connector_unref, connector_shutdown, connector_connect};
122 :
123 : typedef struct {
124 : grpc_subchannel_factory base;
125 : gpr_refcount refs;
126 : grpc_mdctx *mdctx;
127 : grpc_channel_args *merge_args;
128 : grpc_channel *master;
129 : } subchannel_factory;
130 :
131 1243 : static void subchannel_factory_ref(grpc_subchannel_factory *scf) {
132 1243 : subchannel_factory *f = (subchannel_factory *)scf;
133 1243 : gpr_ref(&f->refs);
134 1243 : }
135 :
136 2486 : static void subchannel_factory_unref(grpc_exec_ctx *exec_ctx,
137 : grpc_subchannel_factory *scf) {
138 2486 : subchannel_factory *f = (subchannel_factory *)scf;
139 2486 : if (gpr_unref(&f->refs)) {
140 1243 : GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, f->master, "subchannel_factory");
141 1243 : grpc_channel_args_destroy(f->merge_args);
142 1243 : grpc_mdctx_unref(f->mdctx);
143 1243 : gpr_free(f);
144 : }
145 2486 : }
146 :
147 1051 : static grpc_subchannel *subchannel_factory_create_subchannel(
148 : grpc_exec_ctx *exec_ctx, grpc_subchannel_factory *scf,
149 : grpc_subchannel_args *args) {
150 1051 : subchannel_factory *f = (subchannel_factory *)scf;
151 1051 : connector *c = gpr_malloc(sizeof(*c));
152 1051 : grpc_channel_args *final_args =
153 1051 : grpc_channel_args_merge(args->args, f->merge_args);
154 : grpc_subchannel *s;
155 1051 : memset(c, 0, sizeof(*c));
156 1051 : c->base.vtable = &connector_vtable;
157 1051 : c->mdctx = f->mdctx;
158 1051 : grpc_mdctx_ref(c->mdctx);
159 1051 : gpr_ref_init(&c->refs, 1);
160 1051 : args->mdctx = f->mdctx;
161 1051 : args->args = final_args;
162 1051 : args->master = f->master;
163 1051 : s = grpc_subchannel_create(&c->base, args);
164 1051 : grpc_connector_unref(exec_ctx, &c->base);
165 1051 : grpc_channel_args_destroy(final_args);
166 1051 : return s;
167 : }
168 :
169 : static const grpc_subchannel_factory_vtable subchannel_factory_vtable = {
170 : subchannel_factory_ref, subchannel_factory_unref,
171 : subchannel_factory_create_subchannel};
172 :
173 : /* Create a client channel:
174 : Asynchronously: - resolve target
175 : - connect to it (trying alternatives as presented)
176 : - perform handshakes */
177 1243 : grpc_channel *grpc_insecure_channel_create(const char *target,
178 : const grpc_channel_args *args,
179 : void *reserved) {
180 1243 : grpc_channel *channel = NULL;
181 : #define MAX_FILTERS 3
182 : const grpc_channel_filter *filters[MAX_FILTERS];
183 : grpc_resolver *resolver;
184 : subchannel_factory *f;
185 1243 : grpc_mdctx *mdctx = grpc_mdctx_create();
186 1243 : grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
187 1243 : size_t n = 0;
188 1243 : GRPC_API_TRACE(
189 : "grpc_insecure_channel_create(target=%p, args=%p, reserved=%p)", 3,
190 : (target, args, reserved));
191 1243 : GPR_ASSERT(!reserved);
192 1243 : if (grpc_channel_args_is_census_enabled(args)) {
193 12 : filters[n++] = &grpc_client_census_filter;
194 : }
195 1243 : filters[n++] = &grpc_compress_filter;
196 1243 : filters[n++] = &grpc_client_channel_filter;
197 1243 : GPR_ASSERT(n <= MAX_FILTERS);
198 :
199 1243 : channel = grpc_channel_create_from_filters(&exec_ctx, target, filters, n,
200 : args, mdctx, 1);
201 :
202 1243 : f = gpr_malloc(sizeof(*f));
203 1243 : f->base.vtable = &subchannel_factory_vtable;
204 1243 : gpr_ref_init(&f->refs, 1);
205 1243 : grpc_mdctx_ref(mdctx);
206 1243 : f->mdctx = mdctx;
207 1243 : f->merge_args = grpc_channel_args_copy(args);
208 1243 : f->master = channel;
209 1243 : GRPC_CHANNEL_INTERNAL_REF(f->master, "subchannel_factory");
210 1243 : resolver = grpc_resolver_create(target, &f->base);
211 1243 : if (!resolver) {
212 0 : return NULL;
213 : }
214 :
215 1243 : grpc_client_channel_set_resolver(
216 : &exec_ctx, grpc_channel_get_channel_stack(channel), resolver);
217 1243 : GRPC_RESOLVER_UNREF(&exec_ctx, resolver, "create");
218 1243 : grpc_subchannel_factory_unref(&exec_ctx, &f->base);
219 :
220 1243 : grpc_exec_ctx_finish(&exec_ctx);
221 :
222 1243 : return channel;
223 : }
|