diff options
author | Nicolas "Pixel" Noble <pixel@nobis-crew.org> | 2017-06-26 22:01:11 +0200 |
---|---|---|
committer | Nicolas "Pixel" Noble <pixel@nobis-crew.org> | 2017-06-26 22:01:11 +0200 |
commit | 5d80dc4985ef01a468e027df75912bfc1e95579d (patch) | |
tree | 17bf626f6c6709661435924a74ada235e777c221 /src/core/ext/filters/client_channel/resolver/fake | |
parent | e7c2458d66b4e4210fb4c5d7e1670aef6b4c9381 (diff) | |
parent | 8bec6a93163861e467005a23c997eb93b793710b (diff) |
Merge branch 'master' of https://github.com/grpc/grpc into import
Diffstat (limited to 'src/core/ext/filters/client_channel/resolver/fake')
-rw-r--r-- | src/core/ext/filters/client_channel/resolver/fake/fake_resolver.c | 241 | ||||
-rw-r--r-- | src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h | 60 |
2 files changed, 301 insertions, 0 deletions
diff --git a/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.c b/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.c new file mode 100644 index 0000000000..a311334d13 --- /dev/null +++ b/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.c @@ -0,0 +1,241 @@ +// +// Copyright 2016 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +// This is similar to the sockaddr resolver, except that it supports a +// bunch of query args that are useful for dependency injection in tests. + +#include <limits.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <grpc/support/alloc.h> +#include <grpc/support/host_port.h> +#include <grpc/support/port_platform.h> +#include <grpc/support/string_util.h> + +#include "src/core/ext/filters/client_channel/lb_policy_factory.h" +#include "src/core/ext/filters/client_channel/parse_address.h" +#include "src/core/ext/filters/client_channel/resolver_registry.h" +#include "src/core/lib/channel/channel_args.h" +#include "src/core/lib/iomgr/combiner.h" +#include "src/core/lib/iomgr/resolve_address.h" +#include "src/core/lib/iomgr/unix_sockets_posix.h" +#include "src/core/lib/slice/slice_internal.h" +#include "src/core/lib/slice/slice_string_helpers.h" +#include "src/core/lib/support/string.h" + +#include "src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h" + +// +// fake_resolver +// + +typedef struct { + // base class -- must be first + grpc_resolver base; + + // passed-in parameters + grpc_channel_args* channel_args; + + // If not NULL, the next set of resolution results to be returned to + // grpc_resolver_next_locked()'s closure. + grpc_channel_args* next_results; + + // pending next completion, or NULL + grpc_closure* next_completion; + // target result address for next completion + grpc_channel_args** target_result; +} fake_resolver; + +static void fake_resolver_destroy(grpc_exec_ctx* exec_ctx, grpc_resolver* gr) { + fake_resolver* r = (fake_resolver*)gr; + grpc_channel_args_destroy(exec_ctx, r->next_results); + grpc_channel_args_destroy(exec_ctx, r->channel_args); + gpr_free(r); +} + +static void fake_resolver_shutdown_locked(grpc_exec_ctx* exec_ctx, + grpc_resolver* resolver) { + fake_resolver* r = (fake_resolver*)resolver; + if (r->next_completion != NULL) { + *r->target_result = NULL; + GRPC_CLOSURE_SCHED( + exec_ctx, r->next_completion, + GRPC_ERROR_CREATE_FROM_STATIC_STRING("Resolver Shutdown")); + r->next_completion = NULL; + } +} + +static void fake_resolver_maybe_finish_next_locked(grpc_exec_ctx* exec_ctx, + fake_resolver* r) { + if (r->next_completion != NULL && r->next_results != NULL) { + *r->target_result = + grpc_channel_args_union(r->next_results, r->channel_args); + grpc_channel_args_destroy(exec_ctx, r->next_results); + GRPC_CLOSURE_SCHED(exec_ctx, r->next_completion, GRPC_ERROR_NONE); + r->next_completion = NULL; + r->next_results = NULL; + } +} + +static void fake_resolver_channel_saw_error_locked(grpc_exec_ctx* exec_ctx, + grpc_resolver* resolver) { + fake_resolver* r = (fake_resolver*)resolver; + fake_resolver_maybe_finish_next_locked(exec_ctx, r); +} + +static void fake_resolver_next_locked(grpc_exec_ctx* exec_ctx, + grpc_resolver* resolver, + grpc_channel_args** target_result, + grpc_closure* on_complete) { + fake_resolver* r = (fake_resolver*)resolver; + GPR_ASSERT(!r->next_completion); + r->next_completion = on_complete; + r->target_result = target_result; + fake_resolver_maybe_finish_next_locked(exec_ctx, r); +} + +static const grpc_resolver_vtable fake_resolver_vtable = { + fake_resolver_destroy, fake_resolver_shutdown_locked, + fake_resolver_channel_saw_error_locked, fake_resolver_next_locked}; + +struct grpc_fake_resolver_response_generator { + fake_resolver* resolver; // Set by the fake_resolver constructor to itself. + grpc_channel_args* next_response; + gpr_refcount refcount; +}; + +grpc_fake_resolver_response_generator* +grpc_fake_resolver_response_generator_create() { + grpc_fake_resolver_response_generator* generator = + (grpc_fake_resolver_response_generator*)gpr_zalloc(sizeof(*generator)); + gpr_ref_init(&generator->refcount, 1); + return generator; +} + +grpc_fake_resolver_response_generator* +grpc_fake_resolver_response_generator_ref( + grpc_fake_resolver_response_generator* generator) { + gpr_ref(&generator->refcount); + return generator; +} + +void grpc_fake_resolver_response_generator_unref( + grpc_fake_resolver_response_generator* generator) { + if (gpr_unref(&generator->refcount)) { + gpr_free(generator); + } +} + +static void set_response_cb(grpc_exec_ctx* exec_ctx, void* arg, + grpc_error* error) { + grpc_fake_resolver_response_generator* generator = + (grpc_fake_resolver_response_generator*)arg; + fake_resolver* r = generator->resolver; + if (r->next_results != NULL) { + grpc_channel_args_destroy(exec_ctx, r->next_results); + } + r->next_results = generator->next_response; + fake_resolver_maybe_finish_next_locked(exec_ctx, r); +} + +void grpc_fake_resolver_response_generator_set_response( + grpc_exec_ctx* exec_ctx, grpc_fake_resolver_response_generator* generator, + grpc_channel_args* next_response) { + GPR_ASSERT(generator->resolver != NULL); + generator->next_response = grpc_channel_args_copy(next_response); + GRPC_CLOSURE_SCHED( + exec_ctx, GRPC_CLOSURE_CREATE(set_response_cb, generator, + grpc_combiner_scheduler( + generator->resolver->base.combiner)), + GRPC_ERROR_NONE); +} + +static void* response_generator_arg_copy(void* p) { + return grpc_fake_resolver_response_generator_ref( + (grpc_fake_resolver_response_generator*)p); +} + +static void response_generator_arg_destroy(grpc_exec_ctx* exec_ctx, void* p) { + grpc_fake_resolver_response_generator_unref( + (grpc_fake_resolver_response_generator*)p); +} + +static int response_generator_cmp(void* a, void* b) { return GPR_ICMP(a, b); } + +static const grpc_arg_pointer_vtable response_generator_arg_vtable = { + response_generator_arg_copy, response_generator_arg_destroy, + response_generator_cmp}; + +grpc_arg grpc_fake_resolver_response_generator_arg( + grpc_fake_resolver_response_generator* generator) { + grpc_arg arg; + arg.type = GRPC_ARG_POINTER; + arg.key = GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR; + arg.value.pointer.p = generator; + arg.value.pointer.vtable = &response_generator_arg_vtable; + return arg; +} + +grpc_fake_resolver_response_generator* +grpc_fake_resolver_get_response_generator(const grpc_channel_args* args) { + const grpc_arg* arg = + grpc_channel_args_find(args, GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR); + if (arg == NULL || arg->type != GRPC_ARG_POINTER) return NULL; + return (grpc_fake_resolver_response_generator*)arg->value.pointer.p; +} + +// +// fake_resolver_factory +// + +static void fake_resolver_factory_ref(grpc_resolver_factory* factory) {} + +static void fake_resolver_factory_unref(grpc_resolver_factory* factory) {} + +static grpc_resolver* fake_resolver_create(grpc_exec_ctx* exec_ctx, + grpc_resolver_factory* factory, + grpc_resolver_args* args) { + fake_resolver* r = (fake_resolver*)gpr_zalloc(sizeof(*r)); + r->channel_args = grpc_channel_args_copy(args->args); + grpc_resolver_init(&r->base, &fake_resolver_vtable, args->combiner); + grpc_fake_resolver_response_generator* response_generator = + grpc_fake_resolver_get_response_generator(args->args); + if (response_generator != NULL) response_generator->resolver = r; + return &r->base; +} + +static char* fake_resolver_get_default_authority(grpc_resolver_factory* factory, + grpc_uri* uri) { + const char* path = uri->path; + if (path[0] == '/') ++path; + return gpr_strdup(path); +} + +static const grpc_resolver_factory_vtable fake_resolver_factory_vtable = { + fake_resolver_factory_ref, fake_resolver_factory_unref, + fake_resolver_create, fake_resolver_get_default_authority, "fake"}; + +static grpc_resolver_factory fake_resolver_factory = { + &fake_resolver_factory_vtable}; + +void grpc_resolver_fake_init(void) { + grpc_register_resolver_type(&fake_resolver_factory); +} + +void grpc_resolver_fake_shutdown(void) {} diff --git a/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h b/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h new file mode 100644 index 0000000000..c084ef2a58 --- /dev/null +++ b/src/core/ext/filters/client_channel/resolver/fake/fake_resolver.h @@ -0,0 +1,60 @@ +// +// Copyright 2016 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_FAKE_FAKE_RESOLVER_H +#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_FAKE_FAKE_RESOLVER_H + +#include "src/core/ext/filters/client_channel/lb_policy_factory.h" +#include "src/core/ext/filters/client_channel/uri_parser.h" +#include "src/core/lib/channel/channel_args.h" + +#define GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR \ + "grpc.fake_resolver.response_generator" + +void grpc_resolver_fake_init(); + +// Instances of \a grpc_fake_resolver_response_generator are passed to the +// fake resolver in a channel argument (see \a +// grpc_fake_resolver_response_generator_arg) in order to inject and trigger +// custom resolutions. See also \a +// grpc_fake_resolver_response_generator_set_response. +typedef struct grpc_fake_resolver_response_generator + grpc_fake_resolver_response_generator; +grpc_fake_resolver_response_generator* +grpc_fake_resolver_response_generator_create(); + +// Instruct the fake resolver associated with the \a response_generator instance +// to trigger a new resolution for \a uri and \a args. +void grpc_fake_resolver_response_generator_set_response( + grpc_exec_ctx* exec_ctx, grpc_fake_resolver_response_generator* generator, + grpc_channel_args* next_response); + +// Return a \a grpc_arg for a \a grpc_fake_resolver_response_generator instance. +grpc_arg grpc_fake_resolver_response_generator_arg( + grpc_fake_resolver_response_generator* generator); +// Return the \a grpc_fake_resolver_response_generator instance in \a args or +// NULL. +grpc_fake_resolver_response_generator* +grpc_fake_resolver_get_response_generator(const grpc_channel_args* args); + +grpc_fake_resolver_response_generator* +grpc_fake_resolver_response_generator_ref( + grpc_fake_resolver_response_generator* generator); +void grpc_fake_resolver_response_generator_unref( + grpc_fake_resolver_response_generator* generator); + +#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_FAKE_FAKE_RESOLVER_H \ + */ |