blob: daa8d3a7c6acf6de6f01c2e85af7dcc640c683b1 [file] [log] [blame]
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001/*
2 *
Craig Tiller06059952015-02-18 08:34:56 -08003 * Copyright 2015, Google Inc.
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08004 * 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
Nicolas "Pixel" Nobled5a99852015-01-24 01:27:48 -080034#include "src/core/iomgr/sockaddr.h"
35
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080036#include <grpc/grpc.h>
37
38#include <stdlib.h>
39#include <string.h>
40
41#include "src/core/channel/census_filter.h"
42#include "src/core/channel/channel_args.h"
43#include "src/core/channel/client_channel.h"
44#include "src/core/channel/client_setup.h"
45#include "src/core/channel/connected_channel.h"
46#include "src/core/channel/http_client_filter.h"
ctiller2bbb6c42014-12-17 09:44:44 -080047#include "src/core/iomgr/endpoint.h"
ctiller18b49ab2014-12-09 14:39:16 -080048#include "src/core/iomgr/resolve_address.h"
49#include "src/core/iomgr/tcp_client.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080050#include "src/core/surface/channel.h"
51#include "src/core/surface/client.h"
Craig Tiller485d7762015-01-23 12:54:05 -080052#include "src/core/support/string.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080053#include "src/core/transport/chttp2_transport.h"
54#include <grpc/support/alloc.h>
55#include <grpc/support/log.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080056#include <grpc/support/sync.h>
57#include <grpc/support/useful.h>
58
59typedef struct setup setup;
60
61/* A single setup request (started via initiate) */
62typedef struct {
63 grpc_client_setup_request *cs_request;
64 setup *setup;
65 /* Resolved addresses, or null if resolution not yet completed */
66 grpc_resolved_addresses *resolved;
67 /* which address in resolved should we pick for the next connection attempt */
68 size_t resolved_index;
69} request;
70
71/* Global setup logic (may be running many simultaneous setup requests, but
72 with only one 'active' */
73struct setup {
74 const char *target;
75 grpc_transport_setup_callback setup_callback;
76 void *setup_user_data;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080077};
78
79static int maybe_try_next_resolved(request *r);
80
81static void done(request *r, int was_successful) {
82 grpc_client_setup_request_finish(r->cs_request, was_successful);
83 if (r->resolved) {
84 grpc_resolved_addresses_destroy(r->resolved);
85 }
86 gpr_free(r);
87}
88
89/* connection callback: tcp is either valid, or null on error */
90static void on_connect(void *rp, grpc_endpoint *tcp) {
91 request *r = rp;
92
93 if (!grpc_client_setup_request_should_continue(r->cs_request)) {
94 if (tcp) {
95 grpc_endpoint_shutdown(tcp);
96 grpc_endpoint_destroy(tcp);
97 }
98 done(r, 0);
99 return;
100 }
101
102 if (!tcp) {
103 if (!maybe_try_next_resolved(r)) {
104 done(r, 0);
105 return;
106 } else {
107 return;
108 }
Craig Tiller43a2b172015-02-18 17:17:51 -0800109 } else if (grpc_client_setup_cb_begin(r->cs_request)) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800110 grpc_create_chttp2_transport(
111 r->setup->setup_callback, r->setup->setup_user_data,
112 grpc_client_setup_get_channel_args(r->cs_request), tcp, NULL, 0,
113 grpc_client_setup_get_mdctx(r->cs_request), 1);
Craig Tiller43a2b172015-02-18 17:17:51 -0800114 grpc_client_setup_cb_end(r->cs_request);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800115 done(r, 1);
116 return;
Craig Tiller43a2b172015-02-18 17:17:51 -0800117 } else {
118 done(r, 0);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800119 }
120}
121
122/* attempt to connect to the next available resolved address */
123static int maybe_try_next_resolved(request *r) {
124 grpc_resolved_address *addr;
125 if (!r->resolved) return 0;
126 if (r->resolved_index == r->resolved->naddrs) return 0;
127 addr = &r->resolved->addrs[r->resolved_index++];
ctiller18b49ab2014-12-09 14:39:16 -0800128 grpc_tcp_client_connect(on_connect, r, (struct sockaddr *)&addr->addr,
129 addr->len,
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800130 grpc_client_setup_request_deadline(r->cs_request));
131 return 1;
132}
133
134/* callback for when our target address has been resolved */
135static void on_resolved(void *rp, grpc_resolved_addresses *resolved) {
136 request *r = rp;
137
138 /* if we're not still the active request, abort */
139 if (!grpc_client_setup_request_should_continue(r->cs_request)) {
140 if (resolved) {
141 grpc_resolved_addresses_destroy(resolved);
142 }
143 done(r, 0);
144 return;
145 }
146
147 if (!resolved) {
148 done(r, 0);
149 return;
150 } else {
151 r->resolved = resolved;
152 r->resolved_index = 0;
153 if (!maybe_try_next_resolved(r)) {
154 done(r, 0);
155 }
156 }
157}
158
159static void initiate_setup(void *sp, grpc_client_setup_request *cs_request) {
160 request *r = gpr_malloc(sizeof(request));
161 r->setup = sp;
162 r->cs_request = cs_request;
163 r->resolved = NULL;
164 r->resolved_index = 0;
165 /* TODO(klempner): Make grpc_resolve_address respect deadline */
166 grpc_resolve_address(r->setup->target, "http", on_resolved, r);
167}
168
169static void done_setup(void *sp) {
170 setup *s = sp;
171 gpr_free((void *)s->target);
172 gpr_free(s);
173}
174
175static grpc_transport_setup_result complete_setup(void *channel_stack,
176 grpc_transport *transport,
177 grpc_mdctx *mdctx) {
Craig Tiller06aeea72015-04-23 10:54:45 -0700178 static grpc_channel_filter const *extra_filters[] = {
179 &grpc_http_client_filter};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800180 return grpc_client_channel_transport_setup_complete(
181 channel_stack, transport, extra_filters, GPR_ARRAY_SIZE(extra_filters),
182 mdctx);
183}
184
185/* Create a client channel:
186 Asynchronously: - resolve target
187 - connect to it (trying alternatives as presented)
188 - perform handshakes */
189grpc_channel *grpc_channel_create(const char *target,
190 const grpc_channel_args *args) {
191 setup *s = gpr_malloc(sizeof(setup));
192 grpc_mdctx *mdctx = grpc_mdctx_create();
193 grpc_channel *channel = NULL;
194#define MAX_FILTERS 3
195 const grpc_channel_filter *filters[MAX_FILTERS];
196 int n = 0;
197 filters[n++] = &grpc_client_surface_filter;
198 if (grpc_channel_args_is_census_enabled(args)) {
199 filters[n++] = &grpc_client_census_filter;
200 }
201 filters[n++] = &grpc_client_channel_filter;
202 GPR_ASSERT(n <= MAX_FILTERS);
203 channel = grpc_channel_create_from_filters(filters, n, args, mdctx, 1);
204
205 s->target = gpr_strdup(target);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800206 s->setup_callback = complete_setup;
207 s->setup_user_data = grpc_channel_get_channel_stack(channel);
208
209 grpc_client_setup_create_and_attach(grpc_channel_get_channel_stack(channel),
210 args, mdctx, initiate_setup, done_setup,
ctiller18b49ab2014-12-09 14:39:16 -0800211 s);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800212
213 return channel;
Craig Tiller190d3602015-02-18 09:23:38 -0800214}