aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core
diff options
context:
space:
mode:
authorGravatar Craig Tiller <ctiller@google.com>2015-06-24 15:41:15 -0700
committerGravatar Craig Tiller <ctiller@google.com>2015-06-24 15:41:15 -0700
commit3bc8ebd48eceab0fc9fe2ef4f7a94c1f937172ba (patch)
treea0d3deeb2658619fdbef1019b4d389687aba9ec2 /src/core
parentcf4db6d9a7ae63dd0afa452e9c5b4d9cdc328c0a (diff)
Implementation work for client_config
- uri parsing - dns resolution
Diffstat (limited to 'src/core')
-rw-r--r--src/core/client_config/client_config.h1
-rw-r--r--src/core/client_config/lb_policies/pick_first.c34
-rw-r--r--src/core/client_config/lb_policies/pick_first.h42
-rw-r--r--src/core/client_config/resolver.h3
-rw-r--r--src/core/client_config/resolver_factory.h29
-rw-r--r--src/core/client_config/resolver_registry.c102
-rw-r--r--src/core/client_config/resolver_registry.h54
-rw-r--r--src/core/client_config/resolvers/dns_resolver.c227
-rw-r--r--src/core/client_config/resolvers/dns_resolver.h7
-rw-r--r--src/core/client_config/subchannel_factory.h5
-rw-r--r--src/core/client_config/uri_parser.c169
-rw-r--r--src/core/client_config/uri_parser.h52
12 files changed, 706 insertions, 19 deletions
diff --git a/src/core/client_config/client_config.h b/src/core/client_config/client_config.h
index 44d281f671..47612da42c 100644
--- a/src/core/client_config/client_config.h
+++ b/src/core/client_config/client_config.h
@@ -40,6 +40,7 @@
grpc_resolver */
typedef struct grpc_client_config grpc_client_config;
+grpc_client_config *grpc_client_config_create();
void grpc_client_config_ref(grpc_client_config *client_config);
void grpc_client_config_unref(grpc_client_config *client_config);
diff --git a/src/core/client_config/lb_policies/pick_first.c b/src/core/client_config/lb_policies/pick_first.c
new file mode 100644
index 0000000000..46732b8444
--- /dev/null
+++ b/src/core/client_config/lb_policies/pick_first.c
@@ -0,0 +1,34 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "src/core/client_config/lb_policies/pick_first.h"
diff --git a/src/core/client_config/lb_policies/pick_first.h b/src/core/client_config/lb_policies/pick_first.h
new file mode 100644
index 0000000000..94c2a9f0c7
--- /dev/null
+++ b/src/core/client_config/lb_policies/pick_first.h
@@ -0,0 +1,42 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPC_INTERNAL_CORE_CLIENT_CONFIG_PICK_FIRST_H
+#define GRPC_INTERNAL_CORE_CLIENT_CONFIG_PICK_FIRST_H
+
+#include "src/core/client_config/lb_policy.h"
+
+grpc_lb_policy *grpc_create_pick_first_lb_policy(grpc_subchannel **subchannels,
+ size_t num_subchannels);
+
+#endif
diff --git a/src/core/client_config/resolver.h b/src/core/client_config/resolver.h
index 7ff955ec6e..13d48bc572 100644
--- a/src/core/client_config/resolver.h
+++ b/src/core/client_config/resolver.h
@@ -52,7 +52,8 @@ struct grpc_resolver_vtable {
void (*unref)(grpc_resolver *resolver);
void (*shutdown)(grpc_resolver *resolver);
void (*channel_saw_error)(grpc_resolver *resolver,
- struct sockaddr *failing_address);
+ struct sockaddr *failing_address,
+ int failing_address_len);
void (*next)(grpc_resolver *resolver, grpc_client_config **target_config,
grpc_iomgr_closure *on_complete);
};
diff --git a/src/core/client_config/resolver_factory.h b/src/core/client_config/resolver_factory.h
index 701910d71a..c5d85499c6 100644
--- a/src/core/client_config/resolver_factory.h
+++ b/src/core/client_config/resolver_factory.h
@@ -34,31 +34,34 @@
#ifndef GRPC_INTERNAL_CORE_CLIENT_CONFIG_RESOLVER_FACTORY_H
#define GRPC_INTERNAL_CORE_CLIENT_CONFIG_RESOLVER_FACTORY_H
-#include "src/core/client_config/client_config.h"
-#include "src/core/iomgr/iomgr.h"
-#include "src/core/iomgr/sockaddr.h"
+#include "src/core/client_config/resolver.h"
+#include "src/core/client_config/subchannel_factory.h"
+#include "src/core/client_config/uri_parser.h"
-typedef struct grpc_resolver grpc_resolver;
-typedef struct grpc_resolver_vtable grpc_resolver_vtable;
+typedef struct grpc_resolver_factory grpc_resolver_factory;
+typedef struct grpc_resolver_factory_vtable grpc_resolver_factory_vtable;
/** grpc_resolver provides grpc_client_config objects to grpc_channel
objects */
-struct grpc_resolver {
- const grpc_resolver_vtable *vtable;
+struct grpc_resolver_factory {
+ const grpc_resolver_factory_vtable *vtable;
};
struct grpc_resolver_factory_vtable {
- void (*ref)(grpc_resolver *resolver);
- void (*unref)(grpc_resolver *resolver);
+ void (*ref)(grpc_resolver_factory *factory);
+ void (*unref)(grpc_resolver_factory *factory);
- grpc_resolver *(*create_resolver)(const char *name);
+ grpc_resolver *(*create_resolver)(
+ grpc_resolver_factory *factory, grpc_uri *uri,
+ grpc_subchannel_factory *subchannel_factory);
};
-void grpc_resolver_factory_ref(grpc_resolver *resolver);
-void grpc_resolver_factory_unref(grpc_resolver *resolver);
+void grpc_resolver_factory_ref(grpc_resolver_factory *resolver);
+void grpc_resolver_factory_unref(grpc_resolver_factory *resolver);
/** Create a resolver instance for a name */
grpc_resolver *grpc_resolver_factory_create_resolver(
- grpc_resolver_factory *resolver, const char *name);
+ grpc_resolver_factory *factory, grpc_uri *uri,
+ grpc_subchannel_factory *subchannel_factory);
#endif /* GRPC_INTERNAL_CORE_CONFIG_RESOLVER_FACTORY_H */
diff --git a/src/core/client_config/resolver_registry.c b/src/core/client_config/resolver_registry.c
new file mode 100644
index 0000000000..770d4aca8e
--- /dev/null
+++ b/src/core/client_config/resolver_registry.c
@@ -0,0 +1,102 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "src/core/client_config/resolver_registry.h"
+
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+
+#define MAX_RESOLVERS 10
+
+typedef struct {
+ char *scheme;
+ grpc_resolver_factory *factory;
+} registered_resolver;
+
+static registered_resolver all_of_the_resolvers[MAX_RESOLVERS];
+static int number_of_resolvers = 0;
+
+void grpc_resolver_registry_init(grpc_resolver_factory *r) {
+ number_of_resolvers = 0;
+ grpc_register_resolver_type("default-grpc-resolver", r);
+}
+
+void grpc_resolver_registry_shutdown(void) {
+ int i;
+ for (i = 0; i < number_of_resolvers; i++) {
+ gpr_free(all_of_the_resolvers[i].scheme);
+ grpc_resolver_factory_unref(all_of_the_resolvers[i].factory);
+ }
+}
+
+void grpc_register_resolver_type(const char *scheme,
+ grpc_resolver_factory *factory) {
+ int i;
+ for (i = 0; i < number_of_resolvers; i++) {
+ GPR_ASSERT(0 != strcmp(scheme, all_of_the_resolvers[i].scheme));
+ }
+ GPR_ASSERT(number_of_resolvers != MAX_RESOLVERS);
+ all_of_the_resolvers[number_of_resolvers].scheme = gpr_strdup(scheme);
+ grpc_resolver_factory_ref(factory);
+ all_of_the_resolvers[number_of_resolvers].factory = factory;
+ number_of_resolvers++;
+}
+
+grpc_resolver *grpc_resolver_create(
+ const char *name, grpc_subchannel_factory *subchannel_factory) {
+ grpc_uri *uri;
+ int i;
+ char *tmp;
+ grpc_resolver *resolver = NULL;
+ if (grpc_has_scheme(name)) {
+ uri = grpc_uri_parse(name);
+ if (!uri) {
+ return NULL;
+ }
+ for (i = 0; i < number_of_resolvers; i++) {
+ if (0 == strcmp(all_of_the_resolvers[i].scheme, uri->scheme)) {
+ grpc_resolver_factory_create_resolver(all_of_the_resolvers[i].factory,
+ uri, subchannel_factory);
+ }
+ }
+ } else {
+ gpr_asprintf(&tmp, "default-grpc-resolver:%s", name);
+ GPR_ASSERT(grpc_has_scheme(tmp));
+ resolver = grpc_resolver_create(tmp, subchannel_factory);
+ gpr_free(tmp);
+ }
+ return resolver;
+}
diff --git a/src/core/client_config/resolver_registry.h b/src/core/client_config/resolver_registry.h
new file mode 100644
index 0000000000..53335172da
--- /dev/null
+++ b/src/core/client_config/resolver_registry.h
@@ -0,0 +1,54 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPC_INTERNAL_CORE_CLIENT_CONFIG_RESOLVER_REGISTRY_H
+#define GRPC_INTERNAL_CORE_CLIENT_CONFIG_RESOLVER_REGISTRY_H
+
+#include "src/core/client_config/resolver_factory.h"
+
+void grpc_resolver_registry_init(grpc_resolver_factory *default_resolver);
+void grpc_resolver_registry_shutdown(void);
+
+/** Register a resolver type.
+ URI's of \a scheme will be resolved with the given resolver.
+ If \a priority is greater than zero, then the resolver will be eligible
+ to resolve names that are passed in with no scheme. Higher priority
+ resolvers will be tried before lower priority schemes. */
+void grpc_register_resolver_type(const char *scheme,
+ grpc_resolver_factory *factory);
+
+/** Create a resolver given a \a uri string (with an optional scheme prefix) */
+grpc_resolver *grpc_resolver_create(
+ const char *name, grpc_subchannel_factory *subchannel_factory);
+
+#endif /* GRPC_INTERNAL_CORE_CLIENT_CONFIG_RESOLVER_REGISTRY_H */
diff --git a/src/core/client_config/resolvers/dns_resolver.c b/src/core/client_config/resolvers/dns_resolver.c
index 187ff26466..95f38ecab7 100644
--- a/src/core/client_config/resolvers/dns_resolver.c
+++ b/src/core/client_config/resolvers/dns_resolver.c
@@ -33,4 +33,229 @@
#include "src/core/client_config/resolvers/dns_resolver.h"
- \ No newline at end of file
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/string_util.h>
+
+#include "src/core/iomgr/resolve_address.h"
+#include "src/core/support/string.h"
+
+typedef struct {
+ /** base class: must be first */
+ grpc_resolver base;
+ /** refcount */
+ gpr_refcount refs;
+ /** name to resolve */
+ char *name;
+ /** default port to use */
+ char *default_port;
+ /** subchannel factory */
+ grpc_subchannel_factory *subchannel_factory;
+ /** load balancing policy factory */
+ grpc_lb_policy *(*lb_policy_factory)(grpc_subchannel **subchannels,
+ size_t num_subchannels);
+
+ /** mutex guarding the rest of the state */
+ gpr_mu mu;
+ /** are we currently resolving? */
+ int resolving;
+ /** which version of resolved_config have we published? */
+ int published_version;
+ /** which version of resolved_config is current? */
+ int resolved_version;
+ /** pending next completion, or NULL */
+ grpc_iomgr_closure *next_completion;
+ /** target config address for next completion */
+ grpc_client_config **target_config;
+ /** current (fully resolved) config */
+ grpc_client_config *resolved_config;
+} dns_resolver;
+
+static void dns_destroy(dns_resolver *r);
+
+static void dns_start_resolving_locked(dns_resolver *r);
+static void dns_maybe_finish_next_locked(dns_resolver *r);
+
+static void dns_ref(grpc_resolver *r);
+static void dns_unref(grpc_resolver *r);
+static void dns_shutdown(grpc_resolver *r);
+static void dns_channel_saw_error(grpc_resolver *r,
+ struct sockaddr *failing_address,
+ int failing_address_len);
+static void dns_next(grpc_resolver *r, grpc_client_config **target_config,
+ grpc_iomgr_closure *on_complete);
+
+static const grpc_resolver_vtable dns_resolver_vtable = {
+ dns_ref, dns_unref, dns_shutdown, dns_channel_saw_error, dns_next};
+
+static void dns_ref(grpc_resolver *resolver) {
+ dns_resolver *r = (dns_resolver *)resolver;
+ gpr_ref(&r->refs);
+}
+
+static void dns_unref(grpc_resolver *resolver) {
+ dns_resolver *r = (dns_resolver *)resolver;
+ if (gpr_unref(&r->refs)) {
+ dns_destroy(r);
+ }
+}
+
+static void dns_shutdown(grpc_resolver *resolver) {
+ dns_resolver *r = (dns_resolver *)resolver;
+ gpr_mu_lock(&r->mu);
+ if (r->next_completion != NULL) {
+ *r->target_config = NULL;
+ /* TODO(ctiller): add delayed callback */
+ grpc_iomgr_add_callback(r->next_completion);
+ r->next_completion = NULL;
+ }
+ gpr_mu_unlock(&r->mu);
+}
+
+static void dns_channel_saw_error(grpc_resolver *resolver, struct sockaddr *sa,
+ int len) {
+ dns_resolver *r = (dns_resolver *)resolver;
+ gpr_mu_lock(&r->mu);
+ if (!r->resolving) {
+ dns_start_resolving_locked(r);
+ }
+ gpr_mu_unlock(&r->mu);
+}
+
+static void dns_next(grpc_resolver *resolver,
+ grpc_client_config **target_config,
+ grpc_iomgr_closure *on_complete) {
+ dns_resolver *r = (dns_resolver *)resolver;
+ gpr_mu_lock(&r->mu);
+ GPR_ASSERT(!r->next_completion);
+ r->next_completion = on_complete;
+ r->target_config = target_config;
+ if (r->resolved_version == 0 && !r->resolving) {
+ dns_start_resolving_locked(r);
+ } else {
+ dns_maybe_finish_next_locked(r);
+ }
+ gpr_mu_unlock(&r->mu);
+}
+
+static void dns_on_resolved(void *arg, grpc_resolved_addresses *addresses) {
+ dns_resolver *r = arg;
+ grpc_client_config *config = NULL;
+ grpc_subchannel **subchannels;
+ grpc_subchannel_args args;
+ size_t i;
+ if (addresses) {
+ config = grpc_client_config_create();
+ subchannels = gpr_malloc(sizeof(grpc_subchannel *) * addresses->naddrs);
+ for (i = 0; i < addresses->naddrs; i++) {
+ memset(&args, 0, sizeof(args));
+ args.addr = (struct sockaddr *)(addresses->addrs[i].addr);
+ args.addr_len = addresses->addrs[i].len;
+ subchannels[i] = grpc_subchannel_factory_create_subchannel(
+ r->subchannel_factory, &args);
+ }
+ grpc_client_config_set_lb_policy(
+ config, r->lb_policy_factory(subchannels, addresses->naddrs));
+ }
+ gpr_mu_lock(&r->mu);
+ if (r->resolved_config) {
+ grpc_client_config_unref(r->resolved_config);
+ }
+ r->resolved_config = config;
+ r->resolved_version++;
+ dns_maybe_finish_next_locked(r);
+ gpr_mu_unlock(&r->mu);
+}
+
+static void dns_start_resolving_locked(dns_resolver *r) {
+ dns_ref(&r->base);
+ r->resolving = 1;
+ grpc_resolve_address(r->name, r->default_port, dns_on_resolved, r);
+}
+
+static void dns_maybe_finish_next_locked(dns_resolver *r) {
+ if (r->next_completion != NULL &&
+ r->resolved_version != r->published_version) {
+ grpc_iomgr_add_callback(r->next_completion);
+ r->next_completion = NULL;
+ r->published_version = r->resolved_version;
+ }
+}
+
+static void dns_destroy(dns_resolver *r) {
+ gpr_mu_destroy(&r->mu);
+ grpc_subchannel_factory_unref(r->subchannel_factory);
+ gpr_free(r->name);
+ gpr_free(r->default_port);
+ gpr_free(r);
+}
+
+static grpc_resolver *dns_create(grpc_uri *uri, const char *default_port,
+ grpc_subchannel_factory *subchannel_factory) {
+ dns_resolver *r;
+ const char *path = uri->path;
+
+ if (0 != strcmp(uri->authority, "")) {
+ gpr_log(GPR_ERROR, "authority based uri's not supported");
+ return NULL;
+ }
+
+ if (path[0] == '/') ++path;
+
+ r = gpr_malloc(sizeof(dns_resolver));
+ memset(r, 0, sizeof(*r));
+ gpr_ref_init(&r->refs, 1);
+ gpr_mu_init(&r->mu);
+ r->base.vtable = &dns_resolver_vtable;
+ r->name = gpr_strdup(path);
+ r->default_port = gpr_strdup(default_port);
+ r->subchannel_factory = subchannel_factory;
+ grpc_subchannel_factory_ref(subchannel_factory);
+ return &r->base;
+}
+
+/*
+ * FACTORY
+ */
+
+typedef struct {
+ /** base: must be first */
+ grpc_resolver_factory base;
+ /** ref count */
+ gpr_refcount refs;
+ /** default port */
+ char *default_port;
+} dns_resolver_factory;
+
+static void dns_factory_ref(grpc_resolver_factory *factory) {
+ dns_resolver_factory *f = (dns_resolver_factory *)factory;
+ gpr_ref(&f->refs);
+}
+
+static void dns_factory_unref(grpc_resolver_factory *factory) {
+ dns_resolver_factory *f = (dns_resolver_factory *)factory;
+ if (gpr_unref(&f->refs)) {
+ gpr_free(f->default_port);
+ gpr_free(f);
+ }
+}
+
+static grpc_resolver *dns_factory_create_resolver(
+ grpc_resolver_factory *factory, grpc_uri *uri,
+ grpc_subchannel_factory *subchannel_factory) {
+ dns_resolver_factory *f = (dns_resolver_factory *)factory;
+ return dns_create(uri, f->default_port, subchannel_factory);
+}
+
+static const grpc_resolver_factory_vtable dns_factory_vtable = {
+ dns_factory_ref, dns_factory_unref, dns_factory_create_resolver};
+
+grpc_resolver_factory *grpc_dns_resolver_factory_create(
+ const char *default_port) {
+ dns_resolver_factory *f = gpr_malloc(sizeof(*f));
+ memset(f, 0, sizeof(*f));
+ f->base.vtable = &dns_factory_vtable;
+ f->default_port = gpr_strdup(default_port);
+ return &f->base;
+}
diff --git a/src/core/client_config/resolvers/dns_resolver.h b/src/core/client_config/resolvers/dns_resolver.h
index fc32baa15b..9881448fd8 100644
--- a/src/core/client_config/resolvers/dns_resolver.h
+++ b/src/core/client_config/resolvers/dns_resolver.h
@@ -34,7 +34,10 @@
#ifndef GRPC_INTERNAL_CORE_CLIENT_CONFIG_RESOLVERS_DNS_RESOLVER_H
#define GRPC_INTERNAL_CORE_CLIENT_CONFIG_RESOLVERS_DNS_RESOLVER_H
+#include "src/core/client_config/resolver_factory.h"
+
/** Create a dns resolver for \a name */
-grpc_resolver *grpc_dns_resolver_create(const char *name);
+grpc_resolver_factory *grpc_dns_resolver_factory_create(
+ const char *default_port);
-#endif /* GRPC_INTERNAL_CORE_CLIENT_CONFIG_RESOLVERS_DNS_RESOLVER_H */
+#endif /* GRPC_INTERNAL_CORE_CLIENT_CONFIG_RESOLVERS_DNS_RESOLVER_H */
diff --git a/src/core/client_config/subchannel_factory.h b/src/core/client_config/subchannel_factory.h
index 26fa329797..cbe984f428 100644
--- a/src/core/client_config/subchannel_factory.h
+++ b/src/core/client_config/subchannel_factory.h
@@ -57,6 +57,7 @@ struct grpc_subchannel_args {
const grpc_channel_args *args;
/** Address to connect to */
struct sockaddr *addr;
+ size_t addr_len;
};
struct grpc_subchannel_factory_vtable {
@@ -70,7 +71,7 @@ void grpc_subchannel_factory_ref(grpc_subchannel_factory *factory);
void grpc_subchannel_factory_unref(grpc_subchannel_factory *factory);
/** Create a new grpc_subchannel */
-void grpc_subchannel_factory_create_subchannel(grpc_subchannel_factory *factory,
- grpc_subchannel_args *args);
+grpc_subchannel *grpc_subchannel_factory_create_subchannel(
+ grpc_subchannel_factory *factory, grpc_subchannel_args *args);
#endif /* GRPC_INTERNAL_CORE_CLIENT_CONFIG_SUBCHANNEL_FACTORY_H */
diff --git a/src/core/client_config/uri_parser.c b/src/core/client_config/uri_parser.c
new file mode 100644
index 0000000000..24dfaae497
--- /dev/null
+++ b/src/core/client_config/uri_parser.c
@@ -0,0 +1,169 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "src/core/client_config/uri_parser.h"
+
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+
+static grpc_uri *bad_uri(const char *uri_text, int pos, const char *section) {
+ char *line_prefix;
+ int pfx_len;
+
+ gpr_asprintf(&line_prefix, "bad uri.%s: '", section);
+ pfx_len = strlen(line_prefix) + pos;
+ gpr_log(GPR_ERROR, "%s%s'", line_prefix, uri_text);
+ gpr_free(line_prefix);
+
+ line_prefix = gpr_malloc(pfx_len + 1);
+ memset(line_prefix, ' ', pfx_len);
+ line_prefix[pfx_len] = 0;
+ gpr_log(GPR_ERROR, "%s^ here", line_prefix);
+ gpr_free(line_prefix);
+
+ return NULL;
+}
+
+static char *copy_fragment(const char *src, int begin, int end) {
+ char *out = gpr_malloc(end - begin + 1);
+ memcpy(out, src + begin, end - begin);
+ out[end - begin] = 0;
+ return out;
+}
+
+int grpc_has_scheme(const char *uri_text) {
+ int scheme_begin = 0;
+ int scheme_end = -1;
+ int i;
+
+ for (i = scheme_begin; uri_text[i] != 0; i++) {
+ if (uri_text[i] == ':') {
+ scheme_end = i;
+ break;
+ }
+ if (uri_text[i] >= 'a' && uri_text[i] <= 'z') continue;
+ if (uri_text[i] >= 'A' && uri_text[i] <= 'Z') continue;
+ if (i != scheme_begin) {
+ if (uri_text[i] >= '0' && uri_text[i] <= '9') continue;
+ if (uri_text[i] == '+') continue;
+ if (uri_text[i] == '-') continue;
+ if (uri_text[i] == '.') continue;
+ }
+ break;
+ }
+
+ return scheme_end != -1;
+}
+
+grpc_uri *grpc_uri_parse(const char *uri_text) {
+ grpc_uri *uri;
+ int scheme_begin = 0;
+ int scheme_end = -1;
+ int authority_begin = -1;
+ int authority_end = -1;
+ int path_begin = -1;
+ int path_end = -1;
+ int i;
+
+ for (i = scheme_begin; uri_text[i] != 0; i++) {
+ if (uri_text[i] == ':') {
+ scheme_end = i;
+ break;
+ }
+ if (uri_text[i] >= 'a' && uri_text[i] <= 'z') continue;
+ if (uri_text[i] >= 'A' && uri_text[i] <= 'Z') continue;
+ if (i != scheme_begin) {
+ if (uri_text[i] >= '0' && uri_text[i] <= '9') continue;
+ if (uri_text[i] == '+') continue;
+ if (uri_text[i] == '-') continue;
+ if (uri_text[i] == '.') continue;
+ }
+ break;
+ }
+ if (scheme_end == -1) {
+ return bad_uri(uri_text, i, "scheme");
+ }
+
+ if (uri_text[scheme_end + 1] == '/' && uri_text[scheme_end + 2] == '/') {
+ authority_begin = scheme_end + 3;
+ for (i = authority_begin; uri_text[i] != 0; i++) {
+ if (uri_text[i] == '/') {
+ authority_end = i;
+ }
+ if (uri_text[i] == '?') {
+ return bad_uri(uri_text, i, "query_not_supported");
+ }
+ if (uri_text[i] == '#') {
+ return bad_uri(uri_text, i, "fragment_not_supported");
+ }
+ }
+ if (authority_end == -1 && uri_text[i] == 0) {
+ authority_end = i;
+ }
+ if (authority_end == -1) {
+ return bad_uri(uri_text, i, "authority");
+ }
+ /* TODO(ctiller): parse the authority correctly */
+ path_begin = authority_end;
+ } else {
+ path_begin = scheme_end + 1;
+ }
+
+ for (i = path_begin; uri_text[i] != 0; i++) {
+ if (uri_text[i] == '?') {
+ return bad_uri(uri_text, i, "query_not_supported");
+ }
+ if (uri_text[i] == '#') {
+ return bad_uri(uri_text, i, "fragment_not_supported");
+ }
+ }
+ path_end = i;
+
+ uri = gpr_malloc(sizeof(*uri));
+ memset(uri, 0, sizeof(*uri));
+ uri->scheme = copy_fragment(uri_text, scheme_begin, scheme_end);
+ uri->authority = copy_fragment(uri_text, authority_begin, authority_end);
+ uri->path = copy_fragment(uri_text, path_begin, path_end);
+
+ return uri;
+}
+
+void grpc_uri_destroy(grpc_uri *uri) {
+ gpr_free(uri->scheme);
+ gpr_free(uri->authority);
+ gpr_free(uri->path);
+ gpr_free(uri);
+}
diff --git a/src/core/client_config/uri_parser.h b/src/core/client_config/uri_parser.h
new file mode 100644
index 0000000000..0e21d568a9
--- /dev/null
+++ b/src/core/client_config/uri_parser.h
@@ -0,0 +1,52 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef GRPC_INTERNAL_CORE_CLIENT_CONFIG_URI_PARSER_H
+#define GRPC_INTERNAL_CORE_CLIENT_CONFIG_URI_PARSER_H
+
+typedef struct {
+ char *scheme;
+ char *authority;
+ char *path;
+} grpc_uri;
+
+/** parse a uri, return NULL on failure */
+grpc_uri *grpc_uri_parse(const char *uri_text);
+
+/** return 1 if uri_text has something that is likely a scheme, 0 otherwise */
+int grpc_has_scheme(const char *uri_text);
+
+/** destroy a uri */
+void grpc_uri_destroy(grpc_uri *uri);
+
+#endif