diff --git a/BUILD b/BUILD
index 18e1806e3e5..5f0d50ca0af 100644
--- a/BUILD
+++ b/BUILD
@@ -670,6 +670,8 @@ grpc_cc_library(
"src/core/ext/client_channel/lb_policy_factory.c",
"src/core/ext/client_channel/lb_policy_registry.c",
"src/core/ext/client_channel/parse_address.c",
+ "src/core/ext/client_channel/proxy_mapper.c",
+ "src/core/ext/client_channel/proxy_mapper_registry.c",
"src/core/ext/client_channel/resolver.c",
"src/core/ext/client_channel/resolver_factory.c",
"src/core/ext/client_channel/resolver_registry.c",
@@ -688,6 +690,8 @@ grpc_cc_library(
"src/core/ext/client_channel/lb_policy_factory.h",
"src/core/ext/client_channel/lb_policy_registry.h",
"src/core/ext/client_channel/parse_address.h",
+ "src/core/ext/client_channel/proxy_mapper.h",
+ "src/core/ext/client_channel/proxy_mapper_registry.h",
"src/core/ext/client_channel/resolver.h",
"src/core/ext/client_channel/resolver_factory.h",
"src/core/ext/client_channel/resolver_registry.h",
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c65c832d8f4..ad40bfc10d3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -577,6 +577,8 @@ add_library(grpc
src/core/ext/client_channel/lb_policy_factory.c
src/core/ext/client_channel/lb_policy_registry.c
src/core/ext/client_channel/parse_address.c
+ src/core/ext/client_channel/proxy_mapper.c
+ src/core/ext/client_channel/proxy_mapper_registry.c
src/core/ext/client_channel/resolver.c
src/core/ext/client_channel/resolver_factory.c
src/core/ext/client_channel/resolver_registry.c
@@ -839,6 +841,8 @@ add_library(grpc_cronet
src/core/ext/client_channel/lb_policy_factory.c
src/core/ext/client_channel/lb_policy_registry.c
src/core/ext/client_channel/parse_address.c
+ src/core/ext/client_channel/proxy_mapper.c
+ src/core/ext/client_channel/proxy_mapper_registry.c
src/core/ext/client_channel/resolver.c
src/core/ext/client_channel/resolver_factory.c
src/core/ext/client_channel/resolver_registry.c
@@ -1334,6 +1338,8 @@ add_library(grpc_unsecure
src/core/ext/client_channel/lb_policy_factory.c
src/core/ext/client_channel/lb_policy_registry.c
src/core/ext/client_channel/parse_address.c
+ src/core/ext/client_channel/proxy_mapper.c
+ src/core/ext/client_channel/proxy_mapper_registry.c
src/core/ext/client_channel/resolver.c
src/core/ext/client_channel/resolver_factory.c
src/core/ext/client_channel/resolver_registry.c
@@ -1838,6 +1844,8 @@ add_library(grpc++_cronet
src/core/ext/client_channel/lb_policy_factory.c
src/core/ext/client_channel/lb_policy_registry.c
src/core/ext/client_channel/parse_address.c
+ src/core/ext/client_channel/proxy_mapper.c
+ src/core/ext/client_channel/proxy_mapper_registry.c
src/core/ext/client_channel/resolver.c
src/core/ext/client_channel/resolver_factory.c
src/core/ext/client_channel/resolver_registry.c
diff --git a/Makefile b/Makefile
index 41c6ab2292e..a70d913cc1b 100644
--- a/Makefile
+++ b/Makefile
@@ -2837,6 +2837,8 @@ LIBGRPC_SRC = \
src/core/ext/client_channel/lb_policy_factory.c \
src/core/ext/client_channel/lb_policy_registry.c \
src/core/ext/client_channel/parse_address.c \
+ src/core/ext/client_channel/proxy_mapper.c \
+ src/core/ext/client_channel/proxy_mapper_registry.c \
src/core/ext/client_channel/resolver.c \
src/core/ext/client_channel/resolver_factory.c \
src/core/ext/client_channel/resolver_registry.c \
@@ -3115,6 +3117,8 @@ LIBGRPC_CRONET_SRC = \
src/core/ext/client_channel/lb_policy_factory.c \
src/core/ext/client_channel/lb_policy_registry.c \
src/core/ext/client_channel/parse_address.c \
+ src/core/ext/client_channel/proxy_mapper.c \
+ src/core/ext/client_channel/proxy_mapper_registry.c \
src/core/ext/client_channel/resolver.c \
src/core/ext/client_channel/resolver_factory.c \
src/core/ext/client_channel/resolver_registry.c \
@@ -3632,6 +3636,8 @@ LIBGRPC_UNSECURE_SRC = \
src/core/ext/client_channel/lb_policy_factory.c \
src/core/ext/client_channel/lb_policy_registry.c \
src/core/ext/client_channel/parse_address.c \
+ src/core/ext/client_channel/proxy_mapper.c \
+ src/core/ext/client_channel/proxy_mapper_registry.c \
src/core/ext/client_channel/resolver.c \
src/core/ext/client_channel/resolver_factory.c \
src/core/ext/client_channel/resolver_registry.c \
@@ -4191,6 +4197,8 @@ LIBGRPC++_CRONET_SRC = \
src/core/ext/client_channel/lb_policy_factory.c \
src/core/ext/client_channel/lb_policy_registry.c \
src/core/ext/client_channel/parse_address.c \
+ src/core/ext/client_channel/proxy_mapper.c \
+ src/core/ext/client_channel/proxy_mapper_registry.c \
src/core/ext/client_channel/resolver.c \
src/core/ext/client_channel/resolver_factory.c \
src/core/ext/client_channel/resolver_registry.c \
diff --git a/binding.gyp b/binding.gyp
index c70c4b8eb39..9328a30929c 100644
--- a/binding.gyp
+++ b/binding.gyp
@@ -781,6 +781,8 @@
'src/core/ext/client_channel/lb_policy_factory.c',
'src/core/ext/client_channel/lb_policy_registry.c',
'src/core/ext/client_channel/parse_address.c',
+ 'src/core/ext/client_channel/proxy_mapper.c',
+ 'src/core/ext/client_channel/proxy_mapper_registry.c',
'src/core/ext/client_channel/resolver.c',
'src/core/ext/client_channel/resolver_factory.c',
'src/core/ext/client_channel/resolver_registry.c',
diff --git a/build.yaml b/build.yaml
index 05fb2856827..a0f88dea217 100644
--- a/build.yaml
+++ b/build.yaml
@@ -395,6 +395,8 @@ filegroups:
- src/core/ext/client_channel/lb_policy_factory.h
- src/core/ext/client_channel/lb_policy_registry.h
- src/core/ext/client_channel/parse_address.h
+ - src/core/ext/client_channel/proxy_mapper.h
+ - src/core/ext/client_channel/proxy_mapper_registry.h
- src/core/ext/client_channel/resolver.h
- src/core/ext/client_channel/resolver_factory.h
- src/core/ext/client_channel/resolver_registry.h
@@ -415,6 +417,8 @@ filegroups:
- src/core/ext/client_channel/lb_policy_factory.c
- src/core/ext/client_channel/lb_policy_registry.c
- src/core/ext/client_channel/parse_address.c
+ - src/core/ext/client_channel/proxy_mapper.c
+ - src/core/ext/client_channel/proxy_mapper_registry.c
- src/core/ext/client_channel/resolver.c
- src/core/ext/client_channel/resolver_factory.c
- src/core/ext/client_channel/resolver_registry.c
diff --git a/config.m4 b/config.m4
index 45bbbf27c53..9b2d8192a60 100644
--- a/config.m4
+++ b/config.m4
@@ -260,6 +260,8 @@ if test "$PHP_GRPC" != "no"; then
src/core/ext/client_channel/lb_policy_factory.c \
src/core/ext/client_channel/lb_policy_registry.c \
src/core/ext/client_channel/parse_address.c \
+ src/core/ext/client_channel/proxy_mapper.c \
+ src/core/ext/client_channel/proxy_mapper_registry.c \
src/core/ext/client_channel/resolver.c \
src/core/ext/client_channel/resolver_factory.c \
src/core/ext/client_channel/resolver_registry.c \
diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec
index 1add33eadd1..d9d0f1052fe 100644
--- a/gRPC-Core.podspec
+++ b/gRPC-Core.podspec
@@ -406,6 +406,8 @@ Pod::Spec.new do |s|
'src/core/ext/client_channel/lb_policy_factory.h',
'src/core/ext/client_channel/lb_policy_registry.h',
'src/core/ext/client_channel/parse_address.h',
+ 'src/core/ext/client_channel/proxy_mapper.h',
+ 'src/core/ext/client_channel/proxy_mapper_registry.h',
'src/core/ext/client_channel/resolver.h',
'src/core/ext/client_channel/resolver_factory.h',
'src/core/ext/client_channel/resolver_registry.h',
@@ -613,6 +615,8 @@ Pod::Spec.new do |s|
'src/core/ext/client_channel/lb_policy_factory.c',
'src/core/ext/client_channel/lb_policy_registry.c',
'src/core/ext/client_channel/parse_address.c',
+ 'src/core/ext/client_channel/proxy_mapper.c',
+ 'src/core/ext/client_channel/proxy_mapper_registry.c',
'src/core/ext/client_channel/resolver.c',
'src/core/ext/client_channel/resolver_factory.c',
'src/core/ext/client_channel/resolver_registry.c',
@@ -820,6 +824,8 @@ Pod::Spec.new do |s|
'src/core/ext/client_channel/lb_policy_factory.h',
'src/core/ext/client_channel/lb_policy_registry.h',
'src/core/ext/client_channel/parse_address.h',
+ 'src/core/ext/client_channel/proxy_mapper.h',
+ 'src/core/ext/client_channel/proxy_mapper_registry.h',
'src/core/ext/client_channel/resolver.h',
'src/core/ext/client_channel/resolver_factory.h',
'src/core/ext/client_channel/resolver_registry.h',
diff --git a/grpc.gemspec b/grpc.gemspec
index 5092f6887af..2d84682456b 100755
--- a/grpc.gemspec
+++ b/grpc.gemspec
@@ -323,6 +323,8 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/client_channel/lb_policy_factory.h )
s.files += %w( src/core/ext/client_channel/lb_policy_registry.h )
s.files += %w( src/core/ext/client_channel/parse_address.h )
+ s.files += %w( src/core/ext/client_channel/proxy_mapper.h )
+ s.files += %w( src/core/ext/client_channel/proxy_mapper_registry.h )
s.files += %w( src/core/ext/client_channel/resolver.h )
s.files += %w( src/core/ext/client_channel/resolver_factory.h )
s.files += %w( src/core/ext/client_channel/resolver_registry.h )
@@ -530,6 +532,8 @@ Gem::Specification.new do |s|
s.files += %w( src/core/ext/client_channel/lb_policy_factory.c )
s.files += %w( src/core/ext/client_channel/lb_policy_registry.c )
s.files += %w( src/core/ext/client_channel/parse_address.c )
+ s.files += %w( src/core/ext/client_channel/proxy_mapper.c )
+ s.files += %w( src/core/ext/client_channel/proxy_mapper_registry.c )
s.files += %w( src/core/ext/client_channel/resolver.c )
s.files += %w( src/core/ext/client_channel/resolver_factory.c )
s.files += %w( src/core/ext/client_channel/resolver_registry.c )
diff --git a/package.xml b/package.xml
index bea1fe3ff63..06ce67a02c0 100644
--- a/package.xml
+++ b/package.xml
@@ -332,6 +332,8 @@
+
+
@@ -539,6 +541,8 @@
+
+
diff --git a/src/core/ext/client_channel/client_channel_plugin.c b/src/core/ext/client_channel/client_channel_plugin.c
index d50bba60f6a..7f75233727e 100644
--- a/src/core/ext/client_channel/client_channel_plugin.c
+++ b/src/core/ext/client_channel/client_channel_plugin.c
@@ -40,6 +40,7 @@
#include "src/core/ext/client_channel/client_channel.h"
#include "src/core/ext/client_channel/http_connect_handshaker.h"
#include "src/core/ext/client_channel/lb_policy_registry.h"
+#include "src/core/ext/client_channel/proxy_mapper_registry.h"
#include "src/core/ext/client_channel/resolver_registry.h"
#include "src/core/ext/client_channel/subchannel_index.h"
#include "src/core/lib/surface/channel_init.h"
@@ -80,6 +81,7 @@ static bool set_default_host_if_unset(grpc_exec_ctx *exec_ctx,
void grpc_client_channel_init(void) {
grpc_lb_policy_registry_init();
grpc_resolver_registry_init();
+ grpc_proxy_mapper_registry_init();
grpc_subchannel_index_init();
grpc_channel_init_register_stage(GRPC_CLIENT_CHANNEL, INT_MIN,
set_default_host_if_unset, NULL);
@@ -91,6 +93,7 @@ void grpc_client_channel_init(void) {
void grpc_client_channel_shutdown(void) {
grpc_subchannel_index_shutdown();
grpc_channel_init_shutdown();
+ grpc_proxy_mapper_registry_shutdown();
grpc_resolver_registry_shutdown();
grpc_lb_policy_registry_shutdown();
}
diff --git a/src/core/ext/client_channel/proxy_mapper.c b/src/core/ext/client_channel/proxy_mapper.c
new file mode 100644
index 00000000000..6b6f328d3ce
--- /dev/null
+++ b/src/core/ext/client_channel/proxy_mapper.c
@@ -0,0 +1,52 @@
+/*
+ *
+ * Copyright 2017, 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/ext/client_channel/proxy_mapper.h"
+
+void grpc_proxy_mapper_init(const grpc_proxy_mapper_vtable* vtable,
+ grpc_proxy_mapper* mapper) {
+ mapper->vtable = vtable;
+}
+
+bool grpc_proxy_mapper_map(grpc_exec_ctx* exec_ctx, grpc_proxy_mapper* mapper,
+ const grpc_resolved_address* address,
+ const grpc_channel_args* args,
+ grpc_resolved_address** new_address,
+ grpc_channel_args** new_args) {
+ return mapper->vtable->map(exec_ctx, mapper, address, args, new_address,
+ new_args);
+}
+
+void grpc_proxy_mapper_destroy(grpc_proxy_mapper* mapper) {
+ mapper->vtable->destroy(mapper);
+}
diff --git a/src/core/ext/client_channel/proxy_mapper.h b/src/core/ext/client_channel/proxy_mapper.h
new file mode 100644
index 00000000000..fa930379e70
--- /dev/null
+++ b/src/core/ext/client_channel/proxy_mapper.h
@@ -0,0 +1,73 @@
+/*
+ *
+ * Copyright 2017, 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_CORE_EXT_CLIENT_CHANNEL_PROXY_MAPPER_H
+#define GRPC_CORE_EXT_CLIENT_CHANNEL_PROXY_MAPPER_H
+
+#include
+
+#include
+
+#include "src/core/lib/iomgr/resolve_address.h"
+
+typedef struct grpc_proxy_mapper grpc_proxy_mapper;
+
+typedef struct {
+ /// Determines the proxy address to use to contact \a address.
+ /// If no proxy is needed, returns false.
+ /// Otherwise, sets \a new_address, optionally sets \a new_args, and
+ /// returns true.
+ bool (*map)(grpc_exec_ctx* exec_ctx, grpc_proxy_mapper* mapper,
+ const grpc_resolved_address* address,
+ const grpc_channel_args* args,
+ grpc_resolved_address** new_address,
+ grpc_channel_args** new_args);
+ /// Destroys \a mapper.
+ void (*destroy)(grpc_proxy_mapper* mapper);
+} grpc_proxy_mapper_vtable;
+
+struct grpc_proxy_mapper {
+ const grpc_proxy_mapper_vtable* vtable;
+};
+
+void grpc_proxy_mapper_init(const grpc_proxy_mapper_vtable* vtable,
+ grpc_proxy_mapper* mapper);
+
+bool grpc_proxy_mapper_map(grpc_exec_ctx* exec_ctx, grpc_proxy_mapper* mapper,
+ const grpc_resolved_address* address,
+ const grpc_channel_args* args,
+ grpc_resolved_address** new_address,
+ grpc_channel_args** new_args);
+void grpc_proxy_mapper_destroy(grpc_proxy_mapper* mapper);
+
+#endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_PROXY_MAPPER_H */
diff --git a/src/core/ext/client_channel/proxy_mapper_registry.c b/src/core/ext/client_channel/proxy_mapper_registry.c
new file mode 100644
index 00000000000..0a156c8b1c1
--- /dev/null
+++ b/src/core/ext/client_channel/proxy_mapper_registry.c
@@ -0,0 +1,111 @@
+/*
+ *
+ * Copyright 2017, 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/ext/client_channel/proxy_mapper_registry.h"
+
+#include
+
+#include
+
+//
+// grpc_proxy_mapper_list
+//
+
+typedef struct {
+ grpc_proxy_mapper** list;
+ size_t num_mappers;
+} grpc_proxy_mapper_list;
+
+static void grpc_proxy_mapper_list_register(grpc_proxy_mapper_list* list,
+ bool at_start,
+ grpc_proxy_mapper* mapper) {
+ list->list = gpr_realloc(
+ list->list, (list->num_mappers + 1) * sizeof(grpc_proxy_mapper*));
+ if (at_start) {
+ memmove(list->list + 1, list->list,
+ sizeof(grpc_proxy_mapper*) * list->num_mappers);
+ list->list[0] = mapper;
+ } else {
+ list->list[list->num_mappers] = mapper;
+ }
+ ++list->num_mappers;
+}
+
+static bool grpc_proxy_mapper_list_map(grpc_exec_ctx* exec_ctx,
+ grpc_proxy_mapper_list* list,
+ const grpc_resolved_address* address,
+ const grpc_channel_args* args,
+ grpc_resolved_address** new_address,
+ grpc_channel_args** new_args) {
+ for (size_t i = 0; i < list->num_mappers; ++i) {
+ if (grpc_proxy_mapper_map(exec_ctx, list->list[i], address, args,
+ new_address, new_args)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+static void grpc_proxy_mapper_list_destroy(grpc_proxy_mapper_list* list) {
+ for (size_t i = 0; i < list->num_mappers; ++i) {
+ grpc_proxy_mapper_destroy(list->list[i]);
+ }
+ gpr_free(list->list);
+}
+
+//
+// plugin
+//
+
+static grpc_proxy_mapper_list g_proxy_mapper_list;
+
+void grpc_proxy_mapper_registry_init() {
+ memset(&g_proxy_mapper_list, 0, sizeof(g_proxy_mapper_list));
+}
+
+void grpc_proxy_mapper_registry_shutdown() {
+ grpc_proxy_mapper_list_destroy(&g_proxy_mapper_list);
+}
+
+void grpc_proxy_mapper_register(bool at_start, grpc_proxy_mapper* mapper) {
+ grpc_proxy_mapper_list_register(&g_proxy_mapper_list, at_start, mapper);
+}
+
+bool grpc_proxy_mappers_map(grpc_exec_ctx* exec_ctx,
+ const grpc_resolved_address* address,
+ const grpc_channel_args* args,
+ grpc_resolved_address** new_address,
+ grpc_channel_args** new_args) {
+ return grpc_proxy_mapper_list_map(exec_ctx, &g_proxy_mapper_list, address,
+ args, new_address, new_args);
+}
diff --git a/src/core/ext/client_channel/proxy_mapper_registry.h b/src/core/ext/client_channel/proxy_mapper_registry.h
new file mode 100644
index 00000000000..b76af8d4564
--- /dev/null
+++ b/src/core/ext/client_channel/proxy_mapper_registry.h
@@ -0,0 +1,53 @@
+/*
+ *
+ * Copyright 2017, 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_CORE_EXT_CLIENT_CHANNEL_PROXY_MAPPER_REGISTRY_H
+#define GRPC_CORE_EXT_CLIENT_CHANNEL_PROXY_MAPPER_REGISTRY_H
+
+#include "src/core/ext/client_channel/proxy_mapper.h"
+
+void grpc_proxy_mapper_registry_init();
+void grpc_proxy_mapper_registry_shutdown();
+
+/// Registers a new proxy mapper. Takes ownership.
+/// If \a at_start is true, the new mapper will be at the beginning of
+/// the list. Otherwise, it will be added to the end.
+void grpc_proxy_mapper_register(bool at_start, grpc_proxy_mapper* mapper);
+
+bool grpc_proxy_mappers_map(grpc_exec_ctx* exec_ctx,
+ const grpc_resolved_address* address,
+ const grpc_channel_args* args,
+ grpc_resolved_address** new_address,
+ grpc_channel_args** new_args);
+
+#endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_PROXY_MAPPER_REGISTRY_H */
diff --git a/src/core/ext/client_channel/subchannel.c b/src/core/ext/client_channel/subchannel.c
index 8bd284507d2..05b08826b65 100644
--- a/src/core/ext/client_channel/subchannel.c
+++ b/src/core/ext/client_channel/subchannel.c
@@ -43,6 +43,7 @@
#include "src/core/ext/client_channel/client_channel.h"
#include "src/core/ext/client_channel/initial_connect_string.h"
#include "src/core/ext/client_channel/parse_address.h"
+#include "src/core/ext/client_channel/proxy_mapper_registry.h"
#include "src/core/ext/client_channel/subchannel_index.h"
#include "src/core/ext/client_channel/uri_parser.h"
#include "src/core/lib/channel/channel_args.h"
@@ -332,13 +333,24 @@ grpc_subchannel *grpc_subchannel_create(grpc_exec_ctx *exec_ctx,
grpc_resolved_address *addr = gpr_malloc(sizeof(*addr));
grpc_get_subchannel_address_arg(args->args, addr);
grpc_set_initial_connect_string(&addr, &c->initial_connect_string);
- static const char *keys_to_remove[] = {GRPC_ARG_SUBCHANNEL_ADDRESS};
- grpc_arg new_arg = grpc_create_subchannel_address_arg(addr);
+ grpc_resolved_address *new_address = NULL;
+ grpc_channel_args *new_args = NULL;
+ if (grpc_proxy_mappers_map(exec_ctx, addr, args->args, &new_address,
+ &new_args)) {
+ GPR_ASSERT(new_address != NULL);
+ gpr_free(addr);
+ addr = new_address;
+ if (new_args != NULL) c->args = new_args;
+ }
+ if (c->args == NULL) {
+ static const char *keys_to_remove[] = {GRPC_ARG_SUBCHANNEL_ADDRESS};
+ grpc_arg new_arg = grpc_create_subchannel_address_arg(addr);
+ c->args = grpc_channel_args_copy_and_add_and_remove(
+ args->args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), &new_arg,
+ 1);
+ gpr_free(new_arg.value.string);
+ }
gpr_free(addr);
- c->args = grpc_channel_args_copy_and_add_and_remove(
- args->args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), &new_arg, 1);
- gpr_free(new_arg.value.string);
-
c->root_external_state_watcher.next = c->root_external_state_watcher.prev =
&c->root_external_state_watcher;
grpc_closure_init(&c->connected, subchannel_connected, c,
diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py
index ed80c5c7478..9d470e17dfe 100644
--- a/src/python/grpcio/grpc_core_dependencies.py
+++ b/src/python/grpcio/grpc_core_dependencies.py
@@ -254,6 +254,8 @@ CORE_SOURCE_FILES = [
'src/core/ext/client_channel/lb_policy_factory.c',
'src/core/ext/client_channel/lb_policy_registry.c',
'src/core/ext/client_channel/parse_address.c',
+ 'src/core/ext/client_channel/proxy_mapper.c',
+ 'src/core/ext/client_channel/proxy_mapper_registry.c',
'src/core/ext/client_channel/resolver.c',
'src/core/ext/client_channel/resolver_factory.c',
'src/core/ext/client_channel/resolver_registry.c',
diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal
index 99dac044465..30d4e8f33a9 100644
--- a/tools/doxygen/Doxyfile.core.internal
+++ b/tools/doxygen/Doxyfile.core.internal
@@ -909,6 +909,10 @@ src/core/ext/client_channel/lb_policy_registry.c \
src/core/ext/client_channel/lb_policy_registry.h \
src/core/ext/client_channel/parse_address.c \
src/core/ext/client_channel/parse_address.h \
+src/core/ext/client_channel/proxy_mapper.c \
+src/core/ext/client_channel/proxy_mapper.h \
+src/core/ext/client_channel/proxy_mapper_registry.c \
+src/core/ext/client_channel/proxy_mapper_registry.h \
src/core/ext/client_channel/resolver.c \
src/core/ext/client_channel/resolver.h \
src/core/ext/client_channel/resolver_factory.c \
diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json
index 347c6106ec6..a7d22836373 100644
--- a/tools/run_tests/generated/sources_and_headers.json
+++ b/tools/run_tests/generated/sources_and_headers.json
@@ -7335,6 +7335,8 @@
"src/core/ext/client_channel/lb_policy_factory.h",
"src/core/ext/client_channel/lb_policy_registry.h",
"src/core/ext/client_channel/parse_address.h",
+ "src/core/ext/client_channel/proxy_mapper.h",
+ "src/core/ext/client_channel/proxy_mapper_registry.h",
"src/core/ext/client_channel/resolver.h",
"src/core/ext/client_channel/resolver_factory.h",
"src/core/ext/client_channel/resolver_registry.h",
@@ -7369,6 +7371,10 @@
"src/core/ext/client_channel/lb_policy_registry.h",
"src/core/ext/client_channel/parse_address.c",
"src/core/ext/client_channel/parse_address.h",
+ "src/core/ext/client_channel/proxy_mapper.c",
+ "src/core/ext/client_channel/proxy_mapper.h",
+ "src/core/ext/client_channel/proxy_mapper_registry.c",
+ "src/core/ext/client_channel/proxy_mapper_registry.h",
"src/core/ext/client_channel/resolver.c",
"src/core/ext/client_channel/resolver.h",
"src/core/ext/client_channel/resolver_factory.c",
diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj
index ade6fe1aacf..b531c6f765c 100644
--- a/vsprojects/vcxproj/grpc/grpc.vcxproj
+++ b/vsprojects/vcxproj/grpc/grpc.vcxproj
@@ -455,6 +455,8 @@
+
+
@@ -844,6 +846,10 @@
+
+
+
+
diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
index 6a999b6d734..79bbaec5580 100644
--- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
@@ -541,6 +541,12 @@
src\core\ext\client_channel
+
+ src\core\ext\client_channel
+
+
+ src\core\ext\client_channel
+
src\core\ext\client_channel
@@ -1217,6 +1223,12 @@
src\core\ext\client_channel
+
+ src\core\ext\client_channel
+
+
+ src\core\ext\client_channel
+
src\core\ext\client_channel
diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
index fa0651bab25..66dc4308fcf 100644
--- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
+++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
@@ -422,6 +422,8 @@
+
+
@@ -764,6 +766,10 @@
+
+
+
+
diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
index 3601ba2ea15..67592b24be1 100644
--- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
@@ -472,6 +472,12 @@
src\core\ext\client_channel
+
+ src\core\ext\client_channel
+
+
+ src\core\ext\client_channel
+
src\core\ext\client_channel
@@ -1061,6 +1067,12 @@
src\core\ext\client_channel
+
+ src\core\ext\client_channel
+
+
+ src\core\ext\client_channel
+
src\core\ext\client_channel