aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/client_config/resolvers/sockaddr_resolver.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/client_config/resolvers/sockaddr_resolver.c')
-rw-r--r--src/core/client_config/resolvers/sockaddr_resolver.c59
1 files changed, 48 insertions, 11 deletions
diff --git a/src/core/client_config/resolvers/sockaddr_resolver.c b/src/core/client_config/resolvers/sockaddr_resolver.c
index 74584e7e2c..8419873908 100644
--- a/src/core/client_config/resolvers/sockaddr_resolver.c
+++ b/src/core/client_config/resolvers/sockaddr_resolver.c
@@ -60,9 +60,12 @@ typedef struct {
grpc_lb_policy *(*lb_policy_factory)(grpc_subchannel **subchannels,
size_t num_subchannels);
- /** the address that we've 'resolved' */
- struct sockaddr_storage addr;
- int addr_len;
+ /** the addresses that we've 'resolved' */
+ struct sockaddr_storage *addrs;
+ /** the corresponding length of the addresses */
+ int *addrs_len;
+ /** how many elements in \a addrs */
+ size_t num_addrs;
/** mutex guarding the rest of the state */
gpr_mu mu;
@@ -119,17 +122,22 @@ static void sockaddr_next(grpc_resolver *resolver,
static void sockaddr_maybe_finish_next_locked(sockaddr_resolver *r) {
grpc_client_config *cfg;
grpc_lb_policy *lb_policy;
- grpc_subchannel *subchannel;
+ grpc_subchannel **subchannels;
grpc_subchannel_args args;
if (r->next_completion != NULL && !r->published) {
+ size_t i;
cfg = grpc_client_config_create();
- memset(&args, 0, sizeof(args));
- args.addr = (struct sockaddr *)&r->addr;
- args.addr_len = r->addr_len;
- subchannel =
- grpc_subchannel_factory_create_subchannel(r->subchannel_factory, &args);
- lb_policy = r->lb_policy_factory(&subchannel, 1);
+ subchannels = gpr_malloc(sizeof(grpc_subchannel *) * r->num_addrs);
+ for (i = 0; i < r->num_addrs; i++) {
+ memset(&args, 0, sizeof(args));
+ args.addr = (struct sockaddr *)&r->addrs[i];
+ args.addr_len = r->addrs_len[i];
+ subchannels[i] = grpc_subchannel_factory_create_subchannel(
+ r->subchannel_factory, &args);
+ }
+ lb_policy = r->lb_policy_factory(subchannels, r->num_addrs);
+ gpr_free(subchannels);
grpc_client_config_set_lb_policy(cfg, lb_policy);
GRPC_LB_POLICY_UNREF(lb_policy, "unix");
r->published = 1;
@@ -143,6 +151,8 @@ static void sockaddr_destroy(grpc_resolver *gr) {
sockaddr_resolver *r = (sockaddr_resolver *)gr;
gpr_mu_destroy(&r->mu);
grpc_subchannel_factory_unref(r->subchannel_factory);
+ gpr_free(r->addrs);
+ gpr_free(r->addrs_len);
gpr_free(r);
}
@@ -238,13 +248,18 @@ done:
return result;
}
+static void do_nothing(void *ignored) {}
static grpc_resolver *sockaddr_create(
grpc_uri *uri,
grpc_lb_policy *(*lb_policy_factory)(grpc_subchannel **subchannels,
size_t num_subchannels),
grpc_subchannel_factory *subchannel_factory,
int parse(grpc_uri *uri, struct sockaddr_storage *dst, int *len)) {
+ size_t i;
+ int errors_found = 0; /* GPR_FALSE */
sockaddr_resolver *r;
+ gpr_slice path_slice;
+ gpr_slice_buffer path_parts;
if (0 != strcmp(uri->authority, "")) {
gpr_log(GPR_ERROR, "authority based uri's not supported");
@@ -253,7 +268,29 @@ static grpc_resolver *sockaddr_create(
r = gpr_malloc(sizeof(sockaddr_resolver));
memset(r, 0, sizeof(*r));
- if (!parse(uri, &r->addr, &r->addr_len)) {
+
+ path_slice = gpr_slice_new(uri->path, strlen(uri->path), do_nothing);
+ gpr_slice_buffer_init(&path_parts);
+
+ gpr_slice_split(path_slice, ",", &path_parts);
+ r->num_addrs = path_parts.count;
+ r->addrs = gpr_malloc(sizeof(struct sockaddr_storage) * r->num_addrs);
+ r->addrs_len = gpr_malloc(sizeof(int) * r->num_addrs);
+
+ for(i = 0; i < r->num_addrs; i++) {
+ grpc_uri ith_uri = *uri;
+ char* part_str = gpr_dump_slice(path_parts.slices[i], GPR_DUMP_ASCII);
+ ith_uri.path = part_str;
+ if (!parse(&ith_uri, &r->addrs[i], &r->addrs_len[i])) {
+ errors_found = 1; /* GPR_TRUE */
+ }
+ gpr_free(part_str);
+ if (errors_found) break;
+ }
+
+ gpr_slice_buffer_destroy(&path_parts);
+ gpr_slice_unref(path_slice);
+ if (errors_found) {
gpr_free(r);
return NULL;
}