blob: 9637cf39fec35befbff454d764717efbe1ee5b22 [file] [log] [blame]
Craig Tilleraf691802015-06-23 14:57:07 -07001/*
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 "src/core/client_config/subchannel.h"
Craig Tiller2595ab72015-06-25 15:26:00 -070035
Craig Tillerf7afa1f2015-06-26 09:02:20 -070036#include <string.h>
37
Craig Tiller2595ab72015-06-25 15:26:00 -070038#include <grpc/support/alloc.h>
39
Craig Tillereb3b12e2015-06-26 14:42:49 -070040#include "src/core/channel/channel_args.h"
41
42typedef struct {
43 gpr_refcount refs;
44 grpc_subchannel *subchannel;
45} connection;
46
Craig Tiller2595ab72015-06-25 15:26:00 -070047struct grpc_subchannel {
48 gpr_refcount refs;
Craig Tiller91624662015-06-25 16:31:02 -070049 grpc_connector *connector;
Craig Tillerf7afa1f2015-06-26 09:02:20 -070050
51 /** non-transport related channel filters */
52 const grpc_channel_filter **filters;
53 size_t filter_count;
54 /** channel arguments */
55 grpc_channel_args *args;
56 /** address to connect to */
57 struct sockaddr *addr;
58 size_t addr_len;
Craig Tillereb3b12e2015-06-26 14:42:49 -070059
60 /** set during connection */
61 grpc_transport *connecting_transport;
62
63 /** callback for connection finishing */
64 grpc_iomgr_closure connected;
65
66 /** mutex protecting remaining elements */
67 gpr_mu mu;
68
69 /** active connection */
70 connection *active;
71 /** are we connecting */
72 int connecting;
73 /** closures waiting for a connection */
74 grpc_iomgr_closure *waiting;
Craig Tiller2595ab72015-06-25 15:26:00 -070075};
76
77struct grpc_subchannel_call {
Craig Tillereb3b12e2015-06-26 14:42:49 -070078 connection *connection;
Craig Tiller2595ab72015-06-25 15:26:00 -070079 gpr_refcount refs;
80};
81
82#define SUBCHANNEL_CALL_TO_CALL_STACK(call) (((grpc_call_stack *)(call)) + 1)
83
Craig Tillereb3b12e2015-06-26 14:42:49 -070084static grpc_subchannel_call *create_call(connection *con, grpc_transport_stream_op *initial_op);
85
Craig Tiller2595ab72015-06-25 15:26:00 -070086/*
87 * grpc_subchannel implementation
88 */
89
Craig Tillereb3b12e2015-06-26 14:42:49 -070090void grpc_subchannel_ref(grpc_subchannel *c) { gpr_ref(&c->refs); }
Craig Tiller2595ab72015-06-25 15:26:00 -070091
Craig Tillereb3b12e2015-06-26 14:42:49 -070092void grpc_subchannel_unref(grpc_subchannel *c) {
93 if (gpr_unref(&c->refs)) {
94 gpr_free(c->filters);
95 grpc_channel_args_destroy(c->args);
96 gpr_free(c->addr);
97 gpr_free(c);
Craig Tiller2595ab72015-06-25 15:26:00 -070098 }
99}
100
Craig Tillerf7afa1f2015-06-26 09:02:20 -0700101grpc_subchannel *grpc_subchannel_create(grpc_connector *connector,
102 grpc_subchannel_args *args) {
103 grpc_subchannel *c = gpr_malloc(sizeof(*c));
104 memset(c, 0, sizeof(*c));
105 gpr_ref_init(&c->refs, 1);
106 c->connector = connector;
107 grpc_connector_ref(c->connector);
108 c->filters = gpr_malloc(sizeof(grpc_channel_filter *) * args->filter_count);
109 memcpy(c->filters, args->filters,
110 sizeof(grpc_channel_filter *) * args->filter_count);
111 c->filter_count = args->filter_count;
112 c->addr = gpr_malloc(args->addr_len);
113 memcpy(c->addr, args->addr, args->addr_len);
114 c->addr_len = args->addr_len;
Craig Tillereb3b12e2015-06-26 14:42:49 -0700115 c->args = grpc_channel_args_copy(args->args);
116 gpr_mu_init(&c->mu);
Craig Tillerf7afa1f2015-06-26 09:02:20 -0700117 return c;
118}
119
Craig Tillereb3b12e2015-06-26 14:42:49 -0700120void grpc_subchannel_create_call(grpc_subchannel *c,
121 grpc_mdctx *mdctx,
122 grpc_transport_stream_op *initial_op,
123 grpc_subchannel_call **target,
124 grpc_iomgr_closure *notify) {
125 connection *con;
126 gpr_mu_lock(&c->mu);
127 if (c->active != NULL) {
128 con = c->active;
129 gpr_ref(&con->refs);
130 gpr_mu_unlock(&c->mu);
131
132 *target = create_call(con, initial_op);
133 notify->cb(notify->cb_arg, 1);
134 } else {
135 notify->next = c->waiting;
136 c->waiting = notify;
137 if (!c->connecting) {
138 c->connecting = 1;
139 gpr_mu_unlock(&c->mu);
140
141 grpc_connector_connect(c->connector, c->args, mdctx, &c->connecting_transport, &c->connected);
142 } else {
143 gpr_mu_unlock(&c->mu);
144 }
145 }
146}
147
Craig Tiller2595ab72015-06-25 15:26:00 -0700148/*
149 * grpc_subchannel_call implementation
150 */
151
152void grpc_subchannel_call_ref(grpc_subchannel_call *call) {
153 gpr_ref(&call->refs);
154}
155
156void grpc_subchannel_call_unref(grpc_subchannel_call *call) {
157 if (gpr_unref(&call->refs)) {
158 grpc_call_stack_destroy(SUBCHANNEL_CALL_TO_CALL_STACK(call));
Craig Tillereb3b12e2015-06-26 14:42:49 -0700159 if (gpr_unref(&call->connection->refs)) {
160 gpr_free(call->connection);
161 }
Craig Tiller2595ab72015-06-25 15:26:00 -0700162 gpr_free(call);
163 }
164}
165
166void grpc_subchannel_call_process_op(grpc_subchannel_call *call,
167 grpc_transport_stream_op *op) {
168 grpc_call_stack *call_stack = SUBCHANNEL_CALL_TO_CALL_STACK(call);
169 grpc_call_element *top_elem = grpc_call_stack_element(call_stack, 0);
170 top_elem->filter->start_transport_stream_op(top_elem, op);
171}
Craig Tillereb3b12e2015-06-26 14:42:49 -0700172
173grpc_subchannel_call *create_call(connection *con, grpc_transport_stream_op *initial_op) {
174 abort();
175 return NULL;
176}