Merge pull request #14832 from HugoHo0212/master

Some changes to INSTALL.md to make it more concise and clear
diff --git a/.clang-format b/.clang-format
index 3b24519..f9af763 100644
--- a/.clang-format
+++ b/.clang-format
@@ -3,5 +3,10 @@
 BasedOnStyle:  Google
 DerivePointerAlignment: false
 PointerAlignment: Left
+---
+Language: ObjC
+BasedOnStyle: Google
+ColumnLimit: 100
+ObjCBlockIndentWidth: 2
 ...
 
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index fb6f98c..12f46d1 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -4,6 +4,6 @@
 /**/OWNERS @markdroth @nicolasnoble @a11r
 /bazel/** @nicolasnoble @dgquintas @a11r @vjpai
 /cmake/** @jtattermusch @nicolasnoble @matt-kwong
-/src/core/ext/filters/client_channel/** @markdroth @dgquintas @a11r
+/src/core/ext/filters/client_channel/** @markdroth @dgquintas @AspirinSJL
 /tools/dockerfile/** @jtattermusch @matt-kwong @nicolasnoble
 /tools/run_tests/performance/** @ncteisen @matt-kwong @jtattermusch
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
index 24587a5..5b2ac80 100644
--- a/.github/ISSUE_TEMPLATE.md
+++ b/.github/ISSUE_TEMPLATE.md
@@ -1,12 +1,12 @@
-Please answer these questions before submitting your issue. 
- 
-### Should this be an issue in the gRPC issue tracker?
- 
-Create new issues for bugs and feature requests. An issue needs to be actionable. General gRPC discussions and usage questions belong to:
-- [grpc.io mailing list](https://groups.google.com/forum/#!forum/grpc-io)
-- [StackOverflow, with `grpc` tag](http://stackoverflow.com/questions/tagged/grpc)
- 
-*Please don't double post your questions in more locations; we are monitoring both channels, and the time spent de-duplicating questions is better spent answering more user questions.*
+<!--
+
+This form is for bug reports and feature requests ONLY!
+For general questions and troubleshooting, please ask/look for answers here:
+- grpc.io mailing list: https://groups.google.com/forum/#!forum/grpc-io
+- StackOverflow, with "grpc" tag: http://stackoverflow.com/questions/tagged/grpc
+
+Issues specific to *grpc-java*, *grpc-go*, *grpc-node*, *grpc-dart*, *grpc-web* should be created in the repository they belong to (e.g. https://github.com/grpc/grpc-LANGUAGE/issues/new)
+-->
  
 ### What version of gRPC and what language are you using?
  
diff --git a/.gitignore b/.gitignore
index 0f3cd78..cde82bc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,8 +15,10 @@
 htmlcov/
 dist/
 *.egg
-py27/
-py3[0-9]*/
+py27_gevent/
+py27_native/
+py3[0-9]_gevent/
+py3[0-9]_native/
 
 # Node installation output
 node_modules
diff --git a/.pylintrc-tests b/.pylintrc-tests
new file mode 100644
index 0000000..b358b2c
--- /dev/null
+++ b/.pylintrc-tests
@@ -0,0 +1,108 @@
+[VARIABLES]
+
+# TODO(https://github.com/PyCQA/pylint/issues/1345): How does the inspection
+# not include "unused_" and "ignored_" by default?
+dummy-variables-rgx=^ignored_|^unused_
+
+[DESIGN]
+
+# NOTE(nathaniel): Not particularly attached to this value; it just seems to
+# be what works for us at the moment (excepting the dead-code-walking Beta
+# API).
+max-args=6
+
+[MISCELLANEOUS]
+
+# NOTE(nathaniel): We are big fans of "TODO(<issue link>): " and
+# "NOTE(<username or issue link>): ". We do not allow "TODO:",
+# "TODO(<username>):", "FIXME:", or anything else.
+notes=FIXME,XXX
+
+[MESSAGES CONTROL]
+
+disable=
+	# These suppressions are specific to tests:
+	#
+	# TODO(https://github.com/grpc/grpc/issues/261): investigate
+	# each of the following one by one and consider eliminating
+	# the suppression category.
+	# Eventually, the hope is to eliminate the .pylintrc-tests
+	# altogether and rely on .pylintrc for everything.
+	pointless-statement,
+	no-member,
+	no-self-use,
+	attribute-defined-outside-init,
+	unused-argument,
+	unused-variable,
+	unused-import,
+	redefined-builtin,
+	too-many-public-methods,
+	too-many-locals,
+	redefined-variable-type,
+	redefined-outer-name,
+	ungrouped-imports,
+	too-many-branches,
+	too-many-arguments,
+	too-many-format-args,
+	too-many-return-statements,
+	too-many-statements,
+	line-too-long,
+	wrong-import-position,
+	wrong-import-order,
+	# -- END OF TEST-SPECIFIC SUPPRESSIONS --
+
+
+	# TODO(https://github.com/PyCQA/pylint/issues/59#issuecomment-283774279):
+	# Enable cyclic-import after a 1.7-or-later pylint release that
+	# recognizes our disable=cyclic-import suppressions.
+	cyclic-import,
+	# TODO(https://github.com/grpc/grpc/issues/8622): Enable this after the
+	# Beta API is removed.
+	duplicate-code,
+	# TODO(https://github.com/grpc/grpc/issues/261): Doesn't seem to
+	# understand enum and concurrent.futures; look into this later with the
+	# latest pylint version.
+	import-error,
+	# TODO(https://github.com/grpc/grpc/issues/261): Enable this one.
+	# Should take a little configuration but not much.
+	invalid-name,
+	# TODO(https://github.com/grpc/grpc/issues/261): This doesn't seem to
+	# work for now? Try with a later pylint?
+	locally-disabled,
+	# NOTE(nathaniel): What even is this? *Enabling* an inspection results
+	# in a warning? How does that encourage more analysis and coverage?
+	locally-enabled,
+	# NOTE(nathaniel): We don't write doc strings for most private code
+	# elements.
+	missing-docstring,
+	# NOTE(nathaniel): In numeric comparisons it is better to have the
+	# lesser (or lesser-or-equal-to) quantity on the left when the
+	# expression is true than it is to worry about which is an identifier
+	# and which a literal value.
+	misplaced-comparison-constant,
+	# NOTE(nathaniel): Our completely abstract interface classes don't have
+	# constructors.
+	no-init,
+	# TODO(https://github.com/grpc/grpc/issues/261): Doesn't yet play
+	# nicely with some of our code being implemented in Cython. Maybe in a
+	# later version?
+	no-name-in-module,
+	# TODO(https://github.com/grpc/grpc/issues/261): Suppress these where
+	# the odd shape of the authentication portion of the API forces them on
+	# us and enable everywhere else.
+	protected-access,
+	# NOTE(nathaniel): Pylint and I will probably never agree on this.
+	too-few-public-methods,
+	# NOTE(nathaniel): Pylint and I wil probably never agree on this for
+	# private classes. For public classes maybe?
+	too-many-instance-attributes,
+	# NOTE(nathaniel): Some of our modules have a lot of lines... of
+	# specification and documentation. Maybe if this were
+	# lines-of-code-based we would use it.
+	too-many-lines,
+	# TODO(https://github.com/grpc/grpc/issues/261): Maybe we could have
+	# this one if we extracted just a few more helper functions...
+	too-many-nested-blocks,
+	# NOTE(nathaniel): I have disputed the premise of this inspection from
+	# the beginning and will continue to do so until it goes away for good.
+	useless-else-on-loop,
diff --git a/BUILD b/BUILD
index 54215fe..c35a7d6 100644
--- a/BUILD
+++ b/BUILD
@@ -64,11 +64,11 @@
 )
 
 # This should be updated along with build.yaml
-g_stands_for = "gorgeous"
+g_stands_for = "gloriosa"
 
 core_version = "6.0.0-dev"
 
-version = "1.11.0-dev"
+version = "1.13.0-dev"
 
 GPR_PUBLIC_HDRS = [
     "include/grpc/support/alloc.h",
@@ -141,7 +141,6 @@
     "src/cpp/server/server_posix.cc",
     "src/cpp/thread_manager/thread_manager.cc",
     "src/cpp/util/byte_buffer_cc.cc",
-    "src/cpp/util/slice_cc.cc",
     "src/cpp/util/status.cc",
     "src/cpp/util/string_ref.cc",
     "src/cpp/util/time_cc.cc",
@@ -245,6 +244,8 @@
     "include/grpcpp/support/byte_buffer.h",
     "include/grpcpp/support/channel_arguments.h",
     "include/grpcpp/support/config.h",
+    "include/grpcpp/support/proto_buffer_reader.h",
+    "include/grpcpp/support/proto_buffer_writer.h",
     "include/grpcpp/support/slice.h",
     "include/grpcpp/support/status.h",
     "include/grpcpp/support/status_code_enum.h",
@@ -307,16 +308,8 @@
     language = "c++",
     deps = [
         "grpc_base",
-        "grpc_deadline_filter",
-        "grpc_lb_policy_pick_first",
         "grpc_http_filters",
-        "grpc_max_age_filter",
-        "grpc_message_size_filter",
-        "grpc_resolver_dns_native",
-        "grpc_resolver_sockaddr",
-        "grpc_server_load_reporting",
         "grpc_transport_chttp2_client_secure",
-        "grpc_transport_chttp2_server_secure",
         "grpc_transport_cronet_client_secure",
     ],
 )
@@ -686,11 +679,11 @@
         "src/core/lib/channel/channel_stack_builder.cc",
         "src/core/lib/channel/channel_trace.cc",
         "src/core/lib/channel/channel_trace_registry.cc",
-        "src/core/lib/channel/status_util.cc",
         "src/core/lib/channel/connected_channel.cc",
         "src/core/lib/channel/handshaker.cc",
         "src/core/lib/channel/handshaker_factory.cc",
         "src/core/lib/channel/handshaker_registry.cc",
+        "src/core/lib/channel/status_util.cc",
         "src/core/lib/compression/compression.cc",
         "src/core/lib/compression/compression_internal.cc",
         "src/core/lib/compression/message_compress.cc",
@@ -833,12 +826,12 @@
         "src/core/lib/channel/channel_stack_builder.h",
         "src/core/lib/channel/channel_trace.h",
         "src/core/lib/channel/channel_trace_registry.h",
-        "src/core/lib/channel/status_util.h",
         "src/core/lib/channel/connected_channel.h",
         "src/core/lib/channel/context.h",
         "src/core/lib/channel/handshaker.h",
         "src/core/lib/channel/handshaker_factory.h",
         "src/core/lib/channel/handshaker_registry.h",
+        "src/core/lib/channel/status_util.h",
         "src/core/lib/compression/algorithm_metadata.h",
         "src/core/lib/compression/compression_internal.h",
         "src/core/lib/compression/message_compress.h",
@@ -992,6 +985,7 @@
         # standard plugins
         "census",
         "grpc_deadline_filter",
+        "grpc_client_authority_filter",
         "grpc_lb_policy_pick_first",
         "grpc_lb_policy_round_robin",
         "grpc_server_load_reporting",
@@ -1060,6 +1054,7 @@
     deps = [
         "gpr_base",
         "grpc_base",
+        "grpc_client_authority_filter",
         "grpc_deadline_filter",
         "inlined_vector",
         "orphanable",
@@ -1097,6 +1092,20 @@
 )
 
 grpc_cc_library(
+    name = "grpc_client_authority_filter",
+    srcs = [
+        "src/core/ext/filters/http/client_authority_filter.cc",
+    ],
+    hdrs = [
+        "src/core/ext/filters/http/client_authority_filter.h",
+    ],
+    language = "c++",
+    deps = [
+        "grpc_base",
+    ],
+)
+
+grpc_cc_library(
     name = "grpc_message_size_filter",
     srcs = [
         "src/core/ext/filters/message_size/message_size_filter.cc",
@@ -1174,6 +1183,7 @@
     ],
     hdrs = [
         "src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.h",
+        "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h",
         "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h",
         "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h",
         "src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h",
@@ -1202,6 +1212,7 @@
     ],
     hdrs = [
         "src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.h",
+        "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h",
         "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h",
         "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h",
         "src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h",
@@ -1221,9 +1232,6 @@
 
 grpc_cc_library(
     name = "grpc_lb_subchannel_list",
-    srcs = [
-        "src/core/ext/filters/client_channel/lb_policy/subchannel_list.cc",
-    ],
     hdrs = [
         "src/core/ext/filters/client_channel/lb_policy/subchannel_list.h",
     ],
@@ -1277,6 +1285,20 @@
 )
 
 grpc_cc_library(
+    name = "lb_load_data_store",
+    srcs = [
+        "src/cpp/server/load_reporter/load_data_store.cc",
+    ],
+    hdrs = [
+        "src/cpp/server/load_reporter/load_data_store.h",
+    ],
+    language = "c++",
+    deps = [
+        "grpc++",
+    ],
+)
+
+grpc_cc_library(
     name = "grpc_resolver_dns_native",
     srcs = [
         "src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc",
@@ -1340,6 +1362,7 @@
     srcs = [
         "src/core/lib/http/httpcli_security_connector.cc",
         "src/core/lib/security/context/security_context.cc",
+        "src/core/lib/security/credentials/alts/alts_credentials.cc",
         "src/core/lib/security/credentials/composite/composite_credentials.cc",
         "src/core/lib/security/credentials/credentials.cc",
         "src/core/lib/security/credentials/credentials_metadata.cc",
@@ -1353,7 +1376,6 @@
         "src/core/lib/security/credentials/oauth2/oauth2_credentials.cc",
         "src/core/lib/security/credentials/plugin/plugin_credentials.cc",
         "src/core/lib/security/credentials/ssl/ssl_credentials.cc",
-        "src/core/lib/security/credentials/alts/alts_credentials.cc",
         "src/core/lib/security/security_connector/alts_security_connector.cc",
         "src/core/lib/security/security_connector/security_connector.cc",
         "src/core/lib/security/transport/client_auth_filter.cc",
@@ -1366,7 +1388,9 @@
         "src/core/lib/surface/init_secure.cc",
     ],
     hdrs = [
+        "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h",
         "src/core/lib/security/context/security_context.h",
+        "src/core/lib/security/credentials/alts/alts_credentials.h",
         "src/core/lib/security/credentials/composite/composite_credentials.h",
         "src/core/lib/security/credentials/credentials.h",
         "src/core/lib/security/credentials/fake/fake_credentials.h",
@@ -1378,7 +1402,6 @@
         "src/core/lib/security/credentials/oauth2/oauth2_credentials.h",
         "src/core/lib/security/credentials/plugin/plugin_credentials.h",
         "src/core/lib/security/credentials/ssl/ssl_credentials.h",
-        "src/core/lib/security/credentials/alts/alts_credentials.h",
         "src/core/lib/security/security_connector/alts_security_connector.h",
         "src/core/lib/security/security_connector/security_connector.h",
         "src/core/lib/security/transport/auth_filters.h",
@@ -1472,9 +1495,11 @@
 grpc_cc_library(
     name = "grpc_transport_chttp2_client_connector",
     srcs = [
+        "src/core/ext/transport/chttp2/client/authority.cc",
         "src/core/ext/transport/chttp2/client/chttp2_connector.cc",
     ],
     hdrs = [
+        "src/core/ext/transport/chttp2/client/authority.h",
         "src/core/ext/transport/chttp2/client/chttp2_connector.h",
     ],
     language = "c++",
@@ -1600,11 +1625,9 @@
     name = "tsi_interface",
     srcs = [
         "src/core/tsi/transport_security.cc",
-        "src/core/tsi/transport_security_adapter.cc",
     ],
     hdrs = [
         "src/core/tsi/transport_security.h",
-        "src/core/tsi/transport_security_adapter.h",
         "src/core/tsi/transport_security_interface.h",
     ],
     language = "c++",
@@ -1641,8 +1664,8 @@
         "src/core/tsi/alts/frame_protector/frame_handler.h",
         "src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_integrity_only_record_protocol.h",
         "src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_privacy_integrity_record_protocol.h",
-        "src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.h",
         "src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol.h",
+        "src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.h",
         "src/core/tsi/alts/zero_copy_frame_protector/alts_iovec_record_protocol.h",
         "src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.h",
         "src/core/tsi/transport_security_grpc.h",
@@ -1697,25 +1720,26 @@
         "src/core/tsi/alts/handshaker/alts_handshaker_service_api_util.h",
         "src/core/tsi/alts/handshaker/transport_security_common_api.h",
     ],
+    public_hdrs = GRPC_SECURE_PUBLIC_HDRS, 
     external_deps = [
         "nanopb",
     ],
     language = "c++",
     deps = [
-      "alts_proto",
-      "gpr",
-      "grpc_base",
+        "alts_proto",
+        "gpr",
+        "grpc_base",
     ],
 )
 
 grpc_cc_library(
     name = "tsi",
     srcs = [
-        "src/core/tsi/alts_transport_security.cc",
         "src/core/tsi/alts/handshaker/alts_handshaker_client.cc",
         "src/core/tsi/alts/handshaker/alts_tsi_event.cc",
         "src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc",
         "src/core/tsi/alts/handshaker/alts_tsi_utils.cc",
+        "src/core/tsi/alts_transport_security.cc",
         "src/core/tsi/fake_transport_security.cc",
         "src/core/tsi/ssl/session_cache/ssl_session_boringssl.cc",
         "src/core/tsi/ssl/session_cache/ssl_session_cache.cc",
@@ -1724,12 +1748,12 @@
         "src/core/tsi/transport_security_grpc.cc",
     ],
     hdrs = [
-        "src/core/tsi/alts_transport_security.h",
         "src/core/tsi/alts/handshaker/alts_handshaker_client.h",
         "src/core/tsi/alts/handshaker/alts_tsi_event.h",
         "src/core/tsi/alts/handshaker/alts_tsi_handshaker.h",
         "src/core/tsi/alts/handshaker/alts_tsi_handshaker_private.h",
         "src/core/tsi/alts/handshaker/alts_tsi_utils.h",
+        "src/core/tsi/alts_transport_security.h",
         "src/core/tsi/fake_transport_security.h",
         "src/core/tsi/ssl/session_cache/ssl_session.h",
         "src/core/tsi/ssl/session_cache/ssl_session_cache.h",
@@ -1861,6 +1885,8 @@
     language = "c++",
     public_hdrs = [
         "include/grpc++/impl/codegen/proto_utils.h",
+        "include/grpcpp/impl/codegen/proto_buffer_reader.h",
+        "include/grpcpp/impl/codegen/proto_buffer_writer.h",
         "include/grpcpp/impl/codegen/proto_utils.h",
     ],
     deps = [
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 56dd61e..93f51e7 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -24,7 +24,7 @@
 cmake_minimum_required(VERSION 2.8)
 
 set(PACKAGE_NAME      "grpc")
-set(PACKAGE_VERSION   "1.11.0-dev")
+set(PACKAGE_VERSION   "1.13.0-dev")
 set(PACKAGE_STRING    "${PACKAGE_NAME} ${PACKAGE_VERSION}")
 set(PACKAGE_TARNAME   "${PACKAGE_NAME}-${PACKAGE_VERSION}")
 set(PACKAGE_BUGREPORT "https://github.com/grpc/grpc/issues/")
@@ -34,6 +34,7 @@
 set(gRPC_INSTALL_LIBDIR "lib" CACHE STRING "Installation directory for libraries")
 set(gRPC_INSTALL_INCLUDEDIR "include" CACHE STRING "Installation directory for headers")
 set(gRPC_INSTALL_CMAKEDIR "lib/cmake/${PACKAGE_NAME}" CACHE STRING "Installation directory for cmake config files")
+set(gRPC_INSTALL_SHAREDIR "share/grpc" CACHE STRING "Installation directory for root certificates")
 
 # Options
 option(gRPC_BUILD_TESTS "Build tests" OFF)
@@ -289,7 +290,6 @@
 add_dependencies(buildtests_c grpc_completion_queue_threading_test)
 add_dependencies(buildtests_c grpc_credentials_test)
 add_dependencies(buildtests_c grpc_fetch_oauth2)
-add_dependencies(buildtests_c grpc_invalid_channel_args_test)
 if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 add_dependencies(buildtests_c grpc_json_token_test)
 endif()
@@ -455,6 +455,7 @@
 add_dependencies(buildtests_c h2_uds_nosec_test)
 endif()
 add_dependencies(buildtests_c inproc_nosec_test)
+add_dependencies(buildtests_c alts_credentials_fuzzer_one_entry)
 add_dependencies(buildtests_c api_fuzzer_one_entry)
 add_dependencies(buildtests_c client_fuzzer_one_entry)
 add_dependencies(buildtests_c hpack_parser_fuzzer_test_one_entry)
@@ -585,6 +586,7 @@
 if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 add_dependencies(buildtests_cxx json_run_localhost)
 endif()
+add_dependencies(buildtests_cxx lb_load_data_store_test)
 add_dependencies(buildtests_cxx memory_test)
 add_dependencies(buildtests_cxx metrics_client)
 add_dependencies(buildtests_cxx mock_test)
@@ -605,12 +607,16 @@
 add_dependencies(buildtests_cxx reconnect_interop_server)
 add_dependencies(buildtests_cxx ref_counted_ptr_test)
 add_dependencies(buildtests_cxx ref_counted_test)
+add_dependencies(buildtests_cxx retry_throttle_test)
 add_dependencies(buildtests_cxx secure_auth_context_test)
 if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 add_dependencies(buildtests_cxx secure_sync_unary_ping_pong_test)
 endif()
 add_dependencies(buildtests_cxx server_builder_plugin_test)
 add_dependencies(buildtests_cxx server_builder_test)
+if(_gRPC_PLATFORM_POSIX)
+add_dependencies(buildtests_cxx server_builder_with_socket_mutator_test)
+endif()
 add_dependencies(buildtests_cxx server_context_test_spouse_test)
 if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 add_dependencies(buildtests_cxx server_crash_test)
@@ -1145,9 +1151,9 @@
   third_party/nanopb/pb_decode.c
   third_party/nanopb/pb_encode.c
   src/core/tsi/transport_security.cc
-  src/core/tsi/transport_security_adapter.cc
   src/core/ext/transport/chttp2/client/insecure/channel_create.cc
   src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc
+  src/core/ext/transport/chttp2/client/authority.cc
   src/core/ext/transport/chttp2/client/chttp2_connector.cc
   src/core/ext/filters/client_channel/backup_poller.cc
   src/core/ext/filters/client_channel/channel_connectivity.cc
@@ -1192,7 +1198,6 @@
   src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c
   src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc
   src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc
-  src/core/ext/filters/client_channel/lb_policy/subchannel_list.cc
   src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc
   src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc
   src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc
@@ -1205,6 +1210,7 @@
   src/core/ext/census/grpc_context.cc
   src/core/ext/filters/max_age/max_age_filter.cc
   src/core/ext/filters/message_size/message_size_filter.cc
+  src/core/ext/filters/http/client_authority_filter.cc
   src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc
   src/core/ext/filters/workarounds/workaround_utils.cc
   src/core/plugin_registry/grpc_plugin_registry.cc
@@ -1449,36 +1455,6 @@
   src/core/lib/transport/transport.cc
   src/core/lib/transport/transport_op_string.cc
   src/core/lib/debug/trace.cc
-  src/core/ext/filters/deadline/deadline_filter.cc
-  src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc
-  src/core/ext/filters/client_channel/backup_poller.cc
-  src/core/ext/filters/client_channel/channel_connectivity.cc
-  src/core/ext/filters/client_channel/client_channel.cc
-  src/core/ext/filters/client_channel/client_channel_factory.cc
-  src/core/ext/filters/client_channel/client_channel_plugin.cc
-  src/core/ext/filters/client_channel/connector.cc
-  src/core/ext/filters/client_channel/http_connect_handshaker.cc
-  src/core/ext/filters/client_channel/http_proxy.cc
-  src/core/ext/filters/client_channel/lb_policy.cc
-  src/core/ext/filters/client_channel/lb_policy_factory.cc
-  src/core/ext/filters/client_channel/lb_policy_registry.cc
-  src/core/ext/filters/client_channel/method_params.cc
-  src/core/ext/filters/client_channel/parse_address.cc
-  src/core/ext/filters/client_channel/proxy_mapper.cc
-  src/core/ext/filters/client_channel/proxy_mapper_registry.cc
-  src/core/ext/filters/client_channel/resolver.cc
-  src/core/ext/filters/client_channel/resolver_registry.cc
-  src/core/ext/filters/client_channel/retry_throttle.cc
-  src/core/ext/filters/client_channel/subchannel.cc
-  src/core/ext/filters/client_channel/subchannel_index.cc
-  src/core/ext/filters/client_channel/uri_parser.cc
-  src/core/ext/filters/client_channel/lb_policy/subchannel_list.cc
-  src/core/ext/filters/max_age/max_age_filter.cc
-  src/core/ext/filters/message_size/message_size_filter.cc
-  src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc
-  src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc
-  src/core/ext/filters/load_reporting/server_load_reporting_filter.cc
-  src/core/ext/filters/load_reporting/server_load_reporting_plugin.cc
   src/core/ext/transport/cronet/client/secure/cronet_channel_create.cc
   src/core/ext/transport/cronet/transport/cronet_api_dummy.cc
   src/core/ext/transport/cronet/transport/cronet_transport.cc
@@ -1510,6 +1486,28 @@
   src/core/ext/filters/http/http_filters_plugin.cc
   src/core/ext/filters/http/message_compress/message_compress_filter.cc
   src/core/ext/filters/http/server/http_server_filter.cc
+  src/core/ext/filters/client_channel/backup_poller.cc
+  src/core/ext/filters/client_channel/channel_connectivity.cc
+  src/core/ext/filters/client_channel/client_channel.cc
+  src/core/ext/filters/client_channel/client_channel_factory.cc
+  src/core/ext/filters/client_channel/client_channel_plugin.cc
+  src/core/ext/filters/client_channel/connector.cc
+  src/core/ext/filters/client_channel/http_connect_handshaker.cc
+  src/core/ext/filters/client_channel/http_proxy.cc
+  src/core/ext/filters/client_channel/lb_policy.cc
+  src/core/ext/filters/client_channel/lb_policy_factory.cc
+  src/core/ext/filters/client_channel/lb_policy_registry.cc
+  src/core/ext/filters/client_channel/method_params.cc
+  src/core/ext/filters/client_channel/parse_address.cc
+  src/core/ext/filters/client_channel/proxy_mapper.cc
+  src/core/ext/filters/client_channel/proxy_mapper_registry.cc
+  src/core/ext/filters/client_channel/resolver.cc
+  src/core/ext/filters/client_channel/resolver_registry.cc
+  src/core/ext/filters/client_channel/retry_throttle.cc
+  src/core/ext/filters/client_channel/subchannel.cc
+  src/core/ext/filters/client_channel/subchannel_index.cc
+  src/core/ext/filters/client_channel/uri_parser.cc
+  src/core/ext/filters/deadline/deadline_filter.cc
   src/core/lib/http/httpcli_security_connector.cc
   src/core/lib/security/context/security_context.cc
   src/core/lib/security/credentials/alts/alts_credentials.cc
@@ -1571,9 +1569,9 @@
   third_party/nanopb/pb_decode.c
   third_party/nanopb/pb_encode.c
   src/core/tsi/transport_security.cc
-  src/core/tsi/transport_security_adapter.cc
   src/core/ext/transport/chttp2/client/insecure/channel_create.cc
   src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc
+  src/core/ext/transport/chttp2/client/authority.cc
   src/core/ext/transport/chttp2/client/chttp2_connector.cc
   src/core/tsi/alts_transport_security.cc
   src/core/tsi/fake_transport_security.cc
@@ -1582,8 +1580,8 @@
   src/core/tsi/ssl/session_cache/ssl_session_openssl.cc
   src/core/tsi/ssl_transport_security.cc
   src/core/tsi/transport_security_grpc.cc
-  src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.cc
-  src/core/ext/transport/chttp2/server/chttp2_server.cc
+  src/core/ext/filters/load_reporting/server_load_reporting_filter.cc
+  src/core/ext/filters/load_reporting/server_load_reporting_plugin.cc
   src/core/plugin_registry/grpc_cronet_plugin_registry.cc
 )
 
@@ -1643,20 +1641,9 @@
   include/grpc/impl/codegen/sync_generic.h
   include/grpc/impl/codegen/sync_posix.h
   include/grpc/impl/codegen/sync_windows.h
-  include/grpc/byte_buffer.h
-  include/grpc/byte_buffer_reader.h
-  include/grpc/compression.h
-  include/grpc/fork.h
-  include/grpc/grpc.h
-  include/grpc/grpc_posix.h
-  include/grpc/grpc_security_constants.h
-  include/grpc/load_reporting.h
-  include/grpc/slice.h
-  include/grpc/slice_buffer.h
-  include/grpc/status.h
-  include/grpc/support/workaround_list.h
   include/grpc/grpc_cronet.h
   include/grpc/grpc_security.h
+  include/grpc/grpc_security_constants.h
 )
   string(REPLACE "include/" "" _path ${_hdr})
   get_filename_component(_path ${_path} PATH)
@@ -1688,6 +1675,7 @@
   test/core/end2end/fixtures/proxy.cc
   test/core/iomgr/endpoint_tests.cc
   test/core/util/debugger_macros.cc
+  test/core/util/fuzzer_util.cc
   test/core/util/grpc_profiler.cc
   test/core/util/histogram.cc
   test/core/util/memory_counters.cc
@@ -1991,6 +1979,7 @@
   test/core/end2end/fixtures/proxy.cc
   test/core/iomgr/endpoint_tests.cc
   test/core/util/debugger_macros.cc
+  test/core/util/fuzzer_util.cc
   test/core/util/grpc_profiler.cc
   test/core/util/histogram.cc
   test/core/util/memory_counters.cc
@@ -2470,6 +2459,7 @@
   src/core/ext/transport/chttp2/server/chttp2_server.cc
   src/core/ext/transport/chttp2/client/insecure/channel_create.cc
   src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc
+  src/core/ext/transport/chttp2/client/authority.cc
   src/core/ext/transport/chttp2/client/chttp2_connector.cc
   src/core/ext/filters/client_channel/backup_poller.cc
   src/core/ext/filters/client_channel/channel_connectivity.cc
@@ -2514,11 +2504,11 @@
   third_party/nanopb/pb_decode.c
   third_party/nanopb/pb_encode.c
   src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc
-  src/core/ext/filters/client_channel/lb_policy/subchannel_list.cc
   src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc
   src/core/ext/census/grpc_context.cc
   src/core/ext/filters/max_age/max_age_filter.cc
   src/core/ext/filters/message_size/message_size_filter.cc
+  src/core/ext/filters/http/client_authority_filter.cc
   src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc
   src/core/ext/filters/workarounds/workaround_utils.cc
   src/core/plugin_registry/grpc_unsecure_plugin_registry.cc
@@ -2730,7 +2720,6 @@
   src/cpp/server/server_posix.cc
   src/cpp/thread_manager/thread_manager.cc
   src/cpp/util/byte_buffer_cc.cc
-  src/cpp/util/slice_cc.cc
   src/cpp/util/status.cc
   src/cpp/util/string_ref.cc
   src/cpp/util/time_cc.cc
@@ -2855,6 +2844,8 @@
   include/grpcpp/support/byte_buffer.h
   include/grpcpp/support/channel_arguments.h
   include/grpcpp/support/config.h
+  include/grpcpp/support/proto_buffer_reader.h
+  include/grpcpp/support/proto_buffer_writer.h
   include/grpcpp/support/slice.h
   include/grpcpp/support/status.h
   include/grpcpp/support/status_code_enum.h
@@ -2973,6 +2964,8 @@
   include/grpcpp/impl/codegen/sync_stream.h
   include/grpcpp/impl/codegen/time.h
   include/grpc++/impl/codegen/proto_utils.h
+  include/grpcpp/impl/codegen/proto_buffer_reader.h
+  include/grpcpp/impl/codegen/proto_buffer_writer.h
   include/grpcpp/impl/codegen/proto_utils.h
   include/grpc++/impl/codegen/config_protobuf.h
   include/grpcpp/impl/codegen/config_protobuf.h
@@ -3081,13 +3074,13 @@
   src/cpp/server/server_posix.cc
   src/cpp/thread_manager/thread_manager.cc
   src/cpp/util/byte_buffer_cc.cc
-  src/cpp/util/slice_cc.cc
   src/cpp/util/status.cc
   src/cpp/util/string_ref.cc
   src/cpp/util/time_cc.cc
   src/cpp/codegen/codegen_init.cc
   src/core/ext/transport/chttp2/client/insecure/channel_create.cc
   src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc
+  src/core/ext/transport/chttp2/client/authority.cc
   src/core/ext/transport/chttp2/client/chttp2_connector.cc
   src/core/ext/transport/chttp2/transport/bin_decoder.cc
   src/core/ext/transport/chttp2/transport/bin_encoder.cc
@@ -3415,6 +3408,8 @@
   include/grpcpp/support/byte_buffer.h
   include/grpcpp/support/channel_arguments.h
   include/grpcpp/support/config.h
+  include/grpcpp/support/proto_buffer_reader.h
+  include/grpcpp/support/proto_buffer_writer.h
   include/grpcpp/support/slice.h
   include/grpcpp/support/status.h
   include/grpcpp/support/status_code_enum.h
@@ -3958,6 +3953,8 @@
   include/grpc/impl/codegen/sync_posix.h
   include/grpc/impl/codegen/sync_windows.h
   include/grpc++/impl/codegen/proto_utils.h
+  include/grpcpp/impl/codegen/proto_buffer_reader.h
+  include/grpcpp/impl/codegen/proto_buffer_writer.h
   include/grpcpp/impl/codegen/proto_utils.h
   include/grpc++/impl/codegen/config_protobuf.h
   include/grpcpp/impl/codegen/config_protobuf.h
@@ -4131,6 +4128,8 @@
   include/grpc/impl/codegen/sync_posix.h
   include/grpc/impl/codegen/sync_windows.h
   include/grpc++/impl/codegen/proto_utils.h
+  include/grpcpp/impl/codegen/proto_buffer_reader.h
+  include/grpcpp/impl/codegen/proto_buffer_writer.h
   include/grpcpp/impl/codegen/proto_utils.h
   include/grpc++/impl/codegen/config_protobuf.h
   include/grpcpp/impl/codegen/config_protobuf.h
@@ -4179,7 +4178,6 @@
   src/cpp/server/server_posix.cc
   src/cpp/thread_manager/thread_manager.cc
   src/cpp/util/byte_buffer_cc.cc
-  src/cpp/util/slice_cc.cc
   src/cpp/util/status.cc
   src/cpp/util/string_ref.cc
   src/cpp/util/time_cc.cc
@@ -4303,6 +4301,8 @@
   include/grpcpp/support/byte_buffer.h
   include/grpcpp/support/channel_arguments.h
   include/grpcpp/support/config.h
+  include/grpcpp/support/proto_buffer_reader.h
+  include/grpcpp/support/proto_buffer_writer.h
   include/grpcpp/support/slice.h
   include/grpcpp/support/status.h
   include/grpcpp/support/status_code_enum.h
@@ -4979,6 +4979,49 @@
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
+add_library(lb_load_data_store
+  src/cpp/server/load_reporter/load_data_store.cc
+)
+
+if(WIN32 AND MSVC)
+  set_target_properties(lb_load_data_store PROPERTIES COMPILE_PDB_NAME "lb_load_data_store"
+    COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
+  )
+  if (gRPC_INSTALL)
+    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/lb_load_data_store.pdb
+      DESTINATION ${gRPC_INSTALL_LIBDIR} OPTIONAL
+    )
+  endif()
+endif()
+
+
+target_include_directories(lb_load_data_store
+  PUBLIC $<INSTALL_INTERFACE:${gRPC_INSTALL_INCLUDEDIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
+  PRIVATE ${_gRPC_SSL_INCLUDE_DIR}
+  PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR}
+  PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR}
+  PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR}
+  PRIVATE ${_gRPC_CARES_INCLUDE_DIR}
+  PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR}
+  PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
+  PRIVATE third_party/googletest/googletest/include
+  PRIVATE third_party/googletest/googletest
+  PRIVATE third_party/googletest/googlemock/include
+  PRIVATE third_party/googletest/googlemock
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
+)
+
+target_link_libraries(lb_load_data_store
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  grpc++
+)
+
+
+endif (gRPC_BUILD_TESTS)
+if (gRPC_BUILD_TESTS)
+
 if (gRPC_BUILD_CODEGEN)
 add_library(qps
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/messages.pb.cc
@@ -4997,10 +5040,18 @@
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/control.grpc.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/control.pb.h
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/control.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/services.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/services.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/services.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/services.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/benchmark_service.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/benchmark_service.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/benchmark_service.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/benchmark_service.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/report_qps_scenario_service.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/report_qps_scenario_service.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/report_qps_scenario_service.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/report_qps_scenario_service.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/worker_service.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/worker_service.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/worker_service.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/worker_service.grpc.pb.h
   test/cpp/qps/benchmark_config.cc
   test/cpp/qps/client_async.cc
   test/cpp/qps/client_sync.cc
@@ -5037,7 +5088,13 @@
   src/proto/grpc/testing/control.proto
 )
 protobuf_generate_grpc_cpp(
-  src/proto/grpc/testing/services.proto
+  src/proto/grpc/testing/benchmark_service.proto
+)
+protobuf_generate_grpc_cpp(
+  src/proto/grpc/testing/report_qps_scenario_service.proto
+)
+protobuf_generate_grpc_cpp(
+  src/proto/grpc/testing/worker_service.proto
 )
 
 target_include_directories(qps
@@ -5205,6 +5262,7 @@
   test/core/end2end/tests/bad_ping.cc
   test/core/end2end/tests/binary_metadata.cc
   test/core/end2end/tests/call_creds.cc
+  test/core/end2end/tests/call_host_override.cc
   test/core/end2end/tests/cancel_after_accept.cc
   test/core/end2end/tests/cancel_after_client_done.cc
   test/core/end2end/tests/cancel_after_invoke.cc
@@ -5251,6 +5309,7 @@
   test/core/end2end/tests/retry_exceeds_buffer_size_in_initial_batch.cc
   test/core/end2end/tests/retry_exceeds_buffer_size_in_subsequent_batch.cc
   test/core/end2end/tests/retry_non_retriable_status.cc
+  test/core/end2end/tests/retry_non_retriable_status_before_recv_trailing_metadata_started.cc
   test/core/end2end/tests/retry_recv_initial_metadata.cc
   test/core/end2end/tests/retry_recv_message.cc
   test/core/end2end/tests/retry_server_pushback_delay.cc
@@ -5321,6 +5380,7 @@
   test/core/end2end/tests/bad_hostname.cc
   test/core/end2end/tests/bad_ping.cc
   test/core/end2end/tests/binary_metadata.cc
+  test/core/end2end/tests/call_host_override.cc
   test/core/end2end/tests/cancel_after_accept.cc
   test/core/end2end/tests/cancel_after_client_done.cc
   test/core/end2end/tests/cancel_after_invoke.cc
@@ -5367,6 +5427,7 @@
   test/core/end2end/tests/retry_exceeds_buffer_size_in_initial_batch.cc
   test/core/end2end/tests/retry_exceeds_buffer_size_in_subsequent_batch.cc
   test/core/end2end/tests/retry_non_retriable_status.cc
+  test/core/end2end/tests/retry_non_retriable_status_before_recv_trailing_metadata_started.cc
   test/core/end2end/tests/retry_recv_initial_metadata.cc
   test/core/end2end/tests/retry_recv_message.cc
   test/core/end2end/tests/retry_server_pushback_delay.cc
@@ -5696,15 +5757,6 @@
   gpr
 )
 
-
-if (gRPC_INSTALL)
-  install(TARGETS check_epollexclusive EXPORT gRPCTargets
-    RUNTIME DESTINATION ${gRPC_INSTALL_BINDIR}
-    LIBRARY DESTINATION ${gRPC_INSTALL_LIBDIR}
-    ARCHIVE DESTINATION ${gRPC_INSTALL_LIBDIR}
-  )
-endif()
-
 if (gRPC_BUILD_TESTS)
 
 add_executable(chttp2_hpack_encoder_test
@@ -6980,15 +7032,6 @@
   gpr
 )
 
-
-if (gRPC_INSTALL)
-  install(TARGETS grpc_create_jwt EXPORT gRPCTargets
-    RUNTIME DESTINATION ${gRPC_INSTALL_BINDIR}
-    LIBRARY DESTINATION ${gRPC_INSTALL_LIBDIR}
-    ARCHIVE DESTINATION ${gRPC_INSTALL_LIBDIR}
-  )
-endif()
-
 if (gRPC_BUILD_TESTS)
 
 add_executable(grpc_credentials_test
@@ -7046,34 +7089,6 @@
 
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
-
-add_executable(grpc_invalid_channel_args_test
-  test/core/surface/invalid_channel_args_test.cc
-)
-
-
-target_include_directories(grpc_invalid_channel_args_test
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
-  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
-  PRIVATE ${_gRPC_SSL_INCLUDE_DIR}
-  PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR}
-  PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR}
-  PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR}
-  PRIVATE ${_gRPC_CARES_INCLUDE_DIR}
-  PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR}
-  PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
-)
-
-target_link_libraries(grpc_invalid_channel_args_test
-  ${_gRPC_ALLTARGETS_LIBRARIES}
-  grpc_test_util
-  grpc
-  gpr_test_util
-  gpr
-)
-
-endif (gRPC_BUILD_TESTS)
-if (gRPC_BUILD_TESTS)
 if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 
 add_executable(grpc_json_token_test
@@ -7156,15 +7171,6 @@
   gpr
 )
 
-
-if (gRPC_INSTALL)
-  install(TARGETS grpc_print_google_default_creds_token EXPORT gRPCTargets
-    RUNTIME DESTINATION ${gRPC_INSTALL_BINDIR}
-    LIBRARY DESTINATION ${gRPC_INSTALL_LIBDIR}
-    ARCHIVE DESTINATION ${gRPC_INSTALL_LIBDIR}
-  )
-endif()
-
 if (gRPC_BUILD_TESTS)
 
 add_executable(grpc_security_connector_test
@@ -7246,15 +7252,6 @@
   gpr
 )
 
-
-if (gRPC_INSTALL)
-  install(TARGETS grpc_verify_jwt EXPORT gRPCTargets
-    RUNTIME DESTINATION ${gRPC_INSTALL_BINDIR}
-    LIBRARY DESTINATION ${gRPC_INSTALL_LIBDIR}
-    ARCHIVE DESTINATION ${gRPC_INSTALL_LIBDIR}
-  )
-endif()
-
 if (gRPC_BUILD_TESTS)
 if(_gRPC_PLATFORM_LINUX)
 
@@ -9752,6 +9749,7 @@
   grpc_unsecure
   gpr_test_util
   gpr
+  grpc++_test_config
   ${_gRPC_GFLAGS_LIBRARIES}
 )
 
@@ -9795,6 +9793,7 @@
   grpc_unsecure
   gpr_test_util
   gpr
+  grpc++_test_config
   ${_gRPC_GFLAGS_LIBRARIES}
 )
 
@@ -9838,6 +9837,7 @@
   grpc_unsecure
   gpr_test_util
   gpr
+  grpc++_test_config
   ${_gRPC_GFLAGS_LIBRARIES}
 )
 
@@ -9881,6 +9881,7 @@
   grpc_unsecure
   gpr_test_util
   gpr
+  grpc++_test_config
   ${_gRPC_GFLAGS_LIBRARIES}
 )
 
@@ -9924,6 +9925,7 @@
   grpc_unsecure
   gpr_test_util
   gpr
+  grpc++_test_config
   ${_gRPC_GFLAGS_LIBRARIES}
 )
 
@@ -9967,6 +9969,7 @@
   grpc_unsecure
   gpr_test_util
   gpr
+  grpc++_test_config
   ${_gRPC_GFLAGS_LIBRARIES}
 )
 
@@ -10010,6 +10013,7 @@
   grpc_unsecure
   gpr_test_util
   gpr
+  grpc++_test_config
   ${_gRPC_GFLAGS_LIBRARIES}
 )
 
@@ -10053,6 +10057,7 @@
   grpc_unsecure
   gpr_test_util
   gpr
+  grpc++_test_config
   ${_gRPC_GFLAGS_LIBRARIES}
 )
 
@@ -10096,6 +10101,7 @@
   grpc_unsecure
   gpr_test_util
   gpr
+  grpc++_test_config
   ${_gRPC_GFLAGS_LIBRARIES}
 )
 
@@ -10139,6 +10145,7 @@
   grpc_unsecure
   gpr_test_util
   gpr
+  grpc++_test_config
   ${_gRPC_GFLAGS_LIBRARIES}
 )
 
@@ -10226,6 +10233,7 @@
   grpc_unsecure
   gpr_test_util
   gpr
+  grpc++_test_config
   ${_gRPC_GFLAGS_LIBRARIES}
 )
 
@@ -10269,6 +10277,7 @@
   grpc_unsecure
   gpr_test_util
   gpr
+  grpc++_test_config
   ${_gRPC_GFLAGS_LIBRARIES}
 )
 
@@ -10312,6 +10321,7 @@
   grpc_unsecure
   gpr_test_util
   gpr
+  grpc++_test_config
   ${_gRPC_GFLAGS_LIBRARIES}
 )
 
@@ -10799,10 +10809,18 @@
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/payloads.grpc.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/payloads.pb.h
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/payloads.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/services.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/services.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/services.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/services.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/benchmark_service.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/benchmark_service.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/benchmark_service.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/benchmark_service.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/report_qps_scenario_service.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/report_qps_scenario_service.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/report_qps_scenario_service.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/report_qps_scenario_service.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/worker_service.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/worker_service.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/worker_service.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/worker_service.grpc.pb.h
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/stats.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/stats.grpc.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/stats.pb.h
@@ -10822,7 +10840,13 @@
   src/proto/grpc/testing/payloads.proto
 )
 protobuf_generate_grpc_cpp(
-  src/proto/grpc/testing/services.proto
+  src/proto/grpc/testing/benchmark_service.proto
+)
+protobuf_generate_grpc_cpp(
+  src/proto/grpc/testing/report_qps_scenario_service.proto
+)
+protobuf_generate_grpc_cpp(
+  src/proto/grpc/testing/worker_service.proto
 )
 protobuf_generate_grpc_cpp(
   src/proto/grpc/testing/stats.proto
@@ -10871,10 +10895,18 @@
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/payloads.grpc.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/payloads.pb.h
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/payloads.grpc.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/services.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/services.grpc.pb.cc
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/services.pb.h
-  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/services.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/benchmark_service.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/benchmark_service.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/benchmark_service.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/benchmark_service.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/report_qps_scenario_service.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/report_qps_scenario_service.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/report_qps_scenario_service.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/report_qps_scenario_service.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/worker_service.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/worker_service.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/worker_service.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/worker_service.grpc.pb.h
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/stats.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/stats.grpc.pb.cc
   ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/stats.pb.h
@@ -10895,7 +10927,13 @@
   src/proto/grpc/testing/payloads.proto
 )
 protobuf_generate_grpc_cpp(
-  src/proto/grpc/testing/services.proto
+  src/proto/grpc/testing/benchmark_service.proto
+)
+protobuf_generate_grpc_cpp(
+  src/proto/grpc/testing/report_qps_scenario_service.proto
+)
+protobuf_generate_grpc_cpp(
+  src/proto/grpc/testing/worker_service.proto
 )
 protobuf_generate_grpc_cpp(
   src/proto/grpc/testing/stats.proto
@@ -12280,6 +12318,46 @@
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
+add_executable(lb_load_data_store_test
+  test/cpp/server/load_reporter/load_data_store_test.cc
+  third_party/googletest/googletest/src/gtest-all.cc
+  third_party/googletest/googlemock/src/gmock-all.cc
+)
+
+
+target_include_directories(lb_load_data_store_test
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
+  PRIVATE ${_gRPC_SSL_INCLUDE_DIR}
+  PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR}
+  PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR}
+  PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR}
+  PRIVATE ${_gRPC_CARES_INCLUDE_DIR}
+  PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR}
+  PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
+  PRIVATE third_party/googletest/googletest/include
+  PRIVATE third_party/googletest/googletest
+  PRIVATE third_party/googletest/googlemock/include
+  PRIVATE third_party/googletest/googlemock
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
+)
+
+target_link_libraries(lb_load_data_store_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  lb_load_data_store
+  grpc++_test_util
+  grpc_test_util
+  grpc++
+  grpc
+  gpr_test_util
+  gpr
+  ${_gRPC_GFLAGS_LIBRARIES}
+)
+
+endif (gRPC_BUILD_TESTS)
+if (gRPC_BUILD_TESTS)
+
 add_executable(memory_test
   test/core/gprpp/memory_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
@@ -12959,6 +13037,43 @@
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
+add_executable(retry_throttle_test
+  test/core/client_channel/retry_throttle_test.cc
+  third_party/googletest/googletest/src/gtest-all.cc
+  third_party/googletest/googlemock/src/gmock-all.cc
+)
+
+
+target_include_directories(retry_throttle_test
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
+  PRIVATE ${_gRPC_SSL_INCLUDE_DIR}
+  PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR}
+  PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR}
+  PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR}
+  PRIVATE ${_gRPC_CARES_INCLUDE_DIR}
+  PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR}
+  PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
+  PRIVATE third_party/googletest/googletest/include
+  PRIVATE third_party/googletest/googletest
+  PRIVATE third_party/googletest/googlemock/include
+  PRIVATE third_party/googletest/googlemock
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
+)
+
+target_link_libraries(retry_throttle_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  grpc_test_util
+  grpc
+  gpr_test_util
+  gpr
+  ${_gRPC_GFLAGS_LIBRARIES}
+)
+
+endif (gRPC_BUILD_TESTS)
+if (gRPC_BUILD_TESTS)
+
 add_executable(secure_auth_context_test
   test/cpp/common/secure_auth_context_test.cc
   third_party/googletest/googletest/src/gtest-all.cc
@@ -13133,6 +13248,61 @@
 
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_POSIX)
+
+add_executable(server_builder_with_socket_mutator_test
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo_messages.grpc.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.cc
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.pb.h
+  ${_gRPC_PROTO_GENS_DIR}/src/proto/grpc/testing/echo.grpc.pb.h
+  test/cpp/server/server_builder_with_socket_mutator_test.cc
+  third_party/googletest/googletest/src/gtest-all.cc
+  third_party/googletest/googlemock/src/gmock-all.cc
+)
+
+protobuf_generate_grpc_cpp(
+  src/proto/grpc/testing/echo_messages.proto
+)
+protobuf_generate_grpc_cpp(
+  src/proto/grpc/testing/echo.proto
+)
+
+target_include_directories(server_builder_with_socket_mutator_test
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
+  PRIVATE ${_gRPC_SSL_INCLUDE_DIR}
+  PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR}
+  PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR}
+  PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR}
+  PRIVATE ${_gRPC_CARES_INCLUDE_DIR}
+  PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR}
+  PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
+  PRIVATE third_party/googletest/googletest/include
+  PRIVATE third_party/googletest/googletest
+  PRIVATE third_party/googletest/googlemock/include
+  PRIVATE third_party/googletest/googlemock
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
+)
+
+target_link_libraries(server_builder_with_socket_mutator_test
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  grpc++_test_util_unsecure
+  grpc_test_util_unsecure
+  gpr_test_util
+  grpc++_unsecure
+  grpc_unsecure
+  gpr
+  ${_gRPC_GFLAGS_LIBRARIES}
+)
+
+endif()
+endif (gRPC_BUILD_TESTS)
+if (gRPC_BUILD_TESTS)
 
 add_executable(server_context_test_spouse_test
   test/cpp/test/server_context_test_spouse_test.cc
@@ -13916,15 +14086,6 @@
 )
 
 
-if (gRPC_INSTALL)
-  install(TARGETS gen_hpack_tables EXPORT gRPCTargets
-    RUNTIME DESTINATION ${gRPC_INSTALL_BINDIR}
-    LIBRARY DESTINATION ${gRPC_INSTALL_LIBDIR}
-    ARCHIVE DESTINATION ${gRPC_INSTALL_LIBDIR}
-  )
-endif()
-
-
 add_executable(gen_legal_metadata_characters
   tools/codegen/core/gen_legal_metadata_characters.cc
 )
@@ -13947,15 +14108,6 @@
 )
 
 
-if (gRPC_INSTALL)
-  install(TARGETS gen_legal_metadata_characters EXPORT gRPCTargets
-    RUNTIME DESTINATION ${gRPC_INSTALL_BINDIR}
-    LIBRARY DESTINATION ${gRPC_INSTALL_LIBDIR}
-    ARCHIVE DESTINATION ${gRPC_INSTALL_LIBDIR}
-  )
-endif()
-
-
 add_executable(gen_percent_encoding_tables
   tools/codegen/core/gen_percent_encoding_tables.cc
 )
@@ -13977,15 +14129,6 @@
   ${_gRPC_ALLTARGETS_LIBRARIES}
 )
 
-
-if (gRPC_INSTALL)
-  install(TARGETS gen_percent_encoding_tables EXPORT gRPCTargets
-    RUNTIME DESTINATION ${gRPC_INSTALL_BINDIR}
-    LIBRARY DESTINATION ${gRPC_INSTALL_LIBDIR}
-    ARCHIVE DESTINATION ${gRPC_INSTALL_LIBDIR}
-  )
-endif()
-
 if (gRPC_BUILD_TESTS)
 
 add_executable(badreq_bad_client_test
@@ -15629,6 +15772,35 @@
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
 
+add_executable(alts_credentials_fuzzer_one_entry
+  test/core/security/alts_credentials_fuzzer.cc
+  test/core/util/one_corpus_entry_fuzzer.cc
+)
+
+
+target_include_directories(alts_credentials_fuzzer_one_entry
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
+  PRIVATE ${_gRPC_SSL_INCLUDE_DIR}
+  PRIVATE ${_gRPC_PROTOBUF_INCLUDE_DIR}
+  PRIVATE ${_gRPC_ZLIB_INCLUDE_DIR}
+  PRIVATE ${_gRPC_BENCHMARK_INCLUDE_DIR}
+  PRIVATE ${_gRPC_CARES_INCLUDE_DIR}
+  PRIVATE ${_gRPC_GFLAGS_INCLUDE_DIR}
+  PRIVATE ${_gRPC_ADDRESS_SORTING_INCLUDE_DIR}
+)
+
+target_link_libraries(alts_credentials_fuzzer_one_entry
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  grpc_test_util
+  grpc
+  gpr_test_util
+  gpr
+)
+
+endif (gRPC_BUILD_TESTS)
+if (gRPC_BUILD_TESTS)
+
 add_executable(api_fuzzer_one_entry
   test/core/end2end/fuzzers/api_fuzzer.cc
   test/core/util/one_corpus_entry_fuzzer.cc
@@ -16025,3 +16197,6 @@
     DESTINATION ${gRPC_INSTALL_CMAKEDIR}
   )
 endforeach()
+
+install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/etc/roots.pem
+  DESTINATION ${gRPC_INSTALL_SHAREDIR})
diff --git a/INSTALL.md b/INSTALL.md
index 40faf97..59e127f 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -142,7 +142,7 @@
 > call "%VS140COMNTOOLS%..\..\VC\vcvarsall.bat" x64
 > cmake .. -GNinja -DCMAKE_BUILD_TYPE=Release
 > cmake --build .
-> ninja
+> ninja install
 ```
 
 ### msys2 (with mingw)
diff --git a/Makefile b/Makefile
index a6275aa..ba765f0 100644
--- a/Makefile
+++ b/Makefile
@@ -421,8 +421,8 @@
 endif
 
 CORE_VERSION = 6.0.0-dev
-CPP_VERSION = 1.11.0-dev
-CSHARP_VERSION = 1.11.0-dev
+CPP_VERSION = 1.13.0-dev
+CSHARP_VERSION = 1.13.0-dev
 
 CPPFLAGS_NO_ARCH += $(addprefix -I, $(INCLUDES)) $(addprefix -D, $(DEFINES))
 CPPFLAGS += $(CPPFLAGS_NO_ARCH) $(ARCH_FLAGS)
@@ -503,7 +503,7 @@
 OPENSSL_ALPN_CHECK_CMD = $(PKG_CONFIG) --atleast-version=1.0.2 openssl
 OPENSSL_NPN_CHECK_CMD = $(PKG_CONFIG) --atleast-version=1.0.1 openssl
 ZLIB_CHECK_CMD = $(PKG_CONFIG) --exists zlib
-PROTOBUF_CHECK_CMD = $(PKG_CONFIG) --atleast-version=3.0.0 protobuf
+PROTOBUF_CHECK_CMD = $(PKG_CONFIG) --atleast-version=3.5.0 protobuf
 CARES_CHECK_CMD = $(PKG_CONFIG) --atleast-version=1.11.0 libcares
 else # HAS_PKG_CONFIG
 
@@ -919,7 +919,7 @@
 	@echo
 	@echo "DEPENDENCY ERROR"
 	@echo
-	@echo "The target you are trying to run requires protobuf 3.0.0+"
+	@echo "The target you are trying to run requires protobuf 3.5.0+"
 	@echo "Your system doesn't have it, and neither does the third_party directory."
 	@echo
 	@echo "Please consult INSTALL to get more information."
@@ -933,7 +933,7 @@
 	@echo
 	@echo "DEPENDENCY ERROR"
 	@echo
-	@echo "The target you are trying to run requires protobuf-compiler 3.0.0+"
+	@echo "The target you are trying to run requires protobuf-compiler 3.5.0+"
 	@echo "Your system doesn't have it, and neither does the third_party directory."
 	@echo
 	@echo "Please consult INSTALL to get more information."
@@ -960,6 +960,7 @@
 algorithm_test: $(BINDIR)/$(CONFIG)/algorithm_test
 alloc_test: $(BINDIR)/$(CONFIG)/alloc_test
 alpn_test: $(BINDIR)/$(CONFIG)/alpn_test
+alts_credentials_fuzzer: $(BINDIR)/$(CONFIG)/alts_credentials_fuzzer
 api_fuzzer: $(BINDIR)/$(CONFIG)/api_fuzzer
 arena_test: $(BINDIR)/$(CONFIG)/arena_test
 avl_test: $(BINDIR)/$(CONFIG)/avl_test
@@ -1017,7 +1018,6 @@
 grpc_create_jwt: $(BINDIR)/$(CONFIG)/grpc_create_jwt
 grpc_credentials_test: $(BINDIR)/$(CONFIG)/grpc_credentials_test
 grpc_fetch_oauth2: $(BINDIR)/$(CONFIG)/grpc_fetch_oauth2
-grpc_invalid_channel_args_test: $(BINDIR)/$(CONFIG)/grpc_invalid_channel_args_test
 grpc_json_token_test: $(BINDIR)/$(CONFIG)/grpc_json_token_test
 grpc_jwt_verifier_test: $(BINDIR)/$(CONFIG)/grpc_jwt_verifier_test
 grpc_print_google_default_creds_token: $(BINDIR)/$(CONFIG)/grpc_print_google_default_creds_token
@@ -1179,6 +1179,7 @@
 interop_server: $(BINDIR)/$(CONFIG)/interop_server
 interop_test: $(BINDIR)/$(CONFIG)/interop_test
 json_run_localhost: $(BINDIR)/$(CONFIG)/json_run_localhost
+lb_load_data_store_test: $(BINDIR)/$(CONFIG)/lb_load_data_store_test
 memory_test: $(BINDIR)/$(CONFIG)/memory_test
 metrics_client: $(BINDIR)/$(CONFIG)/metrics_client
 mock_test: $(BINDIR)/$(CONFIG)/mock_test
@@ -1195,10 +1196,12 @@
 reconnect_interop_server: $(BINDIR)/$(CONFIG)/reconnect_interop_server
 ref_counted_ptr_test: $(BINDIR)/$(CONFIG)/ref_counted_ptr_test
 ref_counted_test: $(BINDIR)/$(CONFIG)/ref_counted_test
+retry_throttle_test: $(BINDIR)/$(CONFIG)/retry_throttle_test
 secure_auth_context_test: $(BINDIR)/$(CONFIG)/secure_auth_context_test
 secure_sync_unary_ping_pong_test: $(BINDIR)/$(CONFIG)/secure_sync_unary_ping_pong_test
 server_builder_plugin_test: $(BINDIR)/$(CONFIG)/server_builder_plugin_test
 server_builder_test: $(BINDIR)/$(CONFIG)/server_builder_test
+server_builder_with_socket_mutator_test: $(BINDIR)/$(CONFIG)/server_builder_with_socket_mutator_test
 server_context_test_spouse_test: $(BINDIR)/$(CONFIG)/server_context_test_spouse_test
 server_crash_test: $(BINDIR)/$(CONFIG)/server_crash_test
 server_crash_test_client: $(BINDIR)/$(CONFIG)/server_crash_test_client
@@ -1324,6 +1327,7 @@
 resolver_component_tests_runner_invoker: $(BINDIR)/$(CONFIG)/resolver_component_tests_runner_invoker
 address_sorting_test_unsecure: $(BINDIR)/$(CONFIG)/address_sorting_test_unsecure
 address_sorting_test: $(BINDIR)/$(CONFIG)/address_sorting_test
+alts_credentials_fuzzer_one_entry: $(BINDIR)/$(CONFIG)/alts_credentials_fuzzer_one_entry
 api_fuzzer_one_entry: $(BINDIR)/$(CONFIG)/api_fuzzer_one_entry
 client_fuzzer_one_entry: $(BINDIR)/$(CONFIG)/client_fuzzer_one_entry
 hpack_parser_fuzzer_test_one_entry: $(BINDIR)/$(CONFIG)/hpack_parser_fuzzer_test_one_entry
@@ -1390,9 +1394,9 @@
 pc_cxx_unsecure: $(LIBDIR)/$(CONFIG)/pkgconfig/grpc++_unsecure.pc
 
 ifeq ($(EMBED_OPENSSL),true)
-privatelibs_cxx:  $(LIBDIR)/$(CONFIG)/libgrpc++_core_stats.a $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libhttp2_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a $(LIBDIR)/$(CONFIG)/libinterop_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl_crypto_test_data_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_asn1_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_base64_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bio_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_buf_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bytestring_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_chacha_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_aead_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_cipher_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_cmac_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_compiler_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_constant_time_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ed25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_spake25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_x25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_dh_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_digest_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_dsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ecdh_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_err_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_evp_extra_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_evp_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pbkdf_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_scrypt_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_aes_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bn_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ec_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_p256-x86_64_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_gcm_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ctrdrbg_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_hkdf_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_hmac_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_lhash_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_obj_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pkcs7_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pkcs12_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pkcs8_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_poly1305_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pool_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_refcount_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_rsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_file_test_gtest_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_gtest_main_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_thread_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_x509_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_tab_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_v3name_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_span_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ssl_test_lib.a $(LIBDIR)/$(CONFIG)/libbenchmark.a
+privatelibs_cxx:  $(LIBDIR)/$(CONFIG)/libgrpc++_core_stats.a $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libhttp2_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a $(LIBDIR)/$(CONFIG)/libinterop_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/liblb_load_data_store.a $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libboringssl_test_util.a $(LIBDIR)/$(CONFIG)/libboringssl_crypto_test_data_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_asn1_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_base64_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bio_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_buf_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bytestring_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_chacha_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_aead_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_cipher_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_cmac_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_compiler_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_constant_time_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ed25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_spake25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_x25519_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_dh_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_digest_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_dsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ecdh_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_err_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_evp_extra_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_evp_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pbkdf_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_scrypt_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_aes_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_bn_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ec_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_p256-x86_64_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ecdsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_gcm_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ctrdrbg_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_hkdf_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_hmac_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_lhash_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_obj_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pkcs7_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pkcs12_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pkcs8_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_poly1305_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_pool_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_refcount_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_rsa_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_file_test_gtest_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_gtest_main_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_thread_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_x509_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_tab_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_v3name_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_span_test_lib.a $(LIBDIR)/$(CONFIG)/libboringssl_ssl_test_lib.a $(LIBDIR)/$(CONFIG)/libbenchmark.a
 else
-privatelibs_cxx:  $(LIBDIR)/$(CONFIG)/libgrpc++_core_stats.a $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libhttp2_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a $(LIBDIR)/$(CONFIG)/libinterop_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libbenchmark.a
+privatelibs_cxx:  $(LIBDIR)/$(CONFIG)/libgrpc++_core_stats.a $(LIBDIR)/$(CONFIG)/libgrpc++_proto_reflection_desc_db.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_cli_libs.a $(LIBDIR)/$(CONFIG)/libhttp2_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_client_helper.a $(LIBDIR)/$(CONFIG)/libinterop_client_main.a $(LIBDIR)/$(CONFIG)/libinterop_server_helper.a $(LIBDIR)/$(CONFIG)/libinterop_server_lib.a $(LIBDIR)/$(CONFIG)/libinterop_server_main.a $(LIBDIR)/$(CONFIG)/liblb_load_data_store.a $(LIBDIR)/$(CONFIG)/libqps.a $(LIBDIR)/$(CONFIG)/libbenchmark.a
 endif
 
 
@@ -1455,7 +1459,6 @@
   $(BINDIR)/$(CONFIG)/grpc_completion_queue_threading_test \
   $(BINDIR)/$(CONFIG)/grpc_credentials_test \
   $(BINDIR)/$(CONFIG)/grpc_fetch_oauth2 \
-  $(BINDIR)/$(CONFIG)/grpc_invalid_channel_args_test \
   $(BINDIR)/$(CONFIG)/grpc_json_token_test \
   $(BINDIR)/$(CONFIG)/grpc_jwt_verifier_test \
   $(BINDIR)/$(CONFIG)/grpc_security_connector_test \
@@ -1571,6 +1574,7 @@
   $(BINDIR)/$(CONFIG)/h2_sockpair_1byte_nosec_test \
   $(BINDIR)/$(CONFIG)/h2_uds_nosec_test \
   $(BINDIR)/$(CONFIG)/inproc_nosec_test \
+  $(BINDIR)/$(CONFIG)/alts_credentials_fuzzer_one_entry \
   $(BINDIR)/$(CONFIG)/api_fuzzer_one_entry \
   $(BINDIR)/$(CONFIG)/client_fuzzer_one_entry \
   $(BINDIR)/$(CONFIG)/hpack_parser_fuzzer_test_one_entry \
@@ -1661,6 +1665,7 @@
   $(BINDIR)/$(CONFIG)/interop_server \
   $(BINDIR)/$(CONFIG)/interop_test \
   $(BINDIR)/$(CONFIG)/json_run_localhost \
+  $(BINDIR)/$(CONFIG)/lb_load_data_store_test \
   $(BINDIR)/$(CONFIG)/memory_test \
   $(BINDIR)/$(CONFIG)/metrics_client \
   $(BINDIR)/$(CONFIG)/mock_test \
@@ -1677,10 +1682,12 @@
   $(BINDIR)/$(CONFIG)/reconnect_interop_server \
   $(BINDIR)/$(CONFIG)/ref_counted_ptr_test \
   $(BINDIR)/$(CONFIG)/ref_counted_test \
+  $(BINDIR)/$(CONFIG)/retry_throttle_test \
   $(BINDIR)/$(CONFIG)/secure_auth_context_test \
   $(BINDIR)/$(CONFIG)/secure_sync_unary_ping_pong_test \
   $(BINDIR)/$(CONFIG)/server_builder_plugin_test \
   $(BINDIR)/$(CONFIG)/server_builder_test \
+  $(BINDIR)/$(CONFIG)/server_builder_with_socket_mutator_test \
   $(BINDIR)/$(CONFIG)/server_context_test_spouse_test \
   $(BINDIR)/$(CONFIG)/server_crash_test \
   $(BINDIR)/$(CONFIG)/server_crash_test_client \
@@ -1831,6 +1838,7 @@
   $(BINDIR)/$(CONFIG)/interop_server \
   $(BINDIR)/$(CONFIG)/interop_test \
   $(BINDIR)/$(CONFIG)/json_run_localhost \
+  $(BINDIR)/$(CONFIG)/lb_load_data_store_test \
   $(BINDIR)/$(CONFIG)/memory_test \
   $(BINDIR)/$(CONFIG)/metrics_client \
   $(BINDIR)/$(CONFIG)/mock_test \
@@ -1847,10 +1855,12 @@
   $(BINDIR)/$(CONFIG)/reconnect_interop_server \
   $(BINDIR)/$(CONFIG)/ref_counted_ptr_test \
   $(BINDIR)/$(CONFIG)/ref_counted_test \
+  $(BINDIR)/$(CONFIG)/retry_throttle_test \
   $(BINDIR)/$(CONFIG)/secure_auth_context_test \
   $(BINDIR)/$(CONFIG)/secure_sync_unary_ping_pong_test \
   $(BINDIR)/$(CONFIG)/server_builder_plugin_test \
   $(BINDIR)/$(CONFIG)/server_builder_test \
+  $(BINDIR)/$(CONFIG)/server_builder_with_socket_mutator_test \
   $(BINDIR)/$(CONFIG)/server_context_test_spouse_test \
   $(BINDIR)/$(CONFIG)/server_crash_test \
   $(BINDIR)/$(CONFIG)/server_crash_test_client \
@@ -1990,8 +2000,6 @@
 	$(Q) $(BINDIR)/$(CONFIG)/grpc_completion_queue_threading_test || ( echo test grpc_completion_queue_threading_test failed ; exit 1 )
 	$(E) "[RUN]     Testing grpc_credentials_test"
 	$(Q) $(BINDIR)/$(CONFIG)/grpc_credentials_test || ( echo test grpc_credentials_test failed ; exit 1 )
-	$(E) "[RUN]     Testing grpc_invalid_channel_args_test"
-	$(Q) $(BINDIR)/$(CONFIG)/grpc_invalid_channel_args_test || ( echo test grpc_invalid_channel_args_test failed ; exit 1 )
 	$(E) "[RUN]     Testing grpc_json_token_test"
 	$(Q) $(BINDIR)/$(CONFIG)/grpc_json_token_test || ( echo test grpc_json_token_test failed ; exit 1 )
 	$(E) "[RUN]     Testing grpc_jwt_verifier_test"
@@ -2284,6 +2292,8 @@
 	$(Q) $(BINDIR)/$(CONFIG)/inproc_sync_unary_ping_pong_test || ( echo test inproc_sync_unary_ping_pong_test failed ; exit 1 )
 	$(E) "[RUN]     Testing interop_test"
 	$(Q) $(BINDIR)/$(CONFIG)/interop_test || ( echo test interop_test failed ; exit 1 )
+	$(E) "[RUN]     Testing lb_load_data_store_test"
+	$(Q) $(BINDIR)/$(CONFIG)/lb_load_data_store_test || ( echo test lb_load_data_store_test failed ; exit 1 )
 	$(E) "[RUN]     Testing memory_test"
 	$(Q) $(BINDIR)/$(CONFIG)/memory_test || ( echo test memory_test failed ; exit 1 )
 	$(E) "[RUN]     Testing mock_test"
@@ -2304,6 +2314,8 @@
 	$(Q) $(BINDIR)/$(CONFIG)/ref_counted_ptr_test || ( echo test ref_counted_ptr_test failed ; exit 1 )
 	$(E) "[RUN]     Testing ref_counted_test"
 	$(Q) $(BINDIR)/$(CONFIG)/ref_counted_test || ( echo test ref_counted_test failed ; exit 1 )
+	$(E) "[RUN]     Testing retry_throttle_test"
+	$(Q) $(BINDIR)/$(CONFIG)/retry_throttle_test || ( echo test retry_throttle_test failed ; exit 1 )
 	$(E) "[RUN]     Testing secure_auth_context_test"
 	$(Q) $(BINDIR)/$(CONFIG)/secure_auth_context_test || ( echo test secure_auth_context_test failed ; exit 1 )
 	$(E) "[RUN]     Testing secure_sync_unary_ping_pong_test"
@@ -2312,6 +2324,8 @@
 	$(Q) $(BINDIR)/$(CONFIG)/server_builder_plugin_test || ( echo test server_builder_plugin_test failed ; exit 1 )
 	$(E) "[RUN]     Testing server_builder_test"
 	$(Q) $(BINDIR)/$(CONFIG)/server_builder_test || ( echo test server_builder_test failed ; exit 1 )
+	$(E) "[RUN]     Testing server_builder_with_socket_mutator_test"
+	$(Q) $(BINDIR)/$(CONFIG)/server_builder_with_socket_mutator_test || ( echo test server_builder_with_socket_mutator_test failed ; exit 1 )
 	$(E) "[RUN]     Testing server_context_test_spouse_test"
 	$(Q) $(BINDIR)/$(CONFIG)/server_context_test_spouse_test || ( echo test server_context_test_spouse_test failed ; exit 1 )
 	$(E) "[RUN]     Testing server_crash_test"
@@ -2569,6 +2583,22 @@
 endif
 
 ifeq ($(NO_PROTOC),true)
+$(GENDIR)/src/proto/grpc/testing/benchmark_service.pb.cc: protoc_dep_error
+$(GENDIR)/src/proto/grpc/testing/benchmark_service.grpc.pb.cc: protoc_dep_error
+else
+
+$(GENDIR)/src/proto/grpc/testing/benchmark_service.pb.cc: src/proto/grpc/testing/benchmark_service.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(GENDIR)/src/proto/grpc/testing/messages.pb.cc
+	$(E) "[PROTOC]  Generating protobuf CC file from $<"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --cpp_out=$(GENDIR) $<
+
+$(GENDIR)/src/proto/grpc/testing/benchmark_service.grpc.pb.cc: src/proto/grpc/testing/benchmark_service.proto $(GENDIR)/src/proto/grpc/testing/benchmark_service.pb.cc $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc
+	$(E) "[GRPC]    Generating gRPC's protobuf service CC file from $<"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $<
+endif
+
+ifeq ($(NO_PROTOC),true)
 $(GENDIR)/src/proto/grpc/testing/compiler_test.pb.cc: protoc_dep_error
 $(GENDIR)/src/proto/grpc/testing/compiler_test.grpc.pb.cc: protoc_dep_error
 else
@@ -2715,16 +2745,16 @@
 endif
 
 ifeq ($(NO_PROTOC),true)
-$(GENDIR)/src/proto/grpc/testing/services.pb.cc: protoc_dep_error
-$(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc: protoc_dep_error
+$(GENDIR)/src/proto/grpc/testing/report_qps_scenario_service.pb.cc: protoc_dep_error
+$(GENDIR)/src/proto/grpc/testing/report_qps_scenario_service.grpc.pb.cc: protoc_dep_error
 else
 
-$(GENDIR)/src/proto/grpc/testing/services.pb.cc: src/proto/grpc/testing/services.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc
+$(GENDIR)/src/proto/grpc/testing/report_qps_scenario_service.pb.cc: src/proto/grpc/testing/report_qps_scenario_service.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(GENDIR)/src/proto/grpc/testing/control.pb.cc
 	$(E) "[PROTOC]  Generating protobuf CC file from $<"
 	$(Q) mkdir -p `dirname $@`
 	$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --cpp_out=$(GENDIR) $<
 
-$(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc: src/proto/grpc/testing/services.proto $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc
+$(GENDIR)/src/proto/grpc/testing/report_qps_scenario_service.grpc.pb.cc: src/proto/grpc/testing/report_qps_scenario_service.proto $(GENDIR)/src/proto/grpc/testing/report_qps_scenario_service.pb.cc $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc
 	$(E) "[GRPC]    Generating gRPC's protobuf service CC file from $<"
 	$(Q) mkdir -p `dirname $@`
 	$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $<
@@ -2762,6 +2792,22 @@
 	$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $<
 endif
 
+ifeq ($(NO_PROTOC),true)
+$(GENDIR)/src/proto/grpc/testing/worker_service.pb.cc: protoc_dep_error
+$(GENDIR)/src/proto/grpc/testing/worker_service.grpc.pb.cc: protoc_dep_error
+else
+
+$(GENDIR)/src/proto/grpc/testing/worker_service.pb.cc: src/proto/grpc/testing/worker_service.proto $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(GENDIR)/src/proto/grpc/testing/control.pb.cc
+	$(E) "[PROTOC]  Generating protobuf CC file from $<"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --cpp_out=$(GENDIR) $<
+
+$(GENDIR)/src/proto/grpc/testing/worker_service.grpc.pb.cc: src/proto/grpc/testing/worker_service.proto $(GENDIR)/src/proto/grpc/testing/worker_service.pb.cc $(PROTOBUF_DEP) $(PROTOC_PLUGINS) $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc
+	$(E) "[GRPC]    Generating gRPC's protobuf service CC file from $<"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(PROTOC) -Ithird_party/protobuf/src -I. --grpc_out=$(GENDIR) --plugin=protoc-gen-grpc=$(PROTOC_PLUGINS_DIR)/grpc_cpp_plugin$(EXECUTABLE_SUFFIX) $<
+endif
+
 
 ifeq ($(CONFIG),stapprof)
 src/core/profiling/stap_timers.c: $(GENDIR)/src/core/profiling/stap_probes.h
@@ -3494,9 +3540,9 @@
     third_party/nanopb/pb_decode.c \
     third_party/nanopb/pb_encode.c \
     src/core/tsi/transport_security.cc \
-    src/core/tsi/transport_security_adapter.cc \
     src/core/ext/transport/chttp2/client/insecure/channel_create.cc \
     src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc \
+    src/core/ext/transport/chttp2/client/authority.cc \
     src/core/ext/transport/chttp2/client/chttp2_connector.cc \
     src/core/ext/filters/client_channel/backup_poller.cc \
     src/core/ext/filters/client_channel/channel_connectivity.cc \
@@ -3541,7 +3587,6 @@
     src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c \
     src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc \
     src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc \
-    src/core/ext/filters/client_channel/lb_policy/subchannel_list.cc \
     src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc \
     src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc \
     src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc \
@@ -3554,6 +3599,7 @@
     src/core/ext/census/grpc_context.cc \
     src/core/ext/filters/max_age/max_age_filter.cc \
     src/core/ext/filters/message_size/message_size_filter.cc \
+    src/core/ext/filters/http/client_authority_filter.cc \
     src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc \
     src/core/ext/filters/workarounds/workaround_utils.cc \
     src/core/plugin_registry/grpc_plugin_registry.cc \
@@ -3798,36 +3844,6 @@
     src/core/lib/transport/transport.cc \
     src/core/lib/transport/transport_op_string.cc \
     src/core/lib/debug/trace.cc \
-    src/core/ext/filters/deadline/deadline_filter.cc \
-    src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc \
-    src/core/ext/filters/client_channel/backup_poller.cc \
-    src/core/ext/filters/client_channel/channel_connectivity.cc \
-    src/core/ext/filters/client_channel/client_channel.cc \
-    src/core/ext/filters/client_channel/client_channel_factory.cc \
-    src/core/ext/filters/client_channel/client_channel_plugin.cc \
-    src/core/ext/filters/client_channel/connector.cc \
-    src/core/ext/filters/client_channel/http_connect_handshaker.cc \
-    src/core/ext/filters/client_channel/http_proxy.cc \
-    src/core/ext/filters/client_channel/lb_policy.cc \
-    src/core/ext/filters/client_channel/lb_policy_factory.cc \
-    src/core/ext/filters/client_channel/lb_policy_registry.cc \
-    src/core/ext/filters/client_channel/method_params.cc \
-    src/core/ext/filters/client_channel/parse_address.cc \
-    src/core/ext/filters/client_channel/proxy_mapper.cc \
-    src/core/ext/filters/client_channel/proxy_mapper_registry.cc \
-    src/core/ext/filters/client_channel/resolver.cc \
-    src/core/ext/filters/client_channel/resolver_registry.cc \
-    src/core/ext/filters/client_channel/retry_throttle.cc \
-    src/core/ext/filters/client_channel/subchannel.cc \
-    src/core/ext/filters/client_channel/subchannel_index.cc \
-    src/core/ext/filters/client_channel/uri_parser.cc \
-    src/core/ext/filters/client_channel/lb_policy/subchannel_list.cc \
-    src/core/ext/filters/max_age/max_age_filter.cc \
-    src/core/ext/filters/message_size/message_size_filter.cc \
-    src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc \
-    src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc \
-    src/core/ext/filters/load_reporting/server_load_reporting_filter.cc \
-    src/core/ext/filters/load_reporting/server_load_reporting_plugin.cc \
     src/core/ext/transport/cronet/client/secure/cronet_channel_create.cc \
     src/core/ext/transport/cronet/transport/cronet_api_dummy.cc \
     src/core/ext/transport/cronet/transport/cronet_transport.cc \
@@ -3859,6 +3875,28 @@
     src/core/ext/filters/http/http_filters_plugin.cc \
     src/core/ext/filters/http/message_compress/message_compress_filter.cc \
     src/core/ext/filters/http/server/http_server_filter.cc \
+    src/core/ext/filters/client_channel/backup_poller.cc \
+    src/core/ext/filters/client_channel/channel_connectivity.cc \
+    src/core/ext/filters/client_channel/client_channel.cc \
+    src/core/ext/filters/client_channel/client_channel_factory.cc \
+    src/core/ext/filters/client_channel/client_channel_plugin.cc \
+    src/core/ext/filters/client_channel/connector.cc \
+    src/core/ext/filters/client_channel/http_connect_handshaker.cc \
+    src/core/ext/filters/client_channel/http_proxy.cc \
+    src/core/ext/filters/client_channel/lb_policy.cc \
+    src/core/ext/filters/client_channel/lb_policy_factory.cc \
+    src/core/ext/filters/client_channel/lb_policy_registry.cc \
+    src/core/ext/filters/client_channel/method_params.cc \
+    src/core/ext/filters/client_channel/parse_address.cc \
+    src/core/ext/filters/client_channel/proxy_mapper.cc \
+    src/core/ext/filters/client_channel/proxy_mapper_registry.cc \
+    src/core/ext/filters/client_channel/resolver.cc \
+    src/core/ext/filters/client_channel/resolver_registry.cc \
+    src/core/ext/filters/client_channel/retry_throttle.cc \
+    src/core/ext/filters/client_channel/subchannel.cc \
+    src/core/ext/filters/client_channel/subchannel_index.cc \
+    src/core/ext/filters/client_channel/uri_parser.cc \
+    src/core/ext/filters/deadline/deadline_filter.cc \
     src/core/lib/http/httpcli_security_connector.cc \
     src/core/lib/security/context/security_context.cc \
     src/core/lib/security/credentials/alts/alts_credentials.cc \
@@ -3920,9 +3958,9 @@
     third_party/nanopb/pb_decode.c \
     third_party/nanopb/pb_encode.c \
     src/core/tsi/transport_security.cc \
-    src/core/tsi/transport_security_adapter.cc \
     src/core/ext/transport/chttp2/client/insecure/channel_create.cc \
     src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc \
+    src/core/ext/transport/chttp2/client/authority.cc \
     src/core/ext/transport/chttp2/client/chttp2_connector.cc \
     src/core/tsi/alts_transport_security.cc \
     src/core/tsi/fake_transport_security.cc \
@@ -3931,8 +3969,8 @@
     src/core/tsi/ssl/session_cache/ssl_session_openssl.cc \
     src/core/tsi/ssl_transport_security.cc \
     src/core/tsi/transport_security_grpc.cc \
-    src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.cc \
-    src/core/ext/transport/chttp2/server/chttp2_server.cc \
+    src/core/ext/filters/load_reporting/server_load_reporting_filter.cc \
+    src/core/ext/filters/load_reporting/server_load_reporting_plugin.cc \
     src/core/plugin_registry/grpc_cronet_plugin_registry.cc \
 
 PUBLIC_HEADERS_C += \
@@ -3957,20 +3995,9 @@
     include/grpc/impl/codegen/sync_generic.h \
     include/grpc/impl/codegen/sync_posix.h \
     include/grpc/impl/codegen/sync_windows.h \
-    include/grpc/byte_buffer.h \
-    include/grpc/byte_buffer_reader.h \
-    include/grpc/compression.h \
-    include/grpc/fork.h \
-    include/grpc/grpc.h \
-    include/grpc/grpc_posix.h \
-    include/grpc/grpc_security_constants.h \
-    include/grpc/load_reporting.h \
-    include/grpc/slice.h \
-    include/grpc/slice_buffer.h \
-    include/grpc/status.h \
-    include/grpc/support/workaround_list.h \
     include/grpc/grpc_cronet.h \
     include/grpc/grpc_security.h \
+    include/grpc/grpc_security_constants.h \
 
 LIBGRPC_CRONET_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBGRPC_CRONET_SRC))))
 
@@ -4036,6 +4063,7 @@
     test/core/end2end/fixtures/proxy.cc \
     test/core/iomgr/endpoint_tests.cc \
     test/core/util/debugger_macros.cc \
+    test/core/util/fuzzer_util.cc \
     test/core/util/grpc_profiler.cc \
     test/core/util/histogram.cc \
     test/core/util/memory_counters.cc \
@@ -4331,6 +4359,7 @@
     test/core/end2end/fixtures/proxy.cc \
     test/core/iomgr/endpoint_tests.cc \
     test/core/util/debugger_macros.cc \
+    test/core/util/fuzzer_util.cc \
     test/core/util/grpc_profiler.cc \
     test/core/util/histogram.cc \
     test/core/util/memory_counters.cc \
@@ -4789,6 +4818,7 @@
     src/core/ext/transport/chttp2/server/chttp2_server.cc \
     src/core/ext/transport/chttp2/client/insecure/channel_create.cc \
     src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc \
+    src/core/ext/transport/chttp2/client/authority.cc \
     src/core/ext/transport/chttp2/client/chttp2_connector.cc \
     src/core/ext/filters/client_channel/backup_poller.cc \
     src/core/ext/filters/client_channel/channel_connectivity.cc \
@@ -4833,11 +4863,11 @@
     third_party/nanopb/pb_decode.c \
     third_party/nanopb/pb_encode.c \
     src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc \
-    src/core/ext/filters/client_channel/lb_policy/subchannel_list.cc \
     src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc \
     src/core/ext/census/grpc_context.cc \
     src/core/ext/filters/max_age/max_age_filter.cc \
     src/core/ext/filters/message_size/message_size_filter.cc \
+    src/core/ext/filters/http/client_authority_filter.cc \
     src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc \
     src/core/ext/filters/workarounds/workaround_utils.cc \
     src/core/plugin_registry/grpc_unsecure_plugin_registry.cc \
@@ -5032,7 +5062,6 @@
     src/cpp/server/server_posix.cc \
     src/cpp/thread_manager/thread_manager.cc \
     src/cpp/util/byte_buffer_cc.cc \
-    src/cpp/util/slice_cc.cc \
     src/cpp/util/status.cc \
     src/cpp/util/string_ref.cc \
     src/cpp/util/time_cc.cc \
@@ -5122,6 +5151,8 @@
     include/grpcpp/support/byte_buffer.h \
     include/grpcpp/support/channel_arguments.h \
     include/grpcpp/support/config.h \
+    include/grpcpp/support/proto_buffer_reader.h \
+    include/grpcpp/support/proto_buffer_writer.h \
     include/grpcpp/support/slice.h \
     include/grpcpp/support/status.h \
     include/grpcpp/support/status_code_enum.h \
@@ -5240,6 +5271,8 @@
     include/grpcpp/impl/codegen/sync_stream.h \
     include/grpcpp/impl/codegen/time.h \
     include/grpc++/impl/codegen/proto_utils.h \
+    include/grpcpp/impl/codegen/proto_buffer_reader.h \
+    include/grpcpp/impl/codegen/proto_buffer_writer.h \
     include/grpcpp/impl/codegen/proto_utils.h \
     include/grpc++/impl/codegen/config_protobuf.h \
     include/grpcpp/impl/codegen/config_protobuf.h \
@@ -5393,13 +5426,13 @@
     src/cpp/server/server_posix.cc \
     src/cpp/thread_manager/thread_manager.cc \
     src/cpp/util/byte_buffer_cc.cc \
-    src/cpp/util/slice_cc.cc \
     src/cpp/util/status.cc \
     src/cpp/util/string_ref.cc \
     src/cpp/util/time_cc.cc \
     src/cpp/codegen/codegen_init.cc \
     src/core/ext/transport/chttp2/client/insecure/channel_create.cc \
     src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc \
+    src/core/ext/transport/chttp2/client/authority.cc \
     src/core/ext/transport/chttp2/client/chttp2_connector.cc \
     src/core/ext/transport/chttp2/transport/bin_decoder.cc \
     src/core/ext/transport/chttp2/transport/bin_encoder.cc \
@@ -5691,6 +5724,8 @@
     include/grpcpp/support/byte_buffer.h \
     include/grpcpp/support/channel_arguments.h \
     include/grpcpp/support/config.h \
+    include/grpcpp/support/proto_buffer_reader.h \
+    include/grpcpp/support/proto_buffer_writer.h \
     include/grpcpp/support/slice.h \
     include/grpcpp/support/status.h \
     include/grpcpp/support/status_code_enum.h \
@@ -6219,6 +6254,8 @@
     include/grpc/impl/codegen/sync_posix.h \
     include/grpc/impl/codegen/sync_windows.h \
     include/grpc++/impl/codegen/proto_utils.h \
+    include/grpcpp/impl/codegen/proto_buffer_reader.h \
+    include/grpcpp/impl/codegen/proto_buffer_writer.h \
     include/grpcpp/impl/codegen/proto_utils.h \
     include/grpc++/impl/codegen/config_protobuf.h \
     include/grpcpp/impl/codegen/config_protobuf.h \
@@ -6369,6 +6406,8 @@
     include/grpc/impl/codegen/sync_posix.h \
     include/grpc/impl/codegen/sync_windows.h \
     include/grpc++/impl/codegen/proto_utils.h \
+    include/grpcpp/impl/codegen/proto_buffer_reader.h \
+    include/grpcpp/impl/codegen/proto_buffer_writer.h \
     include/grpcpp/impl/codegen/proto_utils.h \
     include/grpc++/impl/codegen/config_protobuf.h \
     include/grpcpp/impl/codegen/config_protobuf.h \
@@ -6456,7 +6495,6 @@
     src/cpp/server/server_posix.cc \
     src/cpp/thread_manager/thread_manager.cc \
     src/cpp/util/byte_buffer_cc.cc \
-    src/cpp/util/slice_cc.cc \
     src/cpp/util/status.cc \
     src/cpp/util/string_ref.cc \
     src/cpp/util/time_cc.cc \
@@ -6546,6 +6584,8 @@
     include/grpcpp/support/byte_buffer.h \
     include/grpcpp/support/channel_arguments.h \
     include/grpcpp/support/config.h \
+    include/grpcpp/support/proto_buffer_reader.h \
+    include/grpcpp/support/proto_buffer_writer.h \
     include/grpcpp/support/slice.h \
     include/grpcpp/support/status.h \
     include/grpcpp/support/status_code_enum.h \
@@ -7178,12 +7218,63 @@
 endif
 
 
+LIBLB_LOAD_DATA_STORE_SRC = \
+    src/cpp/server/load_reporter/load_data_store.cc \
+
+PUBLIC_HEADERS_CXX += \
+
+LIBLB_LOAD_DATA_STORE_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LIBLB_LOAD_DATA_STORE_SRC))))
+
+
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure libraries if you don't have OpenSSL.
+
+$(LIBDIR)/$(CONFIG)/liblb_load_data_store.a: openssl_dep_error
+
+
+else
+
+ifeq ($(NO_PROTOBUF),true)
+
+# You can't build a C++ library if you don't have protobuf - a bit overreached, but still okay.
+
+$(LIBDIR)/$(CONFIG)/liblb_load_data_store.a: protobuf_dep_error
+
+
+else
+
+$(LIBDIR)/$(CONFIG)/liblb_load_data_store.a: $(ZLIB_DEP) $(OPENSSL_DEP) $(CARES_DEP) $(ADDRESS_SORTING_DEP) $(PROTOBUF_DEP) $(LIBLB_LOAD_DATA_STORE_OBJS) 
+	$(E) "[AR]      Creating $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) rm -f $(LIBDIR)/$(CONFIG)/liblb_load_data_store.a
+	$(Q) $(AR) $(AROPTS) $(LIBDIR)/$(CONFIG)/liblb_load_data_store.a $(LIBLB_LOAD_DATA_STORE_OBJS) 
+ifeq ($(SYSTEM),Darwin)
+	$(Q) ranlib -no_warning_for_no_symbols $(LIBDIR)/$(CONFIG)/liblb_load_data_store.a
+endif
+
+
+
+
+endif
+
+endif
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(LIBLB_LOAD_DATA_STORE_OBJS:.o=.dep)
+endif
+endif
+
+
 LIBQPS_SRC = \
     $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc \
     $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc \
     $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc \
     $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc \
-    $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc \
+    $(GENDIR)/src/proto/grpc/testing/benchmark_service.pb.cc $(GENDIR)/src/proto/grpc/testing/benchmark_service.grpc.pb.cc \
+    $(GENDIR)/src/proto/grpc/testing/report_qps_scenario_service.pb.cc $(GENDIR)/src/proto/grpc/testing/report_qps_scenario_service.grpc.pb.cc \
+    $(GENDIR)/src/proto/grpc/testing/worker_service.pb.cc $(GENDIR)/src/proto/grpc/testing/worker_service.grpc.pb.cc \
     test/cpp/qps/benchmark_config.cc \
     test/cpp/qps/client_async.cc \
     test/cpp/qps/client_sync.cc \
@@ -7239,16 +7330,16 @@
 -include $(LIBQPS_OBJS:.o=.dep)
 endif
 endif
-$(OBJDIR)/$(CONFIG)/test/cpp/qps/benchmark_config.o: $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc
-$(OBJDIR)/$(CONFIG)/test/cpp/qps/client_async.o: $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc
-$(OBJDIR)/$(CONFIG)/test/cpp/qps/client_sync.o: $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc
-$(OBJDIR)/$(CONFIG)/test/cpp/qps/driver.o: $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc
-$(OBJDIR)/$(CONFIG)/test/cpp/qps/parse_json.o: $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc
-$(OBJDIR)/$(CONFIG)/test/cpp/qps/qps_worker.o: $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc
-$(OBJDIR)/$(CONFIG)/test/cpp/qps/report.o: $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc
-$(OBJDIR)/$(CONFIG)/test/cpp/qps/server_async.o: $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc
-$(OBJDIR)/$(CONFIG)/test/cpp/qps/server_sync.o: $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc
-$(OBJDIR)/$(CONFIG)/test/cpp/qps/usage_timer.o: $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc
+$(OBJDIR)/$(CONFIG)/test/cpp/qps/benchmark_config.o: $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/benchmark_service.pb.cc $(GENDIR)/src/proto/grpc/testing/benchmark_service.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/report_qps_scenario_service.pb.cc $(GENDIR)/src/proto/grpc/testing/report_qps_scenario_service.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/worker_service.pb.cc $(GENDIR)/src/proto/grpc/testing/worker_service.grpc.pb.cc
+$(OBJDIR)/$(CONFIG)/test/cpp/qps/client_async.o: $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/benchmark_service.pb.cc $(GENDIR)/src/proto/grpc/testing/benchmark_service.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/report_qps_scenario_service.pb.cc $(GENDIR)/src/proto/grpc/testing/report_qps_scenario_service.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/worker_service.pb.cc $(GENDIR)/src/proto/grpc/testing/worker_service.grpc.pb.cc
+$(OBJDIR)/$(CONFIG)/test/cpp/qps/client_sync.o: $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/benchmark_service.pb.cc $(GENDIR)/src/proto/grpc/testing/benchmark_service.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/report_qps_scenario_service.pb.cc $(GENDIR)/src/proto/grpc/testing/report_qps_scenario_service.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/worker_service.pb.cc $(GENDIR)/src/proto/grpc/testing/worker_service.grpc.pb.cc
+$(OBJDIR)/$(CONFIG)/test/cpp/qps/driver.o: $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/benchmark_service.pb.cc $(GENDIR)/src/proto/grpc/testing/benchmark_service.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/report_qps_scenario_service.pb.cc $(GENDIR)/src/proto/grpc/testing/report_qps_scenario_service.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/worker_service.pb.cc $(GENDIR)/src/proto/grpc/testing/worker_service.grpc.pb.cc
+$(OBJDIR)/$(CONFIG)/test/cpp/qps/parse_json.o: $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/benchmark_service.pb.cc $(GENDIR)/src/proto/grpc/testing/benchmark_service.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/report_qps_scenario_service.pb.cc $(GENDIR)/src/proto/grpc/testing/report_qps_scenario_service.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/worker_service.pb.cc $(GENDIR)/src/proto/grpc/testing/worker_service.grpc.pb.cc
+$(OBJDIR)/$(CONFIG)/test/cpp/qps/qps_worker.o: $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/benchmark_service.pb.cc $(GENDIR)/src/proto/grpc/testing/benchmark_service.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/report_qps_scenario_service.pb.cc $(GENDIR)/src/proto/grpc/testing/report_qps_scenario_service.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/worker_service.pb.cc $(GENDIR)/src/proto/grpc/testing/worker_service.grpc.pb.cc
+$(OBJDIR)/$(CONFIG)/test/cpp/qps/report.o: $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/benchmark_service.pb.cc $(GENDIR)/src/proto/grpc/testing/benchmark_service.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/report_qps_scenario_service.pb.cc $(GENDIR)/src/proto/grpc/testing/report_qps_scenario_service.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/worker_service.pb.cc $(GENDIR)/src/proto/grpc/testing/worker_service.grpc.pb.cc
+$(OBJDIR)/$(CONFIG)/test/cpp/qps/server_async.o: $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/benchmark_service.pb.cc $(GENDIR)/src/proto/grpc/testing/benchmark_service.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/report_qps_scenario_service.pb.cc $(GENDIR)/src/proto/grpc/testing/report_qps_scenario_service.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/worker_service.pb.cc $(GENDIR)/src/proto/grpc/testing/worker_service.grpc.pb.cc
+$(OBJDIR)/$(CONFIG)/test/cpp/qps/server_sync.o: $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/benchmark_service.pb.cc $(GENDIR)/src/proto/grpc/testing/benchmark_service.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/report_qps_scenario_service.pb.cc $(GENDIR)/src/proto/grpc/testing/report_qps_scenario_service.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/worker_service.pb.cc $(GENDIR)/src/proto/grpc/testing/worker_service.grpc.pb.cc
+$(OBJDIR)/$(CONFIG)/test/cpp/qps/usage_timer.o: $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/benchmark_service.pb.cc $(GENDIR)/src/proto/grpc/testing/benchmark_service.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/report_qps_scenario_service.pb.cc $(GENDIR)/src/proto/grpc/testing/report_qps_scenario_service.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/worker_service.pb.cc $(GENDIR)/src/proto/grpc/testing/worker_service.grpc.pb.cc
 
 
 LIBGRPC_CSHARP_EXT_SRC = \
@@ -9832,6 +9923,7 @@
     test/core/end2end/tests/bad_ping.cc \
     test/core/end2end/tests/binary_metadata.cc \
     test/core/end2end/tests/call_creds.cc \
+    test/core/end2end/tests/call_host_override.cc \
     test/core/end2end/tests/cancel_after_accept.cc \
     test/core/end2end/tests/cancel_after_client_done.cc \
     test/core/end2end/tests/cancel_after_invoke.cc \
@@ -9878,6 +9970,7 @@
     test/core/end2end/tests/retry_exceeds_buffer_size_in_initial_batch.cc \
     test/core/end2end/tests/retry_exceeds_buffer_size_in_subsequent_batch.cc \
     test/core/end2end/tests/retry_non_retriable_status.cc \
+    test/core/end2end/tests/retry_non_retriable_status_before_recv_trailing_metadata_started.cc \
     test/core/end2end/tests/retry_recv_initial_metadata.cc \
     test/core/end2end/tests/retry_recv_message.cc \
     test/core/end2end/tests/retry_server_pushback_delay.cc \
@@ -9946,6 +10039,7 @@
     test/core/end2end/tests/bad_hostname.cc \
     test/core/end2end/tests/bad_ping.cc \
     test/core/end2end/tests/binary_metadata.cc \
+    test/core/end2end/tests/call_host_override.cc \
     test/core/end2end/tests/cancel_after_accept.cc \
     test/core/end2end/tests/cancel_after_client_done.cc \
     test/core/end2end/tests/cancel_after_invoke.cc \
@@ -9992,6 +10086,7 @@
     test/core/end2end/tests/retry_exceeds_buffer_size_in_initial_batch.cc \
     test/core/end2end/tests/retry_exceeds_buffer_size_in_subsequent_batch.cc \
     test/core/end2end/tests/retry_non_retriable_status.cc \
+    test/core/end2end/tests/retry_non_retriable_status_before_recv_trailing_metadata_started.cc \
     test/core/end2end/tests/retry_recv_initial_metadata.cc \
     test/core/end2end/tests/retry_recv_message.cc \
     test/core/end2end/tests/retry_server_pushback_delay.cc \
@@ -10139,6 +10234,38 @@
 endif
 
 
+ALTS_CREDENTIALS_FUZZER_SRC = \
+    test/core/security/alts_credentials_fuzzer.cc \
+
+ALTS_CREDENTIALS_FUZZER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(ALTS_CREDENTIALS_FUZZER_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/alts_credentials_fuzzer: openssl_dep_error
+
+else
+
+
+
+$(BINDIR)/$(CONFIG)/alts_credentials_fuzzer: $(ALTS_CREDENTIALS_FUZZER_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LDXX) $(LDFLAGS) $(ALTS_CREDENTIALS_FUZZER_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -lFuzzer -o $(BINDIR)/$(CONFIG)/alts_credentials_fuzzer
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/security/alts_credentials_fuzzer.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_alts_credentials_fuzzer: $(ALTS_CREDENTIALS_FUZZER_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(ALTS_CREDENTIALS_FUZZER_OBJS:.o=.dep)
+endif
+endif
+
+
 API_FUZZER_SRC = \
     test/core/end2end/fuzzers/api_fuzzer.cc \
 
@@ -11969,38 +12096,6 @@
 endif
 
 
-GRPC_INVALID_CHANNEL_ARGS_TEST_SRC = \
-    test/core/surface/invalid_channel_args_test.cc \
-
-GRPC_INVALID_CHANNEL_ARGS_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(GRPC_INVALID_CHANNEL_ARGS_TEST_SRC))))
-ifeq ($(NO_SECURE),true)
-
-# You can't build secure targets if you don't have OpenSSL.
-
-$(BINDIR)/$(CONFIG)/grpc_invalid_channel_args_test: openssl_dep_error
-
-else
-
-
-
-$(BINDIR)/$(CONFIG)/grpc_invalid_channel_args_test: $(GRPC_INVALID_CHANNEL_ARGS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-	$(E) "[LD]      Linking $@"
-	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LD) $(LDFLAGS) $(GRPC_INVALID_CHANNEL_ARGS_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/grpc_invalid_channel_args_test
-
-endif
-
-$(OBJDIR)/$(CONFIG)/test/core/surface/invalid_channel_args_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
-
-deps_grpc_invalid_channel_args_test: $(GRPC_INVALID_CHANNEL_ARGS_TEST_OBJS:.o=.dep)
-
-ifneq ($(NO_SECURE),true)
-ifneq ($(NO_DEPS),true)
--include $(GRPC_INVALID_CHANNEL_ARGS_TEST_OBJS:.o=.dep)
-endif
-endif
-
-
 GRPC_JSON_TOKEN_TEST_SRC = \
     test/core/security/json_token_test.cc \
 
@@ -14625,7 +14720,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/alarm_test: protobuf_dep_error
 
@@ -14668,7 +14763,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/alts_counter_test: protobuf_dep_error
 
@@ -14711,7 +14806,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/alts_crypt_test: protobuf_dep_error
 
@@ -14754,7 +14849,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/alts_crypter_test: protobuf_dep_error
 
@@ -14797,7 +14892,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/alts_frame_handler_test: protobuf_dep_error
 
@@ -14841,7 +14936,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/alts_frame_protector_test: protobuf_dep_error
 
@@ -14886,7 +14981,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/alts_grpc_record_protocol_test: protobuf_dep_error
 
@@ -14929,7 +15024,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/alts_handshaker_client_test: protobuf_dep_error
 
@@ -14972,7 +15067,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/alts_handshaker_service_api_test: protobuf_dep_error
 
@@ -15015,7 +15110,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/alts_iovec_record_protocol_test: protobuf_dep_error
 
@@ -15058,7 +15153,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/alts_security_connector_test: protobuf_dep_error
 
@@ -15101,7 +15196,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/alts_tsi_handshaker_test: protobuf_dep_error
 
@@ -15144,7 +15239,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/alts_tsi_utils_test: protobuf_dep_error
 
@@ -15187,7 +15282,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/alts_zero_copy_grpc_protector_test: protobuf_dep_error
 
@@ -15230,7 +15325,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/async_end2end_test: protobuf_dep_error
 
@@ -15273,7 +15368,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/auth_property_iterator_test: protobuf_dep_error
 
@@ -15316,7 +15411,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/backoff_test: protobuf_dep_error
 
@@ -15359,7 +15454,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/bdp_estimator_test: protobuf_dep_error
 
@@ -15402,23 +15497,23 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/bm_arena: protobuf_dep_error
 
 else
 
-$(BINDIR)/$(CONFIG)/bm_arena: $(PROTOBUF_DEP) $(BM_ARENA_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+$(BINDIR)/$(CONFIG)/bm_arena: $(PROTOBUF_DEP) $(BM_ARENA_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LDXX) $(LDFLAGS) $(BM_ARENA_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_arena
+	$(Q) $(LDXX) $(LDFLAGS) $(BM_ARENA_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_arena
 
 endif
 
 endif
 
 $(BM_ARENA_OBJS): CPPFLAGS += -Ithird_party/benchmark/include -DHAVE_POSIX_REGEX
-$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_arena.o:  $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_arena.o:  $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
 
 deps_bm_arena: $(BM_ARENA_OBJS:.o=.dep)
 
@@ -15446,23 +15541,23 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/bm_call_create: protobuf_dep_error
 
 else
 
-$(BINDIR)/$(CONFIG)/bm_call_create: $(PROTOBUF_DEP) $(BM_CALL_CREATE_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+$(BINDIR)/$(CONFIG)/bm_call_create: $(PROTOBUF_DEP) $(BM_CALL_CREATE_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LDXX) $(LDFLAGS) $(BM_CALL_CREATE_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_call_create
+	$(Q) $(LDXX) $(LDFLAGS) $(BM_CALL_CREATE_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_call_create
 
 endif
 
 endif
 
 $(BM_CALL_CREATE_OBJS): CPPFLAGS += -Ithird_party/benchmark/include -DHAVE_POSIX_REGEX
-$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_call_create.o:  $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_call_create.o:  $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
 
 deps_bm_call_create: $(BM_CALL_CREATE_OBJS:.o=.dep)
 
@@ -15490,23 +15585,23 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/bm_chttp2_hpack: protobuf_dep_error
 
 else
 
-$(BINDIR)/$(CONFIG)/bm_chttp2_hpack: $(PROTOBUF_DEP) $(BM_CHTTP2_HPACK_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+$(BINDIR)/$(CONFIG)/bm_chttp2_hpack: $(PROTOBUF_DEP) $(BM_CHTTP2_HPACK_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LDXX) $(LDFLAGS) $(BM_CHTTP2_HPACK_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_chttp2_hpack
+	$(Q) $(LDXX) $(LDFLAGS) $(BM_CHTTP2_HPACK_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_chttp2_hpack
 
 endif
 
 endif
 
 $(BM_CHTTP2_HPACK_OBJS): CPPFLAGS += -Ithird_party/benchmark/include -DHAVE_POSIX_REGEX
-$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_chttp2_hpack.o:  $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_chttp2_hpack.o:  $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
 
 deps_bm_chttp2_hpack: $(BM_CHTTP2_HPACK_OBJS:.o=.dep)
 
@@ -15534,23 +15629,23 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/bm_chttp2_transport: protobuf_dep_error
 
 else
 
-$(BINDIR)/$(CONFIG)/bm_chttp2_transport: $(PROTOBUF_DEP) $(BM_CHTTP2_TRANSPORT_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+$(BINDIR)/$(CONFIG)/bm_chttp2_transport: $(PROTOBUF_DEP) $(BM_CHTTP2_TRANSPORT_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LDXX) $(LDFLAGS) $(BM_CHTTP2_TRANSPORT_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_chttp2_transport
+	$(Q) $(LDXX) $(LDFLAGS) $(BM_CHTTP2_TRANSPORT_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_chttp2_transport
 
 endif
 
 endif
 
 $(BM_CHTTP2_TRANSPORT_OBJS): CPPFLAGS += -Ithird_party/benchmark/include -DHAVE_POSIX_REGEX
-$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_chttp2_transport.o:  $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_chttp2_transport.o:  $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
 
 deps_bm_chttp2_transport: $(BM_CHTTP2_TRANSPORT_OBJS:.o=.dep)
 
@@ -15578,23 +15673,23 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/bm_closure: protobuf_dep_error
 
 else
 
-$(BINDIR)/$(CONFIG)/bm_closure: $(PROTOBUF_DEP) $(BM_CLOSURE_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+$(BINDIR)/$(CONFIG)/bm_closure: $(PROTOBUF_DEP) $(BM_CLOSURE_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LDXX) $(LDFLAGS) $(BM_CLOSURE_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_closure
+	$(Q) $(LDXX) $(LDFLAGS) $(BM_CLOSURE_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_closure
 
 endif
 
 endif
 
 $(BM_CLOSURE_OBJS): CPPFLAGS += -Ithird_party/benchmark/include -DHAVE_POSIX_REGEX
-$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_closure.o:  $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_closure.o:  $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
 
 deps_bm_closure: $(BM_CLOSURE_OBJS:.o=.dep)
 
@@ -15622,23 +15717,23 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/bm_cq: protobuf_dep_error
 
 else
 
-$(BINDIR)/$(CONFIG)/bm_cq: $(PROTOBUF_DEP) $(BM_CQ_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+$(BINDIR)/$(CONFIG)/bm_cq: $(PROTOBUF_DEP) $(BM_CQ_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LDXX) $(LDFLAGS) $(BM_CQ_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_cq
+	$(Q) $(LDXX) $(LDFLAGS) $(BM_CQ_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_cq
 
 endif
 
 endif
 
 $(BM_CQ_OBJS): CPPFLAGS += -Ithird_party/benchmark/include -DHAVE_POSIX_REGEX
-$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_cq.o:  $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_cq.o:  $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
 
 deps_bm_cq: $(BM_CQ_OBJS:.o=.dep)
 
@@ -15666,23 +15761,23 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/bm_cq_multiple_threads: protobuf_dep_error
 
 else
 
-$(BINDIR)/$(CONFIG)/bm_cq_multiple_threads: $(PROTOBUF_DEP) $(BM_CQ_MULTIPLE_THREADS_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+$(BINDIR)/$(CONFIG)/bm_cq_multiple_threads: $(PROTOBUF_DEP) $(BM_CQ_MULTIPLE_THREADS_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LDXX) $(LDFLAGS) $(BM_CQ_MULTIPLE_THREADS_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_cq_multiple_threads
+	$(Q) $(LDXX) $(LDFLAGS) $(BM_CQ_MULTIPLE_THREADS_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_cq_multiple_threads
 
 endif
 
 endif
 
 $(BM_CQ_MULTIPLE_THREADS_OBJS): CPPFLAGS += -Ithird_party/benchmark/include -DHAVE_POSIX_REGEX
-$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_cq_multiple_threads.o:  $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_cq_multiple_threads.o:  $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
 
 deps_bm_cq_multiple_threads: $(BM_CQ_MULTIPLE_THREADS_OBJS:.o=.dep)
 
@@ -15710,23 +15805,23 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/bm_error: protobuf_dep_error
 
 else
 
-$(BINDIR)/$(CONFIG)/bm_error: $(PROTOBUF_DEP) $(BM_ERROR_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+$(BINDIR)/$(CONFIG)/bm_error: $(PROTOBUF_DEP) $(BM_ERROR_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LDXX) $(LDFLAGS) $(BM_ERROR_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_error
+	$(Q) $(LDXX) $(LDFLAGS) $(BM_ERROR_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_error
 
 endif
 
 endif
 
 $(BM_ERROR_OBJS): CPPFLAGS += -Ithird_party/benchmark/include -DHAVE_POSIX_REGEX
-$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_error.o:  $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_error.o:  $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
 
 deps_bm_error: $(BM_ERROR_OBJS:.o=.dep)
 
@@ -15754,23 +15849,23 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/bm_fullstack_streaming_ping_pong: protobuf_dep_error
 
 else
 
-$(BINDIR)/$(CONFIG)/bm_fullstack_streaming_ping_pong: $(PROTOBUF_DEP) $(BM_FULLSTACK_STREAMING_PING_PONG_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+$(BINDIR)/$(CONFIG)/bm_fullstack_streaming_ping_pong: $(PROTOBUF_DEP) $(BM_FULLSTACK_STREAMING_PING_PONG_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LDXX) $(LDFLAGS) $(BM_FULLSTACK_STREAMING_PING_PONG_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_fullstack_streaming_ping_pong
+	$(Q) $(LDXX) $(LDFLAGS) $(BM_FULLSTACK_STREAMING_PING_PONG_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_fullstack_streaming_ping_pong
 
 endif
 
 endif
 
 $(BM_FULLSTACK_STREAMING_PING_PONG_OBJS): CPPFLAGS += -Ithird_party/benchmark/include -DHAVE_POSIX_REGEX
-$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_fullstack_streaming_ping_pong.o:  $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_fullstack_streaming_ping_pong.o:  $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
 
 deps_bm_fullstack_streaming_ping_pong: $(BM_FULLSTACK_STREAMING_PING_PONG_OBJS:.o=.dep)
 
@@ -15798,23 +15893,23 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/bm_fullstack_streaming_pump: protobuf_dep_error
 
 else
 
-$(BINDIR)/$(CONFIG)/bm_fullstack_streaming_pump: $(PROTOBUF_DEP) $(BM_FULLSTACK_STREAMING_PUMP_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+$(BINDIR)/$(CONFIG)/bm_fullstack_streaming_pump: $(PROTOBUF_DEP) $(BM_FULLSTACK_STREAMING_PUMP_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LDXX) $(LDFLAGS) $(BM_FULLSTACK_STREAMING_PUMP_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_fullstack_streaming_pump
+	$(Q) $(LDXX) $(LDFLAGS) $(BM_FULLSTACK_STREAMING_PUMP_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_fullstack_streaming_pump
 
 endif
 
 endif
 
 $(BM_FULLSTACK_STREAMING_PUMP_OBJS): CPPFLAGS += -Ithird_party/benchmark/include -DHAVE_POSIX_REGEX
-$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_fullstack_streaming_pump.o:  $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_fullstack_streaming_pump.o:  $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
 
 deps_bm_fullstack_streaming_pump: $(BM_FULLSTACK_STREAMING_PUMP_OBJS:.o=.dep)
 
@@ -15842,7 +15937,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/bm_fullstack_trickle: protobuf_dep_error
 
@@ -15886,23 +15981,23 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/bm_fullstack_unary_ping_pong: protobuf_dep_error
 
 else
 
-$(BINDIR)/$(CONFIG)/bm_fullstack_unary_ping_pong: $(PROTOBUF_DEP) $(BM_FULLSTACK_UNARY_PING_PONG_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+$(BINDIR)/$(CONFIG)/bm_fullstack_unary_ping_pong: $(PROTOBUF_DEP) $(BM_FULLSTACK_UNARY_PING_PONG_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LDXX) $(LDFLAGS) $(BM_FULLSTACK_UNARY_PING_PONG_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_fullstack_unary_ping_pong
+	$(Q) $(LDXX) $(LDFLAGS) $(BM_FULLSTACK_UNARY_PING_PONG_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_fullstack_unary_ping_pong
 
 endif
 
 endif
 
 $(BM_FULLSTACK_UNARY_PING_PONG_OBJS): CPPFLAGS += -Ithird_party/benchmark/include -DHAVE_POSIX_REGEX
-$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_fullstack_unary_ping_pong.o:  $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_fullstack_unary_ping_pong.o:  $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
 
 deps_bm_fullstack_unary_ping_pong: $(BM_FULLSTACK_UNARY_PING_PONG_OBJS:.o=.dep)
 
@@ -15930,23 +16025,23 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/bm_metadata: protobuf_dep_error
 
 else
 
-$(BINDIR)/$(CONFIG)/bm_metadata: $(PROTOBUF_DEP) $(BM_METADATA_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+$(BINDIR)/$(CONFIG)/bm_metadata: $(PROTOBUF_DEP) $(BM_METADATA_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LDXX) $(LDFLAGS) $(BM_METADATA_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_metadata
+	$(Q) $(LDXX) $(LDFLAGS) $(BM_METADATA_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_metadata
 
 endif
 
 endif
 
 $(BM_METADATA_OBJS): CPPFLAGS += -Ithird_party/benchmark/include -DHAVE_POSIX_REGEX
-$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_metadata.o:  $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_metadata.o:  $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
 
 deps_bm_metadata: $(BM_METADATA_OBJS:.o=.dep)
 
@@ -15974,23 +16069,23 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/bm_pollset: protobuf_dep_error
 
 else
 
-$(BINDIR)/$(CONFIG)/bm_pollset: $(PROTOBUF_DEP) $(BM_POLLSET_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+$(BINDIR)/$(CONFIG)/bm_pollset: $(PROTOBUF_DEP) $(BM_POLLSET_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LDXX) $(LDFLAGS) $(BM_POLLSET_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_pollset
+	$(Q) $(LDXX) $(LDFLAGS) $(BM_POLLSET_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_pollset
 
 endif
 
 endif
 
 $(BM_POLLSET_OBJS): CPPFLAGS += -Ithird_party/benchmark/include -DHAVE_POSIX_REGEX
-$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_pollset.o:  $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_pollset.o:  $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_config.a
 
 deps_bm_pollset: $(BM_POLLSET_OBJS:.o=.dep)
 
@@ -16018,7 +16113,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/byte_stream_test: protobuf_dep_error
 
@@ -16061,7 +16156,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/channel_arguments_test: protobuf_dep_error
 
@@ -16104,7 +16199,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/channel_filter_test: protobuf_dep_error
 
@@ -16148,7 +16243,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/channel_trace_test: protobuf_dep_error
 
@@ -16194,7 +16289,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/check_gcp_environment_linux_test: protobuf_dep_error
 
@@ -16237,7 +16332,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/check_gcp_environment_windows_test: protobuf_dep_error
 
@@ -16280,7 +16375,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/chttp2_settings_timeout_test: protobuf_dep_error
 
@@ -16323,7 +16418,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/cli_call_test: protobuf_dep_error
 
@@ -16367,7 +16462,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/client_channel_stress_test: protobuf_dep_error
 
@@ -16413,7 +16508,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/client_crash_test: protobuf_dep_error
 
@@ -16456,7 +16551,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/client_crash_test_server: protobuf_dep_error
 
@@ -16499,7 +16594,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/client_lb_end2end_test: protobuf_dep_error
 
@@ -16529,7 +16624,9 @@
     $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc \
     $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc \
     $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc \
-    $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc \
+    $(GENDIR)/src/proto/grpc/testing/benchmark_service.pb.cc $(GENDIR)/src/proto/grpc/testing/benchmark_service.grpc.pb.cc \
+    $(GENDIR)/src/proto/grpc/testing/report_qps_scenario_service.pb.cc $(GENDIR)/src/proto/grpc/testing/report_qps_scenario_service.grpc.pb.cc \
+    $(GENDIR)/src/proto/grpc/testing/worker_service.pb.cc $(GENDIR)/src/proto/grpc/testing/worker_service.grpc.pb.cc \
     $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc \
     test/cpp/codegen/codegen_test_full.cc \
 
@@ -16547,7 +16644,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/codegen_test_full: protobuf_dep_error
 
@@ -16568,7 +16665,11 @@
 
 $(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/payloads.o:  $(LIBDIR)/$(CONFIG)/libgrpc++_core_stats.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
 
-$(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/services.o:  $(LIBDIR)/$(CONFIG)/libgrpc++_core_stats.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
+$(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/benchmark_service.o:  $(LIBDIR)/$(CONFIG)/libgrpc++_core_stats.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+$(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/report_qps_scenario_service.o:  $(LIBDIR)/$(CONFIG)/libgrpc++_core_stats.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+$(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/worker_service.o:  $(LIBDIR)/$(CONFIG)/libgrpc++_core_stats.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
 
 $(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/stats.o:  $(LIBDIR)/$(CONFIG)/libgrpc++_core_stats.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
 
@@ -16581,14 +16682,16 @@
 -include $(CODEGEN_TEST_FULL_OBJS:.o=.dep)
 endif
 endif
-$(OBJDIR)/$(CONFIG)/test/cpp/codegen/codegen_test_full.o: $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc
+$(OBJDIR)/$(CONFIG)/test/cpp/codegen/codegen_test_full.o: $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/benchmark_service.pb.cc $(GENDIR)/src/proto/grpc/testing/benchmark_service.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/report_qps_scenario_service.pb.cc $(GENDIR)/src/proto/grpc/testing/report_qps_scenario_service.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/worker_service.pb.cc $(GENDIR)/src/proto/grpc/testing/worker_service.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc
 
 
 CODEGEN_TEST_MINIMAL_SRC = \
     $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc \
     $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc \
     $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc \
-    $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc \
+    $(GENDIR)/src/proto/grpc/testing/benchmark_service.pb.cc $(GENDIR)/src/proto/grpc/testing/benchmark_service.grpc.pb.cc \
+    $(GENDIR)/src/proto/grpc/testing/report_qps_scenario_service.pb.cc $(GENDIR)/src/proto/grpc/testing/report_qps_scenario_service.grpc.pb.cc \
+    $(GENDIR)/src/proto/grpc/testing/worker_service.pb.cc $(GENDIR)/src/proto/grpc/testing/worker_service.grpc.pb.cc \
     $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc \
     test/cpp/codegen/codegen_test_minimal.cc \
     src/cpp/codegen/codegen_init.cc \
@@ -16607,7 +16710,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/codegen_test_minimal: protobuf_dep_error
 
@@ -16628,7 +16731,11 @@
 
 $(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/payloads.o:  $(LIBDIR)/$(CONFIG)/libgrpc++_core_stats.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
 
-$(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/services.o:  $(LIBDIR)/$(CONFIG)/libgrpc++_core_stats.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
+$(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/benchmark_service.o:  $(LIBDIR)/$(CONFIG)/libgrpc++_core_stats.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+$(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/report_qps_scenario_service.o:  $(LIBDIR)/$(CONFIG)/libgrpc++_core_stats.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+$(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/worker_service.o:  $(LIBDIR)/$(CONFIG)/libgrpc++_core_stats.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
 
 $(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/stats.o:  $(LIBDIR)/$(CONFIG)/libgrpc++_core_stats.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr.a
 
@@ -16643,8 +16750,8 @@
 -include $(CODEGEN_TEST_MINIMAL_OBJS:.o=.dep)
 endif
 endif
-$(OBJDIR)/$(CONFIG)/test/cpp/codegen/codegen_test_minimal.o: $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc
-$(OBJDIR)/$(CONFIG)/src/cpp/codegen/codegen_init.o: $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/services.pb.cc $(GENDIR)/src/proto/grpc/testing/services.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc
+$(OBJDIR)/$(CONFIG)/test/cpp/codegen/codegen_test_minimal.o: $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/benchmark_service.pb.cc $(GENDIR)/src/proto/grpc/testing/benchmark_service.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/report_qps_scenario_service.pb.cc $(GENDIR)/src/proto/grpc/testing/report_qps_scenario_service.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/worker_service.pb.cc $(GENDIR)/src/proto/grpc/testing/worker_service.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc
+$(OBJDIR)/$(CONFIG)/src/cpp/codegen/codegen_init.o: $(GENDIR)/src/proto/grpc/testing/control.pb.cc $(GENDIR)/src/proto/grpc/testing/control.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.pb.cc $(GENDIR)/src/proto/grpc/testing/messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.pb.cc $(GENDIR)/src/proto/grpc/testing/payloads.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/benchmark_service.pb.cc $(GENDIR)/src/proto/grpc/testing/benchmark_service.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/report_qps_scenario_service.pb.cc $(GENDIR)/src/proto/grpc/testing/report_qps_scenario_service.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/worker_service.pb.cc $(GENDIR)/src/proto/grpc/testing/worker_service.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.pb.cc $(GENDIR)/src/proto/grpc/testing/stats.grpc.pb.cc
 
 
 CREDENTIALS_TEST_SRC = \
@@ -16664,7 +16771,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/credentials_test: protobuf_dep_error
 
@@ -16707,7 +16814,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/cxx_byte_buffer_test: protobuf_dep_error
 
@@ -16750,7 +16857,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/cxx_slice_test: protobuf_dep_error
 
@@ -16793,7 +16900,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/cxx_string_ref_test: protobuf_dep_error
 
@@ -16836,7 +16943,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/cxx_time_test: protobuf_dep_error
 
@@ -16879,7 +16986,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/end2end_test: protobuf_dep_error
 
@@ -16923,7 +17030,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/error_details_test: protobuf_dep_error
 
@@ -16969,7 +17076,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/exception_test: protobuf_dep_error
 
@@ -17012,7 +17119,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/filter_end2end_test: protobuf_dep_error
 
@@ -17055,7 +17162,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/generic_end2end_test: protobuf_dep_error
 
@@ -17099,7 +17206,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/golden_file_test: protobuf_dep_error
 
@@ -17145,7 +17252,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/grpc_alts_credentials_options_test: protobuf_dep_error
 
@@ -17188,7 +17295,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/grpc_cli: protobuf_dep_error
 
@@ -17223,7 +17330,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/grpc_cpp_plugin: protobuf_dep_error
 
@@ -17254,7 +17361,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/grpc_csharp_plugin: protobuf_dep_error
 
@@ -17285,7 +17392,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/grpc_node_plugin: protobuf_dep_error
 
@@ -17316,7 +17423,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/grpc_objective_c_plugin: protobuf_dep_error
 
@@ -17347,7 +17454,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/grpc_php_plugin: protobuf_dep_error
 
@@ -17378,7 +17485,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/grpc_python_plugin: protobuf_dep_error
 
@@ -17409,7 +17516,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/grpc_ruby_plugin: protobuf_dep_error
 
@@ -17450,7 +17557,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/grpc_tool_test: protobuf_dep_error
 
@@ -17499,7 +17606,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/grpclb_api_test: protobuf_dep_error
 
@@ -17546,7 +17653,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/grpclb_end2end_test: protobuf_dep_error
 
@@ -17592,7 +17699,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/h2_ssl_cert_test: protobuf_dep_error
 
@@ -17635,7 +17742,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/h2_ssl_session_reuse_test: protobuf_dep_error
 
@@ -17678,7 +17785,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/health_service_end2end_test: protobuf_dep_error
 
@@ -17717,7 +17824,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/http2_client: protobuf_dep_error
 
@@ -17752,7 +17859,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/hybrid_end2end_test: protobuf_dep_error
 
@@ -17795,7 +17902,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/inlined_vector_test: protobuf_dep_error
 
@@ -17838,7 +17945,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/inproc_sync_unary_ping_pong_test: protobuf_dep_error
 
@@ -17877,7 +17984,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/interop_client: protobuf_dep_error
 
@@ -17908,7 +18015,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/interop_server: protobuf_dep_error
 
@@ -17943,7 +18050,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/interop_test: protobuf_dep_error
 
@@ -17986,7 +18093,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/json_run_localhost: protobuf_dep_error
 
@@ -18012,6 +18119,49 @@
 endif
 
 
+LB_LOAD_DATA_STORE_TEST_SRC = \
+    test/cpp/server/load_reporter/load_data_store_test.cc \
+
+LB_LOAD_DATA_STORE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(LB_LOAD_DATA_STORE_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/lb_load_data_store_test: openssl_dep_error
+
+else
+
+
+
+
+ifeq ($(NO_PROTOBUF),true)
+
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
+
+$(BINDIR)/$(CONFIG)/lb_load_data_store_test: protobuf_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/lb_load_data_store_test: $(PROTOBUF_DEP) $(LB_LOAD_DATA_STORE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/liblb_load_data_store.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LDXX) $(LDFLAGS) $(LB_LOAD_DATA_STORE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/liblb_load_data_store.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/lb_load_data_store_test
+
+endif
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/cpp/server/load_reporter/load_data_store_test.o:  $(LIBDIR)/$(CONFIG)/liblb_load_data_store.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_lb_load_data_store_test: $(LB_LOAD_DATA_STORE_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(LB_LOAD_DATA_STORE_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
 MEMORY_TEST_SRC = \
     test/core/gprpp/memory_test.cc \
 
@@ -18029,7 +18179,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/memory_test: protobuf_dep_error
 
@@ -18073,7 +18223,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/metrics_client: protobuf_dep_error
 
@@ -18119,7 +18269,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/mock_test: protobuf_dep_error
 
@@ -18162,7 +18312,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/nonblocking_test: protobuf_dep_error
 
@@ -18205,7 +18355,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/noop-benchmark: protobuf_dep_error
 
@@ -18249,7 +18399,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/orphanable_test: protobuf_dep_error
 
@@ -18292,7 +18442,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/proto_server_reflection_test: protobuf_dep_error
 
@@ -18335,7 +18485,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/proto_utils_test: protobuf_dep_error
 
@@ -18378,7 +18528,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/qps_interarrival_test: protobuf_dep_error
 
@@ -18421,7 +18571,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/qps_json_driver: protobuf_dep_error
 
@@ -18464,7 +18614,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/qps_openloop_test: protobuf_dep_error
 
@@ -18507,7 +18657,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/qps_worker: protobuf_dep_error
 
@@ -18553,7 +18703,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/reconnect_interop_client: protobuf_dep_error
 
@@ -18606,7 +18756,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/reconnect_interop_server: protobuf_dep_error
 
@@ -18656,7 +18806,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/ref_counted_ptr_test: protobuf_dep_error
 
@@ -18699,7 +18849,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/ref_counted_test: protobuf_dep_error
 
@@ -18725,6 +18875,49 @@
 endif
 
 
+RETRY_THROTTLE_TEST_SRC = \
+    test/core/client_channel/retry_throttle_test.cc \
+
+RETRY_THROTTLE_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(RETRY_THROTTLE_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/retry_throttle_test: openssl_dep_error
+
+else
+
+
+
+
+ifeq ($(NO_PROTOBUF),true)
+
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
+
+$(BINDIR)/$(CONFIG)/retry_throttle_test: protobuf_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/retry_throttle_test: $(PROTOBUF_DEP) $(RETRY_THROTTLE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LDXX) $(LDFLAGS) $(RETRY_THROTTLE_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/retry_throttle_test
+
+endif
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/client_channel/retry_throttle_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_retry_throttle_test: $(RETRY_THROTTLE_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(RETRY_THROTTLE_TEST_OBJS:.o=.dep)
+endif
+endif
+
+
 SECURE_AUTH_CONTEXT_TEST_SRC = \
     test/cpp/common/secure_auth_context_test.cc \
 
@@ -18742,7 +18935,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/secure_auth_context_test: protobuf_dep_error
 
@@ -18785,7 +18978,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/secure_sync_unary_ping_pong_test: protobuf_dep_error
 
@@ -18828,7 +19021,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/server_builder_plugin_test: protobuf_dep_error
 
@@ -18873,7 +19066,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/server_builder_test: protobuf_dep_error
 
@@ -18904,6 +19097,56 @@
 $(OBJDIR)/$(CONFIG)/test/cpp/server/server_builder_test.o: $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.grpc.pb.cc
 
 
+SERVER_BUILDER_WITH_SOCKET_MUTATOR_TEST_SRC = \
+    $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc \
+    $(GENDIR)/src/proto/grpc/testing/echo.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.grpc.pb.cc \
+    test/cpp/server/server_builder_with_socket_mutator_test.cc \
+
+SERVER_BUILDER_WITH_SOCKET_MUTATOR_TEST_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(SERVER_BUILDER_WITH_SOCKET_MUTATOR_TEST_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/server_builder_with_socket_mutator_test: openssl_dep_error
+
+else
+
+
+
+
+ifeq ($(NO_PROTOBUF),true)
+
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
+
+$(BINDIR)/$(CONFIG)/server_builder_with_socket_mutator_test: protobuf_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/server_builder_with_socket_mutator_test: $(PROTOBUF_DEP) $(SERVER_BUILDER_WITH_SOCKET_MUTATOR_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LDXX) $(LDFLAGS) $(SERVER_BUILDER_WITH_SOCKET_MUTATOR_TEST_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/server_builder_with_socket_mutator_test
+
+endif
+
+endif
+
+$(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/echo_messages.o:  $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+$(OBJDIR)/$(CONFIG)/src/proto/grpc/testing/echo.o:  $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+$(OBJDIR)/$(CONFIG)/test/cpp/server/server_builder_with_socket_mutator_test.o:  $(LIBDIR)/$(CONFIG)/libgrpc++_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.a $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_server_builder_with_socket_mutator_test: $(SERVER_BUILDER_WITH_SOCKET_MUTATOR_TEST_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(SERVER_BUILDER_WITH_SOCKET_MUTATOR_TEST_OBJS:.o=.dep)
+endif
+endif
+$(OBJDIR)/$(CONFIG)/test/cpp/server/server_builder_with_socket_mutator_test.o: $(GENDIR)/src/proto/grpc/testing/echo_messages.pb.cc $(GENDIR)/src/proto/grpc/testing/echo_messages.grpc.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.pb.cc $(GENDIR)/src/proto/grpc/testing/echo.grpc.pb.cc
+
+
 SERVER_CONTEXT_TEST_SPOUSE_TEST_SRC = \
     test/cpp/test/server_context_test_spouse_test.cc \
 
@@ -18921,7 +19164,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/server_context_test_spouse_test: protobuf_dep_error
 
@@ -18964,7 +19207,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/server_crash_test: protobuf_dep_error
 
@@ -19007,7 +19250,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/server_crash_test_client: protobuf_dep_error
 
@@ -19050,7 +19293,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/server_early_return_test: protobuf_dep_error
 
@@ -19095,7 +19338,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/server_request_call_test: protobuf_dep_error
 
@@ -19143,7 +19386,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/shutdown_test: protobuf_dep_error
 
@@ -19186,7 +19429,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/slice_hash_table_test: protobuf_dep_error
 
@@ -19229,7 +19472,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/slice_weak_hash_table_test: protobuf_dep_error
 
@@ -19272,7 +19515,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/stats_test: protobuf_dep_error
 
@@ -19315,7 +19558,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/status_metadata_test: protobuf_dep_error
 
@@ -19358,7 +19601,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/status_util_test: protobuf_dep_error
 
@@ -19401,7 +19644,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/streaming_throughput_test: protobuf_dep_error
 
@@ -19451,7 +19694,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/stress_test: protobuf_dep_error
 
@@ -19512,7 +19755,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/thread_manager_test: protobuf_dep_error
 
@@ -19555,7 +19798,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/thread_stress_test: protobuf_dep_error
 
@@ -19598,7 +19841,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/transport_pid_controller_test: protobuf_dep_error
 
@@ -19641,7 +19884,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/transport_security_common_api_test: protobuf_dep_error
 
@@ -19684,7 +19927,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/writes_per_rpc_test: protobuf_dep_error
 
@@ -19857,7 +20100,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_crypto_test_data: protobuf_dep_error
 
@@ -19897,7 +20140,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_asn1_test: protobuf_dep_error
 
@@ -19937,7 +20180,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_base64_test: protobuf_dep_error
 
@@ -19977,7 +20220,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_bio_test: protobuf_dep_error
 
@@ -20017,7 +20260,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_buf_test: protobuf_dep_error
 
@@ -20057,7 +20300,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_bytestring_test: protobuf_dep_error
 
@@ -20097,7 +20340,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_chacha_test: protobuf_dep_error
 
@@ -20137,7 +20380,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_aead_test: protobuf_dep_error
 
@@ -20177,7 +20420,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_cipher_test: protobuf_dep_error
 
@@ -20217,7 +20460,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_cmac_test: protobuf_dep_error
 
@@ -20257,7 +20500,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_compiler_test: protobuf_dep_error
 
@@ -20297,7 +20540,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_constant_time_test: protobuf_dep_error
 
@@ -20337,7 +20580,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_ed25519_test: protobuf_dep_error
 
@@ -20377,7 +20620,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_spake25519_test: protobuf_dep_error
 
@@ -20417,7 +20660,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_x25519_test: protobuf_dep_error
 
@@ -20457,7 +20700,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_dh_test: protobuf_dep_error
 
@@ -20497,7 +20740,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_digest_test: protobuf_dep_error
 
@@ -20537,7 +20780,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_dsa_test: protobuf_dep_error
 
@@ -20577,7 +20820,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_ecdh_test: protobuf_dep_error
 
@@ -20617,7 +20860,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_err_test: protobuf_dep_error
 
@@ -20657,7 +20900,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_evp_extra_test: protobuf_dep_error
 
@@ -20697,7 +20940,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_evp_test: protobuf_dep_error
 
@@ -20737,7 +20980,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_pbkdf_test: protobuf_dep_error
 
@@ -20777,7 +21020,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_scrypt_test: protobuf_dep_error
 
@@ -20817,7 +21060,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_aes_test: protobuf_dep_error
 
@@ -20857,7 +21100,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_bn_test: protobuf_dep_error
 
@@ -20897,7 +21140,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_ec_test: protobuf_dep_error
 
@@ -20937,7 +21180,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_p256-x86_64_test: protobuf_dep_error
 
@@ -20977,7 +21220,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_ecdsa_test: protobuf_dep_error
 
@@ -21017,7 +21260,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_gcm_test: protobuf_dep_error
 
@@ -21057,7 +21300,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_ctrdrbg_test: protobuf_dep_error
 
@@ -21097,7 +21340,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_hkdf_test: protobuf_dep_error
 
@@ -21137,7 +21380,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_hmac_test: protobuf_dep_error
 
@@ -21177,7 +21420,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_lhash_test: protobuf_dep_error
 
@@ -21217,7 +21460,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_obj_test: protobuf_dep_error
 
@@ -21257,7 +21500,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_pkcs7_test: protobuf_dep_error
 
@@ -21297,7 +21540,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_pkcs12_test: protobuf_dep_error
 
@@ -21337,7 +21580,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_pkcs8_test: protobuf_dep_error
 
@@ -21377,7 +21620,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_poly1305_test: protobuf_dep_error
 
@@ -21417,7 +21660,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_pool_test: protobuf_dep_error
 
@@ -21457,7 +21700,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_refcount_test: protobuf_dep_error
 
@@ -21497,7 +21740,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_rsa_test: protobuf_dep_error
 
@@ -21537,7 +21780,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_file_test_gtest: protobuf_dep_error
 
@@ -21577,7 +21820,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_gtest_main: protobuf_dep_error
 
@@ -21617,7 +21860,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_thread_test: protobuf_dep_error
 
@@ -21657,7 +21900,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_x509_test: protobuf_dep_error
 
@@ -21697,7 +21940,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_tab_test: protobuf_dep_error
 
@@ -21737,7 +21980,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_v3name_test: protobuf_dep_error
 
@@ -21777,7 +22020,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_span_test: protobuf_dep_error
 
@@ -21817,7 +22060,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/boringssl_ssl_test: protobuf_dep_error
 
@@ -23051,7 +23294,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/resolver_component_test_unsecure: protobuf_dep_error
 
@@ -23094,7 +23337,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/resolver_component_test: protobuf_dep_error
 
@@ -23137,7 +23380,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/resolver_component_tests_runner_invoker_unsecure: protobuf_dep_error
 
@@ -23180,7 +23423,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/resolver_component_tests_runner_invoker: protobuf_dep_error
 
@@ -23223,7 +23466,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/address_sorting_test_unsecure: protobuf_dep_error
 
@@ -23266,7 +23509,7 @@
 
 ifeq ($(NO_PROTOBUF),true)
 
-# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
 $(BINDIR)/$(CONFIG)/address_sorting_test: protobuf_dep_error
 
@@ -23292,6 +23535,41 @@
 endif
 
 
+ALTS_CREDENTIALS_FUZZER_ONE_ENTRY_SRC = \
+    test/core/security/alts_credentials_fuzzer.cc \
+    test/core/util/one_corpus_entry_fuzzer.cc \
+
+ALTS_CREDENTIALS_FUZZER_ONE_ENTRY_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(ALTS_CREDENTIALS_FUZZER_ONE_ENTRY_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/alts_credentials_fuzzer_one_entry: openssl_dep_error
+
+else
+
+
+
+$(BINDIR)/$(CONFIG)/alts_credentials_fuzzer_one_entry: $(ALTS_CREDENTIALS_FUZZER_ONE_ENTRY_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+	$(E) "[LD]      Linking $@"
+	$(Q) mkdir -p `dirname $@`
+	$(Q) $(LD) $(LDFLAGS) $(ALTS_CREDENTIALS_FUZZER_ONE_ENTRY_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/alts_credentials_fuzzer_one_entry
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/core/security/alts_credentials_fuzzer.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+$(OBJDIR)/$(CONFIG)/test/core/util/one_corpus_entry_fuzzer.o:  $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_alts_credentials_fuzzer_one_entry: $(ALTS_CREDENTIALS_FUZZER_ONE_ENTRY_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(ALTS_CREDENTIALS_FUZZER_ONE_ENTRY_OBJS:.o=.dep)
+endif
+endif
+
+
 API_FUZZER_ONE_ENTRY_SRC = \
     test/core/end2end/fuzzers/api_fuzzer.cc \
     test/core/util/one_corpus_entry_fuzzer.cc \
@@ -23827,7 +24105,6 @@
 src/core/tsi/ssl/session_cache/ssl_session_openssl.cc: $(OPENSSL_DEP)
 src/core/tsi/ssl_transport_security.cc: $(OPENSSL_DEP)
 src/core/tsi/transport_security.cc: $(OPENSSL_DEP)
-src/core/tsi/transport_security_adapter.cc: $(OPENSSL_DEP)
 src/core/tsi/transport_security_grpc.cc: $(OPENSSL_DEP)
 src/cpp/client/cronet_credentials.cc: $(OPENSSL_DEP)
 src/cpp/client/secure_credentials.cc: $(OPENSSL_DEP)
@@ -23837,6 +24114,7 @@
 src/cpp/common/secure_create_auth_context.cc: $(OPENSSL_DEP)
 src/cpp/ext/proto_server_reflection.cc: $(OPENSSL_DEP)
 src/cpp/ext/proto_server_reflection_plugin.cc: $(OPENSSL_DEP)
+src/cpp/server/load_reporter/load_data_store.cc: $(OPENSSL_DEP)
 src/cpp/server/secure_server_credentials.cc: $(OPENSSL_DEP)
 src/cpp/util/core_stats.cc: $(OPENSSL_DEP)
 src/cpp/util/error_details.cc: $(OPENSSL_DEP)
diff --git a/PYTHON-MANIFEST.in b/PYTHON-MANIFEST.in
index 8be0af9..b30a1fb 100644
--- a/PYTHON-MANIFEST.in
+++ b/PYTHON-MANIFEST.in
@@ -4,10 +4,11 @@
 graft src/core
 graft src/boringssl
 graft include/grpc
+graft third_party/address_sorting
 graft third_party/boringssl
+graft third_party/cares
 graft third_party/nanopb
 graft third_party/zlib
-graft third_party/cares
 include src/python/grpcio/_spawn_patch.py
 include src/python/grpcio/commands.py
 include src/python/grpcio/grpc_version.py
diff --git a/README.md b/README.md
index e66c0b1..21a9910 100644
--- a/README.md
+++ b/README.md
@@ -39,6 +39,7 @@
 | Java                    | [grpc-java](http://github.com/grpc/grpc-java)        |
 | Go                      | [grpc-go](http://github.com/grpc/grpc-go)            |
 | NodeJS                  | [grpc-node](https://github.com/grpc/grpc-node)       |
+| WebJS                   | [grpc-web](https://github.com/grpc/grpc-web)         |
 | Dart                    | [grpc-dart](https://github.com/grpc/grpc-dart)       |
 
 See [MANIFEST.md](MANIFEST.md) for a listing of top-level items in the
diff --git a/Rakefile b/Rakefile
index 1eac37d..0068a3b 100755
--- a/Rakefile
+++ b/Rakefile
@@ -23,6 +23,12 @@
 
 # Add the extension compiler task
 Rake::ExtensionTask.new('grpc_c', spec) do |ext|
+  unless RUBY_PLATFORM =~ /darwin/
+    # TODO: also set "no_native to true" for mac if possible. As is,
+    # "no_native" can only be set if the RUBY_PLATFORM doing
+    # cross-compilation is contained in the "ext.cross_platform" array.
+    ext.no_native = true
+  end
   ext.source_pattern = '**/*.{c,h}'
   ext.ext_dir = File.join('src', 'ruby', 'ext', 'grpc')
   ext.lib_dir = File.join('src', 'ruby', 'lib', 'grpc')
diff --git a/bazel/generate_cc.bzl b/bazel/generate_cc.bzl
index e610123..ae747aa 100644
--- a/bazel/generate_cc.bzl
+++ b/bazel/generate_cc.bzl
@@ -10,7 +10,16 @@
   includes = [f for src in ctx.attr.srcs for f in src.proto.transitive_imports]
   outs = []
   # label_len is length of the path from WORKSPACE root to the location of this build file
-  label_len = len(ctx.label.package) + 1
+  label_len = 0
+  # proto_root is the directory relative to which generated include paths should be
+  proto_root = ""
+  if ctx.label.package:
+    # The +1 is for the trailing slash.
+    label_len += len(ctx.label.package) + 1
+  if ctx.label.workspace_root:
+    label_len += len(ctx.label.workspace_root) + 1
+    proto_root = "/" + ctx.label.workspace_root
+
   if ctx.executable.plugin:
     outs += [proto.path[label_len:-len(".proto")] + ".grpc.pb.h" for proto in protos]
     outs += [proto.path[label_len:-len(".proto")] + ".grpc.pb.cc" for proto in protos]
@@ -20,7 +29,7 @@
     outs += [proto.path[label_len:-len(".proto")] + ".pb.h" for proto in protos]
     outs += [proto.path[label_len:-len(".proto")] + ".pb.cc" for proto in protos]
   out_files = [ctx.new_file(out) for out in outs]
-  dir_out = str(ctx.genfiles_dir.path)
+  dir_out = str(ctx.genfiles_dir.path + proto_root)
 
   arguments = []
   if ctx.executable.plugin:
@@ -33,7 +42,20 @@
   else:
     arguments += ["--cpp_out=" + ",".join(ctx.attr.flags) + ":" + dir_out]
     additional_input = []
-  arguments += ["-I{0}={0}".format(include.path) for include in includes]
+
+  # Import protos relative to their workspace root so that protoc prints the
+  # right include paths.
+  for include in includes:
+    directory = include.path
+    if directory.startswith("external"):
+      external_sep = directory.find("/")
+      repository_sep = directory.find("/", external_sep + 1)
+      arguments += ["--proto_path=" + directory[:repository_sep]]
+    else:
+      arguments += ["--proto_path=."]
+  # Include the output directory so that protoc puts the generated code in the
+  # right directory.
+  arguments += ["--proto_path={0}{1}".format(dir_out, proto_root)]
   arguments += [proto.path for proto in protos]
 
   # create a list of well known proto files if the argument is non-None
diff --git a/bazel/grpc_deps.bzl b/bazel/grpc_deps.bzl
index a441c3f..3c69a6b 100644
--- a/bazel/grpc_deps.bzl
+++ b/bazel/grpc_deps.bzl
@@ -57,6 +57,16 @@
         actual = "@com_github_gflags_gflags//:gflags",
     )
 
+    native.bind(
+        name = "grpc_cpp_plugin",
+        actual = "@com_github_grpc_grpc//:grpc_cpp_plugin"
+    )
+
+    native.bind(
+        name = "grpc++_codegen_proto",
+        actual = "@com_github_grpc_grpc//:grpc++_codegen_proto"
+    )
+
     if "boringssl" not in native.existing_rules():
         native.http_archive(
             name = "boringssl",
@@ -75,8 +85,8 @@
     if "com_google_protobuf" not in native.existing_rules():
         native.http_archive(
             name = "com_google_protobuf",
-            strip_prefix = "protobuf-2761122b810fe8861004ae785cc3ab39f384d342",
-            url = "https://github.com/google/protobuf/archive/2761122b810fe8861004ae785cc3ab39f384d342.tar.gz",
+            strip_prefix = "protobuf-b5fbb742af122b565925987e65c08957739976a7",
+            url = "https://github.com/google/protobuf/archive/b5fbb742af122b565925987e65c08957739976a7.tar.gz",
         )
 
     if "com_github_google_googletest" not in native.existing_rules():
@@ -120,12 +130,12 @@
     if "com_github_bazelbuild_bazeltoolchains" not in native.existing_rules():
         native.http_archive(
             name = "com_github_bazelbuild_bazeltoolchains",
-            strip_prefix = "bazel-toolchains-b850ccdf53fed1ccab7670f52d6b297d74348d1b",
+            strip_prefix = "bazel-toolchains-44200e0c026d86c53470d107b3697a3e46469c43",
             urls = [
-                "https://mirror.bazel.build/github.com/bazelbuild/bazel-toolchains/archive/b850ccdf53fed1ccab7670f52d6b297d74348d1b.tar.gz",
-                "https://github.com/bazelbuild/bazel-toolchains/archive/b850ccdf53fed1ccab7670f52d6b297d74348d1b.tar.gz",
+                "https://mirror.bazel.build/github.com/bazelbuild/bazel-toolchains/archive/44200e0c026d86c53470d107b3697a3e46469c43.tar.gz",
+                "https://github.com/bazelbuild/bazel-toolchains/archive/44200e0c026d86c53470d107b3697a3e46469c43.tar.gz",
             ],
-            sha256 = "d84d6b2fe88ef99963febf91ddce33503eed14c155ace922e2122271b483be64",
+            sha256 = "699b55a6916c687f4b7dc092dbbf5f64672cde0dc965f79717735ec4e5416556",
         )
 
 # TODO: move some dependencies from "grpc_deps" here?
diff --git a/build.yaml b/build.yaml
index 88f2283..1bc2adb 100644
--- a/build.yaml
+++ b/build.yaml
@@ -13,8 +13,8 @@
   '#09': Per-language overrides are possible with (eg) ruby_version tag here
   '#10': See the expand_version.py for all the quirks here
   core_version: 6.0.0-dev
-  g_stands_for: gorgeous
-  version: 1.11.0-dev
+  g_stands_for: gloriosa
+  version: 1.13.0-dev
 filegroups:
 - name: alts_proto
   headers:
@@ -70,6 +70,8 @@
   - tsi_interface
   - tsi
 - name: alts_util
+  public_headers:
+  - include/grpc/grpc_security.h
   headers:
   - src/core/lib/security/credentials/alts/check_gcp_environment.h
   - src/core/lib/security/credentials/alts/grpc_alts_credentials_options.h
@@ -534,6 +536,14 @@
   uses:
   - grpc_codegen
   - grpc_trace_headers
+- name: grpc_client_authority_filter
+  headers:
+  - src/core/ext/filters/http/client_authority_filter.h
+  src:
+  - src/core/ext/filters/http/client_authority_filter.cc
+  plugin: grpc_client_authority_filter
+  uses:
+  - grpc_base
 - name: grpc_client_channel
   headers:
   - src/core/ext/filters/client_channel/backup_poller.h
@@ -618,6 +628,7 @@
 - name: grpc_lb_policy_grpclb
   headers:
   - src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.h
+  - src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h
   - src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h
   - src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h
   - src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h
@@ -638,6 +649,7 @@
 - name: grpc_lb_policy_grpclb_secure
   headers:
   - src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.h
+  - src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h
   - src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h
   - src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h
   - src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h
@@ -675,8 +687,6 @@
 - name: grpc_lb_subchannel_list
   headers:
   - src/core/ext/filters/client_channel/lb_policy/subchannel_list.h
-  src:
-  - src/core/ext/filters/client_channel/lb_policy/subchannel_list.cc
   uses:
   - grpc_base
   - grpc_client_channel
@@ -736,6 +746,7 @@
   public_headers:
   - include/grpc/grpc_security.h
   headers:
+  - src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h
   - src/core/lib/security/context/security_context.h
   - src/core/lib/security/credentials/alts/alts_credentials.h
   - src/core/lib/security/credentials/composite/composite_credentials.h
@@ -816,6 +827,7 @@
   - test/core/end2end/fixtures/proxy.h
   - test/core/iomgr/endpoint_tests.h
   - test/core/util/debugger_macros.h
+  - test/core/util/fuzzer_util.h
   - test/core/util/grpc_profiler.h
   - test/core/util/histogram.h
   - test/core/util/memory_counters.h
@@ -835,6 +847,7 @@
   - test/core/end2end/fixtures/proxy.cc
   - test/core/iomgr/endpoint_tests.cc
   - test/core/util/debugger_macros.cc
+  - test/core/util/fuzzer_util.cc
   - test/core/util/grpc_profiler.cc
   - test/core/util/histogram.cc
   - test/core/util/memory_counters.cc
@@ -929,8 +942,10 @@
   - gpr
 - name: grpc_transport_chttp2_client_connector
   headers:
+  - src/core/ext/transport/chttp2/client/authority.h
   - src/core/ext/transport/chttp2/client/chttp2_connector.h
   src:
+  - src/core/ext/transport/chttp2/client/authority.cc
   - src/core/ext/transport/chttp2/client/chttp2_connector.cc
   uses:
   - grpc_transport_chttp2
@@ -1065,11 +1080,9 @@
 - name: tsi_interface
   headers:
   - src/core/tsi/transport_security.h
-  - src/core/tsi/transport_security_adapter.h
   - src/core/tsi/transport_security_interface.h
   src:
   - src/core/tsi/transport_security.cc
-  - src/core/tsi/transport_security_adapter.cc
   deps:
   - gpr
   secure: true
@@ -1154,6 +1167,8 @@
   language: c++
   public_headers:
   - include/grpc++/impl/codegen/proto_utils.h
+  - include/grpcpp/impl/codegen/proto_buffer_reader.h
+  - include/grpcpp/impl/codegen/proto_buffer_writer.h
   - include/grpcpp/impl/codegen/proto_utils.h
   uses:
   - grpc++_codegen_base
@@ -1244,6 +1259,8 @@
   - include/grpcpp/support/byte_buffer.h
   - include/grpcpp/support/channel_arguments.h
   - include/grpcpp/support/config.h
+  - include/grpcpp/support/proto_buffer_reader.h
+  - include/grpcpp/support/proto_buffer_writer.h
   - include/grpcpp/support/slice.h
   - include/grpcpp/support/status.h
   - include/grpcpp/support/status_code_enum.h
@@ -1290,7 +1307,6 @@
   - src/cpp/server/server_posix.cc
   - src/cpp/thread_manager/thread_manager.cc
   - src/cpp/util/byte_buffer_cc.cc
-  - src/cpp/util/slice_cc.cc
   - src/cpp/util/status.cc
   - src/cpp/util/string_ref.cc
   - src/cpp/util/time_cc.cc
@@ -1389,6 +1405,7 @@
   - grpc_max_age_filter
   - grpc_message_size_filter
   - grpc_deadline_filter
+  - grpc_client_authority_filter
   - grpc_workaround_cronet_compression_filter
   - grpc_server_backward_compatibility
   generate_plugin_registry: true
@@ -1407,17 +1424,9 @@
   dll: true
   filegroups:
   - grpc_base
-  - grpc_base_headers
-  - grpc_deadline_filter
-  - grpc_lb_policy_pick_first
-  - grpc_max_age_filter
-  - grpc_message_size_filter
-  - grpc_resolver_dns_native
-  - grpc_resolver_sockaddr
-  - grpc_server_load_reporting
   - grpc_transport_cronet_client_secure
   - grpc_transport_chttp2_client_secure
-  - grpc_transport_chttp2_server_secure
+  - grpc_server_load_reporting
   generate_plugin_registry: true
   platforms:
   - linux
@@ -1499,6 +1508,7 @@
   - grpc_max_age_filter
   - grpc_message_size_filter
   - grpc_deadline_filter
+  - grpc_client_authority_filter
   - grpc_workaround_cronet_compression_filter
   - grpc_server_backward_compatibility
   generate_plugin_registry: true
@@ -1881,6 +1891,15 @@
   - test/cpp/interop/interop_server_bootstrap.cc
   deps:
   - interop_server_lib
+- name: lb_load_data_store
+  build: private
+  language: c++
+  headers:
+  - src/cpp/server/load_reporter/load_data_store.h
+  src:
+  - src/cpp/server/load_reporter/load_data_store.cc
+  deps:
+  - grpc++
 - name: qps
   build: private
   language: c++
@@ -1901,7 +1920,9 @@
   - src/proto/grpc/testing/payloads.proto
   - src/proto/grpc/testing/stats.proto
   - src/proto/grpc/testing/control.proto
-  - src/proto/grpc/testing/services.proto
+  - src/proto/grpc/testing/benchmark_service.proto
+  - src/proto/grpc/testing/report_qps_scenario_service.proto
+  - src/proto/grpc/testing/worker_service.proto
   - test/cpp/qps/benchmark_config.cc
   - test/cpp/qps/client_async.cc
   - test/cpp/qps/client_sync.cc
@@ -1970,6 +1991,19 @@
   - grpc
   - gpr_test_util
   - gpr
+- name: alts_credentials_fuzzer
+  build: fuzzer
+  language: c
+  src:
+  - test/core/security/alts_credentials_fuzzer.cc
+  deps:
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
+  corpus_dirs:
+  - test/core/security/corpus/alts_credentials_corpus
+  maxlen: 2048
 - name: api_fuzzer
   build: fuzzer
   language: c
@@ -2613,17 +2647,6 @@
   - grpc
   - gpr_test_util
   - gpr
-- name: grpc_invalid_channel_args_test
-  build: test
-  language: c
-  src:
-  - test/core/surface/invalid_channel_args_test.cc
-  deps:
-  - grpc_test_util
-  - grpc
-  - gpr_test_util
-  - gpr
-  uses_polling: false
 - name: grpc_json_token_test
   build: test
   language: c
@@ -3812,6 +3835,7 @@
   - grpc_unsecure
   - gpr_test_util
   - gpr
+  - grpc++_test_config
   benchmark: true
   defaults: benchmark
   platforms:
@@ -3833,6 +3857,7 @@
   - grpc_unsecure
   - gpr_test_util
   - gpr
+  - grpc++_test_config
   benchmark: true
   defaults: benchmark
   platforms:
@@ -3854,6 +3879,7 @@
   - grpc_unsecure
   - gpr_test_util
   - gpr
+  - grpc++_test_config
   benchmark: true
   defaults: benchmark
   platforms:
@@ -3875,6 +3901,7 @@
   - grpc_unsecure
   - gpr_test_util
   - gpr
+  - grpc++_test_config
   benchmark: true
   defaults: benchmark
   platforms:
@@ -3895,6 +3922,7 @@
   - grpc_unsecure
   - gpr_test_util
   - gpr
+  - grpc++_test_config
   benchmark: true
   defaults: benchmark
   platforms:
@@ -3915,6 +3943,7 @@
   - grpc_unsecure
   - gpr_test_util
   - gpr
+  - grpc++_test_config
   benchmark: true
   defaults: benchmark
   platforms:
@@ -3935,6 +3964,7 @@
   - grpc_unsecure
   - gpr_test_util
   - gpr
+  - grpc++_test_config
   benchmark: true
   defaults: benchmark
   platforms:
@@ -3955,6 +3985,7 @@
   - grpc_unsecure
   - gpr_test_util
   - gpr
+  - grpc++_test_config
   benchmark: true
   defaults: benchmark
   platforms:
@@ -3978,6 +4009,7 @@
   - grpc_unsecure
   - gpr_test_util
   - gpr
+  - grpc++_test_config
   benchmark: true
   defaults: benchmark
   excluded_poll_engines:
@@ -4004,6 +4036,7 @@
   - grpc_unsecure
   - gpr_test_util
   - gpr
+  - grpc++_test_config
   benchmark: true
   defaults: benchmark
   excluded_poll_engines:
@@ -4057,6 +4090,7 @@
   - grpc_unsecure
   - gpr_test_util
   - gpr
+  - grpc++_test_config
   benchmark: true
   defaults: benchmark
   excluded_poll_engines:
@@ -4081,6 +4115,7 @@
   - grpc_unsecure
   - gpr_test_util
   - gpr
+  - grpc++_test_config
   benchmark: true
   defaults: benchmark
   platforms:
@@ -4102,6 +4137,7 @@
   - grpc_unsecure
   - gpr_test_util
   - gpr
+  - grpc++_test_config
   benchmark: true
   defaults: benchmark
   platforms:
@@ -4268,7 +4304,9 @@
   - src/proto/grpc/testing/control.proto
   - src/proto/grpc/testing/messages.proto
   - src/proto/grpc/testing/payloads.proto
-  - src/proto/grpc/testing/services.proto
+  - src/proto/grpc/testing/benchmark_service.proto
+  - src/proto/grpc/testing/report_qps_scenario_service.proto
+  - src/proto/grpc/testing/worker_service.proto
   - src/proto/grpc/testing/stats.proto
   - test/cpp/codegen/codegen_test_full.cc
   deps:
@@ -4287,7 +4325,9 @@
   - src/proto/grpc/testing/control.proto
   - src/proto/grpc/testing/messages.proto
   - src/proto/grpc/testing/payloads.proto
-  - src/proto/grpc/testing/services.proto
+  - src/proto/grpc/testing/benchmark_service.proto
+  - src/proto/grpc/testing/report_qps_scenario_service.proto
+  - src/proto/grpc/testing/worker_service.proto
   - src/proto/grpc/testing/stats.proto
   - test/cpp/codegen/codegen_test_minimal.cc
   deps:
@@ -4749,6 +4789,20 @@
   - mac
   - linux
   - posix
+- name: lb_load_data_store_test
+  gtest: true
+  build: test
+  language: c++
+  src:
+  - test/cpp/server/load_reporter/load_data_store_test.cc
+  deps:
+  - lb_load_data_store
+  - grpc++_test_util
+  - grpc_test_util
+  - grpc++
+  - grpc
+  - gpr_test_util
+  - gpr
 - name: memory_test
   gtest: true
   build: test
@@ -4996,6 +5050,18 @@
   - gpr
   uses:
   - grpc++_test
+- name: retry_throttle_test
+  gtest: true
+  build: test
+  language: c++
+  src:
+  - test/core/client_channel/retry_throttle_test.cc
+  deps:
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
+  uses_polling: false
 - name: secure_auth_context_test
   gtest: true
   build: test
@@ -5056,6 +5122,23 @@
   - grpc++_unsecure
   - grpc_unsecure
   - gpr
+- name: server_builder_with_socket_mutator_test
+  gtest: true
+  build: test
+  language: c++
+  src:
+  - src/proto/grpc/testing/echo_messages.proto
+  - src/proto/grpc/testing/echo.proto
+  - test/cpp/server/server_builder_with_socket_mutator_test.cc
+  deps:
+  - grpc++_test_util_unsecure
+  - grpc_test_util_unsecure
+  - gpr_test_util
+  - grpc++_unsecure
+  - grpc_unsecure
+  - gpr
+  platforms:
+  - posix
 - name: server_context_test_spouse_test
   gtest: true
   build: test
diff --git a/config.m4 b/config.m4
index d7cda0b..ee2aca4 100644
--- a/config.m4
+++ b/config.m4
@@ -8,6 +8,7 @@
   PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/include)
   PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/src/php/ext/grpc)
   PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/boringssl/include)
+  PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/address_sorting/include)
 
   LIBS="-lpthread $LIBS"
 
@@ -320,9 +321,9 @@
     third_party/nanopb/pb_decode.c \
     third_party/nanopb/pb_encode.c \
     src/core/tsi/transport_security.cc \
-    src/core/tsi/transport_security_adapter.cc \
     src/core/ext/transport/chttp2/client/insecure/channel_create.cc \
     src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc \
+    src/core/ext/transport/chttp2/client/authority.cc \
     src/core/ext/transport/chttp2/client/chttp2_connector.cc \
     src/core/ext/filters/client_channel/backup_poller.cc \
     src/core/ext/filters/client_channel/channel_connectivity.cc \
@@ -367,7 +368,6 @@
     src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c \
     src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc \
     src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc \
-    src/core/ext/filters/client_channel/lb_policy/subchannel_list.cc \
     src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc \
     src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc \
     src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc \
@@ -380,6 +380,7 @@
     src/core/ext/census/grpc_context.cc \
     src/core/ext/filters/max_age/max_age_filter.cc \
     src/core/ext/filters/message_size/message_size_filter.cc \
+    src/core/ext/filters/http/client_authority_filter.cc \
     src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc \
     src/core/ext/filters/workarounds/workaround_utils.cc \
     src/core/plugin_registry/grpc_plugin_registry.cc \
@@ -647,7 +648,6 @@
   PHP_ADD_BUILD_DIR($ext_builddir/src/boringssl)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/census)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel)
-  PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/lb_policy)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/lb_policy/grpclb)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1)
   PHP_ADD_BUILD_DIR($ext_builddir/src/core/ext/filters/client_channel/lb_policy/pick_first)
diff --git a/config.w32 b/config.w32
index 5e80781..abca8e2 100644
--- a/config.w32
+++ b/config.w32
@@ -297,9 +297,9 @@
     "third_party\\nanopb\\pb_decode.c " +
     "third_party\\nanopb\\pb_encode.c " +
     "src\\core\\tsi\\transport_security.cc " +
-    "src\\core\\tsi\\transport_security_adapter.cc " +
     "src\\core\\ext\\transport\\chttp2\\client\\insecure\\channel_create.cc " +
     "src\\core\\ext\\transport\\chttp2\\client\\insecure\\channel_create_posix.cc " +
+    "src\\core\\ext\\transport\\chttp2\\client\\authority.cc " +
     "src\\core\\ext\\transport\\chttp2\\client\\chttp2_connector.cc " +
     "src\\core\\ext\\filters\\client_channel\\backup_poller.cc " +
     "src\\core\\ext\\filters\\client_channel\\channel_connectivity.cc " +
@@ -344,7 +344,6 @@
     "src\\core\\ext\\filters\\client_channel\\lb_policy\\grpclb\\proto\\grpc\\lb\\v1\\load_balancer.pb.c " +
     "src\\core\\ext\\filters\\client_channel\\resolver\\fake\\fake_resolver.cc " +
     "src\\core\\ext\\filters\\client_channel\\lb_policy\\pick_first\\pick_first.cc " +
-    "src\\core\\ext\\filters\\client_channel\\lb_policy\\subchannel_list.cc " +
     "src\\core\\ext\\filters\\client_channel\\lb_policy\\round_robin\\round_robin.cc " +
     "src\\core\\ext\\filters\\client_channel\\resolver\\dns\\c_ares\\dns_resolver_ares.cc " +
     "src\\core\\ext\\filters\\client_channel\\resolver\\dns\\c_ares\\grpc_ares_ev_driver_posix.cc " +
@@ -357,6 +356,7 @@
     "src\\core\\ext\\census\\grpc_context.cc " +
     "src\\core\\ext\\filters\\max_age\\max_age_filter.cc " +
     "src\\core\\ext\\filters\\message_size\\message_size_filter.cc " +
+    "src\\core\\ext\\filters\\http\\client_authority_filter.cc " +
     "src\\core\\ext\\filters\\workarounds\\workaround_cronet_compression_filter.cc " +
     "src\\core\\ext\\filters\\workarounds\\workaround_utils.cc " +
     "src\\core\\plugin_registry\\grpc_plugin_registry.cc " +
@@ -635,11 +635,13 @@
   EXTENSION("grpc", grpc_source, null,
     "/DOPENSSL_NO_ASM /D_GNU_SOURCE /DWIN32_LEAN_AND_MEAN "+
     "/D_HAS_EXCEPTIONS=0 /DNOMINMAX /DGRPC_ARES=0 /D_WIN32_WINNT=0x600 "+
+    "/DPB_FIELD_16BIT "+
     "/I"+configure_module_dirname+" "+
     "/I"+configure_module_dirname+"\\include "+
     "/I"+configure_module_dirname+"\\src\\php\\ext\\grpc "+
     "/I"+configure_module_dirname+"\\third_party\\boringssl\\include "+
-    "/I"+configure_module_dirname+"\\third_party\\zlib");
+    "/I"+configure_module_dirname+"\\third_party\\zlib "+
+    "/I"+configure_module_dirname+"\\third_party\\address_sorting\\include");
 
   base_dir = get_define('BUILD_DIR');
   FSO.CreateFolder(base_dir+"\\ext");
diff --git a/doc/PROTOCOL-WEB.md b/doc/PROTOCOL-WEB.md
index c31a048..5100c9b 100644
--- a/doc/PROTOCOL-WEB.md
+++ b/doc/PROTOCOL-WEB.md
@@ -29,7 +29,7 @@
 * evolve over time, mainly to optimize for browser clients or support
 web-specific features such as CORS, XSRF
 * become optional (in 1-2 years) when browsers are able to speak the native
-gRPC protocol via the new [whatwg fetch/streams API](https://github.com/whatwg/fetch)
+gRPC protocol via the new [whatwg streams API](https://github.com/whatwg/streams)
 
 # Protocol differences vs [gRPC over HTTP2](PROTOCOL-HTTP2.md)
 
@@ -106,19 +106,6 @@
 
 # Other features
 
-Compression
-
-* Full-body compression is supported and expected for all unary
-requests/responses. The compression/decompression will be done
-by browsers, using standard Content-Encoding headers
-  * “grpc-encoding” header is not used
-  * SDCH, Brotli will be supported
-* Message-level compression for streamed requests/responses is not supported
-because manual compression/decompression is prohibitively expensive using JS
-  * Per-message compression may be feasible in future with wasm
-
----
-
 Retries, caching
 
 * Will spec out the support after their respective gRPC spec extensions
@@ -128,24 +115,6 @@
 
 ---
 
-Security
-
-* XSRF, XSS etc to be specified
-
----
-
-CORS preflight
-
-* Should follow the [CORS spec](https://developer.mozilla.org/en-US/docs/Web/HTTP/Server-Side_Access_Control)
-  * Access-Control-Allow-Credentials to allow Authorization headers
-  * Access-Control-Allow-Methods to allow POST and (preflight) OPTIONS only
-  * Access-Control-Allow-Headers to whatever the preflight request carries
-* The client library may support header overwrites to avoid preflight
-  * https://github.com/whatwg/fetch/issues/210
-* CSP support to be specified
-
----
-
 Keep-alive
 
 * HTTP/2 PING is not supported or used
@@ -165,3 +134,8 @@
 
 * Special headers may be introduced to support features that may break compatiblity.
 
+---
+
+Browser-specific features
+
+* For features that are unique to browser or HTML clients, check the [spec doc](https://github.com/grpc/grpc-web/blob/master/PROTOCOL-WEB.md) published in the grpc/grpc-web repo.
diff --git a/doc/environment_variables.md b/doc/environment_variables.md
index ed46a48..587ab83 100644
--- a/doc/environment_variables.md
+++ b/doc/environment_variables.md
@@ -50,6 +50,7 @@
   - channel_stack_builder - traces information about channel stacks being built
   - executor - traces grpc's internal thread pool ('the executor')
   - glb - traces the grpclb load balancer
+  - handshaker - traces handshaking state
   - http - traces state in the http2 transport engine
   - http2_stream_state - traces all http2 stream state mutations.
   - http1 - traces HTTP/1.x operations performed by gRPC
diff --git a/doc/g_stands_for.md b/doc/g_stands_for.md
index 47ae7c5..8b9cf91 100644
--- a/doc/g_stands_for.md
+++ b/doc/g_stands_for.md
@@ -1,17 +1,15 @@
-Each version of gRPC gets a new description of what the 'g' stands for, since
-we've never really been able to figure it out.
+'g' stands for something different every gRPC release:
 
-Below is a list of already-used definitions (that should not be repeated in the
-future), and the corresponding version numbers that used them:
-
-- 1.0 'g' stands for 'gRPC'
-- 1.1 'g' stands for 'good'
-- 1.2 'g' stands for 'green'
-- 1.3 'g' stands for 'gentle'
-- 1.4 'g' stands for 'gregarious'
-- 1.6 'g' stands for 'garcia'
-- 1.7 'g' stands for 'gambit'
-- 1.8 'g' stands for 'generous'
-- 1.9 'g' stands for 'glossy'
-- 1.10 'g' stands for 'glamorous'
-- 1.11 'g' stands for 'gorgeous'
+- 1.0 'g' stands for ['gRPC'](https://github.com/grpc/grpc/tree/v1.0.x)
+- 1.1 'g' stands for ['good'](https://github.com/grpc/grpc/tree/v1.1.x)
+- 1.2 'g' stands for ['green'](https://github.com/grpc/grpc/tree/v1.2.x)
+- 1.3 'g' stands for ['gentle'](https://github.com/grpc/grpc/tree/v1.3.x)
+- 1.4 'g' stands for ['gregarious'](https://github.com/grpc/grpc/tree/v1.4.x)
+- 1.6 'g' stands for ['garcia'](https://github.com/grpc/grpc/tree/v1.6.x)
+- 1.7 'g' stands for ['gambit'](https://github.com/grpc/grpc/tree/v1.7.x)
+- 1.8 'g' stands for ['generous'](https://github.com/grpc/grpc/tree/v1.8.x)
+- 1.9 'g' stands for ['glossy'](https://github.com/grpc/grpc/tree/v1.9.x)
+- 1.10 'g' stands for ['glamorous'](https://github.com/grpc/grpc/tree/v1.10.x)
+- 1.11 'g' stands for ['gorgeous'](https://github.com/grpc/grpc/tree/v1.11.x)
+- 1.12 'g' stands for ['glorious'](https://github.com/grpc/grpc/tree/v1.12.x)
+- 1.13 'g' stands for ['gloriosa'](https://github.com/grpc/grpc/tree/master)
diff --git a/etc/roots.pem b/etc/roots.pem
index 15d819b..5dbd1ae 100644
--- a/etc/roots.pem
+++ b/etc/roots.pem
@@ -3525,39 +3525,6 @@
 5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su
 -----END CERTIFICATE-----
 
-# Issuer: CN=TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı H5 O=TÜRKTRUST Bilgi İletişim ve Bilişim Güvenliği Hizmetleri A.Ş.
-# Subject: CN=TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı H5 O=TÜRKTRUST Bilgi İletişim ve Bilişim Güvenliği Hizmetleri A.Ş.
-# Label: "TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı H5"
-# Serial: 156233699172481
-# MD5 Fingerprint: da:70:8e:f0:22:df:93:26:f6:5f:9f:d3:15:06:52:4e
-# SHA1 Fingerprint: c4:18:f6:4d:46:d1:df:00:3d:27:30:13:72:43:a9:12:11:c6:75:fb
-# SHA256 Fingerprint: 49:35:1b:90:34:44:c1:85:cc:dc:5c:69:3d:24:d8:55:5c:b2:08:d6:a8:14:13:07:69:9f:4a:f0:63:19:9d:78
------BEGIN CERTIFICATE-----
-MIIEJzCCAw+gAwIBAgIHAI4X/iQggTANBgkqhkiG9w0BAQsFADCBsTELMAkGA1UE
-BhMCVFIxDzANBgNVBAcMBkFua2FyYTFNMEsGA1UECgxEVMOcUktUUlVTVCBCaWxn
-aSDEsGxldGnFn2ltIHZlIEJpbGnFn2ltIEfDvHZlbmxpxJ9pIEhpem1ldGxlcmkg
-QS7Fni4xQjBABgNVBAMMOVTDnFJLVFJVU1QgRWxla3Ryb25payBTZXJ0aWZpa2Eg
-SGl6bWV0IFNhxJ9sYXnEsWPEsXPEsSBINTAeFw0xMzA0MzAwODA3MDFaFw0yMzA0
-MjgwODA3MDFaMIGxMQswCQYDVQQGEwJUUjEPMA0GA1UEBwwGQW5rYXJhMU0wSwYD
-VQQKDERUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8
-dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLjFCMEAGA1UEAww5VMOcUktUUlVTVCBF
-bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIEg1MIIB
-IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApCUZ4WWe60ghUEoI5RHwWrom
-/4NZzkQqL/7hzmAD/I0Dpe3/a6i6zDQGn1k19uwsu537jVJp45wnEFPzpALFp/kR
-Gml1bsMdi9GYjZOHp3GXDSHHmflS0yxjXVW86B8BSLlg/kJK9siArs1mep5Fimh3
-4khon6La8eHBEJ/rPCmBp+EyCNSgBbGM+42WAA4+Jd9ThiI7/PS98wl+d+yG6w8z
-5UNP9FR1bSmZLmZaQ9/LXMrI5Tjxfjs1nQ/0xVqhzPMggCTTV+wVunUlm+hkS7M0
-hO8EuPbJbKoCPrZV4jI3X/xml1/N1p7HIL9Nxqw/dV8c7TKcfGkAaZHjIxhT6QID
-AQABo0IwQDAdBgNVHQ4EFgQUVpkHHtOsDGlktAxQR95DLL4gwPswDgYDVR0PAQH/
-BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAJ5FdnsX
-SDLyOIspve6WSk6BGLFRRyDN0GSxDsnZAdkJzsiZ3GglE9Rc8qPoBP5yCccLqh0l
-VX6Wmle3usURehnmp349hQ71+S4pL+f5bFgWV1Al9j4uPqrtd3GqqpmWRgqujuwq
-URawXs3qZwQcWDD1YIq9pr1N5Za0/EKJAWv2cMhQOQwt1WbZyNKzMrcbGW3LM/nf
-peYVhDfwwvJllpKQd/Ct9JDpEXjXk4nAPQu6KfTomZ1yju2dL+6SfaHx/126M2CF
-Yv4HAqGEVka+lgqaE9chTLd8B59OTj+RdPsnnRHM3eaxynFNExc5JsUpISuTKWqW
-+qtB4Uu2NQvAmxU=
------END CERTIFICATE-----
-
 # Issuer: CN=Certinomis - Root CA O=Certinomis OU=0002 433998903
 # Subject: CN=Certinomis - Root CA O=Certinomis OU=0002 433998903
 # Label: "Certinomis - Root CA"
diff --git a/examples/android/helloworld/app/CMakeLists.txt b/examples/android/helloworld/app/CMakeLists.txt
index 6ee18da..f449a5c 100644
--- a/examples/android/helloworld/app/CMakeLists.txt
+++ b/examples/android/helloworld/app/CMakeLists.txt
@@ -12,36 +12,6 @@
 
 add_subdirectory(${GRPC_SRC_DIR} ${GRPC_BUILD_DIR})
 
-include_directories(${GRPC_SRC_DIR}/include)
-
-add_library(libgrpc STATIC IMPORTED)
-set_target_properties(libgrpc PROPERTIES IMPORTED_LOCATION
-  ${GRPC_BUILD_DIR}/libgrpc.a)
-
-add_library(libgrpc++ STATIC IMPORTED)
-set_target_properties(libgrpc++ PROPERTIES IMPORTED_LOCATION
-  ${GRPC_BUILD_DIR}/libgrpc++.a)
-
-add_library(libgpr STATIC IMPORTED)
-set_target_properties(libgpr PROPERTIES IMPORTED_LOCATION
-  ${GRPC_BUILD_DIR}/libgpr.a)
-
-add_library(libcares STATIC IMPORTED)
-set_target_properties(libcares PROPERTIES IMPORTED_LOCATION
-  ${GRPC_BUILD_DIR}/third_party/cares/cares/lib/libcares.a)
-
-add_library(libzlib STATIC IMPORTED)
-set_target_properties(libzlib PROPERTIES IMPORTED_LOCATION
-  ${GRPC_BUILD_DIR}/third_party/zlib/libz.a)
-
-add_library(libcrypto STATIC IMPORTED)
-set_target_properties(libcrypto PROPERTIES IMPORTED_LOCATION
-  ${GRPC_BUILD_DIR}/third_party/boringssl/crypto/libcrypto.a)
-
-add_library(libssl STATIC IMPORTED)
-set_target_properties(libssl PROPERTIES IMPORTED_LOCATION
-  ${GRPC_BUILD_DIR}/third_party/boringssl/ssl/libssl.a)
-
 set(GRPC_PROTO_GENS_DIR ${CMAKE_BINARY_DIR}/gens)
 file(MAKE_DIRECTORY ${GRPC_PROTO_GENS_DIR})
 include_directories(${GRPC_PROTO_GENS_DIR})
@@ -96,8 +66,8 @@
   SHARED ${HELLOWORLD_PROTO_HDRS} ${HELLOWORLD_PROTO_SRCS})
 
 target_link_libraries(helloworld_proto_lib
+  grpc++
   libprotobuf
-  libgrpc++
   android
   log)
 
@@ -111,13 +81,6 @@
   PRIVATE ${HELLOWORLD_PROTO_HEADERS})
 
 target_link_libraries(grpc-helloworld
-  libgrpc++
-  libgrpc
-  libzlib
-  libcares
-  libssl
-  libcrypto
   helloworld_proto_lib
-  libgpr
   android
   ${log-lib})
diff --git a/examples/cpp/helloworld/CMakeLists.txt b/examples/cpp/helloworld/CMakeLists.txt
index c3ce4d5..d0f705f 100644
--- a/examples/cpp/helloworld/CMakeLists.txt
+++ b/examples/cpp/helloworld/CMakeLists.txt
@@ -1,7 +1,24 @@
-# Minimum CMake required

+# Copyright 2018 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.

+#

+# cmake build file for C++ helloworld example.

+# Assumes protobuf and gRPC have been installed using cmake.

+# See cmake_externalproject/CMakeLists.txt for all-in-one cmake build

+# that automatically builds all the dependencies before building helloworld.

+

 cmake_minimum_required(VERSION 2.8)

 

-# Project

 project(HelloWorld C CXX)

 

 if(NOT MSVC)

@@ -10,57 +27,76 @@
   add_definitions(-D_WIN32_WINNT=0x600)

 endif()

 

-# Protobuf

-# NOTE: we cannot use "CONFIG" mode here because protobuf-config.cmake

-# is broken when used with CMAKE_INSTALL_PREFIX

-find_package(Protobuf REQUIRED)

-message(STATUS "Using protobuf ${protobuf_VERSION}")

-

-# {Protobuf,PROTOBUF}_FOUND is defined based on find_package type ("MODULE" vs "CONFIG").

-# For "MODULE", the case has also changed between cmake 3.5 and 3.6.

-# We use the legacy uppercase version for *_LIBRARIES AND *_INCLUDE_DIRS variables

-# as newer cmake versions provide them too for backward compatibility.

-if(Protobuf_FOUND OR PROTOBUF_FOUND)

-  if(TARGET protobuf::libprotobuf)

-    set(_PROTOBUF_LIBPROTOBUF protobuf::libprotobuf)

-  else()

-    set(_PROTOBUF_LIBPROTOBUF ${PROTOBUF_LIBRARIES})

-    include_directories(${PROTOBUF_INCLUDE_DIRS})

-  endif()

-  if(TARGET protobuf::protoc)

-    set(_PROTOBUF_PROTOC $<TARGET_FILE:protobuf::protoc>)

-  else()

-    set(_PROTOBUF_PROTOC ${PROTOBUF_PROTOC_EXECUTABLE})

-  endif()

+if(GRPC_AS_SUBMODULE)

+  # One way to build a projects that uses gRPC is to just include the

+  # entire gRPC project tree via "add_subdirectory".

+  # This approach is very simple to use, but the are some potential

+  # disadvantages:

+  # * it includes gRPC's CMakeLists.txt directly into your build script

+  #   without and that can make gRPC's internal setting interfere with your

+  #   own build.

+  # * depending on what's installed on your system, the contents of submodules

+  #   in gRPC's third_party/* might need to be available (and there might be

+  #   additional prerequisites required to build them). Consider using

+  #   the gRPC_*_PROVIDER options to fine-tune the expected behavior.

+  #

+  # A more robust approach to add dependency on gRPC is using

+  # cmake's ExternalProject_Add (see cmake_externalproject/CMakeLists.txt).

+  

+  # Include the gRPC's cmake build (normally grpc source code would live

+  # in a git submodule called "third_party/grpc", but this example lives in

+  # the same repository as gRPC sources, so we just look a few directories up)

+  add_subdirectory(../../.. ${CMAKE_CURRENT_BINARY_DIR}/grpc EXCLUDE_FROM_ALL)

+  message(STATUS "Using gRPC via add_subdirectory.")

+  

+  # After using add_subdirectory, we can now use the grpc targets directly from

+  # this build.

+  set(_PROTOBUF_LIBPROTOBUF libprotobuf)

+  set(_PROTOBUF_PROTOC $<TARGET_FILE:protoc>)

+  set(_GRPC_GRPCPP_UNSECURE grpc++_unsecure)

+  set(_GRPC_CPP_PLUGIN_EXECUTABLE $<TARGET_FILE:grpc_cpp_plugin>)

 else()

-  message(WARNING "Failed to locate libprotobuf and protoc!")

+  # This branch assumes that gRPC and all its dependencies are already installed

+  # on this system, so they can be located by find_package().

+

+  # Find Protobuf installation

+  # Looks for protobuf-config.cmake file installed by Protobuf's cmake installation.

+  set(protobuf_MODULE_COMPATIBLE TRUE)

+  find_package(Protobuf CONFIG REQUIRED)

+  message(STATUS "Using protobuf ${protobuf_VERSION}")

+

+  set(_PROTOBUF_LIBPROTOBUF protobuf::libprotobuf)

+  set(_PROTOBUF_PROTOC $<TARGET_FILE:protobuf::protoc>)

+

+  # Find gRPC installation

+  # Looks for gRPCConfig.cmake file installed by gRPC's cmake installation.

+  find_package(gRPC CONFIG REQUIRED)

+  message(STATUS "Using gRPC ${gRPC_VERSION}")

+

+  set(_GRPC_GRPCPP_UNSECURE gRPC::grpc++_unsecure)

+  set(_GRPC_CPP_PLUGIN_EXECUTABLE $<TARGET_FILE:gRPC::grpc_cpp_plugin>)

 endif()

 

-# gRPC

-find_package(gRPC CONFIG REQUIRED)

-message(STATUS "Using gRPC ${gRPC_VERSION}")

-

-# gRPC C++ plugin

-get_target_property(gRPC_CPP_PLUGIN_EXECUTABLE gRPC::grpc_cpp_plugin

-    IMPORTED_LOCATION_RELEASE)

-

 # Proto file

 get_filename_component(hw_proto "../../protos/helloworld.proto" ABSOLUTE)

 get_filename_component(hw_proto_path "${hw_proto}" PATH)

 

 # Generated sources

-protobuf_generate_cpp(hw_proto_srcs hw_proto_hdrs "${hw_proto}")

+set(hw_proto_srcs "${CMAKE_CURRENT_BINARY_DIR}/helloworld.pb.cc")

+set(hw_proto_hdrs "${CMAKE_CURRENT_BINARY_DIR}/helloworld.pb.h")

 set(hw_grpc_srcs "${CMAKE_CURRENT_BINARY_DIR}/helloworld.grpc.pb.cc")

 set(hw_grpc_hdrs "${CMAKE_CURRENT_BINARY_DIR}/helloworld.grpc.pb.h")

 add_custom_command(

-      OUTPUT "${hw_grpc_srcs}" "${hw_grpc_hdrs}"

+      OUTPUT "${hw_proto_srcs}" "${hw_proto_hdrs}" "${hw_grpc_srcs}" "${hw_grpc_hdrs}"

       COMMAND ${_PROTOBUF_PROTOC}

-      ARGS --grpc_out "${CMAKE_CURRENT_BINARY_DIR}" -I "${hw_proto_path}"

-        --plugin=protoc-gen-grpc="${gRPC_CPP_PLUGIN_EXECUTABLE}"

+      ARGS --grpc_out "${CMAKE_CURRENT_BINARY_DIR}"

+        --cpp_out "${CMAKE_CURRENT_BINARY_DIR}"

+        -I "${hw_proto_path}"

+        --plugin=protoc-gen-grpc="${_GRPC_CPP_PLUGIN_EXECUTABLE}"

         "${hw_proto}"

       DEPENDS "${hw_proto}")

 

-# Generated include directory

+# Include generated *.pb.h files

 include_directories("${CMAKE_CURRENT_BINARY_DIR}")

 

 # Targets greeter_[async_](client|server)

@@ -71,6 +107,6 @@
     ${hw_proto_srcs}

     ${hw_grpc_srcs})

   target_link_libraries(${_target}

-    ${_PROTOBUF_LIBPROTOBUF}

-    gRPC::grpc++_unsecure)

+    ${_GRPC_GRPCPP_UNSECURE}

+    ${_PROTOBUF_LIBPROTOBUF})

 endforeach()

diff --git a/examples/cpp/helloworld/cmake_externalproject/CMakeLists.txt b/examples/cpp/helloworld/cmake_externalproject/CMakeLists.txt
new file mode 100644
index 0000000..9fbdf07
--- /dev/null
+++ b/examples/cpp/helloworld/cmake_externalproject/CMakeLists.txt
@@ -0,0 +1,116 @@
+# Copyright 2018 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.

+#

+# cmake "superbuild" file for C++ helloworld example.

+# This build file demonstrates how to build the helloworld project

+# and all its dependencies in a single cmake build (hence "superbuild")

+# that is easy to build and maintain.

+# cmake's ExternalProject_Add() is used to import all the sub-projects,

+# including the "helloworld" project itself.

+# See https://blog.kitware.com/cmake-superbuilds-git-submodules/

+

+cmake_minimum_required(VERSION 2.8)

+

+# Project

+project(HelloWorld-SuperBuild C CXX)

+

+include(ExternalProject)

+

+# Builds c-ares project from the git submodule.

+# Note: For all external projects, instead of using checked-out code, one could

+# specify GIT_REPOSITORY and GIT_TAG to have cmake download the dependency directly,

+# without needing to add a submodule to your project.

+ExternalProject_Add(c-ares

+  PREFIX c-ares

+  SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../third_party/cares/cares"

+  CMAKE_CACHE_ARGS

+        -DCARES_SHARED:BOOL=OFF

+        -DCARES_STATIC:BOOL=ON

+        -DCARES_STATIC_PIC:BOOL=ON

+        -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_CURRENT_BINARY_DIR}/c-ares

+)

+

+# Builds protobuf project from the git submodule.

+ExternalProject_Add(protobuf

+  PREFIX protobuf

+  SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../third_party/protobuf/cmake"

+  CMAKE_CACHE_ARGS

+        -Dprotobuf_BUILD_TESTS:BOOL=OFF

+        -Dprotobuf_WITH_ZLIB:BOOL=OFF

+        -Dprotobuf_MSVC_STATIC_RUNTIME:BOOL=OFF

+        -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_CURRENT_BINARY_DIR}/protobuf

+)

+

+# Builds zlib project from the git submodule.

+ExternalProject_Add(zlib

+  PREFIX zlib

+  SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../third_party/zlib"

+  CMAKE_CACHE_ARGS

+        -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_CURRENT_BINARY_DIR}/zlib

+)

+

+# the location where protobuf-config.cmake will be installed varies by platform

+if (WIN32)

+  set(_FINDPACKAGE_PROTOBUF_CONFIG_DIR "${CMAKE_CURRENT_BINARY_DIR}/protobuf/cmake")

+else()

+  set(_FINDPACKAGE_PROTOBUF_CONFIG_DIR "${CMAKE_CURRENT_BINARY_DIR}/protobuf/lib/cmake/protobuf")

+endif()

+

+# if OPENSSL_ROOT_DIR is set, propagate that hint path to the external projects with OpenSSL dependency.

+set(_CMAKE_ARGS_OPENSSL_ROOT_DIR "")

+if (OPENSSL_ROOT_DIR)

+  set(_CMAKE_ARGS_OPENSSL_ROOT_DIR "-DOPENSSL_ROOT_DIR:PATH=${OPENSSL_ROOT_DIR}")

+endif()

+

+# Builds gRPC based on locally checked-out sources and set arguments so that all the dependencies

+# are correctly located.

+ExternalProject_Add(grpc

+  PREFIX grpc

+  SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../.."

+  CMAKE_CACHE_ARGS

+        -DgRPC_INSTALL:BOOL=ON

+        -DgRPC_BUILD_TESTS:BOOL=OFF

+        -DgRPC_PROTOBUF_PROVIDER:STRING=package

+        -DgRPC_PROTOBUF_PACKAGE_TYPE:STRING=CONFIG

+        -DProtobuf_DIR:PATH=${_FINDPACKAGE_PROTOBUF_CONFIG_DIR}

+        -DgRPC_ZLIB_PROVIDER:STRING=package

+        -DZLIB_ROOT:STRING=${CMAKE_CURRENT_BINARY_DIR}/zlib

+        -DgRPC_CARES_PROVIDER:STRING=package

+        -Dc-ares_DIR:PATH=${CMAKE_CURRENT_BINARY_DIR}/c-ares/lib/cmake/c-ares

+        -DgRPC_SSL_PROVIDER:STRING=package

+        ${_CMAKE_ARGS_OPENSSL_ROOT_DIR}

+        -DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_CURRENT_BINARY_DIR}/grpc

+  DEPENDS c-ares protobuf zlib

+)

+

+# Build the helloworld projects itself using a CMakeLists.txt that assumes all the dependencies

+# have already been installed.

+# Even though helloworld is not really an "external project" from perspective of this build,

+# we are still importing it using ExternalProject_Add because that allows us to use find_package()

+# to locate all the dependencies (if we were building helloworld directly in this build we,

+# we would have needed to manually import the libraries as opposed to reusing targets exported by

+# gRPC and protobuf).

+ExternalProject_Add(helloworld

+  PREFIX helloworld

+  SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/.."

+  BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/helloworld"

+  INSTALL_COMMAND ""

+  CMAKE_CACHE_ARGS

+        -DProtobuf_DIR:PATH=${_FINDPACKAGE_PROTOBUF_CONFIG_DIR}

+        -Dc-ares_DIR:PATH=${CMAKE_CURRENT_BINARY_DIR}/c-ares/lib/cmake/c-ares

+        -DZLIB_ROOT:STRING=${CMAKE_CURRENT_BINARY_DIR}/zlib

+        ${_CMAKE_ARGS_OPENSSL_ROOT_DIR}

+        -DgRPC_DIR:PATH=${CMAKE_CURRENT_BINARY_DIR}/grpc/lib/cmake/grpc

+  DEPENDS protobuf grpc

+)

diff --git a/examples/csharp/helloworld-from-cli/global.json b/examples/csharp/helloworld-from-cli/global.json
deleted file mode 100644
index e4b797e..0000000
--- a/examples/csharp/helloworld-from-cli/global.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-  "sdk": {
-    "version": "1.0.0"
-  }
-}
diff --git a/examples/node/dynamic_codegen/route_guide/route_guide_server.js b/examples/node/dynamic_codegen/route_guide/route_guide_server.js
index f9028e8..3819c09 100644
--- a/examples/node/dynamic_codegen/route_guide/route_guide_server.js
+++ b/examples/node/dynamic_codegen/route_guide/route_guide_server.js
@@ -122,7 +122,7 @@
   var deltalon = lon2-lon1;
   var a = Math.sin(deltalat/2) * Math.sin(deltalat/2) +
       Math.cos(lat1) * Math.cos(lat2) *
-      Math.sin(dlon/2) * Math.sin(dlon/2);
+      Math.sin(deltalon/2) * Math.sin(deltalon/2);
   var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
   return R * c;
 }
diff --git a/gRPC-C++.podspec b/gRPC-C++.podspec
index f53e9db..29b79e0 100644
--- a/gRPC-C++.podspec
+++ b/gRPC-C++.podspec
@@ -23,7 +23,7 @@
 Pod::Spec.new do |s|
   s.name     = 'gRPC-C++'
   # TODO (mxyan): use version that match gRPC version when pod is stabilized
-  # version = '1.11.0-dev'
+  # version = '1.13.0-dev'
   version = '0.0.2'
   s.version  = version
   s.summary  = 'gRPC C++ library'
@@ -31,7 +31,7 @@
   s.license  = 'Apache License, Version 2.0'
   s.authors  = { 'The gRPC contributors' => 'grpc-packages@google.com' }
 
-  grpc_version = '1.11.0-dev'
+  grpc_version = '1.13.0-dev'
 
   s.source = {
     :git => 'https://github.com/grpc/grpc.git',
@@ -112,6 +112,8 @@
                       'include/grpcpp/support/byte_buffer.h',
                       'include/grpcpp/support/channel_arguments.h',
                       'include/grpcpp/support/config.h',
+                      'include/grpcpp/support/proto_buffer_reader.h',
+                      'include/grpcpp/support/proto_buffer_writer.h',
                       'include/grpcpp/support/slice.h',
                       'include/grpcpp/support/status.h',
                       'include/grpcpp/support/status_code_enum.h',
@@ -206,7 +208,6 @@
                       'src/cpp/server/server_posix.cc',
                       'src/cpp/thread_manager/thread_manager.cc',
                       'src/cpp/util/byte_buffer_cc.cc',
-                      'src/cpp/util/slice_cc.cc',
                       'src/cpp/util/status.cc',
                       'src/cpp/util/string_ref.cc',
                       'src/cpp/util/time_cc.cc',
@@ -259,6 +260,7 @@
                       'src/core/ext/filters/http/client/http_client_filter.h',
                       'src/core/ext/filters/http/message_compress/message_compress_filter.h',
                       'src/core/ext/filters/http/server/http_server_filter.h',
+                      'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h',
                       'src/core/lib/security/context/security_context.h',
                       'src/core/lib/security/credentials/alts/alts_credentials.h',
                       'src/core/lib/security/credentials/composite/composite_credentials.h',
@@ -306,8 +308,8 @@
                       'src/core/tsi/alts/handshaker/handshaker.pb.h',
                       'src/core/tsi/alts/handshaker/transport_security_common.pb.h',
                       'src/core/tsi/transport_security.h',
-                      'src/core/tsi/transport_security_adapter.h',
                       'src/core/tsi/transport_security_interface.h',
+                      'src/core/ext/transport/chttp2/client/authority.h',
                       'src/core/ext/transport/chttp2/client/chttp2_connector.h',
                       'src/core/ext/filters/client_channel/backup_poller.h',
                       'src/core/ext/filters/client_channel/client_channel.h',
@@ -485,6 +487,7 @@
                       'src/core/ext/filters/load_reporting/server_load_reporting_plugin.h',
                       'src/core/ext/filters/max_age/max_age_filter.h',
                       'src/core/ext/filters/message_size/message_size_filter.h',
+                      'src/core/ext/filters/http/client_authority_filter.h',
                       'src/core/ext/filters/workarounds/workaround_cronet_compression_filter.h',
                       'src/core/ext/filters/workarounds/workaround_utils.h'
 
diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec
index f93dded..ce6ff76 100644
--- a/gRPC-Core.podspec
+++ b/gRPC-Core.podspec
@@ -22,7 +22,7 @@
 
 Pod::Spec.new do |s|
   s.name     = 'gRPC-Core'
-  version = '1.11.0-dev'
+  version = '1.13.0-dev'
   s.version  = version
   s.summary  = 'Core cross-platform gRPC library, written in C'
   s.homepage = 'https://grpc.io'
@@ -182,6 +182,7 @@
     ss.dependency 'BoringSSL', '~> 10.0'
     ss.dependency 'nanopb', '~> 0.3'
 
+    # To save you from scrolling, this is the last part of the podspec.
     ss.source_files = 'src/core/lib/gpr/arena.h',
                       'src/core/lib/gpr/env.h',
                       'src/core/lib/gpr/fork.h',
@@ -269,6 +270,7 @@
                       'src/core/ext/filters/http/client/http_client_filter.h',
                       'src/core/ext/filters/http/message_compress/message_compress_filter.h',
                       'src/core/ext/filters/http/server/http_server_filter.h',
+                      'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h',
                       'src/core/lib/security/context/security_context.h',
                       'src/core/lib/security/credentials/alts/alts_credentials.h',
                       'src/core/lib/security/credentials/composite/composite_credentials.h',
@@ -316,8 +318,8 @@
                       'src/core/tsi/alts/handshaker/handshaker.pb.h',
                       'src/core/tsi/alts/handshaker/transport_security_common.pb.h',
                       'src/core/tsi/transport_security.h',
-                      'src/core/tsi/transport_security_adapter.h',
                       'src/core/tsi/transport_security_interface.h',
+                      'src/core/ext/transport/chttp2/client/authority.h',
                       'src/core/ext/transport/chttp2/client/chttp2_connector.h',
                       'src/core/ext/filters/client_channel/backup_poller.h',
                       'src/core/ext/filters/client_channel/client_channel.h',
@@ -495,6 +497,7 @@
                       'src/core/ext/filters/load_reporting/server_load_reporting_plugin.h',
                       'src/core/ext/filters/max_age/max_age_filter.h',
                       'src/core/ext/filters/message_size/message_size_filter.h',
+                      'src/core/ext/filters/http/client_authority_filter.h',
                       'src/core/ext/filters/workarounds/workaround_cronet_compression_filter.h',
                       'src/core/ext/filters/workarounds/workaround_utils.h',
                       'src/core/lib/surface/init.cc',
@@ -733,9 +736,9 @@
                       'src/core/tsi/alts/handshaker/handshaker.pb.c',
                       'src/core/tsi/alts/handshaker/transport_security_common.pb.c',
                       'src/core/tsi/transport_security.cc',
-                      'src/core/tsi/transport_security_adapter.cc',
                       'src/core/ext/transport/chttp2/client/insecure/channel_create.cc',
                       'src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc',
+                      'src/core/ext/transport/chttp2/client/authority.cc',
                       'src/core/ext/transport/chttp2/client/chttp2_connector.cc',
                       'src/core/ext/filters/client_channel/backup_poller.cc',
                       'src/core/ext/filters/client_channel/channel_connectivity.cc',
@@ -780,7 +783,6 @@
                       'src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c',
                       'src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc',
                       'src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc',
-                      'src/core/ext/filters/client_channel/lb_policy/subchannel_list.cc',
                       'src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc',
                       'src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc',
                       'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc',
@@ -793,6 +795,7 @@
                       'src/core/ext/census/grpc_context.cc',
                       'src/core/ext/filters/max_age/max_age_filter.cc',
                       'src/core/ext/filters/message_size/message_size_filter.cc',
+                      'src/core/ext/filters/http/client_authority_filter.cc',
                       'src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc',
                       'src/core/ext/filters/workarounds/workaround_utils.cc',
                       'src/core/plugin_registry/grpc_plugin_registry.cc'
@@ -845,6 +848,7 @@
                               'src/core/ext/filters/http/client/http_client_filter.h',
                               'src/core/ext/filters/http/message_compress/message_compress_filter.h',
                               'src/core/ext/filters/http/server/http_server_filter.h',
+                              'src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h',
                               'src/core/lib/security/context/security_context.h',
                               'src/core/lib/security/credentials/alts/alts_credentials.h',
                               'src/core/lib/security/credentials/composite/composite_credentials.h',
@@ -892,8 +896,8 @@
                               'src/core/tsi/alts/handshaker/handshaker.pb.h',
                               'src/core/tsi/alts/handshaker/transport_security_common.pb.h',
                               'src/core/tsi/transport_security.h',
-                              'src/core/tsi/transport_security_adapter.h',
                               'src/core/tsi/transport_security_interface.h',
+                              'src/core/ext/transport/chttp2/client/authority.h',
                               'src/core/ext/transport/chttp2/client/chttp2_connector.h',
                               'src/core/ext/filters/client_channel/backup_poller.h',
                               'src/core/ext/filters/client_channel/client_channel.h',
@@ -1071,960 +1075,41 @@
                               'src/core/ext/filters/load_reporting/server_load_reporting_plugin.h',
                               'src/core/ext/filters/max_age/max_age_filter.h',
                               'src/core/ext/filters/message_size/message_size_filter.h',
+                              'src/core/ext/filters/http/client_authority_filter.h',
                               'src/core/ext/filters/workarounds/workaround_cronet_compression_filter.h',
                               'src/core/ext/filters/workarounds/workaround_utils.h'
   end
 
   s.subspec 'Cronet-Interface' do |ss|
     ss.header_mappings_dir = 'include/grpc'
-    ss.source_files = 'include/grpc/support/alloc.h',
-                      'include/grpc/support/atm.h',
-                      'include/grpc/support/atm_gcc_atomic.h',
-                      'include/grpc/support/atm_gcc_sync.h',
-                      'include/grpc/support/atm_windows.h',
-                      'include/grpc/support/cpu.h',
-                      'include/grpc/support/log.h',
-                      'include/grpc/support/log_windows.h',
-                      'include/grpc/support/port_platform.h',
-                      'include/grpc/support/string_util.h',
-                      'include/grpc/support/sync.h',
-                      'include/grpc/support/sync_custom.h',
-                      'include/grpc/support/sync_generic.h',
-                      'include/grpc/support/sync_posix.h',
-                      'include/grpc/support/sync_windows.h',
-                      'include/grpc/support/thd_id.h',
-                      'include/grpc/support/time.h',
-                      'include/grpc/impl/codegen/atm.h',
-                      'include/grpc/impl/codegen/atm_gcc_atomic.h',
-                      'include/grpc/impl/codegen/atm_gcc_sync.h',
-                      'include/grpc/impl/codegen/atm_windows.h',
-                      'include/grpc/impl/codegen/fork.h',
-                      'include/grpc/impl/codegen/gpr_slice.h',
-                      'include/grpc/impl/codegen/gpr_types.h',
-                      'include/grpc/impl/codegen/port_platform.h',
-                      'include/grpc/impl/codegen/sync.h',
-                      'include/grpc/impl/codegen/sync_custom.h',
-                      'include/grpc/impl/codegen/sync_generic.h',
-                      'include/grpc/impl/codegen/sync_posix.h',
-                      'include/grpc/impl/codegen/sync_windows.h',
-                      'include/grpc/impl/codegen/byte_buffer.h',
-                      'include/grpc/impl/codegen/byte_buffer_reader.h',
-                      'include/grpc/impl/codegen/compression_types.h',
-                      'include/grpc/impl/codegen/connectivity_state.h',
-                      'include/grpc/impl/codegen/grpc_types.h',
-                      'include/grpc/impl/codegen/propagation_bits.h',
-                      'include/grpc/impl/codegen/slice.h',
-                      'include/grpc/impl/codegen/status.h',
-                      'include/grpc/impl/codegen/atm.h',
-                      'include/grpc/impl/codegen/atm_gcc_atomic.h',
-                      'include/grpc/impl/codegen/atm_gcc_sync.h',
-                      'include/grpc/impl/codegen/atm_windows.h',
-                      'include/grpc/impl/codegen/fork.h',
-                      'include/grpc/impl/codegen/gpr_slice.h',
-                      'include/grpc/impl/codegen/gpr_types.h',
-                      'include/grpc/impl/codegen/port_platform.h',
-                      'include/grpc/impl/codegen/sync.h',
-                      'include/grpc/impl/codegen/sync_custom.h',
-                      'include/grpc/impl/codegen/sync_generic.h',
-                      'include/grpc/impl/codegen/sync_posix.h',
-                      'include/grpc/impl/codegen/sync_windows.h',
-                      'include/grpc/byte_buffer.h',
-                      'include/grpc/byte_buffer_reader.h',
-                      'include/grpc/compression.h',
-                      'include/grpc/fork.h',
-                      'include/grpc/grpc.h',
-                      'include/grpc/grpc_posix.h',
-                      'include/grpc/grpc_security_constants.h',
-                      'include/grpc/load_reporting.h',
-                      'include/grpc/slice.h',
-                      'include/grpc/slice_buffer.h',
-                      'include/grpc/status.h',
-                      'include/grpc/support/workaround_list.h',
-                      'include/grpc/grpc_cronet.h',
-                      'include/grpc/grpc_security.h'
+    ss.source_files = 'include/grpc/grpc_cronet.h'
   end
 
   s.subspec 'Cronet-Implementation' do |ss|
     ss.header_mappings_dir = '.'
-    ss.libraries = 'z'
-    ss.dependency "#{s.name}/Cronet-Interface", version
-    ss.dependency 'BoringSSL', '~> 10.0'
-    ss.dependency 'nanopb', '~> 0.3'
 
-    ss.source_files = 'src/core/lib/gpr/arena.h',
-                      'src/core/lib/gpr/env.h',
-                      'src/core/lib/gpr/fork.h',
-                      'src/core/lib/gpr/host_port.h',
-                      'src/core/lib/gpr/mpscq.h',
-                      'src/core/lib/gpr/murmur_hash.h',
-                      'src/core/lib/gpr/spinlock.h',
-                      'src/core/lib/gpr/string.h',
-                      'src/core/lib/gpr/string_windows.h',
-                      'src/core/lib/gpr/time_precise.h',
-                      'src/core/lib/gpr/tls.h',
-                      'src/core/lib/gpr/tls_gcc.h',
-                      'src/core/lib/gpr/tls_msvc.h',
-                      'src/core/lib/gpr/tls_pthread.h',
-                      'src/core/lib/gpr/tmpfile.h',
-                      'src/core/lib/gpr/useful.h',
-                      'src/core/lib/gprpp/abstract.h',
-                      'src/core/lib/gprpp/atomic.h',
-                      'src/core/lib/gprpp/atomic_with_atm.h',
-                      'src/core/lib/gprpp/atomic_with_std.h',
-                      'src/core/lib/gprpp/manual_constructor.h',
-                      'src/core/lib/gprpp/memory.h',
-                      'src/core/lib/gprpp/thd.h',
-                      'src/core/lib/profiling/timers.h',
-                      'src/core/lib/gpr/alloc.cc',
-                      'src/core/lib/gpr/arena.cc',
-                      'src/core/lib/gpr/atm.cc',
-                      'src/core/lib/gpr/cpu_iphone.cc',
-                      'src/core/lib/gpr/cpu_linux.cc',
-                      'src/core/lib/gpr/cpu_posix.cc',
-                      'src/core/lib/gpr/cpu_windows.cc',
-                      'src/core/lib/gpr/env_linux.cc',
-                      'src/core/lib/gpr/env_posix.cc',
-                      'src/core/lib/gpr/env_windows.cc',
-                      'src/core/lib/gpr/fork.cc',
-                      'src/core/lib/gpr/host_port.cc',
-                      'src/core/lib/gpr/log.cc',
-                      'src/core/lib/gpr/log_android.cc',
-                      'src/core/lib/gpr/log_linux.cc',
-                      'src/core/lib/gpr/log_posix.cc',
-                      'src/core/lib/gpr/log_windows.cc',
-                      'src/core/lib/gpr/mpscq.cc',
-                      'src/core/lib/gpr/murmur_hash.cc',
-                      'src/core/lib/gpr/string.cc',
-                      'src/core/lib/gpr/string_posix.cc',
-                      'src/core/lib/gpr/string_util_windows.cc',
-                      'src/core/lib/gpr/string_windows.cc',
-                      'src/core/lib/gpr/sync.cc',
-                      'src/core/lib/gpr/sync_posix.cc',
-                      'src/core/lib/gpr/sync_windows.cc',
-                      'src/core/lib/gpr/time.cc',
-                      'src/core/lib/gpr/time_posix.cc',
-                      'src/core/lib/gpr/time_precise.cc',
-                      'src/core/lib/gpr/time_windows.cc',
-                      'src/core/lib/gpr/tls_pthread.cc',
-                      'src/core/lib/gpr/tmpfile_msys.cc',
-                      'src/core/lib/gpr/tmpfile_posix.cc',
-                      'src/core/lib/gpr/tmpfile_windows.cc',
-                      'src/core/lib/gpr/wrap_memcpy.cc',
-                      'src/core/lib/gprpp/thd_posix.cc',
-                      'src/core/lib/gprpp/thd_windows.cc',
-                      'src/core/lib/profiling/basic_timers.cc',
-                      'src/core/lib/profiling/stap_timers.cc',
-                      'src/core/lib/avl/avl.h',
-                      'src/core/lib/backoff/backoff.h',
-                      'src/core/lib/channel/channel_args.h',
-                      'src/core/lib/channel/channel_stack.h',
-                      'src/core/lib/channel/channel_stack_builder.h',
-                      'src/core/lib/channel/channel_trace.h',
-                      'src/core/lib/channel/channel_trace_registry.h',
-                      'src/core/lib/channel/connected_channel.h',
-                      'src/core/lib/channel/context.h',
-                      'src/core/lib/channel/handshaker.h',
-                      'src/core/lib/channel/handshaker_factory.h',
-                      'src/core/lib/channel/handshaker_registry.h',
-                      'src/core/lib/channel/status_util.h',
-                      'src/core/lib/compression/algorithm_metadata.h',
-                      'src/core/lib/compression/compression_internal.h',
-                      'src/core/lib/compression/message_compress.h',
-                      'src/core/lib/compression/stream_compression.h',
-                      'src/core/lib/compression/stream_compression_gzip.h',
-                      'src/core/lib/compression/stream_compression_identity.h',
-                      'src/core/lib/debug/stats.h',
-                      'src/core/lib/debug/stats_data.h',
-                      'src/core/lib/gprpp/debug_location.h',
-                      'src/core/lib/gprpp/inlined_vector.h',
-                      'src/core/lib/gprpp/orphanable.h',
-                      'src/core/lib/gprpp/ref_counted.h',
-                      'src/core/lib/gprpp/ref_counted_ptr.h',
-                      'src/core/lib/http/format_request.h',
-                      'src/core/lib/http/httpcli.h',
-                      'src/core/lib/http/parser.h',
-                      'src/core/lib/iomgr/block_annotate.h',
-                      'src/core/lib/iomgr/call_combiner.h',
-                      'src/core/lib/iomgr/closure.h',
-                      'src/core/lib/iomgr/combiner.h',
-                      'src/core/lib/iomgr/endpoint.h',
-                      'src/core/lib/iomgr/endpoint_pair.h',
-                      'src/core/lib/iomgr/error.h',
-                      'src/core/lib/iomgr/error_internal.h',
-                      'src/core/lib/iomgr/ev_epoll1_linux.h',
-                      'src/core/lib/iomgr/ev_epollex_linux.h',
-                      'src/core/lib/iomgr/ev_epollsig_linux.h',
-                      'src/core/lib/iomgr/ev_poll_posix.h',
-                      'src/core/lib/iomgr/ev_posix.h',
-                      'src/core/lib/iomgr/exec_ctx.h',
-                      'src/core/lib/iomgr/executor.h',
-                      'src/core/lib/iomgr/gethostname.h',
-                      'src/core/lib/iomgr/iocp_windows.h',
-                      'src/core/lib/iomgr/iomgr.h',
-                      'src/core/lib/iomgr/iomgr_custom.h',
-                      'src/core/lib/iomgr/iomgr_internal.h',
-                      'src/core/lib/iomgr/iomgr_posix.h',
-                      'src/core/lib/iomgr/is_epollexclusive_available.h',
-                      'src/core/lib/iomgr/load_file.h',
-                      'src/core/lib/iomgr/lockfree_event.h',
-                      'src/core/lib/iomgr/nameser.h',
-                      'src/core/lib/iomgr/network_status_tracker.h',
-                      'src/core/lib/iomgr/polling_entity.h',
-                      'src/core/lib/iomgr/pollset.h',
-                      'src/core/lib/iomgr/pollset_custom.h',
-                      'src/core/lib/iomgr/pollset_set.h',
-                      'src/core/lib/iomgr/pollset_set_custom.h',
-                      'src/core/lib/iomgr/pollset_set_windows.h',
-                      'src/core/lib/iomgr/pollset_windows.h',
-                      'src/core/lib/iomgr/port.h',
-                      'src/core/lib/iomgr/resolve_address.h',
-                      'src/core/lib/iomgr/resolve_address_custom.h',
-                      'src/core/lib/iomgr/resource_quota.h',
-                      'src/core/lib/iomgr/sockaddr.h',
-                      'src/core/lib/iomgr/sockaddr_custom.h',
-                      'src/core/lib/iomgr/sockaddr_posix.h',
-                      'src/core/lib/iomgr/sockaddr_utils.h',
-                      'src/core/lib/iomgr/sockaddr_windows.h',
-                      'src/core/lib/iomgr/socket_factory_posix.h',
-                      'src/core/lib/iomgr/socket_mutator.h',
-                      'src/core/lib/iomgr/socket_utils.h',
-                      'src/core/lib/iomgr/socket_utils_posix.h',
-                      'src/core/lib/iomgr/socket_windows.h',
-                      'src/core/lib/iomgr/sys_epoll_wrapper.h',
-                      'src/core/lib/iomgr/tcp_client.h',
-                      'src/core/lib/iomgr/tcp_client_posix.h',
-                      'src/core/lib/iomgr/tcp_custom.h',
-                      'src/core/lib/iomgr/tcp_posix.h',
-                      'src/core/lib/iomgr/tcp_server.h',
-                      'src/core/lib/iomgr/tcp_server_utils_posix.h',
-                      'src/core/lib/iomgr/tcp_windows.h',
-                      'src/core/lib/iomgr/time_averaged_stats.h',
-                      'src/core/lib/iomgr/timer.h',
-                      'src/core/lib/iomgr/timer_custom.h',
-                      'src/core/lib/iomgr/timer_heap.h',
-                      'src/core/lib/iomgr/timer_manager.h',
-                      'src/core/lib/iomgr/udp_server.h',
-                      'src/core/lib/iomgr/unix_sockets_posix.h',
-                      'src/core/lib/iomgr/wakeup_fd_cv.h',
-                      'src/core/lib/iomgr/wakeup_fd_pipe.h',
-                      'src/core/lib/iomgr/wakeup_fd_posix.h',
-                      'src/core/lib/json/json.h',
-                      'src/core/lib/json/json_common.h',
-                      'src/core/lib/json/json_reader.h',
-                      'src/core/lib/json/json_writer.h',
-                      'src/core/lib/slice/b64.h',
-                      'src/core/lib/slice/percent_encoding.h',
-                      'src/core/lib/slice/slice_hash_table.h',
-                      'src/core/lib/slice/slice_internal.h',
-                      'src/core/lib/slice/slice_string_helpers.h',
-                      'src/core/lib/slice/slice_weak_hash_table.h',
-                      'src/core/lib/surface/api_trace.h',
-                      'src/core/lib/surface/call.h',
-                      'src/core/lib/surface/call_test_only.h',
-                      'src/core/lib/surface/channel.h',
-                      'src/core/lib/surface/channel_init.h',
-                      'src/core/lib/surface/channel_stack_type.h',
-                      'src/core/lib/surface/completion_queue.h',
-                      'src/core/lib/surface/completion_queue_factory.h',
-                      'src/core/lib/surface/event_string.h',
-                      'src/core/lib/surface/init.h',
-                      'src/core/lib/surface/lame_client.h',
-                      'src/core/lib/surface/server.h',
-                      'src/core/lib/surface/validate_metadata.h',
-                      'src/core/lib/transport/bdp_estimator.h',
-                      'src/core/lib/transport/byte_stream.h',
-                      'src/core/lib/transport/connectivity_state.h',
-                      'src/core/lib/transport/error_utils.h',
-                      'src/core/lib/transport/http2_errors.h',
-                      'src/core/lib/transport/metadata.h',
-                      'src/core/lib/transport/metadata_batch.h',
-                      'src/core/lib/transport/pid_controller.h',
-                      'src/core/lib/transport/service_config.h',
-                      'src/core/lib/transport/static_metadata.h',
-                      'src/core/lib/transport/status_conversion.h',
-                      'src/core/lib/transport/status_metadata.h',
-                      'src/core/lib/transport/timeout_encoding.h',
-                      'src/core/lib/transport/transport.h',
-                      'src/core/lib/transport/transport_impl.h',
-                      'src/core/lib/debug/trace.h',
-                      'src/core/ext/filters/deadline/deadline_filter.h',
-                      'src/core/ext/filters/client_channel/backup_poller.h',
-                      'src/core/ext/filters/client_channel/client_channel.h',
-                      'src/core/ext/filters/client_channel/client_channel_factory.h',
-                      'src/core/ext/filters/client_channel/connector.h',
-                      'src/core/ext/filters/client_channel/http_connect_handshaker.h',
-                      'src/core/ext/filters/client_channel/http_proxy.h',
-                      'src/core/ext/filters/client_channel/lb_policy.h',
-                      'src/core/ext/filters/client_channel/lb_policy_factory.h',
-                      'src/core/ext/filters/client_channel/lb_policy_registry.h',
-                      'src/core/ext/filters/client_channel/method_params.h',
-                      'src/core/ext/filters/client_channel/parse_address.h',
-                      'src/core/ext/filters/client_channel/proxy_mapper.h',
-                      'src/core/ext/filters/client_channel/proxy_mapper_registry.h',
-                      'src/core/ext/filters/client_channel/resolver.h',
-                      'src/core/ext/filters/client_channel/resolver_factory.h',
-                      'src/core/ext/filters/client_channel/resolver_registry.h',
-                      'src/core/ext/filters/client_channel/retry_throttle.h',
-                      'src/core/ext/filters/client_channel/subchannel.h',
-                      'src/core/ext/filters/client_channel/subchannel_index.h',
-                      'src/core/ext/filters/client_channel/uri_parser.h',
-                      'src/core/ext/filters/client_channel/lb_policy/subchannel_list.h',
-                      'src/core/ext/filters/max_age/max_age_filter.h',
-                      'src/core/ext/filters/message_size/message_size_filter.h',
-                      'src/core/ext/filters/load_reporting/server_load_reporting_filter.h',
-                      'src/core/ext/filters/load_reporting/server_load_reporting_plugin.h',
-                      'src/core/ext/transport/cronet/transport/cronet_transport.h',
-                      'third_party/objective_c/Cronet/bidirectional_stream_c.h',
-                      'src/core/ext/transport/chttp2/transport/bin_decoder.h',
-                      'src/core/ext/transport/chttp2/transport/bin_encoder.h',
-                      'src/core/ext/transport/chttp2/transport/chttp2_transport.h',
-                      'src/core/ext/transport/chttp2/transport/flow_control.h',
-                      'src/core/ext/transport/chttp2/transport/frame.h',
-                      'src/core/ext/transport/chttp2/transport/frame_data.h',
-                      'src/core/ext/transport/chttp2/transport/frame_goaway.h',
-                      'src/core/ext/transport/chttp2/transport/frame_ping.h',
-                      'src/core/ext/transport/chttp2/transport/frame_rst_stream.h',
-                      'src/core/ext/transport/chttp2/transport/frame_settings.h',
-                      'src/core/ext/transport/chttp2/transport/frame_window_update.h',
-                      'src/core/ext/transport/chttp2/transport/hpack_encoder.h',
-                      'src/core/ext/transport/chttp2/transport/hpack_parser.h',
-                      'src/core/ext/transport/chttp2/transport/hpack_table.h',
-                      'src/core/ext/transport/chttp2/transport/http2_settings.h',
-                      'src/core/ext/transport/chttp2/transport/huffsyms.h',
-                      'src/core/ext/transport/chttp2/transport/incoming_metadata.h',
-                      'src/core/ext/transport/chttp2/transport/internal.h',
-                      'src/core/ext/transport/chttp2/transport/stream_map.h',
-                      'src/core/ext/transport/chttp2/transport/varint.h',
-                      'src/core/ext/transport/chttp2/alpn/alpn.h',
-                      'src/core/ext/filters/http/client/http_client_filter.h',
-                      'src/core/ext/filters/http/message_compress/message_compress_filter.h',
-                      'src/core/ext/filters/http/server/http_server_filter.h',
-                      'src/core/lib/security/context/security_context.h',
-                      'src/core/lib/security/credentials/alts/alts_credentials.h',
-                      'src/core/lib/security/credentials/composite/composite_credentials.h',
-                      'src/core/lib/security/credentials/credentials.h',
-                      'src/core/lib/security/credentials/fake/fake_credentials.h',
-                      'src/core/lib/security/credentials/google_default/google_default_credentials.h',
-                      'src/core/lib/security/credentials/iam/iam_credentials.h',
-                      'src/core/lib/security/credentials/jwt/json_token.h',
-                      'src/core/lib/security/credentials/jwt/jwt_credentials.h',
-                      'src/core/lib/security/credentials/jwt/jwt_verifier.h',
-                      'src/core/lib/security/credentials/oauth2/oauth2_credentials.h',
-                      'src/core/lib/security/credentials/plugin/plugin_credentials.h',
-                      'src/core/lib/security/credentials/ssl/ssl_credentials.h',
-                      'src/core/lib/security/security_connector/alts_security_connector.h',
-                      'src/core/lib/security/security_connector/security_connector.h',
-                      'src/core/lib/security/transport/auth_filters.h',
-                      'src/core/lib/security/transport/secure_endpoint.h',
-                      'src/core/lib/security/transport/security_handshaker.h',
-                      'src/core/lib/security/transport/target_authority_table.h',
-                      'src/core/lib/security/transport/tsi_error.h',
-                      'src/core/lib/security/util/json_util.h',
-                      'src/core/tsi/alts/crypt/gsec.h',
-                      'src/core/tsi/alts/frame_protector/alts_counter.h',
-                      'src/core/tsi/alts/frame_protector/alts_crypter.h',
-                      'src/core/tsi/alts/frame_protector/alts_frame_protector.h',
-                      'src/core/tsi/alts/frame_protector/alts_record_protocol_crypter_common.h',
-                      'src/core/tsi/alts/frame_protector/frame_handler.h',
-                      'src/core/tsi/alts/handshaker/alts_handshaker_client.h',
-                      'src/core/tsi/alts/handshaker/alts_tsi_event.h',
-                      'src/core/tsi/alts/handshaker/alts_tsi_handshaker.h',
-                      'src/core/tsi/alts/handshaker/alts_tsi_handshaker_private.h',
-                      'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_integrity_only_record_protocol.h',
-                      'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_privacy_integrity_record_protocol.h',
-                      'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol.h',
-                      'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.h',
-                      'src/core/tsi/alts/zero_copy_frame_protector/alts_iovec_record_protocol.h',
-                      'src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.h',
-                      'src/core/lib/security/credentials/alts/check_gcp_environment.h',
-                      'src/core/lib/security/credentials/alts/grpc_alts_credentials_options.h',
-                      'src/core/tsi/alts/handshaker/alts_handshaker_service_api.h',
-                      'src/core/tsi/alts/handshaker/alts_handshaker_service_api_util.h',
-                      'src/core/tsi/alts/handshaker/alts_tsi_utils.h',
-                      'src/core/tsi/alts/handshaker/transport_security_common_api.h',
-                      'src/core/tsi/alts/handshaker/altscontext.pb.h',
-                      'src/core/tsi/alts/handshaker/handshaker.pb.h',
-                      'src/core/tsi/alts/handshaker/transport_security_common.pb.h',
-                      'third_party/nanopb/pb.h',
-                      'third_party/nanopb/pb_common.h',
-                      'third_party/nanopb/pb_decode.h',
-                      'third_party/nanopb/pb_encode.h',
-                      'src/core/tsi/transport_security.h',
-                      'src/core/tsi/transport_security_adapter.h',
-                      'src/core/tsi/transport_security_interface.h',
-                      'src/core/ext/transport/chttp2/client/chttp2_connector.h',
-                      'src/core/tsi/alts_transport_security.h',
-                      'src/core/tsi/fake_transport_security.h',
-                      'src/core/tsi/ssl/session_cache/ssl_session.h',
-                      'src/core/tsi/ssl/session_cache/ssl_session_cache.h',
-                      'src/core/tsi/ssl_transport_security.h',
-                      'src/core/tsi/ssl_types.h',
-                      'src/core/tsi/transport_security_grpc.h',
-                      'src/core/ext/transport/chttp2/server/chttp2_server.h',
-                      'src/core/lib/surface/init.cc',
-                      'src/core/lib/avl/avl.cc',
-                      'src/core/lib/backoff/backoff.cc',
-                      'src/core/lib/channel/channel_args.cc',
-                      'src/core/lib/channel/channel_stack.cc',
-                      'src/core/lib/channel/channel_stack_builder.cc',
-                      'src/core/lib/channel/channel_trace.cc',
-                      'src/core/lib/channel/channel_trace_registry.cc',
-                      'src/core/lib/channel/connected_channel.cc',
-                      'src/core/lib/channel/handshaker.cc',
-                      'src/core/lib/channel/handshaker_factory.cc',
-                      'src/core/lib/channel/handshaker_registry.cc',
-                      'src/core/lib/channel/status_util.cc',
-                      'src/core/lib/compression/compression.cc',
-                      'src/core/lib/compression/compression_internal.cc',
-                      'src/core/lib/compression/message_compress.cc',
-                      'src/core/lib/compression/stream_compression.cc',
-                      'src/core/lib/compression/stream_compression_gzip.cc',
-                      'src/core/lib/compression/stream_compression_identity.cc',
-                      'src/core/lib/debug/stats.cc',
-                      'src/core/lib/debug/stats_data.cc',
-                      'src/core/lib/http/format_request.cc',
-                      'src/core/lib/http/httpcli.cc',
-                      'src/core/lib/http/parser.cc',
-                      'src/core/lib/iomgr/call_combiner.cc',
-                      'src/core/lib/iomgr/combiner.cc',
-                      'src/core/lib/iomgr/endpoint.cc',
-                      'src/core/lib/iomgr/endpoint_pair_posix.cc',
-                      'src/core/lib/iomgr/endpoint_pair_uv.cc',
-                      'src/core/lib/iomgr/endpoint_pair_windows.cc',
-                      'src/core/lib/iomgr/error.cc',
-                      'src/core/lib/iomgr/ev_epoll1_linux.cc',
-                      'src/core/lib/iomgr/ev_epollex_linux.cc',
-                      'src/core/lib/iomgr/ev_epollsig_linux.cc',
-                      'src/core/lib/iomgr/ev_poll_posix.cc',
-                      'src/core/lib/iomgr/ev_posix.cc',
-                      'src/core/lib/iomgr/ev_windows.cc',
-                      'src/core/lib/iomgr/exec_ctx.cc',
-                      'src/core/lib/iomgr/executor.cc',
-                      'src/core/lib/iomgr/fork_posix.cc',
-                      'src/core/lib/iomgr/fork_windows.cc',
-                      'src/core/lib/iomgr/gethostname_fallback.cc',
-                      'src/core/lib/iomgr/gethostname_host_name_max.cc',
-                      'src/core/lib/iomgr/gethostname_sysconf.cc',
-                      'src/core/lib/iomgr/iocp_windows.cc',
-                      'src/core/lib/iomgr/iomgr.cc',
-                      'src/core/lib/iomgr/iomgr_custom.cc',
-                      'src/core/lib/iomgr/iomgr_internal.cc',
-                      'src/core/lib/iomgr/iomgr_posix.cc',
-                      'src/core/lib/iomgr/iomgr_uv.cc',
-                      'src/core/lib/iomgr/iomgr_windows.cc',
-                      'src/core/lib/iomgr/is_epollexclusive_available.cc',
-                      'src/core/lib/iomgr/load_file.cc',
-                      'src/core/lib/iomgr/lockfree_event.cc',
-                      'src/core/lib/iomgr/network_status_tracker.cc',
-                      'src/core/lib/iomgr/polling_entity.cc',
-                      'src/core/lib/iomgr/pollset.cc',
-                      'src/core/lib/iomgr/pollset_custom.cc',
-                      'src/core/lib/iomgr/pollset_set.cc',
-                      'src/core/lib/iomgr/pollset_set_custom.cc',
-                      'src/core/lib/iomgr/pollset_set_windows.cc',
-                      'src/core/lib/iomgr/pollset_uv.cc',
-                      'src/core/lib/iomgr/pollset_windows.cc',
-                      'src/core/lib/iomgr/resolve_address.cc',
-                      'src/core/lib/iomgr/resolve_address_custom.cc',
-                      'src/core/lib/iomgr/resolve_address_posix.cc',
-                      'src/core/lib/iomgr/resolve_address_windows.cc',
-                      'src/core/lib/iomgr/resource_quota.cc',
-                      'src/core/lib/iomgr/sockaddr_utils.cc',
-                      'src/core/lib/iomgr/socket_factory_posix.cc',
-                      'src/core/lib/iomgr/socket_mutator.cc',
-                      'src/core/lib/iomgr/socket_utils_common_posix.cc',
-                      'src/core/lib/iomgr/socket_utils_linux.cc',
-                      'src/core/lib/iomgr/socket_utils_posix.cc',
-                      'src/core/lib/iomgr/socket_utils_uv.cc',
-                      'src/core/lib/iomgr/socket_utils_windows.cc',
-                      'src/core/lib/iomgr/socket_windows.cc',
-                      'src/core/lib/iomgr/tcp_client.cc',
-                      'src/core/lib/iomgr/tcp_client_custom.cc',
-                      'src/core/lib/iomgr/tcp_client_posix.cc',
-                      'src/core/lib/iomgr/tcp_client_windows.cc',
-                      'src/core/lib/iomgr/tcp_custom.cc',
-                      'src/core/lib/iomgr/tcp_posix.cc',
-                      'src/core/lib/iomgr/tcp_server.cc',
-                      'src/core/lib/iomgr/tcp_server_custom.cc',
-                      'src/core/lib/iomgr/tcp_server_posix.cc',
-                      'src/core/lib/iomgr/tcp_server_utils_posix_common.cc',
-                      'src/core/lib/iomgr/tcp_server_utils_posix_ifaddrs.cc',
-                      'src/core/lib/iomgr/tcp_server_utils_posix_noifaddrs.cc',
-                      'src/core/lib/iomgr/tcp_server_windows.cc',
-                      'src/core/lib/iomgr/tcp_uv.cc',
-                      'src/core/lib/iomgr/tcp_windows.cc',
-                      'src/core/lib/iomgr/time_averaged_stats.cc',
-                      'src/core/lib/iomgr/timer.cc',
-                      'src/core/lib/iomgr/timer_custom.cc',
-                      'src/core/lib/iomgr/timer_generic.cc',
-                      'src/core/lib/iomgr/timer_heap.cc',
-                      'src/core/lib/iomgr/timer_manager.cc',
-                      'src/core/lib/iomgr/timer_uv.cc',
-                      'src/core/lib/iomgr/udp_server.cc',
-                      'src/core/lib/iomgr/unix_sockets_posix.cc',
-                      'src/core/lib/iomgr/unix_sockets_posix_noop.cc',
-                      'src/core/lib/iomgr/wakeup_fd_cv.cc',
-                      'src/core/lib/iomgr/wakeup_fd_eventfd.cc',
-                      'src/core/lib/iomgr/wakeup_fd_nospecial.cc',
-                      'src/core/lib/iomgr/wakeup_fd_pipe.cc',
-                      'src/core/lib/iomgr/wakeup_fd_posix.cc',
-                      'src/core/lib/json/json.cc',
-                      'src/core/lib/json/json_reader.cc',
-                      'src/core/lib/json/json_string.cc',
-                      'src/core/lib/json/json_writer.cc',
-                      'src/core/lib/slice/b64.cc',
-                      'src/core/lib/slice/percent_encoding.cc',
-                      'src/core/lib/slice/slice.cc',
-                      'src/core/lib/slice/slice_buffer.cc',
-                      'src/core/lib/slice/slice_intern.cc',
-                      'src/core/lib/slice/slice_string_helpers.cc',
-                      'src/core/lib/surface/api_trace.cc',
-                      'src/core/lib/surface/byte_buffer.cc',
-                      'src/core/lib/surface/byte_buffer_reader.cc',
-                      'src/core/lib/surface/call.cc',
-                      'src/core/lib/surface/call_details.cc',
-                      'src/core/lib/surface/call_log_batch.cc',
-                      'src/core/lib/surface/channel.cc',
-                      'src/core/lib/surface/channel_init.cc',
-                      'src/core/lib/surface/channel_ping.cc',
-                      'src/core/lib/surface/channel_stack_type.cc',
-                      'src/core/lib/surface/completion_queue.cc',
-                      'src/core/lib/surface/completion_queue_factory.cc',
-                      'src/core/lib/surface/event_string.cc',
-                      'src/core/lib/surface/lame_client.cc',
-                      'src/core/lib/surface/metadata_array.cc',
-                      'src/core/lib/surface/server.cc',
-                      'src/core/lib/surface/validate_metadata.cc',
-                      'src/core/lib/surface/version.cc',
-                      'src/core/lib/transport/bdp_estimator.cc',
-                      'src/core/lib/transport/byte_stream.cc',
-                      'src/core/lib/transport/connectivity_state.cc',
-                      'src/core/lib/transport/error_utils.cc',
-                      'src/core/lib/transport/metadata.cc',
-                      'src/core/lib/transport/metadata_batch.cc',
-                      'src/core/lib/transport/pid_controller.cc',
-                      'src/core/lib/transport/service_config.cc',
-                      'src/core/lib/transport/static_metadata.cc',
-                      'src/core/lib/transport/status_conversion.cc',
-                      'src/core/lib/transport/status_metadata.cc',
-                      'src/core/lib/transport/timeout_encoding.cc',
-                      'src/core/lib/transport/transport.cc',
-                      'src/core/lib/transport/transport_op_string.cc',
-                      'src/core/lib/debug/trace.cc',
-                      'src/core/ext/filters/deadline/deadline_filter.cc',
-                      'src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc',
-                      'src/core/ext/filters/client_channel/backup_poller.cc',
-                      'src/core/ext/filters/client_channel/channel_connectivity.cc',
-                      'src/core/ext/filters/client_channel/client_channel.cc',
-                      'src/core/ext/filters/client_channel/client_channel_factory.cc',
-                      'src/core/ext/filters/client_channel/client_channel_plugin.cc',
-                      'src/core/ext/filters/client_channel/connector.cc',
-                      'src/core/ext/filters/client_channel/http_connect_handshaker.cc',
-                      'src/core/ext/filters/client_channel/http_proxy.cc',
-                      'src/core/ext/filters/client_channel/lb_policy.cc',
-                      'src/core/ext/filters/client_channel/lb_policy_factory.cc',
-                      'src/core/ext/filters/client_channel/lb_policy_registry.cc',
-                      'src/core/ext/filters/client_channel/method_params.cc',
-                      'src/core/ext/filters/client_channel/parse_address.cc',
-                      'src/core/ext/filters/client_channel/proxy_mapper.cc',
-                      'src/core/ext/filters/client_channel/proxy_mapper_registry.cc',
-                      'src/core/ext/filters/client_channel/resolver.cc',
-                      'src/core/ext/filters/client_channel/resolver_registry.cc',
-                      'src/core/ext/filters/client_channel/retry_throttle.cc',
-                      'src/core/ext/filters/client_channel/subchannel.cc',
-                      'src/core/ext/filters/client_channel/subchannel_index.cc',
-                      'src/core/ext/filters/client_channel/uri_parser.cc',
-                      'src/core/ext/filters/client_channel/lb_policy/subchannel_list.cc',
-                      'src/core/ext/filters/max_age/max_age_filter.cc',
-                      'src/core/ext/filters/message_size/message_size_filter.cc',
-                      'src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc',
-                      'src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.cc',
-                      'src/core/ext/filters/load_reporting/server_load_reporting_filter.cc',
-                      'src/core/ext/filters/load_reporting/server_load_reporting_plugin.cc',
-                      'src/core/ext/transport/cronet/client/secure/cronet_channel_create.cc',
+    ss.dependency "#{s.name}/Interface", version
+    ss.dependency "#{s.name}/Implementation", version
+    ss.dependency "#{s.name}/Cronet-Interface", version
+
+    ss.source_files = 'src/core/ext/transport/cronet/client/secure/cronet_channel_create.cc',
                       'src/core/ext/transport/cronet/transport/cronet_transport.cc',
-                      'src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc',
-                      'src/core/ext/transport/chttp2/transport/bin_decoder.cc',
-                      'src/core/ext/transport/chttp2/transport/bin_encoder.cc',
-                      'src/core/ext/transport/chttp2/transport/chttp2_plugin.cc',
-                      'src/core/ext/transport/chttp2/transport/chttp2_transport.cc',
-                      'src/core/ext/transport/chttp2/transport/flow_control.cc',
-                      'src/core/ext/transport/chttp2/transport/frame_data.cc',
-                      'src/core/ext/transport/chttp2/transport/frame_goaway.cc',
-                      'src/core/ext/transport/chttp2/transport/frame_ping.cc',
-                      'src/core/ext/transport/chttp2/transport/frame_rst_stream.cc',
-                      'src/core/ext/transport/chttp2/transport/frame_settings.cc',
-                      'src/core/ext/transport/chttp2/transport/frame_window_update.cc',
-                      'src/core/ext/transport/chttp2/transport/hpack_encoder.cc',
-                      'src/core/ext/transport/chttp2/transport/hpack_parser.cc',
-                      'src/core/ext/transport/chttp2/transport/hpack_table.cc',
-                      'src/core/ext/transport/chttp2/transport/http2_settings.cc',
-                      'src/core/ext/transport/chttp2/transport/huffsyms.cc',
-                      'src/core/ext/transport/chttp2/transport/incoming_metadata.cc',
-                      'src/core/ext/transport/chttp2/transport/parsing.cc',
-                      'src/core/ext/transport/chttp2/transport/stream_lists.cc',
-                      'src/core/ext/transport/chttp2/transport/stream_map.cc',
-                      'src/core/ext/transport/chttp2/transport/varint.cc',
-                      'src/core/ext/transport/chttp2/transport/writing.cc',
-                      'src/core/ext/transport/chttp2/alpn/alpn.cc',
-                      'src/core/ext/filters/http/client/http_client_filter.cc',
-                      'src/core/ext/filters/http/http_filters_plugin.cc',
-                      'src/core/ext/filters/http/message_compress/message_compress_filter.cc',
-                      'src/core/ext/filters/http/server/http_server_filter.cc',
-                      'src/core/lib/http/httpcli_security_connector.cc',
-                      'src/core/lib/security/context/security_context.cc',
-                      'src/core/lib/security/credentials/alts/alts_credentials.cc',
-                      'src/core/lib/security/credentials/composite/composite_credentials.cc',
-                      'src/core/lib/security/credentials/credentials.cc',
-                      'src/core/lib/security/credentials/credentials_metadata.cc',
-                      'src/core/lib/security/credentials/fake/fake_credentials.cc',
-                      'src/core/lib/security/credentials/google_default/credentials_generic.cc',
-                      'src/core/lib/security/credentials/google_default/google_default_credentials.cc',
-                      'src/core/lib/security/credentials/iam/iam_credentials.cc',
-                      'src/core/lib/security/credentials/jwt/json_token.cc',
-                      'src/core/lib/security/credentials/jwt/jwt_credentials.cc',
-                      'src/core/lib/security/credentials/jwt/jwt_verifier.cc',
-                      'src/core/lib/security/credentials/oauth2/oauth2_credentials.cc',
-                      'src/core/lib/security/credentials/plugin/plugin_credentials.cc',
-                      'src/core/lib/security/credentials/ssl/ssl_credentials.cc',
-                      'src/core/lib/security/security_connector/alts_security_connector.cc',
-                      'src/core/lib/security/security_connector/security_connector.cc',
-                      'src/core/lib/security/transport/client_auth_filter.cc',
-                      'src/core/lib/security/transport/secure_endpoint.cc',
-                      'src/core/lib/security/transport/security_handshaker.cc',
-                      'src/core/lib/security/transport/server_auth_filter.cc',
-                      'src/core/lib/security/transport/target_authority_table.cc',
-                      'src/core/lib/security/transport/tsi_error.cc',
-                      'src/core/lib/security/util/json_util.cc',
-                      'src/core/lib/surface/init_secure.cc',
-                      'src/core/tsi/alts/crypt/aes_gcm.cc',
-                      'src/core/tsi/alts/crypt/gsec.cc',
-                      'src/core/tsi/alts/frame_protector/alts_counter.cc',
-                      'src/core/tsi/alts/frame_protector/alts_crypter.cc',
-                      'src/core/tsi/alts/frame_protector/alts_frame_protector.cc',
-                      'src/core/tsi/alts/frame_protector/alts_record_protocol_crypter_common.cc',
-                      'src/core/tsi/alts/frame_protector/alts_seal_privacy_integrity_crypter.cc',
-                      'src/core/tsi/alts/frame_protector/alts_unseal_privacy_integrity_crypter.cc',
-                      'src/core/tsi/alts/frame_protector/frame_handler.cc',
-                      'src/core/tsi/alts/handshaker/alts_handshaker_client.cc',
-                      'src/core/tsi/alts/handshaker/alts_tsi_event.cc',
-                      'src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc',
-                      'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_integrity_only_record_protocol.cc',
-                      'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_privacy_integrity_record_protocol.cc',
-                      'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.cc',
-                      'src/core/tsi/alts/zero_copy_frame_protector/alts_iovec_record_protocol.cc',
-                      'src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.cc',
-                      'src/core/lib/security/credentials/alts/check_gcp_environment.cc',
-                      'src/core/lib/security/credentials/alts/check_gcp_environment_linux.cc',
-                      'src/core/lib/security/credentials/alts/check_gcp_environment_no_op.cc',
-                      'src/core/lib/security/credentials/alts/check_gcp_environment_windows.cc',
-                      'src/core/lib/security/credentials/alts/grpc_alts_credentials_client_options.cc',
-                      'src/core/lib/security/credentials/alts/grpc_alts_credentials_options.cc',
-                      'src/core/lib/security/credentials/alts/grpc_alts_credentials_server_options.cc',
-                      'src/core/tsi/alts/handshaker/alts_handshaker_service_api.cc',
-                      'src/core/tsi/alts/handshaker/alts_handshaker_service_api_util.cc',
-                      'src/core/tsi/alts/handshaker/alts_tsi_utils.cc',
-                      'src/core/tsi/alts/handshaker/transport_security_common_api.cc',
-                      'src/core/tsi/alts/handshaker/altscontext.pb.c',
-                      'src/core/tsi/alts/handshaker/handshaker.pb.c',
-                      'src/core/tsi/alts/handshaker/transport_security_common.pb.c',
                       'third_party/nanopb/pb_common.c',
                       'third_party/nanopb/pb_decode.c',
                       'third_party/nanopb/pb_encode.c',
-                      'src/core/tsi/transport_security.cc',
-                      'src/core/tsi/transport_security_adapter.cc',
-                      'src/core/ext/transport/chttp2/client/insecure/channel_create.cc',
-                      'src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc',
-                      'src/core/ext/transport/chttp2/client/chttp2_connector.cc',
-                      'src/core/tsi/alts_transport_security.cc',
-                      'src/core/tsi/fake_transport_security.cc',
-                      'src/core/tsi/ssl/session_cache/ssl_session_boringssl.cc',
-                      'src/core/tsi/ssl/session_cache/ssl_session_cache.cc',
-                      'src/core/tsi/ssl/session_cache/ssl_session_openssl.cc',
-                      'src/core/tsi/ssl_transport_security.cc',
-                      'src/core/tsi/transport_security_grpc.cc',
-                      'src/core/ext/transport/chttp2/server/secure/server_secure_chttp2.cc',
-                      'src/core/ext/transport/chttp2/server/chttp2_server.cc',
-                      'src/core/plugin_registry/grpc_cronet_plugin_registry.cc'
-
-    ss.private_header_files = 'src/core/lib/gpr/arena.h',
-                              'src/core/lib/gpr/env.h',
-                              'src/core/lib/gpr/fork.h',
-                              'src/core/lib/gpr/host_port.h',
-                              'src/core/lib/gpr/mpscq.h',
-                              'src/core/lib/gpr/murmur_hash.h',
-                              'src/core/lib/gpr/spinlock.h',
-                              'src/core/lib/gpr/string.h',
-                              'src/core/lib/gpr/string_windows.h',
-                              'src/core/lib/gpr/time_precise.h',
-                              'src/core/lib/gpr/tls.h',
-                              'src/core/lib/gpr/tls_gcc.h',
-                              'src/core/lib/gpr/tls_msvc.h',
-                              'src/core/lib/gpr/tls_pthread.h',
-                              'src/core/lib/gpr/tmpfile.h',
-                              'src/core/lib/gpr/useful.h',
-                              'src/core/lib/gprpp/abstract.h',
-                              'src/core/lib/gprpp/atomic.h',
-                              'src/core/lib/gprpp/atomic_with_atm.h',
-                              'src/core/lib/gprpp/atomic_with_std.h',
-                              'src/core/lib/gprpp/manual_constructor.h',
-                              'src/core/lib/gprpp/memory.h',
-                              'src/core/lib/gprpp/thd.h',
-                              'src/core/lib/profiling/timers.h',
-                              'src/core/lib/avl/avl.h',
-                              'src/core/lib/backoff/backoff.h',
-                              'src/core/lib/channel/channel_args.h',
-                              'src/core/lib/channel/channel_stack.h',
-                              'src/core/lib/channel/channel_stack_builder.h',
-                              'src/core/lib/channel/channel_trace.h',
-                              'src/core/lib/channel/channel_trace_registry.h',
-                              'src/core/lib/channel/connected_channel.h',
-                              'src/core/lib/channel/context.h',
-                              'src/core/lib/channel/handshaker.h',
-                              'src/core/lib/channel/handshaker_factory.h',
-                              'src/core/lib/channel/handshaker_registry.h',
-                              'src/core/lib/channel/status_util.h',
-                              'src/core/lib/compression/algorithm_metadata.h',
-                              'src/core/lib/compression/compression_internal.h',
-                              'src/core/lib/compression/message_compress.h',
-                              'src/core/lib/compression/stream_compression.h',
-                              'src/core/lib/compression/stream_compression_gzip.h',
-                              'src/core/lib/compression/stream_compression_identity.h',
-                              'src/core/lib/debug/stats.h',
-                              'src/core/lib/debug/stats_data.h',
-                              'src/core/lib/gprpp/debug_location.h',
-                              'src/core/lib/gprpp/inlined_vector.h',
-                              'src/core/lib/gprpp/orphanable.h',
-                              'src/core/lib/gprpp/ref_counted.h',
-                              'src/core/lib/gprpp/ref_counted_ptr.h',
-                              'src/core/lib/http/format_request.h',
-                              'src/core/lib/http/httpcli.h',
-                              'src/core/lib/http/parser.h',
-                              'src/core/lib/iomgr/block_annotate.h',
-                              'src/core/lib/iomgr/call_combiner.h',
-                              'src/core/lib/iomgr/closure.h',
-                              'src/core/lib/iomgr/combiner.h',
-                              'src/core/lib/iomgr/endpoint.h',
-                              'src/core/lib/iomgr/endpoint_pair.h',
-                              'src/core/lib/iomgr/error.h',
-                              'src/core/lib/iomgr/error_internal.h',
-                              'src/core/lib/iomgr/ev_epoll1_linux.h',
-                              'src/core/lib/iomgr/ev_epollex_linux.h',
-                              'src/core/lib/iomgr/ev_epollsig_linux.h',
-                              'src/core/lib/iomgr/ev_poll_posix.h',
-                              'src/core/lib/iomgr/ev_posix.h',
-                              'src/core/lib/iomgr/exec_ctx.h',
-                              'src/core/lib/iomgr/executor.h',
-                              'src/core/lib/iomgr/gethostname.h',
-                              'src/core/lib/iomgr/iocp_windows.h',
-                              'src/core/lib/iomgr/iomgr.h',
-                              'src/core/lib/iomgr/iomgr_custom.h',
-                              'src/core/lib/iomgr/iomgr_internal.h',
-                              'src/core/lib/iomgr/iomgr_posix.h',
-                              'src/core/lib/iomgr/is_epollexclusive_available.h',
-                              'src/core/lib/iomgr/load_file.h',
-                              'src/core/lib/iomgr/lockfree_event.h',
-                              'src/core/lib/iomgr/nameser.h',
-                              'src/core/lib/iomgr/network_status_tracker.h',
-                              'src/core/lib/iomgr/polling_entity.h',
-                              'src/core/lib/iomgr/pollset.h',
-                              'src/core/lib/iomgr/pollset_custom.h',
-                              'src/core/lib/iomgr/pollset_set.h',
-                              'src/core/lib/iomgr/pollset_set_custom.h',
-                              'src/core/lib/iomgr/pollset_set_windows.h',
-                              'src/core/lib/iomgr/pollset_windows.h',
-                              'src/core/lib/iomgr/port.h',
-                              'src/core/lib/iomgr/resolve_address.h',
-                              'src/core/lib/iomgr/resolve_address_custom.h',
-                              'src/core/lib/iomgr/resource_quota.h',
-                              'src/core/lib/iomgr/sockaddr.h',
-                              'src/core/lib/iomgr/sockaddr_custom.h',
-                              'src/core/lib/iomgr/sockaddr_posix.h',
-                              'src/core/lib/iomgr/sockaddr_utils.h',
-                              'src/core/lib/iomgr/sockaddr_windows.h',
-                              'src/core/lib/iomgr/socket_factory_posix.h',
-                              'src/core/lib/iomgr/socket_mutator.h',
-                              'src/core/lib/iomgr/socket_utils.h',
-                              'src/core/lib/iomgr/socket_utils_posix.h',
-                              'src/core/lib/iomgr/socket_windows.h',
-                              'src/core/lib/iomgr/sys_epoll_wrapper.h',
-                              'src/core/lib/iomgr/tcp_client.h',
-                              'src/core/lib/iomgr/tcp_client_posix.h',
-                              'src/core/lib/iomgr/tcp_custom.h',
-                              'src/core/lib/iomgr/tcp_posix.h',
-                              'src/core/lib/iomgr/tcp_server.h',
-                              'src/core/lib/iomgr/tcp_server_utils_posix.h',
-                              'src/core/lib/iomgr/tcp_windows.h',
-                              'src/core/lib/iomgr/time_averaged_stats.h',
-                              'src/core/lib/iomgr/timer.h',
-                              'src/core/lib/iomgr/timer_custom.h',
-                              'src/core/lib/iomgr/timer_heap.h',
-                              'src/core/lib/iomgr/timer_manager.h',
-                              'src/core/lib/iomgr/udp_server.h',
-                              'src/core/lib/iomgr/unix_sockets_posix.h',
-                              'src/core/lib/iomgr/wakeup_fd_cv.h',
-                              'src/core/lib/iomgr/wakeup_fd_pipe.h',
-                              'src/core/lib/iomgr/wakeup_fd_posix.h',
-                              'src/core/lib/json/json.h',
-                              'src/core/lib/json/json_common.h',
-                              'src/core/lib/json/json_reader.h',
-                              'src/core/lib/json/json_writer.h',
-                              'src/core/lib/slice/b64.h',
-                              'src/core/lib/slice/percent_encoding.h',
-                              'src/core/lib/slice/slice_hash_table.h',
-                              'src/core/lib/slice/slice_internal.h',
-                              'src/core/lib/slice/slice_string_helpers.h',
-                              'src/core/lib/slice/slice_weak_hash_table.h',
-                              'src/core/lib/surface/api_trace.h',
-                              'src/core/lib/surface/call.h',
-                              'src/core/lib/surface/call_test_only.h',
-                              'src/core/lib/surface/channel.h',
-                              'src/core/lib/surface/channel_init.h',
-                              'src/core/lib/surface/channel_stack_type.h',
-                              'src/core/lib/surface/completion_queue.h',
-                              'src/core/lib/surface/completion_queue_factory.h',
-                              'src/core/lib/surface/event_string.h',
-                              'src/core/lib/surface/init.h',
-                              'src/core/lib/surface/lame_client.h',
-                              'src/core/lib/surface/server.h',
-                              'src/core/lib/surface/validate_metadata.h',
-                              'src/core/lib/transport/bdp_estimator.h',
-                              'src/core/lib/transport/byte_stream.h',
-                              'src/core/lib/transport/connectivity_state.h',
-                              'src/core/lib/transport/error_utils.h',
-                              'src/core/lib/transport/http2_errors.h',
-                              'src/core/lib/transport/metadata.h',
-                              'src/core/lib/transport/metadata_batch.h',
-                              'src/core/lib/transport/pid_controller.h',
-                              'src/core/lib/transport/service_config.h',
-                              'src/core/lib/transport/static_metadata.h',
-                              'src/core/lib/transport/status_conversion.h',
-                              'src/core/lib/transport/status_metadata.h',
-                              'src/core/lib/transport/timeout_encoding.h',
-                              'src/core/lib/transport/transport.h',
-                              'src/core/lib/transport/transport_impl.h',
-                              'src/core/lib/debug/trace.h',
-                              'src/core/ext/filters/deadline/deadline_filter.h',
-                              'src/core/ext/filters/client_channel/backup_poller.h',
-                              'src/core/ext/filters/client_channel/client_channel.h',
-                              'src/core/ext/filters/client_channel/client_channel_factory.h',
-                              'src/core/ext/filters/client_channel/connector.h',
-                              'src/core/ext/filters/client_channel/http_connect_handshaker.h',
-                              'src/core/ext/filters/client_channel/http_proxy.h',
-                              'src/core/ext/filters/client_channel/lb_policy.h',
-                              'src/core/ext/filters/client_channel/lb_policy_factory.h',
-                              'src/core/ext/filters/client_channel/lb_policy_registry.h',
-                              'src/core/ext/filters/client_channel/method_params.h',
-                              'src/core/ext/filters/client_channel/parse_address.h',
-                              'src/core/ext/filters/client_channel/proxy_mapper.h',
-                              'src/core/ext/filters/client_channel/proxy_mapper_registry.h',
-                              'src/core/ext/filters/client_channel/resolver.h',
-                              'src/core/ext/filters/client_channel/resolver_factory.h',
-                              'src/core/ext/filters/client_channel/resolver_registry.h',
-                              'src/core/ext/filters/client_channel/retry_throttle.h',
-                              'src/core/ext/filters/client_channel/subchannel.h',
-                              'src/core/ext/filters/client_channel/subchannel_index.h',
-                              'src/core/ext/filters/client_channel/uri_parser.h',
-                              'src/core/ext/filters/client_channel/lb_policy/subchannel_list.h',
-                              'src/core/ext/filters/max_age/max_age_filter.h',
-                              'src/core/ext/filters/message_size/message_size_filter.h',
-                              'src/core/ext/filters/load_reporting/server_load_reporting_filter.h',
-                              'src/core/ext/filters/load_reporting/server_load_reporting_plugin.h',
-                              'src/core/ext/transport/cronet/transport/cronet_transport.h',
-                              'third_party/objective_c/Cronet/bidirectional_stream_c.h',
-                              'src/core/ext/transport/chttp2/transport/bin_decoder.h',
-                              'src/core/ext/transport/chttp2/transport/bin_encoder.h',
-                              'src/core/ext/transport/chttp2/transport/chttp2_transport.h',
-                              'src/core/ext/transport/chttp2/transport/flow_control.h',
-                              'src/core/ext/transport/chttp2/transport/frame.h',
-                              'src/core/ext/transport/chttp2/transport/frame_data.h',
-                              'src/core/ext/transport/chttp2/transport/frame_goaway.h',
-                              'src/core/ext/transport/chttp2/transport/frame_ping.h',
-                              'src/core/ext/transport/chttp2/transport/frame_rst_stream.h',
-                              'src/core/ext/transport/chttp2/transport/frame_settings.h',
-                              'src/core/ext/transport/chttp2/transport/frame_window_update.h',
-                              'src/core/ext/transport/chttp2/transport/hpack_encoder.h',
-                              'src/core/ext/transport/chttp2/transport/hpack_parser.h',
-                              'src/core/ext/transport/chttp2/transport/hpack_table.h',
-                              'src/core/ext/transport/chttp2/transport/http2_settings.h',
-                              'src/core/ext/transport/chttp2/transport/huffsyms.h',
-                              'src/core/ext/transport/chttp2/transport/incoming_metadata.h',
-                              'src/core/ext/transport/chttp2/transport/internal.h',
-                              'src/core/ext/transport/chttp2/transport/stream_map.h',
-                              'src/core/ext/transport/chttp2/transport/varint.h',
-                              'src/core/ext/transport/chttp2/alpn/alpn.h',
-                              'src/core/ext/filters/http/client/http_client_filter.h',
-                              'src/core/ext/filters/http/message_compress/message_compress_filter.h',
-                              'src/core/ext/filters/http/server/http_server_filter.h',
-                              'src/core/lib/security/context/security_context.h',
-                              'src/core/lib/security/credentials/alts/alts_credentials.h',
-                              'src/core/lib/security/credentials/composite/composite_credentials.h',
-                              'src/core/lib/security/credentials/credentials.h',
-                              'src/core/lib/security/credentials/fake/fake_credentials.h',
-                              'src/core/lib/security/credentials/google_default/google_default_credentials.h',
-                              'src/core/lib/security/credentials/iam/iam_credentials.h',
-                              'src/core/lib/security/credentials/jwt/json_token.h',
-                              'src/core/lib/security/credentials/jwt/jwt_credentials.h',
-                              'src/core/lib/security/credentials/jwt/jwt_verifier.h',
-                              'src/core/lib/security/credentials/oauth2/oauth2_credentials.h',
-                              'src/core/lib/security/credentials/plugin/plugin_credentials.h',
-                              'src/core/lib/security/credentials/ssl/ssl_credentials.h',
-                              'src/core/lib/security/security_connector/alts_security_connector.h',
-                              'src/core/lib/security/security_connector/security_connector.h',
-                              'src/core/lib/security/transport/auth_filters.h',
-                              'src/core/lib/security/transport/secure_endpoint.h',
-                              'src/core/lib/security/transport/security_handshaker.h',
-                              'src/core/lib/security/transport/target_authority_table.h',
-                              'src/core/lib/security/transport/tsi_error.h',
-                              'src/core/lib/security/util/json_util.h',
-                              'src/core/tsi/alts/crypt/gsec.h',
-                              'src/core/tsi/alts/frame_protector/alts_counter.h',
-                              'src/core/tsi/alts/frame_protector/alts_crypter.h',
-                              'src/core/tsi/alts/frame_protector/alts_frame_protector.h',
-                              'src/core/tsi/alts/frame_protector/alts_record_protocol_crypter_common.h',
-                              'src/core/tsi/alts/frame_protector/frame_handler.h',
-                              'src/core/tsi/alts/handshaker/alts_handshaker_client.h',
-                              'src/core/tsi/alts/handshaker/alts_tsi_event.h',
-                              'src/core/tsi/alts/handshaker/alts_tsi_handshaker.h',
-                              'src/core/tsi/alts/handshaker/alts_tsi_handshaker_private.h',
-                              'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_integrity_only_record_protocol.h',
-                              'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_privacy_integrity_record_protocol.h',
-                              'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol.h',
-                              'src/core/tsi/alts/zero_copy_frame_protector/alts_grpc_record_protocol_common.h',
-                              'src/core/tsi/alts/zero_copy_frame_protector/alts_iovec_record_protocol.h',
-                              'src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.h',
-                              'src/core/lib/security/credentials/alts/check_gcp_environment.h',
-                              'src/core/lib/security/credentials/alts/grpc_alts_credentials_options.h',
-                              'src/core/tsi/alts/handshaker/alts_handshaker_service_api.h',
-                              'src/core/tsi/alts/handshaker/alts_handshaker_service_api_util.h',
-                              'src/core/tsi/alts/handshaker/alts_tsi_utils.h',
-                              'src/core/tsi/alts/handshaker/transport_security_common_api.h',
-                              'src/core/tsi/alts/handshaker/altscontext.pb.h',
-                              'src/core/tsi/alts/handshaker/handshaker.pb.h',
-                              'src/core/tsi/alts/handshaker/transport_security_common.pb.h',
-                              'third_party/nanopb/pb.h',
-                              'third_party/nanopb/pb_common.h',
-                              'third_party/nanopb/pb_decode.h',
-                              'third_party/nanopb/pb_encode.h',
-                              'src/core/tsi/transport_security.h',
-                              'src/core/tsi/transport_security_adapter.h',
-                              'src/core/tsi/transport_security_interface.h',
-                              'src/core/ext/transport/chttp2/client/chttp2_connector.h',
-                              'src/core/tsi/alts_transport_security.h',
-                              'src/core/tsi/fake_transport_security.h',
-                              'src/core/tsi/ssl/session_cache/ssl_session.h',
-                              'src/core/tsi/ssl/session_cache/ssl_session_cache.h',
-                              'src/core/tsi/ssl_transport_security.h',
-                              'src/core/tsi/ssl_types.h',
-                              'src/core/tsi/transport_security_grpc.h',
-                              'src/core/ext/transport/chttp2/server/chttp2_server.h'
+                      'src/core/ext/transport/cronet/transport/cronet_transport.h',
+                      'third_party/objective_c/Cronet/bidirectional_stream_c.h',
+                      'third_party/nanopb/pb.h',
+                      'third_party/nanopb/pb_common.h',
+                      'third_party/nanopb/pb_decode.h',
+                      'third_party/nanopb/pb_encode.h'
   end
 
-  s.subspec 'Cronet-Tests' do |ss|
+  s.subspec 'Tests' do |ss|
     ss.header_mappings_dir = '.'
 
-    ss.dependency "#{s.name}/Cronet-Interface", version
-    ss.dependency "#{s.name}/Cronet-Implementation", version
+    ss.dependency "#{s.name}/Interface", version
+    ss.dependency "#{s.name}/Implementation", version
 
     ss.source_files = 'test/core/util/test_config.cc',
                       'test/core/util/test_config.h',
@@ -2038,6 +1123,7 @@
                       'test/core/end2end/fixtures/proxy.cc',
                       'test/core/iomgr/endpoint_tests.cc',
                       'test/core/util/debugger_macros.cc',
+                      'test/core/util/fuzzer_util.cc',
                       'test/core/util/grpc_profiler.cc',
                       'test/core/util/histogram.cc',
                       'test/core/util/memory_counters.cc',
@@ -2060,6 +1146,7 @@
                       'test/core/end2end/fixtures/proxy.h',
                       'test/core/iomgr/endpoint_tests.h',
                       'test/core/util/debugger_macros.h',
+                      'test/core/util/fuzzer_util.h',
                       'test/core/util/grpc_profiler.h',
                       'test/core/util/histogram.h',
                       'test/core/util/memory_counters.h',
@@ -2080,6 +1167,7 @@
                       'test/core/end2end/tests/bad_ping.cc',
                       'test/core/end2end/tests/binary_metadata.cc',
                       'test/core/end2end/tests/call_creds.cc',
+                      'test/core/end2end/tests/call_host_override.cc',
                       'test/core/end2end/tests/cancel_after_accept.cc',
                       'test/core/end2end/tests/cancel_after_client_done.cc',
                       'test/core/end2end/tests/cancel_after_invoke.cc',
@@ -2126,6 +1214,7 @@
                       'test/core/end2end/tests/retry_exceeds_buffer_size_in_initial_batch.cc',
                       'test/core/end2end/tests/retry_exceeds_buffer_size_in_subsequent_batch.cc',
                       'test/core/end2end/tests/retry_non_retriable_status.cc',
+                      'test/core/end2end/tests/retry_non_retriable_status_before_recv_trailing_metadata_started.cc',
                       'test/core/end2end/tests/retry_recv_initial_metadata.cc',
                       'test/core/end2end/tests/retry_recv_message.cc',
                       'test/core/end2end/tests/retry_server_pushback_delay.cc',
diff --git a/gRPC-ProtoRPC.podspec b/gRPC-ProtoRPC.podspec
index 149687e..17e650c 100644
--- a/gRPC-ProtoRPC.podspec
+++ b/gRPC-ProtoRPC.podspec
@@ -21,7 +21,7 @@
 
 Pod::Spec.new do |s|
   s.name     = 'gRPC-ProtoRPC'
-  version = '1.11.0-dev'
+  version = '1.13.0-dev'
   s.version  = version
   s.summary  = 'RPC library for Protocol Buffers, based on gRPC'
   s.homepage = 'https://grpc.io'
diff --git a/gRPC-RxLibrary.podspec b/gRPC-RxLibrary.podspec
index 2497174..b9288af 100644
--- a/gRPC-RxLibrary.podspec
+++ b/gRPC-RxLibrary.podspec
@@ -21,7 +21,7 @@
 
 Pod::Spec.new do |s|
   s.name     = 'gRPC-RxLibrary'
-  version = '1.11.0-dev'
+  version = '1.13.0-dev'
   s.version  = version
   s.summary  = 'Reactive Extensions library for iOS/OSX.'
   s.homepage = 'https://grpc.io'
diff --git a/gRPC.podspec b/gRPC.podspec
index 68e06b5..afc4581 100644
--- a/gRPC.podspec
+++ b/gRPC.podspec
@@ -20,7 +20,7 @@
 
 Pod::Spec.new do |s|
   s.name     = 'gRPC'
-  version = '1.11.0-dev'
+  version = '1.13.0-dev'
   s.version  = version
   s.summary  = 'gRPC client library for iOS/OSX'
   s.homepage = 'https://grpc.io'
diff --git a/grpc.def b/grpc.def
index d64629f..6a91214 100644
--- a/grpc.def
+++ b/grpc.def
@@ -115,6 +115,12 @@
     grpc_server_add_secure_http2_port
     grpc_call_set_credentials
     grpc_server_credentials_set_auth_metadata_processor
+    grpc_alts_credentials_client_options_create
+    grpc_alts_credentials_server_options_create
+    grpc_alts_credentials_client_options_add_target_service_account
+    grpc_alts_credentials_options_destroy
+    grpc_alts_credentials_create
+    grpc_alts_server_credentials_create
     grpc_raw_byte_buffer_create
     grpc_raw_compressed_byte_buffer_create
     grpc_byte_buffer_copy
@@ -185,6 +191,7 @@
     gpr_cpu_current_cpu
     gpr_log_severity_string
     gpr_log
+    gpr_should_log
     gpr_log_message
     gpr_set_log_verbosity
     gpr_log_verbosity_init
diff --git a/grpc.gemspec b/grpc.gemspec
index 920254a..2a66801 100644
--- a/grpc.gemspec
+++ b/grpc.gemspec
@@ -201,6 +201,7 @@
   s.files += %w( src/core/ext/filters/http/client/http_client_filter.h )
   s.files += %w( src/core/ext/filters/http/message_compress/message_compress_filter.h )
   s.files += %w( src/core/ext/filters/http/server/http_server_filter.h )
+  s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h )
   s.files += %w( src/core/lib/security/context/security_context.h )
   s.files += %w( src/core/lib/security/credentials/alts/alts_credentials.h )
   s.files += %w( src/core/lib/security/credentials/composite/composite_credentials.h )
@@ -252,8 +253,8 @@
   s.files += %w( third_party/nanopb/pb_decode.h )
   s.files += %w( third_party/nanopb/pb_encode.h )
   s.files += %w( src/core/tsi/transport_security.h )
-  s.files += %w( src/core/tsi/transport_security_adapter.h )
   s.files += %w( src/core/tsi/transport_security_interface.h )
+  s.files += %w( src/core/ext/transport/chttp2/client/authority.h )
   s.files += %w( src/core/ext/transport/chttp2/client/chttp2_connector.h )
   s.files += %w( src/core/ext/filters/client_channel/backup_poller.h )
   s.files += %w( src/core/ext/filters/client_channel/client_channel.h )
@@ -431,6 +432,7 @@
   s.files += %w( src/core/ext/filters/load_reporting/server_load_reporting_plugin.h )
   s.files += %w( src/core/ext/filters/max_age/max_age_filter.h )
   s.files += %w( src/core/ext/filters/message_size/message_size_filter.h )
+  s.files += %w( src/core/ext/filters/http/client_authority_filter.h )
   s.files += %w( src/core/ext/filters/workarounds/workaround_cronet_compression_filter.h )
   s.files += %w( src/core/ext/filters/workarounds/workaround_utils.h )
   s.files += %w( src/core/lib/surface/init.cc )
@@ -672,9 +674,9 @@
   s.files += %w( third_party/nanopb/pb_decode.c )
   s.files += %w( third_party/nanopb/pb_encode.c )
   s.files += %w( src/core/tsi/transport_security.cc )
-  s.files += %w( src/core/tsi/transport_security_adapter.cc )
   s.files += %w( src/core/ext/transport/chttp2/client/insecure/channel_create.cc )
   s.files += %w( src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc )
+  s.files += %w( src/core/ext/transport/chttp2/client/authority.cc )
   s.files += %w( src/core/ext/transport/chttp2/client/chttp2_connector.cc )
   s.files += %w( src/core/ext/filters/client_channel/backup_poller.cc )
   s.files += %w( src/core/ext/filters/client_channel/channel_connectivity.cc )
@@ -719,7 +721,6 @@
   s.files += %w( src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c )
   s.files += %w( src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc )
   s.files += %w( src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc )
-  s.files += %w( src/core/ext/filters/client_channel/lb_policy/subchannel_list.cc )
   s.files += %w( src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc )
   s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc )
   s.files += %w( src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc )
@@ -732,6 +733,7 @@
   s.files += %w( src/core/ext/census/grpc_context.cc )
   s.files += %w( src/core/ext/filters/max_age/max_age_filter.cc )
   s.files += %w( src/core/ext/filters/message_size/message_size_filter.cc )
+  s.files += %w( src/core/ext/filters/http/client_authority_filter.cc )
   s.files += %w( src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc )
   s.files += %w( src/core/ext/filters/workarounds/workaround_utils.cc )
   s.files += %w( src/core/plugin_registry/grpc_plugin_registry.cc )
diff --git a/grpc.gyp b/grpc.gyp
index 36b89f3..5726719 100644
--- a/grpc.gyp
+++ b/grpc.gyp
@@ -481,9 +481,9 @@
         'third_party/nanopb/pb_decode.c',
         'third_party/nanopb/pb_encode.c',
         'src/core/tsi/transport_security.cc',
-        'src/core/tsi/transport_security_adapter.cc',
         'src/core/ext/transport/chttp2/client/insecure/channel_create.cc',
         'src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc',
+        'src/core/ext/transport/chttp2/client/authority.cc',
         'src/core/ext/transport/chttp2/client/chttp2_connector.cc',
         'src/core/ext/filters/client_channel/backup_poller.cc',
         'src/core/ext/filters/client_channel/channel_connectivity.cc',
@@ -528,7 +528,6 @@
         'src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c',
         'src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc',
         'src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc',
-        'src/core/ext/filters/client_channel/lb_policy/subchannel_list.cc',
         'src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc',
         'src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc',
         'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc',
@@ -541,6 +540,7 @@
         'src/core/ext/census/grpc_context.cc',
         'src/core/ext/filters/max_age/max_age_filter.cc',
         'src/core/ext/filters/message_size/message_size_filter.cc',
+        'src/core/ext/filters/http/client_authority_filter.cc',
         'src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc',
         'src/core/ext/filters/workarounds/workaround_utils.cc',
         'src/core/plugin_registry/grpc_plugin_registry.cc',
@@ -576,6 +576,7 @@
         'test/core/end2end/fixtures/proxy.cc',
         'test/core/iomgr/endpoint_tests.cc',
         'test/core/util/debugger_macros.cc',
+        'test/core/util/fuzzer_util.cc',
         'test/core/util/grpc_profiler.cc',
         'test/core/util/histogram.cc',
         'test/core/util/memory_counters.cc',
@@ -806,6 +807,7 @@
         'test/core/end2end/fixtures/proxy.cc',
         'test/core/iomgr/endpoint_tests.cc',
         'test/core/util/debugger_macros.cc',
+        'test/core/util/fuzzer_util.cc',
         'test/core/util/grpc_profiler.cc',
         'test/core/util/histogram.cc',
         'test/core/util/memory_counters.cc',
@@ -1211,6 +1213,7 @@
         'src/core/ext/transport/chttp2/server/chttp2_server.cc',
         'src/core/ext/transport/chttp2/client/insecure/channel_create.cc',
         'src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc',
+        'src/core/ext/transport/chttp2/client/authority.cc',
         'src/core/ext/transport/chttp2/client/chttp2_connector.cc',
         'src/core/ext/filters/client_channel/backup_poller.cc',
         'src/core/ext/filters/client_channel/channel_connectivity.cc',
@@ -1255,11 +1258,11 @@
         'third_party/nanopb/pb_decode.c',
         'third_party/nanopb/pb_encode.c',
         'src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc',
-        'src/core/ext/filters/client_channel/lb_policy/subchannel_list.cc',
         'src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc',
         'src/core/ext/census/grpc_context.cc',
         'src/core/ext/filters/max_age/max_age_filter.cc',
         'src/core/ext/filters/message_size/message_size_filter.cc',
+        'src/core/ext/filters/http/client_authority_filter.cc',
         'src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc',
         'src/core/ext/filters/workarounds/workaround_utils.cc',
         'src/core/plugin_registry/grpc_unsecure_plugin_registry.cc',
@@ -1338,7 +1341,6 @@
         'src/cpp/server/server_posix.cc',
         'src/cpp/thread_manager/thread_manager.cc',
         'src/cpp/util/byte_buffer_cc.cc',
-        'src/cpp/util/slice_cc.cc',
         'src/cpp/util/status.cc',
         'src/cpp/util/string_ref.cc',
         'src/cpp/util/time_cc.cc',
@@ -1486,7 +1488,6 @@
         'src/cpp/server/server_posix.cc',
         'src/cpp/thread_manager/thread_manager.cc',
         'src/cpp/util/byte_buffer_cc.cc',
-        'src/cpp/util/slice_cc.cc',
         'src/cpp/util/status.cc',
         'src/cpp/util/string_ref.cc',
         'src/cpp/util/time_cc.cc',
@@ -1636,6 +1637,16 @@
       ],
     },
     {
+      'target_name': 'lb_load_data_store',
+      'type': 'static_library',
+      'dependencies': [
+        'grpc++',
+      ],
+      'sources': [
+        'src/cpp/server/load_reporter/load_data_store.cc',
+      ],
+    },
+    {
       'target_name': 'qps',
       'type': 'static_library',
       'dependencies': [
@@ -1650,7 +1661,9 @@
         'src/proto/grpc/testing/payloads.proto',
         'src/proto/grpc/testing/stats.proto',
         'src/proto/grpc/testing/control.proto',
-        'src/proto/grpc/testing/services.proto',
+        'src/proto/grpc/testing/benchmark_service.proto',
+        'src/proto/grpc/testing/report_qps_scenario_service.proto',
+        'src/proto/grpc/testing/worker_service.proto',
         'test/cpp/qps/benchmark_config.cc',
         'test/cpp/qps/client_async.cc',
         'test/cpp/qps/client_sync.cc',
@@ -2573,6 +2586,7 @@
         'test/core/end2end/tests/bad_ping.cc',
         'test/core/end2end/tests/binary_metadata.cc',
         'test/core/end2end/tests/call_creds.cc',
+        'test/core/end2end/tests/call_host_override.cc',
         'test/core/end2end/tests/cancel_after_accept.cc',
         'test/core/end2end/tests/cancel_after_client_done.cc',
         'test/core/end2end/tests/cancel_after_invoke.cc',
@@ -2619,6 +2633,7 @@
         'test/core/end2end/tests/retry_exceeds_buffer_size_in_initial_batch.cc',
         'test/core/end2end/tests/retry_exceeds_buffer_size_in_subsequent_batch.cc',
         'test/core/end2end/tests/retry_non_retriable_status.cc',
+        'test/core/end2end/tests/retry_non_retriable_status_before_recv_trailing_metadata_started.cc',
         'test/core/end2end/tests/retry_recv_initial_metadata.cc',
         'test/core/end2end/tests/retry_recv_message.cc',
         'test/core/end2end/tests/retry_server_pushback_delay.cc',
@@ -2661,6 +2676,7 @@
         'test/core/end2end/tests/bad_hostname.cc',
         'test/core/end2end/tests/bad_ping.cc',
         'test/core/end2end/tests/binary_metadata.cc',
+        'test/core/end2end/tests/call_host_override.cc',
         'test/core/end2end/tests/cancel_after_accept.cc',
         'test/core/end2end/tests/cancel_after_client_done.cc',
         'test/core/end2end/tests/cancel_after_invoke.cc',
@@ -2707,6 +2723,7 @@
         'test/core/end2end/tests/retry_exceeds_buffer_size_in_initial_batch.cc',
         'test/core/end2end/tests/retry_exceeds_buffer_size_in_subsequent_batch.cc',
         'test/core/end2end/tests/retry_non_retriable_status.cc',
+        'test/core/end2end/tests/retry_non_retriable_status_before_recv_trailing_metadata_started.cc',
         'test/core/end2end/tests/retry_recv_initial_metadata.cc',
         'test/core/end2end/tests/retry_recv_message.cc',
         'test/core/end2end/tests/retry_server_pushback_delay.cc',
diff --git a/include/grpc/grpc_security.h b/include/grpc/grpc_security.h
index 7c069b3..e1975a8 100644
--- a/include/grpc/grpc_security.h
+++ b/include/grpc/grpc_security.h
@@ -488,6 +488,76 @@
 GRPCAPI void grpc_server_credentials_set_auth_metadata_processor(
     grpc_server_credentials* creds, grpc_auth_metadata_processor processor);
 
+/** --- ALTS channel/server credentials --- **/
+
+/**
+ * Main interface for ALTS credentials options. The options will contain
+ * information that will be passed from grpc to TSI layer such as RPC protocol
+ * versions. ALTS client (channel) and server credentials will have their own
+ * implementation of this interface. The APIs listed in this header are
+ * thread-compatible. It is used for experimental purpose for now and subject
+ * to change.
+ */
+typedef struct grpc_alts_credentials_options grpc_alts_credentials_options;
+
+/**
+ * This method creates a grpc ALTS credentials client options instance.
+ * It is used for experimental purpose for now and subject to change.
+ */
+GRPCAPI grpc_alts_credentials_options*
+grpc_alts_credentials_client_options_create();
+
+/**
+ * This method creates a grpc ALTS credentials server options instance.
+ * It is used for experimental purpose for now and subject to change.
+ */
+GRPCAPI grpc_alts_credentials_options*
+grpc_alts_credentials_server_options_create();
+
+/**
+ * This method adds a target service account to grpc client's ALTS credentials
+ * options instance. It is used for experimental purpose for now and subject
+ * to change.
+ *
+ * - options: grpc ALTS credentials options instance.
+ * - service_account: service account of target endpoint.
+ */
+GRPCAPI void grpc_alts_credentials_client_options_add_target_service_account(
+    grpc_alts_credentials_options* options, const char* service_account);
+
+/**
+ * This method destroys a grpc_alts_credentials_options instance by
+ * de-allocating all of its occupied memory. It is used for experimental purpose
+ * for now and subject to change.
+ *
+ * - options: a grpc_alts_credentials_options instance that needs to be
+ *   destroyed.
+ */
+GRPCAPI void grpc_alts_credentials_options_destroy(
+    grpc_alts_credentials_options* options);
+
+/**
+ * This method creates an ALTS channel credential object. It is used for
+ * experimental purpose for now and subject to change.
+ *
+ * - options: grpc ALTS credentials options instance for client.
+ *
+ * It returns the created ALTS channel credential object.
+ */
+GRPCAPI grpc_channel_credentials* grpc_alts_credentials_create(
+    const grpc_alts_credentials_options* options);
+
+/**
+ * This method creates an ALTS server credential object. It is used for
+ * experimental purpose for now and subject to change.
+ *
+ * - options: grpc ALTS credentials options instance for server.
+ *
+ * It returns the created ALTS server credential object.
+ */
+GRPCAPI grpc_server_credentials* grpc_alts_server_credentials_create(
+    const grpc_alts_credentials_options* options);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/grpc/impl/codegen/grpc_types.h b/include/grpc/impl/codegen/grpc_types.h
index 03aaa9f..022be5f 100644
--- a/include/grpc/impl/codegen/grpc_types.h
+++ b/include/grpc/impl/codegen/grpc_types.h
@@ -333,6 +333,9 @@
 /** Channel arg that carries the bridged objective c object for custom metrics
  * logging filter. */
 #define GRPC_ARG_MOBILE_LOG_CONFIG "grpc.mobile_log_config"
+/** If non-zero, client authority filter is disabled for the channel */
+#define GRPC_ARG_DISABLE_CLIENT_AUTHORITY_FILTER \
+  "grpc.disable_client_authority_filter"
 /** \} */
 
 /** Result of a grpc call. If the caller satisfies the prerequisites of a
diff --git a/include/grpc/impl/codegen/port_platform.h b/include/grpc/impl/codegen/port_platform.h
index 819d17c..bf1bf3d 100644
--- a/include/grpc/impl/codegen/port_platform.h
+++ b/include/grpc/impl/codegen/port_platform.h
@@ -500,6 +500,17 @@
 #endif /* __GPR_WINDOWS */
 #endif /* GRPC_ALLOW_EXCEPTIONS */
 
+/* Use GPR_LIKELY only in cases where you are sure that a certain outcome is the
+ * most likely. Ideally, also collect performance numbers to justify the claim.
+ */
+#ifdef __GNUC__
+#define GPR_LIKELY(x) __builtin_expect((x), 1)
+#define GPR_UNLIKELY(x) __builtin_expect((x), 0)
+#else /* __GNUC__ */
+#define GPR_LIKELY(x) (x)
+#define GPR_UNLIKELY(x) (x)
+#endif /* __GNUC__ */
+
 #ifndef __STDC_FORMAT_MACROS
 #define __STDC_FORMAT_MACROS
 #endif
diff --git a/include/grpc/support/log.h b/include/grpc/support/log.h
index 2236703..1837d4b 100644
--- a/include/grpc/support/log.h
+++ b/include/grpc/support/log.h
@@ -61,6 +61,8 @@
 GPRAPI void gpr_log(const char* file, int line, gpr_log_severity severity,
                     const char* format, ...) GPR_PRINT_FORMAT_CHECK(4, 5);
 
+GPRAPI int gpr_should_log(gpr_log_severity severity);
+
 GPRAPI void gpr_log_message(const char* file, int line,
                             gpr_log_severity severity, const char* message);
 
@@ -91,12 +93,18 @@
    an exception in a higher-level language, consider returning error code.  */
 #define GPR_ASSERT(x)                                 \
   do {                                                \
-    if (!(x)) {                                       \
+    if (GPR_UNLIKELY(!(x))) {                         \
       gpr_log(GPR_ERROR, "assertion failed: %s", #x); \
       abort();                                        \
     }                                                 \
   } while (0)
 
+#ifndef NDEBUG
+#define GPR_DEBUG_ASSERT(x) GPR_ASSERT(x)
+#else
+#define GPR_DEBUG_ASSERT(x)
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/grpcpp/client_context.h b/include/grpcpp/client_context.h
index 8c12577..1994fcc 100644
--- a/include/grpcpp/client_context.h
+++ b/include/grpcpp/client_context.h
@@ -26,7 +26,7 @@
 ///
 /// Context settings are only relevant to the call they are invoked with, that
 /// is to say, they aren't sticky. Some of these settings, such as the
-/// compression options, can be made persistant at channel construction time
+/// compression options, can be made persistent at channel construction time
 /// (see \a grpc::CreateCustomChannel).
 ///
 /// \warning ClientContext instances should \em not be reused across rpcs.
diff --git a/include/grpcpp/impl/codegen/byte_buffer.h b/include/grpcpp/impl/codegen/byte_buffer.h
index 8d6a169..86c047e 100644
--- a/include/grpcpp/impl/codegen/byte_buffer.h
+++ b/include/grpcpp/impl/codegen/byte_buffer.h
@@ -31,6 +31,10 @@
 
 namespace grpc {
 
+class ServerInterface;
+class ByteBuffer;
+class ServerInterface;
+
 namespace internal {
 class CallOpSendMessage;
 template <class R>
@@ -43,6 +47,7 @@
 class ServerStreamingHandler;
 template <class R>
 class DeserializeFuncType;
+class GrpcByteBufferPeer;
 }  // namespace internal
 /// A sequence of bytes.
 class ByteBuffer final {
@@ -51,7 +56,30 @@
   ByteBuffer() : buffer_(nullptr) {}
 
   /// Construct buffer from \a slices, of which there are \a nslices.
-  ByteBuffer(const Slice* slices, size_t nslices);
+  ByteBuffer(const Slice* slices, size_t nslices) {
+    // The following assertions check that the representation of a grpc::Slice
+    // is identical to that of a grpc_slice:  it has a grpc_slice field, and
+    // nothing else.
+    static_assert(std::is_same<decltype(slices[0].slice_), grpc_slice>::value,
+                  "Slice must have same representation as grpc_slice");
+    static_assert(sizeof(Slice) == sizeof(grpc_slice),
+                  "Slice must have same representation as grpc_slice");
+    // The following assertions check that the representation of a ByteBuffer is
+    // identical to grpc_byte_buffer*:  it has a grpc_byte_buffer* field,
+    // and nothing else.
+    static_assert(std::is_same<decltype(buffer_), grpc_byte_buffer*>::value,
+                  "ByteBuffer must have same representation as "
+                  "grpc_byte_buffer*");
+    static_assert(sizeof(ByteBuffer) == sizeof(grpc_byte_buffer*),
+                  "ByteBuffer must have same representation as "
+                  "grpc_byte_buffer*");
+    // The const_cast is legal if grpc_raw_byte_buffer_create() does no more
+    // than its advertised side effect of increasing the reference count of the
+    // slices it processes, and such an increase does not affect the semantics
+    // seen by the caller of this constructor.
+    buffer_ = g_core_codegen_interface->grpc_raw_byte_buffer_create(
+        reinterpret_cast<grpc_slice*>(const_cast<Slice*>(slices)), nslices);
+  }
 
   /// Constuct a byte buffer by referencing elements of existing buffer
   /// \a buf. Wrapper of core function grpc_byte_buffer_copy
@@ -88,16 +116,25 @@
   void Release() { buffer_ = nullptr; }
 
   /// Buffer size in bytes.
-  size_t Length() const;
+  size_t Length() const {
+    return buffer_ == nullptr
+               ? 0
+               : g_core_codegen_interface->grpc_byte_buffer_length(buffer_);
+  }
 
   /// Swap the state of *this and *other.
-  void Swap(ByteBuffer* other);
+  void Swap(ByteBuffer* other) {
+    grpc_byte_buffer* tmp = other->buffer_;
+    other->buffer_ = buffer_;
+    buffer_ = tmp;
+  }
 
   /// Is this ByteBuffer valid?
   bool Valid() const { return (buffer_ != nullptr); }
 
  private:
   friend class SerializationTraits<ByteBuffer, void>;
+  friend class ServerInterface;
   friend class internal::CallOpSendMessage;
   template <class R>
   friend class internal::CallOpRecvMessage;
@@ -109,6 +146,9 @@
   friend class internal::ServerStreamingHandler;
   template <class R>
   friend class internal::DeserializeFuncType;
+  friend class ProtoBufferReader;
+  friend class ProtoBufferWriter;
+  friend class internal::GrpcByteBufferPeer;
 
   grpc_byte_buffer* buffer_;
 
diff --git a/include/grpcpp/impl/codegen/core_codegen.h b/include/grpcpp/impl/codegen/core_codegen.h
index 0ca4ad5..e9df96b 100644
--- a/include/grpcpp/impl/codegen/core_codegen.h
+++ b/include/grpcpp/impl/codegen/core_codegen.h
@@ -73,6 +73,7 @@
 
   grpc_byte_buffer* grpc_byte_buffer_copy(grpc_byte_buffer* bb) override;
   void grpc_byte_buffer_destroy(grpc_byte_buffer* bb) override;
+  size_t grpc_byte_buffer_length(grpc_byte_buffer* bb) override;
 
   int grpc_byte_buffer_reader_init(grpc_byte_buffer_reader* reader,
                                    grpc_byte_buffer* buffer) override;
@@ -86,6 +87,8 @@
   grpc_slice grpc_slice_new_with_user_data(void* p, size_t len,
                                            void (*destroy)(void*),
                                            void* user_data) override;
+  grpc_slice grpc_slice_new_with_len(void* p, size_t len,
+                                     void (*destroy)(void*, size_t)) override;
   grpc_slice grpc_empty_slice() override;
   grpc_slice grpc_slice_malloc(size_t length) override;
   void grpc_slice_unref(grpc_slice slice) override;
diff --git a/include/grpcpp/impl/codegen/core_codegen_interface.h b/include/grpcpp/impl/codegen/core_codegen_interface.h
index d72f579..1167a18 100644
--- a/include/grpcpp/impl/codegen/core_codegen_interface.h
+++ b/include/grpcpp/impl/codegen/core_codegen_interface.h
@@ -81,6 +81,8 @@
 
   virtual grpc_byte_buffer* grpc_byte_buffer_copy(grpc_byte_buffer* bb) = 0;
   virtual void grpc_byte_buffer_destroy(grpc_byte_buffer* bb) = 0;
+  virtual size_t grpc_byte_buffer_length(grpc_byte_buffer* bb)
+      GRPC_MUST_USE_RESULT = 0;
 
   virtual int grpc_byte_buffer_reader_init(grpc_byte_buffer_reader* reader,
                                            grpc_byte_buffer* buffer)
@@ -95,6 +97,9 @@
   virtual grpc_slice grpc_slice_new_with_user_data(void* p, size_t len,
                                                    void (*destroy)(void*),
                                                    void* user_data) = 0;
+  virtual grpc_slice grpc_slice_new_with_len(void* p, size_t len,
+                                             void (*destroy)(void*,
+                                                             size_t)) = 0;
   virtual grpc_call_error grpc_call_cancel_with_status(grpc_call* call,
                                                        grpc_status_code status,
                                                        const char* description,
diff --git a/include/grpcpp/impl/codegen/proto_buffer_reader.h b/include/grpcpp/impl/codegen/proto_buffer_reader.h
new file mode 100644
index 0000000..9acae47
--- /dev/null
+++ b/include/grpcpp/impl/codegen/proto_buffer_reader.h
@@ -0,0 +1,151 @@
+/*
+ *
+ * Copyright 2015 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 GRPCPP_IMPL_CODEGEN_PROTO_BUFFER_READER_H
+#define GRPCPP_IMPL_CODEGEN_PROTO_BUFFER_READER_H
+
+#include <type_traits>
+
+#include <grpc/impl/codegen/byte_buffer_reader.h>
+#include <grpc/impl/codegen/grpc_types.h>
+#include <grpc/impl/codegen/slice.h>
+#include <grpcpp/impl/codegen/byte_buffer.h>
+#include <grpcpp/impl/codegen/config_protobuf.h>
+#include <grpcpp/impl/codegen/core_codegen_interface.h>
+#include <grpcpp/impl/codegen/serialization_traits.h>
+#include <grpcpp/impl/codegen/status.h>
+
+/// This header provides an object that reads bytes directly from a
+/// grpc::ByteBuffer, via the ZeroCopyInputStream interface
+
+namespace grpc {
+
+extern CoreCodegenInterface* g_core_codegen_interface;
+
+/// This is a specialization of the protobuf class ZeroCopyInputStream
+/// The principle is to get one chunk of data at a time from the proto layer,
+/// with options to backup (re-see some bytes) or skip (forward past some bytes)
+///
+/// Read more about ZeroCopyInputStream interface here:
+/// https://developers.google.com/protocol-buffers/docs/reference/cpp/google.protobuf.io.zero_copy_stream#ZeroCopyInputStream
+class ProtoBufferReader : public ::grpc::protobuf::io::ZeroCopyInputStream {
+ public:
+  /// Constructs buffer reader from \a buffer. Will set \a status() to non ok
+  /// if \a buffer is invalid (the internal buffer has not been initialized).
+  explicit ProtoBufferReader(ByteBuffer* buffer)
+      : byte_count_(0), backup_count_(0), status_() {
+    /// Implemented through a grpc_byte_buffer_reader which iterates
+    /// over the slices that make up a byte buffer
+    if (!buffer->Valid() ||
+        !g_core_codegen_interface->grpc_byte_buffer_reader_init(
+            &reader_, buffer->c_buffer())) {
+      status_ = Status(StatusCode::INTERNAL,
+                       "Couldn't initialize byte buffer reader");
+    }
+  }
+
+  ~ProtoBufferReader() {
+    if (status_.ok()) {
+      g_core_codegen_interface->grpc_byte_buffer_reader_destroy(&reader_);
+    }
+  }
+
+  /// Give the proto library a chunk of data from the stream. The caller
+  /// may safely read from data[0, size - 1].
+  bool Next(const void** data, int* size) override {
+    if (!status_.ok()) {
+      return false;
+    }
+    /// If we have backed up previously, we need to return the backed-up slice
+    if (backup_count_ > 0) {
+      *data = GRPC_SLICE_START_PTR(slice_) + GRPC_SLICE_LENGTH(slice_) -
+              backup_count_;
+      GPR_CODEGEN_ASSERT(backup_count_ <= INT_MAX);
+      *size = (int)backup_count_;
+      backup_count_ = 0;
+      return true;
+    }
+    /// Otherwise get the next slice from the byte buffer reader
+    if (!g_core_codegen_interface->grpc_byte_buffer_reader_next(&reader_,
+                                                                &slice_)) {
+      return false;
+    }
+    g_core_codegen_interface->grpc_slice_unref(slice_);
+    *data = GRPC_SLICE_START_PTR(slice_);
+    // On win x64, int is only 32bit
+    GPR_CODEGEN_ASSERT(GRPC_SLICE_LENGTH(slice_) <= INT_MAX);
+    byte_count_ += * size = (int)GRPC_SLICE_LENGTH(slice_);
+    return true;
+  }
+
+  /// Returns the status of the buffer reader.
+  Status status() const { return status_; }
+
+  /// The proto library calls this to indicate that we should back up \a count
+  /// bytes that have already been returned by the last call of Next.
+  /// So do the backup and have that ready for a later Next.
+  void BackUp(int count) override {
+    GPR_CODEGEN_ASSERT(count <= static_cast<int>(GRPC_SLICE_LENGTH(slice_)));
+    backup_count_ = count;
+  }
+
+  /// The proto library calls this to skip over \a count bytes. Implement this
+  /// using Next and BackUp combined.
+  bool Skip(int count) override {
+    const void* data;
+    int size;
+    while (Next(&data, &size)) {
+      if (size >= count) {
+        BackUp(size - count);
+        return true;
+      }
+      // size < count;
+      count -= size;
+    }
+    // error or we have too large count;
+    return false;
+  }
+
+  /// Returns the total number of bytes read since this object was created.
+  grpc::protobuf::int64 ByteCount() const override {
+    return byte_count_ - backup_count_;
+  }
+
+  // These protected members are needed to support internal optimizations.
+  // they expose internal bits of grpc core that are NOT stable. If you have
+  // a use case needs to use one of these functions, please send an email to
+  // https://groups.google.com/forum/#!forum/grpc-io.
+ protected:
+  void set_byte_count(int64_t byte_count) { byte_count_ = byte_count; }
+  int64_t backup_count() { return backup_count_; }
+  void set_backup_count(int64_t backup_count) { backup_count_ = backup_count; }
+  grpc_byte_buffer_reader* reader() { return &reader_; }
+  grpc_slice* slice() { return &slice_; }
+
+ private:
+  int64_t byte_count_;              ///< total bytes read since object creation
+  int64_t backup_count_;            ///< how far backed up in the stream we are
+  grpc_byte_buffer_reader reader_;  ///< internal object to read \a grpc_slice
+                                    ///< from the \a grpc_byte_buffer
+  grpc_slice slice_;                ///< current slice passed back to the caller
+  Status status_;                   ///< status of the entire object
+};
+
+}  // namespace grpc
+
+#endif  // GRPCPP_IMPL_CODEGEN_PROTO_BUFFER_READER_H
diff --git a/include/grpcpp/impl/codegen/proto_buffer_writer.h b/include/grpcpp/impl/codegen/proto_buffer_writer.h
new file mode 100644
index 0000000..fdff467
--- /dev/null
+++ b/include/grpcpp/impl/codegen/proto_buffer_writer.h
@@ -0,0 +1,167 @@
+/*
+ *
+ * Copyright 2018 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 GRPCPP_IMPL_CODEGEN_PROTO_BUFFER_WRITER_H
+#define GRPCPP_IMPL_CODEGEN_PROTO_BUFFER_WRITER_H
+
+#include <type_traits>
+
+#include <grpc/impl/codegen/grpc_types.h>
+#include <grpc/impl/codegen/slice.h>
+#include <grpcpp/impl/codegen/byte_buffer.h>
+#include <grpcpp/impl/codegen/config_protobuf.h>
+#include <grpcpp/impl/codegen/core_codegen_interface.h>
+#include <grpcpp/impl/codegen/serialization_traits.h>
+#include <grpcpp/impl/codegen/status.h>
+
+/// This header provides an object that writes bytes directly into a
+/// grpc::ByteBuffer, via the ZeroCopyOutputStream interface
+
+namespace grpc {
+
+extern CoreCodegenInterface* g_core_codegen_interface;
+
+// Forward declaration for testing use only
+namespace internal {
+class ProtoBufferWriterPeer;
+}  // namespace internal
+
+const int kProtoBufferWriterMaxBufferLength = 1024 * 1024;
+
+/// This is a specialization of the protobuf class ZeroCopyOutputStream.
+/// The principle is to give the proto layer one buffer of bytes at a time
+/// that it can use to serialize the next portion of the message, with the
+/// option to "backup" if more buffer is given than required at the last buffer.
+///
+/// Read more about ZeroCopyOutputStream interface here:
+/// https://developers.google.com/protocol-buffers/docs/reference/cpp/google.protobuf.io.zero_copy_stream#ZeroCopyOutputStream
+class ProtoBufferWriter : public ::grpc::protobuf::io::ZeroCopyOutputStream {
+ public:
+  /// Constructor for this derived class
+  ///
+  /// \param[out] byte_buffer A pointer to the grpc::ByteBuffer created
+  /// \param block_size How big are the chunks to allocate at a time
+  /// \param total_size How many total bytes are required for this proto
+  ProtoBufferWriter(ByteBuffer* byte_buffer, int block_size, int total_size)
+      : block_size_(block_size),
+        total_size_(total_size),
+        byte_count_(0),
+        have_backup_(false) {
+    GPR_CODEGEN_ASSERT(!byte_buffer->Valid());
+    /// Create an empty raw byte buffer and look at its underlying slice buffer
+    grpc_byte_buffer* bp =
+        g_core_codegen_interface->grpc_raw_byte_buffer_create(NULL, 0);
+    byte_buffer->set_buffer(bp);
+    slice_buffer_ = &bp->data.raw.slice_buffer;
+  }
+
+  ~ProtoBufferWriter() {
+    if (have_backup_) {
+      g_core_codegen_interface->grpc_slice_unref(backup_slice_);
+    }
+  }
+
+  /// Give the proto library the next buffer of bytes and its size. It is
+  /// safe for the caller to write from data[0, size - 1].
+  bool Next(void** data, int* size) override {
+    // Protobuf should not ask for more memory than total_size_.
+    GPR_CODEGEN_ASSERT(byte_count_ < total_size_);
+    // 1. Use the remaining backup slice if we have one
+    // 2. Otherwise allocate a slice, up to the remaining length needed
+    //    or our maximum allocation size
+    // 3. Provide the slice start and size available
+    // 4. Add the slice being returned to the slice buffer
+    size_t remain = total_size_ - byte_count_;
+    if (have_backup_) {
+      /// If we have a backup slice, we should use it first
+      slice_ = backup_slice_;
+      have_backup_ = false;
+      if (GRPC_SLICE_LENGTH(slice_) > remain) {
+        GRPC_SLICE_SET_LENGTH(slice_, remain);
+      }
+    } else {
+      // When less than a whole block is needed, only allocate that much.
+      // But make sure the allocated slice is not inlined.
+      size_t allocate_length =
+          remain > static_cast<size_t>(block_size_) ? block_size_ : remain;
+      slice_ = g_core_codegen_interface->grpc_slice_malloc(
+          allocate_length > GRPC_SLICE_INLINED_SIZE
+              ? allocate_length
+              : GRPC_SLICE_INLINED_SIZE + 1);
+    }
+    *data = GRPC_SLICE_START_PTR(slice_);
+    // On win x64, int is only 32bit
+    GPR_CODEGEN_ASSERT(GRPC_SLICE_LENGTH(slice_) <= INT_MAX);
+    byte_count_ += * size = (int)GRPC_SLICE_LENGTH(slice_);
+    g_core_codegen_interface->grpc_slice_buffer_add(slice_buffer_, slice_);
+    return true;
+  }
+
+  /// Backup by \a count bytes because Next returned more bytes than needed
+  /// (only used in the last buffer). \a count must be less than or equal too
+  /// the last buffer returned from next.
+  void BackUp(int count) override {
+    /// 1. Remove the partially-used last slice from the slice buffer
+    /// 2. Split it into the needed (if any) and unneeded part
+    /// 3. Add the needed part back to the slice buffer
+    /// 4. Mark that we still have the remaining part (for later use/unref)
+    GPR_CODEGEN_ASSERT(count <= static_cast<int>(GRPC_SLICE_LENGTH(slice_)));
+    g_core_codegen_interface->grpc_slice_buffer_pop(slice_buffer_);
+    if ((size_t)count == GRPC_SLICE_LENGTH(slice_)) {
+      backup_slice_ = slice_;
+    } else {
+      backup_slice_ = g_core_codegen_interface->grpc_slice_split_tail(
+          &slice_, GRPC_SLICE_LENGTH(slice_) - count);
+      g_core_codegen_interface->grpc_slice_buffer_add(slice_buffer_, slice_);
+    }
+    // It's dangerous to keep an inlined grpc_slice as the backup slice, since
+    // on a following Next() call, a reference will be returned to this slice
+    // via GRPC_SLICE_START_PTR, which will not be an address held by
+    // slice_buffer_.
+    have_backup_ = backup_slice_.refcount != NULL;
+    byte_count_ -= count;
+  }
+
+  /// Returns the total number of bytes written since this object was created.
+  grpc::protobuf::int64 ByteCount() const override { return byte_count_; }
+
+  // These protected members are needed to support internal optimizations.
+  // they expose internal bits of grpc core that are NOT stable. If you have
+  // a use case needs to use one of these functions, please send an email to
+  // https://groups.google.com/forum/#!forum/grpc-io.
+ protected:
+  grpc_slice_buffer* slice_buffer() { return slice_buffer_; }
+  void set_byte_count(int64_t byte_count) { byte_count_ = byte_count; }
+
+ private:
+  // friend for testing purposes only
+  friend class internal::ProtoBufferWriterPeer;
+  const int block_size_;  ///< size to alloc for each new \a grpc_slice needed
+  const int total_size_;  ///< byte size of proto being serialized
+  int64_t byte_count_;    ///< bytes written since this object was created
+  grpc_slice_buffer*
+      slice_buffer_;  ///< internal buffer of slices holding the serialized data
+  bool have_backup_;  ///< if we are holding a backup slice or not
+  grpc_slice backup_slice_;  ///< holds space we can still write to, if the
+                             ///< caller has called BackUp
+  grpc_slice slice_;         ///< current slice passed back to the caller
+};
+
+}  // namespace grpc
+
+#endif  // GRPCPP_IMPL_CODEGEN_PROTO_BUFFER_WRITER_H
diff --git a/include/grpcpp/impl/codegen/proto_utils.h b/include/grpcpp/impl/codegen/proto_utils.h
index 81438ee..d9db6de 100644
--- a/include/grpcpp/impl/codegen/proto_utils.h
+++ b/include/grpcpp/impl/codegen/proto_utils.h
@@ -24,203 +24,61 @@
 #include <grpc/impl/codegen/byte_buffer_reader.h>
 #include <grpc/impl/codegen/grpc_types.h>
 #include <grpc/impl/codegen/slice.h>
+#include <grpcpp/impl/codegen/byte_buffer.h>
 #include <grpcpp/impl/codegen/config_protobuf.h>
 #include <grpcpp/impl/codegen/core_codegen_interface.h>
+#include <grpcpp/impl/codegen/proto_buffer_reader.h>
+#include <grpcpp/impl/codegen/proto_buffer_writer.h>
 #include <grpcpp/impl/codegen/serialization_traits.h>
+#include <grpcpp/impl/codegen/slice.h>
 #include <grpcpp/impl/codegen/status.h>
 
+/// This header provides serialization and deserialization between gRPC
+/// messages serialized using protobuf and the C++ objects they represent.
+
 namespace grpc {
 
 extern CoreCodegenInterface* g_core_codegen_interface;
 
-namespace internal {
-
-class GrpcBufferWriterPeer;
-
-const int kGrpcBufferWriterMaxBufferLength = 1024 * 1024;
-
-class GrpcBufferWriter : public ::grpc::protobuf::io::ZeroCopyOutputStream {
- public:
-  GrpcBufferWriter(grpc_byte_buffer** bp, int block_size, int total_size)
-      : block_size_(block_size),
-        total_size_(total_size),
-        byte_count_(0),
-        have_backup_(false) {
-    *bp = g_core_codegen_interface->grpc_raw_byte_buffer_create(NULL, 0);
-    slice_buffer_ = &(*bp)->data.raw.slice_buffer;
-  }
-
-  ~GrpcBufferWriter() override {
-    if (have_backup_) {
-      g_core_codegen_interface->grpc_slice_unref(backup_slice_);
-    }
-  }
-
-  bool Next(void** data, int* size) override {
-    // Protobuf should not ask for more memory than total_size_.
-    GPR_CODEGEN_ASSERT(byte_count_ < total_size_);
-    size_t remain = total_size_ - byte_count_;
-    if (have_backup_) {
-      slice_ = backup_slice_;
-      have_backup_ = false;
-      if (GRPC_SLICE_LENGTH(slice_) > remain) {
-        GRPC_SLICE_SET_LENGTH(slice_, remain);
-      }
-    } else {
-      // When less than a whole block is needed, only allocate that much.
-      // But make sure the allocated slice is not inlined.
-      size_t allocate_length =
-          remain > static_cast<size_t>(block_size_) ? block_size_ : remain;
-      slice_ = g_core_codegen_interface->grpc_slice_malloc(
-          allocate_length > GRPC_SLICE_INLINED_SIZE
-              ? allocate_length
-              : GRPC_SLICE_INLINED_SIZE + 1);
-    }
-    *data = GRPC_SLICE_START_PTR(slice_);
-    // On win x64, int is only 32bit
-    GPR_CODEGEN_ASSERT(GRPC_SLICE_LENGTH(slice_) <= INT_MAX);
-    byte_count_ += * size = (int)GRPC_SLICE_LENGTH(slice_);
-    g_core_codegen_interface->grpc_slice_buffer_add(slice_buffer_, slice_);
-    return true;
-  }
-
-  void BackUp(int count) override {
-    g_core_codegen_interface->grpc_slice_buffer_pop(slice_buffer_);
-    if ((size_t)count == GRPC_SLICE_LENGTH(slice_)) {
-      backup_slice_ = slice_;
-    } else {
-      backup_slice_ = g_core_codegen_interface->grpc_slice_split_tail(
-          &slice_, GRPC_SLICE_LENGTH(slice_) - count);
-      g_core_codegen_interface->grpc_slice_buffer_add(slice_buffer_, slice_);
-    }
-    // It's dangerous to keep an inlined grpc_slice as the backup slice, since
-    // on a following Next() call, a reference will be returned to this slice
-    // via GRPC_SLICE_START_PTR, which will not be an adddress held by
-    // slice_buffer_.
-    have_backup_ = backup_slice_.refcount != NULL;
-    byte_count_ -= count;
-  }
-
-  grpc::protobuf::int64 ByteCount() const override { return byte_count_; }
-
- protected:
-  friend class GrpcBufferWriterPeer;
-  const int block_size_;
-  const int total_size_;
-  int64_t byte_count_;
-  grpc_slice_buffer* slice_buffer_;
-  bool have_backup_;
-  grpc_slice backup_slice_;
-  grpc_slice slice_;
-};
-
-class GrpcBufferReader : public ::grpc::protobuf::io::ZeroCopyInputStream {
- public:
-  explicit GrpcBufferReader(grpc_byte_buffer* buffer)
-      : byte_count_(0), backup_count_(0), status_() {
-    if (!g_core_codegen_interface->grpc_byte_buffer_reader_init(&reader_,
-                                                                buffer)) {
-      status_ = Status(StatusCode::INTERNAL,
-                       "Couldn't initialize byte buffer reader");
-    }
-  }
-  ~GrpcBufferReader() override {
-    g_core_codegen_interface->grpc_byte_buffer_reader_destroy(&reader_);
-  }
-
-  bool Next(const void** data, int* size) override {
-    if (!status_.ok()) {
-      return false;
-    }
-    if (backup_count_ > 0) {
-      *data = GRPC_SLICE_START_PTR(slice_) + GRPC_SLICE_LENGTH(slice_) -
-              backup_count_;
-      GPR_CODEGEN_ASSERT(backup_count_ <= INT_MAX);
-      *size = (int)backup_count_;
-      backup_count_ = 0;
-      return true;
-    }
-    if (!g_core_codegen_interface->grpc_byte_buffer_reader_next(&reader_,
-                                                                &slice_)) {
-      return false;
-    }
-    g_core_codegen_interface->grpc_slice_unref(slice_);
-    *data = GRPC_SLICE_START_PTR(slice_);
-    // On win x64, int is only 32bit
-    GPR_CODEGEN_ASSERT(GRPC_SLICE_LENGTH(slice_) <= INT_MAX);
-    byte_count_ += * size = (int)GRPC_SLICE_LENGTH(slice_);
-    return true;
-  }
-
-  Status status() const { return status_; }
-
-  void BackUp(int count) override { backup_count_ = count; }
-
-  bool Skip(int count) override {
-    const void* data;
-    int size;
-    while (Next(&data, &size)) {
-      if (size >= count) {
-        BackUp(size - count);
-        return true;
-      }
-      // size < count;
-      count -= size;
-    }
-    // error or we have too large count;
-    return false;
-  }
-
-  grpc::protobuf::int64 ByteCount() const override {
-    return byte_count_ - backup_count_;
-  }
-
- protected:
-  int64_t byte_count_;
-  int64_t backup_count_;
-  grpc_byte_buffer_reader reader_;
-  grpc_slice slice_;
-  Status status_;
-};
-
-// BufferWriter must be a subclass of io::ZeroCopyOutputStream.
-template <class BufferWriter, class T>
-Status GenericSerialize(const grpc::protobuf::Message& msg,
-                        grpc_byte_buffer** bp, bool* own_buffer) {
-  static_assert(
-      std::is_base_of<protobuf::io::ZeroCopyOutputStream, BufferWriter>::value,
-      "BufferWriter must be a subclass of io::ZeroCopyOutputStream");
+// ProtoBufferWriter must be a subclass of ::protobuf::io::ZeroCopyOutputStream.
+template <class ProtoBufferWriter, class T>
+Status GenericSerialize(const grpc::protobuf::Message& msg, ByteBuffer* bb,
+                        bool* own_buffer) {
+  static_assert(std::is_base_of<protobuf::io::ZeroCopyOutputStream,
+                                ProtoBufferWriter>::value,
+                "ProtoBufferWriter must be a subclass of "
+                "::protobuf::io::ZeroCopyOutputStream");
   *own_buffer = true;
   int byte_size = msg.ByteSize();
   if ((size_t)byte_size <= GRPC_SLICE_INLINED_SIZE) {
-    grpc_slice slice = g_core_codegen_interface->grpc_slice_malloc(byte_size);
-    GPR_CODEGEN_ASSERT(
-        GRPC_SLICE_END_PTR(slice) ==
-        msg.SerializeWithCachedSizesToArray(GRPC_SLICE_START_PTR(slice)));
-    *bp = g_core_codegen_interface->grpc_raw_byte_buffer_create(&slice, 1);
-    g_core_codegen_interface->grpc_slice_unref(slice);
+    Slice slice(byte_size);
+    // We serialize directly into the allocated slices memory
+    GPR_CODEGEN_ASSERT(slice.end() == msg.SerializeWithCachedSizesToArray(
+                                          const_cast<uint8_t*>(slice.begin())));
+    ByteBuffer tmp(&slice, 1);
+    bb->Swap(&tmp);
 
     return g_core_codegen_interface->ok();
   }
-  BufferWriter writer(bp, kGrpcBufferWriterMaxBufferLength, byte_size);
+  ProtoBufferWriter writer(bb, kProtoBufferWriterMaxBufferLength, byte_size);
   return msg.SerializeToZeroCopyStream(&writer)
              ? g_core_codegen_interface->ok()
              : Status(StatusCode::INTERNAL, "Failed to serialize message");
 }
 
-// BufferReader must be a subclass of io::ZeroCopyInputStream.
-template <class BufferReader, class T>
-Status GenericDeserialize(grpc_byte_buffer* buffer,
-                          grpc::protobuf::Message* msg) {
-  static_assert(
-      std::is_base_of<protobuf::io::ZeroCopyInputStream, BufferReader>::value,
-      "BufferReader must be a subclass of io::ZeroCopyInputStream");
+// BufferReader must be a subclass of ::protobuf::io::ZeroCopyInputStream.
+template <class ProtoBufferReader, class T>
+Status GenericDeserialize(ByteBuffer* buffer, grpc::protobuf::Message* msg) {
+  static_assert(std::is_base_of<protobuf::io::ZeroCopyInputStream,
+                                ProtoBufferReader>::value,
+                "ProtoBufferReader must be a subclass of "
+                "::protobuf::io::ZeroCopyInputStream");
   if (buffer == nullptr) {
     return Status(StatusCode::INTERNAL, "No payload");
   }
   Status result = g_core_codegen_interface->ok();
   {
-    BufferReader reader(buffer);
+    ProtoBufferReader reader(buffer);
     if (!reader.status().ok()) {
       return reader.status();
     }
@@ -233,12 +91,10 @@
       result = Status(StatusCode::INTERNAL, "Did not read entire message");
     }
   }
-  g_core_codegen_interface->grpc_byte_buffer_destroy(buffer);
+  buffer->Clear();
   return result;
 }
 
-}  // namespace internal
-
 // this is needed so the following class does not conflict with protobuf
 // serializers that utilize internal-only tools.
 #ifdef GRPC_OPEN_SOURCE_PROTO
@@ -249,16 +105,13 @@
 class SerializationTraits<T, typename std::enable_if<std::is_base_of<
                                  grpc::protobuf::Message, T>::value>::type> {
  public:
-  static Status Serialize(const grpc::protobuf::Message& msg,
-                          grpc_byte_buffer** bp, bool* own_buffer) {
-    return internal::GenericSerialize<internal::GrpcBufferWriter, T>(
-        msg, bp, own_buffer);
+  static Status Serialize(const grpc::protobuf::Message& msg, ByteBuffer* bb,
+                          bool* own_buffer) {
+    return GenericSerialize<ProtoBufferWriter, T>(msg, bb, own_buffer);
   }
 
-  static Status Deserialize(grpc_byte_buffer* buffer,
-                            grpc::protobuf::Message* msg) {
-    return internal::GenericDeserialize<internal::GrpcBufferReader, T>(buffer,
-                                                                       msg);
+  static Status Deserialize(ByteBuffer* buffer, grpc::protobuf::Message* msg) {
+    return GenericDeserialize<ProtoBufferReader, T>(buffer, msg);
   }
 };
 #endif
diff --git a/include/grpcpp/impl/codegen/server_context.h b/include/grpcpp/impl/codegen/server_context.h
index bb357d6..bced420 100644
--- a/include/grpcpp/impl/codegen/server_context.h
+++ b/include/grpcpp/impl/codegen/server_context.h
@@ -88,8 +88,8 @@
 ///
 /// Context settings are only relevant to the call handler they are supplied to,
 /// that is to say, they aren't sticky across multiple calls. Some of these
-/// settings, such as the compression options, can be made persistant at server
-/// construction time by specifying the approriate \a ChannelArguments
+/// settings, such as the compression options, can be made persistent at server
+/// construction time by specifying the appropriate \a ChannelArguments
 /// to a \a grpc::ServerBuilder, via \a ServerBuilder::AddChannelArgument.
 ///
 /// \warning ServerContext instances should \em not be reused across rpcs.
diff --git a/include/grpcpp/impl/codegen/server_interface.h b/include/grpcpp/impl/codegen/server_interface.h
index 4700763..cf330ac 100644
--- a/include/grpcpp/impl/codegen/server_interface.h
+++ b/include/grpcpp/impl/codegen/server_interface.h
@@ -20,6 +20,7 @@
 #define GRPCPP_IMPL_CODEGEN_SERVER_INTERFACE_H
 
 #include <grpc/impl/codegen/grpc_types.h>
+#include <grpcpp/impl/codegen/byte_buffer.h>
 #include <grpcpp/impl/codegen/call_hook.h>
 #include <grpcpp/impl/codegen/completion_queue_tag.h>
 #include <grpcpp/impl/codegen/core_codegen_interface.h>
@@ -185,14 +186,18 @@
           notification_cq_(notification_cq),
           tag_(tag),
           request_(request) {
-      IssueRequest(registered_method, &payload_, notification_cq);
+      IssueRequest(registered_method, payload_.bbuf_ptr(), notification_cq);
+    }
+
+    ~PayloadAsyncRequest() {
+      payload_.Release();  // We do not own the payload_
     }
 
     bool FinalizeResult(void** tag, bool* status) override {
       if (*status) {
-        if (payload_ == nullptr ||
-            !SerializationTraits<Message>::Deserialize(payload_, request_)
-                 .ok()) {
+        if (!payload_.Valid() || !SerializationTraits<Message>::Deserialize(
+                                      payload_.bbuf_ptr(), request_)
+                                      .ok()) {
           // If deserialization fails, we cancel the call and instantiate
           // a new instance of ourselves to request another call.  We then
           // return false, which prevents the call from being returned to
@@ -219,7 +224,7 @@
     ServerCompletionQueue* const notification_cq_;
     void* const tag_;
     Message* const request_;
-    grpc_byte_buffer* payload_;
+    ByteBuffer payload_;
   };
 
   class GenericAsyncRequest : public BaseAsyncRequest {
diff --git a/include/grpcpp/impl/codegen/slice.h b/include/grpcpp/impl/codegen/slice.h
index fcccd4b..8966559 100644
--- a/include/grpcpp/impl/codegen/slice.h
+++ b/include/grpcpp/impl/codegen/slice.h
@@ -35,34 +35,43 @@
 class Slice final {
  public:
   /// Construct an empty slice.
-  Slice();
+  Slice() : slice_(g_core_codegen_interface->grpc_empty_slice()) {}
   /// Destructor - drops one reference.
-  ~Slice();
+  ~Slice() { g_core_codegen_interface->grpc_slice_unref(slice_); }
 
   enum AddRef { ADD_REF };
   /// Construct a slice from \a slice, adding a reference.
-  Slice(grpc_slice slice, AddRef);
+  Slice(grpc_slice slice, AddRef)
+      : slice_(g_core_codegen_interface->grpc_slice_ref(slice)) {}
 
   enum StealRef { STEAL_REF };
   /// Construct a slice from \a slice, stealing a reference.
-  Slice(grpc_slice slice, StealRef);
+  Slice(grpc_slice slice, StealRef) : slice_(slice) {}
 
   /// Allocate a slice of specified size
-  Slice(size_t len);
+  Slice(size_t len)
+      : slice_(g_core_codegen_interface->grpc_slice_malloc(len)) {}
 
   /// Construct a slice from a copied buffer
-  Slice(const void* buf, size_t len);
+  Slice(const void* buf, size_t len)
+      : slice_(g_core_codegen_interface->grpc_slice_from_copied_buffer(
+            reinterpret_cast<const char*>(buf), len)) {}
 
   /// Construct a slice from a copied string
-  Slice(const grpc::string& str);
+  Slice(const grpc::string& str)
+      : slice_(g_core_codegen_interface->grpc_slice_from_copied_buffer(
+            str.c_str(), str.length())) {}
 
   enum StaticSlice { STATIC_SLICE };
 
   /// Construct a slice from a static buffer
-  Slice(const void* buf, size_t len, StaticSlice);
+  Slice(const void* buf, size_t len, StaticSlice)
+      : slice_(g_core_codegen_interface->grpc_slice_from_static_buffer(
+            reinterpret_cast<const char*>(buf), len)) {}
 
   /// Copy constructor, adds a reference.
-  Slice(const Slice& other);
+  Slice(const Slice& other)
+      : slice_(g_core_codegen_interface->grpc_slice_ref(other.slice_)) {}
 
   /// Assignment, reference count is unchanged.
   Slice& operator=(Slice other) {
@@ -75,14 +84,18 @@
   /// user data pointer passed in at destruction. Can be the same as buf or
   /// different (e.g., if data is part of a larger structure that must be
   /// destroyed when the data is no longer needed)
-  Slice(void* buf, size_t len, void (*destroy)(void*), void* user_data);
+  Slice(void* buf, size_t len, void (*destroy)(void*), void* user_data)
+      : slice_(g_core_codegen_interface->grpc_slice_new_with_user_data(
+            buf, len, destroy, user_data)) {}
 
   /// Specialization of above for common case where buf == user_data
   Slice(void* buf, size_t len, void (*destroy)(void*))
       : Slice(buf, len, destroy, buf) {}
 
   /// Similar to the above but has a destroy that also takes slice length
-  Slice(void* buf, size_t len, void (*destroy)(void*, size_t));
+  Slice(void* buf, size_t len, void (*destroy)(void*, size_t))
+      : slice_(g_core_codegen_interface->grpc_slice_new_with_len(buf, len,
+                                                                 destroy)) {}
 
   /// Byte size.
   size_t size() const { return GRPC_SLICE_LENGTH(slice_); }
@@ -94,7 +107,9 @@
   const uint8_t* end() const { return GRPC_SLICE_END_PTR(slice_); }
 
   /// Raw C slice. Caller needs to call grpc_slice_unref when done.
-  grpc_slice c_slice() const;
+  grpc_slice c_slice() const {
+    return g_core_codegen_interface->grpc_slice_ref(slice_);
+  }
 
  private:
   friend class ByteBuffer;
diff --git a/include/grpcpp/security/credentials.h b/include/grpcpp/security/credentials.h
index 837a0e4..36d95d1 100644
--- a/include/grpcpp/security/credentials.h
+++ b/include/grpcpp/security/credentials.h
@@ -21,6 +21,7 @@
 
 #include <map>
 #include <memory>
+#include <vector>
 
 #include <grpcpp/impl/codegen/grpc_library.h>
 #include <grpcpp/security/auth_context.h>
@@ -219,6 +220,21 @@
 std::shared_ptr<CallCredentials> MetadataCredentialsFromPlugin(
     std::unique_ptr<MetadataCredentialsPlugin> plugin);
 
+namespace experimental {
+
+/// Options used to build AltsCredentials.
+struct AltsCredentialsOptions {
+  /// service accounts of target endpoint that will be acceptable
+  /// by the client. If service accounts are provided and none of them matches
+  /// that of the server, authentication will fail.
+  std::vector<grpc::string> target_service_accounts;
+};
+
+/// Builds ALTS Credentials given ALTS specific options
+std::shared_ptr<ChannelCredentials> AltsCredentials(
+    const AltsCredentialsOptions& options);
+
+}  // namespace experimental
 }  // namespace grpc
 
 #endif  // GRPCPP_SECURITY_CREDENTIALS_H
diff --git a/include/grpcpp/security/server_credentials.h b/include/grpcpp/security/server_credentials.h
index 892863e..cf57e27 100644
--- a/include/grpcpp/security/server_credentials.h
+++ b/include/grpcpp/security/server_credentials.h
@@ -86,6 +86,18 @@
 /// Builds insecure server credentials.
 std::shared_ptr<ServerCredentials> InsecureServerCredentials();
 
+namespace experimental {
+
+/// Options to create ServerCredentials with ALTS
+struct AltsServerCredentialsOptions {
+  /// Add fields if needed.
+};
+
+/// Builds ALTS ServerCredentials given ALTS specific options
+std::shared_ptr<ServerCredentials> AltsServerCredentials(
+    const AltsServerCredentialsOptions& options);
+
+}  // namespace experimental
 }  // namespace grpc
 
 #endif  // GRPCPP_SECURITY_SERVER_CREDENTIALS_H
diff --git a/include/grpcpp/support/channel_arguments.h b/include/grpcpp/support/channel_arguments.h
index 1eead4e..217929d 100644
--- a/include/grpcpp/support/channel_arguments.h
+++ b/include/grpcpp/support/channel_arguments.h
@@ -70,7 +70,13 @@
   /// the resolver.
   void SetGrpclbFallbackTimeout(int fallback_timeout);
 
-  /// Set the socket mutator for the channel.
+  /// For client channel's, the socket mutator operates on
+  /// "channel" sockets. For server's, the socket mutator operates
+  /// only on "listen" sockets.
+  /// TODO(apolcyn): allow socket mutators to also operate
+  /// on server "channel" sockets, and adjust the socket mutator
+  /// object to be more speficic about which type of socket
+  /// it should operate on.
   void SetSocketMutator(grpc_socket_mutator* mutator);
 
   /// Set the string to prepend to the user agent.
diff --git a/include/grpcpp/support/proto_buffer_reader.h b/include/grpcpp/support/proto_buffer_reader.h
new file mode 100644
index 0000000..4cdb65d
--- /dev/null
+++ b/include/grpcpp/support/proto_buffer_reader.h
@@ -0,0 +1,24 @@
+/*
+ *
+ * Copyright 2018 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 GRPCPP_SUPPORT_PROTO_BUFFER_READER_H
+#define GRPCPP_SUPPORT_PROTO_BUFFER_READER_H
+
+#include <grpcpp/impl/codegen/proto_buffer_reader.h>
+
+#endif  // GRPCPP_SUPPORT_PROTO_BUFFER_READER_H
diff --git a/include/grpcpp/support/proto_buffer_writer.h b/include/grpcpp/support/proto_buffer_writer.h
new file mode 100644
index 0000000..01cf29c
--- /dev/null
+++ b/include/grpcpp/support/proto_buffer_writer.h
@@ -0,0 +1,24 @@
+/*
+ *
+ * Copyright 2018 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 GRPCPP_SUPPORT_PROTO_BUFFER_WRITER_H
+#define GRPCPP_SUPPORT_PROTO_BUFFER_WRITER_H
+
+#include <grpcpp/impl/codegen/proto_buffer_writer.h>
+
+#endif  // GRPCPP_SUPPORT_PROTO_BUFFER_WRITER_H
diff --git a/package.xml b/package.xml
index 52d5cc9..ac9b520 100644
--- a/package.xml
+++ b/package.xml
@@ -13,8 +13,8 @@
  <date>2018-01-19</date>
  <time>16:06:07</time>
  <version>
-  <release>1.11.0dev</release>
-  <api>1.11.0dev</api>
+  <release>1.13.0dev</release>
+  <api>1.13.0dev</api>
  </version>
  <stability>
   <release>beta</release>
@@ -208,6 +208,7 @@
     <file baseinstalldir="/" name="src/core/ext/filters/http/client/http_client_filter.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/http/message_compress/message_compress_filter.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/http/server/http_server_filter.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/security/context/security_context.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/security/credentials/alts/alts_credentials.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/security/credentials/composite/composite_credentials.h" role="src" />
@@ -259,8 +260,8 @@
     <file baseinstalldir="/" name="third_party/nanopb/pb_decode.h" role="src" />
     <file baseinstalldir="/" name="third_party/nanopb/pb_encode.h" role="src" />
     <file baseinstalldir="/" name="src/core/tsi/transport_security.h" role="src" />
-    <file baseinstalldir="/" name="src/core/tsi/transport_security_adapter.h" role="src" />
     <file baseinstalldir="/" name="src/core/tsi/transport_security_interface.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/authority.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/chttp2_connector.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/backup_poller.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/client_channel.h" role="src" />
@@ -438,6 +439,7 @@
     <file baseinstalldir="/" name="src/core/ext/filters/load_reporting/server_load_reporting_plugin.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/max_age/max_age_filter.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/message_size/message_size_filter.h" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/filters/http/client_authority_filter.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/workarounds/workaround_cronet_compression_filter.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/workarounds/workaround_utils.h" role="src" />
     <file baseinstalldir="/" name="src/core/lib/surface/init.cc" role="src" />
@@ -679,9 +681,9 @@
     <file baseinstalldir="/" name="third_party/nanopb/pb_decode.c" role="src" />
     <file baseinstalldir="/" name="third_party/nanopb/pb_encode.c" role="src" />
     <file baseinstalldir="/" name="src/core/tsi/transport_security.cc" role="src" />
-    <file baseinstalldir="/" name="src/core/tsi/transport_security_adapter.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/insecure/channel_create.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/authority.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/transport/chttp2/client/chttp2_connector.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/backup_poller.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/channel_connectivity.cc" role="src" />
@@ -726,7 +728,6 @@
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/subchannel_list.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc" role="src" />
@@ -739,6 +740,7 @@
     <file baseinstalldir="/" name="src/core/ext/census/grpc_context.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/max_age/max_age_filter.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/message_size/message_size_filter.cc" role="src" />
+    <file baseinstalldir="/" name="src/core/ext/filters/http/client_authority_filter.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc" role="src" />
     <file baseinstalldir="/" name="src/core/ext/filters/workarounds/workaround_utils.cc" role="src" />
     <file baseinstalldir="/" name="src/core/plugin_registry/grpc_plugin_registry.cc" role="src" />
diff --git a/setup.py b/setup.py
index 97a3107..99d1a1c 100644
--- a/setup.py
+++ b/setup.py
@@ -104,9 +104,9 @@
 EXTRA_ENV_COMPILE_ARGS = os.environ.get('GRPC_PYTHON_CFLAGS', None)
 EXTRA_ENV_LINK_ARGS = os.environ.get('GRPC_PYTHON_LDFLAGS', None)
 if EXTRA_ENV_COMPILE_ARGS is None:
-  EXTRA_ENV_COMPILE_ARGS = ''
+  EXTRA_ENV_COMPILE_ARGS = ' -std=c++11'
   if 'win32' in sys.platform and sys.version_info < (3, 5):
-    EXTRA_ENV_COMPILE_ARGS += ' -std=c++11'
+    EXTRA_ENV_COMPILE_ARGS += ' -D_hypot=hypot'
     # We use define flags here and don't directly add to DEFINE_MACROS below to
     # ensure that the expert user/builder has a way of turning it off (via the
     # envvars) without adding yet more GRPC-specific envvars.
@@ -116,10 +116,10 @@
     else:
       EXTRA_ENV_COMPILE_ARGS += ' -D_ftime=_ftime64 -D_timeb=__timeb64'
   elif "linux" in sys.platform:
-    EXTRA_ENV_COMPILE_ARGS += ' -std=c++11 -std=gnu99 -fvisibility=hidden -fno-wrapv -fno-exceptions'
+    EXTRA_ENV_COMPILE_ARGS += ' -std=gnu99 -fvisibility=hidden -fno-wrapv -fno-exceptions'
   elif "darwin" in sys.platform:
     EXTRA_ENV_COMPILE_ARGS += ' -fvisibility=hidden -fno-wrapv -fno-exceptions'
-EXTRA_ENV_COMPILE_ARGS += ' -DPB_FIELD_16BIT'	
+EXTRA_ENV_COMPILE_ARGS += ' -DPB_FIELD_16BIT'
 
 if EXTRA_ENV_LINK_ARGS is None:
   EXTRA_ENV_LINK_ARGS = ''
@@ -182,7 +182,7 @@
 CFLAGS = tuple(EXTRA_COMPILE_ARGS)
 if "linux" in sys.platform or "darwin" in sys.platform:
   pymodinit_type = 'PyObject*' if PY3 else 'void'
-  pymodinit = '__attribute__((visibility ("default"))) {}'.format(pymodinit_type)
+  pymodinit = 'extern "C" __attribute__((visibility ("default"))) {}'.format(pymodinit_type)
   DEFINE_MACROS += (('PyMODINIT_FUNC', pymodinit),)
   DEFINE_MACROS += (('GRPC_POSIX_FORK_ALLOW_PTHREAD_ATFORK', 1),)
 
@@ -239,9 +239,6 @@
 
 INSTALL_REQUIRES = (
     'six>=1.5.2',
-    # TODO(atash): eventually split the grpcio package into a metapackage
-    # depending on protobuf and the runtime component (independent of protobuf)
-    'protobuf>=3.5.0.post1',
 )
 
 if not PY3:
diff --git a/src/android/test/interop/.gitignore b/src/android/test/interop/.gitignore
new file mode 100644
index 0000000..39fb081
--- /dev/null
+++ b/src/android/test/interop/.gitignore
@@ -0,0 +1,9 @@
+*.iml
+.gradle
+/local.properties
+/.idea/workspace.xml
+/.idea/libraries
+.DS_Store
+/build
+/captures
+.externalNativeBuild
diff --git a/src/android/test/interop/README.md b/src/android/test/interop/README.md
new file mode 100644
index 0000000..9526230
--- /dev/null
+++ b/src/android/test/interop/README.md
@@ -0,0 +1,37 @@
+gRPC on Android
+==============
+
+Note: Building the protobuf dependency for Android requires
+https://github.com/google/protobuf/pull/3878. This fix will be in the next
+protobuf release, but until then must be manually patched in to
+`third_party/protobuf` to build gRPC for Android.
+
+PREREQUISITES
+-------------
+
+- Android SDK
+- Android NDK
+- `protoc` and `grpc_cpp_plugin` binaries on the host system
+
+INSTALL
+-------
+
+The example application can be built via Android Studio or on the command line
+using `gradle`:
+
+  ```sh
+  $ ./gradlew installDebug
+  ```
+
+INSTRUMENTATION TESTS
+---------------------
+
+The instrumentation tests can be run via the following `gradle` command. This
+requires an emulator already running on your computer.
+
+```
+$ ./gradlew connectedAndroidTest \
+  -Pandroid.testInstrumentationRunnerArguments.server_host=grpc-test.sandbox.googleapis.com \
+  -Pandroid.testInstrumentationRunnerArguments.server_port=443 \
+  -Pandroid.testInstrumentationRunnerArguments.use_tls=true
+```
diff --git a/src/android/test/interop/app/.gitignore b/src/android/test/interop/app/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/src/android/test/interop/app/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/src/android/test/interop/app/CMakeLists.txt b/src/android/test/interop/app/CMakeLists.txt
new file mode 100644
index 0000000..092995f
--- /dev/null
+++ b/src/android/test/interop/app/CMakeLists.txt
@@ -0,0 +1,119 @@
+cmake_minimum_required(VERSION 3.4.1)
+
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
+
+set(PROTOBUF_PROTOC_EXECUTABLE "/usr/local/bin/protoc" CACHE STRING "Protoc binary on host")
+set(gRPC_CPP_PLUGIN_EXECUTABLE "/usr/local/bin/grpc_cpp_plugin" CACHE STRING "gRPC CPP plugin binary on host")
+
+set(GRPC_SRC_DIR ../../../../../)
+
+set(GRPC_BUILD_DIR ../grpc/outputs/${ANDROID_ABI})
+file(MAKE_DIRECTORY ${GRPC_BUILD_DIR})
+
+add_subdirectory(${GRPC_SRC_DIR} ${GRPC_BUILD_DIR})
+
+#include_directories(${GRPC_SRC_DIR}/include)
+include_directories(${GRPC_SRC_DIR})
+
+set(GRPC_PROTO_GENS_DIR ${CMAKE_BINARY_DIR}/gens)
+file(MAKE_DIRECTORY ${GRPC_PROTO_GENS_DIR})
+include_directories(${GRPC_PROTO_GENS_DIR})
+
+function(android_protobuf_grpc_generate_cpp SRC_FILES HDR_FILES INCLUDE_ROOT)
+  if(NOT ARGN)
+    message(SEND_ERROR "Error: android_protobuf_grpc_generate_cpp() called without any proto files")
+    return()
+  endif()
+
+  set(${SRC_FILES})
+  set(${HDR_FILES})
+  set(PROTOBUF_INCLUDE_PATH -I ${INCLUDE_ROOT})
+  foreach(FIL ${ARGN})
+    get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
+    get_filename_component(FIL_WE ${FIL} NAME_WE)
+    file(RELATIVE_PATH REL_FIL ${CMAKE_CURRENT_SOURCE_DIR}/${INCLUDE_ROOT} ${ABS_FIL})
+    get_filename_component(REL_DIR ${REL_FIL} DIRECTORY)
+    set(RELFIL_WE "${REL_DIR}/${FIL_WE}")
+
+    list(APPEND ${SRC_FILES} "${GRPC_PROTO_GENS_DIR}/${RELFIL_WE}.pb.cc")
+    list(APPEND ${HDR_FILES} "${GRPC_PROTO_GENS_DIR}/${RELFIL_WE}.pb.h")
+    list(APPEND ${SRC_FILES} "${GRPC_PROTO_GENS_DIR}/${RELFIL_WE}.grpc.pb.cc")
+    list(APPEND ${HDR_FILES} "${GRPC_PROTO_GENS_DIR}/${RELFIL_WE}.grpc.pb.h")
+
+    add_custom_command(
+      OUTPUT "${GRPC_PROTO_GENS_DIR}/${RELFIL_WE}.grpc.pb.cc"
+             "${GRPC_PROTO_GENS_DIR}/${RELFIL_WE}.grpc.pb.h"
+             "${GRPC_PROTO_GENS_DIR}/${RELFIL_WE}.pb.cc"
+             "${GRPC_PROTO_GENS_DIR}/${RELFIL_WE}.pb.h"
+      COMMAND ${PROTOBUF_PROTOC_EXECUTABLE}
+      ARGS --grpc_out=${GRPC_PROTO_GENS_DIR}
+        --cpp_out=${GRPC_PROTO_GENS_DIR}
+        --plugin=protoc-gen-grpc=${gRPC_CPP_PLUGIN_EXECUTABLE}
+        ${PROTOBUF_INCLUDE_PATH}
+        ${REL_FIL}
+      WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+      DEPENDS ${PROTOBUF_PROTOC_EXECUTABLE} ${gRPC_CPP_PLUGIN_EXECUTABLE} ${ABS_FIL} )
+  endforeach()
+
+  set_source_files_properties(${${SRC_FILES}} ${${HDR_FILES}} PROPERTIES GENERATED TRUE)
+  set(${SRC_FILES} ${${SRC_FILES}} PARENT_SCOPE)
+  set(${HDR_FILES} ${${HDR_FILES}} PARENT_SCOPE)
+endfunction()
+
+set(PROTO_BASE_DIR ${GRPC_SRC_DIR}/examples/protos)
+
+android_protobuf_grpc_generate_cpp(
+  MESSAGES_PROTO_SRCS MESSAGES_PROTO_HDRS
+  ${GRPC_SRC_DIR} ${GRPC_SRC_DIR}/src/proto/grpc/testing/messages.proto)
+
+add_library(messages_proto_lib
+  SHARED ${MESSAGES_PROTO_SRCS} ${MESSAGES_PROTO_HDRS})
+
+target_link_libraries(messages_proto_lib
+  libprotobuf
+  grpc++
+  android
+  log)
+
+android_protobuf_grpc_generate_cpp(
+  EMPTY_PROTO_SRCS EMPTY_PROTO_HDRS
+  ${GRPC_SRC_DIR} ${GRPC_SRC_DIR}/src/proto/grpc/testing/empty.proto)
+
+add_library(empty_proto_lib
+  SHARED ${EMPTY_PROTO_SRCS} ${EMPTY_PROTO_HDRS})
+
+target_link_libraries(empty_proto_lib
+  libprotobuf
+  grpc++
+  android
+  log)
+
+android_protobuf_grpc_generate_cpp(
+  TEST_PROTO_SRCS TEST_PROTO_HDRS ${GRPC_SRC_DIR} ${GRPC_SRC_DIR}/src/proto/grpc/testing/test.proto)
+
+add_library(test_proto_lib
+  SHARED ${TEST_PROTO_SRCS} ${TEST_PROTO_HDRS})
+
+target_link_libraries(test_proto_lib
+  libprotobuf
+  grpc++
+  empty_proto_lib
+  messages_proto_lib
+  android
+  log)
+
+find_library(log-lib
+ log)
+
+add_library(grpc-interop
+  SHARED
+  src/main/cpp/grpc-interop.cc
+  ${GRPC_SRC_DIR}/test/cpp/interop/interop_client.h
+  ${GRPC_SRC_DIR}/test/cpp/interop/interop_client.cc)
+
+target_link_libraries(grpc-interop
+  messages_proto_lib
+  empty_proto_lib
+  test_proto_lib
+  android
+  ${log-lib})
diff --git a/src/android/test/interop/app/build.gradle b/src/android/test/interop/app/build.gradle
new file mode 100644
index 0000000..2f58b99
--- /dev/null
+++ b/src/android/test/interop/app/build.gradle
@@ -0,0 +1,56 @@
+apply plugin: 'com.android.application'
+
+android {
+    compileSdkVersion 26
+    defaultConfig {
+        applicationId "io.grpc.android.interop.cpp"
+        minSdkVersion 14
+        targetSdkVersion 26
+        versionCode 1
+        versionName "1.0"
+        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+        externalNativeBuild {
+            cmake {
+                // The paths to the protoc and grpc_cpp_plugin binaries on the host system (codegen
+                // is not cross-compiled to Android)
+                def protoc = project.hasProperty('protoc') ?
+                        project.property('protoc') : '/usr/local/bin/protoc'
+                def grpc_cpp_plugin = project.hasProperty('grpc_cpp_plugin') ?
+                        project.property('grpc_cpp_plugin') : '/usr/local/bin/grpc_cpp_plugin'
+
+                cppFlags "-std=c++14 -frtti -fexceptions"
+                arguments '-DANDROID_STL=c++_shared'
+                arguments '-DRUN_HAVE_POSIX_REGEX=0'
+                arguments '-DRUN_HAVE_STD_REGEX=0'
+                arguments '-DRUN_HAVE_STEADY_CLOCK=0'
+                arguments '-Dprotobuf_BUILD_PROTOC_BINARIES=off'
+                arguments '-DgRPC_BUILD_CODEGEN=off'
+                arguments '-DPROTOBUF_PROTOC_EXECUTABLE=' + protoc
+                arguments '-DgRPC_CPP_PLUGIN_EXECUTABLE=' + grpc_cpp_plugin
+            }
+        }
+        ndk.abiFilters 'x86'
+    }
+    buildTypes {
+        debug {
+            minifyEnabled false
+        }
+        release {
+            minifyEnabled true
+            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+        }
+    }
+    externalNativeBuild {
+        cmake {
+            path "CMakeLists.txt"
+        }
+    }
+}
+
+dependencies {
+    implementation fileTree(dir: 'libs', include: ['*.jar'])
+    implementation 'com.android.support:appcompat-v7:26.1.0'
+    testImplementation 'junit:junit:4.12'
+    androidTestImplementation 'com.android.support.test:runner:1.0.1'
+    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
+}
diff --git a/src/android/test/interop/app/proguard-rules.pro b/src/android/test/interop/app/proguard-rules.pro
new file mode 100644
index 0000000..f1b4245
--- /dev/null
+++ b/src/android/test/interop/app/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
diff --git a/src/android/test/interop/app/src/androidTest/java/io/grpc/interop/cpp/InteropTest.java b/src/android/test/interop/app/src/androidTest/java/io/grpc/interop/cpp/InteropTest.java
new file mode 100644
index 0000000..d1bc259
--- /dev/null
+++ b/src/android/test/interop/app/src/androidTest/java/io/grpc/interop/cpp/InteropTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2018, gRPC Authors All rights reserved.
+ *
+ * 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.
+ */
+
+package io.grpc.interop.cpp;
+
+import static junit.framework.Assert.assertTrue;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class InteropTest {
+  private String host;
+  private int port;
+  private boolean useTls;
+
+  @Before
+  public void setUp() throws Exception {
+    host =
+        InstrumentationRegistry.getArguments()
+            .getString("server_host", "grpc-test.sandbox.googleapis.com");
+    port = Integer.parseInt(InstrumentationRegistry.getArguments().getString("server_port", "443"));
+    useTls =
+        Boolean.parseBoolean(InstrumentationRegistry.getArguments().getString("use_tls", "true"));
+
+    if (useTls) {
+      Context ctx = InstrumentationRegistry.getTargetContext();
+      String sslRootsFile = "roots.pem";
+      InputStream in = ctx.getAssets().open(sslRootsFile);
+      File outFile = new File(ctx.getExternalFilesDir(null), sslRootsFile);
+      OutputStream out = new FileOutputStream(outFile);
+      byte[] buffer = new byte[1024];
+      int bytesRead;
+      while ((bytesRead = in.read(buffer)) != -1) {
+        out.write(buffer, 0, bytesRead);
+      }
+      in.close();
+      out.close();
+      InteropActivity.configureSslRoots(outFile.getCanonicalPath());
+    }
+  }
+
+  @Test
+  public void emptyUnary() {
+    assertTrue(InteropActivity.doEmpty(host, port, useTls));
+  }
+
+  @Test
+  public void largeUnary() {
+    assertTrue(InteropActivity.doLargeUnary(host, port, useTls));
+  }
+
+  @Test
+  public void emptyStream() {
+    assertTrue(InteropActivity.doEmptyStream(host, port, useTls));
+  }
+
+  @Test
+  public void requestStreaming() {
+    assertTrue(InteropActivity.doRequestStreaming(host, port, useTls));
+  }
+
+  @Test
+  public void responseStreaming() {
+    assertTrue(InteropActivity.doResponseStreaming(host, port, useTls));
+  }
+
+  @Test
+  public void pingPong() {
+    assertTrue(InteropActivity.doPingPong(host, port, useTls));
+  }
+}
diff --git a/src/android/test/interop/app/src/main/AndroidManifest.xml b/src/android/test/interop/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..009112a
--- /dev/null
+++ b/src/android/test/interop/app/src/main/AndroidManifest.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="io.grpc.interop.cpp" >
+
+    <uses-permission android:name="android.permission.INTERNET" />
+
+    <application
+        android:allowBackup="false"
+        android:icon="@mipmap/ic_launcher"
+        android:label="@string/app_name"
+        android:theme="@style/Base.V7.Theme.AppCompat.Light" >
+        <activity
+            android:name=".InteropActivity"
+            android:label="@string/app_name" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+
+</manifest>
diff --git a/src/android/test/interop/app/src/main/assets/roots.pem b/src/android/test/interop/app/src/main/assets/roots.pem
new file mode 100644
index 0000000..15d819b
--- /dev/null
+++ b/src/android/test/interop/app/src/main/assets/roots.pem
@@ -0,0 +1,4475 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+# Issuer: CN=GlobalSign Root CA O=GlobalSign nv-sa OU=Root CA
+# Subject: CN=GlobalSign Root CA O=GlobalSign nv-sa OU=Root CA
+# Label: "GlobalSign Root CA"
+# Serial: 4835703278459707669005204
+# MD5 Fingerprint: 3e:45:52:15:09:51:92:e1:b7:5d:37:9f:b1:87:29:8a
+# SHA1 Fingerprint: b1:bc:96:8b:d4:f4:9d:62:2a:a8:9a:81:f2:15:01:52:a4:1d:82:9c
+# SHA256 Fingerprint: eb:d4:10:40:e4:bb:3e:c7:42:c9:e3:81:d3:1e:f2:a4:1a:48:b6:68:5c:96:e7:ce:f3:c1:df:6c:d4:33:1c:99
+-----BEGIN CERTIFICATE-----
+MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG
+A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv
+b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw
+MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i
+YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT
+aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ
+jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp
+xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp
+1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG
+snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ
+U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8
+9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E
+BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B
+AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz
+yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE
+38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP
+AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad
+DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME
+HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==
+-----END CERTIFICATE-----
+
+# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R2
+# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R2
+# Label: "GlobalSign Root CA - R2"
+# Serial: 4835703278459682885658125
+# MD5 Fingerprint: 94:14:77:7e:3e:5e:fd:8f:30:bd:41:b0:cf:e7:d0:30
+# SHA1 Fingerprint: 75:e0:ab:b6:13:85:12:27:1c:04:f8:5f:dd:de:38:e4:b7:24:2e:fe
+# SHA256 Fingerprint: ca:42:dd:41:74:5f:d0:b8:1e:b9:02:36:2c:f9:d8:bf:71:9d:a1:bd:1b:1e:fc:94:6f:5b:4c:99:f4:2c:1b:9e
+-----BEGIN CERTIFICATE-----
+MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G
+A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp
+Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1
+MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG
+A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL
+v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8
+eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq
+tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd
+C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa
+zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB
+mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH
+V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n
+bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG
+3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs
+J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO
+291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS
+ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd
+AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7
+TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg==
+-----END CERTIFICATE-----
+
+# Issuer: CN=VeriSign Class 3 Public Primary Certification Authority - G3 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 1999 VeriSign, Inc. - For authorized use only
+# Subject: CN=VeriSign Class 3 Public Primary Certification Authority - G3 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 1999 VeriSign, Inc. - For authorized use only
+# Label: "Verisign Class 3 Public Primary Certification Authority - G3"
+# Serial: 206684696279472310254277870180966723415
+# MD5 Fingerprint: cd:68:b6:a7:c7:c4:ce:75:e0:1d:4f:57:44:61:92:09
+# SHA1 Fingerprint: 13:2d:0d:45:53:4b:69:97:cd:b2:d5:c3:39:e2:55:76:60:9b:5c:c6
+# SHA256 Fingerprint: eb:04:cf:5e:b1:f3:9a:fa:76:2f:2b:b1:20:f2:96:cb:a5:20:c1:b9:7d:b1:58:95:65:b8:1c:b9:a1:7b:72:44
+-----BEGIN CERTIFICATE-----
+MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQsw
+CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl
+cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu
+LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT
+aWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp
+dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD
+VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT
+aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ
+bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu
+IENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg
+LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMu6nFL8eB8aHm8b
+N3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1EUGO+i2t
+KmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGu
+kxUccLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBm
+CC+Vk7+qRy+oRpfwEuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJ
+Xwzw3sJ2zq/3avL6QaaiMxTJ5Xpj055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWu
+imi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAERSWwauSCPc/L8my/uRan2Te
+2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5fj267Cz3qWhMe
+DGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC
+/Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565p
+F4ErWjfJXir0xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGt
+TxzhT5yvDwyd93gN2PQ1VoDat20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ==
+-----END CERTIFICATE-----
+
+# Issuer: CN=Entrust.net Certification Authority (2048) O=Entrust.net OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited
+# Subject: CN=Entrust.net Certification Authority (2048) O=Entrust.net OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited
+# Label: "Entrust.net Premium 2048 Secure Server CA"
+# Serial: 946069240
+# MD5 Fingerprint: ee:29:31:bc:32:7e:9a:e6:e8:b5:f7:51:b4:34:71:90
+# SHA1 Fingerprint: 50:30:06:09:1d:97:d4:f5:ae:39:f7:cb:e7:92:7d:7d:65:2d:34:31
+# SHA256 Fingerprint: 6d:c4:71:72:e0:1c:bc:b0:bf:62:58:0d:89:5f:e2:b8:ac:9a:d4:f8:73:80:1e:0c:10:b9:c8:37:d2:1e:b1:77
+-----BEGIN CERTIFICATE-----
+MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML
+RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp
+bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5
+IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp
+ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0yOTA3
+MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3
+LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp
+YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG
+A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq
+K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe
+sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX
+MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT
+XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/
+HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH
+4QIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV
+HQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJKoZIhvcNAQEFBQADggEBADub
+j1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPyT/4xmf3IDExo
+U8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf
+zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5b
+u/8j72gZyxKTJ1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+
+bYQLCIt+jerXmCHG8+c8eS9enNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/Er
+fF6adulZkMV8gzURZVE=
+-----END CERTIFICATE-----
+
+# Issuer: CN=Baltimore CyberTrust Root O=Baltimore OU=CyberTrust
+# Subject: CN=Baltimore CyberTrust Root O=Baltimore OU=CyberTrust
+# Label: "Baltimore CyberTrust Root"
+# Serial: 33554617
+# MD5 Fingerprint: ac:b6:94:a5:9c:17:e0:d7:91:52:9b:b1:97:06:a6:e4
+# SHA1 Fingerprint: d4:de:20:d0:5e:66:fc:53:fe:1a:50:88:2c:78:db:28:52:ca:e4:74
+# SHA256 Fingerprint: 16:af:57:a9:f6:76:b0:ab:12:60:95:aa:5e:ba:de:f2:2a:b3:11:19:d6:44:ac:95:cd:4b:93:db:f3:f2:6a:eb
+-----BEGIN CERTIFICATE-----
+MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ
+RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD
+VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX
+DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y
+ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy
+VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr
+mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr
+IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK
+mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu
+XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy
+dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye
+jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1
+BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3
+DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92
+9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx
+jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0
+Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz
+ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS
+R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp
+-----END CERTIFICATE-----
+
+# Issuer: CN=AddTrust External CA Root O=AddTrust AB OU=AddTrust External TTP Network
+# Subject: CN=AddTrust External CA Root O=AddTrust AB OU=AddTrust External TTP Network
+# Label: "AddTrust External Root"
+# Serial: 1
+# MD5 Fingerprint: 1d:35:54:04:85:78:b0:3f:42:42:4d:bf:20:73:0a:3f
+# SHA1 Fingerprint: 02:fa:f3:e2:91:43:54:68:60:78:57:69:4d:f5:e4:5b:68:85:18:68
+# SHA256 Fingerprint: 68:7f:a4:51:38:22:78:ff:f0:c8:b1:1f:8d:43:d5:76:67:1c:6e:b2:bc:ea:b4:13:fb:83:d9:65:d0:6d:2f:f2
+-----BEGIN CERTIFICATE-----
+MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU
+MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs
+IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290
+MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux
+FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h
+bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v
+dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt
+H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9
+uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX
+mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX
+a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN
+E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0
+WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD
+VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0
+Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU
+cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx
+IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN
+AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH
+YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5
+6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC
+Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX
+c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a
+mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ=
+-----END CERTIFICATE-----
+
+# Issuer: CN=Entrust Root Certification Authority O=Entrust, Inc. OU=www.entrust.net/CPS is incorporated by reference/(c) 2006 Entrust, Inc.
+# Subject: CN=Entrust Root Certification Authority O=Entrust, Inc. OU=www.entrust.net/CPS is incorporated by reference/(c) 2006 Entrust, Inc.
+# Label: "Entrust Root Certification Authority"
+# Serial: 1164660820
+# MD5 Fingerprint: d6:a5:c3:ed:5d:dd:3e:00:c1:3d:87:92:1f:1d:3f:e4
+# SHA1 Fingerprint: b3:1e:b1:b7:40:e3:6c:84:02:da:dc:37:d4:4d:f5:d4:67:49:52:f9
+# SHA256 Fingerprint: 73:c1:76:43:4f:1b:c6:d5:ad:f4:5b:0e:76:e7:27:28:7c:8d:e5:76:16:c1:e6:e6:14:1a:2b:2c:bc:7d:8e:4c
+-----BEGIN CERTIFICATE-----
+MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMC
+VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0
+Lm5ldC9DUFMgaXMgaW5jb3Jwb3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMW
+KGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsGA1UEAxMkRW50cnVzdCBSb290IENl
+cnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0MloXDTI2MTEyNzIw
+NTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMTkw
+NwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSBy
+ZWZlcmVuY2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNV
+BAMTJEVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJ
+KoZIhvcNAQEBBQADggEPADCCAQoCggEBALaVtkNC+sZtKm9I35RMOVcF7sN5EUFo
+Nu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYszA9u3g3s+IIRe7bJWKKf4
+4LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOwwCj0Yzfv9
+KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGI
+rb68j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi
+94DkZfs0Nw4pgHBNrziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOB
+sDCBrTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAi
+gA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1MzQyWjAfBgNVHSMEGDAWgBRo
+kORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DHhmak8fdLQ/uE
+vW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA
+A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9t
+O1KzKtvn1ISMY/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6Zua
+AGAT/3B+XxFNSRuzFVJ7yVTav52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP
+9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTSW3iDVuycNsMm4hH2Z0kdkquM++v/
+eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0tHuu2guQOHXvgR1m
+0vdXcDazv/wor3ElhVsT/h5/WrQ8
+-----END CERTIFICATE-----
+
+# Issuer: CN=GeoTrust Global CA O=GeoTrust Inc.
+# Subject: CN=GeoTrust Global CA O=GeoTrust Inc.
+# Label: "GeoTrust Global CA"
+# Serial: 144470
+# MD5 Fingerprint: f7:75:ab:29:fb:51:4e:b7:77:5e:ff:05:3c:99:8e:f5
+# SHA1 Fingerprint: de:28:f4:a4:ff:e5:b9:2f:a3:c5:03:d1:a3:49:a7:f9:96:2a:82:12
+# SHA256 Fingerprint: ff:85:6a:2d:25:1d:cd:88:d3:66:56:f4:50:12:67:98:cf:ab:aa:de:40:79:9c:72:2d:e4:d2:b5:db:36:a7:3a
+-----BEGIN CERTIFICATE-----
+MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT
+MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i
+YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG
+EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg
+R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9
+9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq
+fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv
+iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU
+1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+
+bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW
+MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA
+ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l
+uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn
+Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS
+tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF
+PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un
+hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV
+5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw==
+-----END CERTIFICATE-----
+
+# Issuer: CN=GeoTrust Universal CA O=GeoTrust Inc.
+# Subject: CN=GeoTrust Universal CA O=GeoTrust Inc.
+# Label: "GeoTrust Universal CA"
+# Serial: 1
+# MD5 Fingerprint: 92:65:58:8b:a2:1a:31:72:73:68:5c:b4:a5:7a:07:48
+# SHA1 Fingerprint: e6:21:f3:35:43:79:05:9a:4b:68:30:9d:8a:2f:74:22:15:87:ec:79
+# SHA256 Fingerprint: a0:45:9b:9f:63:b2:25:59:f5:fa:5d:4c:6d:b3:f9:f7:2f:f1:93:42:03:35:78:f0:73:bf:1d:1b:46:cb:b9:12
+-----BEGIN CERTIFICATE-----
+MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEW
+MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVy
+c2FsIENBMB4XDTA0MDMwNDA1MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UE
+BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xHjAcBgNVBAMTFUdlb1RydXN0
+IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKYV
+VaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9tJPi8
+cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTT
+QjOgNB0eRXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFh
+F7em6fgemdtzbvQKoiFs7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2v
+c7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d8Lsrlh/eezJS/R27tQahsiFepdaVaH/w
+mZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7VqnJNk22CDtucvc+081xd
+VHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3CgaRr0BHdCX
+teGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZ
+f9hBZ3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfRe
+Bi9Fi1jUIxaS5BZuKGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+
+nhutxx9z3SxPGWX9f5NAEC7S8O08ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB
+/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0XG0D08DYj3rWMB8GA1UdIwQY
+MBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG
+9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc
+aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fX
+IwjhmF7DWgh2qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzyn
+ANXH/KttgCJwpQzgXQQpAvvLoJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0z
+uzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsKxr2EoyNB3tZ3b4XUhRxQ4K5RirqN
+Pnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxFKyDuSN/n3QmOGKja
+QI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2DFKW
+koRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9
+ER/frslKxfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQt
+DF4JbAiXfKM9fJP/P6EUp8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/Sfuvm
+bJxPgWp6ZKy7PtXny3YuxadIwVyQD8vIP/rmMuGNG2+k5o7Y+SlIis5z/iw=
+-----END CERTIFICATE-----
+
+# Issuer: CN=GeoTrust Universal CA 2 O=GeoTrust Inc.
+# Subject: CN=GeoTrust Universal CA 2 O=GeoTrust Inc.
+# Label: "GeoTrust Universal CA 2"
+# Serial: 1
+# MD5 Fingerprint: 34:fc:b8:d0:36:db:9e:14:b3:c2:f2:db:8f:e4:94:c7
+# SHA1 Fingerprint: 37:9a:19:7b:41:85:45:35:0c:a6:03:69:f3:3c:2e:af:47:4f:20:79
+# SHA256 Fingerprint: a0:23:4f:3b:c8:52:7c:a5:62:8e:ec:81:ad:5d:69:89:5d:a5:68:0d:c9:1d:1c:b8:47:7f:33:f8:78:b9:5b:0b
+-----BEGIN CERTIFICATE-----
+MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEW
+MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVy
+c2FsIENBIDIwHhcNMDQwMzA0MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYD
+VQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1
+c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC
+AQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0DE81
+WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUG
+FF+3Qs17j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdq
+XbboW0W63MOhBW9Wjo8QJqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxL
+se4YuU6W3Nx2/zu+z18DwPw76L5GG//aQMJS9/7jOvdqdzXQ2o3rXhhqMcceujwb
+KNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2WP0+GfPtDCapkzj4T8Fd
+IgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP20gaXT73
+y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRt
+hAAnZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgoc
+QIgfksILAAX/8sgCSqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4
+Lt1ZrtmhN79UNdxzMk+MBB4zsslG8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNV
+HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAfBgNV
+HSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8EBAMCAYYwDQYJ
+KoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z
+dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQ
+L1EuxBRa3ugZ4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgr
+Fg5fNuH8KrUwJM/gYwx7WBr+mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSo
+ag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpqA1Ihn0CoZ1Dy81of398j9tx4TuaY
+T1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpgY+RdM4kX2TGq2tbz
+GDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiPpm8m
+1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJV
+OCiNUW7dFGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH
+6aLcr34YEoP9VhdBLtUpgn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwX
+QMAJKOSLakhT2+zNVVXxxvjpoixMptEmX36vWkzaH6byHCx+rgIW0lbQL1dTR+iS
+-----END CERTIFICATE-----
+
+# Issuer: CN=Visa eCommerce Root O=VISA OU=Visa International Service Association
+# Subject: CN=Visa eCommerce Root O=VISA OU=Visa International Service Association
+# Label: "Visa eCommerce Root"
+# Serial: 25952180776285836048024890241505565794
+# MD5 Fingerprint: fc:11:b8:d8:08:93:30:00:6d:23:f9:7e:eb:52:1e:02
+# SHA1 Fingerprint: 70:17:9b:86:8c:00:a4:fa:60:91:52:22:3f:9f:3e:32:bd:e0:05:62
+# SHA256 Fingerprint: 69:fa:c9:bd:55:fb:0a:c7:8d:53:bb:ee:5c:f1:d5:97:98:9f:d0:aa:ab:20:a2:51:51:bd:f1:73:3e:e7:d1:22
+-----BEGIN CERTIFICATE-----
+MIIDojCCAoqgAwIBAgIQE4Y1TR0/BvLB+WUF1ZAcYjANBgkqhkiG9w0BAQUFADBr
+MQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRl
+cm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNv
+bW1lcmNlIFJvb3QwHhcNMDIwNjI2MDIxODM2WhcNMjIwNjI0MDAxNjEyWjBrMQsw
+CQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRlcm5h
+dGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNvbW1l
+cmNlIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvV95WHm6h
+2mCxlCfLF9sHP4CFT8icttD0b0/Pmdjh28JIXDqsOTPHH2qLJj0rNfVIsZHBAk4E
+lpF7sDPwsRROEW+1QK8bRaVK7362rPKgH1g/EkZgPI2h4H3PVz4zHvtH8aoVlwdV
+ZqW1LS7YgFmypw23RuwhY/81q6UCzyr0TP579ZRdhE2o8mCP2w4lPJ9zcc+U30rq
+299yOIzzlr3xF7zSujtFWsan9sYXiwGd/BmoKoMWuDpI/k4+oKsGGelT84ATB+0t
+vz8KPFUgOSwsAGl0lUq8ILKpeeUYiZGo3BxN77t+Nwtd/jmliFKMAGzsGHxBvfaL
+dXe6YJ2E5/4tAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD
+AgEGMB0GA1UdDgQWBBQVOIMPPyw/cDMezUb+B4wg4NfDtzANBgkqhkiG9w0BAQUF
+AAOCAQEAX/FBfXxcCLkr4NWSR/pnXKUTwwMhmytMiUbPWU3J/qVAtmPN3XEolWcR
+zCSs00Rsca4BIGsDoo8Ytyk6feUWYFN4PMCvFYP3j1IzJL1kk5fui/fbGKhtcbP3
+LBfQdCVp9/5rPJS+TUtBjE7ic9DjkCJzQ83z7+pzzkWKsKZJ/0x9nXGIxHYdkFsd
+7v3M9+79YKWxehZx0RbQfBI8bGmX265fOZpwLwU8GUYEmSA20GBuYQa7FkKMcPcw
+++DbZqMAAb3mLNqRX6BGi01qnD093QVG/na/oAo85ADmJ7f/hC3euiInlhBx6yLt
+398znM/jra6O1I7mT1GvFpLgXPYHDw==
+-----END CERTIFICATE-----
+
+# Issuer: CN=AAA Certificate Services O=Comodo CA Limited
+# Subject: CN=AAA Certificate Services O=Comodo CA Limited
+# Label: "Comodo AAA Services root"
+# Serial: 1
+# MD5 Fingerprint: 49:79:04:b0:eb:87:19:ac:47:b0:bc:11:51:9b:74:d0
+# SHA1 Fingerprint: d1:eb:23:a4:6d:17:d6:8f:d9:25:64:c2:f1:f1:60:17:64:d8:e3:49
+# SHA256 Fingerprint: d7:a7:a0:fb:5d:7e:27:31:d7:71:e9:48:4e:bc:de:f7:1d:5f:0c:3e:0a:29:48:78:2b:c8:3e:e0:ea:69:9e:f4
+-----BEGIN CERTIFICATE-----
+MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEb
+MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow
+GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmlj
+YXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezEL
+MAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE
+BwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNVBAMM
+GEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQua
+BtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe
+3M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4
+YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZR
+rOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cm
+ez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQU
+oBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF
+MAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20v
+QUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29t
+b2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG9w0BAQUF
+AAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1Q
+GE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz
+Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2
+G9w84FoVxp7Z8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsi
+l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3
+smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg==
+-----END CERTIFICATE-----
+
+# Issuer: CN=QuoVadis Root Certification Authority O=QuoVadis Limited OU=Root Certification Authority
+# Subject: CN=QuoVadis Root Certification Authority O=QuoVadis Limited OU=Root Certification Authority
+# Label: "QuoVadis Root CA"
+# Serial: 985026699
+# MD5 Fingerprint: 27:de:36:fe:72:b7:00:03:00:9d:f4:f0:1e:6c:04:24
+# SHA1 Fingerprint: de:3f:40:bd:50:93:d3:9b:6c:60:f6:da:bc:07:62:01:00:89:76:c9
+# SHA256 Fingerprint: a4:5e:de:3b:bb:f0:9c:8a:e1:5c:72:ef:c0:72:68:d6:93:a2:1c:99:6f:d5:1e:67:ca:07:94:60:fd:6d:88:73
+-----BEGIN CERTIFICATE-----
+MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJC
+TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0
+aWZpY2F0aW9uIEF1dGhvcml0eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0
+aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAzMTkxODMzMzNaFw0yMTAzMTcxODMz
+MzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUw
+IwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVR
+dW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG
+9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Yp
+li4kVEAkOPcahdxYTMukJ0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2D
+rOpm2RgbaIr1VxqYuvXtdj182d6UajtLF8HVj71lODqV0D1VNk7feVcxKh7YWWVJ
+WCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeLYzcS19Dsw3sgQUSj7cug
+F+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWenAScOospU
+xbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCC
+Ak4wPQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVv
+dmFkaXNvZmZzaG9yZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREw
+ggENMIIBCQYJKwYBBAG+WAABMIH7MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNl
+IG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmljYXRlIGJ5IGFueSBwYXJ0eSBh
+c3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFy
+ZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh
+Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYI
+KwYBBQUHAgEWFmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3T
+KbkGGew5Oanwl4Rqy+/fMIGuBgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rq
+y+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1p
+dGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYD
+VQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6tlCL
+MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSk
+fnIYj9lofFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf8
+7C9TqnN7Az10buYWnuulLsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1R
+cHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2xgI4JVrmcGmD+XcHXetwReNDWXcG31a0y
+mQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi5upZIof4l/UO/erMkqQW
+xFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi5nrQNiOK
+SnQ2+Q==
+-----END CERTIFICATE-----
+
+# Issuer: CN=QuoVadis Root CA 2 O=QuoVadis Limited
+# Subject: CN=QuoVadis Root CA 2 O=QuoVadis Limited
+# Label: "QuoVadis Root CA 2"
+# Serial: 1289
+# MD5 Fingerprint: 5e:39:7b:dd:f8:ba:ec:82:e9:ac:62:ba:0c:54:00:2b
+# SHA1 Fingerprint: ca:3a:fb:cf:12:40:36:4b:44:b2:16:20:88:80:48:39:19:93:7c:f7
+# SHA256 Fingerprint: 85:a0:dd:7d:d7:20:ad:b7:ff:05:f8:3d:54:2b:20:9d:c7:ff:45:28:f7:d6:77:b1:83:89:fe:a5:e5:c4:9e:86
+-----BEGIN CERTIFICATE-----
+MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x
+GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv
+b3QgQ0EgMjAeFw0wNjExMjQxODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNV
+BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W
+YWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCa
+GMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6XJxg
+Fyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55J
+WpzmM+Yklvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bB
+rrcCaoF6qUWD4gXmuVbBlDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp
++ARz8un+XJiM9XOva7R+zdRcAitMOeGylZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1
+ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt66/3FsvbzSUr5R/7mp/i
+Ucw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1JdxnwQ5hYIiz
+PtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og
+/zOhD7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UH
+oycR7hYQe7xFSkyyBNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuI
+yV77zGHcizN300QyNQliBJIWENieJ0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1Ud
+EwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBQahGK8SEwzJQTU7tD2
+A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGUa6FJpEcwRTEL
+MAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT
+ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2f
+BluornFdLwUvZ+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzn
+g/iN/Ae42l9NLmeyhP3ZRPx3UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2Bl
+fF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodmVjB3pjd4M1IQWK4/YY7yarHvGH5K
+WWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK+JDSV6IZUaUtl0Ha
+B0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrWIozc
+hLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPR
+TUIZ3Ph1WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWD
+mbA4CD/pXvk1B+TJYm5Xf6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0Z
+ohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y
+4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8VCLAAVBpQ570su9t+Oza
+8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u
+-----END CERTIFICATE-----
+
+# Issuer: CN=QuoVadis Root CA 3 O=QuoVadis Limited
+# Subject: CN=QuoVadis Root CA 3 O=QuoVadis Limited
+# Label: "QuoVadis Root CA 3"
+# Serial: 1478
+# MD5 Fingerprint: 31:85:3c:62:94:97:63:b9:aa:fd:89:4e:af:6f:e0:cf
+# SHA1 Fingerprint: 1f:49:14:f7:d8:74:95:1d:dd:ae:02:c0:be:fd:3a:2d:82:75:51:85
+# SHA256 Fingerprint: 18:f1:fc:7f:20:5d:f8:ad:dd:eb:7f:e0:07:dd:57:e3:af:37:5a:9c:4d:8d:73:54:6b:f4:f1:fe:d1:e1:8d:35
+-----BEGIN CERTIFICATE-----
+MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x
+GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv
+b3QgQ0EgMzAeFw0wNjExMjQxOTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNV
+BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W
+YWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDM
+V0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNggDhoB
+4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUr
+H556VOijKTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd
+8lyyBTNvijbO0BNO/79KDDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9Cabwv
+vWhDFlaJKjdhkf2mrk7AyxRllDdLkgbvBNDInIjbC3uBr7E9KsRlOni27tyAsdLT
+mZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwpp5ijJUMv7/FfJuGITfhe
+btfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8nT8KKdjc
+T5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDt
+WAEXMJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZ
+c6tsgLjoC2SToJyMGf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A
+4iLItLRkT9a6fUg+qGkM17uGcclzuD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYD
+VR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHTBgkrBgEEAb5YAAMwgcUwgZMG
+CCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmljYXRlIGNvbnN0
+aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0
+aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVu
+dC4wLQYIKwYBBQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2Nw
+czALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4G
+A1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4ywLQoUmkRzBFMQswCQYDVQQGEwJC
+TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UEAxMSUXVvVmFkaXMg
+Um9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZVqyM0
+7ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSem
+d1o417+shvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd
++LJ2w/w4E6oM3kJpK27zPOuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B
+4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadN
+t54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp8kokUvd0/bpO5qgdAm6x
+DYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBCbjPsMZ57
+k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6s
+zHXug/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0j
+Wy10QJLZYxkNc91pvGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeT
+mJlglFwjz1onl14LBQaTNx47aTbrqZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK
+4SVhM7JZG+Ju1zdXtg2pEto=
+-----END CERTIFICATE-----
+
+# Issuer: O=SECOM Trust.net OU=Security Communication RootCA1
+# Subject: O=SECOM Trust.net OU=Security Communication RootCA1
+# Label: "Security Communication Root CA"
+# Serial: 0
+# MD5 Fingerprint: f1:bc:63:6a:54:e0:b5:27:f5:cd:e7:1a:e3:4d:6e:4a
+# SHA1 Fingerprint: 36:b1:2b:49:f9:81:9e:d7:4c:9e:bc:38:0f:c6:56:8f:5d:ac:b2:f7
+# SHA256 Fingerprint: e7:5e:72:ed:9f:56:0e:ec:6e:b4:80:00:73:a4:3f:c3:ad:19:19:5a:39:22:82:01:78:95:97:4a:99:02:6b:6c
+-----BEGIN CERTIFICATE-----
+MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEY
+MBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21t
+dW5pY2F0aW9uIFJvb3RDQTEwHhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5
+WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYD
+VQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw8yl8
+9f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJ
+DKaVv0uMDPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9
+Ms+k2Y7CI9eNqPPYJayX5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/N
+QV3Is00qVUarH9oe4kA92819uZKAnDfdDJZkndwi92SL32HeFZRSFaB9UslLqCHJ
+xrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2JChzAgMBAAGjPzA9MB0G
+A1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYwDwYDVR0T
+AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vG
+kl3g0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfr
+Uj94nK9NrvjVT8+amCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5
+Bw+SUEmK3TGXX8npN6o7WWWXlDLJs58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJU
+JRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ6rBK+1YWc26sTfcioU+tHXot
+RSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAiFL39vmwLAw==
+-----END CERTIFICATE-----
+
+# Issuer: CN=Sonera Class2 CA O=Sonera
+# Subject: CN=Sonera Class2 CA O=Sonera
+# Label: "Sonera Class 2 Root CA"
+# Serial: 29
+# MD5 Fingerprint: a3:ec:75:0f:2e:88:df:fa:48:01:4e:0b:5c:48:6f:fb
+# SHA1 Fingerprint: 37:f7:6d:e6:07:7c:90:c5:b1:3e:93:1a:b7:41:10:b4:f2:e4:9a:27
+# SHA256 Fingerprint: 79:08:b4:03:14:c1:38:10:0b:51:8d:07:35:80:7f:fb:fc:f8:51:8a:00:95:33:71:05:ba:38:6b:15:3d:d9:27
+-----BEGIN CERTIFICATE-----
+MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEP
+MA0GA1UEChMGU29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAx
+MDQwNjA3Mjk0MFoXDTIxMDQwNjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNV
+BAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJhIENsYXNzMiBDQTCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3/Ei9vX+ALTU74W+o
+Z6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybTdXnt
+5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s
+3TmVToMGf+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2Ej
+vOr7nQKV0ba5cTppCD8PtOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu
+8nYybieDwnPz3BjotJPqdURrBGAgcVeHnfO+oJAjPYok4doh28MCAwEAAaMzMDEw
+DwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITTXjwwCwYDVR0PBAQDAgEG
+MA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt0jSv9zil
+zqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/
+3DEIcbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvD
+FNr450kkkdAdavphOe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6
+Tk6ezAyNlNzZRZxe7EJQY670XcSxEtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2
+ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLHllpwrN9M
+-----END CERTIFICATE-----
+
+# Issuer: CN=XRamp Global Certification Authority O=XRamp Security Services Inc OU=www.xrampsecurity.com
+# Subject: CN=XRamp Global Certification Authority O=XRamp Security Services Inc OU=www.xrampsecurity.com
+# Label: "XRamp Global CA Root"
+# Serial: 107108908803651509692980124233745014957
+# MD5 Fingerprint: a1:0b:44:b3:ca:10:d8:00:6e:9d:0f:d8:0f:92:0a:d1
+# SHA1 Fingerprint: b8:01:86:d1:eb:9c:86:a5:41:04:cf:30:54:f3:4c:52:b7:e5:58:c6
+# SHA256 Fingerprint: ce:cd:dc:90:50:99:d8:da:df:c5:b1:d2:09:b7:37:cb:e2:c1:8c:fb:2c:10:c0:ff:0b:cf:0d:32:86:fc:1a:a2
+-----BEGIN CERTIFICATE-----
+MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCB
+gjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEk
+MCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRY
+UmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQxMTAxMTcx
+NDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3
+dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2Vy
+dmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB
+dXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS6
+38eMpSe2OAtp87ZOqCwuIR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCP
+KZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMxfoArtYzAQDsRhtDLooY2YKTVMIJt2W7Q
+DxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FEzG+gSqmUsE3a56k0enI4
+qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqsAxcZZPRa
+JSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNVi
+PvryxS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0P
+BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASs
+jVy16bYbMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0
+eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQEwDQYJKoZIhvcNAQEFBQAD
+ggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc/Kh4ZzXxHfAR
+vbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt
+qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLa
+IR9NmXmd4c8nnxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSy
+i6mx5O+aGtA9aZnuqCij4Tyz8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQ
+O+7ETPTsJ3xCwnR8gooJybQDJbw=
+-----END CERTIFICATE-----
+
+# Issuer: O=The Go Daddy Group, Inc. OU=Go Daddy Class 2 Certification Authority
+# Subject: O=The Go Daddy Group, Inc. OU=Go Daddy Class 2 Certification Authority
+# Label: "Go Daddy Class 2 CA"
+# Serial: 0
+# MD5 Fingerprint: 91:de:06:25:ab:da:fd:32:17:0c:bb:25:17:2a:84:67
+# SHA1 Fingerprint: 27:96:ba:e6:3f:18:01:e2:77:26:1b:a0:d7:77:70:02:8f:20:ee:e4
+# SHA256 Fingerprint: c3:84:6b:f2:4b:9e:93:ca:64:27:4c:0e:c6:7c:1e:cc:5e:02:4f:fc:ac:d2:d7:40:19:35:0e:81:fe:54:6a:e4
+-----BEGIN CERTIFICATE-----
+MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh
+MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE
+YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3
+MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo
+ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg
+MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN
+ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA
+PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w
+wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi
+EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY
+avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+
+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE
+sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h
+/t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5
+IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj
+YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD
+ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy
+OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P
+TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ
+HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER
+dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf
+ReYNnyicsbkqWletNw+vHX/bvZ8=
+-----END CERTIFICATE-----
+
+# Issuer: O=Starfield Technologies, Inc. OU=Starfield Class 2 Certification Authority
+# Subject: O=Starfield Technologies, Inc. OU=Starfield Class 2 Certification Authority
+# Label: "Starfield Class 2 CA"
+# Serial: 0
+# MD5 Fingerprint: 32:4a:4b:bb:c8:63:69:9b:be:74:9a:c6:dd:1d:46:24
+# SHA1 Fingerprint: ad:7e:1c:28:b0:64:ef:8f:60:03:40:20:14:c3:d0:e3:37:0e:b5:8a
+# SHA256 Fingerprint: 14:65:fa:20:53:97:b8:76:fa:a6:f0:a9:95:8e:55:90:e4:0f:cc:7f:aa:4f:b7:c2:c8:67:75:21:fb:5f:b6:58
+-----BEGIN CERTIFICATE-----
+MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl
+MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp
+U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw
+NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE
+ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp
+ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3
+DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf
+8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN
++lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0
+X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa
+K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA
+1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G
+A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR
+zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0
+YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD
+bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w
+DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3
+L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D
+eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl
+xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp
+VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY
+WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q=
+-----END CERTIFICATE-----
+
+# Issuer: O=Government Root Certification Authority
+# Subject: O=Government Root Certification Authority
+# Label: "Taiwan GRCA"
+# Serial: 42023070807708724159991140556527066870
+# MD5 Fingerprint: 37:85:44:53:32:45:1f:20:f0:f3:95:e1:25:c4:43:4e
+# SHA1 Fingerprint: f4:8b:11:bf:de:ab:be:94:54:20:71:e6:41:de:6b:be:88:2b:40:b9
+# SHA256 Fingerprint: 76:00:29:5e:ef:e8:5b:9e:1f:d6:24:db:76:06:2a:aa:ae:59:81:8a:54:d2:77:4c:d4:c0:b2:c0:11:31:e1:b3
+-----BEGIN CERTIFICATE-----
+MIIFcjCCA1qgAwIBAgIQH51ZWtcvwgZEpYAIaeNe9jANBgkqhkiG9w0BAQUFADA/
+MQswCQYDVQQGEwJUVzEwMC4GA1UECgwnR292ZXJubWVudCBSb290IENlcnRpZmlj
+YXRpb24gQXV0aG9yaXR5MB4XDTAyMTIwNTEzMjMzM1oXDTMyMTIwNTEzMjMzM1ow
+PzELMAkGA1UEBhMCVFcxMDAuBgNVBAoMJ0dvdmVybm1lbnQgUm9vdCBDZXJ0aWZp
+Y2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB
+AJoluOzMonWoe/fOW1mKydGGEghU7Jzy50b2iPN86aXfTEc2pBsBHH8eV4qNw8XR
+IePaJD9IK/ufLqGU5ywck9G/GwGHU5nOp/UKIXZ3/6m3xnOUT0b3EEk3+qhZSV1q
+gQdW8or5BtD3cCJNtLdBuTK4sfCxw5w/cP1T3YGq2GN49thTbqGsaoQkclSGxtKy
+yhwOeYHWtXBiCAEuTk8O1RGvqa/lmr/czIdtJuTJV6L7lvnM4T9TjGxMfptTCAts
+F/tnyMKtsc2AtJfcdgEWFelq16TheEfOhtX7MfP6Mb40qij7cEwdScevLJ1tZqa2
+jWR+tSBqnTuBto9AAGdLiYa4zGX+FVPpBMHWXx1E1wovJ5pGfaENda1UhhXcSTvx
+ls4Pm6Dso3pdvtUqdULle96ltqqvKKyskKw4t9VoNSZ63Pc78/1Fm9G7Q3hub/FC
+VGqY8A2tl+lSXunVanLeavcbYBT0peS2cWeqH+riTcFCQP5nRhc4L0c/cZyu5SHK
+YS1tB6iEfC3uUSXxY5Ce/eFXiGvviiNtsea9P63RPZYLhY3Naye7twWb7LuRqQoH
+EgKXTiCQ8P8NHuJBO9NAOueNXdpm5AKwB1KYXA6OM5zCppX7VRluTI6uSw+9wThN
+Xo+EHWbNxWCWtFJaBYmOlXqYwZE8lSOyDvR5tMl8wUohAgMBAAGjajBoMB0GA1Ud
+DgQWBBTMzO/MKWCkO7GStjz6MmKPrCUVOzAMBgNVHRMEBTADAQH/MDkGBGcqBwAE
+MTAvMC0CAQAwCQYFKw4DAhoFADAHBgVnKgMAAAQUA5vwIhP/lSg209yewDL7MTqK
+UWUwDQYJKoZIhvcNAQEFBQADggIBAECASvomyc5eMN1PhnR2WPWus4MzeKR6dBcZ
+TulStbngCnRiqmjKeKBMmo4sIy7VahIkv9Ro04rQ2JyftB8M3jh+Vzj8jeJPXgyf
+qzvS/3WXy6TjZwj/5cAWtUgBfen5Cv8b5Wppv3ghqMKnI6mGq3ZW6A4M9hPdKmaK
+ZEk9GhiHkASfQlK3T8v+R0F2Ne//AHY2RTKbxkaFXeIksB7jSJaYV0eUVXoPQbFE
+JPPB/hprv4j9wabak2BegUqZIJxIZhm1AHlUD7gsL0u8qV1bYH+Mh6XgUmMqvtg7
+hUAV/h62ZT/FS9p+tXo1KaMuephgIqP0fSdOLeq0dDzpD6QzDxARvBMB1uUO07+1
+EqLhRSPAzAhuYbeJq4PjJB7mXQfnHyA+z2fI56wwbSdLaG5LKlwCCDTb+HbkZ6Mm
+nD+iMsJKxYEYMRBWqoTvLQr/uB930r+lWKBi5NdLkXWNiYCYfm3LU05er/ayl4WX
+udpVBrkk7tfGOB5jGxI7leFYrPLfhNVfmS8NVVvmONsuP3LpSIXLuykTjx44Vbnz
+ssQwmSNOXfJIoRIM3BKQCZBUkQM8R+XVyWXgt0t97EfTsws+rZ7QdAAO671RrcDe
+LMDDav7v3Aun+kbfYNucpllQdSNpc5Oy+fwC00fmcc4QAu4njIT/rEUNE1yDMuAl
+pYYsfPQS
+-----END CERTIFICATE-----
+
+# Issuer: CN=DigiCert Assured ID Root CA O=DigiCert Inc OU=www.digicert.com
+# Subject: CN=DigiCert Assured ID Root CA O=DigiCert Inc OU=www.digicert.com
+# Label: "DigiCert Assured ID Root CA"
+# Serial: 17154717934120587862167794914071425081
+# MD5 Fingerprint: 87:ce:0b:7b:2a:0e:49:00:e1:58:71:9b:37:a8:93:72
+# SHA1 Fingerprint: 05:63:b8:63:0d:62:d7:5a:bb:c8:ab:1e:4b:df:b5:a8:99:b2:4d:43
+# SHA256 Fingerprint: 3e:90:99:b5:01:5e:8f:48:6c:00:bc:ea:9d:11:1e:e7:21:fa:ba:35:5a:89:bc:f1:df:69:56:1e:3d:c6:32:5c
+-----BEGIN CERTIFICATE-----
+MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBl
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv
+b3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzExMTEwMDAwMDAwWjBlMQswCQYDVQQG
+EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl
+cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7c
+JpSIqvTO9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYP
+mDI2dsze3Tyoou9q+yHyUmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+
+wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4
+VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpyoeb6pNnVFzF1roV9Iq4/
+AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whfGHdPAgMB
+AAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW
+BBRF66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYun
+pyGd823IDzANBgkqhkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRC
+dWKuh+vy1dneVrOfzM4UKLkNl2BcEkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTf
+fwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38FnSbNd67IJKusm7Xi+fT8r87cm
+NW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i8b5QZ7dsvfPx
+H2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe
++o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g==
+-----END CERTIFICATE-----
+
+# Issuer: CN=DigiCert Global Root CA O=DigiCert Inc OU=www.digicert.com
+# Subject: CN=DigiCert Global Root CA O=DigiCert Inc OU=www.digicert.com
+# Label: "DigiCert Global Root CA"
+# Serial: 10944719598952040374951832963794454346
+# MD5 Fingerprint: 79:e4:a9:84:0d:7d:3a:96:d7:c0:4f:e2:43:4c:89:2e
+# SHA1 Fingerprint: a8:98:5d:3a:65:e5:e5:c4:b2:d7:d6:6d:40:c6:dd:2f:b1:9c:54:36
+# SHA256 Fingerprint: 43:48:a0:e9:44:4c:78:cb:26:5e:05:8d:5e:89:44:b4:d8:4f:96:62:bd:26:db:25:7f:89:34:a4:43:c7:01:61
+-----BEGIN CERTIFICATE-----
+MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
+QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT
+MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
+b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG
+9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB
+CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97
+nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt
+43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P
+T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4
+gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO
+BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR
+TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw
+DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr
+hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg
+06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF
+PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls
+YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
+CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
+-----END CERTIFICATE-----
+
+# Issuer: CN=DigiCert High Assurance EV Root CA O=DigiCert Inc OU=www.digicert.com
+# Subject: CN=DigiCert High Assurance EV Root CA O=DigiCert Inc OU=www.digicert.com
+# Label: "DigiCert High Assurance EV Root CA"
+# Serial: 3553400076410547919724730734378100087
+# MD5 Fingerprint: d4:74:de:57:5c:39:b2:d3:9c:85:83:c5:c0:65:49:8a
+# SHA1 Fingerprint: 5f:b7:ee:06:33:e2:59:db:ad:0c:4c:9a:e6:d3:8f:1a:61:c7:dc:25
+# SHA256 Fingerprint: 74:31:e5:f4:c3:c1:ce:46:90:77:4f:0b:61:e0:54:40:88:3b:a9:a0:1e:d0:0b:a6:ab:d7:80:6e:d3:b1:18:cf
+-----BEGIN CERTIFICATE-----
+MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
+ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL
+MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
+LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
+RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm
++9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW
+PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM
+xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB
+Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3
+hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg
+EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF
+MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA
+FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec
+nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z
+eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF
+hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2
+Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
+vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep
++OkuE6N36B9K
+-----END CERTIFICATE-----
+
+# Issuer: CN=Class 2 Primary CA O=Certplus
+# Subject: CN=Class 2 Primary CA O=Certplus
+# Label: "Certplus Class 2 Primary CA"
+# Serial: 177770208045934040241468760488327595043
+# MD5 Fingerprint: 88:2c:8c:52:b8:a2:3c:f3:f7:bb:03:ea:ae:ac:42:0b
+# SHA1 Fingerprint: 74:20:74:41:72:9c:dd:92:ec:79:31:d8:23:10:8d:c2:81:92:e2:bb
+# SHA256 Fingerprint: 0f:99:3c:8a:ef:97:ba:af:56:87:14:0e:d5:9a:d1:82:1b:b4:af:ac:f0:aa:9a:58:b5:d5:7a:33:8a:3a:fb:cb
+-----BEGIN CERTIFICATE-----
+MIIDkjCCAnqgAwIBAgIRAIW9S/PY2uNp9pTXX8OlRCMwDQYJKoZIhvcNAQEFBQAw
+PTELMAkGA1UEBhMCRlIxETAPBgNVBAoTCENlcnRwbHVzMRswGQYDVQQDExJDbGFz
+cyAyIFByaW1hcnkgQ0EwHhcNOTkwNzA3MTcwNTAwWhcNMTkwNzA2MjM1OTU5WjA9
+MQswCQYDVQQGEwJGUjERMA8GA1UEChMIQ2VydHBsdXMxGzAZBgNVBAMTEkNsYXNz
+IDIgUHJpbWFyeSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANxQ
+ltAS+DXSCHh6tlJw/W/uz7kRy1134ezpfgSN1sxvc0NXYKwzCkTsA18cgCSR5aiR
+VhKC9+Ar9NuuYS6JEI1rbLqzAr3VNsVINyPi8Fo3UjMXEuLRYE2+L0ER4/YXJQyL
+kcAbmXuZVg2v7tK8R1fjeUl7NIknJITesezpWE7+Tt9avkGtrAjFGA7v0lPubNCd
+EgETjdyAYveVqUSISnFOYFWe2yMZeVYHDD9jC1yw4r5+FfyUM1hBOHTE4Y+L3yas
+H7WLO7dDWWuwJKZtkIvEcupdM5i3y95ee++U8Rs+yskhwcWYAqqi9lt3m/V+llU0
+HGdpwPFC40es/CgcZlUCAwEAAaOBjDCBiTAPBgNVHRMECDAGAQH/AgEKMAsGA1Ud
+DwQEAwIBBjAdBgNVHQ4EFgQU43Mt38sOKAze3bOkynm4jrvoMIkwEQYJYIZIAYb4
+QgEBBAQDAgEGMDcGA1UdHwQwMC4wLKAqoCiGJmh0dHA6Ly93d3cuY2VydHBsdXMu
+Y29tL0NSTC9jbGFzczIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCnVM+IRBnL39R/
+AN9WM2K191EBkOvDP9GIROkkXe/nFL0gt5o8AP5tn9uQ3Nf0YtaLcF3n5QRIqWh8
+yfFC82x/xXp8HVGIutIKPidd3i1RTtMTZGnkLuPT55sJmabglZvOGtd/vjzOUrMR
+FcEPF80Du5wlFbqidon8BvEY0JNLDnyCt6X09l/+7UCmnYR0ObncHoUW2ikbhiMA
+ybuJfm6AiB4vFLQDJKgybwOaRywwvlbGp0ICcBvqQNi6BQNwB6SW//1IMwrh3KWB
+kJtN3X3n57LNXMhqlfil9o3EXXgIvnsG1knPGTZQIy4I5p4FTUcY1Rbpsda2ENW7
+l7+ijrRU
+-----END CERTIFICATE-----
+
+# Issuer: CN=DST Root CA X3 O=Digital Signature Trust Co.
+# Subject: CN=DST Root CA X3 O=Digital Signature Trust Co.
+# Label: "DST Root CA X3"
+# Serial: 91299735575339953335919266965803778155
+# MD5 Fingerprint: 41:03:52:dc:0f:f7:50:1b:16:f0:02:8e:ba:6f:45:c5
+# SHA1 Fingerprint: da:c9:02:4f:54:d8:f6:df:94:93:5f:b1:73:26:38:ca:6a:d7:7c:13
+# SHA256 Fingerprint: 06:87:26:03:31:a7:24:03:d9:09:f1:05:e6:9b:cf:0d:32:e1:bd:24:93:ff:c6:d9:20:6d:11:bc:d6:77:07:39
+-----BEGIN CERTIFICATE-----
+MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/
+MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
+DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow
+PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD
+Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O
+rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq
+OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b
+xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw
+7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD
+aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV
+HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG
+SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69
+ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr
+AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz
+R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5
+JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo
+Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ
+-----END CERTIFICATE-----
+
+# Issuer: CN=SwissSign Gold CA - G2 O=SwissSign AG
+# Subject: CN=SwissSign Gold CA - G2 O=SwissSign AG
+# Label: "SwissSign Gold CA - G2"
+# Serial: 13492815561806991280
+# MD5 Fingerprint: 24:77:d9:a8:91:d1:3b:fa:88:2d:c2:ff:f8:cd:33:93
+# SHA1 Fingerprint: d8:c5:38:8a:b7:30:1b:1b:6e:d4:7a:e6:45:25:3a:6f:9f:1a:27:61
+# SHA256 Fingerprint: 62:dd:0b:e9:b9:f5:0a:16:3e:a0:f8:e7:5c:05:3b:1e:ca:57:ea:55:c8:68:8f:64:7c:68:81:f2:c8:35:7b:95
+-----BEGIN CERTIFICATE-----
+MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
+BAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2ln
+biBHb2xkIENBIC0gRzIwHhcNMDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBF
+MQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dpc3NTaWduIEFHMR8wHQYDVQQDExZT
+d2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC
+CgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUqt2/8
+76LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+
+bbqBHH5CjCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c
+6bM8K8vzARO/Ws/BtQpgvd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqE
+emA8atufK+ze3gE/bk3lUIbLtK/tREDFylqM2tIrfKjuvqblCqoOpd8FUrdVxyJd
+MmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvRAiTysybUa9oEVeXBCsdt
+MDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuendjIj3o02y
+MszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69y
+FGkOpeUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPi
+aG59je883WX0XaxR7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxM
+gI93e2CaHt+28kgeDrpOVG2Y4OGiGqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCB
+qTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUWyV7
+lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64OfPAeGZe6Drn
+8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov
+L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe6
+45R88a7A3hfm5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczO
+UYrHUDFu4Up+GC9pWbY9ZIEr44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5
+O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOfMke6UiI0HTJ6CVanfCU2qT1L2sCC
+bwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6mGu6uLftIdxf+u+yv
+GPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxpmo/a
+77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCC
+hdiDyyJkvC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid3
+92qgQmwLOM7XdVAyksLfKzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEpp
+Ld6leNcG2mqeSz53OiATIgHQv2ieY2BrNU0LbbqhPcCT4H8js1WtciVORvnSFu+w
+ZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6LqjviOvrv1vA+ACOzB2+htt
+Qc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ
+-----END CERTIFICATE-----
+
+# Issuer: CN=SwissSign Silver CA - G2 O=SwissSign AG
+# Subject: CN=SwissSign Silver CA - G2 O=SwissSign AG
+# Label: "SwissSign Silver CA - G2"
+# Serial: 5700383053117599563
+# MD5 Fingerprint: e0:06:a1:c9:7d:cf:c9:fc:0d:c0:56:75:96:d8:62:13
+# SHA1 Fingerprint: 9b:aa:e5:9f:56:ee:21:cb:43:5a:be:25:93:df:a7:f0:40:d1:1d:cb
+# SHA256 Fingerprint: be:6c:4d:a2:bb:b9:ba:59:b6:f3:93:97:68:37:42:46:c3:c0:05:99:3f:a9:8f:02:0d:1d:ed:be:d4:8a:81:d5
+-----BEGIN CERTIFICATE-----
+MIIFvTCCA6WgAwIBAgIITxvUL1S7L0swDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UE
+BhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWdu
+IFNpbHZlciBDQSAtIEcyMB4XDTA2MTAyNTA4MzI0NloXDTM2MTAyNTA4MzI0Nlow
+RzELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMY
+U3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
+MIICCgKCAgEAxPGHf9N4Mfc4yfjDmUO8x/e8N+dOcbpLj6VzHVxumK4DV644N0Mv
+Fz0fyM5oEMF4rhkDKxD6LHmD9ui5aLlV8gREpzn5/ASLHvGiTSf5YXu6t+WiE7br
+YT7QbNHm+/pe7R20nqA1W6GSy/BJkv6FCgU+5tkL4k+73JU3/JHpMjUi0R86TieF
+nbAVlDLaYQ1HTWBCrpJH6INaUFjpiou5XaHc3ZlKHzZnu0jkg7Y360g6rw9njxcH
+6ATK72oxh9TAtvmUcXtnZLi2kUpCe2UuMGoM9ZDulebyzYLs2aFK7PayS+VFheZt
+eJMELpyCbTapxDFkH4aDCyr0NQp4yVXPQbBH6TCfmb5hqAaEuSh6XzjZG6k4sIN/
+c8HDO0gqgg8hm7jMqDXDhBuDsz6+pJVpATqJAHgE2cn0mRmrVn5bi4Y5FZGkECwJ
+MoBgs5PAKrYYC51+jUnyEEp/+dVGLxmSo5mnJqy7jDzmDrxHB9xzUfFwZC8I+bRH
+HTBsROopN4WSaGa8gzj+ezku01DwH/teYLappvonQfGbGHLy9YR0SslnxFSuSGTf
+jNFusB3hB48IHpmccelM2KX3RxIfdNFRnobzwqIjQAtz20um53MGjMGg6cFZrEb6
+5i/4z3GcRm25xBWNOHkDRUjvxF3XCO6HOSKGsg0PWEP3calILv3q1h8CAwEAAaOB
+rDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU
+F6DNweRBtjpbO8tFnb0cwpj6hlgwHwYDVR0jBBgwFoAUF6DNweRBtjpbO8tFnb0c
+wpj6hlgwRgYDVR0gBD8wPTA7BglghXQBWQEDAQEwLjAsBggrBgEFBQcCARYgaHR0
+cDovL3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIB
+AHPGgeAn0i0P4JUw4ppBf1AsX19iYamGamkYDHRJ1l2E6kFSGG9YrVBWIGrGvShp
+WJHckRE1qTodvBqlYJ7YH39FkWnZfrt4csEGDyrOj4VwYaygzQu4OSlWhDJOhrs9
+xCrZ1x9y7v5RoSJBsXECYxqCsGKrXlcSH9/L3XWgwF15kIwb4FDm3jH+mHtwX6WQ
+2K34ArZv02DdQEsixT2tOnqfGhpHkXkzuoLcMmkDlm4fS/Bx/uNncqCxv1yL5PqZ
+IseEuRuNI5c/7SXgz2W79WEE790eslpBIlqhn10s6FvJbakMDHiqYMZWjwFaDGi8
+aRl5xB9+lwW/xekkUV7U1UtT7dkjWjYDZaPBA61BMPNGG4WQr2W11bHkFlt4dR2X
+em1ZqSqPe97Dh4kQmUlzeMg9vVE1dCrV8X5pGyq7O70luJpaPXJhkGaH7gzWTdQR
+dAtq/gsD/KNVV4n+SsuuWxcFyPKNIzFTONItaj+CuY0IavdeQXRuwxF+B6wpYJE/
+OMpXEA29MC/HpeZBoNquBYeaoKRlbEwJDIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+
+hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ubDgEj8Z+7fNzcbBGXJbLy
+tGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u
+-----END CERTIFICATE-----
+
+# Issuer: CN=GeoTrust Primary Certification Authority O=GeoTrust Inc.
+# Subject: CN=GeoTrust Primary Certification Authority O=GeoTrust Inc.
+# Label: "GeoTrust Primary Certification Authority"
+# Serial: 32798226551256963324313806436981982369
+# MD5 Fingerprint: 02:26:c3:01:5e:08:30:37:43:a9:d0:7d:cf:37:e6:bf
+# SHA1 Fingerprint: 32:3c:11:8e:1b:f7:b8:b6:52:54:e2:e2:10:0d:d6:02:90:37:f0:96
+# SHA256 Fingerprint: 37:d5:10:06:c5:12:ea:ab:62:64:21:f1:ec:8c:92:01:3f:c5:f8:2a:e9:8e:e5:33:eb:46:19:b8:de:b4:d0:6c
+-----BEGIN CERTIFICATE-----
+MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBY
+MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMo
+R2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEx
+MjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgxCzAJBgNVBAYTAlVTMRYwFAYDVQQK
+Ew1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQcmltYXJ5IENlcnRp
+ZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
+AQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9
+AWbK7hWNb6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjA
+ZIVcFU2Ix7e64HXprQU9nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE0
+7e9GceBrAqg1cmuXm2bgyxx5X9gaBGgeRwLmnWDiNpcB3841kt++Z8dtd1k7j53W
+kBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGttm/81w7a4DSwDRp35+MI
+mO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4G
+A1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJ
+KoZIhvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ1
+6CePbJC/kRYkRj5KTs4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl
+4b7UVXGYNTq+k+qurUKykG/g/CFNNWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6K
+oKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHaFloxt/m0cYASSJlyc1pZU8Fj
+UjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG1riR/aYNKxoU
+AT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk=
+-----END CERTIFICATE-----
+
+# Issuer: CN=thawte Primary Root CA O=thawte, Inc. OU=Certification Services Division/(c) 2006 thawte, Inc. - For authorized use only
+# Subject: CN=thawte Primary Root CA O=thawte, Inc. OU=Certification Services Division/(c) 2006 thawte, Inc. - For authorized use only
+# Label: "thawte Primary Root CA"
+# Serial: 69529181992039203566298953787712940909
+# MD5 Fingerprint: 8c:ca:dc:0b:22:ce:f5:be:72:ac:41:1a:11:a8:d8:12
+# SHA1 Fingerprint: 91:c6:d6:ee:3e:8a:c8:63:84:e5:48:c2:99:29:5c:75:6c:81:7b:81
+# SHA256 Fingerprint: 8d:72:2f:81:a9:c1:13:c0:79:1d:f1:36:a2:96:6d:b2:6c:95:0a:97:1d:b4:6b:41:99:f4:ea:54:b7:8b:fb:9f
+-----BEGIN CERTIFICATE-----
+MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCB
+qTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf
+Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw
+MDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNV
+BAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3MDAwMDAwWhcNMzYw
+NzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5j
+LjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYG
+A1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl
+IG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsoPD7gFnUnMekz52hWXMJEEUMDSxuaPFs
+W0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ1CRfBsDMRJSUjQJib+ta
+3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGcq/gcfomk
+6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6
+Sk/KaAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94J
+NqR32HuHUETVPm4pafs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBA
+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XP
+r87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUFAAOCAQEAeRHAS7ORtvzw6WfU
+DW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeEuzLlQRHAd9mz
+YJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX
+xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2
+/qxAeeWsEG89jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/
+LHbTY5xZ3Y+m4Q6gLkH3LpVHz7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7
+jVaMaA==
+-----END CERTIFICATE-----
+
+# Issuer: CN=VeriSign Class 3 Public Primary Certification Authority - G5 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2006 VeriSign, Inc. - For authorized use only
+# Subject: CN=VeriSign Class 3 Public Primary Certification Authority - G5 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2006 VeriSign, Inc. - For authorized use only
+# Label: "VeriSign Class 3 Public Primary Certification Authority - G5"
+# Serial: 33037644167568058970164719475676101450
+# MD5 Fingerprint: cb:17:e4:31:67:3e:e2:09:fe:45:57:93:f3:0a:fa:1c
+# SHA1 Fingerprint: 4e:b6:d5:78:49:9b:1c:cf:5f:58:1e:ad:56:be:3d:9b:67:44:a5:e5
+# SHA256 Fingerprint: 9a:cf:ab:7e:43:c8:d8:80:d0:6b:26:2a:94:de:ee:e4:b4:65:99:89:c3:d0:ca:f1:9b:af:64:05:e4:1a:b7:df
+-----BEGIN CERTIFICATE-----
+MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB
+yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL
+ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp
+U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW
+ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0
+aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCByjEL
+MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW
+ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2ln
+biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp
+U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y
+aXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1
+nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbex
+t0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIz
+SdhDY2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQG
+BO+QueQA5N06tRn/Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+
+rCpSx4/VBEnkjWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/
+NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E
+BAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAH
+BgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy
+aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKv
+MzEzMA0GCSqGSIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzE
+p6B4Eq1iDkVwZMXnl2YtmAl+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y
+5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKEKQsTb47bDN0lAtukixlE0kF6BWlK
+WE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiCKm0oHw0LxOXnGiYZ
+4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vEZV8N
+hnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq
+-----END CERTIFICATE-----
+
+# Issuer: CN=SecureTrust CA O=SecureTrust Corporation
+# Subject: CN=SecureTrust CA O=SecureTrust Corporation
+# Label: "SecureTrust CA"
+# Serial: 17199774589125277788362757014266862032
+# MD5 Fingerprint: dc:32:c3:a7:6d:25:57:c7:68:09:9d:ea:2d:a9:a2:d1
+# SHA1 Fingerprint: 87:82:c6:c3:04:35:3b:cf:d2:96:92:d2:59:3e:7d:44:d9:34:ff:11
+# SHA256 Fingerprint: f1:c1:b5:0a:e5:a2:0d:d8:03:0e:c9:f6:bc:24:82:3d:d3:67:b5:25:57:59:b4:e7:1b:61:fc:e9:f7:37:5d:73
+-----BEGIN CERTIFICATE-----
+MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBI
+MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x
+FzAVBgNVBAMTDlNlY3VyZVRydXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIz
+MTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAeBgNVBAoTF1NlY3VyZVRydXN0IENv
+cnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCCASIwDQYJKoZIhvcN
+AQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQXOZEz
+Zum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO
+0gMdA+9tDWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIao
+wW8xQmxSPmjL8xk037uHGFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj
+7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b01k/unK8RCSc43Oz969XL0Imnal0ugBS
+8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmHursCAwEAAaOBnTCBmjAT
+BgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB
+/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCeg
+JYYjaHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGC
+NxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt3
+6Z3q059c4EVlew3KW+JwULKUBRSuSceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/
+3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHfmbx8IVQr5Fiiu1cprp6poxkm
+D5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZnMUFdAvnZyPS
+CPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR
+3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE=
+-----END CERTIFICATE-----
+
+# Issuer: CN=Secure Global CA O=SecureTrust Corporation
+# Subject: CN=Secure Global CA O=SecureTrust Corporation
+# Label: "Secure Global CA"
+# Serial: 9751836167731051554232119481456978597
+# MD5 Fingerprint: cf:f4:27:0d:d4:ed:dc:65:16:49:6d:3d:da:bf:6e:de
+# SHA1 Fingerprint: 3a:44:73:5a:e5:81:90:1f:24:86:61:46:1e:3b:9c:c4:5f:f5:3a:1b
+# SHA256 Fingerprint: 42:00:f5:04:3a:c8:59:0e:bb:52:7d:20:9e:d1:50:30:29:fb:cb:d4:1c:a1:b5:06:ec:27:f1:5a:de:7d:ac:69
+-----BEGIN CERTIFICATE-----
+MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBK
+MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x
+GTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkx
+MjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3Qg
+Q29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jxYDiJ
+iQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa
+/FHtaMbQbqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJ
+jnIFHovdRIWCQtBJwB1g8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnI
+HmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYVHDGA76oYa8J719rO+TMg1fW9ajMtgQT7
+sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi0XPnj3pDAgMBAAGjgZ0w
+gZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQF
+MAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCsw
+KaAnoCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsG
+AQQBgjcVAQQDAgEAMA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0L
+URYD7xh8yOOvaliTFGCRsoTciE6+OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXO
+H0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cnCDpOGR86p1hcF895P4vkp9Mm
+I50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/53CYNv6ZHdAbY
+iNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc
+f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW
+-----END CERTIFICATE-----
+
+# Issuer: CN=COMODO Certification Authority O=COMODO CA Limited
+# Subject: CN=COMODO Certification Authority O=COMODO CA Limited
+# Label: "COMODO Certification Authority"
+# Serial: 104350513648249232941998508985834464573
+# MD5 Fingerprint: 5c:48:dc:f7:42:72:ec:56:94:6d:1c:cc:71:35:80:75
+# SHA1 Fingerprint: 66:31:bf:9e:f7:4f:9e:b6:c9:d5:a6:0c:ba:6a:be:d1:f7:bd:ef:7b
+# SHA256 Fingerprint: 0c:2c:d6:3d:f7:80:6f:a3:99:ed:e8:09:11:6b:57:5b:f8:79:89:f0:65:18:f9:80:8c:86:05:03:17:8b:af:66
+-----BEGIN CERTIFICATE-----
+MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCB
+gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
+A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV
+BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAw
+MDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3Jl
+YXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01P
+RE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0
+aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3
+UcEbVASY06m/weaKXTuH+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI
+2GqGd0S7WWaXUF601CxwRM/aN5VCaTwwxHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8
+Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV4EajcNxo2f8ESIl33rXp
++2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA1KGzqSX+
+DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5O
+nKVIrLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW
+/zAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6g
+PKA6hjhodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9u
+QXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOCAQEAPpiem/Yb6dc5t3iuHXIY
+SdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CPOGEIqB6BCsAv
+IC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/
+RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4
+zJVSk/BwJVmcIGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5dd
+BA6+C4OmF4O5MBKgxTMVBbkN+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IB
+ZQ==
+-----END CERTIFICATE-----
+
+# Issuer: CN=Network Solutions Certificate Authority O=Network Solutions L.L.C.
+# Subject: CN=Network Solutions Certificate Authority O=Network Solutions L.L.C.
+# Label: "Network Solutions Certificate Authority"
+# Serial: 116697915152937497490437556386812487904
+# MD5 Fingerprint: d3:f3:a6:16:c0:fa:6b:1d:59:b1:2d:96:4d:0e:11:2e
+# SHA1 Fingerprint: 74:f8:a3:c3:ef:e7:b3:90:06:4b:83:90:3c:21:64:60:20:e5:df:ce
+# SHA256 Fingerprint: 15:f0:ba:00:a3:ac:7a:f3:ac:88:4c:07:2b:10:11:a0:77:bd:77:c0:97:f4:01:64:b2:f8:59:8a:bd:83:86:0c
+-----BEGIN CERTIFICATE-----
+MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBi
+MQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu
+MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3Jp
+dHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMxMjM1OTU5WjBiMQswCQYDVQQGEwJV
+UzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydO
+ZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwz
+c7MEL7xxjOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPP
+OCwGJgl6cvf6UDL4wpPTaaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rl
+mGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXTcrA/vGp97Eh/jcOrqnErU2lBUzS1sLnF
+BgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc/Qzpf14Dl847ABSHJ3A4
+qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMBAAGjgZcw
+gZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIB
+BjAPBgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwu
+bmV0c29sc3NsLmNvbS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3Jp
+dHkuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc8
+6fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q4LqILPxFzBiwmZVRDuwduIj/
+h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/GGUsyfJj4akH
+/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv
+wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHN
+pGxlaKFJdlxDydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey
+-----END CERTIFICATE-----
+
+# Issuer: CN=COMODO ECC Certification Authority O=COMODO CA Limited
+# Subject: CN=COMODO ECC Certification Authority O=COMODO CA Limited
+# Label: "COMODO ECC Certification Authority"
+# Serial: 41578283867086692638256921589707938090
+# MD5 Fingerprint: 7c:62:ff:74:9d:31:53:5e:68:4a:d5:78:aa:1e:bf:23
+# SHA1 Fingerprint: 9f:74:4e:9f:2b:4d:ba:ec:0f:31:2c:50:b6:56:3b:8e:2d:93:c3:11
+# SHA256 Fingerprint: 17:93:92:7a:06:14:54:97:89:ad:ce:2f:8f:34:f7:f0:b6:6d:0f:3a:e3:a3:b8:4d:21:ec:15:db:ba:4f:ad:c7
+-----BEGIN CERTIFICATE-----
+MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTEL
+MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE
+BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMT
+IkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwMzA2MDAw
+MDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdy
+ZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09N
+T0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlv
+biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSR
+FtSrYpn1PlILBs5BAH+X4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0J
+cfRK9ChQtP6IHG4/bC8vCVlbpVsLM5niwz2J+Wos77LTBumjQjBAMB0GA1UdDgQW
+BBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/
+BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VGFAkK+qDm
+fQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdv
+GDeAU/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY=
+-----END CERTIFICATE-----
+
+# Issuer: CN=OISTE WISeKey Global Root GA CA O=WISeKey OU=Copyright (c) 2005/OISTE Foundation Endorsed
+# Subject: CN=OISTE WISeKey Global Root GA CA O=WISeKey OU=Copyright (c) 2005/OISTE Foundation Endorsed
+# Label: "OISTE WISeKey Global Root GA CA"
+# Serial: 86718877871133159090080555911823548314
+# MD5 Fingerprint: bc:6c:51:33:a7:e9:d3:66:63:54:15:72:1b:21:92:93
+# SHA1 Fingerprint: 59:22:a1:e1:5a:ea:16:35:21:f8:98:39:6a:46:46:b0:44:1b:0f:a9
+# SHA256 Fingerprint: 41:c9:23:86:6a:b4:ca:d6:b7:ad:57:80:81:58:2e:02:07:97:a6:cb:df:4f:ff:78:ce:83:96:b3:89:37:d7:f5
+-----BEGIN CERTIFICATE-----
+MIID8TCCAtmgAwIBAgIQQT1yx/RrH4FDffHSKFTfmjANBgkqhkiG9w0BAQUFADCB
+ijELMAkGA1UEBhMCQ0gxEDAOBgNVBAoTB1dJU2VLZXkxGzAZBgNVBAsTEkNvcHly
+aWdodCAoYykgMjAwNTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNl
+ZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQSBDQTAeFw0w
+NTEyMTExNjAzNDRaFw0zNzEyMTExNjA5NTFaMIGKMQswCQYDVQQGEwJDSDEQMA4G
+A1UEChMHV0lTZUtleTEbMBkGA1UECxMSQ29weXJpZ2h0IChjKSAyMDA1MSIwIAYD
+VQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBX
+SVNlS2V5IEdsb2JhbCBSb290IEdBIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEAy0+zAJs9Nt350UlqaxBJH+zYK7LG+DKBKUOVTJoZIyEVRd7jyBxR
+VVuuk+g3/ytr6dTqvirdqFEr12bDYVxgAsj1znJ7O7jyTmUIms2kahnBAbtzptf2
+w93NvKSLtZlhuAGio9RN1AU9ka34tAhxZK9w8RxrfvbDd50kc3vkDIzh2TbhmYsF
+mQvtRTEJysIA2/dyoJaqlYfQjse2YXMNdmaM3Bu0Y6Kff5MTMPGhJ9vZ/yxViJGg
+4E8HsChWjBgbl0SOid3gF27nKu+POQoxhILYQBRJLnpB5Kf+42TMwVlxSywhp1t9
+4B3RLoGbw9ho972WG6xwsRYUC9tguSYBBQIDAQABo1EwTzALBgNVHQ8EBAMCAYYw
+DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUswN+rja8sHnR3JQmthG+IbJphpQw
+EAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBAEuh/wuHbrP5wUOx
+SPMowB0uyQlB+pQAHKSkq0lPjz0e701vvbyk9vImMMkQyh2I+3QZH4VFvbBsUfk2
+ftv1TDI6QU9bR8/oCy22xBmddMVHxjtqD6wU2zz0c5ypBd8A3HR4+vg1YFkCExh8
+vPtNsCBtQ7tgMHpnM1zFmdH4LTlSc/uMqpclXHLZCB6rTjzjgTGfA6b7wP4piFXa
+hNVQA7bihKOmNqoROgHhGEvWRGizPflTdISzRpFGlgC3gCy24eMQ4tui5yiPAZZi
+Fj4A4xylNoEYokxSdsARo27mHbrjWr42U8U+dY+GaSlYU7Wcu2+fXMUY7N0v4ZjJ
+/L7fCg0=
+-----END CERTIFICATE-----
+
+# Issuer: CN=Certigna O=Dhimyotis
+# Subject: CN=Certigna O=Dhimyotis
+# Label: "Certigna"
+# Serial: 18364802974209362175
+# MD5 Fingerprint: ab:57:a6:5b:7d:42:82:19:b5:d8:58:26:28:5e:fd:ff
+# SHA1 Fingerprint: b1:2e:13:63:45:86:a4:6f:1a:b2:60:68:37:58:2d:c4:ac:fd:94:97
+# SHA256 Fingerprint: e3:b6:a2:db:2e:d7:ce:48:84:2f:7a:c5:32:41:c7:b7:1d:54:14:4b:fb:40:c1:1f:3f:1d:0b:42:f5:ee:a1:2d
+-----BEGIN CERTIFICATE-----
+MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNV
+BAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4X
+DTA3MDYyOTE1MTMwNVoXDTI3MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQ
+BgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwIQ2VydGlnbmEwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7qXOEm7RFHYeGifBZ4
+QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyHGxny
+gQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbw
+zBfsV1/pogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q
+130yGLMLLGq/jj8UEYkgDncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2
+JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKfIrjxwo1p3Po6WAbfAgMBAAGjgbwwgbkw
+DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQtCRZvgHyUtVF9lo53BEw
+ZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJBgNVBAYT
+AkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzj
+AQ/JSP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG
+9w0BAQUFAAOCAQEAhQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8h
+bV6lUmPOEvjvKtpv6zf+EwLHyzs+ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFnc
+fca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1kluPBS1xp81HlDQwY9qcEQCYsuu
+HWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY1gkIl2PlwS6w
+t0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw
+WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg==
+-----END CERTIFICATE-----
+
+# Issuer: CN=Deutsche Telekom Root CA 2 O=Deutsche Telekom AG OU=T-TeleSec Trust Center
+# Subject: CN=Deutsche Telekom Root CA 2 O=Deutsche Telekom AG OU=T-TeleSec Trust Center
+# Label: "Deutsche Telekom Root CA 2"
+# Serial: 38
+# MD5 Fingerprint: 74:01:4a:91:b1:08:c4:58:ce:47:cd:f0:dd:11:53:08
+# SHA1 Fingerprint: 85:a4:08:c0:9c:19:3e:5d:51:58:7d:cd:d6:13:30:fd:8c:de:37:bf
+# SHA256 Fingerprint: b6:19:1a:50:d0:c3:97:7f:7d:a9:9b:cd:aa:c8:6a:22:7d:ae:b9:67:9e:c7:0b:a3:b0:c9:d9:22:71:c1:70:d3
+-----BEGIN CERTIFICATE-----
+MIIDnzCCAoegAwIBAgIBJjANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJERTEc
+MBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxlU2Vj
+IFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290IENB
+IDIwHhcNOTkwNzA5MTIxMTAwWhcNMTkwNzA5MjM1OTAwWjBxMQswCQYDVQQGEwJE
+RTEcMBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxl
+U2VjIFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290
+IENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrC6M14IspFLEU
+ha88EOQ5bzVdSq7d6mGNlUn0b2SjGmBmpKlAIoTZ1KXleJMOaAGtuU1cOs7TuKhC
+QN/Po7qCWWqSG6wcmtoIKyUn+WkjR/Hg6yx6m/UTAtB+NHzCnjwAWav12gz1Mjwr
+rFDa1sPeg5TKqAyZMg4ISFZbavva4VhYAUlfckE8FQYBjl2tqriTtM2e66foai1S
+NNs671x1Udrb8zH57nGYMsRUFUQM+ZtV7a3fGAigo4aKSe5TBY8ZTNXeWHmb0moc
+QqvF1afPaA+W5OFhmHZhyJF81j4A4pFQh+GdCuatl9Idxjp9y7zaAzTVjlsB9WoH
+txa2bkp/AgMBAAGjQjBAMB0GA1UdDgQWBBQxw3kbuvVT1xfgiXotF2wKsyudMzAP
+BgNVHRMECDAGAQH/AgEFMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOC
+AQEAlGRZrTlk5ynrE/5aw4sTV8gEJPB0d8Bg42f76Ymmg7+Wgnxu1MM9756Abrsp
+tJh6sTtU6zkXR34ajgv8HzFZMQSyzhfzLMdiNlXiItiJVbSYSKpk+tYcNthEeFpa
+IzpXl/V6ME+un2pMSyuOoAPjPuCp1NJ70rOo4nI8rZ7/gFnkm0W09juwzTkZmDLl
+6iFhkOQxIY40sfcvNUqFENrnijchvllj4PKFiDFT1FQUhXB59C4Gdyd1Lx+4ivn+
+xbrYNuSD7Odlt79jWvNGr4GUN9RBjNYj1h7P9WgbRGOiWrqnNVmh5XAFmw4jV5mU
+Cm26OWMohpLzGITY+9HPBVZkVw==
+-----END CERTIFICATE-----
+
+# Issuer: CN=Cybertrust Global Root O=Cybertrust, Inc
+# Subject: CN=Cybertrust Global Root O=Cybertrust, Inc
+# Label: "Cybertrust Global Root"
+# Serial: 4835703278459682877484360
+# MD5 Fingerprint: 72:e4:4a:87:e3:69:40:80:77:ea:bc:e3:f4:ff:f0:e1
+# SHA1 Fingerprint: 5f:43:e5:b1:bf:f8:78:8c:ac:1c:c7:ca:4a:9a:c6:22:2b:cc:34:c6
+# SHA256 Fingerprint: 96:0a:df:00:63:e9:63:56:75:0c:29:65:dd:0a:08:67:da:0b:9c:bd:6e:77:71:4a:ea:fb:23:49:ab:39:3d:a3
+-----BEGIN CERTIFICATE-----
+MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYG
+A1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2Jh
+bCBSb290MB4XDTA2MTIxNTA4MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UE
+ChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBS
+b290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+Mi8vRRQZhP/8NN5
+7CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW0ozS
+J8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2y
+HLtgwEZLAfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iP
+t3sMpTjr3kfb1V05/Iin89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNz
+FtApD0mpSPCzqrdsxacwOUBdrsTiXSZT8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAY
+XSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/
+MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2MDSgMqAw
+hi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3Js
+MB8GA1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUA
+A4IBAQBW7wojoFROlZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMj
+Wqd8BfP9IjsO0QbE2zZMcwSO5bAi5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUx
+XOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2hO0j9n0Hq0V+09+zv+mKts2o
+omcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+TX3EJIrduPuoc
+A06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW
+WL1WMRJOEcgh4LMRkWXbtKaIOM5V
+-----END CERTIFICATE-----
+
+# Issuer: O=Chunghwa Telecom Co., Ltd. OU=ePKI Root Certification Authority
+# Subject: O=Chunghwa Telecom Co., Ltd. OU=ePKI Root Certification Authority
+# Label: "ePKI Root Certification Authority"
+# Serial: 28956088682735189655030529057352760477
+# MD5 Fingerprint: 1b:2e:00:ca:26:06:90:3d:ad:fe:6f:15:68:d3:6b:b3
+# SHA1 Fingerprint: 67:65:0d:f1:7e:8e:7e:5b:82:40:a4:f4:56:4b:cf:e2:3d:69:c6:f0
+# SHA256 Fingerprint: c0:a6:f4:dc:63:a2:4b:fd:cf:54:ef:2a:6a:08:2a:0a:72:de:35:80:3e:2f:f5:ff:52:7a:e5:d8:72:06:df:d5
+-----BEGIN CERTIFICATE-----
+MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBe
+MQswCQYDVQQGEwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0
+ZC4xKjAoBgNVBAsMIWVQS0kgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe
+Fw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMxMjdaMF4xCzAJBgNVBAYTAlRXMSMw
+IQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEqMCgGA1UECwwhZVBL
+SSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEF
+AAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAH
+SyZbCUNsIZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAh
+ijHyl3SJCRImHJ7K2RKilTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3X
+DZoTM1PRYfl61dd4s5oz9wCGzh1NlDivqOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1
+TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX12ruOzjjK9SXDrkb5wdJ
+fzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0OWQqraffA
+sgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uU
+WH1+ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLS
+nT0IFaUQAS2zMnaolQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pH
+dmX2Os+PYhcZewoozRrSgx4hxyy/vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJip
+NiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXiZo1jDiVN1Rmy5nk3pyKdVDEC
+AwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/QkqiMAwGA1UdEwQF
+MAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH
+ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGB
+uvl2ICO1J2B01GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6Yl
+PwZpVnPDimZI+ymBV3QGypzqKOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkP
+JXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdVxrsStZf0X4OFunHB2WyBEXYKCrC/
+gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEPNXubrjlpC2JgQCA2
+j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+rGNm6
+5ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUB
+o2M3IUxExJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS
+/jQ6fbjpKdx2qcgw+BRxgMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2z
+Gp1iro2C6pSe3VkQw63d4k3jMdXH7OjysP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTE
+W9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmODBCEIZ43ygknQW/2xzQ+D
+hNQ+IIX3Sj0rnP0qCglN6oH4EZw=
+-----END CERTIFICATE-----
+
+# Issuer: O=certSIGN OU=certSIGN ROOT CA
+# Subject: O=certSIGN OU=certSIGN ROOT CA
+# Label: "certSIGN ROOT CA"
+# Serial: 35210227249154
+# MD5 Fingerprint: 18:98:c0:d6:e9:3a:fc:f9:b0:f5:0c:f7:4b:01:44:17
+# SHA1 Fingerprint: fa:b7:ee:36:97:26:62:fb:2d:b0:2a:f6:bf:03:fd:e8:7c:4b:2f:9b
+# SHA256 Fingerprint: ea:a9:62:c4:fa:4a:6b:af:eb:e4:15:19:6d:35:1c:cd:88:8d:4f:53:f3:fa:8a:e6:d7:c4:66:a9:4e:60:42:bb
+-----BEGIN CERTIFICATE-----
+MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYT
+AlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBD
+QTAeFw0wNjA3MDQxNzIwMDRaFw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJP
+MREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTCC
+ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7IJUqOtdu0KBuqV5Do
+0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHHrfAQ
+UySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5d
+RdY4zTW2ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQ
+OA7+j0xbm0bqQfWwCHTD0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwv
+JoIQ4uNllAoEwF73XVv4EOLQunpL+943AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08C
+AwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAcYwHQYDVR0O
+BBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IBAQA+0hyJ
+LjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecY
+MnQ8SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ
+44gx+FkagQnIl6Z0x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6I
+Jd1hJyMctTEHBDa0GpC9oHRxUIltvBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNw
+i/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7NzTogVZ96edhBiIL5VaZVDADlN
+9u6wWk5JRFRYX0KD
+-----END CERTIFICATE-----
+
+# Issuer: CN=GeoTrust Primary Certification Authority - G3 O=GeoTrust Inc. OU=(c) 2008 GeoTrust Inc. - For authorized use only
+# Subject: CN=GeoTrust Primary Certification Authority - G3 O=GeoTrust Inc. OU=(c) 2008 GeoTrust Inc. - For authorized use only
+# Label: "GeoTrust Primary Certification Authority - G3"
+# Serial: 28809105769928564313984085209975885599
+# MD5 Fingerprint: b5:e8:34:36:c9:10:44:58:48:70:6d:2e:83:d4:b8:05
+# SHA1 Fingerprint: 03:9e:ed:b8:0b:e7:a0:3c:69:53:89:3b:20:d2:d9:32:3a:4c:2a:fd
+# SHA256 Fingerprint: b4:78:b8:12:25:0d:f8:78:63:5c:2a:a7:ec:7d:15:5e:aa:62:5e:e8:29:16:e2:cd:29:43:61:88:6c:d1:fb:d4
+-----BEGIN CERTIFICATE-----
+MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCB
+mDELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsT
+MChjKSAyMDA4IEdlb1RydXN0IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25s
+eTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhv
+cml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIzNTk1OVowgZgxCzAJ
+BgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg
+MjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0
+BgNVBAMTLUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg
+LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz
++uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5jK/BGvESyiaHAKAxJcCGVn2TAppMSAmUm
+hsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdEc5IiaacDiGydY8hS2pgn
+5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3CIShwiP/W
+JmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exAL
+DmKudlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZC
+huOl1UcCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw
+HQYDVR0OBBYEFMR5yo6hTgMdHNxr2zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IB
+AQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9cr5HqQ6XErhK8WTTOd8lNNTB
+zU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbEAp7aDHdlDkQN
+kv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD
+AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUH
+SJsMC8tJP33st/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2G
+spki4cErx5z481+oghLrGREt
+-----END CERTIFICATE-----
+
+# Issuer: CN=thawte Primary Root CA - G2 O=thawte, Inc. OU=(c) 2007 thawte, Inc. - For authorized use only
+# Subject: CN=thawte Primary Root CA - G2 O=thawte, Inc. OU=(c) 2007 thawte, Inc. - For authorized use only
+# Label: "thawte Primary Root CA - G2"
+# Serial: 71758320672825410020661621085256472406
+# MD5 Fingerprint: 74:9d:ea:60:24:c4:fd:22:53:3e:cc:3a:72:d9:29:4f
+# SHA1 Fingerprint: aa:db:bc:22:23:8f:c4:01:a1:27:bb:38:dd:f4:1d:db:08:9e:f0:12
+# SHA256 Fingerprint: a4:31:0d:50:af:18:a6:44:71:90:37:2a:86:af:af:8b:95:1f:fb:43:1d:83:7f:1e:56:88:b4:59:71:ed:15:57
+-----BEGIN CERTIFICATE-----
+MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDEL
+MAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMp
+IDIwMDcgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAi
+BgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMjAeFw0wNzExMDUwMDAw
+MDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh
+d3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBGb3Ig
+YXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9v
+dCBDQSAtIEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/
+BebfowJPDQfGAFG6DAJSLSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6
+papu+7qzcMBniKI11KOasf2twu8x+qi58/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8E
+BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUmtgAMADna3+FGO6Lts6K
+DPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUNG4k8VIZ3
+KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41ox
+XZ3Krr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg==
+-----END CERTIFICATE-----
+
+# Issuer: CN=thawte Primary Root CA - G3 O=thawte, Inc. OU=Certification Services Division/(c) 2008 thawte, Inc. - For authorized use only
+# Subject: CN=thawte Primary Root CA - G3 O=thawte, Inc. OU=Certification Services Division/(c) 2008 thawte, Inc. - For authorized use only
+# Label: "thawte Primary Root CA - G3"
+# Serial: 127614157056681299805556476275995414779
+# MD5 Fingerprint: fb:1b:5d:43:8a:94:cd:44:c6:76:f2:43:4b:47:e7:31
+# SHA1 Fingerprint: f1:8b:53:8d:1b:e9:03:b6:a6:f0:56:43:5b:17:15:89:ca:f3:6b:f2
+# SHA256 Fingerprint: 4b:03:f4:58:07:ad:70:f2:1b:fc:2c:ae:71:c9:fd:e4:60:4c:06:4c:f5:ff:b6:86:ba:e5:db:aa:d7:fd:d3:4c
+-----BEGIN CERTIFICATE-----
+MIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCB
+rjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf
+Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw
+MDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNV
+BAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0wODA0MDIwMDAwMDBa
+Fw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhhd3Rl
+LCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9u
+MTgwNgYDVQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXpl
+ZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEcz
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsr8nLPvb2FvdeHsbnndm
+gcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2AtP0LMqmsywCPLLEHd5N/8
+YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC+BsUa0Lf
+b1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS9
+9irY7CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2S
+zhkGcuYMXDhpxwTWvGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUk
+OQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNV
+HQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJKoZIhvcNAQELBQADggEBABpA
+2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweKA3rD6z8KLFIW
+oCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1bu
+t8jLZ8HJnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7c
+KUGRIjxpp7sC8rZcJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fM
+m7v/OeZWYdMKp8RcTGB7BXcmer/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZu
+MdRAGmI0Nj81Aa6sY6A=
+-----END CERTIFICATE-----
+
+# Issuer: CN=GeoTrust Primary Certification Authority - G2 O=GeoTrust Inc. OU=(c) 2007 GeoTrust Inc. - For authorized use only
+# Subject: CN=GeoTrust Primary Certification Authority - G2 O=GeoTrust Inc. OU=(c) 2007 GeoTrust Inc. - For authorized use only
+# Label: "GeoTrust Primary Certification Authority - G2"
+# Serial: 80682863203381065782177908751794619243
+# MD5 Fingerprint: 01:5e:d8:6b:bd:6f:3d:8e:a1:31:f8:12:e0:98:73:6a
+# SHA1 Fingerprint: 8d:17:84:d5:37:f3:03:7d:ec:70:fe:57:8b:51:9a:99:e6:10:d7:b0
+# SHA256 Fingerprint: 5e:db:7a:c4:3b:82:a0:6a:87:61:e8:d7:be:49:79:eb:f2:61:1f:7d:d7:9b:f9:1c:1c:6b:56:6a:21:9e:d7:66
+-----BEGIN CERTIFICATE-----
+MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDEL
+MAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChj
+KSAyMDA3IEdlb1RydXN0IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2
+MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0
+eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1OVowgZgxCzAJBgNV
+BAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykgMjAw
+NyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNV
+BAMTLUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBH
+MjB2MBAGByqGSM49AgEGBSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcL
+So17VDs6bl8VAsBQps8lL33KSLjHUGMcKiEIfJo22Av+0SbFWDEwKCXzXV2juLal
+tJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO
+BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+EVXVMAoG
+CCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGT
+qQ7mndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBucz
+rD6ogRLQy7rQkgu2npaqBA+K
+-----END CERTIFICATE-----
+
+# Issuer: CN=VeriSign Universal Root Certification Authority O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2008 VeriSign, Inc. - For authorized use only
+# Subject: CN=VeriSign Universal Root Certification Authority O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2008 VeriSign, Inc. - For authorized use only
+# Label: "VeriSign Universal Root Certification Authority"
+# Serial: 85209574734084581917763752644031726877
+# MD5 Fingerprint: 8e:ad:b5:01:aa:4d:81:e4:8c:1d:d1:e1:14:00:95:19
+# SHA1 Fingerprint: 36:79:ca:35:66:87:72:30:4d:30:a5:fb:87:3b:0f:a7:7b:b7:0d:54
+# SHA256 Fingerprint: 23:99:56:11:27:a5:71:25:de:8c:ef:ea:61:0d:df:2f:a0:78:b5:c8:06:7f:4e:82:82:90:bf:b8:60:e8:4b:3c
+-----BEGIN CERTIFICATE-----
+MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCB
+vTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL
+ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJp
+U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MTgwNgYDVQQDEy9W
+ZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe
+Fw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJVUzEX
+MBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0
+IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9y
+IGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNh
+bCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF
+AAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj1mCOkdeQmIN65lgZOIzF
+9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGPMiJhgsWH
+H26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+H
+LL729fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN
+/BMReYTtXlT2NJ8IAfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPT
+rJ9VAMf2CGqUuV/c4DPxhGD5WycRtPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1Ud
+EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0GCCsGAQUFBwEMBGEwX6FdoFsw
+WTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2Oa8PPgGrUSBgs
+exkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud
+DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4
+sAPmLGd75JR3Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+
+seQxIcaBlVZaDrHC1LGmWazxY8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz
+4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTxP/jgdFcrGJ2BtMQo2pSXpXDrrB2+
+BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+PwGZsY6rp2aQW9IHR
+lRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4mJO3
+7M2CYfE45k+XmCpajQ==
+-----END CERTIFICATE-----
+
+# Issuer: CN=VeriSign Class 3 Public Primary Certification Authority - G4 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2007 VeriSign, Inc. - For authorized use only
+# Subject: CN=VeriSign Class 3 Public Primary Certification Authority - G4 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2007 VeriSign, Inc. - For authorized use only
+# Label: "VeriSign Class 3 Public Primary Certification Authority - G4"
+# Serial: 63143484348153506665311985501458640051
+# MD5 Fingerprint: 3a:52:e1:e7:fd:6f:3a:e3:6f:f3:6f:99:1b:f9:22:41
+# SHA1 Fingerprint: 22:d5:d8:df:8f:02:31:d1:8d:f7:9d:b7:cf:8a:2d:64:c9:3f:6c:3a
+# SHA256 Fingerprint: 69:dd:d7:ea:90:bb:57:c9:3e:13:5d:c8:5e:a6:fc:d5:48:0b:60:32:39:bd:c4:54:fc:75:8b:2a:26:cf:7f:79
+-----BEGIN CERTIFICATE-----
+MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjEL
+MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW
+ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2ln
+biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp
+U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y
+aXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjELMAkG
+A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJp
+U2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwg
+SW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2ln
+biBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5
+IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8Utpkmw4tXNherJI9/gHm
+GUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGzrl0Bp3ve
+fLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUw
+AwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJ
+aW1hZ2UvZ2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYj
+aHR0cDovL2xvZ28udmVyaXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMW
+kf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMDA2gAMGUCMGYhDBgmYFo4e1ZC
+4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIxAJw9SDkjOVga
+FRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA==
+-----END CERTIFICATE-----
+
+# Issuer: CN=NetLock Arany (Class Gold) Főtanúsítvány O=NetLock Kft. OU=Tanúsítványkiadók (Certification Services)
+# Subject: CN=NetLock Arany (Class Gold) Főtanúsítvány O=NetLock Kft. OU=Tanúsítványkiadók (Certification Services)
+# Label: "NetLock Arany (Class Gold) Főtanúsítvány"
+# Serial: 80544274841616
+# MD5 Fingerprint: c5:a1:b7:ff:73:dd:d6:d7:34:32:18:df:fc:3c:ad:88
+# SHA1 Fingerprint: 06:08:3f:59:3f:15:a1:04:a0:69:a4:6b:a9:03:d0:06:b7:97:09:91
+# SHA256 Fingerprint: 6c:61:da:c3:a2:de:f0:31:50:6b:e0:36:d2:a6:fe:40:19:94:fb:d1:3d:f9:c8:d4:66:59:92:74:c4:46:ec:98
+-----BEGIN CERTIFICATE-----
+MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQG
+EwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3
+MDUGA1UECwwuVGFuw7pzw610dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNl
+cnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBBcmFueSAoQ2xhc3MgR29sZCkgRsWR
+dGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgxMjA2MTUwODIxWjCB
+pzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxOZXRM
+b2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlm
+aWNhdGlvbiBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNz
+IEdvbGQpIEbFkXRhbsO6c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEAxCRec75LbRTDofTjl5Bu0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrT
+lF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw/HpYzY6b7cNGbIRwXdrz
+AZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAkH3B5r9s5
+VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRG
+ILdwfzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2
+BJtr+UBdADTHLpl1neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAG
+AQH/AgEEMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2M
+U9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwWqZw8UQCgwBEIBaeZ5m8BiFRh
+bvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTtaYtOUZcTh5m2C
++C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC
+bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2F
+uLjbvrW5KfnaNwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2
+XjG4Kvte9nHfRCaexOYNkbQudZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E=
+-----END CERTIFICATE-----
+
+# Issuer: CN=Staat der Nederlanden Root CA - G2 O=Staat der Nederlanden
+# Subject: CN=Staat der Nederlanden Root CA - G2 O=Staat der Nederlanden
+# Label: "Staat der Nederlanden Root CA - G2"
+# Serial: 10000012
+# MD5 Fingerprint: 7c:a5:0f:f8:5b:9a:7d:6d:30:ae:54:5a:e3:42:a2:8a
+# SHA1 Fingerprint: 59:af:82:79:91:86:c7:b4:75:07:cb:cf:03:57:46:eb:04:dd:b7:16
+# SHA256 Fingerprint: 66:8c:83:94:7d:a6:3b:72:4b:ec:e1:74:3c:31:a0:e6:ae:d0:db:8e:c5:b3:1b:e3:77:bb:78:4f:91:b6:71:6f
+-----BEGIN CERTIFICATE-----
+MIIFyjCCA7KgAwIBAgIEAJiWjDANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJO
+TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFh
+dCBkZXIgTmVkZXJsYW5kZW4gUm9vdCBDQSAtIEcyMB4XDTA4MDMyNjExMTgxN1oX
+DTIwMDMyNTExMDMxMFowWjELMAkGA1UEBhMCTkwxHjAcBgNVBAoMFVN0YWF0IGRl
+ciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5lZGVybGFuZGVuIFJv
+b3QgQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMVZ5291
+qj5LnLW4rJ4L5PnZyqtdj7U5EILXr1HgO+EASGrP2uEGQxGZqhQlEq0i6ABtQ8Sp
+uOUfiUtnvWFI7/3S4GCI5bkYYCjDdyutsDeqN95kWSpGV+RLufg3fNU254DBtvPU
+Z5uW6M7XxgpT0GtJlvOjCwV3SPcl5XCsMBQgJeN/dVrlSPhOewMHBPqCYYdu8DvE
+pMfQ9XQ+pV0aCPKbJdL2rAQmPlU6Yiile7Iwr/g3wtG61jj99O9JMDeZJiFIhQGp
+5Rbn3JBV3w/oOM2ZNyFPXfUib2rFEhZgF1XyZWampzCROME4HYYEhLoaJXhena/M
+UGDWE4dS7WMfbWV9whUYdMrhfmQpjHLYFhN9C0lK8SgbIHRrxT3dsKpICT0ugpTN
+GmXZK4iambwYfp/ufWZ8Pr2UuIHOzZgweMFvZ9C+X+Bo7d7iscksWXiSqt8rYGPy
+5V6548r6f1CGPqI0GAwJaCgRHOThuVw+R7oyPxjMW4T182t0xHJ04eOLoEq9jWYv
+6q012iDTiIJh8BIitrzQ1aTsr1SIJSQ8p22xcik/Plemf1WvbibG/ufMQFxRRIEK
+eN5KzlW/HdXZt1bv8Hb/C3m1r737qWmRRpdogBQ2HbN/uymYNqUg+oJgYjOk7Na6
+B6duxc8UpufWkjTYgfX8HV2qXB72o007uPc5AgMBAAGjgZcwgZQwDwYDVR0TAQH/
+BAUwAwEB/zBSBgNVHSAESzBJMEcGBFUdIAAwPzA9BggrBgEFBQcCARYxaHR0cDov
+L3d3dy5wa2lvdmVyaGVpZC5ubC9wb2xpY2llcy9yb290LXBvbGljeS1HMjAOBgNV
+HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJFoMocVHYnitfGsNig0jQt8YojrMA0GCSqG
+SIb3DQEBCwUAA4ICAQCoQUpnKpKBglBu4dfYszk78wIVCVBR7y29JHuIhjv5tLyS
+CZa59sCrI2AGeYwRTlHSeYAz+51IvuxBQ4EffkdAHOV6CMqqi3WtFMTC6GY8ggen
+5ieCWxjmD27ZUD6KQhgpxrRW/FYQoAUXvQwjf/ST7ZwaUb7dRUG/kSS0H4zpX897
+IZmflZ85OkYcbPnNe5yQzSipx6lVu6xiNGI1E0sUOlWDuYaNkqbG9AclVMwWVxJK
+gnjIFNkXgiYtXSAfea7+1HAWFpWD2DU5/1JddRwWxRNVz0fMdWVSSt7wsKfkCpYL
++63C4iWEst3kvX5ZbJvw8NjnyvLplzh+ib7M+zkXYT9y2zqR2GUBGR2tUKRXCnxL
+vJxxcypFURmFzI79R6d0lR2o0a9OF7FpJsKqeFdbxU2n5Z4FF5TKsl+gSRiNNOkm
+bEgeqmiSBeGCc1qb3AdbCG19ndeNIdn8FCCqwkXfP+cAslHkwvgFuXkajDTznlvk
+N1trSt8sV4pAWja63XVECDdCcAz+3F4hoKOKwJCcaNpQ5kUQR3i2TtJlycM33+FC
+Y7BXN0Ute4qcvwXqZVUz9zkQxSgqIXobisQk+T8VyJoVIPVVYpbtbZNQvOSqeK3Z
+ywplh6ZmwcSBo3c6WB4L7oOLnR7SUqTMHW+wmG2UMbX4cQrcufx9MmDm66+KAQ==
+-----END CERTIFICATE-----
+
+# Issuer: CN=Hongkong Post Root CA 1 O=Hongkong Post
+# Subject: CN=Hongkong Post Root CA 1 O=Hongkong Post
+# Label: "Hongkong Post Root CA 1"
+# Serial: 1000
+# MD5 Fingerprint: a8:0d:6f:39:78:b9:43:6d:77:42:6d:98:5a:cc:23:ca
+# SHA1 Fingerprint: d6:da:a8:20:8d:09:d2:15:4d:24:b5:2f:cb:34:6e:b2:58:b2:8a:58
+# SHA256 Fingerprint: f9:e6:7d:33:6c:51:00:2a:c0:54:c6:32:02:2d:66:dd:a2:e7:e3:ff:f1:0a:d0:61:ed:31:d8:bb:b4:10:cf:b2
+-----BEGIN CERTIFICATE-----
+MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsx
+FjAUBgNVBAoTDUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3Qg
+Um9vdCBDQSAxMB4XDTAzMDUxNTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkG
+A1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdr
+b25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
+AQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1ApzQ
+jVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEn
+PzlTCeqrauh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjh
+ZY4bXSNmO7ilMlHIhqqhqZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9
+nnV0ttgCXjqQesBCNnLsak3c78QA3xMYV18meMjWCnl3v/evt3a5pQuEF10Q6m/h
+q5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNVHRMBAf8ECDAGAQH/AgED
+MA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7ih9legYsC
+mEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI3
+7piol7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clB
+oiMBdDhViw+5LmeiIAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJs
+EhTkYY2sEJCehFC78JZvRZ+K88psT/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpO
+fMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilTc4afU9hDDl3WY4JxHYB0yvbi
+AmvZWg==
+-----END CERTIFICATE-----
+
+# Issuer: CN=SecureSign RootCA11 O=Japan Certification Services, Inc.
+# Subject: CN=SecureSign RootCA11 O=Japan Certification Services, Inc.
+# Label: "SecureSign RootCA11"
+# Serial: 1
+# MD5 Fingerprint: b7:52:74:e2:92:b4:80:93:f2:75:e4:cc:d7:f2:ea:26
+# SHA1 Fingerprint: 3b:c4:9f:48:f8:f3:73:a0:9c:1e:bd:f8:5b:b1:c3:65:c7:d8:11:b3
+# SHA256 Fingerprint: bf:0f:ee:fb:9e:3a:58:1a:d5:f9:e9:db:75:89:98:57:43:d2:61:08:5c:4d:31:4f:6f:5d:72:59:aa:42:16:12
+-----BEGIN CERTIFICATE-----
+MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDEr
+MCkGA1UEChMiSmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoG
+A1UEAxMTU2VjdXJlU2lnbiBSb290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0
+MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSswKQYDVQQKEyJKYXBhbiBDZXJ0aWZp
+Y2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1cmVTaWduIFJvb3RD
+QTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvLTJsz
+i1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8
+h9uuywGOwvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOV
+MdrAG/LuYpmGYz+/3ZMqg6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9
+UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rPO7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni
+8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitAbpSACW22s293bzUIUPsC
+h8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZXt94wDgYD
+VR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEB
+AKChOBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xm
+KbabfSVSSUOrTC4rbnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQ
+X5Ucv+2rIrVls4W6ng+4reV6G4pQOh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWr
+QbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01y8hSyn+B/tlr0/cR7SXf+Of5
+pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061lgeLKBObjBmN
+QSdJQO7e5iNEOdyhIta6A/I=
+-----END CERTIFICATE-----
+
+# Issuer: CN=Microsec e-Szigno Root CA 2009 O=Microsec Ltd.
+# Subject: CN=Microsec e-Szigno Root CA 2009 O=Microsec Ltd.
+# Label: "Microsec e-Szigno Root CA 2009"
+# Serial: 14014712776195784473
+# MD5 Fingerprint: f8:49:f4:03:bc:44:2d:83:be:48:69:7d:29:64:fc:b1
+# SHA1 Fingerprint: 89:df:74:fe:5c:f4:0f:4a:80:f9:e3:37:7d:54:da:91:e1:01:31:8e
+# SHA256 Fingerprint: 3c:5f:81:fe:a5:fa:b8:2c:64:bf:a2:ea:ec:af:cd:e8:e0:77:fc:86:20:a7:ca:e5:37:16:3d:f3:6e:db:f3:78
+-----BEGIN CERTIFICATE-----
+MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYD
+VQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0
+ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0G
+CSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTAeFw0wOTA2MTYxMTMwMThaFw0y
+OTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3Qx
+FjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3pp
+Z25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o
+dTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvP
+kd6mJviZpWNwrZuuyjNAfW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tc
+cbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG0IMZfcChEhyVbUr02MelTTMuhTlAdX4U
+fIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKApxn1ntxVUwOXewdI/5n7
+N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm1HxdrtbC
+xkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1
++rUCAwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G
+A1UdDgQWBBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPM
+Pcu1SCOhGnqmKrs0aDAbBgNVHREEFDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqG
+SIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0olZMEyL/azXm4Q5DwpL7v8u8h
+mLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfXI/OMn74dseGk
+ddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775
+tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c
+2Pm2G2JwCz02yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5t
+HMN1Rq41Bab2XD0h7lbwyYIiLXpUq3DDfSJlgnCW
+-----END CERTIFICATE-----
+
+# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R3
+# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R3
+# Label: "GlobalSign Root CA - R3"
+# Serial: 4835703278459759426209954
+# MD5 Fingerprint: c5:df:b8:49:ca:05:13:55:ee:2d:ba:1a:c3:3e:b0:28
+# SHA1 Fingerprint: d6:9b:56:11:48:f0:1c:77:c5:45:78:c1:09:26:df:5b:85:69:76:ad
+# SHA256 Fingerprint: cb:b5:22:d7:b7:f1:27:ad:6a:01:13:86:5b:df:1c:d4:10:2e:7d:07:59:af:63:5a:7c:f4:72:0d:c9:63:c5:3b
+-----BEGIN CERTIFICATE-----
+MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G
+A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp
+Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4
+MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG
+A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8
+RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT
+gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm
+KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd
+QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ
+XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw
+DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o
+LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU
+RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp
+jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK
+6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX
+mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs
+Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH
+WD9f
+-----END CERTIFICATE-----
+
+# Issuer: CN=Autoridad de Certificacion Firmaprofesional CIF A62634068
+# Subject: CN=Autoridad de Certificacion Firmaprofesional CIF A62634068
+# Label: "Autoridad de Certificacion Firmaprofesional CIF A62634068"
+# Serial: 6047274297262753887
+# MD5 Fingerprint: 73:3a:74:7a:ec:bb:a3:96:a6:c2:e4:e2:c8:9b:c0:c3
+# SHA1 Fingerprint: ae:c5:fb:3f:c8:e1:bf:c4:e5:4f:03:07:5a:9a:e8:00:b7:f7:b6:fa
+# SHA256 Fingerprint: 04:04:80:28:bf:1f:28:64:d4:8f:9a:d4:d8:32:94:36:6a:82:88:56:55:3f:3b:14:30:3f:90:14:7f:5d:40:ef
+-----BEGIN CERTIFICATE-----
+MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UE
+BhMCRVMxQjBABgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1h
+cHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEy
+MzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUg
+Q2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjgwggIi
+MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDDUtd9
+thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQM
+cas9UX4PB99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefG
+L9ItWY16Ck6WaVICqjaY7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15i
+NA9wBj4gGFrO93IbJWyTdBSTo3OxDqqHECNZXyAFGUftaI6SEspd/NYrspI8IM/h
+X68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyIplD9amML9ZMWGxmPsu2b
+m8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctXMbScyJCy
+Z/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirja
+EbsXLZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/T
+KI8xWVvTyQKmtFLKbpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF
+6NkBiDkal4ZkQdU7hwxu+g/GvUgUvzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVh
+OSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1UdEwEB/wQIMAYBAf8CAQEwDgYD
+VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNHDhpkLzCBpgYD
+VR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp
+cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBv
+ACAAZABlACAAbABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBl
+AGwAbwBuAGEAIAAwADgAMAAxADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF
+661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx51tkljYyGOylMnfX40S2wBEqgLk9
+am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qkR71kMrv2JYSiJ0L1
+ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaPT481
+PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS
+3a/DTg4fJl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5k
+SeTy36LssUzAKh3ntLFlosS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF
+3dvd6qJ2gHN99ZwExEWN57kci57q13XRcrHedUTnQn3iV2t93Jm8PYMo6oCTjcVM
+ZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoRsaS8I8nkvof/uZS2+F0g
+StRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTDKCOM/icz
+Q0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQB
+jLMi6Et8Vcad+qMUu2WFbm5PEn4KPJ2V
+-----END CERTIFICATE-----
+
+# Issuer: CN=Izenpe.com O=IZENPE S.A.
+# Subject: CN=Izenpe.com O=IZENPE S.A.
+# Label: "Izenpe.com"
+# Serial: 917563065490389241595536686991402621
+# MD5 Fingerprint: a6:b0:cd:85:80:da:5c:50:34:a3:39:90:2f:55:67:73
+# SHA1 Fingerprint: 2f:78:3d:25:52:18:a7:4a:65:39:71:b5:2c:a2:9c:45:15:6f:e9:19
+# SHA256 Fingerprint: 25:30:cc:8e:98:32:15:02:ba:d9:6f:9b:1f:ba:1b:09:9e:2d:29:9e:0f:45:48:bb:91:4f:36:3b:c0:d4:53:1f
+-----BEGIN CERTIFICATE-----
+MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4
+MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6
+ZW5wZS5jb20wHhcNMDcxMjEzMTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYD
+VQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5j
+b20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ03rKDx6sp4boFmVq
+scIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAKClaO
+xdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6H
+LmYRY2xU+zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFX
+uaOKmMPsOzTFlUFpfnXCPCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQD
+yCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxTOTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+
+JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbKF7jJeodWLBoBHmy+E60Q
+rLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK0GqfvEyN
+BjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8L
+hij+0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIB
+QFqNeb+Lz0vPqhbBleStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+
+HMh3/1uaD7euBUbl8agW7EekFwIDAQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2lu
+Zm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+SVpFTlBFIFMuQS4gLSBDSUYg
+QTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBGNjIgUzgxQzBB
+BgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx
+MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AQYwHQYDVR0OBBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUA
+A4ICAQB4pgwWSp9MiDrAyw6lFn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWb
+laQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbgakEyrkgPH7UIBzg/YsfqikuFgba56
+awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8qhT/AQKM6WfxZSzwo
+JNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Csg1lw
+LDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCT
+VyvehQP5aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGk
+LhObNA5me0mrZJfQRsN5nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJb
+UjWumDqtujWTI6cfSN01RpiyEGjkpTHCClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/
+QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZoQ0iy2+tzJOeRf1SktoA+
+naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1ZWrOZyGls
+QyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw==
+-----END CERTIFICATE-----
+
+# Issuer: CN=Chambers of Commerce Root - 2008 O=AC Camerfirma S.A.
+# Subject: CN=Chambers of Commerce Root - 2008 O=AC Camerfirma S.A.
+# Label: "Chambers of Commerce Root - 2008"
+# Serial: 11806822484801597146
+# MD5 Fingerprint: 5e:80:9e:84:5a:0e:65:0b:17:02:f3:55:18:2a:3e:d7
+# SHA1 Fingerprint: 78:6a:74:ac:76:ab:14:7f:9c:6a:30:50:ba:9e:a8:7e:fe:9a:ce:3c
+# SHA256 Fingerprint: 06:3e:4a:fa:c4:91:df:d3:32:f3:08:9b:85:42:e9:46:17:d8:93:d7:fe:94:4e:10:a7:93:7e:e2:9d:96:93:c0
+-----BEGIN CERTIFICATE-----
+MIIHTzCCBTegAwIBAgIJAKPaQn6ksa7aMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYD
+VQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0
+IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3
+MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xKTAnBgNVBAMTIENoYW1iZXJz
+IG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4MB4XDTA4MDgwMTEyMjk1MFoXDTM4MDcz
+MTEyMjk1MFowga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNlZSBj
+dXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29tL2FkZHJlc3MpMRIw
+EAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVyZmlybWEgUy5BLjEp
+MCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDgwggIiMA0G
+CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCvAMtwNyuAWko6bHiUfaN/Gh/2NdW9
+28sNRHI+JrKQUrpjOyhYb6WzbZSm891kDFX29ufyIiKAXuFixrYp4YFs8r/lfTJq
+VKAyGVn+H4vXPWCGhSRv4xGzdz4gljUha7MI2XAuZPeEklPWDrCQiorjh40G072Q
+DuKZoRuGDtqaCrsLYVAGUvGef3bsyw/QHg3PmTA9HMRFEFis1tPo1+XqxQEHd9ZR
+5gN/ikilTWh1uem8nk4ZcfUyS5xtYBkL+8ydddy/Js2Pk3g5eXNeJQ7KXOt3EgfL
+ZEFHcpOrUMPrCXZkNNI5t3YRCQ12RcSprj1qr7V9ZS+UWBDsXHyvfuK2GNnQm05a
+Sd+pZgvMPMZ4fKecHePOjlO+Bd5gD2vlGts/4+EhySnB8esHnFIbAURRPHsl18Tl
+UlRdJQfKFiC4reRB7noI/plvg6aRArBsNlVq5331lubKgdaX8ZSD6e2wsWsSaR6s
++12pxZjptFtYer49okQ6Y1nUCyXeG0+95QGezdIp1Z8XGQpvvwyQ0wlf2eOKNcx5
+Wk0ZN5K3xMGtr/R5JJqyAQuxr1yW84Ay+1w9mPGgP0revq+ULtlVmhduYJ1jbLhj
+ya6BXBg14JC7vjxPNyK5fuvPnnchpj04gftI2jE9K+OJ9dC1vX7gUMQSibMjmhAx
+hduub+84Mxh2EQIDAQABo4IBbDCCAWgwEgYDVR0TAQH/BAgwBgEB/wIBDDAdBgNV
+HQ4EFgQU+SSsD7K1+HnA+mCIG8TZTQKeFxkwgeMGA1UdIwSB2zCB2IAU+SSsD7K1
++HnA+mCIG8TZTQKeFxmhgbSkgbEwga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpN
+YWRyaWQgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29t
+L2FkZHJlc3MpMRIwEAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVy
+ZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAt
+IDIwMDiCCQCj2kJ+pLGu2jAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRV
+HSAAMCowKAYIKwYBBQUHAgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20w
+DQYJKoZIhvcNAQEFBQADggIBAJASryI1wqM58C7e6bXpeHxIvj99RZJe6dqxGfwW
+PJ+0W2aeaufDuV2I6A+tzyMP3iU6XsxPpcG1Lawk0lgH3qLPaYRgM+gQDROpI9CF
+5Y57pp49chNyM/WqfcZjHwj0/gF/JM8rLFQJ3uIrbZLGOU8W6jx+ekbURWpGqOt1
+glanq6B8aBMz9p0w8G8nOSQjKpD9kCk18pPfNKXG9/jvjA9iSnyu0/VU+I22mlaH
+FoI6M6taIgj3grrqLuBHmrS1RaMFO9ncLkVAO+rcf+g769HsJtg1pDDFOqxXnrN2
+pSB7+R5KBWIBpih1YJeSDW4+TTdDDZIVnBgizVGZoCkaPF+KMjNbMMeJL0eYD6MD
+xvbxrN8y8NmBGuScvfaAFPDRLLmF9dijscilIeUcE5fuDr3fKanvNFNb0+RqE4QG
+tjICxFKuItLcsiFCGtpA8CnJ7AoMXOLQusxI0zcKzBIKinmwPQN/aUv0NCB9szTq
+jktk9T79syNnFQ0EuPAtwQlRPLJsFfClI9eDdOTlLsn+mCdCxqvGnrDQWzilm1De
+fhiYtUU79nm06PcaewaD+9CL2rvHvRirCG88gGtAPxkZumWK5r7VXNM21+9AUiRg
+OGcEMeyP84LG3rlV8zsxkVrctQgVrXYlCg17LofiDKYGvCYQbTed7N14jHyAxfDZ
+d0jQ
+-----END CERTIFICATE-----
+
+# Issuer: CN=Global Chambersign Root - 2008 O=AC Camerfirma S.A.
+# Subject: CN=Global Chambersign Root - 2008 O=AC Camerfirma S.A.
+# Label: "Global Chambersign Root - 2008"
+# Serial: 14541511773111788494
+# MD5 Fingerprint: 9e:80:ff:78:01:0c:2e:c1:36:bd:fe:96:90:6e:08:f3
+# SHA1 Fingerprint: 4a:bd:ee:ec:95:0d:35:9c:89:ae:c7:52:a1:2c:5b:29:f6:d6:aa:0c
+# SHA256 Fingerprint: 13:63:35:43:93:34:a7:69:80:16:a0:d3:24:de:72:28:4e:07:9d:7b:52:20:bb:8f:bd:74:78:16:ee:be:ba:ca
+-----BEGIN CERTIFICATE-----
+MIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYD
+VQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0
+IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3
+MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBD
+aGFtYmVyc2lnbiBSb290IC0gMjAwODAeFw0wODA4MDExMjMxNDBaFw0zODA3MzEx
+MjMxNDBaMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3Vy
+cmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAG
+A1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAl
+BgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODCCAiIwDQYJKoZI
+hvcNAQEBBQADggIPADCCAgoCggIBAMDfVtPkOpt2RbQT2//BthmLN0EYlVJH6xed
+KYiONWwGMi5HYvNJBL99RDaxccy9Wglz1dmFRP+RVyXfXjaOcNFccUMd2drvXNL7
+G706tcuto8xEpw2uIRU/uXpbknXYpBI4iRmKt4DS4jJvVpyR1ogQC7N0ZJJ0YPP2
+zxhPYLIj0Mc7zmFLmY/CDNBAspjcDahOo7kKrmCgrUVSY7pmvWjg+b4aqIG7HkF4
+ddPB/gBVsIdU6CeQNR1MM62X/JcumIS/LMmjv9GYERTtY/jKmIhYF5ntRQOXfjyG
+HoiMvvKRhI9lNNgATH23MRdaKXoKGCQwoze1eqkBfSbW+Q6OWfH9GzO1KTsXO0G2
+Id3UwD2ln58fQ1DJu7xsepeY7s2MH/ucUa6LcL0nn3HAa6x9kGbo1106DbDVwo3V
+yJ2dwW3Q0L9R5OP4wzg2rtandeavhENdk5IMagfeOx2YItaswTXbo6Al/3K1dh3e
+beksZixShNBFks4c5eUzHdwHU1SjqoI7mjcv3N2gZOnm3b2u/GSFHTynyQbehP9r
+6GsaPMWis0L7iwk+XwhSx2LE1AVxv8Rk5Pihg+g+EpuoHtQ2TS9x9o0o9oOpE9Jh
+wZG7SMA0j0GMS0zbaRL/UJScIINZc+18ofLx/d33SdNDWKBWY8o9PeU1VlnpDsog
+zCtLkykPAgMBAAGjggFqMIIBZjASBgNVHRMBAf8ECDAGAQH/AgEMMB0GA1UdDgQW
+BBS5CcqcHtvTbDprru1U8VuTBjUuXjCB4QYDVR0jBIHZMIHWgBS5CcqcHtvTbDpr
+ru1U8VuTBjUuXqGBsqSBrzCBrDELMAkGA1UEBhMCRVUxQzBBBgNVBAcTOk1hZHJp
+ZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2FtZXJmaXJtYS5jb20vYWRk
+cmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UEChMSQUMgQ2FtZXJmaXJt
+YSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNpZ24gUm9vdCAtIDIwMDiC
+CQDJzdPp1X0jzjAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCow
+KAYIKwYBBQUHAgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZI
+hvcNAQEFBQADggIBAICIf3DekijZBZRG/5BXqfEv3xoNa/p8DhxJJHkn2EaqbylZ
+UohwEurdPfWbU1Rv4WCiqAm57OtZfMY18dwY6fFn5a+6ReAJ3spED8IXDneRRXoz
+X1+WLGiLwUePmJs9wOzL9dWCkoQ10b42OFZyMVtHLaoXpGNR6woBrX/sdZ7LoR/x
+fxKxueRkf2fWIyr0uDldmOghp+G9PUIadJpwr2hsUF1Jz//7Dl3mLEfXgTpZALVz
+a2Mg9jFFCDkO9HB+QHBaP9BrQql0PSgvAm11cpUJjUhjxsYjV5KTXjXBjfkK9yyd
+Yhz2rXzdpjEetrHHfoUm+qRqtdpjMNHvkzeyZi99Bffnt0uYlDXA2TopwZ2yUDMd
+SqlapskD7+3056huirRXhOukP9DuqqqHW2Pok+JrqNS4cnhrG+055F3Lm6qH1U9O
+AP7Zap88MQ8oAgF9mOinsKJknnn4SPIVqczmyETrP3iZ8ntxPjzxmKfFGBI/5rso
+M0LpRQp8bfKGeS/Fghl9CYl8slR2iK7ewfPM4W7bMdaTrpmg7yVqc5iJWzouE4ge
+v8CSlDQb4ye3ix5vQv/n6TebUB0tovkC7stYWDpxvGjjqsGvHCgfotwjZT+B6q6Z
+09gwzxMNTxXJhLynSC34MCN32EZLeW32jO06f2ARePTpm67VVMB0gNELQp/B
+-----END CERTIFICATE-----
+
+# Issuer: CN=Go Daddy Root Certificate Authority - G2 O=GoDaddy.com, Inc.
+# Subject: CN=Go Daddy Root Certificate Authority - G2 O=GoDaddy.com, Inc.
+# Label: "Go Daddy Root Certificate Authority - G2"
+# Serial: 0
+# MD5 Fingerprint: 80:3a:bc:22:c1:e6:fb:8d:9b:3b:27:4a:32:1b:9a:01
+# SHA1 Fingerprint: 47:be:ab:c9:22:ea:e8:0e:78:78:34:62:a7:9f:45:c2:54:fd:e6:8b
+# SHA256 Fingerprint: 45:14:0b:32:47:eb:9c:c8:c5:b4:f0:d7:b5:30:91:f7:32:92:08:9e:6e:5a:63:e2:74:9d:d3:ac:a9:19:8e:da
+-----BEGIN CERTIFICATE-----
+MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx
+EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT
+EUdvRGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRp
+ZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIz
+NTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQH
+EwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8GA1UE
+AxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKD
+E6bFIEMBO4Tx5oVJnyfq9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH
+/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD+qK+ihVqf94Lw7YZFAXK6sOoBJQ7Rnwy
+DfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutdfMh8+7ArU6SSYmlRJQVh
+GkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMlNAJWJwGR
+tDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEA
+AaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE
+FDqahQcQZyi27/a9BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmX
+WWcDYfF+OwYxdS2hII5PZYe096acvNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu
+9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r5N9ss4UXnT3ZJE95kTXWXwTr
+gIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYVN8Gb5DKj7Tjo
+2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO
+LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI
+4uJEvlz36hz1
+-----END CERTIFICATE-----
+
+# Issuer: CN=Starfield Root Certificate Authority - G2 O=Starfield Technologies, Inc.
+# Subject: CN=Starfield Root Certificate Authority - G2 O=Starfield Technologies, Inc.
+# Label: "Starfield Root Certificate Authority - G2"
+# Serial: 0
+# MD5 Fingerprint: d6:39:81:c6:52:7e:96:69:fc:fc:ca:66:ed:05:f2:96
+# SHA1 Fingerprint: b5:1c:06:7c:ee:2b:0c:3d:f8:55:ab:2d:92:f4:fe:39:d4:e7:0f:0e
+# SHA256 Fingerprint: 2c:e1:cb:0b:f9:d2:f9:e1:02:99:3f:be:21:51:52:c3:b2:dd:0c:ab:de:1c:68:e5:31:9b:83:91:54:db:b7:f5
+-----BEGIN CERTIFICATE-----
+MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx
+EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT
+HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVs
+ZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAw
+MFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6
+b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVj
+aG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZp
+Y2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAL3twQP89o/8ArFvW59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMg
+nLRJdzIpVv257IzdIvpy3Cdhl+72WoTsbhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1
+HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNkN3mSwOxGXn/hbVNMYq/N
+Hwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7NfZTD4p7dN
+dloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0
+HZbUJtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO
+BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0G
+CSqGSIb3DQEBCwUAA4IBAQARWfolTwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjU
+sHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx4mcujJUDJi5DnUox9g61DLu3
+4jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUwF5okxBDgBPfg
+8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K
+pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1
+mMpYjn0q7pBZc2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0
+-----END CERTIFICATE-----
+
+# Issuer: CN=Starfield Services Root Certificate Authority - G2 O=Starfield Technologies, Inc.
+# Subject: CN=Starfield Services Root Certificate Authority - G2 O=Starfield Technologies, Inc.
+# Label: "Starfield Services Root Certificate Authority - G2"
+# Serial: 0
+# MD5 Fingerprint: 17:35:74:af:7b:61:1c:eb:f4:f9:3c:e2:ee:40:f9:a2
+# SHA1 Fingerprint: 92:5a:8f:8d:2c:6d:04:e0:66:5f:59:6a:ff:22:d8:63:e8:25:6f:3f
+# SHA256 Fingerprint: 56:8d:69:05:a2:c8:87:08:a4:b3:02:51:90:ed:cf:ed:b1:97:4a:60:6a:13:c6:e5:29:0f:cb:2a:e6:3e:da:b5
+-----BEGIN CERTIFICATE-----
+MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMx
+EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT
+HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVs
+ZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5
+MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNVBAYTAlVTMRAwDgYD
+VQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFy
+ZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2Vy
+dmljZXMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20p
+OsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm2
+8xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4PahHQUw2eeBGg6345AWh1K
+Ts9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLPLJGmpufe
+hRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk
+6mFBrMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAw
+DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+q
+AdcwKziIorhtSpzyEZGDMA0GCSqGSIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMI
+bw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPPE95Dz+I0swSdHynVv/heyNXB
+ve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTyxQGjhdByPq1z
+qwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd
+iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn
+0q23KXB56jzaYyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCN
+sSi6
+-----END CERTIFICATE-----
+
+# Issuer: CN=AffirmTrust Commercial O=AffirmTrust
+# Subject: CN=AffirmTrust Commercial O=AffirmTrust
+# Label: "AffirmTrust Commercial"
+# Serial: 8608355977964138876
+# MD5 Fingerprint: 82:92:ba:5b:ef:cd:8a:6f:a6:3d:55:f9:84:f6:d6:b7
+# SHA1 Fingerprint: f9:b5:b6:32:45:5f:9c:be:ec:57:5f:80:dc:e9:6e:2c:c7:b2:78:b7
+# SHA256 Fingerprint: 03:76:ab:1d:54:c5:f9:80:3c:e4:b2:e2:01:a0:ee:7e:ef:7b:57:b6:36:e8:a9:3c:9b:8d:48:60:c9:6f:5f:a7
+-----BEGIN CERTIFICATE-----
+MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UE
+BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz
+dCBDb21tZXJjaWFsMB4XDTEwMDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDEL
+MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp
+cm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
+AQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6EqdbDuKP
+Hx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yr
+ba0F8PrVC8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPAL
+MeIrJmqbTFeurCA+ukV6BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1
+yHp52UKqK39c/s4mT6NmgTWvRLpUHhwwMmWd5jyTXlBOeuM61G7MGvv50jeuJCqr
+VwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNVHQ4EFgQUnZPGU4teyq8/
+nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ
+KoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYG
+XUPGhi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNj
+vbz4YYCanrHOQnDiqX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivt
+Z8SOyUOyXGsViQK8YvxO8rUzqrJv0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9g
+N53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0khsUlHRUe072o0EclNmsxZt9YC
+nlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8=
+-----END CERTIFICATE-----
+
+# Issuer: CN=AffirmTrust Networking O=AffirmTrust
+# Subject: CN=AffirmTrust Networking O=AffirmTrust
+# Label: "AffirmTrust Networking"
+# Serial: 8957382827206547757
+# MD5 Fingerprint: 42:65:ca:be:01:9a:9a:4c:a9:8c:41:49:cd:c0:d5:7f
+# SHA1 Fingerprint: 29:36:21:02:8b:20:ed:02:f5:66:c5:32:d1:d6:ed:90:9f:45:00:2f
+# SHA256 Fingerprint: 0a:81:ec:5a:92:97:77:f1:45:90:4a:f3:8d:5d:50:9f:66:b5:e2:c5:8f:cd:b5:31:05:8b:0e:17:f3:f0:b4:1b
+-----BEGIN CERTIFICATE-----
+MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UE
+BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz
+dCBOZXR3b3JraW5nMB4XDTEwMDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDEL
+MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp
+cm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
+AQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SEHi3y
+YJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbua
+kCNrmreIdIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRL
+QESxG9fhwoXA3hA/Pe24/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp
+6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gbh+0t+nvujArjqWaJGctB+d1ENmHP4ndG
+yH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNVHQ4EFgQUBx/S55zawm6i
+QLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ
+KoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfO
+tDIuUFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzu
+QY0x2+c06lkh1QF612S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZ
+Lgo/bNjR9eUJtGxUAArgFU2HdW23WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4u
+olu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9/ZFvgrG+CJPbFEfxojfHRZ48
+x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s=
+-----END CERTIFICATE-----
+
+# Issuer: CN=AffirmTrust Premium O=AffirmTrust
+# Subject: CN=AffirmTrust Premium O=AffirmTrust
+# Label: "AffirmTrust Premium"
+# Serial: 7893706540734352110
+# MD5 Fingerprint: c4:5d:0e:48:b6:ac:28:30:4e:0a:bc:f9:38:16:87:57
+# SHA1 Fingerprint: d8:a6:33:2c:e0:03:6f:b1:85:f6:63:4f:7d:6a:06:65:26:32:28:27
+# SHA256 Fingerprint: 70:a7:3f:7f:37:6b:60:07:42:48:90:45:34:b1:14:82:d5:bf:0e:69:8e:cc:49:8d:f5:25:77:eb:f2:e9:3b:9a
+-----BEGIN CERTIFICATE-----
+MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UE
+BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVz
+dCBQcmVtaXVtMB4XDTEwMDEyOTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkG
+A1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1U
+cnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxBLf
+qV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtnBKAQ
+JG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ
++jjeRFcV5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrS
+s8PhaJyJ+HoAVt70VZVs+7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5
+HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmdGPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d7
+70O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5Rp9EixAqnOEhss/n/fauG
+V+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NIS+LI+H+S
+qHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S
+5u046uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4Ia
+C1nEWTJ3s7xgaVY5/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TX
+OwF0lkLgAOIua+rF7nKsu7/+6qqo+Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYE
+FJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/
+BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByvMiPIs0laUZx2
+KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg
+Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B
+8OWycvpEgjNC6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQ
+MKSOyARiqcTtNd56l+0OOF6SL5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc
+0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK+4w1IX2COPKpVJEZNZOUbWo6xbLQ
+u4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmVBtWVyuEklut89pMF
+u+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFgIxpH
+YoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8
+GKa1qF60g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaO
+RtGdFNrHF+QFlozEJLUbzxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6e
+KeC2uAloGRwYQw==
+-----END CERTIFICATE-----
+
+# Issuer: CN=AffirmTrust Premium ECC O=AffirmTrust
+# Subject: CN=AffirmTrust Premium ECC O=AffirmTrust
+# Label: "AffirmTrust Premium ECC"
+# Serial: 8401224907861490260
+# MD5 Fingerprint: 64:b0:09:55:cf:b1:d5:99:e2:be:13:ab:a6:5d:ea:4d
+# SHA1 Fingerprint: b8:23:6b:00:2f:1d:16:86:53:01:55:6c:11:a4:37:ca:eb:ff:c3:bb
+# SHA256 Fingerprint: bd:71:fd:f6:da:97:e4:cf:62:d1:64:7a:dd:25:81:b0:7d:79:ad:f8:39:7e:b4:ec:ba:9c:5e:84:88:82:14:23
+-----BEGIN CERTIFICATE-----
+MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMC
+VVMxFDASBgNVBAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQ
+cmVtaXVtIEVDQzAeFw0xMDAxMjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJ
+BgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEgMB4GA1UEAwwXQWZmaXJt
+VHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQNMF4bFZ0D
+0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQN8O9
+ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0G
+A1UdDgQWBBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4G
+A1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/Vs
+aobgxCd05DhT1wV/GzTjxi+zygk8N53X57hG8f2h4nECMEJZh0PUUd+60wkyWs6I
+flc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKMeQ==
+-----END CERTIFICATE-----
+
+# Issuer: CN=Certum Trusted Network CA O=Unizeto Technologies S.A. OU=Certum Certification Authority
+# Subject: CN=Certum Trusted Network CA O=Unizeto Technologies S.A. OU=Certum Certification Authority
+# Label: "Certum Trusted Network CA"
+# Serial: 279744
+# MD5 Fingerprint: d5:e9:81:40:c5:18:69:fc:46:2c:89:75:62:0f:aa:78
+# SHA1 Fingerprint: 07:e0:32:e0:20:b7:2c:3f:19:2f:06:28:a2:59:3a:19:a7:0f:06:9e
+# SHA256 Fingerprint: 5c:58:46:8d:55:f5:8e:49:7e:74:39:82:d2:b5:00:10:b6:d1:65:37:4a:cf:83:a7:d4:a3:2d:b7:68:c4:40:8e
+-----BEGIN CERTIFICATE-----
+MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBM
+MSIwIAYDVQQKExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5D
+ZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBU
+cnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIyMTIwNzM3WhcNMjkxMjMxMTIwNzM3
+WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMg
+Uy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MSIw
+IAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rH
+UV+rpDKmYYe2bg+G0jACl/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LM
+TXPb865Px1bVWqeWifrzq2jUI4ZZJ88JJ7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVU
+BBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4fOQtf/WsX+sWn7Et0brM
+kUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0cvW0QM8x
+AcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNV
+HRMBAf8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNV
+HQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15y
+sHhE49wcrwn9I0j6vSrEuVUEtRCjjSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfL
+I9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1mS1FhIrlQgnXdAIv94nYmem8
+J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5ajZt3hrvJBW8qY
+VoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI
+03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw=
+-----END CERTIFICATE-----
+
+# Issuer: CN=TWCA Root Certification Authority O=TAIWAN-CA OU=Root CA
+# Subject: CN=TWCA Root Certification Authority O=TAIWAN-CA OU=Root CA
+# Label: "TWCA Root Certification Authority"
+# Serial: 1
+# MD5 Fingerprint: aa:08:8f:f6:f9:7b:b7:f2:b1:a7:1e:9b:ea:ea:bd:79
+# SHA1 Fingerprint: cf:9e:87:6d:d3:eb:fc:42:26:97:a3:b5:a3:7a:a0:76:a9:06:23:48
+# SHA256 Fingerprint: bf:d8:8f:e1:10:1c:41:ae:3e:80:1b:f8:be:56:35:0e:e9:ba:d1:a6:b9:bd:51:5e:dc:5c:6d:5b:87:11:ac:44
+-----BEGIN CERTIFICATE-----
+MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzES
+MBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFU
+V0NBIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMz
+WhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJVEFJV0FO
+LUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlm
+aWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
+AQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFE
+AcK0HMMxQhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HH
+K3XLfJ+utdGdIzdjp9xCoi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeX
+RfwZVzsrb+RH9JlF/h3x+JejiB03HFyP4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/z
+rX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1ry+UPizgN7gr8/g+YnzAx
+3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
+HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkq
+hkiG9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeC
+MErJk/9q56YAf4lCmtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdls
+XebQ79NqZp4VKIV66IIArB6nCWlWQtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62D
+lhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVYT0bf+215WfKEIlKuD8z7fDvn
+aspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocnyYh0igzyXxfkZ
+YiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw==
+-----END CERTIFICATE-----
+
+# Issuer: O=SECOM Trust Systems CO.,LTD. OU=Security Communication RootCA2
+# Subject: O=SECOM Trust Systems CO.,LTD. OU=Security Communication RootCA2
+# Label: "Security Communication RootCA2"
+# Serial: 0
+# MD5 Fingerprint: 6c:39:7d:a4:0e:55:59:b2:3f:d6:41:b1:12:50:de:43
+# SHA1 Fingerprint: 5f:3b:8c:f2:f8:10:b3:7d:78:b4:ce:ec:19:19:c3:73:34:b9:c7:74
+# SHA256 Fingerprint: 51:3b:2c:ec:b8:10:d4:cd:e5:dd:85:39:1a:df:c6:c2:dd:60:d8:7b:b7:36:d2:b5:21:48:4a:a4:7a:0e:be:f6
+-----BEGIN CERTIFICATE-----
+MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDEl
+MCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMe
+U2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoX
+DTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRy
+dXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3VyaXR5IENvbW11bmlj
+YXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANAV
+OVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGr
+zbl+dp+++T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVM
+VAX3NuRFg3sUZdbcDE3R3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQ
+hNBqyjoGADdH5H5XTz+L62e4iKrFvlNVspHEfbmwhRkGeC7bYRr6hfVKkaHnFtWO
+ojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1KEOtOghY6rCcMU/Gt1SSw
+awNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8QIH4D5cs
+OPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3
+DQEBCwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpF
+coJxDjrSzG+ntKEju/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXc
+okgfGT+Ok+vx+hfuzU7jBBJV1uXk3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8
+t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6qtnRGEmyR7jTV7JqR50S+kDFy
+1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29mvVXIwAHIRc/
+SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03
+-----END CERTIFICATE-----
+
+# Issuer: CN=EC-ACC O=Agencia Catalana de Certificacio (NIF Q-0801176-I) OU=Serveis Publics de Certificacio/Vegeu https://www.catcert.net/verarrel (c)03/Jerarquia Entitats de Certificacio Catalanes
+# Subject: CN=EC-ACC O=Agencia Catalana de Certificacio (NIF Q-0801176-I) OU=Serveis Publics de Certificacio/Vegeu https://www.catcert.net/verarrel (c)03/Jerarquia Entitats de Certificacio Catalanes
+# Label: "EC-ACC"
+# Serial: -23701579247955709139626555126524820479
+# MD5 Fingerprint: eb:f5:9d:29:0d:61:f9:42:1f:7c:c2:ba:6d:e3:15:09
+# SHA1 Fingerprint: 28:90:3a:63:5b:52:80:fa:e6:77:4c:0b:6d:a7:d6:ba:a6:4a:f2:e8
+# SHA256 Fingerprint: 88:49:7f:01:60:2f:31:54:24:6a:e2:8c:4d:5a:ef:10:f1:d8:7e:bb:76:62:6f:4a:e0:b7:f9:5b:a7:96:87:99
+-----BEGIN CERTIFICATE-----
+MIIFVjCCBD6gAwIBAgIQ7is969Qh3hSoYqwE893EATANBgkqhkiG9w0BAQUFADCB
+8zELMAkGA1UEBhMCRVMxOzA5BgNVBAoTMkFnZW5jaWEgQ2F0YWxhbmEgZGUgQ2Vy
+dGlmaWNhY2lvIChOSUYgUS0wODAxMTc2LUkpMSgwJgYDVQQLEx9TZXJ2ZWlzIFB1
+YmxpY3MgZGUgQ2VydGlmaWNhY2lvMTUwMwYDVQQLEyxWZWdldSBodHRwczovL3d3
+dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAoYykwMzE1MDMGA1UECxMsSmVyYXJxdWlh
+IEVudGl0YXRzIGRlIENlcnRpZmljYWNpbyBDYXRhbGFuZXMxDzANBgNVBAMTBkVD
+LUFDQzAeFw0wMzAxMDcyMzAwMDBaFw0zMTAxMDcyMjU5NTlaMIHzMQswCQYDVQQG
+EwJFUzE7MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8g
+KE5JRiBRLTA4MDExNzYtSSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBD
+ZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZlZ2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQu
+bmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJhcnF1aWEgRW50aXRhdHMg
+ZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUNDMIIBIjAN
+BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsyLHT+KXQpWIR4NA9h0X84NzJB5R
+85iKw5K4/0CQBXCHYMkAqbWUZRkiFRfCQ2xmRJoNBD45b6VLeqpjt4pEndljkYRm
+4CgPukLjbo73FCeTae6RDqNfDrHrZqJyTxIThmV6PttPB/SnCWDaOkKZx7J/sxaV
+HMf5NLWUhdWZXqBIoH7nF2W4onW4HvPlQn2v7fOKSGRdghST2MDk/7NQcvJ29rNd
+QlB50JQ+awwAvthrDk4q7D7SzIKiGGUzE3eeml0aE9jD2z3Il3rucO2n5nzbcc8t
+lGLfbdb1OL4/pYUKGbio2Al1QnDE6u/LDsg0qBIimAy4E5S2S+zw0JDnJwIDAQAB
+o4HjMIHgMB0GA1UdEQQWMBSBEmVjX2FjY0BjYXRjZXJ0Lm5ldDAPBgNVHRMBAf8E
+BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUoMOLRKo3pUW/l4Ba0fF4
+opvpXY0wfwYDVR0gBHgwdjB0BgsrBgEEAfV4AQMBCjBlMCwGCCsGAQUFBwIBFiBo
+dHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbDA1BggrBgEFBQcCAjApGidW
+ZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAwDQYJKoZIhvcN
+AQEFBQADggEBAKBIW4IB9k1IuDlVNZyAelOZ1Vr/sXE7zDkJlF7W2u++AVtd0x7Y
+/X1PzaBB4DSTv8vihpw3kpBWHNzrKQXlxJ7HNd+KDM3FIUPpqojlNcAZQmNaAl6k
+SBg6hW/cnbw/nZzBh7h6YQjpdwt/cKt63dmXLGQehb+8dJahw3oS7AwaboMMPOhy
+Rp/7SNVel+axofjk70YllJyJ22k4vuxcDlbHZVHlUIiIv0LVKz3l+bqeLrPK9HOS
+Agu+TGbrIP65y7WZf+a2E/rKS03Z7lNGBjvGTq2TWoF+bCpLagVFjPIhpDGQh2xl
+nJ2lYJU6Un/10asIbvPuW/mIPX64b24D5EI=
+-----END CERTIFICATE-----
+
+# Issuer: CN=Hellenic Academic and Research Institutions RootCA 2011 O=Hellenic Academic and Research Institutions Cert. Authority
+# Subject: CN=Hellenic Academic and Research Institutions RootCA 2011 O=Hellenic Academic and Research Institutions Cert. Authority
+# Label: "Hellenic Academic and Research Institutions RootCA 2011"
+# Serial: 0
+# MD5 Fingerprint: 73:9f:4c:4b:73:5b:79:e9:fa:ba:1c:ef:6e:cb:d5:c9
+# SHA1 Fingerprint: fe:45:65:9b:79:03:5b:98:a1:61:b5:51:2e:ac:da:58:09:48:22:4d
+# SHA256 Fingerprint: bc:10:4f:15:a4:8b:e7:09:dc:a5:42:a7:e1:d4:b9:df:6f:05:45:27:e8:02:ea:a9:2d:59:54:44:25:8a:fe:71
+-----BEGIN CERTIFICATE-----
+MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1Ix
+RDBCBgNVBAoTO0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1
+dGlvbnMgQ2VydC4gQXV0aG9yaXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1p
+YyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIFJvb3RDQSAyMDExMB4XDTExMTIw
+NjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYTAkdSMUQwQgYDVQQK
+EztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIENl
+cnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl
+c2VhcmNoIEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEB
+BQADggEPADCCAQoCggEBAKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPz
+dYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJ
+fel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa71HFK9+WXesyHgLacEns
+bgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u8yBRQlqD
+75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSP
+FEDH3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNV
+HRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp
+5dgTBCPuQSUwRwYDVR0eBEAwPqA8MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQu
+b3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQub3JnMA0GCSqGSIb3DQEBBQUA
+A4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVtXdMiKahsog2p
+6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8
+TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7
+dIsXRSZMFpGD/md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8Acys
+Nnq/onN694/BtZqhFLKPM58N7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXI
+l7WdmplNsDz4SgCbZN2fOUvRJ9e4
+-----END CERTIFICATE-----
+
+# Issuer: CN=Actalis Authentication Root CA O=Actalis S.p.A./03358520967
+# Subject: CN=Actalis Authentication Root CA O=Actalis S.p.A./03358520967
+# Label: "Actalis Authentication Root CA"
+# Serial: 6271844772424770508
+# MD5 Fingerprint: 69:c1:0d:4f:07:a3:1b:c3:fe:56:3d:04:bc:11:f6:a6
+# SHA1 Fingerprint: f3:73:b3:87:06:5a:28:84:8a:f2:f3:4a:ce:19:2b:dd:c7:8e:9c:ac
+# SHA256 Fingerprint: 55:92:60:84:ec:96:3a:64:b9:6e:2a:be:01:ce:0b:a8:6a:64:fb:fe:bc:c7:aa:b5:af:c1:55:b3:7f:d7:60:66
+-----BEGIN CERTIFICATE-----
+MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UE
+BhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8w
+MzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290
+IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDkyMjExMjIwMlowazELMAkGA1UEBhMC
+SVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1
+ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENB
+MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNv
+UTufClrJwkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX
+4ay8IMKx4INRimlNAJZaby/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9
+KK3giq0itFZljoZUj5NDKd45RnijMCO6zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/
+gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1fYVEiVRvjRuPjPdA1Yprb
+rxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2oxgkg4YQ
+51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2F
+be8lEfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxe
+KF+w6D9Fz8+vm2/7hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4F
+v6MGn8i1zeQf1xcGDXqVdFUNaBr8EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbn
+fpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5jF66CyCU3nuDuP/jVo23Eek7
+jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLYiDrIn3hm7Ynz
+ezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt
+ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQAL
+e3KHwGCmSUyIWOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70
+jsNjLiNmsGe+b7bAEzlgqqI0JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDz
+WochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKxK3JCaKygvU5a2hi/a5iB0P2avl4V
+SM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+Xlff1ANATIGk0k9j
+pwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC4yyX
+X04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+Ok
+fcvHlXHo2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7R
+K4X9p2jIugErsWx0Hbhzlefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btU
+ZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXemOR/qnuOf0GZvBeyqdn6/axag67XH/JJU
+LysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9vwGYT7JZVEc+NHt4bVaT
+LnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg==
+-----END CERTIFICATE-----
+
+# Issuer: O=Trustis Limited OU=Trustis FPS Root CA
+# Subject: O=Trustis Limited OU=Trustis FPS Root CA
+# Label: "Trustis FPS Root CA"
+# Serial: 36053640375399034304724988975563710553
+# MD5 Fingerprint: 30:c9:e7:1e:6b:e6:14:eb:65:b2:16:69:20:31:67:4d
+# SHA1 Fingerprint: 3b:c0:38:0b:33:c3:f6:a6:0c:86:15:22:93:d9:df:f5:4b:81:c0:04
+# SHA256 Fingerprint: c1:b4:82:99:ab:a5:20:8f:e9:63:0a:ce:55:ca:68:a0:3e:da:5a:51:9c:88:02:a0:d3:a6:73:be:8f:8e:55:7d
+-----BEGIN CERTIFICATE-----
+MIIDZzCCAk+gAwIBAgIQGx+ttiD5JNM2a/fH8YygWTANBgkqhkiG9w0BAQUFADBF
+MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPVHJ1c3RpcyBMaW1pdGVkMRwwGgYDVQQL
+ExNUcnVzdGlzIEZQUyBSb290IENBMB4XDTAzMTIyMzEyMTQwNloXDTI0MDEyMTEx
+MzY1NFowRTELMAkGA1UEBhMCR0IxGDAWBgNVBAoTD1RydXN0aXMgTGltaXRlZDEc
+MBoGA1UECxMTVHJ1c3RpcyBGUFMgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQAD
+ggEPADCCAQoCggEBAMVQe547NdDfxIzNjpvto8A2mfRC6qc+gIMPpqdZh8mQRUN+
+AOqGeSoDvT03mYlmt+WKVoaTnGhLaASMk5MCPjDSNzoiYYkchU59j9WvezX2fihH
+iTHcDnlkH5nSW7r+f2C/revnPDgpai/lkQtV/+xvWNUtyd5MZnGPDNcE2gfmHhjj
+vSkCqPoc4Vu5g6hBSLwacY3nYuUtsuvffM/bq1rKMfFMIvMFE/eC+XN5DL7XSxzA
+0RU8k0Fk0ea+IxciAIleH2ulrG6nS4zto3Lmr2NNL4XSFDWaLk6M6jKYKIahkQlB
+OrTh4/L68MkKokHdqeMDx4gVOxzUGpTXn2RZEm0CAwEAAaNTMFEwDwYDVR0TAQH/
+BAUwAwEB/zAfBgNVHSMEGDAWgBS6+nEleYtXQSUhhgtx67JkDoshZzAdBgNVHQ4E
+FgQUuvpxJXmLV0ElIYYLceuyZA6LIWcwDQYJKoZIhvcNAQEFBQADggEBAH5Y//01
+GX2cGE+esCu8jowU/yyg2kdbw++BLa8F6nRIW/M+TgfHbcWzk88iNVy2P3UnXwmW
+zaD+vkAMXBJV+JOCyinpXj9WV4s4NvdFGkwozZ5BuO1WTISkQMi4sKUraXAEasP4
+1BIy+Q7DsdwyhEQsb8tGD+pmQQ9P8Vilpg0ND2HepZ5dfWWhPBfnqFVO76DH7cZE
+f1T1o+CP8HxVIo8ptoGj4W1OLBuAZ+ytIJ8MYmHVl/9D7S3B2l0pKoU/rGXuhg8F
+jZBf3+6f9L/uHfuY5H+QK4R4EA5sSVPvFVtlRkpdr7r7OnIdzfYliB6XzCGcKQEN
+ZetX2fNXlrtIzYE=
+-----END CERTIFICATE-----
+
+# Issuer: CN=Buypass Class 2 Root CA O=Buypass AS-983163327
+# Subject: CN=Buypass Class 2 Root CA O=Buypass AS-983163327
+# Label: "Buypass Class 2 Root CA"
+# Serial: 2
+# MD5 Fingerprint: 46:a7:d2:fe:45:fb:64:5a:a8:59:90:9b:78:44:9b:29
+# SHA1 Fingerprint: 49:0a:75:74:de:87:0a:47:fe:58:ee:f6:c7:6b:eb:c6:0b:12:40:99
+# SHA256 Fingerprint: 9a:11:40:25:19:7c:5b:b9:5d:94:e6:3d:55:cd:43:79:08:47:b6:46:b2:3c:df:11:ad:a4:a0:0e:ff:15:fb:48
+-----BEGIN CERTIFICATE-----
+MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd
+MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg
+Q2xhc3MgMiBSb290IENBMB4XDTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1ow
+TjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAw
+HgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEB
+BQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1g1Lr
+6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPV
+L4O2fuPn9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC91
+1K2GScuVr1QGbNgGE41b/+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHx
+MlAQTn/0hpPshNOOvEu/XAFOBz3cFIqUCqTqc/sLUegTBxj6DvEr0VQVfTzh97QZ
+QmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeffawrbD02TTqigzXsu8lkB
+arcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgIzRFo1clr
+Us3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLi
+FRhnBkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRS
+P/TizPJhk9H9Z2vXUq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN
+9SG9dKpN6nIDSdvHXx1iY8f93ZHsM+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxP
+AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMmAd+BikoL1Rpzz
+uvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAU18h
+9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s
+A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3t
+OluwlN5E40EIosHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo
++fsicdl9sz1Gv7SEr5AcD48Saq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7
+KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYdDnkM/crqJIByw5c/8nerQyIKx+u2
+DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWDLfJ6v9r9jv6ly0Us
+H8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0oyLQ
+I+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK7
+5t98biGCwWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h
+3PFaTWwyI0PurKju7koSCTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPz
+Y11aWOIv4x3kqdbQCtCev9eBCfHJxyYNrJgWVqA=
+-----END CERTIFICATE-----
+
+# Issuer: CN=Buypass Class 3 Root CA O=Buypass AS-983163327
+# Subject: CN=Buypass Class 3 Root CA O=Buypass AS-983163327
+# Label: "Buypass Class 3 Root CA"
+# Serial: 2
+# MD5 Fingerprint: 3d:3b:18:9e:2c:64:5a:e8:d5:88:ce:0e:f9:37:c2:ec
+# SHA1 Fingerprint: da:fa:f7:fa:66:84:ec:06:8f:14:50:bd:c7:c2:81:a5:bc:a9:64:57
+# SHA256 Fingerprint: ed:f7:eb:bc:a2:7a:2a:38:4d:38:7b:7d:40:10:c6:66:e2:ed:b4:84:3e:4c:29:b4:ae:1d:5b:93:32:e6:b2:4d
+-----BEGIN CERTIFICATE-----
+MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd
+MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg
+Q2xhc3MgMyBSb290IENBMB4XDTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFow
+TjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAw
+HgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEB
+BQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRHsJ8Y
+ZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3E
+N3coTRiR5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9
+tznDDgFHmV0ST9tD+leh7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX
+0DJq1l1sDPGzbjniazEuOQAnFN44wOwZZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c
+/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH2xc519woe2v1n/MuwU8X
+KhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV/afmiSTY
+zIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvS
+O1UQRwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D
+34xFMFbG02SrZvPAXpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgP
+K9Dx2hzLabjKSWJtyNBjYt1gD1iqj6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3
+AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFEe4zf/lb+74suwv
+Tg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAACAj
+QTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV
+cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXS
+IGrs/CIBKM+GuIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2
+HJLw5QY33KbmkJs4j1xrG0aGQ0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsa
+O5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8ZORK15FTAaggiG6cX0S5y2CBNOxv
+033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2KSb12tjE8nVhz36u
+dmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz6MkE
+kbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg41
+3OEMXbugUZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvD
+u79leNKGef9JOxqDDPDeeOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq
+4/g7u9xN12TyUb7mqqta6THuBrxzvxNiCp/HuZc=
+-----END CERTIFICATE-----
+
+# Issuer: CN=T-TeleSec GlobalRoot Class 3 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center
+# Subject: CN=T-TeleSec GlobalRoot Class 3 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center
+# Label: "T-TeleSec GlobalRoot Class 3"
+# Serial: 1
+# MD5 Fingerprint: ca:fb:40:a8:4e:39:92:8a:1d:fe:8e:2f:c4:27:ea:ef
+# SHA1 Fingerprint: 55:a6:72:3e:cb:f2:ec:cd:c3:23:74:70:19:9d:2a:be:11:e3:81:d1
+# SHA256 Fingerprint: fd:73:da:d3:1c:64:4f:f1:b4:3b:ef:0c:cd:da:96:71:0b:9c:d9:87:5e:ca:7e:31:70:7a:f3:e9:6d:52:2b:bd
+-----BEGIN CERTIFICATE-----
+MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUx
+KzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAd
+BgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNl
+YyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgxMDAxMTAyOTU2WhcNMzMxMDAxMjM1
+OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnBy
+aXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50
+ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN
+8ELg63iIVl6bmlQdTQyK9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/
+RLyTPWGrTs0NvvAgJ1gORH8EGoel15YUNpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4
+hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZFiP0Zf3WHHx+xGwpzJFu5
+ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W0eDrXltM
+EnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGj
+QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1
+A/d2O2GCahKqGFPrAyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOy
+WL6ukK2YJ5f+AbGwUgC4TeQbIXQbfsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ
+1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzTucpH9sry9uetuUg/vBa3wW30
+6gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7hP0HHRwA11fXT
+91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml
+e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4p
+TpPDpFQUWw==
+-----END CERTIFICATE-----
+
+# Issuer: CN=EE Certification Centre Root CA O=AS Sertifitseerimiskeskus
+# Subject: CN=EE Certification Centre Root CA O=AS Sertifitseerimiskeskus
+# Label: "EE Certification Centre Root CA"
+# Serial: 112324828676200291871926431888494945866
+# MD5 Fingerprint: 43:5e:88:d4:7d:1a:4a:7e:fd:84:2e:52:eb:01:d4:6f
+# SHA1 Fingerprint: c9:a8:b9:e7:55:80:5e:58:e3:53:77:a7:25:eb:af:c3:7b:27:cc:d7
+# SHA256 Fingerprint: 3e:84:ba:43:42:90:85:16:e7:75:73:c0:99:2f:09:79:ca:08:4e:46:85:68:1f:f1:95:cc:ba:8a:22:9b:8a:76
+-----BEGIN CERTIFICATE-----
+MIIEAzCCAuugAwIBAgIQVID5oHPtPwBMyonY43HmSjANBgkqhkiG9w0BAQUFADB1
+MQswCQYDVQQGEwJFRTEiMCAGA1UECgwZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1
+czEoMCYGA1UEAwwfRUUgQ2VydGlmaWNhdGlvbiBDZW50cmUgUm9vdCBDQTEYMBYG
+CSqGSIb3DQEJARYJcGtpQHNrLmVlMCIYDzIwMTAxMDMwMTAxMDMwWhgPMjAzMDEy
+MTcyMzU5NTlaMHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlBUyBTZXJ0aWZpdHNl
+ZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRyZSBS
+b290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWUwggEiMA0GCSqGSIb3DQEB
+AQUAA4IBDwAwggEKAoIBAQDIIMDs4MVLqwd4lfNE7vsLDP90jmG7sWLqI9iroWUy
+euuOF0+W2Ap7kaJjbMeMTC55v6kF/GlclY1i+blw7cNRfdCT5mzrMEvhvH2/UpvO
+bntl8jixwKIy72KyaOBhU8E2lf/slLo2rpwcpzIP5Xy0xm90/XsY6KxX7QYgSzIw
+WFv9zajmofxwvI6Sc9uXp3whrj3B9UiHbCe9nyV0gVWw93X2PaRka9ZP585ArQ/d
+MtO8ihJTmMmJ+xAdTX7Nfh9WDSFwhfYggx/2uh8Ej+p3iDXE/+pOoYtNP2MbRMNE
+1CV2yreN1x5KZmTNXMWcg+HCCIia7E6j8T4cLNlsHaFLAgMBAAGjgYowgYcwDwYD
+VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBLyWj7qVhy/
+zQas8fElyalL1BSZMEUGA1UdJQQ+MDwGCCsGAQUFBwMCBggrBgEFBQcDAQYIKwYB
+BQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYIKwYBBQUHAwkwDQYJKoZIhvcNAQEF
+BQADggEBAHv25MANqhlHt01Xo/6tu7Fq1Q+e2+RjxY6hUFaTlrg4wCQiZrxTFGGV
+v9DHKpY5P30osxBAIWrEr7BSdxjhlthWXePdNl4dp1BUoMUq5KqMlIpPnTX/dqQG
+E5Gion0ARD9V04I8GtVbvFZMIi5GQ4okQC3zErg7cBqklrkar4dBGmoYDQZPxz5u
+uSlNDUmJEYcyW+ZLBMjkXOZ0c5RdFpgTlf7727FE5TpwrDdr5rMzcijJs1eg9gIW
+iAYLtqZLICjU3j2LrTcFU3T+bsy8QxdxXvnFzBqpYe73dgzzcvRyrc9yAjYHR8/v
+GVCJYMzpJJUPwssd8m92kMfMdcGWxZ0=
+-----END CERTIFICATE-----
+
+# Issuer: CN=D-TRUST Root Class 3 CA 2 2009 O=D-Trust GmbH
+# Subject: CN=D-TRUST Root Class 3 CA 2 2009 O=D-Trust GmbH
+# Label: "D-TRUST Root Class 3 CA 2 2009"
+# Serial: 623603
+# MD5 Fingerprint: cd:e0:25:69:8d:47:ac:9c:89:35:90:f7:fd:51:3d:2f
+# SHA1 Fingerprint: 58:e8:ab:b0:36:15:33:fb:80:f7:9b:1b:6d:29:d3:ff:8d:5f:00:f0
+# SHA256 Fingerprint: 49:e7:a4:42:ac:f0:ea:62:87:05:00:54:b5:25:64:b6:50:e4:f4:9e:42:e3:48:d6:aa:38:e0:39:e9:57:b1:c1
+-----BEGIN CERTIFICATE-----
+MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRF
+MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBD
+bGFzcyAzIENBIDIgMjAwOTAeFw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NTha
+ME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMM
+HkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIwDQYJKoZIhvcNAQEB
+BQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOADER03
+UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42
+tSHKXzlABF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9R
+ySPocq60vFYJfxLLHLGvKZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsM
+lFqVlNpQmvH/pStmMaTJOKDfHR+4CS7zp+hnUquVH+BGPtikw8paxTGA6Eian5Rp
+/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUCAwEAAaOCARowggEWMA8G
+A1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ4PGEMA4G
+A1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVj
+dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUy
+MENBJTIwMiUyMDIwMDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRl
+cmV2b2NhdGlvbmxpc3QwQ6BBoD+GPWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3Js
+L2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAwOS5jcmwwDQYJKoZIhvcNAQEL
+BQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm2H6NMLVwMeni
+acfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0
+o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4K
+zCUqNQT4YJEVdT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8
+PIWmawomDeCTmGCufsYkl4phX5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3Y
+Johw1+qRzT65ysCQblrGXnRl11z+o+I=
+-----END CERTIFICATE-----
+
+# Issuer: CN=D-TRUST Root Class 3 CA 2 EV 2009 O=D-Trust GmbH
+# Subject: CN=D-TRUST Root Class 3 CA 2 EV 2009 O=D-Trust GmbH
+# Label: "D-TRUST Root Class 3 CA 2 EV 2009"
+# Serial: 623604
+# MD5 Fingerprint: aa:c6:43:2c:5e:2d:cd:c4:34:c0:50:4f:11:02:4f:b6
+# SHA1 Fingerprint: 96:c9:1b:0b:95:b4:10:98:42:fa:d0:d8:22:79:fe:60:fa:b9:16:83
+# SHA256 Fingerprint: ee:c5:49:6b:98:8c:e9:86:25:b9:34:09:2e:ec:29:08:be:d0:b0:f3:16:c2:d4:73:0c:84:ea:f1:f3:d3:48:81
+-----BEGIN CERTIFICATE-----
+MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRF
+MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBD
+bGFzcyAzIENBIDIgRVYgMjAwOTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUw
+NDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNV
+BAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAwOTCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfSegpn
+ljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM0
+3TP1YtHhzRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6Z
+qQTMFexgaDbtCHu39b+T7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lR
+p75mpoo6Kr3HGrHhFPC+Oh25z1uxav60sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8
+HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure3511H3a6UCAwEAAaOCASQw
+ggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyvcop9Ntea
+HNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFw
+Oi8vZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xh
+c3MlMjAzJTIwQ0ElMjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1E
+RT9jZXJ0aWZpY2F0ZXJldm9jYXRpb25saXN0MEagRKBChkBodHRwOi8vd3d3LmQt
+dHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xhc3NfM19jYV8yX2V2XzIwMDku
+Y3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+PPoeUSbrh/Yp
+3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05
+nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNF
+CSuGdXzfX2lXANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7na
+xpeG0ILD5EJt/rDiZE4OJudANCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqX
+KVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVvw9y4AyHqnxbxLFS1
+-----END CERTIFICATE-----
+
+# Issuer: CN=CA Disig Root R2 O=Disig a.s.
+# Subject: CN=CA Disig Root R2 O=Disig a.s.
+# Label: "CA Disig Root R2"
+# Serial: 10572350602393338211
+# MD5 Fingerprint: 26:01:fb:d8:27:a7:17:9a:45:54:38:1a:43:01:3b:03
+# SHA1 Fingerprint: b5:61:eb:ea:a4:de:e4:25:4b:69:1a:98:a5:57:47:c2:34:c7:d9:71
+# SHA256 Fingerprint: e2:3d:4a:03:6d:7b:70:e9:f5:95:b1:42:20:79:d2:b9:1e:df:bb:1f:b6:51:a0:63:3e:aa:8a:9d:c5:f8:07:03
+-----BEGIN CERTIFICATE-----
+MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNV
+BAYTAlNLMRMwEQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMu
+MRkwFwYDVQQDExBDQSBEaXNpZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQy
+MDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sxEzARBgNVBAcTCkJyYXRpc2xhdmEx
+EzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERpc2lnIFJvb3QgUjIw
+ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbCw3Oe
+NcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNH
+PWSb6WiaxswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3I
+x2ymrdMxp7zo5eFm1tL7A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbe
+QTg06ov80egEFGEtQX6sx3dOy1FU+16SGBsEWmjGycT6txOgmLcRK7fWV8x8nhfR
+yyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqVg8NTEQxzHQuyRpDRQjrO
+QG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa5Beny912
+H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJ
+QfYEkoopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUD
+i/ZnWejBBhG93c+AAk9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORs
+nLMOPReisjQS1n6yqEm70XooQL6iFh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1
+rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud
+DwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5uQu0wDQYJKoZI
+hvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM
+tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqf
+GopTpti72TVVsRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkb
+lvdhuDvEK7Z4bLQjb/D907JedR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka
++elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W81k/BfDxujRNt+3vrMNDcTa/F1bal
+TFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjxmHHEt38OFdAlab0i
+nSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01utI3
+gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18Dr
+G5gPcFw0sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3Os
+zMOl6W8KjptlwlCFtaOgUxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8x
+L4ysEr3vQCj8KWefshNPZiTEUxnpHikV7+ZtsH8tZ/3zbBt1RqPlShfppNcL
+-----END CERTIFICATE-----
+
+# Issuer: CN=ACCVRAIZ1 O=ACCV OU=PKIACCV
+# Subject: CN=ACCVRAIZ1 O=ACCV OU=PKIACCV
+# Label: "ACCVRAIZ1"
+# Serial: 6828503384748696800
+# MD5 Fingerprint: d0:a0:5a:ee:05:b6:09:94:21:a1:7d:f1:b2:29:82:02
+# SHA1 Fingerprint: 93:05:7a:88:15:c6:4f:ce:88:2f:fa:91:16:52:28:78:bc:53:64:17
+# SHA256 Fingerprint: 9a:6e:c0:12:e1:a7:da:9d:be:34:19:4d:47:8a:d7:c0:db:18:22:fb:07:1d:f1:29:81:49:6e:d1:04:38:41:13
+-----BEGIN CERTIFICATE-----
+MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UE
+AwwJQUNDVlJBSVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQsw
+CQYDVQQGEwJFUzAeFw0xMTA1MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQ
+BgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwHUEtJQUNDVjENMAsGA1UECgwEQUND
+VjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCb
+qau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gMjmoY
+HtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWo
+G2ioPej0RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpA
+lHPrzg5XPAOBOp0KoVdDaaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhr
+IA8wKFSVf+DuzgpmndFALW4ir50awQUZ0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/
+0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDGWuzndN9wrqODJerWx5eH
+k6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs78yM2x/47
+4KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMO
+m3WR5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpa
+cXpkatcnYGMN285J9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPl
+uUsXQA+xtrn13k/c4LOsOxFwYIRKQ26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYI
+KwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRwOi8vd3d3LmFjY3YuZXMvZmls
+ZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEuY3J0MB8GCCsG
+AQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2
+VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeT
+VfZW6oHlNsyMHj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIG
+CCsGAQUFBwICMIIBFB6CARAAQQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUA
+cgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBhAO0AegAgAGQAZQAgAGwAYQAgAEEA
+QwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUAYwBuAG8AbABvAGcA
+7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBjAHQA
+cgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAA
+QwBQAFMAIABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUA
+czAwBggrBgEFBQcCARYkaHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2Mu
+aHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRt
+aW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2MV9kZXIuY3JsMA4GA1Ud
+DwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZIhvcNAQEF
+BQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdp
+D70ER9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gU
+JyCpZET/LtZ1qmxNYEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+m
+AM/EKXMRNt6GGT6d7hmKG9Ww7Y49nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepD
+vV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJTS+xJlsndQAJxGJ3KQhfnlms
+tn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3sCPdK6jT2iWH
+7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h
+I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szA
+h1xA2syVP1XgNce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xF
+d3+YJ5oyXSrjhO7FmGYvliAd3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2H
+pPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3pEfbRD0tVNEYqi4Y7
+-----END CERTIFICATE-----
+
+# Issuer: CN=TWCA Global Root CA O=TAIWAN-CA OU=Root CA
+# Subject: CN=TWCA Global Root CA O=TAIWAN-CA OU=Root CA
+# Label: "TWCA Global Root CA"
+# Serial: 3262
+# MD5 Fingerprint: f9:03:7e:cf:e6:9e:3c:73:7a:2a:90:07:69:ff:2b:96
+# SHA1 Fingerprint: 9c:bb:48:53:f6:a4:f6:d3:52:a4:e8:32:52:55:60:13:f5:ad:af:65
+# SHA256 Fingerprint: 59:76:90:07:f7:68:5d:0f:cd:50:87:2f:9f:95:d5:75:5a:5b:2b:45:7d:81:f3:69:2b:61:0a:98:67:2f:0e:1b
+-----BEGIN CERTIFICATE-----
+MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcx
+EjAQBgNVBAoTCVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMT
+VFdDQSBHbG9iYWwgUm9vdCBDQTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5
+NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQKEwlUQUlXQU4tQ0ExEDAOBgNVBAsT
+B1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3QgQ0EwggIiMA0GCSqG
+SIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2CnJfF
+10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz
+0ALfUPZVr2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfCh
+MBwqoJimFb3u/Rk28OKRQ4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbH
+zIh1HrtsBv+baz4X7GGqcXzGHaL3SekVtTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc
+46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1WKKD+u4ZqyPpcC1jcxkt2
+yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99sy2sbZCi
+laLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYP
+oA/pyJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQA
+BDzfuBSO6N+pjWxnkjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcE
+qYSjMq+u7msXi7Kx/mzhkIyIqJdIzshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm
+4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
+/zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6gcFGn90xHNcgL
+1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn
+LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WF
+H6vPNOw/KP4M8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNo
+RI2T9GRwoD2dKAXDOXC4Ynsg/eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+
+nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlglPx4mI88k1HtQJAH32RjJMtOcQWh
+15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryPA9gK8kxkRr05YuWW
+6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3mi4TW
+nsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5j
+wa19hAM8EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWz
+aGHQRiapIVJpLesux+t3zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmy
+KwbQBM0=
+-----END CERTIFICATE-----
+
+# Issuer: CN=TeliaSonera Root CA v1 O=TeliaSonera
+# Subject: CN=TeliaSonera Root CA v1 O=TeliaSonera
+# Label: "TeliaSonera Root CA v1"
+# Serial: 199041966741090107964904287217786801558
+# MD5 Fingerprint: 37:41:49:1b:18:56:9a:26:f5:ad:c2:66:fb:40:a5:4c
+# SHA1 Fingerprint: 43:13:bb:96:f1:d5:86:9b:c1:4e:6a:92:f6:cf:f6:34:69:87:82:37
+# SHA256 Fingerprint: dd:69:36:fe:21:f8:f0:77:c1:23:a1:a5:21:c1:22:24:f7:22:55:b7:3e:03:a7:26:06:93:e8:a2:4b:0f:a3:89
+-----BEGIN CERTIFICATE-----
+MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAw
+NzEUMBIGA1UECgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJv
+b3QgQ0EgdjEwHhcNMDcxMDE4MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYD
+VQQKDAtUZWxpYVNvbmVyYTEfMB0GA1UEAwwWVGVsaWFTb25lcmEgUm9vdCBDQSB2
+MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMK+6yfwIaPzaSZVfp3F
+VRaRXP3vIb9TgHot0pGMYzHw7CTww6XScnwQbfQ3t+XmfHnqjLWCi65ItqwA3GV1
+7CpNX8GH9SBlK4GoRz6JI5UwFpB/6FcHSOcZrr9FZ7E3GwYq/t75rH2D+1665I+X
+Z75Ljo1kB1c4VWk0Nj0TSO9P4tNmHqTPGrdeNjPUtAa9GAH9d4RQAEX1jF3oI7x+
+/jXh7VB7qTCNGdMJjmhnXb88lxhTuylixcpecsHHltTbLaC0H2kD7OriUPEMPPCs
+81Mt8Bz17Ww5OXOAFshSsCPN4D7c3TxHoLs1iuKYaIu+5b9y7tL6pe0S7fyYGKkm
+dtwoSxAgHNN/Fnct7W+A90m7UwW7XWjH1Mh1Fj+JWov3F0fUTPHSiXk+TT2YqGHe
+Oh7S+F4D4MHJHIzTjU3TlTazN19jY5szFPAtJmtTfImMMsJu7D0hADnJoWjiUIMu
+sDor8zagrC/kb2HCUQk5PotTubtn2txTuXZZNp1D5SDgPTJghSJRt8czu90VL6R4
+pgd7gUY2BIbdeTXHlSw7sKMXNeVzH7RcWe/a6hBle3rQf5+ztCo3O3CLm1u5K7fs
+slESl1MpWtTwEhDcTwK7EpIvYtQ/aUN8Ddb8WHUBiJ1YFkveupD/RwGJBmr2X7KQ
+arMCpgKIv7NHfirZ1fpoeDVNAgMBAAGjPzA9MA8GA1UdEwEB/wQFMAMBAf8wCwYD
+VR0PBAQDAgEGMB0GA1UdDgQWBBTwj1k4ALP1j5qWDNXr+nuqF+gTEjANBgkqhkiG
+9w0BAQUFAAOCAgEAvuRcYk4k9AwI//DTDGjkk0kiP0Qnb7tt3oNmzqjMDfz1mgbl
+dxSR651Be5kqhOX//CHBXfDkH1e3damhXwIm/9fH907eT/j3HEbAek9ALCI18Bmx
+0GtnLLCo4MBANzX2hFxc469CeP6nyQ1Q6g2EdvZR74NTxnr/DlZJLo961gzmJ1Tj
+TQpgcmLNkQfWpb/ImWvtxBnmq0wROMVvMeJuScg/doAmAyYp4Db29iBT4xdwNBed
+Y2gea+zDTYa4EzAvXUYNR0PVG6pZDrlcjQZIrXSHX8f8MVRBE+LHIQ6e4B4N4cB7
+Q4WQxYpYxmUKeFfyxiMPAdkgS94P+5KFdSpcc41teyWRyu5FrgZLAMzTsVlQ2jqI
+OylDRl6XK1TOU2+NSueW+r9xDkKLfP0ooNBIytrEgUy7onOTJsjrDNYmiLbAJM+7
+vVvrdX3pCI6GMyx5dwlppYn8s3CQh3aP0yK7Qs69cwsgJirQmz1wHiRszYd2qReW
+t88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcn
+HL/EVlP6Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVx
+SK236thZiNSQvxaz2emsWWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY=
+-----END CERTIFICATE-----
+
+# Issuer: CN=E-Tugra Certification Authority O=E-Tuğra EBG Bilişim Teknolojileri ve Hizmetleri A.Ş. OU=E-Tugra Sertifikasyon Merkezi
+# Subject: CN=E-Tugra Certification Authority O=E-Tuğra EBG Bilişim Teknolojileri ve Hizmetleri A.Ş. OU=E-Tugra Sertifikasyon Merkezi
+# Label: "E-Tugra Certification Authority"
+# Serial: 7667447206703254355
+# MD5 Fingerprint: b8:a1:03:63:b0:bd:21:71:70:8a:6f:13:3a:bb:79:49
+# SHA1 Fingerprint: 51:c6:e7:08:49:06:6e:f3:92:d4:5c:a0:0d:6d:a3:62:8f:c3:52:39
+# SHA256 Fingerprint: b0:bf:d5:2b:b0:d7:d9:bd:92:bf:5d:4d:c1:3d:a2:55:c0:2c:54:2f:37:83:65:ea:89:39:11:f5:5e:55:f2:3c
+-----BEGIN CERTIFICATE-----
+MIIGSzCCBDOgAwIBAgIIamg+nFGby1MwDQYJKoZIhvcNAQELBQAwgbIxCzAJBgNV
+BAYTAlRSMQ8wDQYDVQQHDAZBbmthcmExQDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBC
+aWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhpem1ldGxlcmkgQS7Fni4xJjAkBgNV
+BAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBNZXJrZXppMSgwJgYDVQQDDB9FLVR1
+Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTEzMDMwNTEyMDk0OFoXDTIz
+MDMwMzEyMDk0OFowgbIxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmExQDA+
+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhp
+em1ldGxlcmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBN
+ZXJrZXppMSgwJgYDVQQDDB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5
+MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA4vU/kwVRHoViVF56C/UY
+B4Oufq9899SKa6VjQzm5S/fDxmSJPZQuVIBSOTkHS0vdhQd2h8y/L5VMzH2nPbxH
+D5hw+IyFHnSOkm0bQNGZDbt1bsipa5rAhDGvykPL6ys06I+XawGb1Q5KCKpbknSF
+Q9OArqGIW66z6l7LFpp3RMih9lRozt6Plyu6W0ACDGQXwLWTzeHxE2bODHnv0ZEo
+q1+gElIwcxmOj+GMB6LDu0rw6h8VqO4lzKRG+Bsi77MOQ7osJLjFLFzUHPhdZL3D
+k14opz8n8Y4e0ypQBaNV2cvnOVPAmJ6MVGKLJrD3fY185MaeZkJVgkfnsliNZvcH
+fC425lAcP9tDJMW/hkd5s3kc91r0E+xs+D/iWR+V7kI+ua2oMoVJl0b+SzGPWsut
+dEcf6ZG33ygEIqDUD13ieU/qbIWGvaimzuT6w+Gzrt48Ue7LE3wBf4QOXVGUnhMM
+ti6lTPk5cDZvlsouDERVxcr6XQKj39ZkjFqzAQqptQpHF//vkUAqjqFGOjGY5RH8
+zLtJVor8udBhmm9lbObDyz51Sf6Pp+KJxWfXnUYTTjF2OySznhFlhqt/7x3U+Lzn
+rFpct1pHXFXOVbQicVtbC/DP3KBhZOqp12gKY6fgDT+gr9Oq0n7vUaDmUStVkhUX
+U8u3Zg5mTPj5dUyQ5xJwx0UCAwEAAaNjMGEwHQYDVR0OBBYEFC7j27JJ0JxUeVz6
+Jyr+zE7S6E5UMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAULuPbsknQnFR5
+XPonKv7MTtLoTlQwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQAF
+Nzr0TbdF4kV1JI+2d1LoHNgQk2Xz8lkGpD4eKexd0dCrfOAKkEh47U6YA5n+KGCR
+HTAduGN8qOY1tfrTYXbm1gdLymmasoR6d5NFFxWfJNCYExL/u6Au/U5Mh/jOXKqY
+GwXgAEZKgoClM4so3O0409/lPun++1ndYYRP0lSWE2ETPo+Aab6TR7U1Q9Jauz1c
+77NCR807VRMGsAnb/WP2OogKmW9+4c4bU2pEZiNRCHu8W1Ki/QY3OEBhj0qWuJA3
++GbHeJAAFS6LrVE1Uweoa2iu+U48BybNCAVwzDk/dr2l02cmAYamU9JgO3xDf1WK
+vJUawSg5TB9D0pH0clmKuVb8P7Sd2nCcdlqMQ1DujjByTd//SffGqWfZbawCEeI6
+FiWnWAjLb1NBnEg4R2gz0dfHj9R0IdTDBZB6/86WiLEVKV0jq9BgoRJP3vQXzTLl
+yb/IQ639Lo7xr+L0mPoSHyDYwKcMhcWQ9DstliaxLL5Mq+ux0orJ23gTDx4JnW2P
+AJ8C2sH6H3p6CcRK5ogql5+Ji/03X186zjhZhkuvcQu02PJwT58yE+Owp1fl2tpD
+y4Q08ijE6m30Ku/Ba3ba+367hTzSU8JNvnHhRdH9I2cNE3X7z2VnIp2usAnRCf8d
+NL/+I5c30jn6PQ0GC7TbO6Orb1wdtn7os4I07QZcJA==
+-----END CERTIFICATE-----
+
+# Issuer: CN=T-TeleSec GlobalRoot Class 2 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center
+# Subject: CN=T-TeleSec GlobalRoot Class 2 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center
+# Label: "T-TeleSec GlobalRoot Class 2"
+# Serial: 1
+# MD5 Fingerprint: 2b:9b:9e:e4:7b:6c:1f:00:72:1a:cc:c1:77:79:df:6a
+# SHA1 Fingerprint: 59:0d:2d:7d:88:4f:40:2e:61:7e:a5:62:32:17:65:cf:17:d8:94:e9
+# SHA256 Fingerprint: 91:e2:f5:78:8d:58:10:eb:a7:ba:58:73:7d:e1:54:8a:8e:ca:cd:01:45:98:bc:0b:14:3e:04:1b:17:05:25:52
+-----BEGIN CERTIFICATE-----
+MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUx
+KzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAd
+BgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNl
+YyBHbG9iYWxSb290IENsYXNzIDIwHhcNMDgxMDAxMTA0MDE0WhcNMzMxMDAxMjM1
+OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnBy
+aXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50
+ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCqX9obX+hzkeXaXPSi5kfl82hVYAUd
+AqSzm1nzHoqvNK38DcLZSBnuaY/JIPwhqgcZ7bBcrGXHX+0CfHt8LRvWurmAwhiC
+FoT6ZrAIxlQjgeTNuUk/9k9uN0goOA/FvudocP05l03Sx5iRUKrERLMjfTlH6VJi
+1hKTXrcxlkIF+3anHqP1wvzpesVsqXFP6st4vGCvx9702cu+fjOlbpSD8DT6Iavq
+jnKgP6TeMFvvhk1qlVtDRKgQFRzlAVfFmPHmBiiRqiDFt1MmUUOyCxGVWOHAD3bZ
+wI18gfNycJ5v/hqO2V81xrJvNHy+SE/iWjnX2J14np+GPgNeGYtEotXHAgMBAAGj
+QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS/
+WSA2AHmgoCJrjNXyYdK4LMuCSjANBgkqhkiG9w0BAQsFAAOCAQEAMQOiYQsfdOhy
+NsZt+U2e+iKo4YFWz827n+qrkRk4r6p8FU3ztqONpfSO9kSpp+ghla0+AGIWiPAC
+uvxhI+YzmzB6azZie60EI4RYZeLbK4rnJVM3YlNfvNoBYimipidx5joifsFvHZVw
+IEoHNN/q/xWA5brXethbdXwFeilHfkCoMRN3zUA7tFFHei4R40cR3p1m0IvVVGb6
+g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN
+9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlP
+BSeOE6Fuwg==
+-----END CERTIFICATE-----
+
+# Issuer: CN=Atos TrustedRoot 2011 O=Atos
+# Subject: CN=Atos TrustedRoot 2011 O=Atos
+# Label: "Atos TrustedRoot 2011"
+# Serial: 6643877497813316402
+# MD5 Fingerprint: ae:b9:c4:32:4b:ac:7f:5d:66:cc:77:94:bb:2a:77:56
+# SHA1 Fingerprint: 2b:b1:f5:3e:55:0c:1d:c5:f1:d4:e6:b7:6a:46:4b:55:06:02:ac:21
+# SHA256 Fingerprint: f3:56:be:a2:44:b7:a9:1e:b3:5d:53:ca:9a:d7:86:4a:ce:01:8e:2d:35:d5:f8:f9:6d:df:68:a6:f4:1a:a4:74
+-----BEGIN CERTIFICATE-----
+MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UE
+AwwVQXRvcyBUcnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQG
+EwJERTAeFw0xMTA3MDcxNDU4MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMM
+FUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsGA1UECgwEQXRvczELMAkGA1UEBhMC
+REUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCVhTuXbyo7LjvPpvMp
+Nb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr54rM
+VD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+
+SZFhyBH+DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ
+4J7sVaE3IqKHBAUsR320HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0L
+cp2AMBYHlT8oDv3FdU9T1nSatCQujgKRz3bFmx5VdJx4IbHwLfELn8LVlhgf8FQi
+eowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7Rl+lwrrw7GWzbITAPBgNV
+HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZbNshMBgG
+A1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3
+DQEBCwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8j
+vZfza1zv7v1Apt+hk6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kP
+DpFrdRbhIfzYJsdHt6bPWHJxfrrhTZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pc
+maHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a961qn8FYiqTxlVMYVqL2Gns2D
+lmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G3mB/ufNPRJLv
+KrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed
+-----END CERTIFICATE-----
+
+# Issuer: CN=QuoVadis Root CA 1 G3 O=QuoVadis Limited
+# Subject: CN=QuoVadis Root CA 1 G3 O=QuoVadis Limited
+# Label: "QuoVadis Root CA 1 G3"
+# Serial: 687049649626669250736271037606554624078720034195
+# MD5 Fingerprint: a4:bc:5b:3f:fe:37:9a:fa:64:f0:e2:fa:05:3d:0b:ab
+# SHA1 Fingerprint: 1b:8e:ea:57:96:29:1a:c9:39:ea:b8:0a:81:1a:73:73:c0:93:79:67
+# SHA256 Fingerprint: 8a:86:6f:d1:b2:76:b5:7e:57:8e:92:1c:65:82:8a:2b:ed:58:e9:f2:f2:88:05:41:34:b7:f1:f4:bf:c9:cc:74
+-----BEGIN CERTIFICATE-----
+MIIFYDCCA0igAwIBAgIUeFhfLq0sGUvjNwc1NBMotZbUZZMwDQYJKoZIhvcNAQEL
+BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc
+BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMSBHMzAeFw0xMjAxMTIxNzI3NDRaFw00
+MjAxMTIxNzI3NDRaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
+aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEgRzMwggIiMA0GCSqG
+SIb3DQEBAQUAA4ICDwAwggIKAoICAQCgvlAQjunybEC0BJyFuTHK3C3kEakEPBtV
+wedYMB0ktMPvhd6MLOHBPd+C5k+tR4ds7FtJwUrVu4/sh6x/gpqG7D0DmVIB0jWe
+rNrwU8lmPNSsAgHaJNM7qAJGr6Qc4/hzWHa39g6QDbXwz8z6+cZM5cOGMAqNF341
+68Xfuw6cwI2H44g4hWf6Pser4BOcBRiYz5P1sZK0/CPTz9XEJ0ngnjybCKOLXSoh
+4Pw5qlPafX7PGglTvF0FBM+hSo+LdoINofjSxxR3W5A2B4GbPgb6Ul5jxaYA/qXp
+UhtStZI5cgMJYr2wYBZupt0lwgNm3fME0UDiTouG9G/lg6AnhF4EwfWQvTA9xO+o
+abw4m6SkltFi2mnAAZauy8RRNOoMqv8hjlmPSlzkYZqn0ukqeI1RPToV7qJZjqlc
+3sX5kCLliEVx3ZGZbHqfPT2YfF72vhZooF6uCyP8Wg+qInYtyaEQHeTTRCOQiJ/G
+KubX9ZqzWB4vMIkIG1SitZgj7Ah3HJVdYdHLiZxfokqRmu8hqkkWCKi9YSgxyXSt
+hfbZxbGL0eUQMk1fiyA6PEkfM4VZDdvLCXVDaXP7a3F98N/ETH3Goy7IlXnLc6KO
+Tk0k+17kBL5yG6YnLUlamXrXXAkgt3+UuU/xDRxeiEIbEbfnkduebPRq34wGmAOt
+zCjvpUfzUwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB
+BjAdBgNVHQ4EFgQUo5fW816iEOGrRZ88F2Q87gFwnMwwDQYJKoZIhvcNAQELBQAD
+ggIBABj6W3X8PnrHX3fHyt/PX8MSxEBd1DKquGrX1RUVRpgjpeaQWxiZTOOtQqOC
+MTaIzen7xASWSIsBx40Bz1szBpZGZnQdT+3Btrm0DWHMY37XLneMlhwqI2hrhVd2
+cDMT/uFPpiN3GPoajOi9ZcnPP/TJF9zrx7zABC4tRi9pZsMbj/7sPtPKlL92CiUN
+qXsCHKnQO18LwIE6PWThv6ctTr1NxNgpxiIY0MWscgKCP6o6ojoilzHdCGPDdRS5
+YCgtW2jgFqlmgiNR9etT2DGbe+m3nUvriBbP+V04ikkwj+3x6xn0dxoxGE1nVGwv
+b2X52z3sIexe9PSLymBlVNFxZPT5pqOBMzYzcfCkeF9OrYMh3jRJjehZrJ3ydlo2
+8hP0r+AJx2EqbPfgna67hkooby7utHnNkDPDs3b69fBsnQGQ+p6Q9pxyz0fawx/k
+NSBT8lTR32GDpgLiJTjehTItXnOQUl1CxM49S+H5GYQd1aJQzEH7QRTDvdbJWqNj
+ZgKAvQU6O0ec7AAmTPWIUb+oI38YB7AL7YsmoWTTYUrrXJ/es69nA7Mf3W1daWhp
+q1467HxpvMc7hU6eFbm0FU/DlXpY18ls6Wy58yljXrQs8C097Vpl4KlbQMJImYFt
+nh8GKjwStIsPm6Ik8KaN1nrgS7ZklmOVhMJKzRwuJIczYOXD
+-----END CERTIFICATE-----
+
+# Issuer: CN=QuoVadis Root CA 2 G3 O=QuoVadis Limited
+# Subject: CN=QuoVadis Root CA 2 G3 O=QuoVadis Limited
+# Label: "QuoVadis Root CA 2 G3"
+# Serial: 390156079458959257446133169266079962026824725800
+# MD5 Fingerprint: af:0c:86:6e:bf:40:2d:7f:0b:3e:12:50:ba:12:3d:06
+# SHA1 Fingerprint: 09:3c:61:f3:8b:8b:dc:7d:55:df:75:38:02:05:00:e1:25:f5:c8:36
+# SHA256 Fingerprint: 8f:e4:fb:0a:f9:3a:4d:0d:67:db:0b:eb:b2:3e:37:c7:1b:f3:25:dc:bc:dd:24:0e:a0:4d:af:58:b4:7e:18:40
+-----BEGIN CERTIFICATE-----
+MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQEL
+BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc
+BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00
+MjAxMTIxODU5MzJaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
+aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIgRzMwggIiMA0GCSqG
+SIb3DQEBAQUAA4ICDwAwggIKAoICAQChriWyARjcV4g/Ruv5r+LrI3HimtFhZiFf
+qq8nUeVuGxbULX1QsFN3vXg6YOJkApt8hpvWGo6t/x8Vf9WVHhLL5hSEBMHfNrMW
+n4rjyduYNM7YMxcoRvynyfDStNVNCXJJ+fKH46nafaF9a7I6JaltUkSs+L5u+9ym
+c5GQYaYDFCDy54ejiK2toIz/pgslUiXnFgHVy7g1gQyjO/Dh4fxaXc6AcW34Sas+
+O7q414AB+6XrW7PFXmAqMaCvN+ggOp+oMiwMzAkd056OXbxMmO7FGmh77FOm6RQ1
+o9/NgJ8MSPsc9PG/Srj61YxxSscfrf5BmrODXfKEVu+lV0POKa2Mq1W/xPtbAd0j
+IaFYAI7D0GoT7RPjEiuA3GfmlbLNHiJuKvhB1PLKFAeNilUSxmn1uIZoL1NesNKq
+IcGY5jDjZ1XHm26sGahVpkUG0CM62+tlXSoREfA7T8pt9DTEceT/AFr2XK4jYIVz
+8eQQsSWu1ZK7E8EM4DnatDlXtas1qnIhO4M15zHfeiFuuDIIfR0ykRVKYnLP43eh
+vNURG3YBZwjgQQvD6xVu+KQZ2aKrr+InUlYrAoosFCT5v0ICvybIxo/gbjh9Uy3l
+7ZizlWNof/k19N+IxWA1ksB8aRxhlRbQ694Lrz4EEEVlWFA4r0jyWbYW8jwNkALG
+cC4BrTwV1wIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB
+BjAdBgNVHQ4EFgQU7edvdlq/YOxJW8ald7tyFnGbxD0wDQYJKoZIhvcNAQELBQAD
+ggIBAJHfgD9DCX5xwvfrs4iP4VGyvD11+ShdyLyZm3tdquXK4Qr36LLTn91nMX66
+AarHakE7kNQIXLJgapDwyM4DYvmL7ftuKtwGTTwpD4kWilhMSA/ohGHqPHKmd+RC
+roijQ1h5fq7KpVMNqT1wvSAZYaRsOPxDMuHBR//47PERIjKWnML2W2mWeyAMQ0Ga
+W/ZZGYjeVYg3UQt4XAoeo0L9x52ID8DyeAIkVJOviYeIyUqAHerQbj5hLja7NQ4n
+lv1mNDthcnPxFlxHBlRJAHpYErAK74X9sbgzdWqTHBLmYF5vHX/JHyPLhGGfHoJE
++V+tYlUkmlKY7VHnoX6XOuYvHxHaU4AshZ6rNRDbIl9qxV6XU/IyAgkwo1jwDQHV
+csaxfGl7w/U2Rcxhbl5MlMVerugOXou/983g7aEOGzPuVBj+D77vfoRrQ+NwmNtd
+dbINWQeFFSM51vHfqSYP1kjHs6Yi9TM3WpVHn3u6GBVv/9YUZINJ0gpnIdsPNWNg
+KCLjsZWDzYWm3S8P52dSbrsvhXz1SnPnxT7AvSESBT/8twNJAlvIJebiVDj1eYeM
+HVOyToV7BjjHLPj4sHKNJeV3UvQDHEimUF+IIDBu8oJDqz2XhOdT+yHBTw8imoa4
+WSr2Rz0ZiC3oheGe7IUIarFsNMkd7EgrO3jtZsSOeWmD3n+M
+-----END CERTIFICATE-----
+
+# Issuer: CN=QuoVadis Root CA 3 G3 O=QuoVadis Limited
+# Subject: CN=QuoVadis Root CA 3 G3 O=QuoVadis Limited
+# Label: "QuoVadis Root CA 3 G3"
+# Serial: 268090761170461462463995952157327242137089239581
+# MD5 Fingerprint: df:7d:b9:ad:54:6f:68:a1:df:89:57:03:97:43:b0:d7
+# SHA1 Fingerprint: 48:12:bd:92:3c:a8:c4:39:06:e7:30:6d:27:96:e6:a4:cf:22:2e:7d
+# SHA256 Fingerprint: 88:ef:81:de:20:2e:b0:18:45:2e:43:f8:64:72:5c:ea:5f:bd:1f:c2:d9:d2:05:73:07:09:c5:d8:b8:69:0f:46
+-----BEGIN CERTIFICATE-----
+MIIFYDCCA0igAwIBAgIULvWbAiin23r/1aOp7r0DoM8Sah0wDQYJKoZIhvcNAQEL
+BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc
+BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMyBHMzAeFw0xMjAxMTIyMDI2MzJaFw00
+MjAxMTIyMDI2MzJaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
+aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMgRzMwggIiMA0GCSqG
+SIb3DQEBAQUAA4ICDwAwggIKAoICAQCzyw4QZ47qFJenMioKVjZ/aEzHs286IxSR
+/xl/pcqs7rN2nXrpixurazHb+gtTTK/FpRp5PIpM/6zfJd5O2YIyC0TeytuMrKNu
+FoM7pmRLMon7FhY4futD4tN0SsJiCnMK3UmzV9KwCoWdcTzeo8vAMvMBOSBDGzXR
+U7Ox7sWTaYI+FrUoRqHe6okJ7UO4BUaKhvVZR74bbwEhELn9qdIoyhA5CcoTNs+c
+ra1AdHkrAj80//ogaX3T7mH1urPnMNA3I4ZyYUUpSFlob3emLoG+B01vr87ERROR
+FHAGjx+f+IdpsQ7vw4kZ6+ocYfx6bIrc1gMLnia6Et3UVDmrJqMz6nWB2i3ND0/k
+A9HvFZcba5DFApCTZgIhsUfei5pKgLlVj7WiL8DWM2fafsSntARE60f75li59wzw
+eyuxwHApw0BiLTtIadwjPEjrewl5qW3aqDCYz4ByA4imW0aucnl8CAMhZa634Ryl
+sSqiMd5mBPfAdOhx3v89WcyWJhKLhZVXGqtrdQtEPREoPHtht+KPZ0/l7DxMYIBp
+VzgeAVuNVejH38DMdyM0SXV89pgR6y3e7UEuFAUCf+D+IOs15xGsIs5XPd7JMG0Q
+A4XN8f+MFrXBsj6IbGB/kE+V9/YtrQE5BwT6dYB9v0lQ7e/JxHwc64B+27bQ3RP+
+ydOc17KXqQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB
+BjAdBgNVHQ4EFgQUxhfQvKjqAkPyGwaZXSuQILnXnOQwDQYJKoZIhvcNAQELBQAD
+ggIBADRh2Va1EodVTd2jNTFGu6QHcrxfYWLopfsLN7E8trP6KZ1/AvWkyaiTt3px
+KGmPc+FSkNrVvjrlt3ZqVoAh313m6Tqe5T72omnHKgqwGEfcIHB9UqM+WXzBusnI
+FUBhynLWcKzSt/Ac5IYp8M7vaGPQtSCKFWGafoaYtMnCdvvMujAWzKNhxnQT5Wvv
+oxXqA/4Ti2Tk08HS6IT7SdEQTXlm66r99I0xHnAUrdzeZxNMgRVhvLfZkXdxGYFg
+u/BYpbWcC/ePIlUnwEsBbTuZDdQdm2NnL9DuDcpmvJRPpq3t/O5jrFc/ZSXPsoaP
+0Aj/uHYUbt7lJ+yreLVTubY/6CD50qi+YUbKh4yE8/nxoGibIh6BJpsQBJFxwAYf
+3KDTuVan45gtf4Od34wrnDKOMpTwATwiKp9Dwi7DmDkHOHv8XgBCH/MyJnmDhPbl
+8MFREsALHgQjDFSlTC9JxUrRtm5gDWv8a4uFJGS3iQ6rJUdbPM9+Sb3H6QrG2vd+
+DhcI00iX0HGS8A85PjRqHH3Y8iKuu2n0M7SmSFXRDw4m6Oy2Cy2nhTXN/VnIn9HN
+PlopNLk9hM6xZdRZkZFWdSHBd575euFgndOtBBj0fOtek49TSiIp+EgrPk2GrFt/
+ywaZWWDYWGWVjUTR939+J399roD1B0y2PpxxVJkES/1Y+Zj0
+-----END CERTIFICATE-----
+
+# Issuer: CN=DigiCert Assured ID Root G2 O=DigiCert Inc OU=www.digicert.com
+# Subject: CN=DigiCert Assured ID Root G2 O=DigiCert Inc OU=www.digicert.com
+# Label: "DigiCert Assured ID Root G2"
+# Serial: 15385348160840213938643033620894905419
+# MD5 Fingerprint: 92:38:b9:f8:63:24:82:65:2c:57:33:e6:fe:81:8f:9d
+# SHA1 Fingerprint: a1:4b:48:d9:43:ee:0a:0e:40:90:4f:3c:e0:a4:c0:91:93:51:5d:3f
+# SHA256 Fingerprint: 7d:05:eb:b6:82:33:9f:8c:94:51:ee:09:4e:eb:fe:fa:79:53:a1:14:ed:b2:f4:49:49:45:2f:ab:7d:2f:c1:85
+-----BEGIN CERTIFICATE-----
+MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBl
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv
+b3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQG
+EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl
+cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSA
+n61UQbVH35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4Htecc
+biJVMWWXvdMX0h5i89vqbFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9Hp
+EgjAALAcKxHad3A2m67OeYfcgnDmCXRwVWmvo2ifv922ebPynXApVfSr/5Vh88lA
+bx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OPYLfykqGxvYmJHzDNw6Yu
+YjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+RnlTGNAgMB
+AAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQW
+BBTOw0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPI
+QW5pJ6d1Ee88hjZv0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I
+0jJmwYrA8y8678Dj1JGG0VDjA9tzd29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4Gni
+lmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAWhsI6yLETcDbYz+70CjTVW0z9
+B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0MjomZmWzwPDCv
+ON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo
+IhNzbM8m9Yop5w==
+-----END CERTIFICATE-----
+
+# Issuer: CN=DigiCert Assured ID Root G3 O=DigiCert Inc OU=www.digicert.com
+# Subject: CN=DigiCert Assured ID Root G3 O=DigiCert Inc OU=www.digicert.com
+# Label: "DigiCert Assured ID Root G3"
+# Serial: 15459312981008553731928384953135426796
+# MD5 Fingerprint: 7c:7f:65:31:0c:81:df:8d:ba:3e:99:e2:5c:ad:6e:fb
+# SHA1 Fingerprint: f5:17:a2:4f:9a:48:c6:c9:f8:a2:00:26:9f:dc:0f:48:2c:ab:30:89
+# SHA256 Fingerprint: 7e:37:cb:8b:4c:47:09:0c:ab:36:55:1b:a6:f4:5d:b8:40:68:0f:ba:16:6a:95:2d:b1:00:71:7f:43:05:3f:c2
+-----BEGIN CERTIFICATE-----
+MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQsw
+CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu
+ZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3Qg
+RzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQGEwJV
+UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu
+Y29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQBgcq
+hkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJf
+Zn4f5dwbRXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17Q
+RSAPWXYQ1qAk8C3eNvJsKTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/
+BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgFUaFNN6KDec6NHSrkhDAKBggqhkjOPQQD
+AwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5FyYZ5eEJJZVrmDxxDnOOlY
+JjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy1vUhZscv
+6pZjamVFkpUBtA==
+-----END CERTIFICATE-----
+
+# Issuer: CN=DigiCert Global Root G2 O=DigiCert Inc OU=www.digicert.com
+# Subject: CN=DigiCert Global Root G2 O=DigiCert Inc OU=www.digicert.com
+# Label: "DigiCert Global Root G2"
+# Serial: 4293743540046975378534879503202253541
+# MD5 Fingerprint: e4:a6:8a:c8:54:ac:52:42:46:0a:fd:72:48:1b:2a:44
+# SHA1 Fingerprint: df:3c:24:f9:bf:d6:66:76:1b:26:80:73:fe:06:d1:cc:8d:4f:82:a4
+# SHA256 Fingerprint: cb:3c:cb:b7:60:31:e5:e0:13:8f:8d:d3:9a:23:f9:de:47:ff:c3:5e:43:c1:14:4c:ea:27:d4:6a:5a:b1:cb:5f
+-----BEGIN CERTIFICATE-----
+MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH
+MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT
+MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
+b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG
+9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI
+2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx
+1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ
+q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz
+tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ
+vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP
+BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV
+5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY
+1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4
+NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG
+Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91
+8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe
+pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl
+MrY=
+-----END CERTIFICATE-----
+
+# Issuer: CN=DigiCert Global Root G3 O=DigiCert Inc OU=www.digicert.com
+# Subject: CN=DigiCert Global Root G3 O=DigiCert Inc OU=www.digicert.com
+# Label: "DigiCert Global Root G3"
+# Serial: 7089244469030293291760083333884364146
+# MD5 Fingerprint: f5:5d:a4:50:a5:fb:28:7e:1e:0f:0d:cc:96:57:56:ca
+# SHA1 Fingerprint: 7e:04:de:89:6a:3e:66:6d:00:e6:87:d3:3f:fa:d9:3b:e8:3d:34:9e
+# SHA256 Fingerprint: 31:ad:66:48:f8:10:41:38:c7:38:f3:9e:a4:32:01:33:39:3e:3a:18:cc:02:29:6e:f9:7c:2a:c9:ef:67:31:d0
+-----BEGIN CERTIFICATE-----
+MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQsw
+CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu
+ZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAe
+Fw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVTMRUw
+EwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20x
+IDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0CAQYF
+K4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FG
+fp4tn+6OYwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPO
+Z9wj/wMco+I+o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAd
+BgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNpYim8S8YwCgYIKoZIzj0EAwMDaAAwZQIx
+AK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y3maTD/HMsQmP3Wyr+mt/
+oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34VOKa5Vt8
+sycX
+-----END CERTIFICATE-----
+
+# Issuer: CN=DigiCert Trusted Root G4 O=DigiCert Inc OU=www.digicert.com
+# Subject: CN=DigiCert Trusted Root G4 O=DigiCert Inc OU=www.digicert.com
+# Label: "DigiCert Trusted Root G4"
+# Serial: 7451500558977370777930084869016614236
+# MD5 Fingerprint: 78:f2:fc:aa:60:1f:2f:b4:eb:c9:37:ba:53:2e:75:49
+# SHA1 Fingerprint: dd:fb:16:cd:49:31:c9:73:a2:03:7d:3f:c8:3a:4d:7d:77:5d:05:e4
+# SHA256 Fingerprint: 55:2f:7b:dc:f1:a7:af:9e:6c:e6:72:01:7f:4f:12:ab:f7:72:40:c7:8e:76:1a:c2:03:d1:d9:d2:0a:c8:99:88
+-----BEGIN CERTIFICATE-----
+MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBi
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3Qg
+RzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBiMQswCQYDVQQGEwJV
+UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu
+Y29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0GCSqG
+SIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3y
+ithZwuEppz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1If
+xp4VpX6+n6lXFllVcq9ok3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDV
+ySAdYyktzuxeTsiT+CFhmzTrBcZe7FsavOvJz82sNEBfsXpm7nfISKhmV1efVFiO
+DCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGYQJB5w3jHtrHEtWoYOAMQ
+jdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6MUSaM0C/
+CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCi
+EhtmmnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADM
+fRyVw4/3IbKyEbe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QY
+uKZ3AeEPlAwhHbJUKSWJbOUOUlFHdL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXK
+chYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7FwI+isX4KJpn15GkvmB0t
+9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB
+hjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD
+ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2
+SV1EY+CtnJYYZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd
++SeuMIW59mdNOj6PWTkiU0TryF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWc
+fFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy7zBZLq7gcfJW5GqXb5JQbZaNaHqa
+sjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iahixTXTBmyUEFxPT9N
+cCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN5r5N
+0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie
+4u1Ki7wb/UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mI
+r/OSmbaz5mEP0oUA51Aa5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1
+/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tKG48BtieVU+i2iW1bvGjUI+iLUaJW+fCm
+gKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP82Z+
+-----END CERTIFICATE-----
+
+# Issuer: CN=COMODO RSA Certification Authority O=COMODO CA Limited
+# Subject: CN=COMODO RSA Certification Authority O=COMODO CA Limited
+# Label: "COMODO RSA Certification Authority"
+# Serial: 101909084537582093308941363524873193117
+# MD5 Fingerprint: 1b:31:b0:71:40:36:cc:14:36:91:ad:c4:3e:fd:ec:18
+# SHA1 Fingerprint: af:e5:d2:44:a8:d1:19:42:30:ff:47:9f:e2:f8:97:bb:cd:7a:8c:b4
+# SHA256 Fingerprint: 52:f0:e1:c4:e5:8e:c6:29:29:1b:60:31:7f:07:46:71:b8:5d:7e:a8:0d:5b:07:27:34:63:53:4b:32:b4:02:34
+-----BEGIN CERTIFICATE-----
+MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCB
+hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
+A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV
+BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMTE5
+MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgT
+EkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR
+Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNh
+dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR
+6FSS0gpWsawNJN3Fz0RndJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8X
+pz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZFGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC
+9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+5eNu/Nio5JIk2kNrYrhV
+/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pGx8cgoLEf
+Zd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z
++pUX2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7w
+qP/0uK3pN/u6uPQLOvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZah
+SL0896+1DSJMwBGB7FY79tOi4lu3sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVIC
+u9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+CGCe01a60y1Dma/RMhnEw6abf
+Fobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5WdYgGq/yapiq
+crxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E
+FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB
+/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvl
+wFTPoCWOAvn9sKIN9SCYPBMtrFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM
+4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+nq6PK7o9mfjYcwlYRm6mnPTXJ9OV
+2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSgtZx8jb8uk2Intzna
+FxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwWsRqZ
+CuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiK
+boHGhfKppC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmcke
+jkk9u+UJueBPSZI9FoJAzMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yL
+S0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHqZJx64SIDqZxubw5lT2yHh17zbqD5daWb
+QOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk527RH89elWsn2/x20Kk4yl
+0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7ILaZRfyHB
+NVOFBkpdn627G190
+-----END CERTIFICATE-----
+
+# Issuer: CN=USERTrust RSA Certification Authority O=The USERTRUST Network
+# Subject: CN=USERTrust RSA Certification Authority O=The USERTRUST Network
+# Label: "USERTrust RSA Certification Authority"
+# Serial: 2645093764781058787591871645665788717
+# MD5 Fingerprint: 1b:fe:69:d1:91:b7:19:33:a3:72:a8:0f:e1:55:e5:b5
+# SHA1 Fingerprint: 2b:8f:1b:57:33:0d:bb:a2:d0:7a:6c:51:f7:0e:e9:0d:da:b9:ad:8e
+# SHA256 Fingerprint: e7:93:c9:b0:2f:d8:aa:13:e2:1c:31:22:8a:cc:b0:81:19:64:3b:74:9c:89:89:64:b1:74:6d:46:c3:d4:cb:d2
+-----BEGIN CERTIFICATE-----
+MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCB
+iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl
+cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV
+BAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAw
+MjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNV
+BAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU
+aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2Vy
+dGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK
+AoICAQCAEmUXNg7D2wiz0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B
+3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2jY0K2dvKpOyuR+OJv0OwWIJAJPuLodMkY
+tJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFnRghRy4YUVD+8M/5+bJz/
+Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O+T23LLb2
+VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT
+79uq/nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6
+c0Plfg6lZrEpfDKEY1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmT
+Yo61Zs8liM2EuLE/pDkP2QKe6xJMlXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97l
+c6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8yexDJtC/QV9AqURE9JnnV4ee
+UB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+eLf8ZxXhyVeE
+Hg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd
+BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8G
+A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPF
+Up/L+M+ZBn8b2kMVn54CVVeWFPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KO
+VWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ7l8wXEskEVX/JJpuXior7gtNn3/3
+ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQEg9zKC7F4iRO/Fjs
+8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM8WcR
+iQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYze
+Sf7dNXGiFSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZ
+XHlKYC6SQK5MNyosycdiyA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/
+qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9cJ2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRB
+VXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGwsAvgnEzDHNb842m1R0aB
+L6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gxQ+6IHdfG
+jjxDah2nGN59PRbxYvnKkKj9
+-----END CERTIFICATE-----
+
+# Issuer: CN=USERTrust ECC Certification Authority O=The USERTRUST Network
+# Subject: CN=USERTrust ECC Certification Authority O=The USERTRUST Network
+# Label: "USERTrust ECC Certification Authority"
+# Serial: 123013823720199481456569720443997572134
+# MD5 Fingerprint: fa:68:bc:d9:b5:7f:ad:fd:c9:1d:06:83:28:cc:24:c1
+# SHA1 Fingerprint: d1:cb:ca:5d:b2:d5:2a:7f:69:3b:67:4d:e5:f0:5a:1d:0c:95:7d:f0
+# SHA256 Fingerprint: 4f:f4:60:d5:4b:9c:86:da:bf:bc:fc:57:12:e0:40:0d:2b:ed:3f:bc:4d:4f:bd:aa:86:e0:6a:dc:d2:a9:ad:7a
+-----BEGIN CERTIFICATE-----
+MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDEL
+MAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNl
+eSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMT
+JVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMjAx
+MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgT
+Ck5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVUaGUg
+VVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlm
+aWNhdGlvbiBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqflo
+I+d61SRvU8Za2EurxtW20eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinng
+o4N+LZfQYcTxmdwlkWOrfzCjtHDix6EznPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0G
+A1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNVHQ8BAf8EBAMCAQYwDwYD
+VR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBBHU6+4WMB
+zzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbW
+RNZu9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg=
+-----END CERTIFICATE-----
+
+# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R4
+# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R4
+# Label: "GlobalSign ECC Root CA - R4"
+# Serial: 14367148294922964480859022125800977897474
+# MD5 Fingerprint: 20:f0:27:68:d1:7e:a0:9d:0e:e6:2a:ca:df:5c:89:8e
+# SHA1 Fingerprint: 69:69:56:2e:40:80:f4:24:a1:e7:19:9f:14:ba:f3:ee:58:ab:6a:bb
+# SHA256 Fingerprint: be:c9:49:11:c2:95:56:76:db:6c:0a:55:09:86:d7:6e:3b:a0:05:66:7c:44:2c:97:62:b4:fb:b7:73:de:22:8c
+-----BEGIN CERTIFICATE-----
+MIIB4TCCAYegAwIBAgIRKjikHJYKBN5CsiilC+g0mAIwCgYIKoZIzj0EAwIwUDEk
+MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpH
+bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX
+DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD
+QSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu
+MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuMZ5049sJQ6fLjkZHAOkrprlOQcJ
+FspjsbmG+IpXwVfOQvpzofdlQv8ewQCybnMO/8ch5RikqtlxP6jUuc6MHaNCMEAw
+DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFSwe61F
+uOJAf/sKbvu+M8k8o4TVMAoGCCqGSM49BAMCA0gAMEUCIQDckqGgE6bPA7DmxCGX
+kPoUVy0D7O48027KqGx2vKLeuwIgJ6iFJzWbVsaj8kfSt24bAgAXqmemFZHe+pTs
+ewv4n4Q=
+-----END CERTIFICATE-----
+
+# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R5
+# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R5
+# Label: "GlobalSign ECC Root CA - R5"
+# Serial: 32785792099990507226680698011560947931244
+# MD5 Fingerprint: 9f:ad:3b:1c:02:1e:8a:ba:17:74:38:81:0c:a2:bc:08
+# SHA1 Fingerprint: 1f:24:c6:30:cd:a4:18:ef:20:69:ff:ad:4f:dd:5f:46:3a:1b:69:aa
+# SHA256 Fingerprint: 17:9f:bc:14:8a:3d:d0:0f:d2:4e:a1:34:58:cc:43:bf:a7:f5:9c:81:82:d7:83:a5:13:f6:eb:ec:10:0c:89:24
+-----BEGIN CERTIFICATE-----
+MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEk
+MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpH
+bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX
+DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD
+QSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu
+MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6SFkc
+8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8ke
+hOvRnkmSh5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD
+VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYI
+KoZIzj0EAwMDaAAwZQIxAOVpEslu28YxuglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg
+515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7yFz9SO8NdCKoCOJuxUnO
+xwy8p2Fp8fc74SrL+SvzZpA3
+-----END CERTIFICATE-----
+
+# Issuer: CN=Staat der Nederlanden Root CA - G3 O=Staat der Nederlanden
+# Subject: CN=Staat der Nederlanden Root CA - G3 O=Staat der Nederlanden
+# Label: "Staat der Nederlanden Root CA - G3"
+# Serial: 10003001
+# MD5 Fingerprint: 0b:46:67:07:db:10:2f:19:8c:35:50:60:d1:0b:f4:37
+# SHA1 Fingerprint: d8:eb:6b:41:51:92:59:e0:f3:e7:85:00:c0:3d:b6:88:97:c9:ee:fc
+# SHA256 Fingerprint: 3c:4f:b0:b9:5a:b8:b3:00:32:f4:32:b8:6f:53:5f:e1:72:c1:85:d0:fd:39:86:58:37:cf:36:18:7f:a6:f4:28
+-----BEGIN CERTIFICATE-----
+MIIFdDCCA1ygAwIBAgIEAJiiOTANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJO
+TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFh
+dCBkZXIgTmVkZXJsYW5kZW4gUm9vdCBDQSAtIEczMB4XDTEzMTExNDExMjg0MloX
+DTI4MTExMzIzMDAwMFowWjELMAkGA1UEBhMCTkwxHjAcBgNVBAoMFVN0YWF0IGRl
+ciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5lZGVybGFuZGVuIFJv
+b3QgQ0EgLSBHMzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAL4yolQP
+cPssXFnrbMSkUeiFKrPMSjTysF/zDsccPVMeiAho2G89rcKezIJnByeHaHE6n3WW
+IkYFsO2tx1ueKt6c/DrGlaf1F2cY5y9JCAxcz+bMNO14+1Cx3Gsy8KL+tjzk7FqX
+xz8ecAgwoNzFs21v0IJyEavSgWhZghe3eJJg+szeP4TrjTgzkApyI/o1zCZxMdFy
+KJLZWyNtZrVtB0LrpjPOktvA9mxjeM3KTj215VKb8b475lRgsGYeCasH/lSJEULR
+9yS6YHgamPfJEf0WwTUaVHXvQ9Plrk7O53vDxk5hUUurmkVLoR9BvUhTFXFkC4az
+5S6+zqQbwSmEorXLCCN2QyIkHxcE1G6cxvx/K2Ya7Irl1s9N9WMJtxU51nus6+N8
+6U78dULI7ViVDAZCopz35HCz33JvWjdAidiFpNfxC95DGdRKWCyMijmev4SH8RY7
+Ngzp07TKbBlBUgmhHbBqv4LvcFEhMtwFdozL92TkA1CvjJFnq8Xy7ljY3r735zHP
+bMk7ccHViLVlvMDoFxcHErVc0qsgk7TmgoNwNsXNo42ti+yjwUOH5kPiNL6VizXt
+BznaqB16nzaeErAMZRKQFWDZJkBE41ZgpRDUajz9QdwOWke275dhdU/Z/seyHdTt
+XUmzqWrLZoQT1Vyg3N9udwbRcXXIV2+vD3dbAgMBAAGjQjBAMA8GA1UdEwEB/wQF
+MAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRUrfrHkleuyjWcLhL75Lpd
+INyUVzANBgkqhkiG9w0BAQsFAAOCAgEAMJmdBTLIXg47mAE6iqTnB/d6+Oea31BD
+U5cqPco8R5gu4RV78ZLzYdqQJRZlwJ9UXQ4DO1t3ApyEtg2YXzTdO2PCwyiBwpwp
+LiniyMMB8jPqKqrMCQj3ZWfGzd/TtiunvczRDnBfuCPRy5FOCvTIeuXZYzbB1N/8
+Ipf3YF3qKS9Ysr1YvY2WTxB1v0h7PVGHoTx0IsL8B3+A3MSs/mrBcDCw6Y5p4ixp
+gZQJut3+TcCDjJRYwEYgr5wfAvg1VUkvRtTA8KCWAg8zxXHzniN9lLf9OtMJgwYh
+/WA9rjLA0u6NpvDntIJ8CsxwyXmA+P5M9zWEGYox+wrZ13+b8KKaa8MFSu1BYBQw
+0aoRQm7TIwIEC8Zl3d1Sd9qBa7Ko+gE4uZbqKmxnl4mUnrzhVNXkanjvSr0rmj1A
+fsbAddJu+2gw7OyLnflJNZoaLNmzlTnVHpL3prllL+U9bTpITAjc5CgSKL59NVzq
+4BZ+Extq1z7XnvwtdbLBFNUjA9tbbws+eC8N3jONFrdI54OagQ97wUNNVQQXOEpR
+1VmiiXTTn74eS9fGbbeIJG9gkaSChVtWQbzQRKtqE77RLFi3EjNYsjdj3BP1lB0/
+QFH1T/U67cjF68IeHRaVesd+QnGTbksVtzDfqu1XhUisHWrdOWnk4Xl4vs4Fv6EM
+94B7IWcnMFk=
+-----END CERTIFICATE-----
+
+# Issuer: CN=Staat der Nederlanden EV Root CA O=Staat der Nederlanden
+# Subject: CN=Staat der Nederlanden EV Root CA O=Staat der Nederlanden
+# Label: "Staat der Nederlanden EV Root CA"
+# Serial: 10000013
+# MD5 Fingerprint: fc:06:af:7b:e8:1a:f1:9a:b4:e8:d2:70:1f:c0:f5:ba
+# SHA1 Fingerprint: 76:e2:7e:c1:4f:db:82:c1:c0:a6:75:b5:05:be:3d:29:b4:ed:db:bb
+# SHA256 Fingerprint: 4d:24:91:41:4c:fe:95:67:46:ec:4c:ef:a6:cf:6f:72:e2:8a:13:29:43:2f:9d:8a:90:7a:c4:cb:5d:ad:c1:5a
+-----BEGIN CERTIFICATE-----
+MIIFcDCCA1igAwIBAgIEAJiWjTANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJO
+TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSkwJwYDVQQDDCBTdGFh
+dCBkZXIgTmVkZXJsYW5kZW4gRVYgUm9vdCBDQTAeFw0xMDEyMDgxMTE5MjlaFw0y
+MjEyMDgxMTEwMjhaMFgxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIg
+TmVkZXJsYW5kZW4xKTAnBgNVBAMMIFN0YWF0IGRlciBOZWRlcmxhbmRlbiBFViBS
+b290IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA48d+ifkkSzrS
+M4M1LGns3Amk41GoJSt5uAg94JG6hIXGhaTK5skuU6TJJB79VWZxXSzFYGgEt9nC
+UiY4iKTWO0Cmws0/zZiTs1QUWJZV1VD+hq2kY39ch/aO5ieSZxeSAgMs3NZmdO3d
+Z//BYY1jTw+bbRcwJu+r0h8QoPnFfxZpgQNH7R5ojXKhTbImxrpsX23Wr9GxE46p
+rfNeaXUmGD5BKyF/7otdBwadQ8QpCiv8Kj6GyzyDOvnJDdrFmeK8eEEzduG/L13l
+pJhQDBXd4Pqcfzho0LKmeqfRMb1+ilgnQ7O6M5HTp5gVXJrm0w912fxBmJc+qiXb
+j5IusHsMX/FjqTf5m3VpTCgmJdrV8hJwRVXj33NeN/UhbJCONVrJ0yPr08C+eKxC
+KFhmpUZtcALXEPlLVPxdhkqHz3/KRawRWrUgUY0viEeXOcDPusBCAUCZSCELa6fS
+/ZbV0b5GnUngC6agIk440ME8MLxwjyx1zNDFjFE7PZQIZCZhfbnDZY8UnCHQqv0X
+cgOPvZuM5l5Tnrmd74K74bzickFbIZTTRTeU0d8JOV3nI6qaHcptqAqGhYqCvkIH
+1vI4gnPah1vlPNOePqc7nvQDs/nxfRN0Av+7oeX6AHkcpmZBiFxgV6YuCcS6/ZrP
+px9Aw7vMWgpVSzs4dlG4Y4uElBbmVvMCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB
+/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFP6rAJCYniT8qcwaivsnuL8wbqg7
+MA0GCSqGSIb3DQEBCwUAA4ICAQDPdyxuVr5Os7aEAJSrR8kN0nbHhp8dB9O2tLsI
+eK9p0gtJ3jPFrK3CiAJ9Brc1AsFgyb/E6JTe1NOpEyVa/m6irn0F3H3zbPB+po3u
+2dfOWBfoqSmuc0iH55vKbimhZF8ZE/euBhD/UcabTVUlT5OZEAFTdfETzsemQUHS
+v4ilf0X8rLiltTMMgsT7B/Zq5SWEXwbKwYY5EdtYzXc7LMJMD16a4/CrPmEbUCTC
+wPTxGfARKbalGAKb12NMcIxHowNDXLldRqANb/9Zjr7dn3LDWyvfjFvO5QxGbJKy
+CqNMVEIYFRIYvdr8unRu/8G2oGTYqV9Vrp9canaW2HNnh/tNf1zuacpzEPuKqf2e
+vTY4SUmH9A4U8OmHuD+nT3pajnnUk+S7aFKErGzp85hwVXIy+TSrK0m1zSBi5Dp6
+Z2Orltxtrpfs/J92VoguZs9btsmksNcFuuEnL5O7Jiqik7Ab846+HUCjuTaPPoIa
+Gl6I6lD4WeKDRikL40Rc4ZW2aZCaFG+XroHPaO+Zmr615+F/+PoTRxZMzG0IQOeL
+eG9QgkRQP2YGiqtDhFZKDyAthg710tvSeopLzaXoTvFeJiUBWSOgftL2fiFX1ye8
+FVdMpEbB4IMeDExNH08GGeL5qPQ6gqGyeUN51q1veieQA6TqJIc/2b3Z6fJfUEkc
+7uzXLg==
+-----END CERTIFICATE-----
+
+# Issuer: CN=IdenTrust Commercial Root CA 1 O=IdenTrust
+# Subject: CN=IdenTrust Commercial Root CA 1 O=IdenTrust
+# Label: "IdenTrust Commercial Root CA 1"
+# Serial: 13298821034946342390520003877796839426
+# MD5 Fingerprint: b3:3e:77:73:75:ee:a0:d3:e3:7e:49:63:49:59:bb:c7
+# SHA1 Fingerprint: df:71:7e:aa:4a:d9:4e:c9:55:84:99:60:2d:48:de:5f:bc:f0:3a:25
+# SHA256 Fingerprint: 5d:56:49:9b:e4:d2:e0:8b:cf:ca:d0:8a:3e:38:72:3d:50:50:3b:de:70:69:48:e4:2f:55:60:30:19:e5:28:ae
+-----BEGIN CERTIFICATE-----
+MIIFYDCCA0igAwIBAgIQCgFCgAAAAUUjyES1AAAAAjANBgkqhkiG9w0BAQsFADBK
+MQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVu
+VHJ1c3QgQ29tbWVyY2lhbCBSb290IENBIDEwHhcNMTQwMTE2MTgxMjIzWhcNMzQw
+MTE2MTgxMjIzWjBKMQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MScw
+JQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBSb290IENBIDEwggIiMA0GCSqG
+SIb3DQEBAQUAA4ICDwAwggIKAoICAQCnUBneP5k91DNG8W9RYYKyqU+PZ4ldhNlT
+3Qwo2dfw/66VQ3KZ+bVdfIrBQuExUHTRgQ18zZshq0PirK1ehm7zCYofWjK9ouuU
++ehcCuz/mNKvcbO0U59Oh++SvL3sTzIwiEsXXlfEU8L2ApeN2WIrvyQfYo3fw7gp
+S0l4PJNgiCL8mdo2yMKi1CxUAGc1bnO/AljwpN3lsKImesrgNqUZFvX9t++uP0D1
+bVoE/c40yiTcdCMbXTMTEl3EASX2MN0CXZ/g1Ue9tOsbobtJSdifWwLziuQkkORi
+T0/Br4sOdBeo0XKIanoBScy0RnnGF7HamB4HWfp1IYVl3ZBWzvurpWCdxJ35UrCL
+vYf5jysjCiN2O/cz4ckA82n5S6LgTrx+kzmEB/dEcH7+B1rlsazRGMzyNeVJSQjK
+Vsk9+w8YfYs7wRPCTY/JTw436R+hDmrfYi7LNQZReSzIJTj0+kuniVyc0uMNOYZK
+dHzVWYfCP04MXFL0PfdSgvHqo6z9STQaKPNBiDoT7uje/5kdX7rL6B7yuVBgwDHT
+c+XvvqDtMwt0viAgxGds8AgDelWAf0ZOlqf0Hj7h9tgJ4TNkK2PXMl6f+cB7D3hv
+l7yTmvmcEpB4eoCHFddydJxVdHixuuFucAS6T6C6aMN7/zHwcz09lCqxC0EOoP5N
+iGVreTO01wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
+/zAdBgNVHQ4EFgQU7UQZwNPwBovupHu+QucmVMiONnYwDQYJKoZIhvcNAQELBQAD
+ggIBAA2ukDL2pkt8RHYZYR4nKM1eVO8lvOMIkPkp165oCOGUAFjvLi5+U1KMtlwH
+6oi6mYtQlNeCgN9hCQCTrQ0U5s7B8jeUeLBfnLOic7iPBZM4zY0+sLj7wM+x8uwt
+LRvM7Kqas6pgghstO8OEPVeKlh6cdbjTMM1gCIOQ045U8U1mwF10A0Cj7oV+wh93
+nAbowacYXVKV7cndJZ5t+qntozo00Fl72u1Q8zW/7esUTTHHYPTa8Yec4kjixsU3
++wYQ+nVZZjFHKdp2mhzpgq7vmrlR94gjmmmVYjzlVYA211QC//G5Xc7UI2/YRYRK
+W2XviQzdFKcgyxilJbQN+QHwotL0AMh0jqEqSI5l2xPE4iUXfeu+h1sXIFRRk0pT
+AwvsXcoz7WL9RccvW9xYoIA55vrX/hMUpu09lEpCdNTDd1lzzY9GvlU47/rokTLq
+l1gEIt44w8y8bckzOmoKaT+gyOpyj4xjhiO9bTyWnpXgSUyqorkqG5w2gXjtw+hG
+4iZZRHUe2XWJUc0QhJ1hYMtd+ZciTY6Y5uN/9lu7rs3KSoFrXgvzUeF0K+l+J6fZ
+mUlO+KWA2yUPHGNiiskzZ2s8EIPGrd6ozRaOjfAHN3Gf8qv8QfXBi+wAN10J5U6A
+7/qxXDgGpRtK4dw4LTzcqx+QGtVKnO7RcGzM7vRX+Bi6hG6H
+-----END CERTIFICATE-----
+
+# Issuer: CN=IdenTrust Public Sector Root CA 1 O=IdenTrust
+# Subject: CN=IdenTrust Public Sector Root CA 1 O=IdenTrust
+# Label: "IdenTrust Public Sector Root CA 1"
+# Serial: 13298821034946342390521976156843933698
+# MD5 Fingerprint: 37:06:a5:b0:fc:89:9d:ba:f4:6b:8c:1a:64:cd:d5:ba
+# SHA1 Fingerprint: ba:29:41:60:77:98:3f:f4:f3:ef:f2:31:05:3b:2e:ea:6d:4d:45:fd
+# SHA256 Fingerprint: 30:d0:89:5a:9a:44:8a:26:20:91:63:55:22:d1:f5:20:10:b5:86:7a:ca:e1:2c:78:ef:95:8f:d4:f4:38:9f:2f
+-----BEGIN CERTIFICATE-----
+MIIFZjCCA06gAwIBAgIQCgFCgAAAAUUjz0Z8AAAAAjANBgkqhkiG9w0BAQsFADBN
+MQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVu
+VHJ1c3QgUHVibGljIFNlY3RvciBSb290IENBIDEwHhcNMTQwMTE2MTc1MzMyWhcN
+MzQwMTE2MTc1MzMyWjBNMQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0
+MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3RvciBSb290IENBIDEwggIi
+MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2IpT8pEiv6EdrCvsnduTyP4o7
+ekosMSqMjbCpwzFrqHd2hCa2rIFCDQjrVVi7evi8ZX3yoG2LqEfpYnYeEe4IFNGy
+RBb06tD6Hi9e28tzQa68ALBKK0CyrOE7S8ItneShm+waOh7wCLPQ5CQ1B5+ctMlS
+bdsHyo+1W/CD80/HLaXIrcuVIKQxKFdYWuSNG5qrng0M8gozOSI5Cpcu81N3uURF
+/YTLNiCBWS2ab21ISGHKTN9T0a9SvESfqy9rg3LvdYDaBjMbXcjaY8ZNzaxmMc3R
+3j6HEDbhuaR672BQssvKplbgN6+rNBM5Jeg5ZuSYeqoSmJxZZoY+rfGwyj4GD3vw
+EUs3oERte8uojHH01bWRNszwFcYr3lEXsZdMUD2xlVl8BX0tIdUAvwFnol57plzy
+9yLxkA2T26pEUWbMfXYD62qoKjgZl3YNa4ph+bz27nb9cCvdKTz4Ch5bQhyLVi9V
+GxyhLrXHFub4qjySjmm2AcG1hp2JDws4lFTo6tyePSW8Uybt1as5qsVATFSrsrTZ
+2fjXctscvG29ZV/viDUqZi/u9rNl8DONfJhBaUYPQxxp+pu10GFqzcpL2UyQRqsV
+WaFHVCkugyhfHMKiq3IXAAaOReyL4jM9f9oZRORicsPfIsbyVtTdX5Vy7W1f90gD
+W/3FKqD2cyOEEBsB5wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/
+BAUwAwEB/zAdBgNVHQ4EFgQU43HgntinQtnbcZFrlJPrw6PRFKMwDQYJKoZIhvcN
+AQELBQADggIBAEf63QqwEZE4rU1d9+UOl1QZgkiHVIyqZJnYWv6IAcVYpZmxI1Qj
+t2odIFflAWJBF9MJ23XLblSQdf4an4EKwt3X9wnQW3IV5B4Jaj0z8yGa5hV+rVHV
+DRDtfULAj+7AmgjVQdZcDiFpboBhDhXAuM/FSRJSzL46zNQuOAXeNf0fb7iAaJg9
+TaDKQGXSc3z1i9kKlT/YPyNtGtEqJBnZhbMX73huqVjRI9PHE+1yJX9dsXNw0H8G
+lwmEKYBhHfpe/3OsoOOJuBxxFcbeMX8S3OFtm6/n6J91eEyrRjuazr8FGF1NFTwW
+mhlQBJqymm9li1JfPFgEKCXAZmExfrngdbkaqIHWchezxQMxNRF4eKLg6TCMf4Df
+WN88uieW4oA0beOY02QnrEh+KHdcxiVhJfiFDGX6xDIvpZgF5PgLZxYWxoK4Mhn5
++bl53B/N66+rDt0b20XkeucC4pVd/GnwU2lhlXV5C15V5jgclKlZM57IcXR5f1GJ
+tshquDDIajjDbp7hNxbqBWJMWxJH7ae0s1hWx0nzfxJoCTFx8G34Tkf71oXuxVhA
+GaQdp/lLQzfcaFpPz+vCZHTetBXZ9FRUGi8c15dxVJCO2SCdUyt/q4/i6jC8UDfv
+8Ue1fXwsBOxonbRJRBD0ckscZOf85muQ3Wl9af0AVqW3rLatt8o+Ae+c
+-----END CERTIFICATE-----
+
+# Issuer: CN=Entrust Root Certification Authority - G2 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2009 Entrust, Inc. - for authorized use only
+# Subject: CN=Entrust Root Certification Authority - G2 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2009 Entrust, Inc. - for authorized use only
+# Label: "Entrust Root Certification Authority - G2"
+# Serial: 1246989352
+# MD5 Fingerprint: 4b:e2:c9:91:96:65:0c:f4:0e:5a:93:92:a0:0a:fe:b2
+# SHA1 Fingerprint: 8c:f4:27:fd:79:0c:3a:d1:66:06:8d:e8:1e:57:ef:bb:93:22:72:d4
+# SHA256 Fingerprint: 43:df:57:74:b0:3e:7f:ef:5f:e4:0d:93:1a:7b:ed:f1:bb:2e:6b:42:73:8c:4e:6d:38:41:10:3d:3a:a7:f3:39
+-----BEGIN CERTIFICATE-----
+MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMC
+VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50
+cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3Qs
+IEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVz
+dCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwHhcNMDkwNzA3MTcy
+NTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUVu
+dHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwt
+dGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0
+aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmlj
+YXRpb24gQXV0aG9yaXR5IC0gRzIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
+AoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP/vaCeb9zYQYKpSfYs1/T
+RU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXzHHfV1IWN
+cCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hW
+wcKUs/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1
+U1+cPvQXLOZprE4yTGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0
+jaWvYkxN4FisZDQSA/i2jZRjJKRxAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAP
+BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ60B7vfec7aVHUbI2fkBJmqzAN
+BgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5ZiXMRrEPR9RP/
+jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ
+Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v
+1fN2D807iDginWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4R
+nAuknZoh8/CbCzB428Hch0P+vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmH
+VHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xOe4pIb4tF9g==
+-----END CERTIFICATE-----
+
+# Issuer: CN=Entrust Root Certification Authority - EC1 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2012 Entrust, Inc. - for authorized use only
+# Subject: CN=Entrust Root Certification Authority - EC1 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2012 Entrust, Inc. - for authorized use only
+# Label: "Entrust Root Certification Authority - EC1"
+# Serial: 51543124481930649114116133369
+# MD5 Fingerprint: b6:7e:1d:f0:58:c5:49:6c:24:3b:3d:ed:98:18:ed:bc
+# SHA1 Fingerprint: 20:d8:06:40:df:9b:25:f5:12:25:3a:11:ea:f7:59:8a:eb:14:b5:47
+# SHA256 Fingerprint: 02:ed:0e:b2:8c:14:da:45:16:5c:56:67:91:70:0d:64:51:d7:fb:56:f0:b2:ab:1d:3b:8e:b0:70:e5:6e:df:f5
+-----BEGIN CERTIFICATE-----
+MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkG
+A1UEBhMCVVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3
+d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVu
+dHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEzMDEGA1UEAxMq
+RW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRUMxMB4XDTEy
+MTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYwFAYD
+VQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0
+L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0g
+Zm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBD
+ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEVDMTB2MBAGByqGSM49AgEGBSuBBAAi
+A2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHyAsWfoPZb1YsGGYZPUxBt
+ByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef9eNi1KlH
+Bz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O
+BBYEFLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVC
+R98crlOZF7ZvHH3hvxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nX
+hTcGtXsI/esni0qU+eH6p44mCOh8kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G
+-----END CERTIFICATE-----
+
+# Issuer: CN=CFCA EV ROOT O=China Financial Certification Authority
+# Subject: CN=CFCA EV ROOT O=China Financial Certification Authority
+# Label: "CFCA EV ROOT"
+# Serial: 407555286
+# MD5 Fingerprint: 74:e1:b6:ed:26:7a:7a:44:30:33:94:ab:7b:27:81:30
+# SHA1 Fingerprint: e2:b8:29:4b:55:84:ab:6b:58:c2:90:46:6c:ac:3f:b8:39:8f:84:83
+# SHA256 Fingerprint: 5c:c3:d7:8e:4e:1d:5e:45:54:7a:04:e6:87:3e:64:f9:0c:f9:53:6d:1c:cc:2e:f8:00:f3:55:c4:c5:fd:70:fd
+-----BEGIN CERTIFICATE-----
+MIIFjTCCA3WgAwIBAgIEGErM1jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJD
+TjEwMC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9y
+aXR5MRUwEwYDVQQDDAxDRkNBIEVWIFJPT1QwHhcNMTIwODA4MDMwNzAxWhcNMjkx
+MjMxMDMwNzAxWjBWMQswCQYDVQQGEwJDTjEwMC4GA1UECgwnQ2hpbmEgRmluYW5j
+aWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQDDAxDRkNBIEVWIFJP
+T1QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXXWvNED8fBVnVBU03
+sQ7smCuOFR36k0sXgiFxEFLXUWRwFsJVaU2OFW2fvwwbwuCjZ9YMrM8irq93VCpL
+TIpTUnrD7i7es3ElweldPe6hL6P3KjzJIx1qqx2hp/Hz7KDVRM8Vz3IvHWOX6Jn5
+/ZOkVIBMUtRSqy5J35DNuF++P96hyk0g1CXohClTt7GIH//62pCfCqktQT+x8Rgp
+7hZZLDRJGqgG16iI0gNyejLi6mhNbiyWZXvKWfry4t3uMCz7zEasxGPrb382KzRz
+EpR/38wmnvFyXVBlWY9ps4deMm/DGIq1lY+wejfeWkU7xzbh72fROdOXW3NiGUgt
+hxwG+3SYIElz8AXSG7Ggo7cbcNOIabla1jj0Ytwli3i/+Oh+uFzJlU9fpy25IGvP
+a931DfSCt/SyZi4QKPaXWnuWFo8BGS1sbn85WAZkgwGDg8NNkt0yxoekN+kWzqot
+aK8KgWU6cMGbrU1tVMoqLUuFG7OA5nBFDWteNfB/O7ic5ARwiRIlk9oKmSJgamNg
+TnYGmE69g60dWIolhdLHZR4tjsbftsbhf4oEIRUpdPA+nJCdDC7xij5aqgwJHsfV
+PKPtl8MeNPo4+QgO48BdK4PRVmrJtqhUUy54Mmc9gn900PvhtgVguXDbjgv5E1hv
+cWAQUhC5wUEJ73IfZzF4/5YFjQIDAQABo2MwYTAfBgNVHSMEGDAWgBTj/i39KNAL
+tbq2osS/BqoFjJP7LzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAd
+BgNVHQ4EFgQU4/4t/SjQC7W6tqLEvwaqBYyT+y8wDQYJKoZIhvcNAQELBQADggIB
+ACXGumvrh8vegjmWPfBEp2uEcwPenStPuiB/vHiyz5ewG5zz13ku9Ui20vsXiObT
+ej/tUxPQ4i9qecsAIyjmHjdXNYmEwnZPNDatZ8POQQaIxffu2Bq41gt/UP+TqhdL
+jOztUmCypAbqTuv0axn96/Ua4CUqmtzHQTb3yHQFhDmVOdYLO6Qn+gjYXB74BGBS
+ESgoA//vU2YApUo0FmZ8/Qmkrp5nGm9BC2sGE5uPhnEFtC+NiWYzKXZUmhH4J/qy
+P5Hgzg0b8zAarb8iXRvTvyUFTeGSGn+ZnzxEk8rUQElsgIfXBDrDMlI1Dlb4pd19
+xIsNER9Tyx6yF7Zod1rg1MvIB671Oi6ON7fQAUtDKXeMOZePglr4UeWJoBjnaH9d
+Ci77o0cOPaYjesYBx4/IXr9tgFa+iiS6M+qf4TIRnvHST4D2G0CvOJ4RUHlzEhLN
+5mydLIhyPDCBBpEi6lmt2hkuIsKNuYyH4Ga8cyNfIWRjgEj1oDwYPZTISEEdQLpe
+/v5WOaHIz16eGWRGENoXkbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+Z
+AAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3CekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ
+5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su
+-----END CERTIFICATE-----
+
+# Issuer: CN=TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı H5 O=TÜRKTRUST Bilgi İletişim ve Bilişim Güvenliği Hizmetleri A.Ş.
+# Subject: CN=TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı H5 O=TÜRKTRUST Bilgi İletişim ve Bilişim Güvenliği Hizmetleri A.Ş.
+# Label: "TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı H5"
+# Serial: 156233699172481
+# MD5 Fingerprint: da:70:8e:f0:22:df:93:26:f6:5f:9f:d3:15:06:52:4e
+# SHA1 Fingerprint: c4:18:f6:4d:46:d1:df:00:3d:27:30:13:72:43:a9:12:11:c6:75:fb
+# SHA256 Fingerprint: 49:35:1b:90:34:44:c1:85:cc:dc:5c:69:3d:24:d8:55:5c:b2:08:d6:a8:14:13:07:69:9f:4a:f0:63:19:9d:78
+-----BEGIN CERTIFICATE-----
+MIIEJzCCAw+gAwIBAgIHAI4X/iQggTANBgkqhkiG9w0BAQsFADCBsTELMAkGA1UE
+BhMCVFIxDzANBgNVBAcMBkFua2FyYTFNMEsGA1UECgxEVMOcUktUUlVTVCBCaWxn
+aSDEsGxldGnFn2ltIHZlIEJpbGnFn2ltIEfDvHZlbmxpxJ9pIEhpem1ldGxlcmkg
+QS7Fni4xQjBABgNVBAMMOVTDnFJLVFJVU1QgRWxla3Ryb25payBTZXJ0aWZpa2Eg
+SGl6bWV0IFNhxJ9sYXnEsWPEsXPEsSBINTAeFw0xMzA0MzAwODA3MDFaFw0yMzA0
+MjgwODA3MDFaMIGxMQswCQYDVQQGEwJUUjEPMA0GA1UEBwwGQW5rYXJhMU0wSwYD
+VQQKDERUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8
+dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLjFCMEAGA1UEAww5VMOcUktUUlVTVCBF
+bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIEg1MIIB
+IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApCUZ4WWe60ghUEoI5RHwWrom
+/4NZzkQqL/7hzmAD/I0Dpe3/a6i6zDQGn1k19uwsu537jVJp45wnEFPzpALFp/kR
+Gml1bsMdi9GYjZOHp3GXDSHHmflS0yxjXVW86B8BSLlg/kJK9siArs1mep5Fimh3
+4khon6La8eHBEJ/rPCmBp+EyCNSgBbGM+42WAA4+Jd9ThiI7/PS98wl+d+yG6w8z
+5UNP9FR1bSmZLmZaQ9/LXMrI5Tjxfjs1nQ/0xVqhzPMggCTTV+wVunUlm+hkS7M0
+hO8EuPbJbKoCPrZV4jI3X/xml1/N1p7HIL9Nxqw/dV8c7TKcfGkAaZHjIxhT6QID
+AQABo0IwQDAdBgNVHQ4EFgQUVpkHHtOsDGlktAxQR95DLL4gwPswDgYDVR0PAQH/
+BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAJ5FdnsX
+SDLyOIspve6WSk6BGLFRRyDN0GSxDsnZAdkJzsiZ3GglE9Rc8qPoBP5yCccLqh0l
+VX6Wmle3usURehnmp349hQ71+S4pL+f5bFgWV1Al9j4uPqrtd3GqqpmWRgqujuwq
+URawXs3qZwQcWDD1YIq9pr1N5Za0/EKJAWv2cMhQOQwt1WbZyNKzMrcbGW3LM/nf
+peYVhDfwwvJllpKQd/Ct9JDpEXjXk4nAPQu6KfTomZ1yju2dL+6SfaHx/126M2CF
+Yv4HAqGEVka+lgqaE9chTLd8B59OTj+RdPsnnRHM3eaxynFNExc5JsUpISuTKWqW
++qtB4Uu2NQvAmxU=
+-----END CERTIFICATE-----
+
+# Issuer: CN=Certinomis - Root CA O=Certinomis OU=0002 433998903
+# Subject: CN=Certinomis - Root CA O=Certinomis OU=0002 433998903
+# Label: "Certinomis - Root CA"
+# Serial: 1
+# MD5 Fingerprint: 14:0a:fd:8d:a8:28:b5:38:69:db:56:7e:61:22:03:3f
+# SHA1 Fingerprint: 9d:70:bb:01:a5:a4:a0:18:11:2e:f7:1c:01:b9:32:c5:34:e7:88:a8
+# SHA256 Fingerprint: 2a:99:f5:bc:11:74:b7:3c:bb:1d:62:08:84:e0:1c:34:e5:1c:cb:39:78:da:12:5f:0e:33:26:88:83:bf:41:58
+-----BEGIN CERTIFICATE-----
+MIIFkjCCA3qgAwIBAgIBATANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJGUjET
+MBEGA1UEChMKQ2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxHTAb
+BgNVBAMTFENlcnRpbm9taXMgLSBSb290IENBMB4XDTEzMTAyMTA5MTcxOFoXDTMz
+MTAyMTA5MTcxOFowWjELMAkGA1UEBhMCRlIxEzARBgNVBAoTCkNlcnRpbm9taXMx
+FzAVBgNVBAsTDjAwMDIgNDMzOTk4OTAzMR0wGwYDVQQDExRDZXJ0aW5vbWlzIC0g
+Um9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANTMCQosP5L2
+fxSeC5yaah1AMGT9qt8OHgZbn1CF6s2Nq0Nn3rD6foCWnoR4kkjW4znuzuRZWJfl
+LieY6pOod5tK8O90gC3rMB+12ceAnGInkYjwSond3IjmFPnVAy//ldu9n+ws+hQV
+WZUKxkd8aRi5pwP5ynapz8dvtF4F/u7BUrJ1Mofs7SlmO/NKFoL21prbcpjp3vDF
+TKWrteoB4owuZH9kb/2jJZOLyKIOSY008B/sWEUuNKqEUL3nskoTuLAPrjhdsKkb
+5nPJWqHZZkCqqU2mNAKthH6yI8H7KsZn9DS2sJVqM09xRLWtwHkziOC/7aOgFLSc
+CbAK42C++PhmiM1b8XcF4LVzbsF9Ri6OSyemzTUK/eVNfaoqoynHWmgE6OXWk6Ri
+wsXm9E/G+Z8ajYJJGYrKWUM66A0ywfRMEwNvbqY/kXPLynNvEiCL7sCCeN5LLsJJ
+wx3tFvYk9CcbXFcx3FXuqB5vbKziRcxXV4p1VxngtViZSTYxPDMBbRZKzbgqg4SG
+m/lg0h9tkQPTYKbVPZrdd5A9NaSfD171UkRpucC63M9933zZxKyGIjK8e2uR73r4
+F2iw4lNVYC2vPsKD2NkJK/DAZNuHi5HMkesE/Xa0lZrmFAYb1TQdvtj/dBxThZng
+WVJKYe2InmtJiUZ+IFrZ50rlau7SZRFDAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIB
+BjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTvkUz1pcMw6C8I6tNxIqSSaHh0
+2TAfBgNVHSMEGDAWgBTvkUz1pcMw6C8I6tNxIqSSaHh02TANBgkqhkiG9w0BAQsF
+AAOCAgEAfj1U2iJdGlg+O1QnurrMyOMaauo++RLrVl89UM7g6kgmJs95Vn6RHJk/
+0KGRHCwPT5iVWVO90CLYiF2cN/z7ZMF4jIuaYAnq1fohX9B0ZedQxb8uuQsLrbWw
+F6YSjNRieOpWauwK0kDDPAUwPk2Ut59KA9N9J0u2/kTO+hkzGm2kQtHdzMjI1xZS
+g081lLMSVX3l4kLr5JyTCcBMWwerx20RoFAXlCOotQqSD7J6wWAsOMwaplv/8gzj
+qh8c3LigkyfeY+N/IZ865Z764BNqdeuWXGKRlI5nU7aJ+BIJy29SWwNyhlCVCNSN
+h4YVH5Uk2KRvms6knZtt0rJ2BobGVgjF6wnaNsIbW0G+YSrjcOa4pvi2WsS9Iff/
+ql+hbHY5ZtbqTFXhADObE5hjyW/QASAJN1LnDE8+zbz1X5YnpyACleAu6AdBBR8V
+btaw5BngDwKTACdyxYvRVB9dSsNAl35VpnzBMwQUAR1JIGkLGZOdblgi90AMRgwj
+Y/M50n92Uaf0yKHxDHYiI0ZSKS3io0EHVmmY0gUJvGnHWmHNj4FgFU2A3ZDifcRQ
+8ow7bkrHxuaAKzyBvBGAFhAn1/DNP3nMcyrDflOR1m749fPH0FFNjkulW+YZFzvW
+gQncItzujrnEj1PhZ7szuIgVRs/taTX/dQ1G885x4cVrhkIGuUE=
+-----END CERTIFICATE-----
+
+# Issuer: CN=OISTE WISeKey Global Root GB CA O=WISeKey OU=OISTE Foundation Endorsed
+# Subject: CN=OISTE WISeKey Global Root GB CA O=WISeKey OU=OISTE Foundation Endorsed
+# Label: "OISTE WISeKey Global Root GB CA"
+# Serial: 157768595616588414422159278966750757568
+# MD5 Fingerprint: a4:eb:b9:61:28:2e:b7:2f:98:b0:35:26:90:99:51:1d
+# SHA1 Fingerprint: 0f:f9:40:76:18:d3:d7:6a:4b:98:f0:a8:35:9e:0c:fd:27:ac:cc:ed
+# SHA256 Fingerprint: 6b:9c:08:e8:6e:b0:f7:67:cf:ad:65:cd:98:b6:21:49:e5:49:4a:67:f5:84:5e:7b:d1:ed:01:9f:27:b8:6b:d6
+-----BEGIN CERTIFICATE-----
+MIIDtTCCAp2gAwIBAgIQdrEgUnTwhYdGs/gjGvbCwDANBgkqhkiG9w0BAQsFADBt
+MQswCQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUg
+Rm91bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9i
+YWwgUm9vdCBHQiBDQTAeFw0xNDEyMDExNTAwMzJaFw0zOTEyMDExNTEwMzFaMG0x
+CzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQLExlPSVNURSBG
+b3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2Jh
+bCBSb290IEdCIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Be3
+HEokKtaXscriHvt9OO+Y9bI5mE4nuBFde9IllIiCFSZqGzG7qFshISvYD06fWvGx
+WuR51jIjK+FTzJlFXHtPrby/h0oLS5daqPZI7H17Dc0hBt+eFf1Biki3IPShehtX
+1F1Q/7pn2COZH8g/497/b1t3sWtuuMlk9+HKQUYOKXHQuSP8yYFfTvdv37+ErXNk
+u7dCjmn21HYdfp2nuFeKUWdy19SouJVUQHMD9ur06/4oQnc/nSMbsrY9gBQHTC5P
+99UKFg29ZkM3fiNDecNAhvVMKdqOmq0NpQSHiB6F4+lT1ZvIiwNjeOvgGUpuuy9r
+M2RYk61pv48b74JIxwIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUw
+AwEB/zAdBgNVHQ4EFgQUNQ/INmNe4qPs+TtmFc5RUuORmj0wEAYJKwYBBAGCNxUB
+BAMCAQAwDQYJKoZIhvcNAQELBQADggEBAEBM+4eymYGQfp3FsLAmzYh7KzKNbrgh
+cViXfa43FK8+5/ea4n32cZiZBKpDdHij40lhPnOMTZTg+XHEthYOU3gf1qKHLwI5
+gSk8rxWYITD+KJAAjNHhy/peyP34EEY7onhCkRd0VQreUGdNZtGn//3ZwLWoo4rO
+ZvUPQ82nK1d7Y0Zqqi5S2PTt4W2tKZB4SLrhI6qjiey1q5bAtEuiHZeeevJuQHHf
+aPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic
+Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM=
+-----END CERTIFICATE-----
+
+# Issuer: CN=SZAFIR ROOT CA2 O=Krajowa Izba Rozliczeniowa S.A.
+# Subject: CN=SZAFIR ROOT CA2 O=Krajowa Izba Rozliczeniowa S.A.
+# Label: "SZAFIR ROOT CA2"
+# Serial: 357043034767186914217277344587386743377558296292
+# MD5 Fingerprint: 11:64:c1:89:b0:24:b1:8c:b1:07:7e:89:9e:51:9e:99
+# SHA1 Fingerprint: e2:52:fa:95:3f:ed:db:24:60:bd:6e:28:f3:9c:cc:cf:5e:b3:3f:de
+# SHA256 Fingerprint: a1:33:9d:33:28:1a:0b:56:e5:57:d3:d3:2b:1c:e7:f9:36:7e:b0:94:bd:5f:a7:2a:7e:50:04:c8:de:d7:ca:fe
+-----BEGIN CERTIFICATE-----
+MIIDcjCCAlqgAwIBAgIUPopdB+xV0jLVt+O2XwHrLdzk1uQwDQYJKoZIhvcNAQEL
+BQAwUTELMAkGA1UEBhMCUEwxKDAmBgNVBAoMH0tyYWpvd2EgSXpiYSBSb3psaWN6
+ZW5pb3dhIFMuQS4xGDAWBgNVBAMMD1NaQUZJUiBST09UIENBMjAeFw0xNTEwMTkw
+NzQzMzBaFw0zNTEwMTkwNzQzMzBaMFExCzAJBgNVBAYTAlBMMSgwJgYDVQQKDB9L
+cmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMRgwFgYDVQQDDA9TWkFGSVIg
+Uk9PVCBDQTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3vD5QqEvN
+QLXOYeeWyrSh2gwisPq1e3YAd4wLz32ohswmUeQgPYUM1ljj5/QqGJ3a0a4m7utT
+3PSQ1hNKDJA8w/Ta0o4NkjrcsbH/ON7Dui1fgLkCvUqdGw+0w8LBZwPd3BucPbOw
+3gAeqDRHu5rr/gsUvTaE2g0gv/pby6kWIK05YO4vdbbnl5z5Pv1+TW9NL++IDWr6
+3fE9biCloBK0TXC5ztdyO4mTp4CEHCdJckm1/zuVnsHMyAHs6A6KCpbns6aH5db5
+BSsNl0BwPLqsdVqc1U2dAgrSS5tmS0YHF2Wtn2yIANwiieDhZNRnvDF5YTy7ykHN
+XGoAyDw4jlivAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD
+AgEGMB0GA1UdDgQWBBQuFqlKGLXLzPVvUPMjX/hd56zwyDANBgkqhkiG9w0BAQsF
+AAOCAQEAtXP4A9xZWx126aMqe5Aosk3AM0+qmrHUuOQn/6mWmc5G4G18TKI4pAZw
+8PRBEew/R40/cof5O/2kbytTAOD/OblqBw7rHRz2onKQy4I9EYKL0rufKq8h5mOG
+nXkZ7/e7DDWQw4rtTw/1zBLZpD67oPwglV9PJi8RI4NOdQcPv5vRtB3pEAT+ymCP
+oky4rc/hkA/NrgrHXXu3UNLUYfrVFdvXn4dRVOul4+vJhaAlIDf7js4MNIThPIGy
+d05DpYhfhmehPea0XGG2Ptv+tyjFogeutcrKjSoS75ftwjCkySp6+/NNIxuZMzSg
+LvWpCz/UXeHPhJ/iGcJfitYgHuNztw==
+-----END CERTIFICATE-----
+
+# Issuer: CN=Certum Trusted Network CA 2 O=Unizeto Technologies S.A. OU=Certum Certification Authority
+# Subject: CN=Certum Trusted Network CA 2 O=Unizeto Technologies S.A. OU=Certum Certification Authority
+# Label: "Certum Trusted Network CA 2"
+# Serial: 44979900017204383099463764357512596969
+# MD5 Fingerprint: 6d:46:9e:d9:25:6d:08:23:5b:5e:74:7d:1e:27:db:f2
+# SHA1 Fingerprint: d3:dd:48:3e:2b:bf:4c:05:e8:af:10:f5:fa:76:26:cf:d3:dc:30:92
+# SHA256 Fingerprint: b6:76:f2:ed:da:e8:77:5c:d3:6c:b0:f6:3c:d1:d4:60:39:61:f4:9e:62:65:ba:01:3a:2f:03:07:b6:d0:b8:04
+-----BEGIN CERTIFICATE-----
+MIIF0jCCA7qgAwIBAgIQIdbQSk8lD8kyN/yqXhKN6TANBgkqhkiG9w0BAQ0FADCB
+gDELMAkGA1UEBhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMu
+QS4xJzAlBgNVBAsTHkNlcnR1bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIG
+A1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0d29yayBDQSAyMCIYDzIwMTExMDA2MDgz
+OTU2WhgPMjA0NjEwMDYwODM5NTZaMIGAMQswCQYDVQQGEwJQTDEiMCAGA1UEChMZ
+VW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRp
+ZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtDZXJ0dW0gVHJ1c3RlZCBOZXR3
+b3JrIENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC9+Xj45tWA
+DGSdhhuWZGc/IjoedQF97/tcZ4zJzFxrqZHmuULlIEub2pt7uZld2ZuAS9eEQCsn
+0+i6MLs+CRqnSZXvK0AkwpfHp+6bJe+oCgCXhVqqndwpyeI1B+twTUrWwbNWuKFB
+OJvR+zF/j+Bf4bE/D44WSWDXBo0Y+aomEKsq09DRZ40bRr5HMNUuctHFY9rnY3lE
+fktjJImGLjQ/KUxSiyqnwOKRKIm5wFv5HdnnJ63/mgKXwcZQkpsCLL2puTRZCr+E
+Sv/f/rOf69me4Jgj7KZrdxYq28ytOxykh9xGc14ZYmhFV+SQgkK7QtbwYeDBoz1m
+o130GO6IyY0XRSmZMnUCMe4pJshrAua1YkV/NxVaI2iJ1D7eTiew8EAMvE0Xy02i
+sx7QBlrd9pPPV3WZ9fqGGmd4s7+W/jTcvedSVuWz5XV710GRBdxdaeOVDUO5/IOW
+OZV7bIBaTxNyxtd9KXpEulKkKtVBRgkg/iKgtlswjbyJDNXXcPiHUv3a76xRLgez
+Tv7QCdpw75j6VuZt27VXS9zlLCUVyJ4ueE742pyehizKV/Ma5ciSixqClnrDvFAS
+adgOWkaLOusm+iPJtrCBvkIApPjW/jAux9JG9uWOdf3yzLnQh1vMBhBgu4M1t15n
+3kfsmUjxpKEV/q2MYo45VU85FrmxY53/twIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
+AQH/MB0GA1UdDgQWBBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAOBgNVHQ8BAf8EBAMC
+AQYwDQYJKoZIhvcNAQENBQADggIBAHGlDs7k6b8/ONWJWsQCYftMxRQXLYtPU2sQ
+F/xlhMcQSZDe28cmk4gmb3DWAl45oPePq5a1pRNcgRRtDoGCERuKTsZPpd1iHkTf
+CVn0W3cLN+mLIMb4Ck4uWBzrM9DPhmDJ2vuAL55MYIR4PSFk1vtBHxgP58l1cb29
+XN40hz5BsA72udY/CROWFC/emh1auVbONTqwX3BNXuMp8SMoclm2q8KMZiYcdywm
+djWLKKdpoPk79SPdhRB0yZADVpHnr7pH1BKXESLjokmUbOe3lEu6LaTaM4tMpkT/
+WjzGHWTYtTHkpjx6qFcL2+1hGsvxznN3Y6SHb0xRONbkX8eftoEq5IVIeVheO/jb
+AoJnwTnbw3RLPTYe+SmTiGhbqEQZIfCn6IENLOiTNrQ3ssqwGyZ6miUfmpqAnksq
+P/ujmv5zMnHCnsZy4YpoJ/HkD7TETKVhk/iXEAcqMCWpuchxuO9ozC1+9eB+D4Ko
+b7a6bINDd82Kkhehnlt4Fj1F4jNy3eFmypnTycUm/Q1oBEauttmbjL4ZvrHG8hnj
+XALKLNhvSgfZyTXaQHXyxKcZb55CEJh15pWLYLztxRLXis7VmFxWlgPF7ncGNf/P
+5O4/E2Hu29othfDNrp2yGAlFw5Khchf8R7agCyzxxN5DaAhqXzvwdmP7zAYspsbi
+DrW5viSP
+-----END CERTIFICATE-----
+
+# Issuer: CN=Hellenic Academic and Research Institutions RootCA 2015 O=Hellenic Academic and Research Institutions Cert. Authority
+# Subject: CN=Hellenic Academic and Research Institutions RootCA 2015 O=Hellenic Academic and Research Institutions Cert. Authority
+# Label: "Hellenic Academic and Research Institutions RootCA 2015"
+# Serial: 0
+# MD5 Fingerprint: ca:ff:e2:db:03:d9:cb:4b:e9:0f:ad:84:fd:7b:18:ce
+# SHA1 Fingerprint: 01:0c:06:95:a6:98:19:14:ff:bf:5f:c6:b0:b6:95:ea:29:e9:12:a6
+# SHA256 Fingerprint: a0:40:92:9a:02:ce:53:b4:ac:f4:f2:ff:c6:98:1c:e4:49:6f:75:5e:6d:45:fe:0b:2a:69:2b:cd:52:52:3f:36
+-----BEGIN CERTIFICATE-----
+MIIGCzCCA/OgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBpjELMAkGA1UEBhMCR1Ix
+DzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5k
+IFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMT
+N0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9v
+dENBIDIwMTUwHhcNMTUwNzA3MTAxMTIxWhcNNDAwNjMwMTAxMTIxWjCBpjELMAkG
+A1UEBhMCR1IxDzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNh
+ZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkx
+QDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1
+dGlvbnMgUm9vdENBIDIwMTUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC
+AQDC+Kk/G4n8PDwEXT2QNrCROnk8ZlrvbTkBSRq0t89/TSNTt5AA4xMqKKYx8ZEA
+4yjsriFBzh/a/X0SWwGDD7mwX5nh8hKDgE0GPt+sr+ehiGsxr/CL0BgzuNtFajT0
+AoAkKAoCFZVedioNmToUW/bLy1O8E00BiDeUJRtCvCLYjqOWXjrZMts+6PAQZe10
+4S+nfK8nNLspfZu2zwnI5dMK/IhlZXQK3HMcXM1AsRzUtoSMTFDPaI6oWa7CJ06C
+ojXdFPQf/7J31Ycvqm59JCfnxssm5uX+Zwdj2EUN3TpZZTlYepKZcj2chF6IIbjV
+9Cz82XBST3i4vTwri5WY9bPRaM8gFH5MXF/ni+X1NYEZN9cRCLdmvtNKzoNXADrD
+gfgXy5I2XdGj2HUb4Ysn6npIQf1FGQatJ5lOwXBH3bWfgVMS5bGMSF0xQxfjjMZ6
+Y5ZLKTBOhE5iGV48zpeQpX8B653g+IuJ3SWYPZK2fu/Z8VFRfS0myGlZYeCsargq
+NhEEelC9MoS+L9xy1dcdFkfkR2YgP/SWxa+OAXqlD3pk9Q0Yh9muiNX6hME6wGko
+LfINaFGq46V3xqSQDqE3izEjR8EJCOtu93ib14L8hCCZSRm2Ekax+0VVFqmjZayc
+Bw/qa9wfLgZy7IaIEuQt218FL+TwA9MmM+eAws1CoRc0CwIDAQABo0IwQDAPBgNV
+HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUcRVnyMjJvXVd
+ctA4GGqd83EkVAswDQYJKoZIhvcNAQELBQADggIBAHW7bVRLqhBYRjTyYtcWNl0I
+XtVsyIe9tC5G8jH4fOpCtZMWVdyhDBKg2mF+D1hYc2Ryx+hFjtyp8iY/xnmMsVMI
+M4GwVhO+5lFc2JsKT0ucVlMC6U/2DWDqTUJV6HwbISHTGzrMd/K4kPFox/la/vot
+9L/J9UUbzjgQKjeKeaO04wlshYaT/4mWJ3iBj2fjRnRUjtkNaeJK9E10A/+yd+2V
+Z5fkscWrv2oj6NSU4kQoYsRL4vDY4ilrGnB+JGGTe08DMiUNRSQrlrRGar9KC/ea
+j8GsGsVn82800vpzY4zvFrCopEYq+OsS7HK07/grfoxSwIuEVPkvPuNVqNxmsdnh
+X9izjFk0WaSrT2y7HxjbdavYy5LNlDhhDgcGH0tGEPEVvo2FXDtKK4F5D7Rpn0lQ
+l033DlZdwJVqwjbDG2jJ9SrcR5q+ss7FJej6A7na+RZukYT1HCjI/CbM1xyQVqdf
+bzoEvM14iQuODy+jqk+iGxI9FghAD/FGTNeqewjBCvVtJ94Cj8rDtSvK6evIIVM4
+pcw72Hc3MKJP2W/R8kCtQXoXxdZKNYm3QdV8hn9VTYNKpXMgwDqvkPGaJI7ZjnHK
+e7iG2rKPmT4dEw0SEe7Uq/DpFXYC5ODfqiAeW2GFZECpkJcNrVPSWh2HagCXZWK0
+vm9qp/UsQu0yrbYhnr68
+-----END CERTIFICATE-----
+
+# Issuer: CN=Hellenic Academic and Research Institutions ECC RootCA 2015 O=Hellenic Academic and Research Institutions Cert. Authority
+# Subject: CN=Hellenic Academic and Research Institutions ECC RootCA 2015 O=Hellenic Academic and Research Institutions Cert. Authority
+# Label: "Hellenic Academic and Research Institutions ECC RootCA 2015"
+# Serial: 0
+# MD5 Fingerprint: 81:e5:b4:17:eb:c2:f5:e1:4b:0d:41:7b:49:92:fe:ef
+# SHA1 Fingerprint: 9f:f1:71:8d:92:d5:9a:f3:7d:74:97:b4:bc:6f:84:68:0b:ba:b6:66
+# SHA256 Fingerprint: 44:b5:45:aa:8a:25:e6:5a:73:ca:15:dc:27:fc:36:d2:4c:1c:b9:95:3a:06:65:39:b1:15:82:dc:48:7b:48:33
+-----BEGIN CERTIFICATE-----
+MIICwzCCAkqgAwIBAgIBADAKBggqhkjOPQQDAjCBqjELMAkGA1UEBhMCR1IxDzAN
+BgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl
+c2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxRDBCBgNVBAMTO0hl
+bGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgRUNDIFJv
+b3RDQSAyMDE1MB4XDTE1MDcwNzEwMzcxMloXDTQwMDYzMDEwMzcxMlowgaoxCzAJ
+BgNVBAYTAkdSMQ8wDQYDVQQHEwZBdGhlbnMxRDBCBgNVBAoTO0hlbGxlbmljIEFj
+YWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9yaXR5
+MUQwQgYDVQQDEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0
+dXRpb25zIEVDQyBSb290Q0EgMjAxNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABJKg
+QehLgoRc4vgxEZmGZE4JJS+dQS8KrjVPdJWyUWRrjWvmP3CV8AVER6ZyOFB2lQJa
+jq4onvktTpnvLEhvTCUp6NFxW98dwXU3tNf6e3pCnGoKVlp8aQuqgAkkbH7BRqNC
+MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFLQi
+C4KZJAEOnLvkDv2/+5cgk5kqMAoGCCqGSM49BAMCA2cAMGQCMGfOFmI4oqxiRaep
+lSTAGiecMjvAwNW6qef4BENThe5SId6d9SWDPp5YSy/XZxMOIQIwBeF1Ad5o7Sof
+TUwJCA3sS61kFyjndc5FZXIhF8siQQ6ME5g4mlRtm8rifOoCWCKR
+-----END CERTIFICATE-----
+
+# Issuer: CN=Certplus Root CA G1 O=Certplus
+# Subject: CN=Certplus Root CA G1 O=Certplus
+# Label: "Certplus Root CA G1"
+# Serial: 1491911565779898356709731176965615564637713
+# MD5 Fingerprint: 7f:09:9c:f7:d9:b9:5c:69:69:56:d5:37:3e:14:0d:42
+# SHA1 Fingerprint: 22:fd:d0:b7:fd:a2:4e:0d:ac:49:2c:a0:ac:a6:7b:6a:1f:e3:f7:66
+# SHA256 Fingerprint: 15:2a:40:2b:fc:df:2c:d5:48:05:4d:22:75:b3:9c:7f:ca:3e:c0:97:80:78:b0:f0:ea:76:e5:61:a6:c7:43:3e
+-----BEGIN CERTIFICATE-----
+MIIFazCCA1OgAwIBAgISESBVg+QtPlRWhS2DN7cs3EYRMA0GCSqGSIb3DQEBDQUA
+MD4xCzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2Vy
+dHBsdXMgUm9vdCBDQSBHMTAeFw0xNDA1MjYwMDAwMDBaFw0zODAxMTUwMDAwMDBa
+MD4xCzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2Vy
+dHBsdXMgUm9vdCBDQSBHMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB
+ANpQh7bauKk+nWT6VjOaVj0W5QOVsjQcmm1iBdTYj+eJZJ+622SLZOZ5KmHNr49a
+iZFluVj8tANfkT8tEBXgfs+8/H9DZ6itXjYj2JizTfNDnjl8KvzsiNWI7nC9hRYt
+6kuJPKNxQv4c/dMcLRC4hlTqQ7jbxofaqK6AJc96Jh2qkbBIb6613p7Y1/oA/caP
+0FG7Yn2ksYyy/yARujVjBYZHYEMzkPZHogNPlk2dT8Hq6pyi/jQu3rfKG3akt62f
+6ajUeD94/vI4CTYd0hYCyOwqaK/1jpTvLRN6HkJKHRUxrgwEV/xhc/MxVoYxgKDE
+EW4wduOU8F8ExKyHcomYxZ3MVwia9Az8fXoFOvpHgDm2z4QTd28n6v+WZxcIbekN
+1iNQMLAVdBM+5S//Ds3EC0pd8NgAM0lm66EYfFkuPSi5YXHLtaW6uOrc4nBvCGrc
+h2c0798wct3zyT8j/zXhviEpIDCB5BmlIOklynMxdCm+4kLV87ImZsdo/Rmz5yCT
+mehd4F6H50boJZwKKSTUzViGUkAksnsPmBIgJPaQbEfIDbsYIC7Z/fyL8inqh3SV
+4EJQeIQEQWGw9CEjjy3LKCHyamz0GqbFFLQ3ZU+V/YDI+HLlJWvEYLF7bY5KinPO
+WftwenMGE9nTdDckQQoRb5fc5+R+ob0V8rqHDz1oihYHAgMBAAGjYzBhMA4GA1Ud
+DwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSowcCbkahDFXxd
+Bie0KlHYlwuBsTAfBgNVHSMEGDAWgBSowcCbkahDFXxdBie0KlHYlwuBsTANBgkq
+hkiG9w0BAQ0FAAOCAgEAnFZvAX7RvUz1isbwJh/k4DgYzDLDKTudQSk0YcbX8ACh
+66Ryj5QXvBMsdbRX7gp8CXrc1cqh0DQT+Hern+X+2B50ioUHj3/MeXrKls3N/U/7
+/SMNkPX0XtPGYX2eEeAC7gkE2Qfdpoq3DIMku4NQkv5gdRE+2J2winq14J2by5BS
+S7CTKtQ+FjPlnsZlFT5kOwQ/2wyPX1wdaR+v8+khjPPvl/aatxm2hHSco1S1cE5j
+2FddUyGbQJJD+tZ3VTNPZNX70Cxqjm0lpu+F6ALEUz65noe8zDUa3qHpimOHZR4R
+Kttjd5cUvpoUmRGywO6wT/gUITJDT5+rosuoD6o7BlXGEilXCNQ314cnrUlZp5Gr
+RHpejXDbl85IULFzk/bwg2D5zfHhMf1bfHEhYxQUqq/F3pN+aLHsIqKqkHWetUNy
+6mSjhEv9DKgma3GX7lZjZuhCVPnHHd/Qj1vfyDBviP4NxDMcU6ij/UgQ8uQKTuEV
+V/xuZDDCVRHc6qnNSlSsKWNEz0pAoNZoWRsz+e86i9sgktxChL8Bq4fA1SCC28a5
+g4VCXA9DO2pJNdWY9BW/+mGBDAkgGNLQFwzLSABQ6XaCjGTXOqAHVcweMcDvOrRl
+++O/QmueD6i9a5jc2NvLi6Td11n0bt3+qsOR0C5CB8AMTVPNJLFMWx5R9N/pkvo=
+-----END CERTIFICATE-----
+
+# Issuer: CN=Certplus Root CA G2 O=Certplus
+# Subject: CN=Certplus Root CA G2 O=Certplus
+# Label: "Certplus Root CA G2"
+# Serial: 1492087096131536844209563509228951875861589
+# MD5 Fingerprint: a7:ee:c4:78:2d:1b:ee:2d:b9:29:ce:d6:a7:96:32:31
+# SHA1 Fingerprint: 4f:65:8e:1f:e9:06:d8:28:02:e9:54:47:41:c9:54:25:5d:69:cc:1a
+# SHA256 Fingerprint: 6c:c0:50:41:e6:44:5e:74:69:6c:4c:fb:c9:f8:0f:54:3b:7e:ab:bb:44:b4:ce:6f:78:7c:6a:99:71:c4:2f:17
+-----BEGIN CERTIFICATE-----
+MIICHDCCAaKgAwIBAgISESDZkc6uo+jF5//pAq/Pc7xVMAoGCCqGSM49BAMDMD4x
+CzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBs
+dXMgUm9vdCBDQSBHMjAeFw0xNDA1MjYwMDAwMDBaFw0zODAxMTUwMDAwMDBaMD4x
+CzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBs
+dXMgUm9vdCBDQSBHMjB2MBAGByqGSM49AgEGBSuBBAAiA2IABM0PW1aC3/BFGtat
+93nwHcmsltaeTpwftEIRyoa/bfuFo8XlGVzX7qY/aWfYeOKmycTbLXku54uNAm8x
+Ik0G42ByRZ0OQneezs/lf4WbGOT8zC5y0xaTTsqZY1yhBSpsBqNjMGEwDgYDVR0P
+AQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNqDYwJ5jtpMxjwj
+FNiPwyCrKGBZMB8GA1UdIwQYMBaAFNqDYwJ5jtpMxjwjFNiPwyCrKGBZMAoGCCqG
+SM49BAMDA2gAMGUCMHD+sAvZ94OX7PNVHdTcswYO/jOYnYs5kGuUIe22113WTNch
+p+e/IQ8rzfcq3IUHnQIxAIYUFuXcsGXCwI4Un78kFmjlvPl5adytRSv3tjFzzAal
+U5ORGpOucGpnutee5WEaXw==
+-----END CERTIFICATE-----
+
+# Issuer: CN=OpenTrust Root CA G1 O=OpenTrust
+# Subject: CN=OpenTrust Root CA G1 O=OpenTrust
+# Label: "OpenTrust Root CA G1"
+# Serial: 1492036577811947013770400127034825178844775
+# MD5 Fingerprint: 76:00:cc:81:29:cd:55:5e:88:6a:7a:2e:f7:4d:39:da
+# SHA1 Fingerprint: 79:91:e8:34:f7:e2:ee:dd:08:95:01:52:e9:55:2d:14:e9:58:d5:7e
+# SHA256 Fingerprint: 56:c7:71:28:d9:8c:18:d9:1b:4c:fd:ff:bc:25:ee:91:03:d4:75:8e:a2:ab:ad:82:6a:90:f3:45:7d:46:0e:b4
+-----BEGIN CERTIFICATE-----
+MIIFbzCCA1egAwIBAgISESCzkFU5fX82bWTCp59rY45nMA0GCSqGSIb3DQEBCwUA
+MEAxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9w
+ZW5UcnVzdCBSb290IENBIEcxMB4XDTE0MDUyNjA4NDU1MFoXDTM4MDExNTAwMDAw
+MFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCU9wZW5UcnVzdDEdMBsGA1UEAwwU
+T3BlblRydXN0IFJvb3QgQ0EgRzEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK
+AoICAQD4eUbalsUwXopxAy1wpLuwxQjczeY1wICkES3d5oeuXT2R0odsN7faYp6b
+wiTXj/HbpqbfRm9RpnHLPhsxZ2L3EVs0J9V5ToybWL0iEA1cJwzdMOWo010hOHQX
+/uMftk87ay3bfWAfjH1MBcLrARYVmBSO0ZB3Ij/swjm4eTrwSSTilZHcYTSSjFR0
+77F9jAHiOH3BX2pfJLKOYheteSCtqx234LSWSE9mQxAGFiQD4eCcjsZGT44ameGP
+uY4zbGneWK2gDqdkVBFpRGZPTBKnjix9xNRbxQA0MMHZmf4yzgeEtE7NCv82TWLx
+p2NX5Ntqp66/K7nJ5rInieV+mhxNaMbBGN4zK1FGSxyO9z0M+Yo0FMT7MzUj8czx
+Kselu7Cizv5Ta01BG2Yospb6p64KTrk5M0ScdMGTHPjgniQlQ/GbI4Kq3ywgsNw2
+TgOzfALU5nsaqocTvz6hdLubDuHAk5/XpGbKuxs74zD0M1mKB3IDVedzagMxbm+W
+G+Oin6+Sx+31QrclTDsTBM8clq8cIqPQqwWyTBIjUtz9GVsnnB47ev1CI9sjgBPw
+vFEVVJSmdz7QdFG9URQIOTfLHzSpMJ1ShC5VkLG631UAC9hWLbFJSXKAqWLXwPYY
+EQRVzXR7z2FwefR7LFxckvzluFqrTJOVoSfupb7PcSNCupt2LQIDAQABo2MwYTAO
+BgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUl0YhVyE1
+2jZVx/PxN3DlCPaTKbYwHwYDVR0jBBgwFoAUl0YhVyE12jZVx/PxN3DlCPaTKbYw
+DQYJKoZIhvcNAQELBQADggIBAB3dAmB84DWn5ph76kTOZ0BP8pNuZtQ5iSas000E
+PLuHIT839HEl2ku6q5aCgZG27dmxpGWX4m9kWaSW7mDKHyP7Rbr/jyTwyqkxf3kf
+gLMtMrpkZ2CvuVnN35pJ06iCsfmYlIrM4LvgBBuZYLFGZdwIorJGnkSI6pN+VxbS
+FXJfLkur1J1juONI5f6ELlgKn0Md/rcYkoZDSw6cMoYsYPXpSOqV7XAp8dUv/TW0
+V8/bhUiZucJvbI/NeJWsZCj9VrDDb8O+WVLhX4SPgPL0DTatdrOjteFkdjpY3H1P
+XlZs5VVZV6Xf8YpmMIzUUmI4d7S+KNfKNsSbBfD4Fdvb8e80nR14SohWZ25g/4/I
+i+GOvUKpMwpZQhISKvqxnUOOBZuZ2mKtVzazHbYNeS2WuOvyDEsMpZTGMKcmGS3t
+TAZQMPH9WD25SxdfGbRqhFS0OE85og2WaMMolP3tLR9Ka0OWLpABEPs4poEL0L91
+09S5zvE/bw4cHjdx5RiHdRk/ULlepEU0rbDK5uUTdg8xFKmOLZTW1YVNcxVPS/Ky
+Pu1svf0OnWZzsD2097+o4BGkxK51CUpjAEggpsadCwmKtODmzj7HPiY46SvepghJ
+AwSQiumPv+i2tCqjI40cHLI5kqiPAlxAOXXUc0ECd97N4EOH1uS6SsNsEn/+KuYj
+1oxx
+-----END CERTIFICATE-----
+
+# Issuer: CN=OpenTrust Root CA G2 O=OpenTrust
+# Subject: CN=OpenTrust Root CA G2 O=OpenTrust
+# Label: "OpenTrust Root CA G2"
+# Serial: 1492012448042702096986875987676935573415441
+# MD5 Fingerprint: 57:24:b6:59:24:6b:ae:c8:fe:1c:0c:20:f2:c0:4e:eb
+# SHA1 Fingerprint: 79:5f:88:60:c5:ab:7c:3d:92:e6:cb:f4:8d:e1:45:cd:11:ef:60:0b
+# SHA256 Fingerprint: 27:99:58:29:fe:6a:75:15:c1:bf:e8:48:f9:c4:76:1d:b1:6c:22:59:29:25:7b:f4:0d:08:94:f2:9e:a8:ba:f2
+-----BEGIN CERTIFICATE-----
+MIIFbzCCA1egAwIBAgISESChaRu/vbm9UpaPI+hIvyYRMA0GCSqGSIb3DQEBDQUA
+MEAxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9w
+ZW5UcnVzdCBSb290IENBIEcyMB4XDTE0MDUyNjAwMDAwMFoXDTM4MDExNTAwMDAw
+MFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCU9wZW5UcnVzdDEdMBsGA1UEAwwU
+T3BlblRydXN0IFJvb3QgQ0EgRzIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK
+AoICAQDMtlelM5QQgTJT32F+D3Y5z1zCU3UdSXqWON2ic2rxb95eolq5cSG+Ntmh
+/LzubKh8NBpxGuga2F8ORAbtp+Dz0mEL4DKiltE48MLaARf85KxP6O6JHnSrT78e
+CbY2albz4e6WiWYkBuTNQjpK3eCasMSCRbP+yatcfD7J6xcvDH1urqWPyKwlCm/6
+1UWY0jUJ9gNDlP7ZvyCVeYCYitmJNbtRG6Q3ffyZO6v/v6wNj0OxmXsWEH4db0fE
+FY8ElggGQgT4hNYdvJGmQr5J1WqIP7wtUdGejeBSzFfdNTVY27SPJIjki9/ca1TS
+gSuyzpJLHB9G+h3Ykst2Z7UJmQnlrBcUVXDGPKBWCgOz3GIZ38i1MH/1PCZ1Eb3X
+G7OHngevZXHloM8apwkQHZOJZlvoPGIytbU6bumFAYueQ4xncyhZW+vj3CzMpSZy
+YhK05pyDRPZRpOLAeiRXyg6lPzq1O4vldu5w5pLeFlwoW5cZJ5L+epJUzpM5ChaH
+vGOz9bGTXOBut9Dq+WIyiET7vycotjCVXRIouZW+j1MY5aIYFuJWpLIsEPUdN6b4
+t/bQWVyJ98LVtZR00dX+G7bw5tYee9I8y6jj9RjzIR9u701oBnstXW5DiabA+aC/
+gh7PU3+06yzbXfZqfUAkBXKJOAGTy3HCOV0GEfZvePg3DTmEJwIDAQABo2MwYTAO
+BgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUajn6QiL3
+5okATV59M4PLuG53hq8wHwYDVR0jBBgwFoAUajn6QiL35okATV59M4PLuG53hq8w
+DQYJKoZIhvcNAQENBQADggIBAJjLq0A85TMCl38th6aP1F5Kr7ge57tx+4BkJamz
+Gj5oXScmp7oq4fBXgwpkTx4idBvpkF/wrM//T2h6OKQQbA2xx6R3gBi2oihEdqc0
+nXGEL8pZ0keImUEiyTCYYW49qKgFbdEfwFFEVn8nNQLdXpgKQuswv42hm1GqO+qT
+RmTFAHneIWv2V6CG1wZy7HBGS4tz3aAhdT7cHcCP009zHIXZ/n9iyJVvttN7jLpT
+wm+bREx50B1ws9efAvSyB7DH5fitIw6mVskpEndI2S9G/Tvw/HRwkqWOOAgfZDC2
+t0v7NqwQjqBSM2OdAzVWxWm9xiNaJ5T2pBL4LTM8oValX9YZ6e18CL13zSdkzJTa
+TkZQh+D5wVOAHrut+0dSixv9ovneDiK3PTNZbNTe9ZUGMg1RGUFcPk8G97krgCf2
+o6p6fAbhQ8MTOWIaNr3gKC6UAuQpLmBVrkA9sHSSXvAgZJY/X0VdiLWK2gKgW0VU
+3jg9CcCoSmVGFvyqv1ROTVu+OEO3KMqLM6oaJbolXCkvW0pujOotnCr2BXbgd5eA
+iN1nE28daCSLT7d0geX0YJ96Vdc+N9oWaz53rK4YcJUIeSkDiv7BO7M/Gg+kO14f
+WKGVyasvc0rQLW6aWQ9VGHgtPFGml4vmu7JwqkwR3v98KzfUetF3NI/n+UL3PIEM
+S1IK
+-----END CERTIFICATE-----
+
+# Issuer: CN=OpenTrust Root CA G3 O=OpenTrust
+# Subject: CN=OpenTrust Root CA G3 O=OpenTrust
+# Label: "OpenTrust Root CA G3"
+# Serial: 1492104908271485653071219941864171170455615
+# MD5 Fingerprint: 21:37:b4:17:16:92:7b:67:46:70:a9:96:d7:a8:13:24
+# SHA1 Fingerprint: 6e:26:64:f3:56:bf:34:55:bf:d1:93:3f:7c:01:de:d8:13:da:8a:a6
+# SHA256 Fingerprint: b7:c3:62:31:70:6e:81:07:8c:36:7c:b8:96:19:8f:1e:32:08:dd:92:69:49:dd:8f:57:09:a4:10:f7:5b:62:92
+-----BEGIN CERTIFICATE-----
+MIICITCCAaagAwIBAgISESDm+Ez8JLC+BUCs2oMbNGA/MAoGCCqGSM49BAMDMEAx
+CzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9wZW5U
+cnVzdCBSb290IENBIEczMB4XDTE0MDUyNjAwMDAwMFoXDTM4MDExNTAwMDAwMFow
+QDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCU9wZW5UcnVzdDEdMBsGA1UEAwwUT3Bl
+blRydXN0IFJvb3QgQ0EgRzMwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARK7liuTcpm
+3gY6oxH84Bjwbhy6LTAMidnW7ptzg6kjFYwvWYpa3RTqnVkrQ7cG7DK2uu5Bta1d
+oYXM6h0UZqNnfkbilPPntlahFVmhTzeXuSIevRHr9LIfXsMUmuXZl5mjYzBhMA4G
+A1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRHd8MUi2I5
+DMlv4VBN0BBY3JWIbTAfBgNVHSMEGDAWgBRHd8MUi2I5DMlv4VBN0BBY3JWIbTAK
+BggqhkjOPQQDAwNpADBmAjEAj6jcnboMBBf6Fek9LykBl7+BFjNAk2z8+e2AcG+q
+j9uEwov1NcoG3GRvaBbhj5G5AjEA2Euly8LQCGzpGPta3U1fJAuwACEl74+nBCZx
+4nxp5V2a+EEfOzmTk51V6s2N8fvB
+-----END CERTIFICATE-----
+
+# Issuer: CN=ISRG Root X1 O=Internet Security Research Group
+# Subject: CN=ISRG Root X1 O=Internet Security Research Group
+# Label: "ISRG Root X1"
+# Serial: 172886928669790476064670243504169061120
+# MD5 Fingerprint: 0c:d2:f9:e0:da:17:73:e9:ed:86:4d:a5:e3:70:e7:4e
+# SHA1 Fingerprint: ca:bd:2a:79:a1:07:6a:31:f2:1d:25:36:35:cb:03:9d:43:29:a5:e8
+# SHA256 Fingerprint: 96:bc:ec:06:26:49:76:f3:74:60:77:9a:cf:28:c5:a7:cf:e8:a3:c0:aa:e1:1a:8f:fc:ee:05:c0:bd:df:08:c6
+-----BEGIN CERTIFICATE-----
+MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw
+TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
+cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4
+WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu
+ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY
+MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc
+h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+
+0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U
+A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW
+T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH
+B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC
+B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv
+KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn
+OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn
+jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw
+qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI
+rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
+HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq
+hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
+ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ
+3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK
+NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5
+ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur
+TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC
+jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc
+oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq
+4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA
+mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d
+emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=
+-----END CERTIFICATE-----
+
+# Issuer: O=FNMT-RCM OU=AC RAIZ FNMT-RCM
+# Subject: O=FNMT-RCM OU=AC RAIZ FNMT-RCM
+# Label: "AC RAIZ FNMT-RCM"
+# Serial: 485876308206448804701554682760554759
+# MD5 Fingerprint: e2:09:04:b4:d3:bd:d1:a0:14:fd:1a:d2:47:c4:57:1d
+# SHA1 Fingerprint: ec:50:35:07:b2:15:c4:95:62:19:e2:a8:9a:5b:42:99:2c:4c:2c:20
+# SHA256 Fingerprint: eb:c5:57:0c:29:01:8c:4d:67:b1:aa:12:7b:af:12:f7:03:b4:61:1e:bc:17:b7:da:b5:57:38:94:17:9b:93:fa
+-----BEGIN CERTIFICATE-----
+MIIFgzCCA2ugAwIBAgIPXZONMGc2yAYdGsdUhGkHMA0GCSqGSIb3DQEBCwUAMDsx
+CzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJ
+WiBGTk1ULVJDTTAeFw0wODEwMjkxNTU5NTZaFw0zMDAxMDEwMDAwMDBaMDsxCzAJ
+BgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBG
+Tk1ULVJDTTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALpxgHpMhm5/
+yBNtwMZ9HACXjywMI7sQmkCpGreHiPibVmr75nuOi5KOpyVdWRHbNi63URcfqQgf
+BBckWKo3Shjf5TnUV/3XwSyRAZHiItQDwFj8d0fsjz50Q7qsNI1NOHZnjrDIbzAz
+WHFctPVrbtQBULgTfmxKo0nRIBnuvMApGGWn3v7v3QqQIecaZ5JCEJhfTzC8PhxF
+tBDXaEAUwED653cXeuYLj2VbPNmaUtu1vZ5Gzz3rkQUCwJaydkxNEJY7kvqcfw+Z
+374jNUUeAlz+taibmSXaXvMiwzn15Cou08YfxGyqxRxqAQVKL9LFwag0Jl1mpdIC
+IfkYtwb1TplvqKtMUejPUBjFd8g5CSxJkjKZqLsXF3mwWsXmo8RZZUc1g16p6DUL
+mbvkzSDGm0oGObVo/CK67lWMK07q87Hj/LaZmtVC+nFNCM+HHmpxffnTtOmlcYF7
+wk5HlqX2doWjKI/pgG6BU6VtX7hI+cL5NqYuSf+4lsKMB7ObiFj86xsc3i1w4peS
+MKGJ47xVqCfWS+2QrYv6YyVZLag13cqXM7zlzced0ezvXg5KkAYmY6252TUtB7p2
+ZSysV4999AeU14ECll2jB0nVetBX+RvnU0Z1qrB5QstocQjpYL05ac70r8NWQMet
+UqIJ5G+GR4of6ygnXYMgrwTJbFaai0b1AgMBAAGjgYMwgYAwDwYDVR0TAQH/BAUw
+AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFPd9xf3E6Jobd2Sn9R2gzL+H
+YJptMD4GA1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1odHRwOi8vd3d3
+LmNlcnQuZm5tdC5lcy9kcGNzLzANBgkqhkiG9w0BAQsFAAOCAgEAB5BK3/MjTvDD
+nFFlm5wioooMhfNzKWtN/gHiqQxjAb8EZ6WdmF/9ARP67Jpi6Yb+tmLSbkyU+8B1
+RXxlDPiyN8+sD8+Nb/kZ94/sHvJwnvDKuO+3/3Y3dlv2bojzr2IyIpMNOmqOFGYM
+LVN0V2Ue1bLdI4E7pWYjJ2cJj+F3qkPNZVEI7VFY/uY5+ctHhKQV8Xa7pO6kO8Rf
+77IzlhEYt8llvhjho6Tc+hj507wTmzl6NLrTQfv6MooqtyuGC2mDOL7Nii4LcK2N
+JpLuHvUBKwrZ1pebbuCoGRw6IYsMHkCtA+fdZn71uSANA+iW+YJF1DngoABd15jm
+fZ5nc8OaKveri6E6FO80vFIOiZiaBECEHX5FaZNXzuvO+FB8TxxuBEOb+dY7Ixjp
+6o7RTUaN8Tvkasq6+yO3m/qZASlaWFot4/nUbQ4mrcFuNLwy+AwF+mWj2zs3gyLp
+1txyM/1d8iC9djwj2ij3+RvrWWTV3F9yfiD8zYm1kGdNYno/Tq0dwzn+evQoFt9B
+9kiABdcPUXmsEKvU7ANm5mqwujGSQkBqvjrTcuFqN1W8rB2Vt2lh8kORdOag0wok
+RqEIr9baRRmW1FMdW4R58MD3R++Lj8UGrp1MYp3/RgT408m2ECVAdf4WqslKYIYv
+uu8wd+RU4riEmViAqhOLUTpPSPaLtrM=
+-----END CERTIFICATE-----
+
+# Issuer: CN=Amazon Root CA 1 O=Amazon
+# Subject: CN=Amazon Root CA 1 O=Amazon
+# Label: "Amazon Root CA 1"
+# Serial: 143266978916655856878034712317230054538369994
+# MD5 Fingerprint: 43:c6:bf:ae:ec:fe:ad:2f:18:c6:88:68:30:fc:c8:e6
+# SHA1 Fingerprint: 8d:a7:f9:65:ec:5e:fc:37:91:0f:1c:6e:59:fd:c1:cc:6a:6e:de:16
+# SHA256 Fingerprint: 8e:cd:e6:88:4f:3d:87:b1:12:5b:a3:1a:c3:fc:b1:3d:70:16:de:7f:57:cc:90:4f:e1:cb:97:c6:ae:98:19:6e
+-----BEGIN CERTIFICATE-----
+MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF
+ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6
+b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL
+MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv
+b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj
+ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM
+9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw
+IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6
+VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L
+93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm
+jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA
+A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI
+U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs
+N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv
+o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU
+5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy
+rqXRfboQnoZsG4q5WTP468SQvvG5
+-----END CERTIFICATE-----
+
+# Issuer: CN=Amazon Root CA 2 O=Amazon
+# Subject: CN=Amazon Root CA 2 O=Amazon
+# Label: "Amazon Root CA 2"
+# Serial: 143266982885963551818349160658925006970653239
+# MD5 Fingerprint: c8:e5:8d:ce:a8:42:e2:7a:c0:2a:5c:7c:9e:26:bf:66
+# SHA1 Fingerprint: 5a:8c:ef:45:d7:a6:98:59:76:7a:8c:8b:44:96:b5:78:cf:47:4b:1a
+# SHA256 Fingerprint: 1b:a5:b2:aa:8c:65:40:1a:82:96:01:18:f8:0b:ec:4f:62:30:4d:83:ce:c4:71:3a:19:c3:9c:01:1e:a4:6d:b4
+-----BEGIN CERTIFICATE-----
+MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwF
+ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6
+b24gUm9vdCBDQSAyMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTEL
+MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv
+b3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK2Wny2cSkxK
+gXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4kHbZ
+W0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg
+1dKmSYXpN+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K
+8nu+NQWpEjTj82R0Yiw9AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r
+2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvdfLC6HM783k81ds8P+HgfajZRRidhW+me
+z/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAExkv8LV/SasrlX6avvDXbR
+8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSSbtqDT6Zj
+mUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz
+7Mt0Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6
++XUyo05f7O0oYtlNc/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI
+0u1ufm8/0i2BWSlmy5A5lREedCf+3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMB
+Af8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSwDPBMMPQFWAJI/TPlUq9LhONm
+UjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oAA7CXDpO8Wqj2
+LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY
++gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kS
+k5Nrp+gvU5LEYFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl
+7uxMMne0nxrpS10gxdr9HIcWxkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygm
+btmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQgj9sAq+uEjonljYE1x2igGOpm/Hl
+urR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbWaQbLU8uz/mtBzUF+
+fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoVYh63
+n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE
+76KlXIx3KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H
+9jVlpNMKVv/1F2Rs76giJUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT
+4PsJYGw=
+-----END CERTIFICATE-----
+
+# Issuer: CN=Amazon Root CA 3 O=Amazon
+# Subject: CN=Amazon Root CA 3 O=Amazon
+# Label: "Amazon Root CA 3"
+# Serial: 143266986699090766294700635381230934788665930
+# MD5 Fingerprint: a0:d4:ef:0b:f7:b5:d8:49:95:2a:ec:f5:c4:fc:81:87
+# SHA1 Fingerprint: 0d:44:dd:8c:3c:8c:1a:1a:58:75:64:81:e9:0f:2e:2a:ff:b3:d2:6e
+# SHA256 Fingerprint: 18:ce:6c:fe:7b:f1:4e:60:b2:e3:47:b8:df:e8:68:cb:31:d0:2e:bb:3a:da:27:15:69:f5:03:43:b4:6d:b3:a4
+-----BEGIN CERTIFICATE-----
+MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5
+MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g
+Um9vdCBDQSAzMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG
+A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg
+Q0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZBf8ANm+gBG1bG8lKl
+ui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjrZt6j
+QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSr
+ttvXBp43rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkr
+BqWTrBqYaGFy+uGh0PsceGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteM
+YyRIHN8wfdVoOw==
+-----END CERTIFICATE-----
+
+# Issuer: CN=Amazon Root CA 4 O=Amazon
+# Subject: CN=Amazon Root CA 4 O=Amazon
+# Label: "Amazon Root CA 4"
+# Serial: 143266989758080763974105200630763877849284878
+# MD5 Fingerprint: 89:bc:27:d5:eb:17:8d:06:6a:69:d5:fd:89:47:b4:cd
+# SHA1 Fingerprint: f6:10:84:07:d6:f8:bb:67:98:0c:c2:e2:44:c2:eb:ae:1c:ef:63:be
+# SHA256 Fingerprint: e3:5d:28:41:9e:d0:20:25:cf:a6:90:38:cd:62:39:62:45:8d:a5:c6:95:fb:de:a3:c2:2b:0b:fb:25:89:70:92
+-----BEGIN CERTIFICATE-----
+MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5
+MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g
+Um9vdCBDQSA0MB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG
+A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg
+Q0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN/sGKe0uoe0ZLY7Bi
+9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri83Bk
+M6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB
+/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WB
+MAoGCCqGSM49BAMDA2gAMGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlw
+CkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1AE47xDqUEpHJWEadIRNyp4iciuRMStuW
+1KyLa2tJElMzrdfkviT8tQp21KW8EA==
+-----END CERTIFICATE-----
+
+# Issuer: CN=LuxTrust Global Root 2 O=LuxTrust S.A.
+# Subject: CN=LuxTrust Global Root 2 O=LuxTrust S.A.
+# Label: "LuxTrust Global Root 2"
+# Serial: 59914338225734147123941058376788110305822489521
+# MD5 Fingerprint: b2:e1:09:00:61:af:f7:f1:91:6f:c4:ad:8d:5e:3b:7c
+# SHA1 Fingerprint: 1e:0e:56:19:0a:d1:8b:25:98:b2:04:44:ff:66:8a:04:17:99:5f:3f
+# SHA256 Fingerprint: 54:45:5f:71:29:c2:0b:14:47:c4:18:f9:97:16:8f:24:c5:8f:c5:02:3b:f5:da:5b:e2:eb:6e:1d:d8:90:2e:d5
+-----BEGIN CERTIFICATE-----
+MIIFwzCCA6ugAwIBAgIUCn6m30tEntpqJIWe5rgV0xZ/u7EwDQYJKoZIhvcNAQEL
+BQAwRjELMAkGA1UEBhMCTFUxFjAUBgNVBAoMDUx1eFRydXN0IFMuQS4xHzAdBgNV
+BAMMFkx1eFRydXN0IEdsb2JhbCBSb290IDIwHhcNMTUwMzA1MTMyMTU3WhcNMzUw
+MzA1MTMyMTU3WjBGMQswCQYDVQQGEwJMVTEWMBQGA1UECgwNTHV4VHJ1c3QgUy5B
+LjEfMB0GA1UEAwwWTHV4VHJ1c3QgR2xvYmFsIFJvb3QgMjCCAiIwDQYJKoZIhvcN
+AQEBBQADggIPADCCAgoCggIBANeFl78RmOnwYoNMPIf5U2o3C/IPPIfOb9wmKb3F
+ibrJgz337spbxm1Jc7TJRqMbNBM/wYlFV/TZsfs2ZUv7COJIcRHIbjuend+JZTem
+hfY7RBi2xjcwYkSSl2l9QjAk5A0MiWtj3sXh306pFGxT4GHO9hcvHTy95iJMHZP1
+EMShduxq3sVs35a0VkBCwGKSMKEtFZSg0iAGCW5qbeXrt77U8PEVfIvmTroTzEsn
+Xpk8F12PgX8zPU/TPxvsXD/wPEx1bvKm1Z3aLQdjAsZy6ZS8TEmVT4hSyNvoaYL4
+zDRbIvCGp4m9SAptZoFtyMhk+wHh9OHe2Z7d21vUKpkmFRseTJIpgp7VkoGSQXAZ
+96Tlk0u8d2cx3Rz9MXANF5kM+Qw5GSoXtTBxVdUPrljhPS80m8+f9niFwpN6cj5m
+j5wWEWCPnolvZ77gR1o7DJpni89Gxq44o/KnvObWhWszJHAiS8sIm7vI+AIpHb4g
+DEa/a4ebsypmQjVGbKq6rfmYe+lQVRQxv7HaLe2ArWgk+2mr2HETMOZns4dA/Yl+
+8kPREd8vZS9kzl8UubG/Mb2HeFpZZYiq/FkySIbWTLkpS5XTdvN3JW1CHDiDTf2j
+X5t/Lax5Gw5CMZdjpPuKadUiDTSQMC6otOBttpSsvItO13D8xTiOZCXhTTmQzsmH
+hFhxAgMBAAGjgagwgaUwDwYDVR0TAQH/BAUwAwEB/zBCBgNVHSAEOzA5MDcGByuB
+KwEBAQowLDAqBggrBgEFBQcCARYeaHR0cHM6Ly9yZXBvc2l0b3J5Lmx1eHRydXN0
+Lmx1MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBT/GCh2+UgFLKGu8SsbK7JT
++Et8szAdBgNVHQ4EFgQU/xgodvlIBSyhrvErGyuyU/hLfLMwDQYJKoZIhvcNAQEL
+BQADggIBAGoZFO1uecEsh9QNcH7X9njJCwROxLHOk3D+sFTAMs2ZMGQXvw/l4jP9
+BzZAcg4atmpZ1gDlaCDdLnINH2pkMSCEfUmmWjfrRcmF9dTHF5kH5ptV5AzoqbTO
+jFu1EVzPig4N1qx3gf4ynCSecs5U89BvolbW7MM3LGVYvlcAGvI1+ut7MV3CwRI9
+loGIlonBWVx65n9wNOeD4rHh4bhY79SV5GCc8JaXcozrhAIuZY+kt9J/Z93I055c
+qqmkoCUUBpvsT34tC38ddfEz2O3OuHVtPlu5mB0xDVbYQw8wkbIEa91WvpWAVWe+
+2M2D2RjuLg+GLZKecBPs3lHJQ3gCpU3I+V/EkVhGFndadKpAvAefMLmx9xIX3eP/
+JEAdemrRTxgKqpAd60Ae36EeRJIQmvKN4dFLRp7oRUKX6kWZ8+xm1QL68qZKJKre
+zrnK+T+Tb/mjuuqlPpmt/f97mfVl7vBZKGfXkJWkE4SphMHozs51k2MavDzq1WQf
+LSoSOcbDWjLtR5EWDrw4wVDej8oqkDQc7kGUnF4ZLvhFSZl0kbAEb+MEWrGrKqv+
+x9CWttrhSmQGbmBNvUJO/3jaJMobtNeWOWyu8Q6qp31IiyBMz2TWuJdGsE7RKlY6
+oJO9r4Ak4Ap+58rVyuiFVdw2KuGUaJPHZnJED4AhMmwlxyOAgwrr
+-----END CERTIFICATE-----
+
+# Issuer: CN=TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1 O=Turkiye Bilimsel ve Teknolojik Arastirma Kurumu - TUBITAK OU=Kamu Sertifikasyon Merkezi - Kamu SM
+# Subject: CN=TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1 O=Turkiye Bilimsel ve Teknolojik Arastirma Kurumu - TUBITAK OU=Kamu Sertifikasyon Merkezi - Kamu SM
+# Label: "TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1"
+# Serial: 1
+# MD5 Fingerprint: dc:00:81:dc:69:2f:3e:2f:b0:3b:f6:3d:5a:91:8e:49
+# SHA1 Fingerprint: 31:43:64:9b:ec:ce:27:ec:ed:3a:3f:0b:8f:0d:e4:e8:91:dd:ee:ca
+# SHA256 Fingerprint: 46:ed:c3:68:90:46:d5:3a:45:3f:b3:10:4a:b8:0d:ca:ec:65:8b:26:60:ea:16:29:dd:7e:86:79:90:64:87:16
+-----BEGIN CERTIFICATE-----
+MIIEYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQsFADCB0jELMAkGA1UEBhMCVFIx
+GDAWBgNVBAcTD0dlYnplIC0gS29jYWVsaTFCMEAGA1UEChM5VHVya2l5ZSBCaWxp
+bXNlbCB2ZSBUZWtub2xvamlrIEFyYXN0aXJtYSBLdXJ1bXUgLSBUVUJJVEFLMS0w
+KwYDVQQLEyRLYW11IFNlcnRpZmlrYXN5b24gTWVya2V6aSAtIEthbXUgU00xNjA0
+BgNVBAMTLVRVQklUQUsgS2FtdSBTTSBTU0wgS29rIFNlcnRpZmlrYXNpIC0gU3Vy
+dW0gMTAeFw0xMzExMjUwODI1NTVaFw00MzEwMjUwODI1NTVaMIHSMQswCQYDVQQG
+EwJUUjEYMBYGA1UEBxMPR2ViemUgLSBLb2NhZWxpMUIwQAYDVQQKEzlUdXJraXll
+IEJpbGltc2VsIHZlIFRla25vbG9qaWsgQXJhc3Rpcm1hIEt1cnVtdSAtIFRVQklU
+QUsxLTArBgNVBAsTJEthbXUgU2VydGlmaWthc3lvbiBNZXJrZXppIC0gS2FtdSBT
+TTE2MDQGA1UEAxMtVFVCSVRBSyBLYW11IFNNIFNTTCBLb2sgU2VydGlmaWthc2kg
+LSBTdXJ1bSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr3UwM6q7
+a9OZLBI3hNmNe5eA027n/5tQlT6QlVZC1xl8JoSNkvoBHToP4mQ4t4y86Ij5iySr
+LqP1N+RAjhgleYN1Hzv/bKjFxlb4tO2KRKOrbEz8HdDc72i9z+SqzvBV96I01INr
+N3wcwv61A+xXzry0tcXtAA9TNypN9E8Mg/uGz8v+jE69h/mniyFXnHrfA2eJLJ2X
+YacQuFWQfw4tJzh03+f92k4S400VIgLI4OD8D62K18lUUMw7D8oWgITQUVbDjlZ/
+iSIzL+aFCr2lqBs23tPcLG07xxO9WSMs5uWk99gL7eqQQESolbuT1dCANLZGeA4f
+AJNG4e7p+exPFwIDAQABo0IwQDAdBgNVHQ4EFgQUZT/HiobGPN08VFw1+DrtUgxH
+V8gwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL
+BQADggEBACo/4fEyjq7hmFxLXs9rHmoJ0iKpEsdeV31zVmSAhHqT5Am5EM2fKifh
+AHe+SMg1qIGf5LgsyX8OsNJLN13qudULXjS99HMpw+0mFZx+CFOKWI3QSyjfwbPf
+IPP54+M638yclNhOT8NrF7f3cuitZjO1JVOr4PhMqZ398g26rrnZqsZr+ZO7rqu4
+lzwDGrpDxpa5RXI4s6ehlj2Re37AIVNMh+3yC1SVUZPVIqUNivGTDj5UDrDYyU7c
+8jEyVupk+eq1nRZmQnLzf9OxMUP8pI4X8W0jq5Rm+K37DwhuJi1/FwcJsoz7UMCf
+lo3Ptv0AnVoUmr8CRPXBwp8iXqIPoeM=
+-----END CERTIFICATE-----
+
+# Issuer: CN=GDCA TrustAUTH R5 ROOT O=GUANG DONG CERTIFICATE AUTHORITY CO.,LTD.
+# Subject: CN=GDCA TrustAUTH R5 ROOT O=GUANG DONG CERTIFICATE AUTHORITY CO.,LTD.
+# Label: "GDCA TrustAUTH R5 ROOT"
+# Serial: 9009899650740120186
+# MD5 Fingerprint: 63:cc:d9:3d:34:35:5c:6f:53:a3:e2:08:70:48:1f:b4
+# SHA1 Fingerprint: 0f:36:38:5b:81:1a:25:c3:9b:31:4e:83:ca:e9:34:66:70:cc:74:b4
+# SHA256 Fingerprint: bf:ff:8f:d0:44:33:48:7d:6a:8a:a6:0c:1a:29:76:7a:9f:c2:bb:b0:5e:42:0f:71:3a:13:b9:92:89:1d:38:93
+-----BEGIN CERTIFICATE-----
+MIIFiDCCA3CgAwIBAgIIfQmX/vBH6nowDQYJKoZIhvcNAQELBQAwYjELMAkGA1UE
+BhMCQ04xMjAwBgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZ
+IENPLixMVEQuMR8wHQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMB4XDTE0
+MTEyNjA1MTMxNVoXDTQwMTIzMTE1NTk1OVowYjELMAkGA1UEBhMCQ04xMjAwBgNV
+BAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZIENPLixMVEQuMR8w
+HQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMIICIjANBgkqhkiG9w0BAQEF
+AAOCAg8AMIICCgKCAgEA2aMW8Mh0dHeb7zMNOwZ+Vfy1YI92hhJCfVZmPoiC7XJj
+Dp6L3TQsAlFRwxn9WVSEyfFrs0yw6ehGXTjGoqcuEVe6ghWinI9tsJlKCvLriXBj
+TnnEt1u9ol2x8kECK62pOqPseQrsXzrj/e+APK00mxqriCZ7VqKChh/rNYmDf1+u
+KU49tm7srsHwJ5uu4/Ts765/94Y9cnrrpftZTqfrlYwiOXnhLQiPzLyRuEH3FMEj
+qcOtmkVEs7LXLM3GKeJQEK5cy4KOFxg2fZfmiJqwTTQJ9Cy5WmYqsBebnh52nUpm
+MUHfP/vFBu8btn4aRjb3ZGM74zkYI+dndRTVdVeSN72+ahsmUPI2JgaQxXABZG12
+ZuGR224HwGGALrIuL4xwp9E7PLOR5G62xDtw8mySlwnNR30YwPO7ng/Wi64HtloP
+zgsMR6flPri9fcebNaBhlzpBdRfMK5Z3KpIhHtmVdiBnaM8Nvd/WHwlqmuLMc3Gk
+L30SgLdTMEZeS1SZD2fJpcjyIMGC7J0R38IC+xo70e0gmu9lZJIQDSri3nDxGGeC
+jGHeuLzRL5z7D9Ar7Rt2ueQ5Vfj4oR24qoAATILnsn8JuLwwoC8N9VKejveSswoA
+HQBUlwbgsQfZxw9cZX08bVlX5O2ljelAU58VS6Bx9hoh49pwBiFYFIeFd3mqgnkC
+AwEAAaNCMEAwHQYDVR0OBBYEFOLJQJ9NzuiaoXzPDj9lxSmIahlRMA8GA1UdEwEB
+/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQDRSVfg
+p8xoWLoBDysZzY2wYUWsEe1jUGn4H3++Fo/9nesLqjJHdtJnJO29fDMylyrHBYZm
+DRd9FBUb1Ov9H5r2XpdptxolpAqzkT9fNqyL7FeoPueBihhXOYV0GkLH6VsTX4/5
+COmSdI31R9KrO9b7eGZONn356ZLpBN79SWP8bfsUcZNnL0dKt7n/HipzcEYwv1ry
+L3ml4Y0M2fmyYzeMN2WFcGpcWwlyua1jPLHd+PwyvzeG5LuOmCd+uh8W4XAR8gPf
+JWIyJyYYMoSf/wA6E7qaTfRPuBRwIrHKK5DOKcFw9C+df/KQHtZa37dG/OaG+svg
+IHZ6uqbL9XzeYqWxi+7egmaKTjowHz+Ay60nugxe19CxVsp3cbK1daFQqUBDF8Io
+2c9Si1vIY9RCPqAzekYu9wogRlR+ak8x8YF+QnQ4ZXMn7sZ8uI7XpTrXmKGcjBBV
+09tL7ECQ8s1uV9JiDnxXk7Gnbc2dg7sq5+W2O3FYrf3RRbxake5TFW/TRQl1brqQ
+XR4EzzffHqhmsYzmIGrv/EhOdJhCrylvLmrH+33RZjEizIYAfmaDDEL0vTSSwxrq
+T8p+ck0LcIymSLumoRT2+1hEmRSuqguTaaApJUqlyyvdimYHFngVV3Eb7PVHhPOe
+MTd61X8kreS8/f3MboPoDKi3QWwH3b08hpcv0g==
+-----END CERTIFICATE-----
+
+# Issuer: CN=TrustCor RootCert CA-1 O=TrustCor Systems S. de R.L. OU=TrustCor Certificate Authority
+# Subject: CN=TrustCor RootCert CA-1 O=TrustCor Systems S. de R.L. OU=TrustCor Certificate Authority
+# Label: "TrustCor RootCert CA-1"
+# Serial: 15752444095811006489
+# MD5 Fingerprint: 6e:85:f1:dc:1a:00:d3:22:d5:b2:b2:ac:6b:37:05:45
+# SHA1 Fingerprint: ff:bd:cd:e7:82:c8:43:5e:3c:6f:26:86:5c:ca:a8:3a:45:5b:c3:0a
+# SHA256 Fingerprint: d4:0e:9c:86:cd:8f:e4:68:c1:77:69:59:f4:9e:a7:74:fa:54:86:84:b6:c4:06:f3:90:92:61:f4:dc:e2:57:5c
+-----BEGIN CERTIFICATE-----
+MIIEMDCCAxigAwIBAgIJANqb7HHzA7AZMA0GCSqGSIb3DQEBCwUAMIGkMQswCQYD
+VQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEk
+MCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5U
+cnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRydXN0Q29y
+IFJvb3RDZXJ0IENBLTEwHhcNMTYwMjA0MTIzMjE2WhcNMjkxMjMxMTcyMzE2WjCB
+pDELMAkGA1UEBhMCUEExDzANBgNVBAgMBlBhbmFtYTEUMBIGA1UEBwwLUGFuYW1h
+IENpdHkxJDAiBgNVBAoMG1RydXN0Q29yIFN5c3RlbXMgUy4gZGUgUi5MLjEnMCUG
+A1UECwweVHJ1c3RDb3IgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MR8wHQYDVQQDDBZU
+cnVzdENvciBSb290Q2VydCBDQS0xMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEAv463leLCJhJrMxnHQFgKq1mqjQCj/IDHUHuO1CAmujIS2CNUSSUQIpid
+RtLByZ5OGy4sDjjzGiVoHKZaBeYei0i/mJZ0PmnK6bV4pQa81QBeCQryJ3pS/C3V
+seq0iWEk8xoT26nPUu0MJLq5nux+AHT6k61sKZKuUbS701e/s/OojZz0JEsq1pme
+9J7+wH5COucLlVPat2gOkEz7cD+PSiyU8ybdY2mplNgQTsVHCJCZGxdNuWxu72CV
+EY4hgLW9oHPY0LJ3xEXqWib7ZnZ2+AYfYW0PVcWDtxBWcgYHpfOxGgMFZA6dWorW
+hnAbJN7+KIor0Gqw/Hqi3LJ5DotlDwIDAQABo2MwYTAdBgNVHQ4EFgQU7mtJPHo/
+DeOxCbeKyKsZn3MzUOcwHwYDVR0jBBgwFoAU7mtJPHo/DeOxCbeKyKsZn3MzUOcw
+DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQAD
+ggEBACUY1JGPE+6PHh0RU9otRCkZoB5rMZ5NDp6tPVxBb5UrJKF5mDo4Nvu7Zp5I
+/5CQ7z3UuJu0h3U/IJvOcs+hVcFNZKIZBqEHMwwLKeXx6quj7LUKdJDHfXLy11yf
+ke+Ri7fc7Waiz45mO7yfOgLgJ90WmMCV1Aqk5IGadZQ1nJBfiDcGrVmVCrDRZ9MZ
+yonnMlo2HD6CqFqTvsbQZJG2z9m2GM/bftJlo6bEjhcxwft+dtvTheNYsnd6djts
+L1Ac59v2Z3kf9YKVmgenFK+P3CghZwnS1k1aHBkcjndcw5QkPTJrS37UeJSDvjdN
+zl/HHk484IkzlQsPpTLWPFp5LBk=
+-----END CERTIFICATE-----
+
+# Issuer: CN=TrustCor RootCert CA-2 O=TrustCor Systems S. de R.L. OU=TrustCor Certificate Authority
+# Subject: CN=TrustCor RootCert CA-2 O=TrustCor Systems S. de R.L. OU=TrustCor Certificate Authority
+# Label: "TrustCor RootCert CA-2"
+# Serial: 2711694510199101698
+# MD5 Fingerprint: a2:e1:f8:18:0b:ba:45:d5:c7:41:2a:bb:37:52:45:64
+# SHA1 Fingerprint: b8:be:6d:cb:56:f1:55:b9:63:d4:12:ca:4e:06:34:c7:94:b2:1c:c0
+# SHA256 Fingerprint: 07:53:e9:40:37:8c:1b:d5:e3:83:6e:39:5d:ae:a5:cb:83:9e:50:46:f1:bd:0e:ae:19:51:cf:10:fe:c7:c9:65
+-----BEGIN CERTIFICATE-----
+MIIGLzCCBBegAwIBAgIIJaHfyjPLWQIwDQYJKoZIhvcNAQELBQAwgaQxCzAJBgNV
+BAYTAlBBMQ8wDQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5MSQw
+IgYDVQQKDBtUcnVzdENvciBTeXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRy
+dXN0Q29yIENlcnRpZmljYXRlIEF1dGhvcml0eTEfMB0GA1UEAwwWVHJ1c3RDb3Ig
+Um9vdENlcnQgQ0EtMjAeFw0xNjAyMDQxMjMyMjNaFw0zNDEyMzExNzI2MzlaMIGk
+MQswCQYDVQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEg
+Q2l0eTEkMCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYD
+VQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRy
+dXN0Q29yIFJvb3RDZXJ0IENBLTIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK
+AoICAQCnIG7CKqJiJJWQdsg4foDSq8GbZQWU9MEKENUCrO2fk8eHyLAnK0IMPQo+
+QVqedd2NyuCb7GgypGmSaIwLgQ5WoD4a3SwlFIIvl9NkRvRUqdw6VC0xK5mC8tkq
+1+9xALgxpL56JAfDQiDyitSSBBtlVkxs1Pu2YVpHI7TYabS3OtB0PAx1oYxOdqHp
+2yqlO/rOsP9+aij9JxzIsekp8VduZLTQwRVtDr4uDkbIXvRR/u8OYzo7cbrPb1nK
+DOObXUm4TOJXsZiKQlecdu/vvdFoqNL0Cbt3Nb4lggjEFixEIFapRBF37120Hape
+az6LMvYHL1cEksr1/p3C6eizjkxLAjHZ5DxIgif3GIJ2SDpxsROhOdUuxTTCHWKF
+3wP+TfSvPd9cW436cOGlfifHhi5qjxLGhF5DUVCcGZt45vz27Ud+ez1m7xMTiF88
+oWP7+ayHNZ/zgp6kPwqcMWmLmaSISo5uZk3vFsQPeSghYA2FFn3XVDjxklb9tTNM
+g9zXEJ9L/cb4Qr26fHMC4P99zVvh1Kxhe1fVSntb1IVYJ12/+CtgrKAmrhQhJ8Z3
+mjOAPF5GP/fDsaOGM8boXg25NSyqRsGFAnWAoOsk+xWq5Gd/bnc/9ASKL3x74xdh
+8N0JqSDIvgmk0H5Ew7IwSjiqqewYmgeCK9u4nBit2uBGF6zPXQIDAQABo2MwYTAd
+BgNVHQ4EFgQU2f4hQG6UnrybPZx9mCAZ5YwwYrIwHwYDVR0jBBgwFoAU2f4hQG6U
+nrybPZx9mCAZ5YwwYrIwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYw
+DQYJKoZIhvcNAQELBQADggIBAJ5Fngw7tu/hOsh80QA9z+LqBrWyOrsGS2h60COX
+dKcs8AjYeVrXWoSK2BKaG9l9XE1wxaX5q+WjiYndAfrs3fnpkpfbsEZC89NiqpX+
+MWcUaViQCqoL7jcjx1BRtPV+nuN79+TMQjItSQzL/0kMmx40/W5ulop5A7Zv2wnL
+/V9lFDfhOPXzYRZY5LVtDQsEGz9QLX+zx3oaFoBg+Iof6Rsqxvm6ARppv9JYx1RX
+CI/hOWB3S6xZhBqI8d3LT3jX5+EzLfzuQfogsL7L9ziUwOHQhQ+77Sxzq+3+knYa
+ZH9bDTMJBzN7Bj8RpFxwPIXAz+OQqIN3+tvmxYxoZxBnpVIt8MSZj3+/0WvitUfW
+2dCFmU2Umw9Lje4AWkcdEQOsQRivh7dvDDqPys/cA8GiCcjl/YBeyGBCARsaU1q7
+N6a3vLqE6R5sGtRk2tRD/pOLS/IseRYQ1JMLiI+h2IYURpFHmygk71dSTlxCnKr3
+Sewn6EAes6aJInKc9Q0ztFijMDvd1GpUk74aTfOTlPf8hAs/hCBcNANExdqtvArB
+As8e5ZTZ845b2EzwnexhF7sUMlQMAimTHpKG9n/v55IFDlndmQguLvqcAFLTxWYp
+5KeXRKQOKIETNcX2b2TmQcTVL8w0RSXPQQCWPUouwpaYT05KnJe32x+SMsj/D1Fu
+1uwJ
+-----END CERTIFICATE-----
+
+# Issuer: CN=TrustCor ECA-1 O=TrustCor Systems S. de R.L. OU=TrustCor Certificate Authority
+# Subject: CN=TrustCor ECA-1 O=TrustCor Systems S. de R.L. OU=TrustCor Certificate Authority
+# Label: "TrustCor ECA-1"
+# Serial: 9548242946988625984
+# MD5 Fingerprint: 27:92:23:1d:0a:f5:40:7c:e9:e6:6b:9d:d8:f5:e7:6c
+# SHA1 Fingerprint: 58:d1:df:95:95:67:6b:63:c0:f0:5b:1c:17:4d:8b:84:0b:c8:78:bd
+# SHA256 Fingerprint: 5a:88:5d:b1:9c:01:d9:12:c5:75:93:88:93:8c:af:bb:df:03:1a:b2:d4:8e:91:ee:15:58:9b:42:97:1d:03:9c
+-----BEGIN CERTIFICATE-----
+MIIEIDCCAwigAwIBAgIJAISCLF8cYtBAMA0GCSqGSIb3DQEBCwUAMIGcMQswCQYD
+VQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEk
+MCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5U
+cnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxFzAVBgNVBAMMDlRydXN0Q29y
+IEVDQS0xMB4XDTE2MDIwNDEyMzIzM1oXDTI5MTIzMTE3MjgwN1owgZwxCzAJBgNV
+BAYTAlBBMQ8wDQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5MSQw
+IgYDVQQKDBtUcnVzdENvciBTeXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRy
+dXN0Q29yIENlcnRpZmljYXRlIEF1dGhvcml0eTEXMBUGA1UEAwwOVHJ1c3RDb3Ig
+RUNBLTEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDPj+ARtZ+odnbb
+3w9U73NjKYKtR8aja+3+XzP4Q1HpGjORMRegdMTUpwHmspI+ap3tDvl0mEDTPwOA
+BoJA6LHip1GnHYMma6ve+heRK9jGrB6xnhkB1Zem6g23xFUfJ3zSCNV2HykVh0A5
+3ThFEXXQmqc04L/NyFIduUd+Dbi7xgz2c1cWWn5DkR9VOsZtRASqnKmcp0yJF4Ou
+owReUoCLHhIlERnXDH19MURB6tuvsBzvgdAsxZohmz3tQjtQJvLsznFhBmIhVE5/
+wZ0+fyCMgMsq2JdiyIMzkX2woloPV+g7zPIlstR8L+xNxqE6FXrntl019fZISjZF
+ZtS6mFjBAgMBAAGjYzBhMB0GA1UdDgQWBBREnkj1zG1I1KBLf/5ZJC+Dl5mahjAf
+BgNVHSMEGDAWgBREnkj1zG1I1KBLf/5ZJC+Dl5mahjAPBgNVHRMBAf8EBTADAQH/
+MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEABT41XBVwm8nHc2Fv
+civUwo/yQ10CzsSUuZQRg2dd4mdsdXa/uwyqNsatR5Nj3B5+1t4u/ukZMjgDfxT2
+AHMsWbEhBuH7rBiVDKP/mZb3Kyeb1STMHd3BOuCYRLDE5D53sXOpZCz2HAF8P11F
+hcCF5yWPldwX8zyfGm6wyuMdKulMY/okYWLW2n62HGz1Ah3UKt1VkOsqEUc8Ll50
+soIipX1TH0XsJ5F95yIW6MBoNtjG8U+ARDL54dHRHareqKucBK+tIA5kmE2la8BI
+WJZpTdwHjFGTot+fDz2LYLSCjaoITmJF4PkL0uDgPFveXHEnJcLmA4GLEFPjx1Wi
+tJ/X5g==
+-----END CERTIFICATE-----
+
+# Issuer: CN=SSL.com Root Certification Authority RSA O=SSL Corporation
+# Subject: CN=SSL.com Root Certification Authority RSA O=SSL Corporation
+# Label: "SSL.com Root Certification Authority RSA"
+# Serial: 8875640296558310041
+# MD5 Fingerprint: 86:69:12:c0:70:f1:ec:ac:ac:c2:d5:bc:a5:5b:a1:29
+# SHA1 Fingerprint: b7:ab:33:08:d1:ea:44:77:ba:14:80:12:5a:6f:bd:a9:36:49:0c:bb
+# SHA256 Fingerprint: 85:66:6a:56:2e:e0:be:5c:e9:25:c1:d8:89:0a:6f:76:a8:7e:c1:6d:4d:7d:5f:29:ea:74:19:cf:20:12:3b:69
+-----BEGIN CERTIFICATE-----
+MIIF3TCCA8WgAwIBAgIIeyyb0xaAMpkwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UE
+BhMCVVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQK
+DA9TU0wgQ29ycG9yYXRpb24xMTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZp
+Y2F0aW9uIEF1dGhvcml0eSBSU0EwHhcNMTYwMjEyMTczOTM5WhcNNDEwMjEyMTcz
+OTM5WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hv
+dXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNv
+bSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFJTQTCCAiIwDQYJKoZIhvcN
+AQEBBQADggIPADCCAgoCggIBAPkP3aMrfcvQKv7sZ4Wm5y4bunfh4/WvpOz6Sl2R
+xFdHaxh3a3by/ZPkPQ/CFp4LZsNWlJ4Xg4XOVu/yFv0AYvUiCVToZRdOQbngT0aX
+qhvIuG5iXmmxX9sqAn78bMrzQdjt0Oj8P2FI7bADFB0QDksZ4LtO7IZl/zbzXmcC
+C52GVWH9ejjt/uIZALdvoVBidXQ8oPrIJZK0bnoix/geoeOy3ZExqysdBP+lSgQ3
+6YWkMyv94tZVNHwZpEpox7Ko07fKoZOI68GXvIz5HdkihCR0xwQ9aqkpk8zruFvh
+/l8lqjRYyMEjVJ0bmBHDOJx+PYZspQ9AhnwC9FwCTyjLrnGfDzrIM/4RJTXq/LrF
+YD3ZfBjVsqnTdXgDciLKOsMf7yzlLqn6niy2UUb9rwPW6mBo6oUWNmuF6R7As93E
+JNyAKoFBbZQ+yODJgUEAnl6/f8UImKIYLEJAs/lvOCdLToD0PYFH4Ih86hzOtXVc
+US4cK38acijnALXRdMbX5J+tB5O2UzU1/Dfkw/ZdFr4hc96SCvigY2q8lpJqPvi8
+ZVWb3vUNiSYE/CUapiVpy8JtynziWV+XrOvvLsi81xtZPCvM8hnIk2snYxnP/Okm
++Mpxm3+T/jRnhE6Z6/yzeAkzcLpmpnbtG3PrGqUNxCITIJRWCk4sbE6x/c+cCbqi
+M+2HAgMBAAGjYzBhMB0GA1UdDgQWBBTdBAkHovV6fVJTEpKV7jiAJQ2mWTAPBgNV
+HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFN0ECQei9Xp9UlMSkpXuOIAlDaZZMA4G
+A1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAIBgRlCn7Jp0cHh5wYfGV
+cpNxJK1ok1iOMq8bs3AD/CUrdIWQPXhq9LmLpZc7tRiRux6n+UBbkflVma8eEdBc
+Hadm47GUBwwyOabqG7B52B2ccETjit3E+ZUfijhDPwGFpUenPUayvOUiaPd7nNgs
+PgohyC0zrL/FgZkxdMF1ccW+sfAjRfSda/wZY52jvATGGAslu1OJD7OAUN5F7kR/
+q5R4ZJjT9ijdh9hwZXT7DrkT66cPYakylszeu+1jTBi7qUD3oFRuIIhxdRjqerQ0
+cuAjJ3dctpDqhiVAq+8zD8ufgr6iIPv2tS0a5sKFsXQP+8hlAqRSAUfdSSLBv9jr
+a6x+3uxjMxW3IwiPxg+NQVrdjsW5j+VFP3jbutIbQLH+cU0/4IGiul607BXgk90I
+H37hVZkLId6Tngr75qNJvTYw/ud3sqB1l7UtgYgXZSD32pAAn8lSzDLKNXz1PQ/Y
+K9f1JmzJBjSWFupwWRoyeXkLtoh/D1JIPb9s2KJELtFOt3JY04kTlf5Eq/jXixtu
+nLwsoFvVagCvXzfh1foQC5ichucmj87w7G6KVwuA406ywKBjYZC6VWg3dGq2ktuf
+oYYitmUnDuy2n0Jg5GfCtdpBC8TTi2EbvPofkSvXRAdeuims2cXp71NIWuuA8ShY
+Ic2wBlX7Jz9TkHCpBB5XJ7k=
+-----END CERTIFICATE-----
+
+# Issuer: CN=SSL.com Root Certification Authority ECC O=SSL Corporation
+# Subject: CN=SSL.com Root Certification Authority ECC O=SSL Corporation
+# Label: "SSL.com Root Certification Authority ECC"
+# Serial: 8495723813297216424
+# MD5 Fingerprint: 2e:da:e4:39:7f:9c:8f:37:d1:70:9f:26:17:51:3a:8e
+# SHA1 Fingerprint: c3:19:7c:39:24:e6:54:af:1b:c4:ab:20:95:7a:e2:c3:0e:13:02:6a
+# SHA256 Fingerprint: 34:17:bb:06:cc:60:07:da:1b:96:1c:92:0b:8a:b4:ce:3f:ad:82:0e:4a:a3:0b:9a:cb:c4:a7:4e:bd:ce:bc:65
+-----BEGIN CERTIFICATE-----
+MIICjTCCAhSgAwIBAgIIdebfy8FoW6gwCgYIKoZIzj0EAwIwfDELMAkGA1UEBhMC
+VVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9T
+U0wgQ29ycG9yYXRpb24xMTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0
+aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEyMTgxNDAzWhcNNDEwMjEyMTgxNDAz
+WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hvdXN0
+b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNvbSBS
+b290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuB
+BAAiA2IABEVuqVDEpiM2nl8ojRfLliJkP9x6jh3MCLOicSS6jkm5BBtHllirLZXI
+7Z4INcgn64mMU1jrYor+8FsPazFSY0E7ic3s7LaNGdM0B9y7xgZ/wkWV7Mt/qCPg
+CemB+vNH06NjMGEwHQYDVR0OBBYEFILRhXMw5zUE044CkvvlpNHEIejNMA8GA1Ud
+EwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUgtGFczDnNQTTjgKS++Wk0cQh6M0wDgYD
+VR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2cAMGQCMG/n61kRpGDPYbCWe+0F+S8T
+kdzt5fxQaxFGRrMcIQBiu77D5+jNB5n5DQtdcj7EqgIwH7y6C+IwJPt8bYBVCpk+
+gA0z5Wajs6O7pdWLjwkspl1+4vAHCGht0nxpbl/f5Wpl
+-----END CERTIFICATE-----
+
+# Issuer: CN=SSL.com EV Root Certification Authority RSA R2 O=SSL Corporation
+# Subject: CN=SSL.com EV Root Certification Authority RSA R2 O=SSL Corporation
+# Label: "SSL.com EV Root Certification Authority RSA R2"
+# Serial: 6248227494352943350
+# MD5 Fingerprint: e1:1e:31:58:1a:ae:54:53:02:f6:17:6a:11:7b:4d:95
+# SHA1 Fingerprint: 74:3a:f0:52:9b:d0:32:a0:f4:4a:83:cd:d4:ba:a9:7b:7c:2e:c4:9a
+# SHA256 Fingerprint: 2e:7b:f1:6c:c2:24:85:a7:bb:e2:aa:86:96:75:07:61:b0:ae:39:be:3b:2f:e9:d0:cc:6d:4e:f7:34:91:42:5c
+-----BEGIN CERTIFICATE-----
+MIIF6zCCA9OgAwIBAgIIVrYpzTS8ePYwDQYJKoZIhvcNAQELBQAwgYIxCzAJBgNV
+BAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UE
+CgwPU1NMIENvcnBvcmF0aW9uMTcwNQYDVQQDDC5TU0wuY29tIEVWIFJvb3QgQ2Vy
+dGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIyMB4XDTE3MDUzMTE4MTQzN1oXDTQy
+MDUzMDE4MTQzN1owgYIxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4G
+A1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTcwNQYDVQQD
+DC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIy
+MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAjzZlQOHWTcDXtOlG2mvq
+M0fNTPl9fb69LT3w23jhhqXZuglXaO1XPqDQCEGD5yhBJB/jchXQARr7XnAjssuf
+OePPxU7Gkm0mxnu7s9onnQqG6YE3Bf7wcXHswxzpY6IXFJ3vG2fThVUCAtZJycxa
+4bH3bzKfydQ7iEGonL3Lq9ttewkfokxykNorCPzPPFTOZw+oz12WGQvE43LrrdF9
+HSfvkusQv1vrO6/PgN3B0pYEW3p+pKk8OHakYo6gOV7qd89dAFmPZiw+B6KjBSYR
+aZfqhbcPlgtLyEDhULouisv3D5oi53+aNxPN8k0TayHRwMwi8qFG9kRpnMphNQcA
+b9ZhCBHqurj26bNg5U257J8UZslXWNvNh2n4ioYSA0e/ZhN2rHd9NCSFg83XqpyQ
+Gp8hLH94t2S42Oim9HizVcuE0jLEeK6jj2HdzghTreyI/BXkmg3mnxp3zkyPuBQV
+PWKchjgGAGYS5Fl2WlPAApiiECtoRHuOec4zSnaqW4EWG7WK2NAAe15itAnWhmMO
+pgWVSbooi4iTsjQc2KRVbrcc0N6ZVTsj9CLg+SlmJuwgUHfbSguPvuUCYHBBXtSu
+UDkiFCbLsjtzdFVHB3mBOagwE0TlBIqulhMlQg+5U8Sb/M3kHN48+qvWBkofZ6aY
+MBzdLNvcGJVXZsb/XItW9XcCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNV
+HSMEGDAWgBT5YLvU49U09rj1BoAlp3PbRmmonjAdBgNVHQ4EFgQU+WC71OPVNPa4
+9QaAJadz20ZpqJ4wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBW
+s47LCp1Jjr+kxJG7ZhcFUZh1++VQLHqe8RT6q9OKPv+RKY9ji9i0qVQBDb6Thi/5
+Sm3HXvVX+cpVHBK+Rw82xd9qt9t1wkclf7nxY/hoLVUE0fKNsKTPvDxeH3jnpaAg
+cLAExbf3cqfeIg29MyVGjGSSJuM+LmOW2puMPfgYCdcDzH2GguDKBAdRUNf/ktUM
+79qGn5nX67evaOI5JpS6aLe/g9Pqemc9YmeuJeVy6OLk7K4S9ksrPJ/psEDzOFSz
+/bdoyNrGj1E8svuR3Bznm53htw1yj+KkxKl4+esUrMZDBcJlOSgYAsOCsp0FvmXt
+ll9ldDz7CTUue5wT/RsPXcdtgTpWD8w74a8CLyKsRspGPKAcTNZEtF4uXBVmCeEm
+Kf7GUmG6sXP/wwyc5WxqlD8UykAWlYTzWamsX0xhk23RO8yilQwipmdnRC652dKK
+QbNmC1r7fSOl8hqw/96bg5Qu0T/fkreRrwU7ZcegbLHNYhLDkBvjJc40vG93drEQ
+w/cFGsDWr3RiSBd3kmmQYRzelYB0VI8YHMPzA9C/pEN1hlMYegouCRw2n5H9gooi
+S9EOUCXdywMMF8mDAAhONU2Ki+3wApRmLER/y5UnlhetCTCstnEXbosX9hwJ1C07
+mKVx01QT2WDz9UtmT/rx7iASjbSsV7FFY6GsdqnC+w==
+-----END CERTIFICATE-----
+
+# Issuer: CN=SSL.com EV Root Certification Authority ECC O=SSL Corporation
+# Subject: CN=SSL.com EV Root Certification Authority ECC O=SSL Corporation
+# Label: "SSL.com EV Root Certification Authority ECC"
+# Serial: 3182246526754555285
+# MD5 Fingerprint: 59:53:22:65:83:42:01:54:c0:ce:42:b9:5a:7c:f2:90
+# SHA1 Fingerprint: 4c:dd:51:a3:d1:f5:20:32:14:b0:c6:c5:32:23:03:91:c7:46:42:6d
+# SHA256 Fingerprint: 22:a2:c1:f7:bd:ed:70:4c:c1:e7:01:b5:f4:08:c3:10:88:0f:e9:56:b5:de:2a:4a:44:f9:9c:87:3a:25:a7:c8
+-----BEGIN CERTIFICATE-----
+MIIClDCCAhqgAwIBAgIILCmcWxbtBZUwCgYIKoZIzj0EAwIwfzELMAkGA1UEBhMC
+VVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9T
+U0wgQ29ycG9yYXRpb24xNDAyBgNVBAMMK1NTTC5jb20gRVYgUm9vdCBDZXJ0aWZp
+Y2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEyMTgxNTIzWhcNNDEwMjEyMTgx
+NTIzWjB/MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hv
+dXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjE0MDIGA1UEAwwrU1NMLmNv
+bSBFViBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49
+AgEGBSuBBAAiA2IABKoSR5CYG/vvw0AHgyBO8TCCogbR8pKGYfL2IWjKAMTH6kMA
+VIbc/R/fALhBYlzccBYy3h+Z1MzFB8gIH2EWB1E9fVwHU+M1OIzfzZ/ZLg1Kthku
+WnBaBu2+8KGwytAJKaNjMGEwHQYDVR0OBBYEFFvKXuXe0oGqzagtZFG22XKbl+ZP
+MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUW8pe5d7SgarNqC1kUbbZcpuX
+5k8wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2gAMGUCMQCK5kCJN+vp1RPZ
+ytRrJPOwPYdGWBrssd9v+1a6cGvHOMzosYxPD/fxZ3YOg9AeUY8CMD32IygmTMZg
+h5Mmm7I1HrrW9zzRHM76JTymGoEVW/MSD2zuZYrJh6j5B+BimoxcSg==
+-----END CERTIFICATE-----
diff --git a/src/android/test/interop/app/src/main/cpp/grpc-interop.cc b/src/android/test/interop/app/src/main/cpp/grpc-interop.cc
new file mode 100644
index 0000000..bbdc84a
--- /dev/null
+++ b/src/android/test/interop/app/src/main/cpp/grpc-interop.cc
@@ -0,0 +1,124 @@
+/*
+ *
+ * Copyright 2018 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.
+ *
+ */
+
+#include <grpcpp/grpcpp.h>
+#include <jni.h>
+#include <src/core/lib/gpr/env.h>
+
+#include "test/cpp/interop/interop_client.h"
+
+extern "C" JNIEXPORT void JNICALL
+Java_io_grpc_interop_cpp_InteropActivity_configureSslRoots(JNIEnv* env,
+                                                           jobject obj_this,
+                                                           jstring path_raw) {
+  const char* path = env->GetStringUTFChars(path_raw, (jboolean*)0);
+
+  gpr_setenv("GRPC_DEFAULT_SSL_ROOTS_FILE_PATH", path);
+}
+
+std::shared_ptr<grpc::testing::InteropClient> GetClient(const char* host,
+                                                        int port,
+                                                        bool use_tls) {
+  const int host_port_buf_size = 1024;
+  char host_port[host_port_buf_size];
+  snprintf(host_port, host_port_buf_size, "%s:%d", host, port);
+
+  std::shared_ptr<grpc::ChannelCredentials> credentials;
+  if (use_tls) {
+    credentials = grpc::SslCredentials(grpc::SslCredentialsOptions());
+  } else {
+    credentials = grpc::InsecureChannelCredentials();
+  }
+
+  return std::shared_ptr<grpc::testing::InteropClient>(
+      new grpc::testing::InteropClient(
+          grpc::CreateChannel(host_port, credentials), true, false));
+}
+
+extern "C" JNIEXPORT jboolean JNICALL
+Java_io_grpc_interop_cpp_InteropActivity_doEmpty(JNIEnv* env, jobject obj_this,
+                                                 jstring host_raw,
+                                                 jint port_raw,
+                                                 jboolean use_tls_raw) {
+  const char* host = env->GetStringUTFChars(host_raw, (jboolean*)0);
+  int port = static_cast<int>(port_raw);
+  bool use_tls = static_cast<bool>(use_tls_raw);
+
+  return GetClient(host, port, use_tls)->DoEmpty();
+}
+
+extern "C" JNIEXPORT jboolean JNICALL
+Java_io_grpc_interop_cpp_InteropActivity_doLargeUnary(JNIEnv* env,
+                                                      jobject obj_this,
+                                                      jstring host_raw,
+                                                      jint port_raw,
+                                                      jboolean use_tls_raw) {
+  const char* host = env->GetStringUTFChars(host_raw, (jboolean*)0);
+  int port = static_cast<int>(port_raw);
+  bool use_tls = static_cast<bool>(use_tls_raw);
+
+  return GetClient(host, port, use_tls)->DoLargeUnary();
+}
+
+extern "C" JNIEXPORT jboolean JNICALL
+Java_io_grpc_interop_cpp_InteropActivity_doEmptyStream(JNIEnv* env,
+                                                       jobject obj_this,
+                                                       jstring host_raw,
+                                                       jint port_raw,
+                                                       jboolean use_tls_raw) {
+  const char* host = env->GetStringUTFChars(host_raw, (jboolean*)0);
+  int port = static_cast<int>(port_raw);
+  bool use_tls = static_cast<bool>(use_tls_raw);
+
+  return GetClient(host, port, use_tls)->DoEmptyStream();
+}
+
+extern "C" JNIEXPORT jboolean JNICALL
+Java_io_grpc_interop_cpp_InteropActivity_doRequestStreaming(
+    JNIEnv* env, jobject obj_this, jstring host_raw, jint port_raw,
+    jboolean use_tls_raw) {
+  const char* host = env->GetStringUTFChars(host_raw, (jboolean*)0);
+  int port = static_cast<int>(port_raw);
+  bool use_tls = static_cast<bool>(use_tls_raw);
+
+  return GetClient(host, port, use_tls)->DoRequestStreaming();
+}
+
+extern "C" JNIEXPORT jboolean JNICALL
+Java_io_grpc_interop_cpp_InteropActivity_doResponseStreaming(
+    JNIEnv* env, jobject obj_this, jstring host_raw, jint port_raw,
+    jboolean use_tls_raw) {
+  const char* host = env->GetStringUTFChars(host_raw, (jboolean*)0);
+  int port = static_cast<int>(port_raw);
+  bool use_tls = static_cast<bool>(use_tls_raw);
+
+  return GetClient(host, port, use_tls)->DoResponseStreaming();
+}
+
+extern "C" JNIEXPORT jboolean JNICALL
+Java_io_grpc_interop_cpp_InteropActivity_doPingPong(JNIEnv* env,
+                                                    jobject obj_this,
+                                                    jstring host_raw,
+                                                    jint port_raw,
+                                                    jboolean use_tls_raw) {
+  const char* host = env->GetStringUTFChars(host_raw, (jboolean*)0);
+  int port = static_cast<int>(port_raw);
+  bool use_tls = static_cast<bool>(use_tls_raw);
+
+  return GetClient(host, port, use_tls)->DoPingPong();
+}
diff --git a/src/android/test/interop/app/src/main/java/io/grpc/interop/cpp/InteropActivity.java b/src/android/test/interop/app/src/main/java/io/grpc/interop/cpp/InteropActivity.java
new file mode 100644
index 0000000..001f313
--- /dev/null
+++ b/src/android/test/interop/app/src/main/java/io/grpc/interop/cpp/InteropActivity.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2018, gRPC Authors All rights reserved.
+ *
+ * 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.
+ */
+
+package io.grpc.interop.cpp;
+
+import android.content.Context;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.support.v7.app.AppCompatActivity;
+import android.text.TextUtils;
+import android.text.method.ScrollingMovementMethod;
+import android.view.View;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.TextView;
+import java.lang.ref.WeakReference;
+
+public class InteropActivity extends AppCompatActivity {
+
+  static {
+    System.loadLibrary("grpc-interop");
+  }
+
+  private Button sendButton;
+  private EditText hostEdit;
+  private EditText portEdit;
+  private TextView resultText;
+  private GrpcTask grpcTask;
+
+  @Override
+  protected void onCreate(Bundle savedInstanceState) {
+    super.onCreate(savedInstanceState);
+    setContentView(R.layout.activity_interop);
+    sendButton = (Button) findViewById(R.id.ping_pong_button);
+    hostEdit = (EditText) findViewById(R.id.host_edit_text);
+    portEdit = (EditText) findViewById(R.id.port_edit_text);
+    resultText = (TextView) findViewById(R.id.grpc_result_text);
+    resultText.setMovementMethod(new ScrollingMovementMethod());
+  }
+
+  @Override
+  protected void onPause() {
+    super.onPause();
+    if (grpcTask != null) {
+      grpcTask.cancel(true);
+      grpcTask = null;
+    }
+  }
+
+  public void doPingPong(View view) {
+    ((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE))
+        .hideSoftInputFromWindow(hostEdit.getWindowToken(), 0);
+    sendButton.setEnabled(false);
+    resultText.setText("");
+    grpcTask = new GrpcTask(this);
+    grpcTask.executeOnExecutor(
+        AsyncTask.THREAD_POOL_EXECUTOR,
+        hostEdit.getText().toString(),
+        portEdit.getText().toString());
+  }
+
+  private static class GrpcTask extends AsyncTask<String, Void, String> {
+    private final WeakReference<InteropActivity> activityReference;
+
+    private GrpcTask(InteropActivity activity) {
+      this.activityReference = new WeakReference<InteropActivity>(activity);
+    }
+
+    @Override
+    protected String doInBackground(String... params) {
+      String host = params[0];
+      String portStr = params[1];
+      int port = TextUtils.isEmpty(portStr) ? 50051 : Integer.valueOf(portStr);
+      // TODO(ericgribkoff) Support other test cases in the app UI
+      if (doPingPong(host, port, false)) {
+        return "Success";
+      } else {
+        return "Failure";
+      }
+    }
+
+    @Override
+    protected void onPostExecute(String result) {
+      InteropActivity activity = activityReference.get();
+      if (activity == null || isCancelled()) {
+        return;
+      }
+      TextView resultText = (TextView) activity.findViewById(R.id.grpc_result_text);
+      Button sendButton = (Button) activity.findViewById(R.id.ping_pong_button);
+      resultText.setText(result);
+      sendButton.setEnabled(true);
+    }
+  }
+
+  public static native void configureSslRoots(String path);
+
+  public static native boolean doEmpty(String host, int port, boolean useTls);
+
+  public static native boolean doLargeUnary(String host, int port, boolean useTls);
+
+  public static native boolean doEmptyStream(String host, int port, boolean useTls);
+
+  public static native boolean doRequestStreaming(String host, int port, boolean useTls);
+
+  public static native boolean doResponseStreaming(String host, int port, boolean useTls);
+
+  public static native boolean doPingPong(String host, int port, boolean useTls);
+}
diff --git a/src/android/test/interop/app/src/main/res/layout/activity_interop.xml b/src/android/test/interop/app/src/main/res/layout/activity_interop.xml
new file mode 100644
index 0000000..81ec342
--- /dev/null
+++ b/src/android/test/interop/app/src/main/res/layout/activity_interop.xml
@@ -0,0 +1,48 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
+              android:layout_height="match_parent"
+              tools:context=".InteropActivity"
+              android:orientation="vertical" >
+
+    <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal">
+        <EditText
+                android:id="@+id/host_edit_text"
+                android:layout_weight="2"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:hint="Enter Host" />
+        <EditText
+                android:id="@+id/port_edit_text"
+                android:layout_weight="1"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:inputType="numberDecimal"
+                android:hint="Enter Port" />
+    </LinearLayout>
+
+    <Button
+            android:id="@+id/ping_pong_button"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:onClick="doPingPong"
+            android:text="Ping Pong" />
+
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingTop="12dp"
+        android:paddingBottom="12dp"
+        android:textSize="16sp"
+        android:text="Result:" />
+
+    <TextView
+        android:id="@+id/grpc_result_text"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:scrollbars = "vertical"
+        android:textSize="16sp" />
+
+</LinearLayout>
diff --git a/src/android/test/interop/app/src/main/res/mipmap-hdpi/ic_launcher.png b/src/android/test/interop/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..cde69bc
--- /dev/null
+++ b/src/android/test/interop/app/src/main/res/mipmap-hdpi/ic_launcher.png
Binary files differ
diff --git a/src/android/test/interop/app/src/main/res/mipmap-mdpi/ic_launcher.png b/src/android/test/interop/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..c133a0c
--- /dev/null
+++ b/src/android/test/interop/app/src/main/res/mipmap-mdpi/ic_launcher.png
Binary files differ
diff --git a/src/android/test/interop/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/src/android/test/interop/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..bfa42f0
--- /dev/null
+++ b/src/android/test/interop/app/src/main/res/mipmap-xhdpi/ic_launcher.png
Binary files differ
diff --git a/src/android/test/interop/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/src/android/test/interop/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..324e72c
--- /dev/null
+++ b/src/android/test/interop/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/src/android/test/interop/app/src/main/res/values/strings.xml b/src/android/test/interop/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..e63210b
--- /dev/null
+++ b/src/android/test/interop/app/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+<resources>
+    <string name="app_name">gRPC C++ Interop App</string>
+</resources>
diff --git a/src/android/test/interop/build.gradle b/src/android/test/interop/build.gradle
new file mode 100644
index 0000000..bd5f337
--- /dev/null
+++ b/src/android/test/interop/build.gradle
@@ -0,0 +1,24 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+    repositories {
+        google()
+        jcenter()
+    }
+    dependencies {
+        classpath 'com.android.tools.build:gradle:3.0.1'
+        // NOTE: Do not place your application dependencies here; they belong
+        // in the individual module build.gradle files
+    }
+}
+
+allprojects {
+    repositories {
+        google()
+        jcenter()
+    }
+}
+
+task clean(type: Delete) {
+    delete rootProject.buildDir
+}
diff --git a/src/android/test/interop/gradle.properties b/src/android/test/interop/gradle.properties
new file mode 100644
index 0000000..aac7c9b
--- /dev/null
+++ b/src/android/test/interop/gradle.properties
@@ -0,0 +1,17 @@
+# Project-wide Gradle settings.
+
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx1536m
+
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
diff --git a/src/android/test/interop/gradle/wrapper/gradle-wrapper.jar b/src/android/test/interop/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..13372ae
--- /dev/null
+++ b/src/android/test/interop/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/src/android/test/interop/gradle/wrapper/gradle-wrapper.properties b/src/android/test/interop/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..4c81831
--- /dev/null
+++ b/src/android/test/interop/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Thu Jan 25 11:45:30 PST 2018
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip
diff --git a/src/android/test/interop/gradlew b/src/android/test/interop/gradlew
new file mode 100755
index 0000000..9d82f78
--- /dev/null
+++ b/src/android/test/interop/gradlew
@@ -0,0 +1,160 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+##  Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+    echo "$*"
+}
+
+die ( ) {
+    echo
+    echo "$*"
+    echo
+    exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+  CYGWIN* )
+    cygwin=true
+    ;;
+  Darwin* )
+    darwin=true
+    ;;
+  MINGW* )
+    msys=true
+    ;;
+esac
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+        JAVACMD="$JAVA_HOME/bin/java"
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD="java"
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+    MAX_FD_LIMIT=`ulimit -H -n`
+    if [ $? -eq 0 ] ; then
+        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+            MAX_FD="$MAX_FD_LIMIT"
+        fi
+        ulimit -n $MAX_FD
+        if [ $? -ne 0 ] ; then
+            warn "Could not set maximum file descriptor limit: $MAX_FD"
+        fi
+    else
+        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+    fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+    JAVACMD=`cygpath --unix "$JAVACMD"`
+
+    # We build the pattern for arguments to be converted via cygpath
+    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+    SEP=""
+    for dir in $ROOTDIRSRAW ; do
+        ROOTDIRS="$ROOTDIRS$SEP$dir"
+        SEP="|"
+    done
+    OURCYGPATTERN="(^($ROOTDIRS))"
+    # Add a user-defined pattern to the cygpath arguments
+    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+    fi
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    i=0
+    for arg in "$@" ; do
+        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
+
+        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
+            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+        else
+            eval `echo args$i`="\"$arg\""
+        fi
+        i=$((i+1))
+    done
+    case $i in
+        (0) set -- ;;
+        (1) set -- "$args0" ;;
+        (2) set -- "$args0" "$args1" ;;
+        (3) set -- "$args0" "$args1" "$args2" ;;
+        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+    esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+    JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/src/android/test/interop/gradlew.bat b/src/android/test/interop/gradlew.bat
new file mode 100644
index 0000000..8a0b282
--- /dev/null
+++ b/src/android/test/interop/gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem  Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/src/android/test/interop/settings.gradle b/src/android/test/interop/settings.gradle
new file mode 100644
index 0000000..e7b4def
--- /dev/null
+++ b/src/android/test/interop/settings.gradle
@@ -0,0 +1 @@
+include ':app'
diff --git a/src/compiler/node_generator.cc b/src/compiler/node_generator.cc
index 661587c..a430628 100644
--- a/src/compiler/node_generator.cc
+++ b/src/compiler/node_generator.cc
@@ -20,6 +20,7 @@
 
 #include "src/compiler/config.h"
 #include "src/compiler/generator_helpers.h"
+#include "src/compiler/node_generator.h"
 #include "src/compiler/node_generator_helpers.h"
 
 using grpc::protobuf::Descriptor;
@@ -119,7 +120,8 @@
 }
 
 // Prints out the message serializer and deserializer functions
-void PrintMessageTransformer(const Descriptor* descriptor, Printer* out) {
+void PrintMessageTransformer(const Descriptor* descriptor, Printer* out,
+                             const Parameters& params) {
   map<grpc::string, grpc::string> template_vars;
   grpc::string full_name = descriptor->full_name();
   template_vars["identifier_name"] = MessageIdentifierName(full_name);
@@ -134,7 +136,12 @@
              "throw new Error('Expected argument of type $name$');\n");
   out->Outdent();
   out->Print("}\n");
-  out->Print("return new Buffer(arg.serializeBinary());\n");
+  if (params.minimum_node_version > 5) {
+    // Node version is > 5, we should use Buffer.from
+    out->Print("return Buffer.from(arg.serializeBinary());\n");
+  } else {
+    out->Print("return new Buffer(arg.serializeBinary());\n");
+  }
   out->Outdent();
   out->Print("}\n\n");
 
@@ -219,12 +226,13 @@
   out->Print("\n");
 }
 
-void PrintTransformers(const FileDescriptor* file, Printer* out) {
+void PrintTransformers(const FileDescriptor* file, Printer* out,
+                       const Parameters& params) {
   map<grpc::string, const Descriptor*> messages = GetAllMessages(file);
   for (std::map<grpc::string, const Descriptor*>::iterator it =
            messages.begin();
        it != messages.end(); it++) {
-    PrintMessageTransformer(it->second, out);
+    PrintMessageTransformer(it->second, out, params);
   }
   out->Print("\n");
 }
@@ -236,7 +244,8 @@
 }
 }  // namespace
 
-grpc::string GenerateFile(const FileDescriptor* file) {
+grpc::string GenerateFile(const FileDescriptor* file,
+                          const Parameters& params) {
   grpc::string output;
   {
     StringOutputStream output_stream(&output);
@@ -257,7 +266,7 @@
 
     PrintImports(file, &out);
 
-    PrintTransformers(file, &out);
+    PrintTransformers(file, &out, params);
 
     PrintServices(file, &out);
 
diff --git a/src/compiler/node_generator.h b/src/compiler/node_generator.h
index a9ffe75..f3a5315 100644
--- a/src/compiler/node_generator.h
+++ b/src/compiler/node_generator.h
@@ -23,7 +23,14 @@
 
 namespace grpc_node_generator {
 
-grpc::string GenerateFile(const grpc::protobuf::FileDescriptor* file);
+// Contains all the parameters that are parsed from the command line.
+struct Parameters {
+  // Sets the earliest version of nodejs that needs to be supported.
+  int minimum_node_version;
+};
+
+grpc::string GenerateFile(const grpc::protobuf::FileDescriptor* file,
+                          const Parameters& params);
 
 }  // namespace grpc_node_generator
 
diff --git a/src/compiler/node_plugin.cc b/src/compiler/node_plugin.cc
index bc38e90..0d19d8e 100644
--- a/src/compiler/node_plugin.cc
+++ b/src/compiler/node_plugin.cc
@@ -36,7 +36,27 @@
                 const grpc::string& parameter,
                 grpc::protobuf::compiler::GeneratorContext* context,
                 grpc::string* error) const {
-    grpc::string code = GenerateFile(file);
+    grpc_node_generator::Parameters generator_parameters;
+    generator_parameters.minimum_node_version = 4;
+
+    if (!parameter.empty()) {
+      std::vector<grpc::string> parameters_list =
+          grpc_generator::tokenize(parameter, ",");
+      for (auto parameter_string = parameters_list.begin();
+           parameter_string != parameters_list.end(); parameter_string++) {
+        std::vector<grpc::string> param =
+            grpc_generator::tokenize(*parameter_string, "=");
+        if (param[0] == "minimum_node_version") {
+          sscanf(param[1].c_str(), "%d",
+                 &generator_parameters.minimum_node_version);
+        } else {
+          *error = grpc::string("Unknown parameter: ") + *parameter_string;
+          return false;
+        }
+      }
+    }
+
+    grpc::string code = GenerateFile(file, generator_parameters);
     if (code.size() == 0) {
       return true;
     }
diff --git a/src/compiler/objective_c_generator.cc b/src/compiler/objective_c_generator.cc
index ffdeb8f..39f68cb 100644
--- a/src/compiler/objective_c_generator.cc
+++ b/src/compiler/objective_c_generator.cc
@@ -206,7 +206,7 @@
     }
   }
   for (auto one_class : classes) {
-    output += "  @class " + one_class + ";\n";
+    output += "@class " + one_class + ";\n";
   }
 
   return output;
diff --git a/src/compiler/objective_c_plugin.cc b/src/compiler/objective_c_plugin.cc
index 76703d7..f0fe368 100644
--- a/src/compiler/objective_c_plugin.cc
+++ b/src/compiler/objective_c_plugin.cc
@@ -118,11 +118,11 @@
       Write(context, file_name + ".pbrpc.h",
             PreprocIfNot(kForwardDeclare, imports) + "\n" +
                 PreprocIfNot(kProtocolOnly, system_imports) + "\n" +
-                PreprocIfElse(kForwardDeclare, class_declarations,
-                              class_imports) +
-                "\n" + forward_declarations + "\n" + kNonNullBegin + "\n" +
-                protocols + "\n" + PreprocIfNot(kProtocolOnly, interfaces) +
-                "\n" + kNonNullEnd + "\n");
+                class_declarations + "\n" +
+                PreprocIfNot(kForwardDeclare, class_imports) + "\n" +
+                forward_declarations + "\n" + kNonNullBegin + "\n" + protocols +
+                "\n" + PreprocIfNot(kProtocolOnly, interfaces) + "\n" +
+                kNonNullEnd + "\n");
     }
 
     {
diff --git a/src/compiler/ruby_generator.cc b/src/compiler/ruby_generator.cc
index e81dea6..c7af9c3 100644
--- a/src/compiler/ruby_generator.cc
+++ b/src/compiler/ruby_generator.cc
@@ -73,7 +73,7 @@
   // Begin the service module
   std::map<grpc::string, grpc::string> module_vars = ListToDict({
       "module.name",
-      CapitalizeFirst(service->name()),
+      Modularize(service->name()),
   });
   out->Print(module_vars, "module $module.name$\n");
   out->Indent();
diff --git a/src/compiler/ruby_generator_string-inl.h b/src/compiler/ruby_generator_string-inl.h
index fb42978..ecfe796 100644
--- a/src/compiler/ruby_generator_string-inl.h
+++ b/src/compiler/ruby_generator_string-inl.h
@@ -81,13 +81,23 @@
   return true;
 }
 
-// CapitalizeFirst capitalizes the first char in a string.
-inline grpc::string CapitalizeFirst(grpc::string s) {
+// Modularize converts a string into a ruby module compatible name
+inline grpc::string Modularize(grpc::string s) {
   if (s.empty()) {
     return s;
   }
-  s[0] = ::toupper(s[0]);
-  return s;
+  grpc::string new_string = "";
+  bool was_last_underscore = false;
+  new_string.append(1, ::toupper(s[0]));
+  for (grpc::string::size_type i = 1; i < s.size(); ++i) {
+    if (was_last_underscore && s[i] != '_') {
+      new_string.append(1, ::toupper(s[i]));
+    } else if (s[i] != '_') {
+      new_string.append(1, s[i]);
+    }
+    was_last_underscore = s[i] == '_';
+  }
+  return new_string;
 }
 
 // RubyTypeOf updates a proto type to the required ruby equivalent.
@@ -106,7 +116,7 @@
         res += "::";  // switch '.' to the ruby module delim
       }
       if (i < prefixes_and_type.size() - 1) {
-        res += CapitalizeFirst(prefixes_and_type[i]);  // capitalize pkgs
+        res += Modularize(prefixes_and_type[i]);  // capitalize pkgs
       } else {
         res += prefixes_and_type[i];
       }
diff --git a/src/core/ext/filters/client_channel/OWNERS b/src/core/ext/filters/client_channel/OWNERS
index 8f5e928..c8760d9 100644
--- a/src/core/ext/filters/client_channel/OWNERS
+++ b/src/core/ext/filters/client_channel/OWNERS
@@ -1,4 +1,4 @@
 set noparent
 @markdroth
 @dgquintas
-@a11r
+@AspirinSJL
diff --git a/src/core/ext/filters/client_channel/client_channel.cc b/src/core/ext/filters/client_channel/client_channel.cc
index 67dd3a1..80a647f 100644
--- a/src/core/ext/filters/client_channel/client_channel.cc
+++ b/src/core/ext/filters/client_channel/client_channel.cc
@@ -63,6 +63,7 @@
 #include "src/core/lib/transport/status_metadata.h"
 
 using grpc_core::internal::ClientChannelMethodParams;
+using grpc_core::internal::ServerRetryThrottleData;
 
 /* Client channel implementation */
 
@@ -99,7 +100,7 @@
   /** currently active load balancer */
   grpc_core::OrphanablePtr<grpc_core::LoadBalancingPolicy> lb_policy;
   /** retry throttle data */
-  grpc_server_retry_throttle_data* retry_throttle_data;
+  grpc_core::RefCountedPtr<ServerRetryThrottleData> retry_throttle_data;
   /** maps method names to method_parameters structs */
   grpc_core::RefCountedPtr<MethodParamsTable> method_params_table;
   /** incoming resolver result - set by resolver.next() */
@@ -173,7 +174,7 @@
     }
   }
   if (grpc_client_channel_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "chand=%p: setting connectivity state to %s", chand,
+    gpr_log(GPR_INFO, "chand=%p: setting connectivity state to %s", chand,
             grpc_connectivity_state_name(state));
   }
   grpc_connectivity_state_set(&chand->state_tracker, state, error, reason);
@@ -185,7 +186,7 @@
   /* check if the notification is for the latest policy */
   if (w->lb_policy == w->chand->lb_policy.get()) {
     if (grpc_client_channel_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "chand=%p: lb_policy=%p state changed to %s", w->chand,
+      gpr_log(GPR_INFO, "chand=%p: lb_policy=%p state changed to %s", w->chand,
               w->lb_policy, grpc_connectivity_state_name(w->state));
     }
     set_channel_connectivity_state_locked(w->chand, w->state,
@@ -214,7 +215,7 @@
 
 static void start_resolving_locked(channel_data* chand) {
   if (grpc_client_channel_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "chand=%p: starting name resolution", chand);
+    gpr_log(GPR_INFO, "chand=%p: starting name resolution", chand);
   }
   GPR_ASSERT(!chand->started_resolving);
   chand->started_resolving = true;
@@ -225,7 +226,7 @@
 
 typedef struct {
   char* server_name;
-  grpc_server_retry_throttle_data* retry_throttle_data;
+  grpc_core::RefCountedPtr<ServerRetryThrottleData> retry_throttle_data;
 } service_config_parsing_state;
 
 static void parse_retry_throttle_params(
@@ -278,7 +279,7 @@
       }
     }
     parsing_state->retry_throttle_data =
-        grpc_retry_throttle_map_get_data_for_server(
+        grpc_core::internal::ServerRetryThrottleMap::GetDataForServer(
             parsing_state->server_name, max_milli_tokens, milli_token_ratio);
   }
 }
@@ -296,7 +297,7 @@
     return;
   }
   if (grpc_client_channel_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "chand=%p: started name re-resolving", chand);
+    gpr_log(GPR_INFO, "chand=%p: started name re-resolving", chand);
   }
   chand->resolver->RequestReresolutionLocked();
   // Give back the closure to the LB policy.
@@ -310,7 +311,7 @@
 static void on_resolver_result_changed_locked(void* arg, grpc_error* error) {
   channel_data* chand = static_cast<channel_data*>(arg);
   if (grpc_client_channel_trace.enabled()) {
-    gpr_log(GPR_DEBUG,
+    gpr_log(GPR_INFO,
             "chand=%p: got resolver result: resolver_result=%p error=%s", chand,
             chand->resolver_result, grpc_error_string(error));
   }
@@ -321,7 +322,7 @@
   bool lb_policy_name_changed = false;
   grpc_core::OrphanablePtr<grpc_core::LoadBalancingPolicy> new_lb_policy;
   char* service_config_json = nullptr;
-  grpc_server_retry_throttle_data* retry_throttle_data = nullptr;
+  grpc_core::RefCountedPtr<ServerRetryThrottleData> retry_throttle_data;
   grpc_core::RefCountedPtr<MethodParamsTable> method_params_table;
   if (chand->resolver_result != nullptr) {
     if (chand->resolver != nullptr) {
@@ -421,7 +422,7 @@
             service_config->ParseGlobalParams(parse_retry_throttle_params,
                                               &parsing_state);
             grpc_uri_destroy(uri);
-            retry_throttle_data = parsing_state.retry_throttle_data;
+            retry_throttle_data = std::move(parsing_state.retry_throttle_data);
           }
           method_params_table = service_config->CreateMethodConfigTable(
               ClientChannelMethodParams::CreateFromJson);
@@ -430,7 +431,7 @@
     }
   }
   if (grpc_client_channel_trace.enabled()) {
-    gpr_log(GPR_DEBUG,
+    gpr_log(GPR_INFO,
             "chand=%p: resolver result: lb_policy_name=\"%s\"%s, "
             "service_config=\"%s\"",
             chand, lb_policy_name_dup,
@@ -452,10 +453,7 @@
   }
   gpr_mu_unlock(&chand->info_mu);
   // Swap out the retry throttle data.
-  if (chand->retry_throttle_data != nullptr) {
-    grpc_server_retry_throttle_data_unref(chand->retry_throttle_data);
-  }
-  chand->retry_throttle_data = retry_throttle_data;
+  chand->retry_throttle_data = std::move(retry_throttle_data);
   // Swap out the method params table.
   chand->method_params_table = std::move(method_params_table);
   // If we have a new LB policy or are shutting down (in which case
@@ -468,7 +466,7 @@
       chand->resolver == nullptr) {
     if (chand->lb_policy != nullptr) {
       if (grpc_client_channel_trace.enabled()) {
-        gpr_log(GPR_DEBUG, "chand=%p: unreffing lb_policy=%p", chand,
+        gpr_log(GPR_INFO, "chand=%p: unreffing lb_policy=%p", chand,
                 chand->lb_policy.get());
       }
       grpc_pollset_set_del_pollset_set(chand->lb_policy->interested_parties(),
@@ -482,11 +480,11 @@
   // error or shutdown.
   if (error != GRPC_ERROR_NONE || chand->resolver == nullptr) {
     if (grpc_client_channel_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "chand=%p: shutting down", chand);
+      gpr_log(GPR_INFO, "chand=%p: shutting down", chand);
     }
     if (chand->resolver != nullptr) {
       if (grpc_client_channel_trace.enabled()) {
-        gpr_log(GPR_DEBUG, "chand=%p: shutting down resolver", chand);
+        gpr_log(GPR_INFO, "chand=%p: shutting down resolver", chand);
       }
       chand->resolver.reset();
     }
@@ -508,7 +506,7 @@
         GRPC_ERROR_CREATE_FROM_STATIC_STRING("No load balancing policy");
     if (lb_policy_created) {
       if (grpc_client_channel_trace.enabled()) {
-        gpr_log(GPR_DEBUG, "chand=%p: initializing new LB policy", chand);
+        gpr_log(GPR_INFO, "chand=%p: initializing new LB policy", chand);
       }
       GRPC_ERROR_UNREF(state_error);
       state = chand->lb_policy->CheckConnectivityLocked(&state_error);
@@ -725,12 +723,8 @@
   }
   gpr_free(chand->info_lb_policy_name);
   gpr_free(chand->info_service_config_json);
-  if (chand->retry_throttle_data != nullptr) {
-    grpc_server_retry_throttle_data_unref(chand->retry_throttle_data);
-  }
-  if (chand->method_params_table != nullptr) {
-    chand->method_params_table.reset();
-  }
+  chand->retry_throttle_data.reset();
+  chand->method_params_table.reset();
   grpc_client_channel_stop_backup_polling(chand->interested_parties);
   grpc_connectivity_state_destroy(&chand->state_tracker);
   grpc_pollset_set_destroy(chand->interested_parties);
@@ -848,10 +842,11 @@
   bool completed_recv_trailing_metadata : 1;
   // State for callback processing.
   bool retry_dispatched : 1;
-  bool recv_initial_metadata_ready_deferred : 1;
-  bool recv_message_ready_deferred : 1;
+  subchannel_batch_data* recv_initial_metadata_ready_deferred_batch;
   grpc_error* recv_initial_metadata_error;
+  subchannel_batch_data* recv_message_ready_deferred_batch;
   grpc_error* recv_message_error;
+  subchannel_batch_data* recv_trailing_metadata_internal_batch;
 } subchannel_call_retry_state;
 
 // Pending batches stored in call data.
@@ -883,7 +878,7 @@
   grpc_call_stack* owning_call;
   grpc_call_combiner* call_combiner;
 
-  grpc_server_retry_throttle_data* retry_throttle_data;
+  grpc_core::RefCountedPtr<ServerRetryThrottleData> retry_throttle_data;
   grpc_core::RefCountedPtr<ClientChannelMethodParams> method_params;
 
   grpc_subchannel_call* subchannel_call;
@@ -930,7 +925,9 @@
   // Note: We inline the cache for the first 3 send_message ops and use
   // dynamic allocation after that.  This number was essentially picked
   // at random; it could be changed in the future to tune performance.
-  grpc_core::InlinedVector<grpc_core::ByteStreamCache*, 3> send_messages;
+  grpc_core::ManualConstructor<
+      grpc_core::InlinedVector<grpc_core::ByteStreamCache*, 3>>
+      send_messages;
   // send_trailing_metadata
   bool seen_send_trailing_metadata;
   grpc_linked_mdelem* send_trailing_metadata_storage;
@@ -980,7 +977,7 @@
             gpr_arena_alloc(calld->arena, sizeof(grpc_core::ByteStreamCache)));
     new (cache) grpc_core::ByteStreamCache(
         std::move(batch->payload->send_message.send_message));
-    calld->send_messages.push_back(cache);
+    calld->send_messages->push_back(cache);
   }
   // Save metadata batch for send_trailing_metadata ops.
   if (batch->send_trailing_metadata) {
@@ -998,6 +995,39 @@
   }
 }
 
+// Frees cached send_initial_metadata.
+static void free_cached_send_initial_metadata(channel_data* chand,
+                                              call_data* calld) {
+  if (grpc_client_channel_trace.enabled()) {
+    gpr_log(GPR_INFO,
+            "chand=%p calld=%p: destroying calld->send_initial_metadata", chand,
+            calld);
+  }
+  grpc_metadata_batch_destroy(&calld->send_initial_metadata);
+}
+
+// Frees cached send_message at index idx.
+static void free_cached_send_message(channel_data* chand, call_data* calld,
+                                     size_t idx) {
+  if (grpc_client_channel_trace.enabled()) {
+    gpr_log(GPR_INFO,
+            "chand=%p calld=%p: destroying calld->send_messages[%" PRIuPTR "]",
+            chand, calld, idx);
+  }
+  (*calld->send_messages)[idx]->Destroy();
+}
+
+// Frees cached send_trailing_metadata.
+static void free_cached_send_trailing_metadata(channel_data* chand,
+                                               call_data* calld) {
+  if (grpc_client_channel_trace.enabled()) {
+    gpr_log(GPR_INFO,
+            "chand=%p calld=%p: destroying calld->send_trailing_metadata",
+            chand, calld);
+  }
+  grpc_metadata_batch_destroy(&calld->send_trailing_metadata);
+}
+
 // Frees cached send ops that have already been completed after
 // committing the call.
 static void free_cached_send_op_data_after_commit(
@@ -1005,19 +1035,13 @@
   channel_data* chand = static_cast<channel_data*>(elem->channel_data);
   call_data* calld = static_cast<call_data*>(elem->call_data);
   if (retry_state->completed_send_initial_metadata) {
-    grpc_metadata_batch_destroy(&calld->send_initial_metadata);
+    free_cached_send_initial_metadata(chand, calld);
   }
   for (size_t i = 0; i < retry_state->completed_send_message_count; ++i) {
-    if (grpc_client_channel_trace.enabled()) {
-      gpr_log(GPR_DEBUG,
-              "chand=%p calld=%p: destroying calld->send_messages[%" PRIuPTR
-              "]",
-              chand, calld, i);
-    }
-    calld->send_messages[i]->Destroy();
+    free_cached_send_message(chand, calld, i);
   }
   if (retry_state->completed_send_trailing_metadata) {
-    grpc_metadata_batch_destroy(&calld->send_trailing_metadata);
+    free_cached_send_trailing_metadata(chand, calld);
   }
 }
 
@@ -1029,20 +1053,14 @@
   channel_data* chand = static_cast<channel_data*>(elem->channel_data);
   call_data* calld = static_cast<call_data*>(elem->call_data);
   if (batch_data->batch.send_initial_metadata) {
-    grpc_metadata_batch_destroy(&calld->send_initial_metadata);
+    free_cached_send_initial_metadata(chand, calld);
   }
   if (batch_data->batch.send_message) {
-    if (grpc_client_channel_trace.enabled()) {
-      gpr_log(GPR_DEBUG,
-              "chand=%p calld=%p: destroying calld->send_messages[%" PRIuPTR
-              "]",
-              chand, calld, retry_state->completed_send_message_count - 1);
-    }
-    calld->send_messages[retry_state->completed_send_message_count - 1]
-        ->Destroy();
+    free_cached_send_message(chand, calld,
+                             retry_state->completed_send_message_count - 1);
   }
   if (batch_data->batch.send_trailing_metadata) {
-    grpc_metadata_batch_destroy(&calld->send_trailing_metadata);
+    free_cached_send_trailing_metadata(chand, calld);
   }
 }
 
@@ -1070,7 +1088,7 @@
   call_data* calld = static_cast<call_data*>(elem->call_data);
   const size_t idx = get_batch_index(batch);
   if (grpc_client_channel_trace.enabled()) {
-    gpr_log(GPR_DEBUG,
+    gpr_log(GPR_INFO,
             "chand=%p calld=%p: adding pending batch at index %" PRIuPTR, chand,
             calld, idx);
   }
@@ -1098,7 +1116,7 @@
     }
     if (calld->bytes_buffered_for_retry > chand->per_rpc_retry_buffer_size) {
       if (grpc_client_channel_trace.enabled()) {
-        gpr_log(GPR_DEBUG,
+        gpr_log(GPR_INFO,
                 "chand=%p calld=%p: exceeded retry buffer size, committing",
                 chand, calld);
       }
@@ -1113,7 +1131,7 @@
       // retries are disabled so that we don't bother with retry overhead.
       if (calld->num_attempts_completed == 0) {
         if (grpc_client_channel_trace.enabled()) {
-          gpr_log(GPR_DEBUG,
+          gpr_log(GPR_INFO,
                   "chand=%p calld=%p: disabling retries before first attempt",
                   chand, calld);
         }
@@ -1160,7 +1178,7 @@
     for (size_t i = 0; i < GPR_ARRAY_SIZE(calld->pending_batches); ++i) {
       if (calld->pending_batches[i].batch != nullptr) ++num_batches;
     }
-    gpr_log(GPR_DEBUG,
+    gpr_log(GPR_INFO,
             "chand=%p calld=%p: failing %" PRIuPTR " pending batches: %s",
             elem->channel_data, calld, num_batches, grpc_error_string(error));
   }
@@ -1222,7 +1240,7 @@
     for (size_t i = 0; i < GPR_ARRAY_SIZE(calld->pending_batches); ++i) {
       if (calld->pending_batches[i].batch != nullptr) ++num_batches;
     }
-    gpr_log(GPR_DEBUG,
+    gpr_log(GPR_INFO,
             "chand=%p calld=%p: starting %" PRIuPTR
             " pending batches on subchannel_call=%p",
             chand, calld, num_batches, calld->subchannel_call);
@@ -1267,7 +1285,7 @@
       (!batch->recv_message ||
        batch->payload->recv_message.recv_message_ready == nullptr)) {
     if (grpc_client_channel_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "chand=%p calld=%p: clearing pending batch", chand,
+      gpr_log(GPR_INFO, "chand=%p calld=%p: clearing pending batch", chand,
               calld);
     }
     pending_batch_clear(calld, pending);
@@ -1286,7 +1304,8 @@
     return false;
   }
   if (pending->batch->send_message &&
-      retry_state->completed_send_message_count < calld->send_messages.size()) {
+      retry_state->completed_send_message_count <
+          calld->send_messages->size()) {
     return false;
   }
   if (pending->batch->send_trailing_metadata &&
@@ -1321,7 +1340,7 @@
     return true;
   }
   if (pending->batch->send_message &&
-      retry_state->started_send_message_count < calld->send_messages.size()) {
+      retry_state->started_send_message_count < calld->send_messages->size()) {
     return true;
   }
   if (pending->batch->send_trailing_metadata &&
@@ -1356,7 +1375,7 @@
   if (calld->retry_committed) return;
   calld->retry_committed = true;
   if (grpc_client_channel_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "chand=%p calld=%p: committing retries", chand, calld);
+    gpr_log(GPR_INFO, "chand=%p calld=%p: committing retries", chand, calld);
   }
   if (retry_state != nullptr) {
     free_cached_send_op_data_after_commit(elem, retry_state);
@@ -1401,7 +1420,7 @@
     next_attempt_time = calld->retry_backoff->NextAttemptTime();
   }
   if (grpc_client_channel_trace.enabled()) {
-    gpr_log(GPR_DEBUG,
+    gpr_log(GPR_INFO,
             "chand=%p calld=%p: retrying failed call in %" PRIuPTR " ms", chand,
             calld, next_attempt_time - grpc_core::ExecCtx::Get()->Now());
   }
@@ -1435,7 +1454,7 @@
             batch_data->subchannel_call));
     if (retry_state->retry_dispatched) {
       if (grpc_client_channel_trace.enabled()) {
-        gpr_log(GPR_DEBUG, "chand=%p calld=%p: retry already dispatched", chand,
+        gpr_log(GPR_INFO, "chand=%p calld=%p: retry already dispatched", chand,
                 calld);
       }
       return true;
@@ -1443,16 +1462,18 @@
   }
   // Check status.
   if (status == GRPC_STATUS_OK) {
-    grpc_server_retry_throttle_data_record_success(calld->retry_throttle_data);
+    if (calld->retry_throttle_data != nullptr) {
+      calld->retry_throttle_data->RecordSuccess();
+    }
     if (grpc_client_channel_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "chand=%p calld=%p: call succeeded", chand, calld);
+      gpr_log(GPR_INFO, "chand=%p calld=%p: call succeeded", chand, calld);
     }
     return false;
   }
   // Status is not OK.  Check whether the status is retryable.
   if (!retry_policy->retryable_status_codes.Contains(status)) {
     if (grpc_client_channel_trace.enabled()) {
-      gpr_log(GPR_DEBUG,
+      gpr_log(GPR_INFO,
               "chand=%p calld=%p: status %s not configured as retryable", chand,
               calld, grpc_status_code_to_string(status));
     }
@@ -1465,17 +1486,17 @@
   // things like failures due to malformed requests (INVALID_ARGUMENT).
   // Conversely, it's important for this to come before the remaining
   // checks, so that we don't fail to record failures due to other factors.
-  if (!grpc_server_retry_throttle_data_record_failure(
-          calld->retry_throttle_data)) {
+  if (calld->retry_throttle_data != nullptr &&
+      !calld->retry_throttle_data->RecordFailure()) {
     if (grpc_client_channel_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "chand=%p calld=%p: retries throttled", chand, calld);
+      gpr_log(GPR_INFO, "chand=%p calld=%p: retries throttled", chand, calld);
     }
     return false;
   }
   // Check whether the call is committed.
   if (calld->retry_committed) {
     if (grpc_client_channel_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "chand=%p calld=%p: retries already committed", chand,
+      gpr_log(GPR_INFO, "chand=%p calld=%p: retries already committed", chand,
               calld);
     }
     return false;
@@ -1484,7 +1505,7 @@
   ++calld->num_attempts_completed;
   if (calld->num_attempts_completed >= retry_policy->max_attempts) {
     if (grpc_client_channel_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "chand=%p calld=%p: exceeded %d retry attempts", chand,
+      gpr_log(GPR_INFO, "chand=%p calld=%p: exceeded %d retry attempts", chand,
               calld, retry_policy->max_attempts);
     }
     return false;
@@ -1492,7 +1513,7 @@
   // If the call was cancelled from the surface, don't retry.
   if (calld->cancel_error != GRPC_ERROR_NONE) {
     if (grpc_client_channel_trace.enabled()) {
-      gpr_log(GPR_DEBUG,
+      gpr_log(GPR_INFO,
               "chand=%p calld=%p: call cancelled from surface, not retrying",
               chand, calld);
     }
@@ -1505,16 +1526,15 @@
     uint32_t ms;
     if (!grpc_parse_slice_to_uint32(GRPC_MDVALUE(*server_pushback_md), &ms)) {
       if (grpc_client_channel_trace.enabled()) {
-        gpr_log(GPR_DEBUG,
+        gpr_log(GPR_INFO,
                 "chand=%p calld=%p: not retrying due to server push-back",
                 chand, calld);
       }
       return false;
     } else {
       if (grpc_client_channel_trace.enabled()) {
-        gpr_log(GPR_DEBUG,
-                "chand=%p calld=%p: server push-back: retry in %u ms", chand,
-                calld, ms);
+        gpr_log(GPR_INFO, "chand=%p calld=%p: server push-back: retry in %u ms",
+                chand, calld, ms);
       }
       server_pushback_ms = (grpc_millis)ms;
     }
@@ -1587,7 +1607,7 @@
         batch->payload->recv_initial_metadata.recv_initial_metadata_ready !=
             nullptr) {
       if (grpc_client_channel_trace.enabled()) {
-        gpr_log(GPR_DEBUG,
+        gpr_log(GPR_INFO,
                 "chand=%p calld=%p: invoking recv_initial_metadata_ready for "
                 "pending batch at index %" PRIuPTR,
                 chand, calld, i);
@@ -1623,7 +1643,7 @@
   channel_data* chand = static_cast<channel_data*>(elem->channel_data);
   call_data* calld = static_cast<call_data*>(elem->call_data);
   if (grpc_client_channel_trace.enabled()) {
-    gpr_log(GPR_DEBUG,
+    gpr_log(GPR_INFO,
             "chand=%p calld=%p: got recv_initial_metadata_ready, error=%s",
             chand, calld, grpc_error_string(error));
   }
@@ -1638,12 +1658,12 @@
   if ((batch_data->trailing_metadata_available || error != GRPC_ERROR_NONE) &&
       !retry_state->completed_recv_trailing_metadata) {
     if (grpc_client_channel_trace.enabled()) {
-      gpr_log(GPR_DEBUG,
+      gpr_log(GPR_INFO,
               "chand=%p calld=%p: deferring recv_initial_metadata_ready "
               "(Trailers-Only)",
               chand, calld);
     }
-    retry_state->recv_initial_metadata_ready_deferred = true;
+    retry_state->recv_initial_metadata_ready_deferred_batch = batch_data;
     retry_state->recv_initial_metadata_error = GRPC_ERROR_REF(error);
     if (!retry_state->started_recv_trailing_metadata) {
       // recv_trailing_metadata not yet started by application; start it
@@ -1680,7 +1700,7 @@
     if (batch != nullptr && batch->recv_message &&
         batch->payload->recv_message.recv_message_ready != nullptr) {
       if (grpc_client_channel_trace.enabled()) {
-        gpr_log(GPR_DEBUG,
+        gpr_log(GPR_INFO,
                 "chand=%p calld=%p: invoking recv_message_ready for "
                 "pending batch at index %" PRIuPTR,
                 chand, calld, i);
@@ -1713,7 +1733,7 @@
   channel_data* chand = static_cast<channel_data*>(elem->channel_data);
   call_data* calld = static_cast<call_data*>(elem->call_data);
   if (grpc_client_channel_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "chand=%p calld=%p: got recv_message_ready, error=%s",
+    gpr_log(GPR_INFO, "chand=%p calld=%p: got recv_message_ready, error=%s",
             chand, calld, grpc_error_string(error));
   }
   subchannel_call_retry_state* retry_state =
@@ -1727,12 +1747,12 @@
   if ((batch_data->recv_message == nullptr || error != GRPC_ERROR_NONE) &&
       !retry_state->completed_recv_trailing_metadata) {
     if (grpc_client_channel_trace.enabled()) {
-      gpr_log(GPR_DEBUG,
+      gpr_log(GPR_INFO,
               "chand=%p calld=%p: deferring recv_message_ready (nullptr "
               "message and recv_trailing_metadata pending)",
               chand, calld);
     }
-    retry_state->recv_message_ready_deferred = true;
+    retry_state->recv_message_ready_deferred_batch = batch_data;
     retry_state->recv_message_error = GRPC_ERROR_REF(error);
     if (!retry_state->started_recv_trailing_metadata) {
       // recv_trailing_metadata not yet started by application; start it
@@ -1751,6 +1771,59 @@
 }
 
 //
+// list of closures to execute in call combiner
+//
+
+// Represents a closure that needs to run in the call combiner as part of
+// starting or completing a batch.
+typedef struct {
+  grpc_closure* closure;
+  grpc_error* error;
+  const char* reason;
+  bool free_reason = false;
+} closure_to_execute;
+
+static void execute_closures_in_call_combiner(grpc_call_element* elem,
+                                              const char* caller,
+                                              closure_to_execute* closures,
+                                              size_t num_closures) {
+  channel_data* chand = static_cast<channel_data*>(elem->channel_data);
+  call_data* calld = static_cast<call_data*>(elem->call_data);
+  // Note that the call combiner will be yielded for each closure that
+  // we schedule.  We're already running in the call combiner, so one of
+  // the closures can be scheduled directly, but the others will
+  // have to re-enter the call combiner.
+  if (num_closures > 0) {
+    if (grpc_client_channel_trace.enabled()) {
+      gpr_log(GPR_INFO, "chand=%p calld=%p: %s starting closure: %s", chand,
+              calld, caller, closures[0].reason);
+    }
+    GRPC_CLOSURE_SCHED(closures[0].closure, closures[0].error);
+    if (closures[0].free_reason) {
+      gpr_free(const_cast<char*>(closures[0].reason));
+    }
+    for (size_t i = 1; i < num_closures; ++i) {
+      if (grpc_client_channel_trace.enabled()) {
+        gpr_log(GPR_INFO,
+                "chand=%p calld=%p: %s starting closure in call combiner: %s",
+                chand, calld, caller, closures[i].reason);
+      }
+      GRPC_CALL_COMBINER_START(calld->call_combiner, closures[i].closure,
+                               closures[i].error, closures[i].reason);
+      if (closures[i].free_reason) {
+        gpr_free(const_cast<char*>(closures[i].reason));
+      }
+    }
+  } else {
+    if (grpc_client_channel_trace.enabled()) {
+      gpr_log(GPR_INFO, "chand=%p calld=%p: no closures to run for %s", chand,
+              calld, caller);
+    }
+    GRPC_CALL_COMBINER_STOP(calld->call_combiner, "no closures to run");
+  }
+}
+
+//
 // on_complete callback handling
 //
 
@@ -1778,36 +1851,35 @@
   }
 }
 
-// Represents a closure that needs to run as a result of a completed batch.
-typedef struct {
-  grpc_closure* closure;
-  grpc_error* error;
-  const char* reason;
-} closure_to_execute;
-
 // Adds any necessary closures for deferred recv_initial_metadata and
 // recv_message callbacks to closures, updating *num_closures as needed.
 static void add_closures_for_deferred_recv_callbacks(
     subchannel_batch_data* batch_data, subchannel_call_retry_state* retry_state,
     closure_to_execute* closures, size_t* num_closures) {
-  if (batch_data->batch.recv_trailing_metadata &&
-      retry_state->recv_initial_metadata_ready_deferred) {
-    closure_to_execute* closure = &closures[(*num_closures)++];
-    closure->closure =
-        GRPC_CLOSURE_INIT(&batch_data->recv_initial_metadata_ready,
-                          invoke_recv_initial_metadata_callback, batch_data,
-                          grpc_schedule_on_exec_ctx);
-    closure->error = retry_state->recv_initial_metadata_error;
-    closure->reason = "resuming recv_initial_metadata_ready";
-  }
-  if (batch_data->batch.recv_trailing_metadata &&
-      retry_state->recv_message_ready_deferred) {
-    closure_to_execute* closure = &closures[(*num_closures)++];
-    closure->closure = GRPC_CLOSURE_INIT(&batch_data->recv_message_ready,
-                                         invoke_recv_message_callback,
-                                         batch_data, grpc_schedule_on_exec_ctx);
-    closure->error = retry_state->recv_message_error;
-    closure->reason = "resuming recv_message_ready";
+  if (batch_data->batch.recv_trailing_metadata) {
+    // Add closure for deferred recv_initial_metadata_ready.
+    if (retry_state->recv_initial_metadata_ready_deferred_batch != nullptr) {
+      closure_to_execute* closure = &closures[(*num_closures)++];
+      closure->closure = GRPC_CLOSURE_INIT(
+          &batch_data->recv_initial_metadata_ready,
+          invoke_recv_initial_metadata_callback,
+          retry_state->recv_initial_metadata_ready_deferred_batch,
+          grpc_schedule_on_exec_ctx);
+      closure->error = retry_state->recv_initial_metadata_error;
+      closure->reason = "resuming recv_initial_metadata_ready";
+      retry_state->recv_initial_metadata_ready_deferred_batch = nullptr;
+    }
+    // Add closure for deferred recv_message_ready.
+    if (retry_state->recv_message_ready_deferred_batch != nullptr) {
+      closure_to_execute* closure = &closures[(*num_closures)++];
+      closure->closure = GRPC_CLOSURE_INIT(
+          &batch_data->recv_message_ready, invoke_recv_message_callback,
+          retry_state->recv_message_ready_deferred_batch,
+          grpc_schedule_on_exec_ctx);
+      closure->error = retry_state->recv_message_error;
+      closure->reason = "resuming recv_message_ready";
+      retry_state->recv_message_ready_deferred_batch = nullptr;
+    }
   }
 }
 
@@ -1821,7 +1893,7 @@
   channel_data* chand = static_cast<channel_data*>(elem->channel_data);
   call_data* calld = static_cast<call_data*>(elem->call_data);
   bool have_pending_send_message_ops =
-      retry_state->started_send_message_count < calld->send_messages.size();
+      retry_state->started_send_message_count < calld->send_messages->size();
   bool have_pending_send_trailing_metadata_op =
       calld->seen_send_trailing_metadata &&
       !retry_state->started_send_trailing_metadata;
@@ -1839,7 +1911,7 @@
   }
   if (have_pending_send_message_ops || have_pending_send_trailing_metadata_op) {
     if (grpc_client_channel_trace.enabled()) {
-      gpr_log(GPR_DEBUG,
+      gpr_log(GPR_INFO,
               "chand=%p calld=%p: starting next batch for pending send op(s)",
               chand, calld);
     }
@@ -1864,7 +1936,7 @@
     pending_batch* pending = &calld->pending_batches[i];
     if (pending_batch_is_completed(pending, calld, retry_state)) {
       if (grpc_client_channel_trace.enabled()) {
-        gpr_log(GPR_DEBUG,
+        gpr_log(GPR_INFO,
                 "chand=%p calld=%p: pending batch completed at index %" PRIuPTR,
                 chand, calld, i);
       }
@@ -1897,7 +1969,7 @@
     pending_batch* pending = &calld->pending_batches[i];
     if (pending_batch_is_unstarted(pending, calld, retry_state)) {
       if (grpc_client_channel_trace.enabled()) {
-        gpr_log(GPR_DEBUG,
+        gpr_log(GPR_INFO,
                 "chand=%p calld=%p: failing unstarted pending batch at index "
                 "%" PRIuPTR,
                 chand, calld, i);
@@ -1941,7 +2013,7 @@
   call_data* calld = static_cast<call_data*>(elem->call_data);
   if (grpc_client_channel_trace.enabled()) {
     char* batch_str = grpc_transport_stream_op_batch_string(&batch_data->batch);
-    gpr_log(GPR_DEBUG, "chand=%p calld=%p: got on_complete, error=%s, batch=%s",
+    gpr_log(GPR_INFO, "chand=%p calld=%p: got on_complete, error=%s, batch=%s",
             chand, calld, grpc_error_string(error), batch_str);
     gpr_free(batch_str);
   }
@@ -1952,11 +2024,13 @@
   // If we have previously completed recv_trailing_metadata, then the
   // call is finished.
   bool call_finished = retry_state->completed_recv_trailing_metadata;
+  // Record whether we were already committed before receiving this callback.
+  const bool previously_committed = calld->retry_committed;
   // Update bookkeeping in retry_state.
   update_retry_state_for_completed_batch(batch_data, retry_state);
   if (call_finished) {
     if (grpc_client_channel_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "chand=%p calld=%p: call already finished", chand,
+      gpr_log(GPR_INFO, "chand=%p calld=%p: call already finished", chand,
               calld);
     }
   } else {
@@ -1980,35 +2054,39 @@
       if (md_batch->idx.named.grpc_retry_pushback_ms != nullptr) {
         server_pushback_md = &md_batch->idx.named.grpc_retry_pushback_ms->md;
       }
-    } else if (retry_state->completed_recv_trailing_metadata) {
-      call_finished = true;
     }
-    if (call_finished && grpc_client_channel_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "chand=%p calld=%p: call finished, status=%s", chand,
-              calld, grpc_status_code_to_string(status));
-    }
-    // If the call is finished, check if we should retry.
-    if (call_finished &&
-        maybe_retry(elem, batch_data, status, server_pushback_md)) {
-      // Unref batch_data for deferred recv_initial_metadata_ready or
-      // recv_message_ready callbacks, if any.
-      if (batch_data->batch.recv_trailing_metadata &&
-          retry_state->recv_initial_metadata_ready_deferred) {
-        batch_data_unref(batch_data);
-        GRPC_ERROR_UNREF(retry_state->recv_initial_metadata_error);
+    // If the call just finished, check if we should retry.
+    if (call_finished) {
+      if (grpc_client_channel_trace.enabled()) {
+        gpr_log(GPR_INFO, "chand=%p calld=%p: call finished, status=%s", chand,
+                calld, grpc_status_code_to_string(status));
       }
-      if (batch_data->batch.recv_trailing_metadata &&
-          retry_state->recv_message_ready_deferred) {
+      if (maybe_retry(elem, batch_data, status, server_pushback_md)) {
+        // Unref batch_data for deferred recv_initial_metadata_ready or
+        // recv_message_ready callbacks, if any.
+        if (batch_data->batch.recv_trailing_metadata &&
+            retry_state->recv_initial_metadata_ready_deferred_batch !=
+                nullptr) {
+          batch_data_unref(batch_data);
+          GRPC_ERROR_UNREF(retry_state->recv_initial_metadata_error);
+        }
+        if (batch_data->batch.recv_trailing_metadata &&
+            retry_state->recv_message_ready_deferred_batch != nullptr) {
+          batch_data_unref(batch_data);
+          GRPC_ERROR_UNREF(retry_state->recv_message_error);
+        }
         batch_data_unref(batch_data);
-        GRPC_ERROR_UNREF(retry_state->recv_message_error);
+        return;
       }
-      batch_data_unref(batch_data);
-      return;
+      // Not retrying, so commit the call.
+      retry_commit(elem, retry_state);
     }
   }
-  // If the call is finished or retries are committed, free cached data for
-  // send ops that we've just completed.
-  if (call_finished || calld->retry_committed) {
+  // If we were already committed before receiving this callback, free
+  // cached data for send ops that we've just completed.  (If the call has
+  // just now finished, the call to retry_commit() above will have freed all
+  // cached send ops, so we don't need to do it here.)
+  if (previously_committed) {
     free_cached_send_op_data_for_completed_batch(elem, batch_data, retry_state);
   }
   // Call not being retried.
@@ -2043,20 +2121,8 @@
   // Don't need batch_data anymore.
   batch_data_unref(batch_data);
   // Schedule all of the closures identified above.
-  // Note that the call combiner will be yielded for each closure that
-  // we schedule.  We're already running in the call combiner, so one of
-  // the closures can be scheduled directly, but the others will
-  // have to re-enter the call combiner.
-  if (num_closures > 0) {
-    GRPC_CLOSURE_SCHED(closures[0].closure, closures[0].error);
-    for (size_t i = 1; i < num_closures; ++i) {
-      GRPC_CALL_COMBINER_START(calld->call_combiner, closures[i].closure,
-                               closures[i].error, closures[i].reason);
-    }
-  } else {
-    GRPC_CALL_COMBINER_STOP(calld->call_combiner,
-                            "no closures to run for on_complete");
-  }
+  execute_closures_in_call_combiner(elem, "on_complete", closures,
+                                    num_closures);
 }
 
 //
@@ -2073,6 +2139,31 @@
   grpc_subchannel_call_process_op(subchannel_call, batch);
 }
 
+// Adds a closure to closures that will execute batch in the call combiner.
+static void add_closure_for_subchannel_batch(
+    call_data* calld, grpc_transport_stream_op_batch* batch,
+    closure_to_execute* closures, size_t* num_closures) {
+  batch->handler_private.extra_arg = calld->subchannel_call;
+  GRPC_CLOSURE_INIT(&batch->handler_private.closure,
+                    start_batch_in_call_combiner, batch,
+                    grpc_schedule_on_exec_ctx);
+  closure_to_execute* closure = &closures[(*num_closures)++];
+  closure->closure = &batch->handler_private.closure;
+  closure->error = GRPC_ERROR_NONE;
+  // If the tracer is enabled, we log a more detailed message, which
+  // requires dynamic allocation.  This will be freed in
+  // start_retriable_subchannel_batches().
+  if (grpc_client_channel_trace.enabled()) {
+    char* batch_str = grpc_transport_stream_op_batch_string(batch);
+    gpr_asprintf(const_cast<char**>(&closure->reason),
+                 "starting batch in call combiner: %s", batch_str);
+    gpr_free(batch_str);
+    closure->free_reason = true;
+  } else {
+    closure->reason = "start_subchannel_batch";
+  }
+}
+
 // Adds retriable send_initial_metadata op to batch_data.
 static void add_retriable_send_initial_metadata_op(
     call_data* calld, subchannel_call_retry_state* retry_state,
@@ -2132,12 +2223,12 @@
   channel_data* chand = static_cast<channel_data*>(elem->channel_data);
   call_data* calld = static_cast<call_data*>(elem->call_data);
   if (grpc_client_channel_trace.enabled()) {
-    gpr_log(GPR_DEBUG,
+    gpr_log(GPR_INFO,
             "chand=%p calld=%p: starting calld->send_messages[%" PRIuPTR "]",
             chand, calld, retry_state->started_send_message_count);
   }
   grpc_core::ByteStreamCache* cache =
-      calld->send_messages[retry_state->started_send_message_count];
+      (*calld->send_messages)[retry_state->started_send_message_count];
   ++retry_state->started_send_message_count;
   batch_data->send_message.Init(cache);
   batch_data->batch.send_message = true;
@@ -2219,7 +2310,7 @@
   channel_data* chand = static_cast<channel_data*>(elem->channel_data);
   call_data* calld = static_cast<call_data*>(elem->call_data);
   if (grpc_client_channel_trace.enabled()) {
-    gpr_log(GPR_DEBUG,
+    gpr_log(GPR_INFO,
             "chand=%p calld=%p: call failed but recv_trailing_metadata not "
             "started; starting it internally",
             chand, calld);
@@ -2228,8 +2319,12 @@
       static_cast<subchannel_call_retry_state*>(
           grpc_connected_subchannel_call_get_parent_data(
               calld->subchannel_call));
-  subchannel_batch_data* batch_data = batch_data_create(elem, 1);
+  // Create batch_data with 2 refs, since this batch will be unreffed twice:
+  // once when the subchannel batch returns, and again when we actually get
+  // a recv_trailing_metadata op from the surface.
+  subchannel_batch_data* batch_data = batch_data_create(elem, 2);
   add_retriable_recv_trailing_metadata_op(calld, retry_state, batch_data);
+  retry_state->recv_trailing_metadata_internal_batch = batch_data;
   // Note: This will release the call combiner.
   grpc_subchannel_call_process_op(calld->subchannel_call, &batch_data->batch);
 }
@@ -2247,7 +2342,7 @@
       !retry_state->started_send_initial_metadata &&
       !calld->pending_send_initial_metadata) {
     if (grpc_client_channel_trace.enabled()) {
-      gpr_log(GPR_DEBUG,
+      gpr_log(GPR_INFO,
               "chand=%p calld=%p: replaying previously completed "
               "send_initial_metadata op",
               chand, calld);
@@ -2258,12 +2353,12 @@
   }
   // send_message.
   // Note that we can only have one send_message op in flight at a time.
-  if (retry_state->started_send_message_count < calld->send_messages.size() &&
+  if (retry_state->started_send_message_count < calld->send_messages->size() &&
       retry_state->started_send_message_count ==
           retry_state->completed_send_message_count &&
       !calld->pending_send_message) {
     if (grpc_client_channel_trace.enabled()) {
-      gpr_log(GPR_DEBUG,
+      gpr_log(GPR_INFO,
               "chand=%p calld=%p: replaying previously completed "
               "send_message op",
               chand, calld);
@@ -2278,11 +2373,11 @@
   // to start, since we can't send down any more send_message ops after
   // send_trailing_metadata.
   if (calld->seen_send_trailing_metadata &&
-      retry_state->started_send_message_count == calld->send_messages.size() &&
+      retry_state->started_send_message_count == calld->send_messages->size() &&
       !retry_state->started_send_trailing_metadata &&
       !calld->pending_send_trailing_metadata) {
     if (grpc_client_channel_trace.enabled()) {
-      gpr_log(GPR_DEBUG,
+      gpr_log(GPR_INFO,
               "chand=%p calld=%p: replaying previously completed "
               "send_trailing_metadata op",
               chand, calld);
@@ -2300,7 +2395,7 @@
 // *num_batches as needed.
 static void add_subchannel_batches_for_pending_batches(
     grpc_call_element* elem, subchannel_call_retry_state* retry_state,
-    grpc_transport_stream_op_batch** batches, size_t* num_batches) {
+    closure_to_execute* closures, size_t* num_closures) {
   call_data* calld = static_cast<call_data*>(elem->call_data);
   for (size_t i = 0; i < GPR_ARRAY_SIZE(calld->pending_batches); ++i) {
     pending_batch* pending = &calld->pending_batches[i];
@@ -2329,7 +2424,7 @@
     // send_message ops after send_trailing_metadata.
     if (batch->send_trailing_metadata &&
         (retry_state->started_send_message_count + batch->send_message <
-             calld->send_messages.size() ||
+             calld->send_messages->size() ||
          retry_state->started_send_trailing_metadata)) {
       continue;
     }
@@ -2343,13 +2438,37 @@
     }
     if (batch->recv_trailing_metadata &&
         retry_state->started_recv_trailing_metadata) {
+      // If we previously completed a recv_trailing_metadata op
+      // initiated by start_internal_recv_trailing_metadata(), use the
+      // result of that instead of trying to re-start this op.
+      if (retry_state->recv_trailing_metadata_internal_batch != nullptr) {
+        // If the batch completed, then trigger the completion callback
+        // directly, so that we return the previously returned results to
+        // the application.  Otherwise, just unref the internally
+        // started subchannel batch, since we'll propagate the
+        // completion when it completes.
+        if (retry_state->completed_recv_trailing_metadata) {
+          subchannel_batch_data* batch_data =
+              retry_state->recv_trailing_metadata_internal_batch;
+          closure_to_execute* closure = &closures[(*num_closures)++];
+          closure->closure = &batch_data->on_complete;
+          // Batches containing recv_trailing_metadata always succeed.
+          closure->error = GRPC_ERROR_NONE;
+          closure->reason =
+              "re-executing on_complete for recv_trailing_metadata "
+              "to propagate internally triggered result";
+        } else {
+          batch_data_unref(retry_state->recv_trailing_metadata_internal_batch);
+        }
+        retry_state->recv_trailing_metadata_internal_batch = nullptr;
+      }
       continue;
     }
     // If we're not retrying, just send the batch as-is.
     if (calld->method_params == nullptr ||
         calld->method_params->retry_policy() == nullptr ||
         calld->retry_committed) {
-      batches[(*num_batches)++] = batch;
+      add_closure_for_subchannel_batch(calld, batch, closures, num_closures);
       pending_batch_clear(calld, pending);
       continue;
     }
@@ -2386,7 +2505,8 @@
       GPR_ASSERT(batch->collect_stats);
       add_retriable_recv_trailing_metadata_op(calld, retry_state, batch_data);
     }
-    batches[(*num_batches)++] = &batch_data->batch;
+    add_closure_for_subchannel_batch(calld, &batch_data->batch, closures,
+                                     num_closures);
   }
 }
 
@@ -2397,69 +2517,36 @@
   channel_data* chand = static_cast<channel_data*>(elem->channel_data);
   call_data* calld = static_cast<call_data*>(elem->call_data);
   if (grpc_client_channel_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "chand=%p calld=%p: constructing retriable batches",
+    gpr_log(GPR_INFO, "chand=%p calld=%p: constructing retriable batches",
             chand, calld);
   }
   subchannel_call_retry_state* retry_state =
       static_cast<subchannel_call_retry_state*>(
           grpc_connected_subchannel_call_get_parent_data(
               calld->subchannel_call));
+  // Construct list of closures to execute, one for each pending batch.
   // We can start up to 6 batches.
-  grpc_transport_stream_op_batch*
-      batches[GPR_ARRAY_SIZE(calld->pending_batches)];
-  size_t num_batches = 0;
+  closure_to_execute closures[GPR_ARRAY_SIZE(calld->pending_batches)];
+  size_t num_closures = 0;
   // Replay previously-returned send_* ops if needed.
   subchannel_batch_data* replay_batch_data =
       maybe_create_subchannel_batch_for_replay(elem, retry_state);
   if (replay_batch_data != nullptr) {
-    batches[num_batches++] = &replay_batch_data->batch;
+    add_closure_for_subchannel_batch(calld, &replay_batch_data->batch, closures,
+                                     &num_closures);
   }
   // Now add pending batches.
-  add_subchannel_batches_for_pending_batches(elem, retry_state, batches,
-                                             &num_batches);
+  add_subchannel_batches_for_pending_batches(elem, retry_state, closures,
+                                             &num_closures);
   // Start batches on subchannel call.
-  // Note that the call combiner will be yielded for each batch that we
-  // send down.  We're already running in the call combiner, so one of
-  // the batches can be started directly, but the others will have to
-  // re-enter the call combiner.
   if (grpc_client_channel_trace.enabled()) {
-    gpr_log(GPR_DEBUG,
+    gpr_log(GPR_INFO,
             "chand=%p calld=%p: starting %" PRIuPTR
             " retriable batches on subchannel_call=%p",
-            chand, calld, num_batches, calld->subchannel_call);
+            chand, calld, num_closures, calld->subchannel_call);
   }
-  if (num_batches == 0) {
-    // This should be fairly rare, but it can happen when (e.g.) an
-    // attempt completes before it has finished replaying all
-    // previously sent messages.
-    GRPC_CALL_COMBINER_STOP(calld->call_combiner,
-                            "no retriable subchannel batches to start");
-  } else {
-    for (size_t i = 1; i < num_batches; ++i) {
-      if (grpc_client_channel_trace.enabled()) {
-        char* batch_str = grpc_transport_stream_op_batch_string(batches[i]);
-        gpr_log(GPR_DEBUG,
-                "chand=%p calld=%p: starting batch in call combiner: %s", chand,
-                calld, batch_str);
-        gpr_free(batch_str);
-      }
-      batches[i]->handler_private.extra_arg = calld->subchannel_call;
-      GRPC_CLOSURE_INIT(&batches[i]->handler_private.closure,
-                        start_batch_in_call_combiner, batches[i],
-                        grpc_schedule_on_exec_ctx);
-      GRPC_CALL_COMBINER_START(calld->call_combiner,
-                               &batches[i]->handler_private.closure,
-                               GRPC_ERROR_NONE, "start_subchannel_batch");
-    }
-    if (grpc_client_channel_trace.enabled()) {
-      char* batch_str = grpc_transport_stream_op_batch_string(batches[0]);
-      gpr_log(GPR_DEBUG, "chand=%p calld=%p: starting batch: %s", chand, calld,
-              batch_str);
-      gpr_free(batch_str);
-    }
-    // Note: This will release the call combiner.
-    grpc_subchannel_call_process_op(calld->subchannel_call, batches[0]);
-  }
+  execute_closures_in_call_combiner(elem, "start_retriable_subchannel_batches",
+                                    closures, num_closures);
 }
 
 //
@@ -2484,7 +2571,7 @@
   grpc_error* new_error = calld->pick.connected_subchannel->CreateCall(
       call_args, &calld->subchannel_call);
   if (grpc_client_channel_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "chand=%p calld=%p: create subchannel_call=%p: error=%s",
+    gpr_log(GPR_INFO, "chand=%p calld=%p: create subchannel_call=%p: error=%s",
             chand, calld, calld->subchannel_call, grpc_error_string(new_error));
   }
   if (new_error != GRPC_ERROR_NONE) {
@@ -2525,7 +2612,7 @@
               : GRPC_ERROR_CREATE_REFERENCING_FROM_STATIC_STRING(
                     "Failed to create subchannel", &error, 1);
       if (grpc_client_channel_trace.enabled()) {
-        gpr_log(GPR_DEBUG,
+        gpr_log(GPR_INFO,
                 "chand=%p calld=%p: failed to create subchannel: error=%s",
                 chand, calld, grpc_error_string(new_error));
       }
@@ -2569,7 +2656,7 @@
   // the one we started it on.  However, this will just be a no-op.
   if (error != GRPC_ERROR_NONE && chand->lb_policy != nullptr) {
     if (grpc_client_channel_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "chand=%p calld=%p: cancelling pick from LB policy %p",
+      gpr_log(GPR_INFO, "chand=%p calld=%p: cancelling pick from LB policy %p",
               chand, calld, chand->lb_policy.get());
     }
     chand->lb_policy->CancelPickLocked(&calld->pick, GRPC_ERROR_REF(error));
@@ -2584,8 +2671,8 @@
   channel_data* chand = static_cast<channel_data*>(elem->channel_data);
   call_data* calld = static_cast<call_data*>(elem->call_data);
   if (grpc_client_channel_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "chand=%p calld=%p: pick completed asynchronously",
-            chand, calld);
+    gpr_log(GPR_INFO, "chand=%p calld=%p: pick completed asynchronously", chand,
+            calld);
   }
   async_pick_done_locked(elem, GRPC_ERROR_REF(error));
   GRPC_CALL_STACK_UNREF(calld->owning_call, "pick_callback");
@@ -2597,12 +2684,11 @@
   channel_data* chand = static_cast<channel_data*>(elem->channel_data);
   call_data* calld = static_cast<call_data*>(elem->call_data);
   if (grpc_client_channel_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "chand=%p calld=%p: applying service config to call",
+    gpr_log(GPR_INFO, "chand=%p calld=%p: applying service config to call",
             chand, calld);
   }
   if (chand->retry_throttle_data != nullptr) {
-    calld->retry_throttle_data =
-        grpc_server_retry_throttle_data_ref(chand->retry_throttle_data);
+    calld->retry_throttle_data = chand->retry_throttle_data->Ref();
   }
   if (chand->method_params_table != nullptr) {
     calld->method_params = grpc_core::ServiceConfig::MethodConfigTableLookup(
@@ -2636,8 +2722,8 @@
   channel_data* chand = static_cast<channel_data*>(elem->channel_data);
   call_data* calld = static_cast<call_data*>(elem->call_data);
   if (grpc_client_channel_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "chand=%p calld=%p: starting pick on lb_policy=%p",
-            chand, calld, chand->lb_policy.get());
+    gpr_log(GPR_INFO, "chand=%p calld=%p: starting pick on lb_policy=%p", chand,
+            calld, chand->lb_policy.get());
   }
   // Only get service config data on the first attempt.
   if (calld->num_attempts_completed == 0) {
@@ -2684,7 +2770,7 @@
   if (pick_done) {
     // Pick completed synchronously.
     if (grpc_client_channel_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "chand=%p calld=%p: pick completed synchronously",
+      gpr_log(GPR_INFO, "chand=%p calld=%p: pick completed synchronously",
               chand, calld);
     }
     GRPC_CALL_STACK_UNREF(calld->owning_call, "pick_callback");
@@ -2728,7 +2814,7 @@
   channel_data* chand = static_cast<channel_data*>(elem->channel_data);
   call_data* calld = static_cast<call_data*>(elem->call_data);
   if (grpc_client_channel_trace.enabled()) {
-    gpr_log(GPR_DEBUG,
+    gpr_log(GPR_INFO,
             "chand=%p calld=%p: cancelling pick waiting for resolver result",
             chand, calld);
   }
@@ -2748,7 +2834,7 @@
   if (args->finished) {
     /* cancelled, do nothing */
     if (grpc_client_channel_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "call cancelled before resolver result");
+      gpr_log(GPR_INFO, "call cancelled before resolver result");
     }
     gpr_free(args);
     return;
@@ -2759,14 +2845,14 @@
   call_data* calld = static_cast<call_data*>(elem->call_data);
   if (error != GRPC_ERROR_NONE) {
     if (grpc_client_channel_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "chand=%p calld=%p: resolver failed to return data",
+      gpr_log(GPR_INFO, "chand=%p calld=%p: resolver failed to return data",
               chand, calld);
     }
     async_pick_done_locked(elem, GRPC_ERROR_REF(error));
   } else if (chand->resolver == nullptr) {
     // Shutting down.
     if (grpc_client_channel_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "chand=%p calld=%p: resolver disconnected", chand,
+      gpr_log(GPR_INFO, "chand=%p calld=%p: resolver disconnected", chand,
               calld);
     }
     async_pick_done_locked(
@@ -2782,7 +2868,7 @@
                   .send_initial_metadata_flags;
     if (send_initial_metadata_flags & GRPC_INITIAL_METADATA_WAIT_FOR_READY) {
       if (grpc_client_channel_trace.enabled()) {
-        gpr_log(GPR_DEBUG,
+        gpr_log(GPR_INFO,
                 "chand=%p calld=%p: resolver returned but no LB policy; "
                 "wait_for_ready=true; trying again",
                 chand, calld);
@@ -2790,7 +2876,7 @@
       pick_after_resolver_result_start_locked(elem);
     } else {
       if (grpc_client_channel_trace.enabled()) {
-        gpr_log(GPR_DEBUG,
+        gpr_log(GPR_INFO,
                 "chand=%p calld=%p: resolver returned but no LB policy; "
                 "wait_for_ready=false; failing",
                 chand, calld);
@@ -2803,7 +2889,7 @@
     }
   } else {
     if (grpc_client_channel_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "chand=%p calld=%p: resolver returned, doing pick",
+      gpr_log(GPR_INFO, "chand=%p calld=%p: resolver returned, doing pick",
               chand, calld);
     }
     if (pick_callback_start_locked(elem)) {
@@ -2821,7 +2907,7 @@
   channel_data* chand = static_cast<channel_data*>(elem->channel_data);
   call_data* calld = static_cast<call_data*>(elem->call_data);
   if (grpc_client_channel_trace.enabled()) {
-    gpr_log(GPR_DEBUG,
+    gpr_log(GPR_INFO,
             "chand=%p calld=%p: deferring pick pending resolver result", chand,
             calld);
   }
@@ -2888,7 +2974,7 @@
   // If we've previously been cancelled, immediately fail any new batches.
   if (calld->cancel_error != GRPC_ERROR_NONE) {
     if (grpc_client_channel_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "chand=%p calld=%p: failing batch with error: %s",
+      gpr_log(GPR_INFO, "chand=%p calld=%p: failing batch with error: %s",
               chand, calld, grpc_error_string(calld->cancel_error));
     }
     // Note: This will release the call combiner.
@@ -2907,7 +2993,7 @@
     calld->cancel_error =
         GRPC_ERROR_REF(batch->payload->cancel_stream.cancel_error);
     if (grpc_client_channel_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "chand=%p calld=%p: recording cancel_error=%s", chand,
+      gpr_log(GPR_INFO, "chand=%p calld=%p: recording cancel_error=%s", chand,
               calld, grpc_error_string(calld->cancel_error));
     }
     // If we do not have a subchannel call (i.e., a pick has not yet
@@ -2933,7 +3019,7 @@
   // streaming calls).
   if (calld->subchannel_call != nullptr) {
     if (grpc_client_channel_trace.enabled()) {
-      gpr_log(GPR_DEBUG,
+      gpr_log(GPR_INFO,
               "chand=%p calld=%p: starting batch on subchannel_call=%p", chand,
               calld, calld->subchannel_call);
     }
@@ -2945,7 +3031,7 @@
   // combiner to start a pick.
   if (batch->send_initial_metadata) {
     if (grpc_client_channel_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "chand=%p calld=%p: entering client_channel combiner",
+      gpr_log(GPR_INFO, "chand=%p calld=%p: entering client_channel combiner",
               chand, calld);
     }
     GRPC_CLOSURE_SCHED(
@@ -2955,7 +3041,7 @@
   } else {
     // For all other batches, release the call combiner.
     if (grpc_client_channel_trace.enabled()) {
-      gpr_log(GPR_DEBUG,
+      gpr_log(GPR_INFO,
               "chand=%p calld=%p: saved batch, yeilding call combiner", chand,
               calld);
     }
@@ -2981,6 +3067,7 @@
                              calld->deadline);
   }
   calld->enable_retries = chand->enable_retries;
+  calld->send_messages.Init();
   return GRPC_ERROR_NONE;
 }
 
@@ -2994,6 +3081,7 @@
     grpc_deadline_state_destroy(elem);
   }
   grpc_slice_unref_internal(calld->path);
+  calld->retry_throttle_data.reset();
   calld->method_params.reset();
   GRPC_ERROR_UNREF(calld->cancel_error);
   if (calld->subchannel_call != nullptr) {
@@ -3015,6 +3103,7 @@
           calld->pick.subchannel_call_context[i].value);
     }
   }
+  calld->send_messages.Destroy();
   GRPC_CLOSURE_SCHED(then_schedule_closure, GRPC_ERROR_NONE);
 }
 
@@ -3163,6 +3252,8 @@
   external_connectivity_watcher* found = nullptr;
   if (w->state != nullptr) {
     external_connectivity_watcher_list_append(w->chand, w);
+    // An assumption is being made that the closure is scheduled on the exec ctx
+    // scheduler and that GRPC_CLOSURE_RUN would run the closure immediately.
     GRPC_CLOSURE_RUN(w->watcher_timer_init, GRPC_ERROR_NONE);
     GRPC_CLOSURE_INIT(&w->my_closure, on_external_watch_complete_locked, w,
                       grpc_combiner_scheduler(w->chand->combiner));
diff --git a/src/core/ext/filters/client_channel/client_channel_plugin.cc b/src/core/ext/filters/client_channel/client_channel_plugin.cc
index 3c3a975..8385852 100644
--- a/src/core/ext/filters/client_channel/client_channel_plugin.cc
+++ b/src/core/ext/filters/client_channel/client_channel_plugin.cc
@@ -39,38 +39,13 @@
       builder, static_cast<const grpc_channel_filter*>(arg), nullptr, nullptr);
 }
 
-static bool set_default_host_if_unset(grpc_channel_stack_builder* builder,
-                                      void* unused) {
-  const grpc_channel_args* args =
-      grpc_channel_stack_builder_get_channel_arguments(builder);
-  for (size_t i = 0; i < args->num_args; i++) {
-    if (0 == strcmp(args->args[i].key, GRPC_ARG_DEFAULT_AUTHORITY) ||
-        0 == strcmp(args->args[i].key, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG)) {
-      return true;
-    }
-  }
-  grpc_core::UniquePtr<char> default_authority =
-      grpc_core::ResolverRegistry::GetDefaultAuthority(
-          grpc_channel_stack_builder_get_target(builder));
-  if (default_authority.get() != nullptr) {
-    grpc_arg arg = grpc_channel_arg_string_create(
-        (char*)GRPC_ARG_DEFAULT_AUTHORITY, default_authority.get());
-    grpc_channel_args* new_args = grpc_channel_args_copy_and_add(args, &arg, 1);
-    grpc_channel_stack_builder_set_channel_arguments(builder, new_args);
-    grpc_channel_args_destroy(new_args);
-  }
-  return true;
-}
-
 void grpc_client_channel_init(void) {
   grpc_core::LoadBalancingPolicyRegistry::Builder::InitRegistry();
   grpc_core::ResolverRegistry::Builder::InitRegistry();
-  grpc_retry_throttle_map_init();
+  grpc_core::internal::ServerRetryThrottleMap::Init();
   grpc_proxy_mapper_registry_init();
   grpc_register_http_proxy_mapper();
   grpc_subchannel_index_init();
-  grpc_channel_init_register_stage(GRPC_CLIENT_CHANNEL, INT_MIN,
-                                   set_default_host_if_unset, nullptr);
   grpc_channel_init_register_stage(
       GRPC_CLIENT_CHANNEL, GRPC_CHANNEL_INIT_BUILTIN_PRIORITY, append_filter,
       (void*)&grpc_client_channel_filter);
@@ -81,7 +56,7 @@
   grpc_subchannel_index_shutdown();
   grpc_channel_init_shutdown();
   grpc_proxy_mapper_registry_shutdown();
-  grpc_retry_throttle_map_shutdown();
+  grpc_core::internal::ServerRetryThrottleMap::Shutdown();
   grpc_core::ResolverRegistry::Builder::ShutdownRegistry();
   grpc_core::LoadBalancingPolicyRegistry::Builder::ShutdownRegistry();
 }
diff --git a/src/core/ext/filters/client_channel/http_connect_handshaker.cc b/src/core/ext/filters/client_channel/http_connect_handshaker.cc
index fb29fa7..4e8b8b7 100644
--- a/src/core/ext/filters/client_channel/http_connect_handshaker.cc
+++ b/src/core/ext/filters/client_channel/http_connect_handshaker.cc
@@ -326,7 +326,7 @@
 
 static const grpc_handshaker_vtable http_connect_handshaker_vtable = {
     http_connect_handshaker_destroy, http_connect_handshaker_shutdown,
-    http_connect_handshaker_do_handshake};
+    http_connect_handshaker_do_handshake, "http_connect"};
 
 static grpc_handshaker* grpc_http_connect_handshaker_create() {
   http_connect_handshaker* handshaker =
diff --git a/src/core/ext/filters/client_channel/lb_policy.cc b/src/core/ext/filters/client_channel/lb_policy.cc
index fa63dd7..e065f45 100644
--- a/src/core/ext/filters/client_channel/lb_policy.cc
+++ b/src/core/ext/filters/client_channel/lb_policy.cc
@@ -44,13 +44,13 @@
     GRPC_CLOSURE_SCHED(request_reresolution_, error);
     request_reresolution_ = nullptr;
     if (grpc_lb_trace->enabled()) {
-      gpr_log(GPR_DEBUG,
+      gpr_log(GPR_INFO,
               "%s %p: scheduling re-resolution closure with error=%s.",
               grpc_lb_trace->name(), this, grpc_error_string(error));
     }
   } else {
     if (grpc_lb_trace->enabled()) {
-      gpr_log(GPR_DEBUG, "%s %p: no available re-resolution closure.",
+      gpr_log(GPR_INFO, "%s %p: no available re-resolution closure.",
               grpc_lb_trace->name(), this);
     }
   }
diff --git a/src/core/ext/filters/client_channel/lb_policy.h b/src/core/ext/filters/client_channel/lb_policy.h
index c3e43e5..454e00a 100644
--- a/src/core/ext/filters/client_channel/lb_policy.h
+++ b/src/core/ext/filters/client_channel/lb_policy.h
@@ -162,6 +162,10 @@
   GRPC_ABSTRACT_BASE_CLASS
 
  protected:
+  // So Delete() can access our protected dtor.
+  template <typename T>
+  friend void Delete(T*);
+
   explicit LoadBalancingPolicy(const Args& args);
   virtual ~LoadBalancingPolicy();
 
diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc
index e805593..70a91b2 100644
--- a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc
+++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc
@@ -76,6 +76,7 @@
 #include "src/core/ext/filters/client_channel/client_channel.h"
 #include "src/core/ext/filters/client_channel/client_channel_factory.h"
 #include "src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.h"
+#include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h"
 #include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h"
 #include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h"
 #include "src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h"
@@ -189,6 +190,10 @@
     bool seen_initial_response() const { return seen_initial_response_; }
 
    private:
+    // So Delete() can access our private dtor.
+    template <typename T>
+    friend void grpc_core::Delete(T*);
+
     ~BalancerCallState();
 
     GrpcLb* grpclb_policy() const {
@@ -505,9 +510,7 @@
   // the polling entities from client_channel.
   GPR_ASSERT(grpclb_policy()->server_name_ != nullptr);
   GPR_ASSERT(grpclb_policy()->server_name_[0] != '\0');
-  grpc_slice host =
-      grpc_slice_from_copied_string(grpclb_policy()->server_name_);
-  grpc_millis deadline =
+  const grpc_millis deadline =
       grpclb_policy()->lb_call_timeout_ms_ == 0
           ? GRPC_MILLIS_INF_FUTURE
           : ExecCtx::Get()->Now() + grpclb_policy()->lb_call_timeout_ms_;
@@ -515,8 +518,7 @@
       grpclb_policy()->lb_channel_, nullptr, GRPC_PROPAGATE_DEFAULTS,
       grpclb_policy_->interested_parties(),
       GRPC_MDSTR_SLASH_GRPC_DOT_LB_DOT_V1_DOT_LOADBALANCER_SLASH_BALANCELOAD,
-      &host, deadline, nullptr);
-  grpc_slice_unref_internal(host);
+      nullptr, deadline, nullptr);
   // Init the LB call request payload.
   grpc_grpclb_request* request =
       grpc_grpclb_request_create(grpclb_policy()->server_name_);
@@ -983,6 +985,14 @@
       // with the one from the grpclb policy, used to propagate updates to
       // the LB channel.
       GRPC_ARG_FAKE_RESOLVER_RESPONSE_GENERATOR,
+      // The LB channel should use the authority indicated by the target
+      // authority table (see \a grpc_lb_policy_grpclb_modify_lb_channel_args),
+      // as opposed to the authority from the parent channel.
+      GRPC_ARG_DEFAULT_AUTHORITY,
+      // Just as for \a GRPC_ARG_DEFAULT_AUTHORITY, the LB channel should be
+      // treated as a stand-alone channel and not inherit this argument from the
+      // args of the parent channel.
+      GRPC_SSL_TARGET_NAME_OVERRIDE_ARG,
   };
   // Channel args to add.
   const grpc_arg args_to_add[] = {
@@ -994,6 +1004,9 @@
       // address updates into the LB channel.
       grpc_core::FakeResolverResponseGenerator::MakeChannelArg(
           response_generator),
+      // A channel arg indicating the target is a grpclb load balancer.
+      grpc_channel_arg_integer_create(
+          const_cast<char*>(GRPC_ARG_ADDRESS_IS_GRPCLB_LOAD_BALANCER), 1),
   };
   // Construct channel args.
   grpc_channel_args* new_args = grpc_channel_args_copy_and_add_and_remove(
@@ -1238,7 +1251,7 @@
     }
   } else {  // rr_policy_ == NULL
     if (grpc_lb_glb_trace.enabled()) {
-      gpr_log(GPR_DEBUG,
+      gpr_log(GPR_INFO,
               "[grpclb %p] No RR policy. Adding to grpclb's pending picks",
               this);
     }
@@ -1404,14 +1417,13 @@
 void GrpcLb::StartBalancerCallRetryTimerLocked() {
   grpc_millis next_try = lb_call_backoff_.NextAttemptTime();
   if (grpc_lb_glb_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "[grpclb %p] Connection to LB server lost...", this);
+    gpr_log(GPR_INFO, "[grpclb %p] Connection to LB server lost...", this);
     grpc_millis timeout = next_try - ExecCtx::Get()->Now();
     if (timeout > 0) {
-      gpr_log(GPR_DEBUG,
-              "[grpclb %p] ... retry_timer_active in %" PRIuPTR "ms.", this,
-              timeout);
+      gpr_log(GPR_INFO, "[grpclb %p] ... retry_timer_active in %" PRIuPTR "ms.",
+              this, timeout);
     } else {
-      gpr_log(GPR_DEBUG, "[grpclb %p] ... retry_timer_active immediately.",
+      gpr_log(GPR_INFO, "[grpclb %p] ... retry_timer_active immediately.",
               this);
     }
   }
@@ -1690,9 +1702,11 @@
 
 grpc_channel_args* GrpcLb::CreateRoundRobinPolicyArgsLocked() {
   grpc_lb_addresses* addresses;
+  bool is_backend_from_grpclb_load_balancer = false;
   if (serverlist_ != nullptr) {
     GPR_ASSERT(serverlist_->num_servers > 0);
     addresses = ProcessServerlist(serverlist_);
+    is_backend_from_grpclb_load_balancer = true;
   } else {
     // If CreateOrUpdateRoundRobinPolicyLocked() is invoked when we haven't
     // received any serverlist from the balancer, we use the fallback backends
@@ -1706,9 +1720,18 @@
   // Replace the LB addresses in the channel args that we pass down to
   // the subchannel.
   static const char* keys_to_remove[] = {GRPC_ARG_LB_ADDRESSES};
-  const grpc_arg arg = grpc_lb_addresses_create_channel_arg(addresses);
+  const grpc_arg args_to_add[] = {
+      grpc_lb_addresses_create_channel_arg(addresses),
+      // A channel arg indicating if the target is a backend inferred from a
+      // grpclb load balancer.
+      grpc_channel_arg_integer_create(
+          const_cast<char*>(
+              GRPC_ARG_ADDRESS_IS_BACKEND_FROM_GRPCLB_LOAD_BALANCER),
+          is_backend_from_grpclb_load_balancer),
+  };
   grpc_channel_args* args = grpc_channel_args_copy_and_add_and_remove(
-      args_, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), &arg, 1);
+      args_, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), args_to_add,
+      GPR_ARRAY_SIZE(args_to_add));
   grpc_lb_addresses_destroy(addresses);
   return args;
 }
@@ -1719,7 +1742,7 @@
   GPR_ASSERT(args != nullptr);
   if (rr_policy_ != nullptr) {
     if (grpc_lb_glb_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "[grpclb %p] Updating RR policy %p", this,
+      gpr_log(GPR_INFO, "[grpclb %p] Updating RR policy %p", this,
               rr_policy_.get());
     }
     rr_policy_->UpdateLocked(*args);
@@ -1730,7 +1753,7 @@
     lb_policy_args.args = args;
     CreateRoundRobinPolicyLocked(lb_policy_args);
     if (grpc_lb_glb_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "[grpclb %p] Created new RR policy %p", this,
+      gpr_log(GPR_INFO, "[grpclb %p] Created new RR policy %p", this,
               rr_policy_.get());
     }
   }
@@ -1746,7 +1769,7 @@
   }
   if (grpc_lb_glb_trace.enabled()) {
     gpr_log(
-        GPR_DEBUG,
+        GPR_INFO,
         "[grpclb %p] Re-resolution requested from the internal RR policy (%p).",
         grpclb_policy, grpclb_policy->rr_policy_.get());
   }
diff --git a/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h
new file mode 100644
index 0000000..4d39c4d
--- /dev/null
+++ b/src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h
@@ -0,0 +1,36 @@
+/*
+ *
+ * Copyright 2018 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_LB_POLICY_GRPCLB_GRPCLB_H
+#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_GRPCLB_GRPCLB_H
+
+#include <grpc/support/port_platform.h>
+
+/** Channel arg indicating if a target corresponding to the address is grpclb
+ * loadbalancer. The type of this arg is an integer and the value is treated as
+ * a bool. */
+#define GRPC_ARG_ADDRESS_IS_GRPCLB_LOAD_BALANCER \
+  "grpc.address_is_grpclb_load_balancer"
+/** Channel arg indicating if a target corresponding to the address is a backend
+ * received from a balancer. The type of this arg is an integer and the value is
+ * treated as a bool. */
+#define GRPC_ARG_ADDRESS_IS_BACKEND_FROM_GRPCLB_LOAD_BALANCER \
+  "grpc.address_is_backend_from_grpclb_load_balancer"
+
+#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_GRPCLB_GRPCLB_H \
+        */
diff --git a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc
index 9090c34..76df976 100644
--- a/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc
+++ b/src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc
@@ -62,31 +62,65 @@
  private:
   ~PickFirst();
 
+  class PickFirstSubchannelList;
+
+  class PickFirstSubchannelData
+      : public SubchannelData<PickFirstSubchannelList,
+                              PickFirstSubchannelData> {
+   public:
+    PickFirstSubchannelData(PickFirstSubchannelList* subchannel_list,
+                            const grpc_lb_user_data_vtable* user_data_vtable,
+                            const grpc_lb_address& address,
+                            grpc_subchannel* subchannel,
+                            grpc_combiner* combiner)
+        : SubchannelData(subchannel_list, user_data_vtable, address, subchannel,
+                         combiner) {}
+
+    void ProcessConnectivityChangeLocked(
+        grpc_connectivity_state connectivity_state, grpc_error* error) override;
+  };
+
+  class PickFirstSubchannelList
+      : public SubchannelList<PickFirstSubchannelList,
+                              PickFirstSubchannelData> {
+   public:
+    PickFirstSubchannelList(PickFirst* policy, TraceFlag* tracer,
+                            const grpc_lb_addresses* addresses,
+                            grpc_combiner* combiner,
+                            grpc_client_channel_factory* client_channel_factory,
+                            const grpc_channel_args& args)
+        : SubchannelList(policy, tracer, addresses, combiner,
+                         client_channel_factory, args) {
+      // Need to maintain a ref to the LB policy as long as we maintain
+      // any references to subchannels, since the subchannels'
+      // pollset_sets will include the LB policy's pollset_set.
+      policy->Ref(DEBUG_LOCATION, "subchannel_list").release();
+    }
+
+    ~PickFirstSubchannelList() {
+      PickFirst* p = static_cast<PickFirst*>(policy());
+      p->Unref(DEBUG_LOCATION, "subchannel_list");
+    }
+  };
+
   void ShutdownLocked() override;
 
   void StartPickingLocked();
   void DestroyUnselectedSubchannelsLocked();
 
-  static void OnConnectivityChangedLocked(void* arg, grpc_error* error);
-
-  void SubchannelListRefForConnectivityWatch(
-      grpc_lb_subchannel_list* subchannel_list, const char* reason);
-  void SubchannelListUnrefForConnectivityWatch(
-      grpc_lb_subchannel_list* subchannel_list, const char* reason);
-
-  /** all our subchannels */
-  grpc_lb_subchannel_list* subchannel_list_ = nullptr;
-  /** latest pending subchannel list */
-  grpc_lb_subchannel_list* latest_pending_subchannel_list_ = nullptr;
-  /** selected subchannel in \a subchannel_list */
-  grpc_lb_subchannel_data* selected_ = nullptr;
-  /** have we started picking? */
+  // All our subchannels.
+  OrphanablePtr<PickFirstSubchannelList> subchannel_list_;
+  // Latest pending subchannel list.
+  OrphanablePtr<PickFirstSubchannelList> latest_pending_subchannel_list_;
+  // Selected subchannel in \a subchannel_list_.
+  PickFirstSubchannelData* selected_ = nullptr;
+  // Have we started picking?
   bool started_picking_ = false;
-  /** are we shut down? */
+  // Are we shut down?
   bool shutdown_ = false;
-  /** list of picks that are waiting on connectivity */
+  // List of picks that are waiting on connectivity.
   PickState* pending_picks_ = nullptr;
-  /** our connectivity state tracker */
+  // Our connectivity state tracker.
   grpc_connectivity_state_tracker state_tracker_;
 };
 
@@ -95,7 +129,7 @@
   grpc_connectivity_state_init(&state_tracker_, GRPC_CHANNEL_IDLE,
                                "pick_first");
   if (grpc_lb_pick_first_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "Pick First %p created.", this);
+    gpr_log(GPR_INFO, "Pick First %p created.", this);
   }
   UpdateLocked(*args.args);
   grpc_subchannel_index_ref();
@@ -103,7 +137,7 @@
 
 PickFirst::~PickFirst() {
   if (grpc_lb_pick_first_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "Destroying Pick First %p", this);
+    gpr_log(GPR_INFO, "Destroying Pick First %p", this);
   }
   GPR_ASSERT(subchannel_list_ == nullptr);
   GPR_ASSERT(latest_pending_subchannel_list_ == nullptr);
@@ -126,7 +160,7 @@
 void PickFirst::ShutdownLocked() {
   grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Channel shutdown");
   if (grpc_lb_pick_first_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "Pick First %p Shutting down", this);
+    gpr_log(GPR_INFO, "Pick First %p Shutting down", this);
   }
   shutdown_ = true;
   PickState* pick;
@@ -137,15 +171,8 @@
   }
   grpc_connectivity_state_set(&state_tracker_, GRPC_CHANNEL_SHUTDOWN,
                               GRPC_ERROR_REF(error), "shutdown");
-  if (subchannel_list_ != nullptr) {
-    grpc_lb_subchannel_list_shutdown_and_unref(subchannel_list_, "pf_shutdown");
-    subchannel_list_ = nullptr;
-  }
-  if (latest_pending_subchannel_list_ != nullptr) {
-    grpc_lb_subchannel_list_shutdown_and_unref(latest_pending_subchannel_list_,
-                                               "pf_shutdown");
-    latest_pending_subchannel_list_ = nullptr;
-  }
+  subchannel_list_.reset();
+  latest_pending_subchannel_list_.reset();
   TryReresolutionLocked(&grpc_lb_pick_first_trace, GRPC_ERROR_CANCELLED);
   GRPC_ERROR_UNREF(error);
 }
@@ -192,14 +219,10 @@
 
 void PickFirst::StartPickingLocked() {
   started_picking_ = true;
-  if (subchannel_list_ != nullptr && subchannel_list_->num_subchannels > 0) {
-    subchannel_list_->checking_subchannel = 0;
-    for (size_t i = 0; i < subchannel_list_->num_subchannels; ++i) {
-      if (subchannel_list_->subchannels[i].subchannel != nullptr) {
-        SubchannelListRefForConnectivityWatch(
-            subchannel_list_, "connectivity_watch+start_picking");
-        grpc_lb_subchannel_data_start_connectivity_watch(
-            &subchannel_list_->subchannels[i]);
+  if (subchannel_list_ != nullptr) {
+    for (size_t i = 0; i < subchannel_list_->num_subchannels(); ++i) {
+      if (subchannel_list_->subchannel(i)->subchannel() != nullptr) {
+        subchannel_list_->subchannel(i)->StartConnectivityWatchLocked();
         break;
       }
     }
@@ -215,7 +238,7 @@
 bool PickFirst::PickLocked(PickState* pick) {
   // If we have a selected subchannel already, return synchronously.
   if (selected_ != nullptr) {
-    pick->connected_subchannel = selected_->connected_subchannel;
+    pick->connected_subchannel = selected_->connected_subchannel()->Ref();
     return true;
   }
   // No subchannel selected yet, so handle asynchronously.
@@ -228,11 +251,10 @@
 }
 
 void PickFirst::DestroyUnselectedSubchannelsLocked() {
-  for (size_t i = 0; i < subchannel_list_->num_subchannels; ++i) {
-    grpc_lb_subchannel_data* sd = &subchannel_list_->subchannels[i];
+  for (size_t i = 0; i < subchannel_list_->num_subchannels(); ++i) {
+    PickFirstSubchannelData* sd = subchannel_list_->subchannel(i);
     if (selected_ != sd) {
-      grpc_lb_subchannel_data_unref_subchannel(sd,
-                                               "selected_different_subchannel");
+      sd->UnrefSubchannelLocked("selected_different_subchannel");
     }
   }
 }
@@ -249,7 +271,7 @@
 
 void PickFirst::PingOneLocked(grpc_closure* on_initiate, grpc_closure* on_ack) {
   if (selected_ != nullptr) {
-    selected_->connected_subchannel->Ping(on_initiate, on_ack);
+    selected_->connected_subchannel()->Ping(on_initiate, on_ack);
   } else {
     GRPC_CLOSURE_SCHED(on_initiate,
                        GRPC_ERROR_CREATE_FROM_STATIC_STRING("Not connected"));
@@ -258,24 +280,6 @@
   }
 }
 
-void PickFirst::SubchannelListRefForConnectivityWatch(
-    grpc_lb_subchannel_list* subchannel_list, const char* reason) {
-  // TODO(roth): We currently track this ref manually.  Once the new
-  // ClosureRef API is ready and the subchannel_list code has been
-  // converted to a C++ API, find a way to hold the RefCountedPtr<>
-  // somewhere (maybe in the subchannel_data object) instead of doing
-  // this manually.
-  auto self = Ref(DEBUG_LOCATION, reason);
-  self.release();
-  grpc_lb_subchannel_list_ref(subchannel_list, reason);
-}
-
-void PickFirst::SubchannelListUnrefForConnectivityWatch(
-    grpc_lb_subchannel_list* subchannel_list, const char* reason) {
-  Unref(DEBUG_LOCATION, reason);
-  grpc_lb_subchannel_list_unref(subchannel_list, reason);
-}
-
 void PickFirst::UpdateLocked(const grpc_channel_args& args) {
   const grpc_arg* arg = grpc_channel_args_find(&args, GRPC_ARG_LB_ADDRESSES);
   if (arg == nullptr || arg->type != GRPC_ARG_POINTER) {
@@ -295,75 +299,67 @@
     return;
   }
   const grpc_lb_addresses* addresses =
-      (const grpc_lb_addresses*)arg->value.pointer.p;
+      static_cast<const grpc_lb_addresses*>(arg->value.pointer.p);
   if (grpc_lb_pick_first_trace.enabled()) {
     gpr_log(GPR_INFO,
             "Pick First %p received update with %" PRIuPTR " addresses", this,
             addresses->num_addresses);
   }
-  grpc_lb_subchannel_list* subchannel_list = grpc_lb_subchannel_list_create(
+  auto subchannel_list = MakeOrphanable<PickFirstSubchannelList>(
       this, &grpc_lb_pick_first_trace, addresses, combiner(),
-      client_channel_factory(), args, &PickFirst::OnConnectivityChangedLocked);
-  if (subchannel_list->num_subchannels == 0) {
+      client_channel_factory(), args);
+  if (subchannel_list->num_subchannels() == 0) {
     // Empty update or no valid subchannels. Unsubscribe from all current
     // subchannels and put the channel in TRANSIENT_FAILURE.
     grpc_connectivity_state_set(
         &state_tracker_, GRPC_CHANNEL_TRANSIENT_FAILURE,
         GRPC_ERROR_CREATE_FROM_STATIC_STRING("Empty update"),
         "pf_update_empty");
-    if (subchannel_list_ != nullptr) {
-      grpc_lb_subchannel_list_shutdown_and_unref(subchannel_list_,
-                                                 "sl_shutdown_empty_update");
-    }
-    subchannel_list_ = subchannel_list;  // Empty list.
+    subchannel_list_ = std::move(subchannel_list);  // Empty list.
     selected_ = nullptr;
     return;
   }
   if (selected_ == nullptr) {
     // We don't yet have a selected subchannel, so replace the current
     // subchannel list immediately.
-    if (subchannel_list_ != nullptr) {
-      grpc_lb_subchannel_list_shutdown_and_unref(subchannel_list_,
-                                                 "pf_update_before_selected");
+    subchannel_list_ = std::move(subchannel_list);
+    // If we've started picking, start trying to connect to the first
+    // subchannel in the new list.
+    if (started_picking_) {
+      subchannel_list_->subchannel(0)->StartConnectivityWatchLocked();
     }
-    subchannel_list_ = subchannel_list;
   } else {
     // We do have a selected subchannel.
     // Check if it's present in the new list.  If so, we're done.
-    for (size_t i = 0; i < subchannel_list->num_subchannels; ++i) {
-      grpc_lb_subchannel_data* sd = &subchannel_list->subchannels[i];
-      if (sd->subchannel == selected_->subchannel) {
+    for (size_t i = 0; i < subchannel_list->num_subchannels(); ++i) {
+      PickFirstSubchannelData* sd = subchannel_list->subchannel(i);
+      if (sd->subchannel() == selected_->subchannel()) {
         // The currently selected subchannel is in the update: we are done.
         if (grpc_lb_pick_first_trace.enabled()) {
           gpr_log(GPR_INFO,
                   "Pick First %p found already selected subchannel %p "
                   "at update index %" PRIuPTR " of %" PRIuPTR "; update done",
-                  this, selected_->subchannel, i,
-                  subchannel_list->num_subchannels);
+                  this, selected_->subchannel(), i,
+                  subchannel_list->num_subchannels());
         }
-        if (selected_->connected_subchannel != nullptr) {
-          sd->connected_subchannel = selected_->connected_subchannel;
+        // Make sure it's in state READY.  It might not be if we grabbed
+        // the combiner while a connectivity state notification
+        // informing us otherwise is pending.
+        // Note that CheckConnectivityStateLocked() also takes a ref to
+        // the connected subchannel.
+        grpc_error* error = GRPC_ERROR_NONE;
+        if (sd->CheckConnectivityStateLocked(&error) == GRPC_CHANNEL_READY) {
+          selected_ = sd;
+          subchannel_list_ = std::move(subchannel_list);
+          DestroyUnselectedSubchannelsLocked();
+          sd->StartConnectivityWatchLocked();
+          // If there was a previously pending update (which may or may
+          // not have contained the currently selected subchannel), drop
+          // it, so that it doesn't override what we've done here.
+          latest_pending_subchannel_list_.reset();
+          return;
         }
-        selected_ = sd;
-        if (subchannel_list_ != nullptr) {
-          grpc_lb_subchannel_list_shutdown_and_unref(
-              subchannel_list_, "pf_update_includes_selected");
-        }
-        subchannel_list_ = subchannel_list;
-        DestroyUnselectedSubchannelsLocked();
-        SubchannelListRefForConnectivityWatch(
-            subchannel_list, "connectivity_watch+replace_selected");
-        grpc_lb_subchannel_data_start_connectivity_watch(sd);
-        // If there was a previously pending update (which may or may
-        // not have contained the currently selected subchannel), drop
-        // it, so that it doesn't override what we've done here.
-        if (latest_pending_subchannel_list_ != nullptr) {
-          grpc_lb_subchannel_list_shutdown_and_unref(
-              latest_pending_subchannel_list_,
-              "pf_update_includes_selected+outdated");
-          latest_pending_subchannel_list_ = nullptr;
-        }
-        return;
+        GRPC_ERROR_UNREF(error);
       }
     }
     // Not keeping the previous selected subchannel, so set the latest
@@ -372,88 +368,66 @@
     // subchannel list.
     if (latest_pending_subchannel_list_ != nullptr) {
       if (grpc_lb_pick_first_trace.enabled()) {
-        gpr_log(GPR_DEBUG,
+        gpr_log(GPR_INFO,
                 "Pick First %p Shutting down latest pending subchannel list "
                 "%p, about to be replaced by newer latest %p",
-                this, latest_pending_subchannel_list_, subchannel_list);
+                this, latest_pending_subchannel_list_.get(),
+                subchannel_list.get());
       }
-      grpc_lb_subchannel_list_shutdown_and_unref(
-          latest_pending_subchannel_list_, "sl_outdated_dont_smash");
     }
-    latest_pending_subchannel_list_ = subchannel_list;
-  }
-  // If we've started picking, start trying to connect to the first
-  // subchannel in the new list.
-  if (started_picking_) {
-    SubchannelListRefForConnectivityWatch(subchannel_list,
-                                          "connectivity_watch+update");
-    grpc_lb_subchannel_data_start_connectivity_watch(
-        &subchannel_list->subchannels[0]);
+    latest_pending_subchannel_list_ = std::move(subchannel_list);
+    // If we've started picking, start trying to connect to the first
+    // subchannel in the new list.
+    if (started_picking_) {
+      latest_pending_subchannel_list_->subchannel(0)
+          ->StartConnectivityWatchLocked();
+    }
   }
 }
 
-void PickFirst::OnConnectivityChangedLocked(void* arg, grpc_error* error) {
-  grpc_lb_subchannel_data* sd = static_cast<grpc_lb_subchannel_data*>(arg);
-  PickFirst* p = static_cast<PickFirst*>(sd->subchannel_list->policy);
-  if (grpc_lb_pick_first_trace.enabled()) {
-    gpr_log(GPR_DEBUG,
-            "Pick First %p connectivity changed for subchannel %p (%" PRIuPTR
-            " of %" PRIuPTR
-            "), subchannel_list %p: state=%s p->shutdown_=%d "
-            "sd->subchannel_list->shutting_down=%d error=%s",
-            p, sd->subchannel, sd->subchannel_list->checking_subchannel,
-            sd->subchannel_list->num_subchannels, sd->subchannel_list,
-            grpc_connectivity_state_name(sd->pending_connectivity_state_unsafe),
-            p->shutdown_, sd->subchannel_list->shutting_down,
-            grpc_error_string(error));
-  }
-  // If the policy is shutting down, unref and return.
-  if (p->shutdown_) {
-    grpc_lb_subchannel_data_stop_connectivity_watch(sd);
-    grpc_lb_subchannel_data_unref_subchannel(sd, "pf_shutdown");
-    p->SubchannelListUnrefForConnectivityWatch(sd->subchannel_list,
-                                               "pf_shutdown");
-    return;
-  }
-  // If the subchannel list is shutting down, stop watching.
-  if (sd->subchannel_list->shutting_down || error == GRPC_ERROR_CANCELLED) {
-    grpc_lb_subchannel_data_stop_connectivity_watch(sd);
-    grpc_lb_subchannel_data_unref_subchannel(sd, "pf_sl_shutdown");
-    p->SubchannelListUnrefForConnectivityWatch(sd->subchannel_list,
-                                               "pf_sl_shutdown");
-    return;
-  }
-  // If we're still here, the notification must be for a subchannel in
-  // either the current or latest pending subchannel lists.
-  GPR_ASSERT(sd->subchannel_list == p->subchannel_list_ ||
-             sd->subchannel_list == p->latest_pending_subchannel_list_);
-  // Update state.
-  sd->curr_connectivity_state = sd->pending_connectivity_state_unsafe;
+void PickFirst::PickFirstSubchannelData::ProcessConnectivityChangeLocked(
+    grpc_connectivity_state connectivity_state, grpc_error* error) {
+  PickFirst* p = static_cast<PickFirst*>(subchannel_list()->policy());
+  // The notification must be for a subchannel in either the current or
+  // latest pending subchannel lists.
+  GPR_ASSERT(subchannel_list() == p->subchannel_list_.get() ||
+             subchannel_list() == p->latest_pending_subchannel_list_.get());
   // Handle updates for the currently selected subchannel.
-  if (p->selected_ == sd) {
+  if (p->selected_ == this) {
+    if (grpc_lb_pick_first_trace.enabled()) {
+      gpr_log(GPR_INFO,
+              "Pick First %p connectivity changed for selected subchannel", p);
+    }
     // If the new state is anything other than READY and there is a
     // pending update, switch to the pending update.
-    if (sd->curr_connectivity_state != GRPC_CHANNEL_READY &&
+    if (connectivity_state != GRPC_CHANNEL_READY &&
         p->latest_pending_subchannel_list_ != nullptr) {
+      if (grpc_lb_pick_first_trace.enabled()) {
+        gpr_log(GPR_INFO,
+                "Pick First %p promoting pending subchannel list %p to "
+                "replace %p",
+                p, p->latest_pending_subchannel_list_.get(),
+                p->subchannel_list_.get());
+      }
       p->selected_ = nullptr;
-      grpc_lb_subchannel_data_stop_connectivity_watch(sd);
-      p->SubchannelListUnrefForConnectivityWatch(
-          sd->subchannel_list, "selected_not_ready+switch_to_update");
-      grpc_lb_subchannel_list_shutdown_and_unref(
-          p->subchannel_list_, "selected_not_ready+switch_to_update");
-      p->subchannel_list_ = p->latest_pending_subchannel_list_;
-      p->latest_pending_subchannel_list_ = nullptr;
+      StopConnectivityWatchLocked();
+      p->subchannel_list_ = std::move(p->latest_pending_subchannel_list_);
       grpc_connectivity_state_set(
           &p->state_tracker_, GRPC_CHANNEL_TRANSIENT_FAILURE,
-          GRPC_ERROR_REF(error), "selected_not_ready+switch_to_update");
+          error != GRPC_ERROR_NONE
+              ? GRPC_ERROR_REF(error)
+              : GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+                    "selected subchannel not ready; switching to pending "
+                    "update"),
+          "selected_not_ready+switch_to_update");
     } else {
       // TODO(juanlishen): we re-resolve when the selected subchannel goes to
       // TRANSIENT_FAILURE because we used to shut down in this case before
       // re-resolution is introduced. But we need to investigate whether we
       // really want to take any action instead of waiting for the selected
       // subchannel reconnecting.
-      GPR_ASSERT(sd->curr_connectivity_state != GRPC_CHANNEL_SHUTDOWN);
-      if (sd->curr_connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
+      GPR_ASSERT(connectivity_state != GRPC_CHANNEL_SHUTDOWN);
+      if (connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
         // If the selected channel goes bad, request a re-resolution.
         grpc_connectivity_state_set(&p->state_tracker_, GRPC_CHANNEL_IDLE,
                                     GRPC_ERROR_NONE,
@@ -462,19 +436,16 @@
         p->TryReresolutionLocked(&grpc_lb_pick_first_trace, GRPC_ERROR_NONE);
         // In transient failure. Rely on re-resolution to recover.
         p->selected_ = nullptr;
-        grpc_lb_subchannel_data_stop_connectivity_watch(sd);
-        p->SubchannelListUnrefForConnectivityWatch(sd->subchannel_list,
-                                                   "pf_selected_shutdown");
-        grpc_lb_subchannel_data_unref_subchannel(
-            sd, "pf_selected_shutdown");  // Unrefs connected subchannel
+        UnrefSubchannelLocked("pf_selected_shutdown");
+        StopConnectivityWatchLocked();
       } else {
-        grpc_connectivity_state_set(&p->state_tracker_,
-                                    sd->curr_connectivity_state,
+        grpc_connectivity_state_set(&p->state_tracker_, connectivity_state,
                                     GRPC_ERROR_REF(error), "selected_changed");
         // Renew notification.
-        grpc_lb_subchannel_data_start_connectivity_watch(sd);
+        RenewConnectivityWatchLocked();
       }
     }
+    GRPC_ERROR_UNREF(error);
     return;
   }
   // If we get here, there are two possible cases:
@@ -486,26 +457,27 @@
   //    for a subchannel in p->latest_pending_subchannel_list_.  The
   //    goal here is to find a subchannel from the update that we can
   //    select in place of the current one.
-  switch (sd->curr_connectivity_state) {
+  switch (connectivity_state) {
     case GRPC_CHANNEL_READY: {
       // Case 2.  Promote p->latest_pending_subchannel_list_ to
       // p->subchannel_list_.
-      sd->connected_subchannel =
-          grpc_subchannel_get_connected_subchannel(sd->subchannel);
-      if (sd->subchannel_list == p->latest_pending_subchannel_list_) {
-        GPR_ASSERT(p->subchannel_list_ != nullptr);
-        grpc_lb_subchannel_list_shutdown_and_unref(p->subchannel_list_,
-                                                   "finish_update");
-        p->subchannel_list_ = p->latest_pending_subchannel_list_;
-        p->latest_pending_subchannel_list_ = nullptr;
+      if (subchannel_list() == p->latest_pending_subchannel_list_.get()) {
+        if (grpc_lb_pick_first_trace.enabled()) {
+          gpr_log(GPR_INFO,
+                  "Pick First %p promoting pending subchannel list %p to "
+                  "replace %p",
+                  p, p->latest_pending_subchannel_list_.get(),
+                  p->subchannel_list_.get());
+        }
+        p->subchannel_list_ = std::move(p->latest_pending_subchannel_list_);
       }
       // Cases 1 and 2.
       grpc_connectivity_state_set(&p->state_tracker_, GRPC_CHANNEL_READY,
                                   GRPC_ERROR_NONE, "connecting_ready");
-      p->selected_ = sd;
+      p->selected_ = this;
       if (grpc_lb_pick_first_trace.enabled()) {
         gpr_log(GPR_INFO, "Pick First %p selected subchannel %p", p,
-                sd->subchannel);
+                subchannel());
       }
       // Drop all other subchannels, since we are now connected.
       p->DestroyUnselectedSubchannelsLocked();
@@ -513,7 +485,8 @@
       PickState* pick;
       while ((pick = p->pending_picks_)) {
         p->pending_picks_ = pick->next;
-        pick->connected_subchannel = p->selected_->connected_subchannel;
+        pick->connected_subchannel =
+            p->selected_->connected_subchannel()->Ref();
         if (grpc_lb_pick_first_trace.enabled()) {
           gpr_log(GPR_INFO,
                   "Servicing pending pick with selected subchannel %p",
@@ -522,45 +495,43 @@
         GRPC_CLOSURE_SCHED(pick->on_complete, GRPC_ERROR_NONE);
       }
       // Renew notification.
-      grpc_lb_subchannel_data_start_connectivity_watch(sd);
+      RenewConnectivityWatchLocked();
       break;
     }
     case GRPC_CHANNEL_TRANSIENT_FAILURE: {
-      grpc_lb_subchannel_data_stop_connectivity_watch(sd);
+      StopConnectivityWatchLocked();
+      PickFirstSubchannelData* sd = this;
       do {
-        sd->subchannel_list->checking_subchannel =
-            (sd->subchannel_list->checking_subchannel + 1) %
-            sd->subchannel_list->num_subchannels;
-        sd = &sd->subchannel_list
-                  ->subchannels[sd->subchannel_list->checking_subchannel];
-      } while (sd->subchannel == nullptr);
+        size_t next_index =
+            (sd->Index() + 1) % subchannel_list()->num_subchannels();
+        sd = subchannel_list()->subchannel(next_index);
+      } while (sd->subchannel() == nullptr);
       // Case 1: Only set state to TRANSIENT_FAILURE if we've tried
       // all subchannels.
-      if (sd->subchannel_list->checking_subchannel == 0 &&
-          sd->subchannel_list == p->subchannel_list_) {
+      if (sd->Index() == 0 && subchannel_list() == p->subchannel_list_.get()) {
         grpc_connectivity_state_set(
             &p->state_tracker_, GRPC_CHANNEL_TRANSIENT_FAILURE,
             GRPC_ERROR_REF(error), "connecting_transient_failure");
       }
-      // Reuses the connectivity refs from the previous watch.
-      grpc_lb_subchannel_data_start_connectivity_watch(sd);
+      sd->StartConnectivityWatchLocked();
       break;
     }
     case GRPC_CHANNEL_CONNECTING:
     case GRPC_CHANNEL_IDLE: {
       // Only update connectivity state in case 1.
-      if (sd->subchannel_list == p->subchannel_list_) {
+      if (subchannel_list() == p->subchannel_list_.get()) {
         grpc_connectivity_state_set(&p->state_tracker_, GRPC_CHANNEL_CONNECTING,
                                     GRPC_ERROR_REF(error),
                                     "connecting_changed");
       }
       // Renew notification.
-      grpc_lb_subchannel_data_start_connectivity_watch(sd);
+      RenewConnectivityWatchLocked();
       break;
     }
     case GRPC_CHANNEL_SHUTDOWN:
       GPR_UNREACHABLE_CODE(break);
   }
+  GRPC_ERROR_UNREF(error);
 }
 
 //
diff --git a/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc b/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc
index e534131..79e8ad5 100644
--- a/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc
+++ b/src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc
@@ -73,23 +73,127 @@
  private:
   ~RoundRobin();
 
+  // Forward declaration.
+  class RoundRobinSubchannelList;
+
+  // Data for a particular subchannel in a subchannel list.
+  // This subclass adds the following functionality:
+  // - Tracks user_data associated with each address, which will be
+  //   returned along with picks that select the subchannel.
+  // - Tracks the previous connectivity state of the subchannel, so that
+  //   we know how many subchannels are in each state.
+  class RoundRobinSubchannelData
+      : public SubchannelData<RoundRobinSubchannelList,
+                              RoundRobinSubchannelData> {
+   public:
+    RoundRobinSubchannelData(RoundRobinSubchannelList* subchannel_list,
+                             const grpc_lb_user_data_vtable* user_data_vtable,
+                             const grpc_lb_address& address,
+                             grpc_subchannel* subchannel,
+                             grpc_combiner* combiner)
+        : SubchannelData(subchannel_list, user_data_vtable, address, subchannel,
+                         combiner),
+          user_data_vtable_(user_data_vtable),
+          user_data_(user_data_vtable_ != nullptr
+                         ? user_data_vtable_->copy(address.user_data)
+                         : nullptr) {}
+
+    void UnrefSubchannelLocked(const char* reason) override {
+      SubchannelData::UnrefSubchannelLocked(reason);
+      if (user_data_ != nullptr) {
+        GPR_ASSERT(user_data_vtable_ != nullptr);
+        user_data_vtable_->destroy(user_data_);
+        user_data_ = nullptr;
+      }
+    }
+
+    void* user_data() const { return user_data_; }
+
+    grpc_connectivity_state connectivity_state() const {
+      return last_connectivity_state_;
+    }
+
+    void UpdateConnectivityStateLocked(
+        grpc_connectivity_state connectivity_state, grpc_error* error);
+
+   private:
+    void ProcessConnectivityChangeLocked(
+        grpc_connectivity_state connectivity_state, grpc_error* error) override;
+
+    const grpc_lb_user_data_vtable* user_data_vtable_;
+    void* user_data_ = nullptr;
+    grpc_connectivity_state last_connectivity_state_ = GRPC_CHANNEL_IDLE;
+  };
+
+  // A list of subchannels.
+  class RoundRobinSubchannelList
+      : public SubchannelList<RoundRobinSubchannelList,
+                              RoundRobinSubchannelData> {
+   public:
+    RoundRobinSubchannelList(
+        RoundRobin* policy, TraceFlag* tracer,
+        const grpc_lb_addresses* addresses, grpc_combiner* combiner,
+        grpc_client_channel_factory* client_channel_factory,
+        const grpc_channel_args& args)
+        : SubchannelList(policy, tracer, addresses, combiner,
+                         client_channel_factory, args) {
+      // Need to maintain a ref to the LB policy as long as we maintain
+      // any references to subchannels, since the subchannels'
+      // pollset_sets will include the LB policy's pollset_set.
+      policy->Ref(DEBUG_LOCATION, "subchannel_list").release();
+    }
+
+    ~RoundRobinSubchannelList() {
+      GRPC_ERROR_UNREF(last_transient_failure_error_);
+      RoundRobin* p = static_cast<RoundRobin*>(policy());
+      p->Unref(DEBUG_LOCATION, "subchannel_list");
+    }
+
+    // Starts watching the subchannels in this list.
+    void StartWatchingLocked();
+
+    // Updates the counters of subchannels in each state when a
+    // subchannel transitions from old_state to new_state.
+    // transient_failure_error is the error that is reported when
+    // new_state is TRANSIENT_FAILURE.
+    void UpdateStateCountersLocked(grpc_connectivity_state old_state,
+                                   grpc_connectivity_state new_state,
+                                   grpc_error* transient_failure_error);
+
+    // If this subchannel list is the RR policy's current subchannel
+    // list, updates the RR policy's connectivity state based on the
+    // subchannel list's state counters.
+    void MaybeUpdateRoundRobinConnectivityStateLocked();
+
+    // Updates the RR policy's overall state based on the counters of
+    // subchannels in each state.
+    void UpdateRoundRobinStateFromSubchannelStateCountsLocked();
+
+    size_t GetNextReadySubchannelIndexLocked();
+    void UpdateLastReadySubchannelIndexLocked(size_t last_ready_index);
+
+   private:
+    size_t num_ready_ = 0;
+    size_t num_connecting_ = 0;
+    size_t num_transient_failure_ = 0;
+    grpc_error* last_transient_failure_error_ = GRPC_ERROR_NONE;
+    size_t last_ready_index_ = -1;  // Index into list of last pick.
+  };
+
   void ShutdownLocked() override;
 
   void StartPickingLocked();
-  size_t GetNextReadySubchannelIndexLocked();
-  void UpdateLastReadySubchannelIndexLocked(size_t last_ready_index);
-  void UpdateConnectivityStatusLocked(grpc_lb_subchannel_data* sd,
-                                      grpc_error* error);
-
-  static void OnConnectivityChangedLocked(void* arg, grpc_error* error);
-
-  void SubchannelListRefForConnectivityWatch(
-      grpc_lb_subchannel_list* subchannel_list, const char* reason);
-  void SubchannelListUnrefForConnectivityWatch(
-      grpc_lb_subchannel_list* subchannel_list, const char* reason);
+  bool DoPickLocked(PickState* pick);
+  void DrainPendingPicksLocked();
 
   /** list of subchannels */
-  grpc_lb_subchannel_list* subchannel_list_ = nullptr;
+  OrphanablePtr<RoundRobinSubchannelList> subchannel_list_;
+  /** Latest version of the subchannel list.
+   * Subchannel connectivity callbacks will only promote updated subchannel
+   * lists if they equal \a latest_pending_subchannel_list. In other words,
+   * racing callbacks that reference outdated subchannel lists won't perform any
+   * update. */
+  OrphanablePtr<RoundRobinSubchannelList> latest_pending_subchannel_list_;
   /** have we started picking? */
   bool started_picking_ = false;
   /** are we shutting down? */
@@ -98,14 +202,6 @@
   PickState* pending_picks_ = nullptr;
   /** our connectivity state tracker */
   grpc_connectivity_state_tracker state_tracker_;
-  /** Index into subchannels for last pick. */
-  size_t last_ready_subchannel_index_ = 0;
-  /** Latest version of the subchannel list.
-   * Subchannel connectivity callbacks will only promote updated subchannel
-   * lists if they equal \a latest_pending_subchannel_list. In other words,
-   * racing callbacks that reference outdated subchannel lists won't perform any
-   * update. */
-  grpc_lb_subchannel_list* latest_pending_subchannel_list_ = nullptr;
 };
 
 RoundRobin::RoundRobin(const Args& args) : LoadBalancingPolicy(args) {
@@ -114,15 +210,15 @@
                                "round_robin");
   UpdateLocked(*args.args);
   if (grpc_lb_round_robin_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "[RR %p] Created with %" PRIuPTR " subchannels", this,
-            subchannel_list_->num_subchannels);
+    gpr_log(GPR_INFO, "[RR %p] Created with %" PRIuPTR " subchannels", this,
+            subchannel_list_->num_subchannels());
   }
   grpc_subchannel_index_ref();
 }
 
 RoundRobin::~RoundRobin() {
   if (grpc_lb_round_robin_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "[RR %p] Destroying Round Robin policy", this);
+    gpr_log(GPR_INFO, "[RR %p] Destroying Round Robin policy", this);
   }
   GPR_ASSERT(subchannel_list_ == nullptr);
   GPR_ASSERT(latest_pending_subchannel_list_ == nullptr);
@@ -131,68 +227,6 @@
   grpc_subchannel_index_unref();
 }
 
-/** Returns the index into p->subchannel_list->subchannels of the next
- * subchannel in READY state, or p->subchannel_list->num_subchannels if no
- * subchannel is READY.
- *
- * Note that this function does *not* update p->last_ready_subchannel_index.
- * The caller must do that if it returns a pick. */
-size_t RoundRobin::GetNextReadySubchannelIndexLocked() {
-  GPR_ASSERT(subchannel_list_ != nullptr);
-  if (grpc_lb_round_robin_trace.enabled()) {
-    gpr_log(GPR_INFO,
-            "[RR %p] getting next ready subchannel (out of %" PRIuPTR
-            "), "
-            "last_ready_subchannel_index=%" PRIuPTR,
-            this, subchannel_list_->num_subchannels,
-            last_ready_subchannel_index_);
-  }
-  for (size_t i = 0; i < subchannel_list_->num_subchannels; ++i) {
-    const size_t index = (i + last_ready_subchannel_index_ + 1) %
-                         subchannel_list_->num_subchannels;
-    if (grpc_lb_round_robin_trace.enabled()) {
-      gpr_log(
-          GPR_DEBUG,
-          "[RR %p] checking subchannel %p, subchannel_list %p, index %" PRIuPTR
-          ": state=%s",
-          this, subchannel_list_->subchannels[index].subchannel,
-          subchannel_list_, index,
-          grpc_connectivity_state_name(
-              subchannel_list_->subchannels[index].curr_connectivity_state));
-    }
-    if (subchannel_list_->subchannels[index].curr_connectivity_state ==
-        GRPC_CHANNEL_READY) {
-      if (grpc_lb_round_robin_trace.enabled()) {
-        gpr_log(GPR_DEBUG,
-                "[RR %p] found next ready subchannel (%p) at index %" PRIuPTR
-                " of subchannel_list %p",
-                this, subchannel_list_->subchannels[index].subchannel, index,
-                subchannel_list_);
-      }
-      return index;
-    }
-  }
-  if (grpc_lb_round_robin_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "[RR %p] no subchannels in ready state", this);
-  }
-  return subchannel_list_->num_subchannels;
-}
-
-// Sets last_ready_subchannel_index_ to last_ready_index.
-void RoundRobin::UpdateLastReadySubchannelIndexLocked(size_t last_ready_index) {
-  GPR_ASSERT(last_ready_index < subchannel_list_->num_subchannels);
-  last_ready_subchannel_index_ = last_ready_index;
-  if (grpc_lb_round_robin_trace.enabled()) {
-    gpr_log(GPR_DEBUG,
-            "[RR %p] setting last_ready_subchannel_index=%" PRIuPTR
-            " (SC %p, CSC %p)",
-            this, last_ready_index,
-            subchannel_list_->subchannels[last_ready_index].subchannel,
-            subchannel_list_->subchannels[last_ready_index]
-                .connected_subchannel.get());
-  }
-}
-
 void RoundRobin::HandOffPendingPicksLocked(LoadBalancingPolicy* new_policy) {
   PickState* pick;
   while ((pick = pending_picks_) != nullptr) {
@@ -207,7 +241,7 @@
 void RoundRobin::ShutdownLocked() {
   grpc_error* error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Channel shutdown");
   if (grpc_lb_round_robin_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "[RR %p] Shutting down", this);
+    gpr_log(GPR_INFO, "[RR %p] Shutting down", this);
   }
   shutdown_ = true;
   PickState* pick;
@@ -218,16 +252,8 @@
   }
   grpc_connectivity_state_set(&state_tracker_, GRPC_CHANNEL_SHUTDOWN,
                               GRPC_ERROR_REF(error), "rr_shutdown");
-  if (subchannel_list_ != nullptr) {
-    grpc_lb_subchannel_list_shutdown_and_unref(subchannel_list_,
-                                               "sl_shutdown_rr_shutdown");
-    subchannel_list_ = nullptr;
-  }
-  if (latest_pending_subchannel_list_ != nullptr) {
-    grpc_lb_subchannel_list_shutdown_and_unref(
-        latest_pending_subchannel_list_, "sl_shutdown_pending_rr_shutdown");
-    latest_pending_subchannel_list_ = nullptr;
-  }
+  subchannel_list_.reset();
+  latest_pending_subchannel_list_.reset();
   TryReresolutionLocked(&grpc_lb_round_robin_trace, GRPC_ERROR_CANCELLED);
   GRPC_ERROR_UNREF(error);
 }
@@ -273,34 +299,9 @@
   GRPC_ERROR_UNREF(error);
 }
 
-void RoundRobin::SubchannelListRefForConnectivityWatch(
-    grpc_lb_subchannel_list* subchannel_list, const char* reason) {
-  // TODO(roth): We currently track this ref manually.  Once the new
-  // ClosureRef API is ready and the subchannel_list code has been
-  // converted to a C++ API, find a way to hold the RefCountedPtr<>
-  // somewhere (maybe in the subchannel_data object) instead of doing
-  // this manually.
-  auto self = Ref(DEBUG_LOCATION, reason);
-  self.release();
-  grpc_lb_subchannel_list_ref(subchannel_list, reason);
-}
-
-void RoundRobin::SubchannelListUnrefForConnectivityWatch(
-    grpc_lb_subchannel_list* subchannel_list, const char* reason) {
-  Unref(DEBUG_LOCATION, reason);
-  grpc_lb_subchannel_list_unref(subchannel_list, reason);
-}
-
 void RoundRobin::StartPickingLocked() {
   started_picking_ = true;
-  for (size_t i = 0; i < subchannel_list_->num_subchannels; i++) {
-    if (subchannel_list_->subchannels[i].subchannel != nullptr) {
-      SubchannelListRefForConnectivityWatch(subchannel_list_,
-                                            "connectivity_watch");
-      grpc_lb_subchannel_data_start_connectivity_watch(
-          &subchannel_list_->subchannels[i]);
-    }
-  }
+  subchannel_list_->StartWatchingLocked();
 }
 
 void RoundRobin::ExitIdleLocked() {
@@ -309,34 +310,48 @@
   }
 }
 
+bool RoundRobin::DoPickLocked(PickState* pick) {
+  const size_t next_ready_index =
+      subchannel_list_->GetNextReadySubchannelIndexLocked();
+  if (next_ready_index < subchannel_list_->num_subchannels()) {
+    /* readily available, report right away */
+    RoundRobinSubchannelData* sd =
+        subchannel_list_->subchannel(next_ready_index);
+    GPR_ASSERT(sd->connected_subchannel() != nullptr);
+    pick->connected_subchannel = sd->connected_subchannel()->Ref();
+    if (pick->user_data != nullptr) {
+      *pick->user_data = sd->user_data();
+    }
+    if (grpc_lb_round_robin_trace.enabled()) {
+      gpr_log(GPR_INFO,
+              "[RR %p] Picked target <-- Subchannel %p (connected %p) (sl %p, "
+              "index %" PRIuPTR ")",
+              this, sd->subchannel(), pick->connected_subchannel.get(),
+              sd->subchannel_list(), next_ready_index);
+    }
+    /* only advance the last picked pointer if the selection was used */
+    subchannel_list_->UpdateLastReadySubchannelIndexLocked(next_ready_index);
+    return true;
+  }
+  return false;
+}
+
+void RoundRobin::DrainPendingPicksLocked() {
+  PickState* pick;
+  while ((pick = pending_picks_)) {
+    pending_picks_ = pick->next;
+    GPR_ASSERT(DoPickLocked(pick));
+    GRPC_CLOSURE_SCHED(pick->on_complete, GRPC_ERROR_NONE);
+  }
+}
+
 bool RoundRobin::PickLocked(PickState* pick) {
   if (grpc_lb_round_robin_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "[RR %p] Trying to pick (shutdown: %d)", this,
-            shutdown_);
+    gpr_log(GPR_INFO, "[RR %p] Trying to pick (shutdown: %d)", this, shutdown_);
   }
   GPR_ASSERT(!shutdown_);
   if (subchannel_list_ != nullptr) {
-    const size_t next_ready_index = GetNextReadySubchannelIndexLocked();
-    if (next_ready_index < subchannel_list_->num_subchannels) {
-      /* readily available, report right away */
-      grpc_lb_subchannel_data* sd =
-          &subchannel_list_->subchannels[next_ready_index];
-      pick->connected_subchannel = sd->connected_subchannel;
-      if (pick->user_data != nullptr) {
-        *pick->user_data = sd->user_data;
-      }
-      if (grpc_lb_round_robin_trace.enabled()) {
-        gpr_log(
-            GPR_DEBUG,
-            "[RR %p] Picked target <-- Subchannel %p (connected %p) (sl %p, "
-            "index %" PRIuPTR ")",
-            this, sd->subchannel, pick->connected_subchannel.get(),
-            sd->subchannel_list, next_ready_index);
-      }
-      /* only advance the last picked pointer if the selection was used */
-      UpdateLastReadySubchannelIndexLocked(next_ready_index);
-      return true;
-    }
+    if (DoPickLocked(pick)) return true;
   }
   /* no pick currently available. Save for later in list of pending picks */
   if (!started_picking_) {
@@ -347,36 +362,62 @@
   return false;
 }
 
-void UpdateStateCountersLocked(grpc_lb_subchannel_data* sd) {
-  grpc_lb_subchannel_list* subchannel_list = sd->subchannel_list;
-  GPR_ASSERT(sd->prev_connectivity_state != GRPC_CHANNEL_SHUTDOWN);
-  GPR_ASSERT(sd->curr_connectivity_state != GRPC_CHANNEL_SHUTDOWN);
-  if (sd->prev_connectivity_state == GRPC_CHANNEL_READY) {
-    GPR_ASSERT(subchannel_list->num_ready > 0);
-    --subchannel_list->num_ready;
-  } else if (sd->prev_connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
-    GPR_ASSERT(subchannel_list->num_transient_failures > 0);
-    --subchannel_list->num_transient_failures;
-  } else if (sd->prev_connectivity_state == GRPC_CHANNEL_IDLE) {
-    GPR_ASSERT(subchannel_list->num_idle > 0);
-    --subchannel_list->num_idle;
+void RoundRobin::RoundRobinSubchannelList::StartWatchingLocked() {
+  if (num_subchannels() == 0) return;
+  // Check current state of each subchannel synchronously, since any
+  // subchannel already used by some other channel may have a non-IDLE
+  // state.
+  for (size_t i = 0; i < num_subchannels(); ++i) {
+    grpc_error* error = GRPC_ERROR_NONE;
+    grpc_connectivity_state state =
+        subchannel(i)->CheckConnectivityStateLocked(&error);
+    if (state != GRPC_CHANNEL_IDLE) {
+      subchannel(i)->UpdateConnectivityStateLocked(state, error);
+    }
   }
-  sd->prev_connectivity_state = sd->curr_connectivity_state;
-  if (sd->curr_connectivity_state == GRPC_CHANNEL_READY) {
-    ++subchannel_list->num_ready;
-  } else if (sd->curr_connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
-    ++subchannel_list->num_transient_failures;
-  } else if (sd->curr_connectivity_state == GRPC_CHANNEL_IDLE) {
-    ++subchannel_list->num_idle;
+  // Now set the LB policy's state based on the subchannels' states.
+  UpdateRoundRobinStateFromSubchannelStateCountsLocked();
+  // Start connectivity watch for each subchannel.
+  for (size_t i = 0; i < num_subchannels(); i++) {
+    if (subchannel(i)->subchannel() != nullptr) {
+      subchannel(i)->StartConnectivityWatchLocked();
+    }
   }
 }
 
-/** Sets the policy's connectivity status based on that of the passed-in \a sd
- * (the grpc_lb_subchannel_data associated with the updated subchannel) and the
- * subchannel list \a sd belongs to (sd->subchannel_list). \a error will be used
- * only if the policy transitions to state TRANSIENT_FAILURE. */
-void RoundRobin::UpdateConnectivityStatusLocked(grpc_lb_subchannel_data* sd,
-                                                grpc_error* error) {
+void RoundRobin::RoundRobinSubchannelList::UpdateStateCountersLocked(
+    grpc_connectivity_state old_state, grpc_connectivity_state new_state,
+    grpc_error* transient_failure_error) {
+  GPR_ASSERT(old_state != GRPC_CHANNEL_SHUTDOWN);
+  GPR_ASSERT(new_state != GRPC_CHANNEL_SHUTDOWN);
+  if (old_state == GRPC_CHANNEL_READY) {
+    GPR_ASSERT(num_ready_ > 0);
+    --num_ready_;
+  } else if (old_state == GRPC_CHANNEL_CONNECTING) {
+    GPR_ASSERT(num_connecting_ > 0);
+    --num_connecting_;
+  } else if (old_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
+    GPR_ASSERT(num_transient_failure_ > 0);
+    --num_transient_failure_;
+  }
+  if (new_state == GRPC_CHANNEL_READY) {
+    ++num_ready_;
+  } else if (new_state == GRPC_CHANNEL_CONNECTING) {
+    ++num_connecting_;
+  } else if (new_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
+    ++num_transient_failure_;
+  }
+  GRPC_ERROR_UNREF(last_transient_failure_error_);
+  last_transient_failure_error_ = transient_failure_error;
+}
+
+// Sets the RR policy's connectivity state based on the current
+// subchannel list.
+void RoundRobin::RoundRobinSubchannelList::
+    MaybeUpdateRoundRobinConnectivityStateLocked() {
+  RoundRobin* p = static_cast<RoundRobin*>(policy());
+  // Only set connectivity state if this is the current subchannel list.
+  if (p->subchannel_list_.get() != this) return;
   /* In priority order. The first rule to match terminates the search (ie, if we
    * are on rule n, all previous rules were unfulfilled).
    *
@@ -391,155 +432,151 @@
    *    CHECK: subchannel_list->num_transient_failures ==
    *           subchannel_list->num_subchannels.
    */
-  grpc_lb_subchannel_list* subchannel_list = sd->subchannel_list;
-  GPR_ASSERT(sd->curr_connectivity_state != GRPC_CHANNEL_IDLE);
-  if (subchannel_list->num_ready > 0) {
+  if (num_ready_ > 0) {
     /* 1) READY */
-    grpc_connectivity_state_set(&state_tracker_, GRPC_CHANNEL_READY,
+    grpc_connectivity_state_set(&p->state_tracker_, GRPC_CHANNEL_READY,
                                 GRPC_ERROR_NONE, "rr_ready");
-  } else if (sd->curr_connectivity_state == GRPC_CHANNEL_CONNECTING) {
+  } else if (num_connecting_ > 0) {
     /* 2) CONNECTING */
-    grpc_connectivity_state_set(&state_tracker_, GRPC_CHANNEL_CONNECTING,
+    grpc_connectivity_state_set(&p->state_tracker_, GRPC_CHANNEL_CONNECTING,
                                 GRPC_ERROR_NONE, "rr_connecting");
-  } else if (subchannel_list->num_transient_failures ==
-             subchannel_list->num_subchannels) {
+  } else if (num_transient_failure_ == num_subchannels()) {
     /* 3) TRANSIENT_FAILURE */
-    grpc_connectivity_state_set(&state_tracker_, GRPC_CHANNEL_TRANSIENT_FAILURE,
-                                GRPC_ERROR_REF(error),
+    grpc_connectivity_state_set(&p->state_tracker_,
+                                GRPC_CHANNEL_TRANSIENT_FAILURE,
+                                GRPC_ERROR_REF(last_transient_failure_error_),
                                 "rr_exhausted_subchannels");
   }
-  GRPC_ERROR_UNREF(error);
 }
 
-void RoundRobin::OnConnectivityChangedLocked(void* arg, grpc_error* error) {
-  grpc_lb_subchannel_data* sd = static_cast<grpc_lb_subchannel_data*>(arg);
-  RoundRobin* p = static_cast<RoundRobin*>(sd->subchannel_list->policy);
+void RoundRobin::RoundRobinSubchannelList::
+    UpdateRoundRobinStateFromSubchannelStateCountsLocked() {
+  RoundRobin* p = static_cast<RoundRobin*>(policy());
+  if (num_ready_ > 0) {
+    if (p->subchannel_list_.get() != this) {
+      // Promote this list to p->subchannel_list_.
+      // This list must be p->latest_pending_subchannel_list_, because
+      // any previous update would have been shut down already and
+      // therefore we would not be receiving a notification for them.
+      GPR_ASSERT(p->latest_pending_subchannel_list_.get() == this);
+      GPR_ASSERT(!shutting_down());
+      if (grpc_lb_round_robin_trace.enabled()) {
+        const size_t old_num_subchannels =
+            p->subchannel_list_ != nullptr
+                ? p->subchannel_list_->num_subchannels()
+                : 0;
+        gpr_log(GPR_INFO,
+                "[RR %p] phasing out subchannel list %p (size %" PRIuPTR
+                ") in favor of %p (size %" PRIuPTR ")",
+                p, p->subchannel_list_.get(), old_num_subchannels, this,
+                num_subchannels());
+      }
+      p->subchannel_list_ = std::move(p->latest_pending_subchannel_list_);
+    }
+    // Drain pending picks.
+    p->DrainPendingPicksLocked();
+  }
+  // Update the RR policy's connectivity state if needed.
+  MaybeUpdateRoundRobinConnectivityStateLocked();
+}
+
+void RoundRobin::RoundRobinSubchannelData::UpdateConnectivityStateLocked(
+    grpc_connectivity_state connectivity_state, grpc_error* error) {
+  RoundRobin* p = static_cast<RoundRobin*>(subchannel_list()->policy());
   if (grpc_lb_round_robin_trace.enabled()) {
     gpr_log(
-        GPR_DEBUG,
-        "[RR %p] connectivity changed for subchannel %p, subchannel_list %p: "
-        "prev_state=%s new_state=%s p->shutdown=%d "
-        "sd->subchannel_list->shutting_down=%d error=%s",
-        p, sd->subchannel, sd->subchannel_list,
-        grpc_connectivity_state_name(sd->prev_connectivity_state),
-        grpc_connectivity_state_name(sd->pending_connectivity_state_unsafe),
-        p->shutdown_, sd->subchannel_list->shutting_down,
-        grpc_error_string(error));
+        GPR_INFO,
+        "[RR %p] connectivity changed for subchannel %p, subchannel_list %p "
+        "(index %" PRIuPTR " of %" PRIuPTR "): prev_state=%s new_state=%s",
+        p, subchannel(), subchannel_list(), Index(),
+        subchannel_list()->num_subchannels(),
+        grpc_connectivity_state_name(last_connectivity_state_),
+        grpc_connectivity_state_name(connectivity_state));
   }
-  GPR_ASSERT(sd->subchannel != nullptr);
-  // If the policy is shutting down, unref and return.
-  if (p->shutdown_) {
-    grpc_lb_subchannel_data_stop_connectivity_watch(sd);
-    grpc_lb_subchannel_data_unref_subchannel(sd, "rr_shutdown");
-    p->SubchannelListUnrefForConnectivityWatch(sd->subchannel_list,
-                                               "rr_shutdown");
-    return;
-  }
-  // If the subchannel list is shutting down, stop watching.
-  if (sd->subchannel_list->shutting_down || error == GRPC_ERROR_CANCELLED) {
-    grpc_lb_subchannel_data_stop_connectivity_watch(sd);
-    grpc_lb_subchannel_data_unref_subchannel(sd, "rr_sl_shutdown");
-    p->SubchannelListUnrefForConnectivityWatch(sd->subchannel_list,
-                                               "rr_sl_shutdown");
-    return;
-  }
-  // If we're still here, the notification must be for a subchannel in
-  // either the current or latest pending subchannel lists.
-  GPR_ASSERT(sd->subchannel_list == p->subchannel_list_ ||
-             sd->subchannel_list == p->latest_pending_subchannel_list_);
-  GPR_ASSERT(sd->pending_connectivity_state_unsafe != GRPC_CHANNEL_SHUTDOWN);
-  // Now that we're inside the combiner, copy the pending connectivity
-  // state (which was set by the connectivity state watcher) to
-  // curr_connectivity_state, which is what we use inside of the combiner.
-  sd->curr_connectivity_state = sd->pending_connectivity_state_unsafe;
-  // If the sd's new state is TRANSIENT_FAILURE, unref the *connected*
-  // subchannel, if any.
-  switch (sd->curr_connectivity_state) {
-    case GRPC_CHANNEL_TRANSIENT_FAILURE: {
-      sd->connected_subchannel.reset();
-      if (grpc_lb_round_robin_trace.enabled()) {
-        gpr_log(GPR_DEBUG,
-                "[RR %p] Subchannel %p has gone into TRANSIENT_FAILURE. "
-                "Requesting re-resolution",
-                p, sd->subchannel);
-      }
-      p->TryReresolutionLocked(&grpc_lb_round_robin_trace, GRPC_ERROR_NONE);
-      break;
+  subchannel_list()->UpdateStateCountersLocked(last_connectivity_state_,
+                                               connectivity_state, error);
+  last_connectivity_state_ = connectivity_state;
+}
+
+void RoundRobin::RoundRobinSubchannelData::ProcessConnectivityChangeLocked(
+    grpc_connectivity_state connectivity_state, grpc_error* error) {
+  RoundRobin* p = static_cast<RoundRobin*>(subchannel_list()->policy());
+  GPR_ASSERT(subchannel() != nullptr);
+  // If the new state is TRANSIENT_FAILURE, re-resolve.
+  // Only do this if we've started watching, not at startup time.
+  // Otherwise, if the subchannel was already in state TRANSIENT_FAILURE
+  // when the subchannel list was created, we'd wind up in a constant
+  // loop of re-resolution.
+  if (connectivity_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
+    if (grpc_lb_round_robin_trace.enabled()) {
+      gpr_log(GPR_INFO,
+              "[RR %p] Subchannel %p has gone into TRANSIENT_FAILURE. "
+              "Requesting re-resolution",
+              p, subchannel());
     }
-    case GRPC_CHANNEL_READY: {
-      if (sd->connected_subchannel == nullptr) {
-        sd->connected_subchannel =
-            grpc_subchannel_get_connected_subchannel(sd->subchannel);
-      }
-      if (sd->subchannel_list != p->subchannel_list_) {
-        // promote sd->subchannel_list to p->subchannel_list_.
-        // sd->subchannel_list must be equal to
-        // p->latest_pending_subchannel_list_ because we have already filtered
-        // for sds belonging to outdated subchannel lists.
-        GPR_ASSERT(sd->subchannel_list == p->latest_pending_subchannel_list_);
-        GPR_ASSERT(!sd->subchannel_list->shutting_down);
-        if (grpc_lb_round_robin_trace.enabled()) {
-          const size_t num_subchannels =
-              p->subchannel_list_ != nullptr
-                  ? p->subchannel_list_->num_subchannels
-                  : 0;
-          gpr_log(GPR_DEBUG,
-                  "[RR %p] phasing out subchannel list %p (size %" PRIuPTR
-                  ") in favor of %p (size %" PRIuPTR ")",
-                  p, p->subchannel_list_, num_subchannels, sd->subchannel_list,
-                  num_subchannels);
-        }
-        if (p->subchannel_list_ != nullptr) {
-          // dispose of the current subchannel_list
-          grpc_lb_subchannel_list_shutdown_and_unref(p->subchannel_list_,
-                                                     "sl_phase_out_shutdown");
-        }
-        p->subchannel_list_ = p->latest_pending_subchannel_list_;
-        p->latest_pending_subchannel_list_ = nullptr;
-      }
-      /* at this point we know there's at least one suitable subchannel. Go
-       * ahead and pick one and notify the pending suitors in
-       * p->pending_picks. This preemptively replicates rr_pick()'s actions. */
-      const size_t next_ready_index = p->GetNextReadySubchannelIndexLocked();
-      GPR_ASSERT(next_ready_index < p->subchannel_list_->num_subchannels);
-      grpc_lb_subchannel_data* selected =
-          &p->subchannel_list_->subchannels[next_ready_index];
-      if (p->pending_picks_ != nullptr) {
-        // if the selected subchannel is going to be used for the pending
-        // picks, update the last picked pointer
-        p->UpdateLastReadySubchannelIndexLocked(next_ready_index);
-      }
-      PickState* pick;
-      while ((pick = p->pending_picks_)) {
-        p->pending_picks_ = pick->next;
-        pick->connected_subchannel = selected->connected_subchannel;
-        if (pick->user_data != nullptr) {
-          *pick->user_data = selected->user_data;
-        }
-        if (grpc_lb_round_robin_trace.enabled()) {
-          gpr_log(GPR_DEBUG,
-                  "[RR %p] Fulfilling pending pick. Target <-- subchannel %p "
-                  "(subchannel_list %p, index %" PRIuPTR ")",
-                  p, selected->subchannel, p->subchannel_list_,
-                  next_ready_index);
-        }
-        GRPC_CLOSURE_SCHED(pick->on_complete, GRPC_ERROR_NONE);
-      }
-      break;
-    }
-    case GRPC_CHANNEL_SHUTDOWN:
-      GPR_UNREACHABLE_CODE(return );
-    case GRPC_CHANNEL_CONNECTING:
-    case GRPC_CHANNEL_IDLE:;  // fallthrough
+    p->TryReresolutionLocked(&grpc_lb_round_robin_trace, GRPC_ERROR_NONE);
   }
   // Update state counters.
-  UpdateStateCountersLocked(sd);
-  // Only update connectivity based on the selected subchannel list.
-  if (sd->subchannel_list == p->subchannel_list_) {
-    p->UpdateConnectivityStatusLocked(sd, GRPC_ERROR_REF(error));
+  UpdateConnectivityStateLocked(connectivity_state, error);
+  // Update overall state and renew notification.
+  subchannel_list()->UpdateRoundRobinStateFromSubchannelStateCountsLocked();
+  RenewConnectivityWatchLocked();
+}
+
+/** Returns the index into p->subchannel_list->subchannels of the next
+ * subchannel in READY state, or p->subchannel_list->num_subchannels if no
+ * subchannel is READY.
+ *
+ * Note that this function does *not* update p->last_ready_subchannel_index.
+ * The caller must do that if it returns a pick. */
+size_t
+RoundRobin::RoundRobinSubchannelList::GetNextReadySubchannelIndexLocked() {
+  if (grpc_lb_round_robin_trace.enabled()) {
+    gpr_log(GPR_INFO,
+            "[RR %p] getting next ready subchannel (out of %" PRIuPTR
+            "), last_ready_index=%" PRIuPTR,
+            policy(), num_subchannels(), last_ready_index_);
   }
-  // Renew notification.
-  grpc_lb_subchannel_data_start_connectivity_watch(sd);
+  for (size_t i = 0; i < num_subchannels(); ++i) {
+    const size_t index = (i + last_ready_index_ + 1) % num_subchannels();
+    if (grpc_lb_round_robin_trace.enabled()) {
+      gpr_log(
+          GPR_INFO,
+          "[RR %p] checking subchannel %p, subchannel_list %p, index %" PRIuPTR
+          ": state=%s",
+          policy(), subchannel(index)->subchannel(), this, index,
+          grpc_connectivity_state_name(
+              subchannel(index)->connectivity_state()));
+    }
+    if (subchannel(index)->connectivity_state() == GRPC_CHANNEL_READY) {
+      if (grpc_lb_round_robin_trace.enabled()) {
+        gpr_log(GPR_INFO,
+                "[RR %p] found next ready subchannel (%p) at index %" PRIuPTR
+                " of subchannel_list %p",
+                policy(), subchannel(index)->subchannel(), index, this);
+      }
+      return index;
+    }
+  }
+  if (grpc_lb_round_robin_trace.enabled()) {
+    gpr_log(GPR_INFO, "[RR %p] no subchannels in ready state", this);
+  }
+  return num_subchannels();
+}
+
+// Sets last_ready_index_ to last_ready_index.
+void RoundRobin::RoundRobinSubchannelList::UpdateLastReadySubchannelIndexLocked(
+    size_t last_ready_index) {
+  GPR_ASSERT(last_ready_index < num_subchannels());
+  last_ready_index_ = last_ready_index;
+  if (grpc_lb_round_robin_trace.enabled()) {
+    gpr_log(GPR_INFO,
+            "[RR %p] setting last_ready_subchannel_index=%" PRIuPTR
+            " (SC %p, CSC %p)",
+            policy(), last_ready_index,
+            subchannel(last_ready_index)->subchannel(),
+            subchannel(last_ready_index)->connected_subchannel());
+  }
 }
 
 grpc_connectivity_state RoundRobin::CheckConnectivityLocked(
@@ -555,11 +592,12 @@
 
 void RoundRobin::PingOneLocked(grpc_closure* on_initiate,
                                grpc_closure* on_ack) {
-  const size_t next_ready_index = GetNextReadySubchannelIndexLocked();
-  if (next_ready_index < subchannel_list_->num_subchannels) {
-    grpc_lb_subchannel_data* selected =
-        &subchannel_list_->subchannels[next_ready_index];
-    selected->connected_subchannel->Ping(on_initiate, on_ack);
+  const size_t next_ready_index =
+      subchannel_list_->GetNextReadySubchannelIndexLocked();
+  if (next_ready_index < subchannel_list_->num_subchannels()) {
+    RoundRobinSubchannelData* selected =
+        subchannel_list_->subchannel(next_ready_index);
+    selected->connected_subchannel()->Ping(on_initiate, on_ack);
   } else {
     GRPC_CLOSURE_SCHED(on_initiate, GRPC_ERROR_CREATE_FROM_STATIC_STRING(
                                         "Round Robin not connected"));
@@ -582,80 +620,37 @@
     }
     return;
   }
-  grpc_lb_addresses* addresses = (grpc_lb_addresses*)arg->value.pointer.p;
+  grpc_lb_addresses* addresses =
+      static_cast<grpc_lb_addresses*>(arg->value.pointer.p);
   if (grpc_lb_round_robin_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "[RR %p] received update with %" PRIuPTR " addresses",
+    gpr_log(GPR_INFO, "[RR %p] received update with %" PRIuPTR " addresses",
             this, addresses->num_addresses);
   }
-  grpc_lb_subchannel_list* subchannel_list = grpc_lb_subchannel_list_create(
-      this, &grpc_lb_round_robin_trace, addresses, combiner(),
-      client_channel_factory(), args, &RoundRobin::OnConnectivityChangedLocked);
-  if (subchannel_list->num_subchannels == 0) {
-    grpc_connectivity_state_set(
-        &state_tracker_, GRPC_CHANNEL_TRANSIENT_FAILURE,
-        GRPC_ERROR_CREATE_FROM_STATIC_STRING("Empty update"),
-        "rr_update_empty");
-    if (subchannel_list_ != nullptr) {
-      grpc_lb_subchannel_list_shutdown_and_unref(subchannel_list_,
-                                                 "sl_shutdown_empty_update");
+  // Replace latest_pending_subchannel_list_.
+  if (latest_pending_subchannel_list_ != nullptr) {
+    if (grpc_lb_round_robin_trace.enabled()) {
+      gpr_log(GPR_INFO,
+              "[RR %p] Shutting down previous pending subchannel list %p", this,
+              latest_pending_subchannel_list_.get());
     }
-    subchannel_list_ = subchannel_list;  // empty list
-    return;
   }
-  if (started_picking_) {
-    for (size_t i = 0; i < subchannel_list->num_subchannels; ++i) {
-      const grpc_connectivity_state subchannel_state =
-          grpc_subchannel_check_connectivity(
-              subchannel_list->subchannels[i].subchannel, nullptr);
-      // Override the default setting of IDLE for connectivity notification
-      // purposes if the subchannel is already in transient failure. Otherwise
-      // we'd be immediately notified of the IDLE-TRANSIENT_FAILURE
-      // discrepancy, attempt to re-resolve and end up here again.
-      // TODO(roth): As part of C++-ifying the subchannel_list API, design a
-      // better API for notifying the LB policy of subchannel states, which can
-      // be used both for the subchannel's initial state and for subsequent
-      // state changes. This will allow us to handle this more generally instead
-      // of special-casing TRANSIENT_FAILURE (e.g., we can also distribute any
-      // pending picks across all READY subchannels rather than sending them all
-      // to the first one).
-      if (subchannel_state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
-        subchannel_list->subchannels[i].pending_connectivity_state_unsafe =
-            subchannel_list->subchannels[i].curr_connectivity_state =
-                subchannel_list->subchannels[i].prev_connectivity_state =
-                    subchannel_state;
-        --subchannel_list->num_idle;
-        ++subchannel_list->num_transient_failures;
-      }
+  latest_pending_subchannel_list_ = MakeOrphanable<RoundRobinSubchannelList>(
+      this, &grpc_lb_round_robin_trace, addresses, combiner(),
+      client_channel_factory(), args);
+  // If we haven't started picking yet or the new list is empty,
+  // immediately promote the new list to the current list.
+  if (!started_picking_ ||
+      latest_pending_subchannel_list_->num_subchannels() == 0) {
+    if (latest_pending_subchannel_list_->num_subchannels() == 0) {
+      grpc_connectivity_state_set(
+          &state_tracker_, GRPC_CHANNEL_TRANSIENT_FAILURE,
+          GRPC_ERROR_CREATE_FROM_STATIC_STRING("Empty update"),
+          "rr_update_empty");
     }
-    if (latest_pending_subchannel_list_ != nullptr) {
-      if (grpc_lb_round_robin_trace.enabled()) {
-        gpr_log(GPR_DEBUG,
-                "[RR %p] Shutting down latest pending subchannel list %p, "
-                "about to be replaced by newer latest %p",
-                this, latest_pending_subchannel_list_, subchannel_list);
-      }
-      grpc_lb_subchannel_list_shutdown_and_unref(
-          latest_pending_subchannel_list_, "sl_outdated");
-    }
-    latest_pending_subchannel_list_ = subchannel_list;
-    for (size_t i = 0; i < subchannel_list->num_subchannels; ++i) {
-      /* Watch every new subchannel. A subchannel list becomes active the
-       * moment one of its subchannels is READY. At that moment, we swap
-       * p->subchannel_list for sd->subchannel_list, provided the subchannel
-       * list is still valid (ie, isn't shutting down) */
-      SubchannelListRefForConnectivityWatch(subchannel_list,
-                                            "connectivity_watch");
-      grpc_lb_subchannel_data_start_connectivity_watch(
-          &subchannel_list->subchannels[i]);
-    }
+    subchannel_list_ = std::move(latest_pending_subchannel_list_);
   } else {
-    // The policy isn't picking yet. Save the update for later, disposing of
-    // previous version if any.
-    if (subchannel_list_ != nullptr) {
-      grpc_lb_subchannel_list_shutdown_and_unref(
-          subchannel_list_, "rr_update_before_started_picking");
-    }
-    subchannel_list_ = subchannel_list;
+    // If we've started picking, start watching the new list.
+    latest_pending_subchannel_list_->StartWatchingLocked();
   }
 }
 
diff --git a/src/core/ext/filters/client_channel/lb_policy/subchannel_list.cc b/src/core/ext/filters/client_channel/lb_policy/subchannel_list.cc
deleted file mode 100644
index 79cb64c..0000000
--- a/src/core/ext/filters/client_channel/lb_policy/subchannel_list.cc
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- *
- * Copyright 2015 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.
- *
- */
-
-#include <grpc/support/port_platform.h>
-
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-
-#include "src/core/ext/filters/client_channel/lb_policy/subchannel_list.h"
-#include "src/core/lib/channel/channel_args.h"
-#include "src/core/lib/debug/trace.h"
-#include "src/core/lib/iomgr/closure.h"
-#include "src/core/lib/iomgr/combiner.h"
-#include "src/core/lib/iomgr/sockaddr_utils.h"
-#include "src/core/lib/transport/connectivity_state.h"
-
-void grpc_lb_subchannel_data_unref_subchannel(grpc_lb_subchannel_data* sd,
-                                              const char* reason) {
-  if (sd->subchannel != nullptr) {
-    if (sd->subchannel_list->tracer->enabled()) {
-      gpr_log(GPR_DEBUG,
-              "[%s %p] subchannel list %p index %" PRIuPTR " of %" PRIuPTR
-              " (subchannel %p): unreffing subchannel",
-              sd->subchannel_list->tracer->name(), sd->subchannel_list->policy,
-              sd->subchannel_list,
-              static_cast<size_t>(sd - sd->subchannel_list->subchannels),
-              sd->subchannel_list->num_subchannels, sd->subchannel);
-    }
-    GRPC_SUBCHANNEL_UNREF(sd->subchannel, reason);
-    sd->subchannel = nullptr;
-    sd->connected_subchannel.reset();
-    if (sd->user_data != nullptr) {
-      GPR_ASSERT(sd->user_data_vtable != nullptr);
-      sd->user_data_vtable->destroy(sd->user_data);
-      sd->user_data = nullptr;
-    }
-  }
-}
-
-void grpc_lb_subchannel_data_start_connectivity_watch(
-    grpc_lb_subchannel_data* sd) {
-  if (sd->subchannel_list->tracer->enabled()) {
-    gpr_log(
-        GPR_DEBUG,
-        "[%s %p] subchannel list %p index %" PRIuPTR " of %" PRIuPTR
-        " (subchannel %p): requesting connectivity change "
-        "notification (from %s)",
-        sd->subchannel_list->tracer->name(), sd->subchannel_list->policy,
-        sd->subchannel_list,
-        static_cast<size_t>(sd - sd->subchannel_list->subchannels),
-        sd->subchannel_list->num_subchannels, sd->subchannel,
-        grpc_connectivity_state_name(sd->pending_connectivity_state_unsafe));
-  }
-  sd->connectivity_notification_pending = true;
-  grpc_subchannel_notify_on_state_change(
-      sd->subchannel, sd->subchannel_list->policy->interested_parties(),
-      &sd->pending_connectivity_state_unsafe,
-      &sd->connectivity_changed_closure);
-}
-
-void grpc_lb_subchannel_data_stop_connectivity_watch(
-    grpc_lb_subchannel_data* sd) {
-  if (sd->subchannel_list->tracer->enabled()) {
-    gpr_log(GPR_DEBUG,
-            "[%s %p] subchannel list %p index %" PRIuPTR " of %" PRIuPTR
-            " (subchannel %p): stopping connectivity watch",
-            sd->subchannel_list->tracer->name(), sd->subchannel_list->policy,
-            sd->subchannel_list,
-            static_cast<size_t>(sd - sd->subchannel_list->subchannels),
-            sd->subchannel_list->num_subchannels, sd->subchannel);
-  }
-  GPR_ASSERT(sd->connectivity_notification_pending);
-  sd->connectivity_notification_pending = false;
-}
-
-grpc_lb_subchannel_list* grpc_lb_subchannel_list_create(
-    grpc_core::LoadBalancingPolicy* p, grpc_core::TraceFlag* tracer,
-    const grpc_lb_addresses* addresses, grpc_combiner* combiner,
-    grpc_client_channel_factory* client_channel_factory,
-    const grpc_channel_args& args, grpc_iomgr_cb_func connectivity_changed_cb) {
-  grpc_lb_subchannel_list* subchannel_list =
-      static_cast<grpc_lb_subchannel_list*>(
-          gpr_zalloc(sizeof(*subchannel_list)));
-  if (tracer->enabled()) {
-    gpr_log(GPR_DEBUG,
-            "[%s %p] Creating subchannel list %p for %" PRIuPTR " subchannels",
-            tracer->name(), p, subchannel_list, addresses->num_addresses);
-  }
-  subchannel_list->policy = p;
-  subchannel_list->tracer = tracer;
-  gpr_ref_init(&subchannel_list->refcount, 1);
-  subchannel_list->subchannels = static_cast<grpc_lb_subchannel_data*>(
-      gpr_zalloc(sizeof(grpc_lb_subchannel_data) * addresses->num_addresses));
-  // We need to remove the LB addresses in order to be able to compare the
-  // subchannel keys of subchannels from a different batch of addresses.
-  static const char* keys_to_remove[] = {GRPC_ARG_SUBCHANNEL_ADDRESS,
-                                         GRPC_ARG_LB_ADDRESSES};
-  // Create a subchannel for each address.
-  grpc_subchannel_args sc_args;
-  size_t subchannel_index = 0;
-  for (size_t i = 0; i < addresses->num_addresses; i++) {
-    // If there were any balancer, we would have chosen grpclb policy instead.
-    GPR_ASSERT(!addresses->addresses[i].is_balancer);
-    memset(&sc_args, 0, sizeof(grpc_subchannel_args));
-    grpc_arg addr_arg =
-        grpc_create_subchannel_address_arg(&addresses->addresses[i].address);
-    grpc_channel_args* new_args = grpc_channel_args_copy_and_add_and_remove(
-        &args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), &addr_arg, 1);
-    gpr_free(addr_arg.value.string);
-    sc_args.args = new_args;
-    grpc_subchannel* subchannel = grpc_client_channel_factory_create_subchannel(
-        client_channel_factory, &sc_args);
-    grpc_channel_args_destroy(new_args);
-    if (subchannel == nullptr) {
-      // Subchannel could not be created.
-      if (tracer->enabled()) {
-        char* address_uri =
-            grpc_sockaddr_to_uri(&addresses->addresses[i].address);
-        gpr_log(GPR_DEBUG,
-                "[%s %p] could not create subchannel for address uri %s, "
-                "ignoring",
-                tracer->name(), subchannel_list->policy, address_uri);
-        gpr_free(address_uri);
-      }
-      continue;
-    }
-    if (tracer->enabled()) {
-      char* address_uri =
-          grpc_sockaddr_to_uri(&addresses->addresses[i].address);
-      gpr_log(GPR_DEBUG,
-              "[%s %p] subchannel list %p index %" PRIuPTR
-              ": Created subchannel %p for address uri %s",
-              tracer->name(), p, subchannel_list, subchannel_index, subchannel,
-              address_uri);
-      gpr_free(address_uri);
-    }
-    grpc_lb_subchannel_data* sd =
-        &subchannel_list->subchannels[subchannel_index++];
-    sd->subchannel_list = subchannel_list;
-    sd->subchannel = subchannel;
-    GRPC_CLOSURE_INIT(&sd->connectivity_changed_closure,
-                      connectivity_changed_cb, sd,
-                      grpc_combiner_scheduler(combiner));
-    // We assume that the current state is IDLE.  If not, we'll get a
-    // callback telling us that.
-    sd->prev_connectivity_state = GRPC_CHANNEL_IDLE;
-    sd->curr_connectivity_state = GRPC_CHANNEL_IDLE;
-    sd->pending_connectivity_state_unsafe = GRPC_CHANNEL_IDLE;
-    sd->user_data_vtable = addresses->user_data_vtable;
-    if (sd->user_data_vtable != nullptr) {
-      sd->user_data =
-          sd->user_data_vtable->copy(addresses->addresses[i].user_data);
-    }
-  }
-  subchannel_list->num_subchannels = subchannel_index;
-  subchannel_list->num_idle = subchannel_index;
-  return subchannel_list;
-}
-
-static void subchannel_list_destroy(grpc_lb_subchannel_list* subchannel_list) {
-  if (subchannel_list->tracer->enabled()) {
-    gpr_log(GPR_DEBUG, "[%s %p] Destroying subchannel_list %p",
-            subchannel_list->tracer->name(), subchannel_list->policy,
-            subchannel_list);
-  }
-  for (size_t i = 0; i < subchannel_list->num_subchannels; i++) {
-    grpc_lb_subchannel_data* sd = &subchannel_list->subchannels[i];
-    grpc_lb_subchannel_data_unref_subchannel(sd, "subchannel_list_destroy");
-  }
-  gpr_free(subchannel_list->subchannels);
-  gpr_free(subchannel_list);
-}
-
-void grpc_lb_subchannel_list_ref(grpc_lb_subchannel_list* subchannel_list,
-                                 const char* reason) {
-  gpr_ref_non_zero(&subchannel_list->refcount);
-  if (subchannel_list->tracer->enabled()) {
-    const gpr_atm count = gpr_atm_acq_load(&subchannel_list->refcount.count);
-    gpr_log(GPR_DEBUG, "[%s %p] subchannel_list %p REF %lu->%lu (%s)",
-            subchannel_list->tracer->name(), subchannel_list->policy,
-            subchannel_list, static_cast<unsigned long>(count - 1),
-            static_cast<unsigned long>(count), reason);
-  }
-}
-
-void grpc_lb_subchannel_list_unref(grpc_lb_subchannel_list* subchannel_list,
-                                   const char* reason) {
-  const bool done = gpr_unref(&subchannel_list->refcount);
-  if (subchannel_list->tracer->enabled()) {
-    const gpr_atm count = gpr_atm_acq_load(&subchannel_list->refcount.count);
-    gpr_log(GPR_DEBUG, "[%s %p] subchannel_list %p UNREF %lu->%lu (%s)",
-            subchannel_list->tracer->name(), subchannel_list->policy,
-            subchannel_list, static_cast<unsigned long>(count + 1),
-            static_cast<unsigned long>(count), reason);
-  }
-  if (done) {
-    subchannel_list_destroy(subchannel_list);
-  }
-}
-
-static void subchannel_data_cancel_connectivity_watch(
-    grpc_lb_subchannel_data* sd, const char* reason) {
-  if (sd->subchannel_list->tracer->enabled()) {
-    gpr_log(GPR_DEBUG,
-            "[%s %p] subchannel list %p index %" PRIuPTR " of %" PRIuPTR
-            " (subchannel %p): canceling connectivity watch (%s)",
-            sd->subchannel_list->tracer->name(), sd->subchannel_list->policy,
-            sd->subchannel_list,
-            static_cast<size_t>(sd - sd->subchannel_list->subchannels),
-            sd->subchannel_list->num_subchannels, sd->subchannel, reason);
-  }
-  grpc_subchannel_notify_on_state_change(sd->subchannel, nullptr, nullptr,
-                                         &sd->connectivity_changed_closure);
-}
-
-void grpc_lb_subchannel_list_shutdown_and_unref(
-    grpc_lb_subchannel_list* subchannel_list, const char* reason) {
-  if (subchannel_list->tracer->enabled()) {
-    gpr_log(GPR_DEBUG, "[%s %p] Shutting down subchannel_list %p (%s)",
-            subchannel_list->tracer->name(), subchannel_list->policy,
-            subchannel_list, reason);
-  }
-  GPR_ASSERT(!subchannel_list->shutting_down);
-  subchannel_list->shutting_down = true;
-  for (size_t i = 0; i < subchannel_list->num_subchannels; i++) {
-    grpc_lb_subchannel_data* sd = &subchannel_list->subchannels[i];
-    // If there's a pending notification for this subchannel, cancel it;
-    // the callback is responsible for unreffing the subchannel.
-    // Otherwise, unref the subchannel directly.
-    if (sd->connectivity_notification_pending) {
-      subchannel_data_cancel_connectivity_watch(sd, reason);
-    } else if (sd->subchannel != nullptr) {
-      grpc_lb_subchannel_data_unref_subchannel(sd, reason);
-    }
-  }
-  grpc_lb_subchannel_list_unref(subchannel_list, reason);
-}
diff --git a/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h b/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h
index 6889d59..7e2046b 100644
--- a/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h
+++ b/src/core/ext/filters/client_channel/lb_policy/subchannel_list.h
@@ -21,116 +21,516 @@
 
 #include <grpc/support/port_platform.h>
 
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+
 #include "src/core/ext/filters/client_channel/lb_policy_registry.h"
 #include "src/core/ext/filters/client_channel/subchannel.h"
+#include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/debug/trace.h"
+#include "src/core/lib/gprpp/abstract.h"
+#include "src/core/lib/gprpp/inlined_vector.h"
+#include "src/core/lib/gprpp/orphanable.h"
+#include "src/core/lib/gprpp/ref_counted.h"
 #include "src/core/lib/gprpp/ref_counted_ptr.h"
+#include "src/core/lib/iomgr/closure.h"
+#include "src/core/lib/iomgr/combiner.h"
+#include "src/core/lib/iomgr/sockaddr_utils.h"
 #include "src/core/lib/transport/connectivity_state.h"
 
-// TODO(roth): This code is intended to be shared between pick_first and
-// round_robin.  However, the interface needs more work to provide clean
-// encapsulation.  For example, the structs here have some fields that are
-// only used in one of the two (e.g., the state counters in
-// grpc_lb_subchannel_list and the prev_connectivity_state field in
-// grpc_lb_subchannel_data are only used in round_robin, and the
-// checking_subchannel field in grpc_lb_subchannel_list is only used by
-// pick_first).  Also, there is probably some code duplication between the
-// connectivity state notification callback code in both pick_first and
-// round_robin that could be refactored and moved here.  In a future PR,
-// need to clean this up.
+// Code for maintaining a list of subchannels within an LB policy.
+//
+// To use this, callers must create their own subclasses, like so:
+/*
 
-typedef struct grpc_lb_subchannel_list grpc_lb_subchannel_list;
+class MySubchannelList;  // Forward declaration.
 
-typedef struct {
-  /** backpointer to owning subchannel list */
-  grpc_lb_subchannel_list* subchannel_list;
-  /** subchannel itself */
-  grpc_subchannel* subchannel;
-  grpc_core::RefCountedPtr<grpc_core::ConnectedSubchannel> connected_subchannel;
-  /** Is a connectivity notification pending? */
-  bool connectivity_notification_pending;
-  /** notification that connectivity has changed on subchannel */
-  grpc_closure connectivity_changed_closure;
-  /** previous and current connectivity states.  Updated by \a
-   * \a connectivity_changed_closure based on
-   * \a pending_connectivity_state_unsafe. */
-  grpc_connectivity_state prev_connectivity_state;
-  grpc_connectivity_state curr_connectivity_state;
-  /** connectivity state to be updated by
-   * grpc_subchannel_notify_on_state_change(), not guarded by
-   * the combiner.  To be copied to \a curr_connectivity_state by
-   * \a connectivity_changed_closure. */
-  grpc_connectivity_state pending_connectivity_state_unsafe;
-  /** the subchannel's target user data */
-  void* user_data;
-  /** vtable to operate over \a user_data */
-  const grpc_lb_user_data_vtable* user_data_vtable;
-} grpc_lb_subchannel_data;
-
-/// Unrefs the subchannel contained in sd.
-void grpc_lb_subchannel_data_unref_subchannel(grpc_lb_subchannel_data* sd,
-                                              const char* reason);
-
-/// Starts watching the connectivity state of the subchannel.
-/// The connectivity_changed_cb callback must invoke either
-/// grpc_lb_subchannel_data_stop_connectivity_watch() or again call
-/// grpc_lb_subchannel_data_start_connectivity_watch().
-void grpc_lb_subchannel_data_start_connectivity_watch(
-    grpc_lb_subchannel_data* sd);
-
-/// Stops watching the connectivity state of the subchannel.
-void grpc_lb_subchannel_data_stop_connectivity_watch(
-    grpc_lb_subchannel_data* sd);
-
-struct grpc_lb_subchannel_list {
-  /** backpointer to owning policy */
-  grpc_core::LoadBalancingPolicy* policy;
-
-  grpc_core::TraceFlag* tracer;
-
-  /** all our subchannels */
-  size_t num_subchannels;
-  grpc_lb_subchannel_data* subchannels;
-
-  /** Index into subchannels of the one we're currently checking.
-   * Used when connecting to subchannels serially instead of in parallel. */
-  // TODO(roth): When we have time, we can probably make this go away
-  // and compute the index dynamically by subtracting
-  // subchannel_list->subchannels from the subchannel_data pointer.
-  size_t checking_subchannel;
-
-  /** how many subchannels are in state READY */
-  size_t num_ready;
-  /** how many subchannels are in state TRANSIENT_FAILURE */
-  size_t num_transient_failures;
-  /** how many subchannels are in state IDLE */
-  size_t num_idle;
-
-  /** There will be one ref for each entry in subchannels for which there is a
-   * pending connectivity state watcher callback. */
-  gpr_refcount refcount;
-
-  /** Is this list shutting down? This may be true due to the shutdown of the
-   * policy itself or because a newer update has arrived while this one hadn't
-   * finished processing. */
-  bool shutting_down;
+class MySubchannelData
+    : public SubchannelData<MySubchannelList, MySubchannelData> {
+ public:
+  void ProcessConnectivityChangeLocked(
+      grpc_connectivity_state connectivity_state, grpc_error* error) override {
+    // ...code to handle connectivity changes...
+  }
 };
 
-grpc_lb_subchannel_list* grpc_lb_subchannel_list_create(
-    grpc_core::LoadBalancingPolicy* p, grpc_core::TraceFlag* tracer,
+class MySubchannelList
+    : public SubchannelList<MySubchannelList, MySubchannelData> {
+};
+
+*/
+// All methods with a Locked() suffix must be called from within the
+// client_channel combiner.
+
+namespace grpc_core {
+
+// Stores data for a particular subchannel in a subchannel list.
+// Callers must create a subclass that implements the
+// ProcessConnectivityChangeLocked() method.
+template <typename SubchannelListType, typename SubchannelDataType>
+class SubchannelData {
+ public:
+  // Returns a pointer to the subchannel list containing this object.
+  SubchannelListType* subchannel_list() const { return subchannel_list_; }
+
+  // Returns the index into the subchannel list of this object.
+  size_t Index() const {
+    return static_cast<size_t>(static_cast<const SubchannelDataType*>(this) -
+                               subchannel_list_->subchannel(0));
+  }
+
+  // Returns a pointer to the subchannel.
+  grpc_subchannel* subchannel() const { return subchannel_; }
+
+  // Returns the connected subchannel.  Will be null if the subchannel
+  // is not connected.
+  ConnectedSubchannel* connected_subchannel() const {
+    return connected_subchannel_.get();
+  }
+
+  // Synchronously checks the subchannel's connectivity state.
+  // Must not be called while there is a connectivity notification
+  // pending (i.e., between calling StartConnectivityWatchLocked() or
+  // RenewConnectivityWatchLocked() and the resulting invocation of
+  // ProcessConnectivityChangeLocked()).
+  grpc_connectivity_state CheckConnectivityStateLocked(grpc_error** error) {
+    GPR_ASSERT(!connectivity_notification_pending_);
+    pending_connectivity_state_unsafe_ =
+        grpc_subchannel_check_connectivity(subchannel(), error);
+    UpdateConnectedSubchannelLocked();
+    return pending_connectivity_state_unsafe_;
+  }
+
+  // Unrefs the subchannel.  May be used if an individual subchannel is
+  // no longer needed even though the subchannel list as a whole is not
+  // being unreffed.
+  virtual void UnrefSubchannelLocked(const char* reason);
+
+  // Starts watching the connectivity state of the subchannel.
+  // ProcessConnectivityChangeLocked() will be called when the
+  // connectivity state changes.
+  void StartConnectivityWatchLocked();
+
+  // Renews watching the connectivity state of the subchannel.
+  void RenewConnectivityWatchLocked();
+
+  // Stops watching the connectivity state of the subchannel.
+  void StopConnectivityWatchLocked();
+
+  // Cancels watching the connectivity state of the subchannel.
+  // Must be called only while there is a connectivity notification
+  // pending (i.e., between calling StartConnectivityWatchLocked() or
+  // RenewConnectivityWatchLocked() and the resulting invocation of
+  // ProcessConnectivityChangeLocked()).
+  // From within ProcessConnectivityChangeLocked(), use
+  // StopConnectivityWatchLocked() instead.
+  void CancelConnectivityWatchLocked(const char* reason);
+
+  // Cancels any pending connectivity watch and unrefs the subchannel.
+  void ShutdownLocked();
+
+  GRPC_ABSTRACT_BASE_CLASS
+
+ protected:
+  SubchannelData(SubchannelListType* subchannel_list,
+                 const grpc_lb_user_data_vtable* user_data_vtable,
+                 const grpc_lb_address& address, grpc_subchannel* subchannel,
+                 grpc_combiner* combiner);
+
+  virtual ~SubchannelData();
+
+  // After StartConnectivityWatchLocked() or RenewConnectivityWatchLocked()
+  // is called, this method will be invoked when the subchannel's connectivity
+  // state changes.
+  // Implementations must invoke either RenewConnectivityWatchLocked() or
+  // StopConnectivityWatchLocked() before returning.
+  virtual void ProcessConnectivityChangeLocked(
+      grpc_connectivity_state connectivity_state,
+      grpc_error* error) GRPC_ABSTRACT;
+
+ private:
+  // Updates connected_subchannel_ based on pending_connectivity_state_unsafe_.
+  // Returns true if the connectivity state should be reported.
+  bool UpdateConnectedSubchannelLocked();
+
+  static void OnConnectivityChangedLocked(void* arg, grpc_error* error);
+
+  // Backpointer to owning subchannel list.  Not owned.
+  SubchannelListType* subchannel_list_;
+
+  // The subchannel and connected subchannel.
+  grpc_subchannel* subchannel_;
+  RefCountedPtr<ConnectedSubchannel> connected_subchannel_;
+
+  // Notification that connectivity has changed on subchannel.
+  grpc_closure connectivity_changed_closure_;
+  // Is a connectivity notification pending?
+  bool connectivity_notification_pending_ = false;
+  // Connectivity state to be updated by
+  // grpc_subchannel_notify_on_state_change(), not guarded by
+  // the combiner.
+  grpc_connectivity_state pending_connectivity_state_unsafe_;
+};
+
+// A list of subchannels.
+template <typename SubchannelListType, typename SubchannelDataType>
+class SubchannelList
+    : public InternallyRefCountedWithTracing<SubchannelListType> {
+ public:
+  typedef InlinedVector<SubchannelDataType, 10> SubchannelVector;
+
+  // The number of subchannels in the list.
+  size_t num_subchannels() const { return subchannels_.size(); }
+
+  // The data for the subchannel at a particular index.
+  SubchannelDataType* subchannel(size_t index) { return &subchannels_[index]; }
+
+  // Returns true if the subchannel list is shutting down.
+  bool shutting_down() const { return shutting_down_; }
+
+  // Accessors.
+  LoadBalancingPolicy* policy() const { return policy_; }
+  TraceFlag* tracer() const { return tracer_; }
+
+  // Note: Caller must ensure that this is invoked inside of the combiner.
+  void Orphan() override {
+    ShutdownLocked();
+    InternallyRefCountedWithTracing<SubchannelListType>::Unref(DEBUG_LOCATION,
+                                                               "shutdown");
+  }
+
+  GRPC_ABSTRACT_BASE_CLASS
+
+ protected:
+  SubchannelList(LoadBalancingPolicy* policy, TraceFlag* tracer,
+                 const grpc_lb_addresses* addresses, grpc_combiner* combiner,
+                 grpc_client_channel_factory* client_channel_factory,
+                 const grpc_channel_args& args);
+
+  virtual ~SubchannelList();
+
+ private:
+  // So New() can call our private ctor.
+  template <typename T, typename... Args>
+  friend T* New(Args&&... args);
+
+  // For accessing Ref() and Unref().
+  friend class SubchannelData<SubchannelListType, SubchannelDataType>;
+
+  void ShutdownLocked();
+
+  // Backpointer to owning policy.
+  LoadBalancingPolicy* policy_;
+
+  TraceFlag* tracer_;
+
+  grpc_combiner* combiner_;
+
+  // The list of subchannels.
+  SubchannelVector subchannels_;
+
+  // Is this list shutting down? This may be true due to the shutdown of the
+  // policy itself or because a newer update has arrived while this one hadn't
+  // finished processing.
+  bool shutting_down_ = false;
+};
+
+//
+// implementation -- no user-servicable parts below
+//
+
+//
+// SubchannelData
+//
+
+template <typename SubchannelListType, typename SubchannelDataType>
+SubchannelData<SubchannelListType, SubchannelDataType>::SubchannelData(
+    SubchannelListType* subchannel_list,
+    const grpc_lb_user_data_vtable* user_data_vtable,
+    const grpc_lb_address& address, grpc_subchannel* subchannel,
+    grpc_combiner* combiner)
+    : subchannel_list_(subchannel_list),
+      subchannel_(subchannel),
+      // We assume that the current state is IDLE.  If not, we'll get a
+      // callback telling us that.
+      pending_connectivity_state_unsafe_(GRPC_CHANNEL_IDLE) {
+  GRPC_CLOSURE_INIT(
+      &connectivity_changed_closure_,
+      (&SubchannelData<SubchannelListType,
+                       SubchannelDataType>::OnConnectivityChangedLocked),
+      this, grpc_combiner_scheduler(combiner));
+}
+
+template <typename SubchannelListType, typename SubchannelDataType>
+SubchannelData<SubchannelListType, SubchannelDataType>::~SubchannelData() {
+  UnrefSubchannelLocked("subchannel_data_destroy");
+}
+
+template <typename SubchannelListType, typename SubchannelDataType>
+void SubchannelData<SubchannelListType, SubchannelDataType>::
+    UnrefSubchannelLocked(const char* reason) {
+  if (subchannel_ != nullptr) {
+    if (subchannel_list_->tracer()->enabled()) {
+      gpr_log(GPR_INFO,
+              "[%s %p] subchannel list %p index %" PRIuPTR " of %" PRIuPTR
+              " (subchannel %p): unreffing subchannel",
+              subchannel_list_->tracer()->name(), subchannel_list_->policy(),
+              subchannel_list_, Index(), subchannel_list_->num_subchannels(),
+              subchannel_);
+    }
+    GRPC_SUBCHANNEL_UNREF(subchannel_, reason);
+    subchannel_ = nullptr;
+    connected_subchannel_.reset();
+  }
+}
+
+template <typename SubchannelListType, typename SubchannelDataType>
+void SubchannelData<SubchannelListType,
+                    SubchannelDataType>::StartConnectivityWatchLocked() {
+  if (subchannel_list_->tracer()->enabled()) {
+    gpr_log(GPR_INFO,
+            "[%s %p] subchannel list %p index %" PRIuPTR " of %" PRIuPTR
+            " (subchannel %p): starting watch: requesting connectivity change "
+            "notification (from %s)",
+            subchannel_list_->tracer()->name(), subchannel_list_->policy(),
+            subchannel_list_, Index(), subchannel_list_->num_subchannels(),
+            subchannel_,
+            grpc_connectivity_state_name(pending_connectivity_state_unsafe_));
+  }
+  GPR_ASSERT(!connectivity_notification_pending_);
+  connectivity_notification_pending_ = true;
+  subchannel_list()->Ref(DEBUG_LOCATION, "connectivity_watch").release();
+  grpc_subchannel_notify_on_state_change(
+      subchannel_, subchannel_list_->policy()->interested_parties(),
+      &pending_connectivity_state_unsafe_, &connectivity_changed_closure_);
+}
+
+template <typename SubchannelListType, typename SubchannelDataType>
+void SubchannelData<SubchannelListType,
+                    SubchannelDataType>::RenewConnectivityWatchLocked() {
+  if (subchannel_list_->tracer()->enabled()) {
+    gpr_log(GPR_INFO,
+            "[%s %p] subchannel list %p index %" PRIuPTR " of %" PRIuPTR
+            " (subchannel %p): renewing watch: requesting connectivity change "
+            "notification (from %s)",
+            subchannel_list_->tracer()->name(), subchannel_list_->policy(),
+            subchannel_list_, Index(), subchannel_list_->num_subchannels(),
+            subchannel_,
+            grpc_connectivity_state_name(pending_connectivity_state_unsafe_));
+  }
+  GPR_ASSERT(connectivity_notification_pending_);
+  grpc_subchannel_notify_on_state_change(
+      subchannel_, subchannel_list_->policy()->interested_parties(),
+      &pending_connectivity_state_unsafe_, &connectivity_changed_closure_);
+}
+
+template <typename SubchannelListType, typename SubchannelDataType>
+void SubchannelData<SubchannelListType,
+                    SubchannelDataType>::StopConnectivityWatchLocked() {
+  if (subchannel_list_->tracer()->enabled()) {
+    gpr_log(GPR_INFO,
+            "[%s %p] subchannel list %p index %" PRIuPTR " of %" PRIuPTR
+            " (subchannel %p): stopping connectivity watch",
+            subchannel_list_->tracer()->name(), subchannel_list_->policy(),
+            subchannel_list_, Index(), subchannel_list_->num_subchannels(),
+            subchannel_);
+  }
+  GPR_ASSERT(connectivity_notification_pending_);
+  connectivity_notification_pending_ = false;
+  subchannel_list()->Unref(DEBUG_LOCATION, "connectivity_watch");
+}
+
+template <typename SubchannelListType, typename SubchannelDataType>
+void SubchannelData<SubchannelListType, SubchannelDataType>::
+    CancelConnectivityWatchLocked(const char* reason) {
+  if (subchannel_list_->tracer()->enabled()) {
+    gpr_log(GPR_INFO,
+            "[%s %p] subchannel list %p index %" PRIuPTR " of %" PRIuPTR
+            " (subchannel %p): canceling connectivity watch (%s)",
+            subchannel_list_->tracer()->name(), subchannel_list_->policy(),
+            subchannel_list_, Index(), subchannel_list_->num_subchannels(),
+            subchannel_, reason);
+  }
+  GPR_ASSERT(connectivity_notification_pending_);
+  grpc_subchannel_notify_on_state_change(subchannel_, nullptr, nullptr,
+                                         &connectivity_changed_closure_);
+}
+
+template <typename SubchannelListType, typename SubchannelDataType>
+bool SubchannelData<SubchannelListType,
+                    SubchannelDataType>::UpdateConnectedSubchannelLocked() {
+  // If the subchannel is READY, take a ref to the connected subchannel.
+  if (pending_connectivity_state_unsafe_ == GRPC_CHANNEL_READY) {
+    connected_subchannel_ =
+        grpc_subchannel_get_connected_subchannel(subchannel_);
+    // If the subchannel became disconnected between the time that READY
+    // was reported and the time we got here (e.g., between when a
+    // notification callback is scheduled and when it was actually run in
+    // the combiner), then the connected subchannel may have disappeared out
+    // from under us.  In that case, we don't actually want to consider the
+    // subchannel to be in state READY.  Instead, we use IDLE as the
+    // basis for any future connectivity watch; this is the one state that
+    // the subchannel will never transition back into, so this ensures
+    // that we will get a notification for the next state, even if that state
+    // is READY again (e.g., if the subchannel has transitioned back to
+    // READY before the next watch gets requested).
+    if (connected_subchannel_ == nullptr) {
+      if (subchannel_list_->tracer()->enabled()) {
+        gpr_log(GPR_INFO,
+                "[%s %p] subchannel list %p index %" PRIuPTR " of %" PRIuPTR
+                " (subchannel %p): state is READY but connected subchannel is "
+                "null; moving to state IDLE",
+                subchannel_list_->tracer()->name(), subchannel_list_->policy(),
+                subchannel_list_, Index(), subchannel_list_->num_subchannels(),
+                subchannel_);
+      }
+      pending_connectivity_state_unsafe_ = GRPC_CHANNEL_IDLE;
+      return false;
+    }
+  } else {
+    // For any state other than READY, unref the connected subchannel.
+    connected_subchannel_.reset();
+  }
+  return true;
+}
+
+template <typename SubchannelListType, typename SubchannelDataType>
+void SubchannelData<SubchannelListType, SubchannelDataType>::
+    OnConnectivityChangedLocked(void* arg, grpc_error* error) {
+  SubchannelData* sd = static_cast<SubchannelData*>(arg);
+  if (sd->subchannel_list_->tracer()->enabled()) {
+    gpr_log(
+        GPR_INFO,
+        "[%s %p] subchannel list %p index %" PRIuPTR " of %" PRIuPTR
+        " (subchannel %p): connectivity changed: state=%s, error=%s, "
+        "shutting_down=%d",
+        sd->subchannel_list_->tracer()->name(), sd->subchannel_list_->policy(),
+        sd->subchannel_list_, sd->Index(),
+        sd->subchannel_list_->num_subchannels(), sd->subchannel_,
+        grpc_connectivity_state_name(sd->pending_connectivity_state_unsafe_),
+        grpc_error_string(error), sd->subchannel_list_->shutting_down());
+  }
+  // If shutting down, unref subchannel and stop watching.
+  if (sd->subchannel_list_->shutting_down() || error == GRPC_ERROR_CANCELLED) {
+    sd->UnrefSubchannelLocked("connectivity_shutdown");
+    sd->StopConnectivityWatchLocked();
+    return;
+  }
+  // Get or release ref to connected subchannel.
+  if (!sd->UpdateConnectedSubchannelLocked()) {
+    // We don't want to report this connectivity state, so renew the watch.
+    sd->RenewConnectivityWatchLocked();
+    return;
+  }
+  // Call the subclass's ProcessConnectivityChangeLocked() method.
+  sd->ProcessConnectivityChangeLocked(sd->pending_connectivity_state_unsafe_,
+                                      GRPC_ERROR_REF(error));
+}
+
+template <typename SubchannelListType, typename SubchannelDataType>
+void SubchannelData<SubchannelListType, SubchannelDataType>::ShutdownLocked() {
+  // If there's a pending notification for this subchannel, cancel it;
+  // the callback is responsible for unreffing the subchannel.
+  // Otherwise, unref the subchannel directly.
+  if (connectivity_notification_pending_) {
+    CancelConnectivityWatchLocked("shutdown");
+  } else if (subchannel_ != nullptr) {
+    UnrefSubchannelLocked("shutdown");
+  }
+}
+
+//
+// SubchannelList
+//
+
+template <typename SubchannelListType, typename SubchannelDataType>
+SubchannelList<SubchannelListType, SubchannelDataType>::SubchannelList(
+    LoadBalancingPolicy* policy, TraceFlag* tracer,
     const grpc_lb_addresses* addresses, grpc_combiner* combiner,
     grpc_client_channel_factory* client_channel_factory,
-    const grpc_channel_args& args, grpc_iomgr_cb_func connectivity_changed_cb);
+    const grpc_channel_args& args)
+    : InternallyRefCountedWithTracing<SubchannelListType>(tracer),
+      policy_(policy),
+      tracer_(tracer),
+      combiner_(GRPC_COMBINER_REF(combiner, "subchannel_list")) {
+  if (tracer_->enabled()) {
+    gpr_log(GPR_INFO,
+            "[%s %p] Creating subchannel list %p for %" PRIuPTR " subchannels",
+            tracer_->name(), policy, this, addresses->num_addresses);
+  }
+  subchannels_.reserve(addresses->num_addresses);
+  // We need to remove the LB addresses in order to be able to compare the
+  // subchannel keys of subchannels from a different batch of addresses.
+  static const char* keys_to_remove[] = {GRPC_ARG_SUBCHANNEL_ADDRESS,
+                                         GRPC_ARG_LB_ADDRESSES};
+  // Create a subchannel for each address.
+  grpc_subchannel_args sc_args;
+  for (size_t i = 0; i < addresses->num_addresses; i++) {
+    // If there were any balancer, we would have chosen grpclb policy instead.
+    GPR_ASSERT(!addresses->addresses[i].is_balancer);
+    memset(&sc_args, 0, sizeof(grpc_subchannel_args));
+    grpc_arg addr_arg =
+        grpc_create_subchannel_address_arg(&addresses->addresses[i].address);
+    grpc_channel_args* new_args = grpc_channel_args_copy_and_add_and_remove(
+        &args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), &addr_arg, 1);
+    gpr_free(addr_arg.value.string);
+    sc_args.args = new_args;
+    grpc_subchannel* subchannel = grpc_client_channel_factory_create_subchannel(
+        client_channel_factory, &sc_args);
+    grpc_channel_args_destroy(new_args);
+    if (subchannel == nullptr) {
+      // Subchannel could not be created.
+      if (tracer_->enabled()) {
+        char* address_uri =
+            grpc_sockaddr_to_uri(&addresses->addresses[i].address);
+        gpr_log(GPR_INFO,
+                "[%s %p] could not create subchannel for address uri %s, "
+                "ignoring",
+                tracer_->name(), policy_, address_uri);
+        gpr_free(address_uri);
+      }
+      continue;
+    }
+    if (tracer_->enabled()) {
+      char* address_uri =
+          grpc_sockaddr_to_uri(&addresses->addresses[i].address);
+      gpr_log(GPR_INFO,
+              "[%s %p] subchannel list %p index %" PRIuPTR
+              ": Created subchannel %p for address uri %s",
+              tracer_->name(), policy_, this, subchannels_.size(), subchannel,
+              address_uri);
+      gpr_free(address_uri);
+    }
+    subchannels_.emplace_back(static_cast<SubchannelListType*>(this),
+                              addresses->user_data_vtable,
+                              addresses->addresses[i], subchannel, combiner);
+  }
+}
 
-void grpc_lb_subchannel_list_ref(grpc_lb_subchannel_list* subchannel_list,
-                                 const char* reason);
+template <typename SubchannelListType, typename SubchannelDataType>
+SubchannelList<SubchannelListType, SubchannelDataType>::~SubchannelList() {
+  if (tracer_->enabled()) {
+    gpr_log(GPR_INFO, "[%s %p] Destroying subchannel_list %p", tracer_->name(),
+            policy_, this);
+  }
+  GRPC_COMBINER_UNREF(combiner_, "subchannel_list");
+}
 
-void grpc_lb_subchannel_list_unref(grpc_lb_subchannel_list* subchannel_list,
-                                   const char* reason);
+template <typename SubchannelListType, typename SubchannelDataType>
+void SubchannelList<SubchannelListType, SubchannelDataType>::ShutdownLocked() {
+  if (tracer_->enabled()) {
+    gpr_log(GPR_INFO, "[%s %p] Shutting down subchannel_list %p",
+            tracer_->name(), policy_, this);
+  }
+  GPR_ASSERT(!shutting_down_);
+  shutting_down_ = true;
+  for (size_t i = 0; i < subchannels_.size(); i++) {
+    SubchannelDataType* sd = &subchannels_[i];
+    sd->ShutdownLocked();
+  }
+}
 
-/// Mark subchannel_list as discarded. Unsubscribes all its subchannels. The
-/// connectivity state notification callback will ultimately unref it.
-void grpc_lb_subchannel_list_shutdown_and_unref(
-    grpc_lb_subchannel_list* subchannel_list, const char* reason);
+}  // namespace grpc_core
 
 #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_LB_POLICY_SUBCHANNEL_LIST_H */
diff --git a/src/core/ext/filters/client_channel/method_params.h b/src/core/ext/filters/client_channel/method_params.h
index 099924e..a31d360 100644
--- a/src/core/ext/filters/client_channel/method_params.h
+++ b/src/core/ext/filters/client_channel/method_params.h
@@ -60,6 +60,10 @@
   template <typename T, typename... Args>
   friend T* grpc_core::New(Args&&... args);
 
+  // So Delete() can call our private dtor.
+  template <typename T>
+  friend void grpc_core::Delete(T*);
+
   ClientChannelMethodParams() {}
   virtual ~ClientChannelMethodParams() {}
 
diff --git a/src/core/ext/filters/client_channel/resolver.h b/src/core/ext/filters/client_channel/resolver.h
index cdb5a20..0238031 100644
--- a/src/core/ext/filters/client_channel/resolver.h
+++ b/src/core/ext/filters/client_channel/resolver.h
@@ -105,6 +105,10 @@
   GRPC_ABSTRACT_BASE_CLASS
 
  protected:
+  // So Delete() can access our protected dtor.
+  template <typename T>
+  friend void Delete(T*);
+
   /// Does NOT take ownership of the reference to \a combiner.
   // TODO(roth): Once we have a C++-like interface for combiners, this
   // API should change to take a RefCountedPtr<>, so that we always take
diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc
index aca7307..c3c62b6 100644
--- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc
+++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc
@@ -135,6 +135,7 @@
   if (path[0] == '/') ++path;
   name_to_resolve_ = gpr_strdup(path);
   // Get DNS server from URI authority.
+  dns_server_ = nullptr;
   if (0 != strcmp(args.uri->authority, "")) {
     dns_server_ = gpr_strdup(args.uri->authority);
   }
@@ -362,6 +363,15 @@
 }
 
 void AresDnsResolver::MaybeStartResolvingLocked() {
+  // If there is an existing timer, the time it fires is the earliest time we
+  // can start the next resolution.
+  if (have_next_resolution_timer_) {
+    // TODO(dgq): remove the following two lines once Pick First stops
+    // discarding subchannels after selecting.
+    ++resolved_version_;
+    MaybeFinishNextLocked();
+    return;
+  }
   if (last_resolution_timestamp_ >= 0) {
     const grpc_millis earliest_next_resolution =
         last_resolution_timestamp_ + min_time_between_resolutions_;
@@ -374,17 +384,15 @@
               "In cooldown from last resolution (from %" PRIdPTR
               " ms ago). Will resolve again in %" PRIdPTR " ms",
               last_resolution_ago, ms_until_next_resolution);
-      if (!have_next_resolution_timer_) {
-        have_next_resolution_timer_ = true;
-        // TODO(roth): We currently deal with this ref manually.  Once the
-        // new closure API is done, find a way to track this ref with the timer
-        // callback as part of the type system.
-        RefCountedPtr<Resolver> self =
-            Ref(DEBUG_LOCATION, "next_resolution_timer_cooldown");
-        self.release();
-        grpc_timer_init(&next_resolution_timer_, ms_until_next_resolution,
-                        &on_next_resolution_);
-      }
+      have_next_resolution_timer_ = true;
+      // TODO(roth): We currently deal with this ref manually.  Once the
+      // new closure API is done, find a way to track this ref with the timer
+      // callback as part of the type system.
+      RefCountedPtr<Resolver> self =
+          Ref(DEBUG_LOCATION, "next_resolution_timer_cooldown");
+      self.release();
+      grpc_timer_init(&next_resolution_timer_, ms_until_next_resolution,
+                      &on_next_resolution_);
       // TODO(dgq): remove the following two lines once Pick First stops
       // discarding subchannels after selecting.
       ++resolved_version_;
@@ -396,6 +404,7 @@
 }
 
 void AresDnsResolver::StartResolvingLocked() {
+  gpr_log(GPR_DEBUG, "Start resolving.");
   // TODO(roth): We currently deal with this ref manually.  Once the
   // new closure API is done, find a way to track this ref with the timer
   // callback as part of the type system.
diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc
index fb24357..e86ab5a 100644
--- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc
+++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.cc
@@ -153,7 +153,10 @@
   /* If there are no pending queries, invoke on_done callback and destroy the
      request */
   if (gpr_unref(&r->pending_queries)) {
-    grpc_cares_wrapper_address_sorting_sort(*(r->lb_addrs_out));
+    grpc_lb_addresses* lb_addrs = *(r->lb_addrs_out);
+    if (lb_addrs != nullptr) {
+      grpc_cares_wrapper_address_sorting_sort(lb_addrs);
+    }
     GRPC_CLOSURE_SCHED(r->on_done, r->error);
     gpr_mu_destroy(&r->mu);
     grpc_ares_ev_driver_destroy(r->ev_driver);
diff --git a/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc b/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc
index fbab136..e7842a7 100644
--- a/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc
+++ b/src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.cc
@@ -236,6 +236,15 @@
 }
 
 void NativeDnsResolver::MaybeStartResolvingLocked() {
+  // If there is an existing timer, the time it fires is the earliest time we
+  // can start the next resolution.
+  if (have_next_resolution_timer_) {
+    // TODO(dgq): remove the following two lines once Pick First stops
+    // discarding subchannels after selecting.
+    ++resolved_version_;
+    MaybeFinishNextLocked();
+    return;
+  }
   if (last_resolution_timestamp_ >= 0) {
     const grpc_millis earliest_next_resolution =
         last_resolution_timestamp_ + min_time_between_resolutions_;
@@ -248,17 +257,15 @@
               "In cooldown from last resolution (from %" PRIdPTR
               " ms ago). Will resolve again in %" PRIdPTR " ms",
               last_resolution_ago, ms_until_next_resolution);
-      if (!have_next_resolution_timer_) {
-        have_next_resolution_timer_ = true;
-        // TODO(roth): We currently deal with this ref manually.  Once the
-        // new closure API is done, find a way to track this ref with the timer
-        // callback as part of the type system.
-        RefCountedPtr<Resolver> self =
-            Ref(DEBUG_LOCATION, "next_resolution_timer_cooldown");
-        self.release();
-        grpc_timer_init(&next_resolution_timer_, ms_until_next_resolution,
-                        &on_next_resolution_);
-      }
+      have_next_resolution_timer_ = true;
+      // TODO(roth): We currently deal with this ref manually.  Once the
+      // new closure API is done, find a way to track this ref with the timer
+      // callback as part of the type system.
+      RefCountedPtr<Resolver> self =
+          Ref(DEBUG_LOCATION, "next_resolution_timer_cooldown");
+      self.release();
+      grpc_timer_init(&next_resolution_timer_, ms_until_next_resolution,
+                      &on_next_resolution_);
       // TODO(dgq): remove the following two lines once Pick First stops
       // discarding subchannels after selecting.
       ++resolved_version_;
@@ -270,6 +277,7 @@
 }
 
 void NativeDnsResolver::StartResolvingLocked() {
+  gpr_log(GPR_DEBUG, "Start resolving.");
   // TODO(roth): We currently deal with this ref manually.  Once the
   // new closure API is done, find a way to track this ref with the timer
   // callback as part of the type system.
diff --git a/src/core/ext/filters/client_channel/retry_throttle.cc b/src/core/ext/filters/client_channel/retry_throttle.cc
index 45de666..bdeb7e4 100644
--- a/src/core/ext/filters/client_channel/retry_throttle.cc
+++ b/src/core/ext/filters/client_channel/retry_throttle.cc
@@ -30,184 +30,162 @@
 
 #include "src/core/lib/avl/avl.h"
 
+namespace grpc_core {
+namespace internal {
+
 //
-// server_retry_throttle_data
+// ServerRetryThrottleData
 //
 
-struct grpc_server_retry_throttle_data {
-  gpr_refcount refs;
-  int max_milli_tokens;
-  int milli_token_ratio;
-  gpr_atm milli_tokens;
-  // A pointer to the replacement for this grpc_server_retry_throttle_data
-  // entry.  If non-nullptr, then this entry is stale and must not be used.
-  // We hold a reference to the replacement.
-  gpr_atm replacement;
-};
-
-static void get_replacement_throttle_data_if_needed(
-    grpc_server_retry_throttle_data** throttle_data) {
-  while (true) {
-    grpc_server_retry_throttle_data* new_throttle_data =
-        (grpc_server_retry_throttle_data*)gpr_atm_acq_load(
-            &(*throttle_data)->replacement);
-    if (new_throttle_data == nullptr) return;
-    *throttle_data = new_throttle_data;
-  }
-}
-
-bool grpc_server_retry_throttle_data_record_failure(
-    grpc_server_retry_throttle_data* throttle_data) {
-  if (throttle_data == nullptr) return true;
-  // First, check if we are stale and need to be replaced.
-  get_replacement_throttle_data_if_needed(&throttle_data);
-  // We decrement milli_tokens by 1000 (1 token) for each failure.
-  const int new_value = static_cast<int>(gpr_atm_no_barrier_clamped_add(
-      &throttle_data->milli_tokens, static_cast<gpr_atm>(-1000),
-      static_cast<gpr_atm>(0),
-      static_cast<gpr_atm>(throttle_data->max_milli_tokens)));
-  // Retries are allowed as long as the new value is above the threshold
-  // (max_milli_tokens / 2).
-  return new_value > throttle_data->max_milli_tokens / 2;
-}
-
-void grpc_server_retry_throttle_data_record_success(
-    grpc_server_retry_throttle_data* throttle_data) {
-  if (throttle_data == nullptr) return;
-  // First, check if we are stale and need to be replaced.
-  get_replacement_throttle_data_if_needed(&throttle_data);
-  // We increment milli_tokens by milli_token_ratio for each success.
-  gpr_atm_no_barrier_clamped_add(
-      &throttle_data->milli_tokens,
-      static_cast<gpr_atm>(throttle_data->milli_token_ratio),
-      static_cast<gpr_atm>(0),
-      static_cast<gpr_atm>(throttle_data->max_milli_tokens));
-}
-
-grpc_server_retry_throttle_data* grpc_server_retry_throttle_data_ref(
-    grpc_server_retry_throttle_data* throttle_data) {
-  gpr_ref(&throttle_data->refs);
-  return throttle_data;
-}
-
-void grpc_server_retry_throttle_data_unref(
-    grpc_server_retry_throttle_data* throttle_data) {
-  if (gpr_unref(&throttle_data->refs)) {
-    grpc_server_retry_throttle_data* replacement =
-        (grpc_server_retry_throttle_data*)gpr_atm_acq_load(
-            &throttle_data->replacement);
-    if (replacement != nullptr) {
-      grpc_server_retry_throttle_data_unref(replacement);
-    }
-    gpr_free(throttle_data);
-  }
-}
-
-static grpc_server_retry_throttle_data* grpc_server_retry_throttle_data_create(
-    int max_milli_tokens, int milli_token_ratio,
-    grpc_server_retry_throttle_data* old_throttle_data) {
-  grpc_server_retry_throttle_data* throttle_data =
-      static_cast<grpc_server_retry_throttle_data*>(
-          gpr_malloc(sizeof(*throttle_data)));
-  memset(throttle_data, 0, sizeof(*throttle_data));
-  gpr_ref_init(&throttle_data->refs, 1);
-  throttle_data->max_milli_tokens = max_milli_tokens;
-  throttle_data->milli_token_ratio = milli_token_ratio;
-  int initial_milli_tokens = max_milli_tokens;
+ServerRetryThrottleData::ServerRetryThrottleData(
+    intptr_t max_milli_tokens, intptr_t milli_token_ratio,
+    ServerRetryThrottleData* old_throttle_data)
+    : max_milli_tokens_(max_milli_tokens),
+      milli_token_ratio_(milli_token_ratio) {
+  intptr_t initial_milli_tokens = max_milli_tokens;
   // If there was a pre-existing entry for this server name, initialize
   // the token count by scaling proportionately to the old data.  This
   // ensures that if we're already throttling retries on the old scale,
   // we will start out doing the same thing on the new one.
   if (old_throttle_data != nullptr) {
     double token_fraction =
-        static_cast<int>(gpr_atm_acq_load(&old_throttle_data->milli_tokens)) /
-        static_cast<double>(old_throttle_data->max_milli_tokens);
-    initial_milli_tokens = static_cast<int>(token_fraction * max_milli_tokens);
+        static_cast<intptr_t>(
+            gpr_atm_acq_load(&old_throttle_data->milli_tokens_)) /
+        static_cast<double>(old_throttle_data->max_milli_tokens_);
+    initial_milli_tokens =
+        static_cast<intptr_t>(token_fraction * max_milli_tokens);
   }
-  gpr_atm_rel_store(&throttle_data->milli_tokens,
-                    (gpr_atm)initial_milli_tokens);
+  gpr_atm_rel_store(&milli_tokens_, static_cast<gpr_atm>(initial_milli_tokens));
   // If there was a pre-existing entry, mark it as stale and give it a
   // pointer to the new entry, which is its replacement.
   if (old_throttle_data != nullptr) {
-    grpc_server_retry_throttle_data_ref(throttle_data);
-    gpr_atm_rel_store(&old_throttle_data->replacement, (gpr_atm)throttle_data);
+    Ref().release();  // Ref held by pre-existing entry.
+    gpr_atm_rel_store(&old_throttle_data->replacement_,
+                      reinterpret_cast<gpr_atm>(this));
   }
-  return throttle_data;
+}
+
+ServerRetryThrottleData::~ServerRetryThrottleData() {
+  ServerRetryThrottleData* replacement =
+      reinterpret_cast<ServerRetryThrottleData*>(
+          gpr_atm_acq_load(&replacement_));
+  if (replacement != nullptr) {
+    replacement->Unref();
+  }
+}
+
+void ServerRetryThrottleData::GetReplacementThrottleDataIfNeeded(
+    ServerRetryThrottleData** throttle_data) {
+  while (true) {
+    ServerRetryThrottleData* new_throttle_data =
+        reinterpret_cast<ServerRetryThrottleData*>(
+            gpr_atm_acq_load(&(*throttle_data)->replacement_));
+    if (new_throttle_data == nullptr) return;
+    *throttle_data = new_throttle_data;
+  }
+}
+
+bool ServerRetryThrottleData::RecordFailure() {
+  // First, check if we are stale and need to be replaced.
+  ServerRetryThrottleData* throttle_data = this;
+  GetReplacementThrottleDataIfNeeded(&throttle_data);
+  // We decrement milli_tokens by 1000 (1 token) for each failure.
+  const intptr_t new_value =
+      static_cast<intptr_t>(gpr_atm_no_barrier_clamped_add(
+          &throttle_data->milli_tokens_, static_cast<gpr_atm>(-1000),
+          static_cast<gpr_atm>(0),
+          static_cast<gpr_atm>(throttle_data->max_milli_tokens_)));
+  // Retries are allowed as long as the new value is above the threshold
+  // (max_milli_tokens / 2).
+  return new_value > throttle_data->max_milli_tokens_ / 2;
+}
+
+void ServerRetryThrottleData::RecordSuccess() {
+  // First, check if we are stale and need to be replaced.
+  ServerRetryThrottleData* throttle_data = this;
+  GetReplacementThrottleDataIfNeeded(&throttle_data);
+  // We increment milli_tokens by milli_token_ratio for each success.
+  gpr_atm_no_barrier_clamped_add(
+      &throttle_data->milli_tokens_,
+      static_cast<gpr_atm>(throttle_data->milli_token_ratio_),
+      static_cast<gpr_atm>(0),
+      static_cast<gpr_atm>(throttle_data->max_milli_tokens_));
 }
 
 //
 // avl vtable for string -> server_retry_throttle_data map
 //
 
-static void* copy_server_name(void* key, void* unused) {
+namespace {
+
+void* copy_server_name(void* key, void* unused) {
   return gpr_strdup(static_cast<const char*>(key));
 }
 
-static long compare_server_name(void* key1, void* key2, void* unused) {
+long compare_server_name(void* key1, void* key2, void* unused) {
   return strcmp(static_cast<const char*>(key1), static_cast<const char*>(key2));
 }
 
-static void destroy_server_retry_throttle_data(void* value, void* unused) {
-  grpc_server_retry_throttle_data* throttle_data =
-      static_cast<grpc_server_retry_throttle_data*>(value);
-  grpc_server_retry_throttle_data_unref(throttle_data);
+void destroy_server_retry_throttle_data(void* value, void* unused) {
+  ServerRetryThrottleData* throttle_data =
+      static_cast<ServerRetryThrottleData*>(value);
+  throttle_data->Unref();
 }
 
-static void* copy_server_retry_throttle_data(void* value, void* unused) {
-  grpc_server_retry_throttle_data* throttle_data =
-      static_cast<grpc_server_retry_throttle_data*>(value);
-  return grpc_server_retry_throttle_data_ref(throttle_data);
+void* copy_server_retry_throttle_data(void* value, void* unused) {
+  ServerRetryThrottleData* throttle_data =
+      static_cast<ServerRetryThrottleData*>(value);
+  return throttle_data->Ref().release();
 }
 
-static void destroy_server_name(void* key, void* unused) { gpr_free(key); }
+void destroy_server_name(void* key, void* unused) { gpr_free(key); }
 
-static const grpc_avl_vtable avl_vtable = {
+const grpc_avl_vtable avl_vtable = {
     destroy_server_name, copy_server_name, compare_server_name,
     destroy_server_retry_throttle_data, copy_server_retry_throttle_data};
 
+}  // namespace
+
 //
-// server_retry_throttle_map
+// ServerRetryThrottleMap
 //
 
 static gpr_mu g_mu;
 static grpc_avl g_avl;
 
-void grpc_retry_throttle_map_init() {
+void ServerRetryThrottleMap::Init() {
   gpr_mu_init(&g_mu);
   g_avl = grpc_avl_create(&avl_vtable);
 }
 
-void grpc_retry_throttle_map_shutdown() {
+void ServerRetryThrottleMap::Shutdown() {
   gpr_mu_destroy(&g_mu);
   grpc_avl_unref(g_avl, nullptr);
 }
 
-grpc_server_retry_throttle_data* grpc_retry_throttle_map_get_data_for_server(
-    const char* server_name, int max_milli_tokens, int milli_token_ratio) {
+RefCountedPtr<ServerRetryThrottleData> ServerRetryThrottleMap::GetDataForServer(
+    const char* server_name, intptr_t max_milli_tokens,
+    intptr_t milli_token_ratio) {
+  RefCountedPtr<ServerRetryThrottleData> result;
   gpr_mu_lock(&g_mu);
-  grpc_server_retry_throttle_data* throttle_data =
-      static_cast<grpc_server_retry_throttle_data*>(
+  ServerRetryThrottleData* throttle_data =
+      static_cast<ServerRetryThrottleData*>(
           grpc_avl_get(g_avl, const_cast<char*>(server_name), nullptr));
-  if (throttle_data == nullptr) {
-    // Entry not found.  Create a new one.
-    throttle_data = grpc_server_retry_throttle_data_create(
-        max_milli_tokens, milli_token_ratio, nullptr);
-    g_avl = grpc_avl_add(g_avl, const_cast<char*>(server_name), throttle_data,
-                         nullptr);
+  if (throttle_data == nullptr ||
+      throttle_data->max_milli_tokens() != max_milli_tokens ||
+      throttle_data->milli_token_ratio() != milli_token_ratio) {
+    // Entry not found, or found with old parameters.  Create a new one.
+    result = MakeRefCounted<ServerRetryThrottleData>(
+        max_milli_tokens, milli_token_ratio, throttle_data);
+    g_avl = grpc_avl_add(g_avl, gpr_strdup(server_name),
+                         result->Ref().release(), nullptr);
   } else {
-    if (throttle_data->max_milli_tokens != max_milli_tokens ||
-        throttle_data->milli_token_ratio != milli_token_ratio) {
-      // Entry found but with old parameters.  Create a new one based on
-      // the original one.
-      throttle_data = grpc_server_retry_throttle_data_create(
-          max_milli_tokens, milli_token_ratio, throttle_data);
-      g_avl = grpc_avl_add(g_avl, const_cast<char*>(server_name), throttle_data,
-                           nullptr);
-    } else {
-      // Entry found.  Increase refcount.
-      grpc_server_retry_throttle_data_ref(throttle_data);
-    }
+    // Entry found.  Return a new ref to it.
+    result = throttle_data->Ref();
   }
   gpr_mu_unlock(&g_mu);
-  return throttle_data;
+  return result;
 }
+
+}  // namespace internal
+}  // namespace grpc_core
diff --git a/src/core/ext/filters/client_channel/retry_throttle.h b/src/core/ext/filters/client_channel/retry_throttle.h
index 0505fc2..fddafcd 100644
--- a/src/core/ext/filters/client_channel/retry_throttle.h
+++ b/src/core/ext/filters/client_channel/retry_throttle.h
@@ -21,32 +21,61 @@
 
 #include <grpc/support/port_platform.h>
 
-#include <stdbool.h>
+#include "src/core/lib/gprpp/ref_counted.h"
+
+namespace grpc_core {
+namespace internal {
 
 /// Tracks retry throttling data for an individual server name.
-typedef struct grpc_server_retry_throttle_data grpc_server_retry_throttle_data;
+class ServerRetryThrottleData : public RefCounted<ServerRetryThrottleData> {
+ public:
+  ServerRetryThrottleData(intptr_t max_milli_tokens, intptr_t milli_token_ratio,
+                          ServerRetryThrottleData* old_throttle_data);
 
-/// Records a failure.  Returns true if it's okay to send a retry.
-bool grpc_server_retry_throttle_data_record_failure(
-    grpc_server_retry_throttle_data* throttle_data);
-/// Records a success.
-void grpc_server_retry_throttle_data_record_success(
-    grpc_server_retry_throttle_data* throttle_data);
+  /// Records a failure.  Returns true if it's okay to send a retry.
+  bool RecordFailure();
 
-grpc_server_retry_throttle_data* grpc_server_retry_throttle_data_ref(
-    grpc_server_retry_throttle_data* throttle_data);
-void grpc_server_retry_throttle_data_unref(
-    grpc_server_retry_throttle_data* throttle_data);
+  /// Records a success.
+  void RecordSuccess();
 
-/// Initializes global map of failure data for each server name.
-void grpc_retry_throttle_map_init();
-/// Shuts down global map of failure data for each server name.
-void grpc_retry_throttle_map_shutdown();
+  intptr_t max_milli_tokens() const { return max_milli_tokens_; }
+  intptr_t milli_token_ratio() const { return milli_token_ratio_; }
 
-/// Returns a reference to the failure data for \a server_name, creating
-/// a new entry if needed.
-/// Caller must eventually unref via \a grpc_server_retry_throttle_data_unref().
-grpc_server_retry_throttle_data* grpc_retry_throttle_map_get_data_for_server(
-    const char* server_name, int max_milli_tokens, int milli_token_ratio);
+ private:
+  // So Delete() can call our private dtor.
+  template <typename T>
+  friend void grpc_core::Delete(T*);
+
+  ~ServerRetryThrottleData();
+
+  void GetReplacementThrottleDataIfNeeded(
+      ServerRetryThrottleData** throttle_data);
+
+  const intptr_t max_milli_tokens_;
+  const intptr_t milli_token_ratio_;
+  gpr_atm milli_tokens_;
+  // A pointer to the replacement for this ServerRetryThrottleData entry.
+  // If non-nullptr, then this entry is stale and must not be used.
+  // We hold a reference to the replacement.
+  gpr_atm replacement_ = 0;
+};
+
+/// Global map of server name to retry throttle data.
+class ServerRetryThrottleMap {
+ public:
+  /// Initializes global map of failure data for each server name.
+  static void Init();
+  /// Shuts down global map of failure data for each server name.
+  static void Shutdown();
+
+  /// Returns the failure data for \a server_name, creating a new entry if
+  /// needed.
+  static RefCountedPtr<ServerRetryThrottleData> GetDataForServer(
+      const char* server_name, intptr_t max_milli_tokens,
+      intptr_t milli_token_ratio);
+};
+
+}  // namespace internal
+}  // namespace grpc_core
 
 #endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RETRY_THROTTLE_H */
diff --git a/src/core/ext/filters/http/client_authority_filter.cc b/src/core/ext/filters/http/client_authority_filter.cc
new file mode 100644
index 0000000..1f57ab5
--- /dev/null
+++ b/src/core/ext/filters/http/client_authority_filter.cc
@@ -0,0 +1,156 @@
+/*
+ *
+ * Copyright 2018 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.
+ *
+ */
+
+#include <grpc/support/port_platform.h>
+
+#include <assert.h>
+#include <limits.h>
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+
+#include "src/core/ext/filters/http/client_authority_filter.h"
+#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/gpr/string.h"
+#include "src/core/lib/slice/slice_internal.h"
+#include "src/core/lib/slice/slice_string_helpers.h"
+#include "src/core/lib/surface/call.h"
+#include "src/core/lib/surface/channel_init.h"
+#include "src/core/lib/surface/channel_stack_type.h"
+#include "src/core/lib/transport/static_metadata.h"
+
+namespace {
+
+struct call_data {
+  grpc_linked_mdelem authority_storage;
+  grpc_call_combiner* call_combiner;
+};
+
+struct channel_data {
+  grpc_slice default_authority;
+};
+
+void authority_start_transport_stream_op_batch(
+    grpc_call_element* elem, grpc_transport_stream_op_batch* batch) {
+  channel_data* chand = static_cast<channel_data*>(elem->channel_data);
+  call_data* calld = static_cast<call_data*>(elem->call_data);
+  // Handle send_initial_metadata.
+  auto* initial_metadata =
+      batch->payload->send_initial_metadata.send_initial_metadata;
+  // If the initial metadata doesn't already contain :authority, add it.
+  if (batch->send_initial_metadata &&
+      initial_metadata->idx.named.authority == nullptr) {
+    grpc_error* error = grpc_metadata_batch_add_head(
+        initial_metadata, &calld->authority_storage,
+        grpc_mdelem_from_slices(GRPC_MDSTR_AUTHORITY,
+                                grpc_slice_ref(chand->default_authority)));
+    if (error != GRPC_ERROR_NONE) {
+      grpc_transport_stream_op_batch_finish_with_failure(batch, error,
+                                                         calld->call_combiner);
+      return;
+    }
+  }
+  // Pass control down the stack.
+  grpc_call_next_op(elem, batch);
+}
+
+/* Constructor for call_data */
+grpc_error* init_call_elem(grpc_call_element* elem,
+                           const grpc_call_element_args* args) {
+  call_data* calld = static_cast<call_data*>(elem->call_data);
+  calld->call_combiner = args->call_combiner;
+  return GRPC_ERROR_NONE;
+}
+
+/* Destructor for call_data */
+void destroy_call_elem(grpc_call_element* elem,
+                       const grpc_call_final_info* final_info,
+                       grpc_closure* ignored) {}
+
+/* Constructor for channel_data */
+grpc_error* init_channel_elem(grpc_channel_element* elem,
+                              grpc_channel_element_args* args) {
+  channel_data* chand = static_cast<channel_data*>(elem->channel_data);
+  const grpc_arg* default_authority_arg =
+      grpc_channel_args_find(args->channel_args, GRPC_ARG_DEFAULT_AUTHORITY);
+  if (default_authority_arg == nullptr) {
+    return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+        "GRPC_ARG_DEFAULT_AUTHORITY channel arg. not found. Note that direct "
+        "channels must explicity specify a value for this argument.");
+  }
+  const char* default_authority_str =
+      grpc_channel_arg_get_string(default_authority_arg);
+  if (default_authority_str == nullptr) {
+    return GRPC_ERROR_CREATE_FROM_STATIC_STRING(
+        "GRPC_ARG_DEFAULT_AUTHORITY channel arg. must be a string");
+  }
+  chand->default_authority =
+      grpc_slice_from_copied_string(default_authority_str);
+  GPR_ASSERT(!args->is_last);
+  return GRPC_ERROR_NONE;
+}
+
+/* Destructor for channel data */
+void destroy_channel_elem(grpc_channel_element* elem) {
+  channel_data* chand = static_cast<channel_data*>(elem->channel_data);
+  grpc_slice_unref(chand->default_authority);
+}
+}  // namespace
+
+const grpc_channel_filter grpc_client_authority_filter = {
+    authority_start_transport_stream_op_batch,
+    grpc_channel_next_op,
+    sizeof(call_data),
+    init_call_elem,
+    grpc_call_stack_ignore_set_pollset_or_pollset_set,
+    destroy_call_elem,
+    sizeof(channel_data),
+    init_channel_elem,
+    destroy_channel_elem,
+    grpc_channel_next_get_info,
+    "authority"};
+
+static bool add_client_authority_filter(grpc_channel_stack_builder* builder,
+                                        void* arg) {
+  const grpc_channel_args* channel_args =
+      grpc_channel_stack_builder_get_channel_arguments(builder);
+  const grpc_arg* disable_client_authority_filter_arg = grpc_channel_args_find(
+      channel_args, GRPC_ARG_DISABLE_CLIENT_AUTHORITY_FILTER);
+  if (disable_client_authority_filter_arg != nullptr) {
+    const bool is_client_authority_filter_disabled =
+        grpc_channel_arg_get_bool(disable_client_authority_filter_arg, false);
+    if (is_client_authority_filter_disabled) {
+      return true;
+    }
+  }
+  return grpc_channel_stack_builder_prepend_filter(
+      builder, static_cast<const grpc_channel_filter*>(arg), nullptr, nullptr);
+}
+
+void grpc_client_authority_filter_init(void) {
+  grpc_channel_init_register_stage(GRPC_CLIENT_SUBCHANNEL, INT_MAX,
+                                   add_client_authority_filter,
+                                   (void*)&grpc_client_authority_filter);
+  grpc_channel_init_register_stage(GRPC_CLIENT_DIRECT_CHANNEL, INT_MAX,
+                                   add_client_authority_filter,
+                                   (void*)&grpc_client_authority_filter);
+}
+
+void grpc_client_authority_filter_shutdown(void) {}
diff --git a/src/core/ext/filters/http/client_authority_filter.h b/src/core/ext/filters/http/client_authority_filter.h
new file mode 100644
index 0000000..5824e91
--- /dev/null
+++ b/src/core/ext/filters/http/client_authority_filter.h
@@ -0,0 +1,34 @@
+/*
+ *
+ * Copyright 2018 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_HTTP_CLIENT_AUTHORITY_FILTER_H
+#define GRPC_CORE_EXT_FILTERS_HTTP_CLIENT_AUTHORITY_FILTER_H
+
+#include <grpc/support/port_platform.h>
+
+#include <grpc/impl/codegen/compression_types.h>
+
+#include "src/core/lib/channel/channel_stack.h"
+
+/// Filter responsible for setting the authority header, if not already set. It
+/// uses the value of the GRPC_ARG_DEFAULT_AUTHORITY channel arg if the initial
+/// metadata doesn't already contain an authority value.
+
+extern const grpc_channel_filter grpc_client_authority_filter;
+
+#endif /* GRPC_CORE_EXT_FILTERS_HTTP_CLIENT_AUTHORITY_FILTER_H */
diff --git a/src/core/ext/filters/http/message_compress/message_compress_filter.cc b/src/core/ext/filters/http/message_compress/message_compress_filter.cc
index e7d9949..f8f478b 100644
--- a/src/core/ext/filters/http/message_compress/message_compress_filter.cc
+++ b/src/core/ext/filters/http/message_compress/message_compress_filter.cc
@@ -234,7 +234,7 @@
                                              static_cast<float>(before_size);
       GPR_ASSERT(grpc_message_compression_algorithm_name(
           calld->message_compression_algorithm, &algo_name));
-      gpr_log(GPR_DEBUG,
+      gpr_log(GPR_INFO,
               "Compressed[%s] %" PRIuPTR " bytes vs. %" PRIuPTR
               " bytes (%.2f%% savings)",
               algo_name, before_size, after_size, 100 * savings_ratio);
@@ -246,7 +246,7 @@
       const char* algo_name;
       GPR_ASSERT(grpc_message_compression_algorithm_name(
           calld->message_compression_algorithm, &algo_name));
-      gpr_log(GPR_DEBUG,
+      gpr_log(GPR_INFO,
               "Algorithm '%s' enabled but decided not to compress. Input size: "
               "%" PRIuPTR,
               algo_name, calld->slices.length);
diff --git a/src/core/ext/transport/chttp2/client/authority.cc b/src/core/ext/transport/chttp2/client/authority.cc
new file mode 100644
index 0000000..bad3153
--- /dev/null
+++ b/src/core/ext/transport/chttp2/client/authority.cc
@@ -0,0 +1,42 @@
+/*
+ *
+ * Copyright 2018 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.
+ *
+ */
+
+#include <grpc/support/port_platform.h>
+
+#include "src/core/ext/transport/chttp2/client/authority.h"
+
+grpc_channel_args* grpc_default_authority_add_if_not_present(
+    const grpc_channel_args* args) {
+  const bool has_default_authority =
+      grpc_channel_args_find(args, GRPC_ARG_DEFAULT_AUTHORITY) != nullptr;
+  grpc_arg new_args[1];
+  size_t num_new_args = 0;
+  grpc_core::UniquePtr<char> default_authority;
+  if (!has_default_authority) {
+    const grpc_arg* server_uri_arg =
+        grpc_channel_args_find(args, GRPC_ARG_SERVER_URI);
+    const char* server_uri_str = grpc_channel_arg_get_string(server_uri_arg);
+    GPR_ASSERT(server_uri_str != nullptr);
+    default_authority =
+        grpc_core::ResolverRegistry::GetDefaultAuthority(server_uri_str);
+    GPR_ASSERT(default_authority != nullptr);
+    new_args[num_new_args++] = grpc_channel_arg_string_create(
+        const_cast<char*>(GRPC_ARG_DEFAULT_AUTHORITY), default_authority.get());
+  }
+  return grpc_channel_args_copy_and_add(args, new_args, num_new_args);
+}
diff --git a/src/core/ext/transport/chttp2/client/authority.h b/src/core/ext/transport/chttp2/client/authority.h
new file mode 100644
index 0000000..642584e
--- /dev/null
+++ b/src/core/ext/transport/chttp2/client/authority.h
@@ -0,0 +1,36 @@
+/*
+ *
+ * Copyright 2018 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_TRANSPORT_CHTTP2_CLIENT_AUTHORITY_H
+#define GRPC_CORE_EXT_TRANSPORT_CHTTP2_CLIENT_AUTHORITY_H
+
+#include <grpc/support/port_platform.h>
+
+#include <grpc/grpc.h>
+
+#include "src/core/ext/filters/client_channel/client_channel.h"
+#include "src/core/ext/filters/client_channel/resolver_registry.h"
+#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/gprpp/memory.h"
+
+/// Returns a copy of \a args with the default authority channel arg set if it
+/// wasn't already present.
+grpc_channel_args* grpc_default_authority_add_if_not_present(
+    const grpc_channel_args* args);
+
+#endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_CLIENT_AUTHORITY_H */
diff --git a/src/core/ext/transport/chttp2/client/insecure/channel_create.cc b/src/core/ext/transport/chttp2/client/insecure/channel_create.cc
index 6080036..e6c8c38 100644
--- a/src/core/ext/transport/chttp2/client/insecure/channel_create.cc
+++ b/src/core/ext/transport/chttp2/client/insecure/channel_create.cc
@@ -27,6 +27,7 @@
 
 #include "src/core/ext/filters/client_channel/client_channel.h"
 #include "src/core/ext/filters/client_channel/resolver_registry.h"
+#include "src/core/ext/transport/chttp2/client/authority.h"
 #include "src/core/ext/transport/chttp2/client/chttp2_connector.h"
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/surface/api_trace.h"
@@ -40,9 +41,13 @@
 
 static grpc_subchannel* client_channel_factory_create_subchannel(
     grpc_client_channel_factory* cc_factory, const grpc_subchannel_args* args) {
+  grpc_subchannel_args final_sc_args;
+  memcpy(&final_sc_args, args, sizeof(*args));
+  final_sc_args.args = grpc_default_authority_add_if_not_present(args->args);
   grpc_connector* connector = grpc_chttp2_connector_create();
-  grpc_subchannel* s = grpc_subchannel_create(connector, args);
+  grpc_subchannel* s = grpc_subchannel_create(connector, &final_sc_args);
   grpc_connector_unref(connector);
+  grpc_channel_args_destroy(const_cast<grpc_channel_args*>(final_sc_args.args));
   return s;
 }
 
@@ -56,8 +61,8 @@
   // Add channel arg containing the server URI.
   grpc_core::UniquePtr<char> canonical_target =
       grpc_core::ResolverRegistry::AddDefaultPrefixIfNeeded(target);
-  grpc_arg arg = grpc_channel_arg_string_create((char*)GRPC_ARG_SERVER_URI,
-                                                canonical_target.get());
+  grpc_arg arg = grpc_channel_arg_string_create(
+      const_cast<char*>(GRPC_ARG_SERVER_URI), canonical_target.get());
   const char* to_remove[] = {GRPC_ARG_SERVER_URI};
   grpc_channel_args* new_args =
       grpc_channel_args_copy_and_add_and_remove(args, to_remove, 1, &arg, 1);
diff --git a/src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc b/src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc
index a82009f..5ce73a9 100644
--- a/src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc
+++ b/src/core/ext/transport/chttp2/client/secure/secure_channel_create.cc
@@ -71,9 +71,6 @@
   grpc_uri* server_uri =
       grpc_uri_parse(server_uri_str, true /* supress errors */);
   GPR_ASSERT(server_uri != nullptr);
-  const char* server_uri_path;
-  server_uri_path =
-      server_uri->path[0] == '/' ? server_uri->path + 1 : server_uri->path;
   const grpc_core::TargetAuthorityTable* target_authority_table =
       grpc_core::FindTargetAuthorityTableInArgs(args->args);
   grpc_core::UniquePtr<char> authority;
@@ -98,33 +95,49 @@
   // authority table was present or because the target was not present
   // in the table), fall back to using the original server URI.
   if (authority == nullptr) {
-    authority.reset(gpr_strdup(server_uri_path));
+    authority =
+        grpc_core::ResolverRegistry::GetDefaultAuthority(server_uri_str);
   }
+  grpc_arg args_to_add[2];
+  size_t num_args_to_add = 0;
+  if (grpc_channel_args_find(args->args, GRPC_ARG_DEFAULT_AUTHORITY) ==
+      nullptr) {
+    // If the channel args don't already contain GRPC_ARG_DEFAULT_AUTHORITY, add
+    // the arg, setting it to the value just obtained.
+    args_to_add[num_args_to_add++] = grpc_channel_arg_string_create(
+        const_cast<char*>(GRPC_ARG_DEFAULT_AUTHORITY), authority.get());
+  }
+  grpc_channel_args* args_with_authority =
+      grpc_channel_args_copy_and_add(args->args, args_to_add, num_args_to_add);
   grpc_uri_destroy(server_uri);
   grpc_channel_security_connector* subchannel_security_connector = nullptr;
   // Create the security connector using the credentials and target name.
   grpc_channel_args* new_args_from_connector = nullptr;
   const grpc_security_status security_status =
       grpc_channel_credentials_create_security_connector(
-          channel_credentials, authority.get(), args->args,
+          channel_credentials, authority.get(), args_with_authority,
           &subchannel_security_connector, &new_args_from_connector);
   if (security_status != GRPC_SECURITY_OK) {
     gpr_log(GPR_ERROR,
             "Failed to create secure subchannel for secure name '%s'",
             authority.get());
+    grpc_channel_args_destroy(args_with_authority);
     return nullptr;
   }
   grpc_arg new_security_connector_arg =
       grpc_security_connector_to_arg(&subchannel_security_connector->base);
 
   grpc_channel_args* new_args = grpc_channel_args_copy_and_add(
-      new_args_from_connector != nullptr ? new_args_from_connector : args->args,
+      new_args_from_connector != nullptr ? new_args_from_connector
+                                         : args_with_authority,
       &new_security_connector_arg, 1);
+
   GRPC_SECURITY_CONNECTOR_UNREF(&subchannel_security_connector->base,
                                 "lb_channel_create");
   if (new_args_from_connector != nullptr) {
     grpc_channel_args_destroy(new_args_from_connector);
   }
+  grpc_channel_args_destroy(args_with_authority);
   grpc_subchannel_args* final_sc_args =
       static_cast<grpc_subchannel_args*>(gpr_malloc(sizeof(*final_sc_args)));
   memcpy(final_sc_args, args, sizeof(*args));
diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc
index dc4e002..0ef7396 100644
--- a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc
+++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc
@@ -807,7 +807,7 @@
 
 static void set_write_state(grpc_chttp2_transport* t,
                             grpc_chttp2_write_state st, const char* reason) {
-  GRPC_CHTTP2_IF_TRACING(gpr_log(GPR_DEBUG, "W:%p %s state %s -> %s [%s]", t,
+  GRPC_CHTTP2_IF_TRACING(gpr_log(GPR_INFO, "W:%p %s state %s -> %s [%s]", t,
                                  t->is_client ? "CLIENT" : "SERVER",
                                  write_state_name(t->write_state),
                                  write_state_name(st), reason));
@@ -1072,7 +1072,7 @@
                                      uint32_t goaway_error,
                                      grpc_slice goaway_text) {
   // GRPC_CHTTP2_IF_TRACING(
-  //     gpr_log(GPR_DEBUG, "got goaway [%d]: %s", goaway_error, msg));
+  //     gpr_log(GPR_INFO, "got goaway [%d]: %s", goaway_error, msg));
 
   // Discard the error from a previous goaway frame (if any)
   if (t->goaway_error != GRPC_ERROR_NONE) {
@@ -1118,7 +1118,7 @@
          grpc_chttp2_list_pop_waiting_for_concurrency(t, &s)) {
     /* safe since we can't (legally) be parsing this stream yet */
     GRPC_CHTTP2_IF_TRACING(gpr_log(
-        GPR_DEBUG, "HTTP:%s: Allocating new grpc_chttp2_stream %p to id %d",
+        GPR_INFO, "HTTP:%s: Allocating new grpc_chttp2_stream %p to id %d",
         t->is_client ? "CLI" : "SVR", s, t->next_stream_id));
 
     GPR_ASSERT(s->id == 0);
@@ -1183,7 +1183,7 @@
   if (grpc_http_trace.enabled()) {
     const char* errstr = grpc_error_string(error);
     gpr_log(
-        GPR_DEBUG,
+        GPR_INFO,
         "complete_closure_step: t=%p %p refs=%d flags=0x%04x desc=%s err=%s "
         "write_state=%s",
         t, closure,
@@ -1336,7 +1336,7 @@
 
   if (grpc_http_trace.enabled()) {
     char* str = grpc_transport_stream_op_batch_string(op);
-    gpr_log(GPR_DEBUG, "perform_stream_op_locked: %s; on_complete = %p", str,
+    gpr_log(GPR_INFO, "perform_stream_op_locked: %s; on_complete = %p", str,
             op->on_complete);
     gpr_free(str);
     if (op->send_initial_metadata) {
@@ -1638,7 +1638,7 @@
 
   if (grpc_http_trace.enabled()) {
     char* str = grpc_transport_stream_op_batch_string(op);
-    gpr_log(GPR_DEBUG, "perform_stream_op[s=%p]: %s", s, str);
+    gpr_log(GPR_INFO, "perform_stream_op[s=%p]: %s", s, str);
     gpr_free(str);
   }
 
@@ -1676,6 +1676,33 @@
                            GRPC_ERROR_NONE);
 }
 
+/*
+ * Specialized form of send_ping_locked for keepalive ping. If there is already
+ * a ping in progress, the keepalive ping would piggyback onto that ping,
+ * instead of waiting for that ping to complete and then starting a new ping.
+ */
+static void send_keepalive_ping_locked(grpc_chttp2_transport* t) {
+  if (t->closed_with_error != GRPC_ERROR_NONE) {
+    GRPC_CLOSURE_SCHED(&t->start_keepalive_ping_locked,
+                       GRPC_ERROR_REF(t->closed_with_error));
+    GRPC_CLOSURE_SCHED(&t->finish_keepalive_ping_locked,
+                       GRPC_ERROR_REF(t->closed_with_error));
+    return;
+  }
+  grpc_chttp2_ping_queue* pq = &t->ping_queue;
+  if (!grpc_closure_list_empty(pq->lists[GRPC_CHTTP2_PCL_INFLIGHT])) {
+    /* There is a ping in flight. Add yourself to the inflight closure list. */
+    GRPC_CLOSURE_SCHED(&t->start_keepalive_ping_locked, GRPC_ERROR_NONE);
+    grpc_closure_list_append(&pq->lists[GRPC_CHTTP2_PCL_INFLIGHT],
+                             &t->finish_keepalive_ping_locked, GRPC_ERROR_NONE);
+    return;
+  }
+  grpc_closure_list_append(&pq->lists[GRPC_CHTTP2_PCL_INITIATE],
+                           &t->start_keepalive_ping_locked, GRPC_ERROR_NONE);
+  grpc_closure_list_append(&pq->lists[GRPC_CHTTP2_PCL_NEXT],
+                           &t->finish_keepalive_ping_locked, GRPC_ERROR_NONE);
+}
+
 static void retry_initiate_ping_locked(void* tp, grpc_error* error) {
   grpc_chttp2_transport* t = static_cast<grpc_chttp2_transport*>(tp);
   t->ping_state.is_delayed_ping_timer_set = false;
@@ -2502,7 +2529,7 @@
 static void start_bdp_ping_locked(void* tp, grpc_error* error) {
   grpc_chttp2_transport* t = static_cast<grpc_chttp2_transport*>(tp);
   if (grpc_http_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "%s: Start BDP ping err=%s", t->peer_string,
+    gpr_log(GPR_INFO, "%s: Start BDP ping err=%s", t->peer_string,
             grpc_error_string(error));
   }
   /* Reset the keepalive ping timer */
@@ -2515,7 +2542,7 @@
 static void finish_bdp_ping_locked(void* tp, grpc_error* error) {
   grpc_chttp2_transport* t = static_cast<grpc_chttp2_transport*>(tp);
   if (grpc_http_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "%s: Complete BDP ping err=%s", t->peer_string,
+    gpr_log(GPR_INFO, "%s: Complete BDP ping err=%s", t->peer_string,
             grpc_error_string(error));
   }
   if (error != GRPC_ERROR_NONE) {
@@ -2619,8 +2646,7 @@
         grpc_chttp2_stream_map_size(&t->stream_map) > 0) {
       t->keepalive_state = GRPC_CHTTP2_KEEPALIVE_STATE_PINGING;
       GRPC_CHTTP2_REF_TRANSPORT(t, "keepalive ping end");
-      send_ping_locked(t, &t->start_keepalive_ping_locked,
-                       &t->finish_keepalive_ping_locked);
+      send_keepalive_ping_locked(t);
       grpc_chttp2_initiate_write(t, GRPC_CHTTP2_INITIATE_WRITE_KEEPALIVE_PING);
     } else {
       GRPC_CHTTP2_REF_TRANSPORT(t, "init keepalive ping");
@@ -2690,8 +2716,7 @@
 static void connectivity_state_set(grpc_chttp2_transport* t,
                                    grpc_connectivity_state state,
                                    grpc_error* error, const char* reason) {
-  GRPC_CHTTP2_IF_TRACING(
-      gpr_log(GPR_DEBUG, "set connectivity_state=%d", state));
+  GRPC_CHTTP2_IF_TRACING(gpr_log(GPR_INFO, "set connectivity_state=%d", state));
   grpc_connectivity_state_set(&t->channel_callback.state_tracker, state, error,
                               reason);
 }
@@ -2958,7 +2983,7 @@
     /* Channel with no active streams: send a goaway to try and make it
      * disconnect cleanly */
     if (grpc_resource_quota_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "HTTP2: %s - send goaway to free memory",
+      gpr_log(GPR_INFO, "HTTP2: %s - send goaway to free memory",
               t->peer_string);
     }
     send_goaway(t,
@@ -2966,7 +2991,7 @@
                     GRPC_ERROR_CREATE_FROM_STATIC_STRING("Buffers full"),
                     GRPC_ERROR_INT_HTTP2_ERROR, GRPC_HTTP2_ENHANCE_YOUR_CALM));
   } else if (error == GRPC_ERROR_NONE && grpc_resource_quota_trace.enabled()) {
-    gpr_log(GPR_DEBUG,
+    gpr_log(GPR_INFO,
             "HTTP2: %s - skip benign reclamation, there are still %" PRIdPTR
             " streams",
             t->peer_string, grpc_chttp2_stream_map_size(&t->stream_map));
@@ -2987,7 +3012,7 @@
     grpc_chttp2_stream* s = static_cast<grpc_chttp2_stream*>(
         grpc_chttp2_stream_map_rand(&t->stream_map));
     if (grpc_resource_quota_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "HTTP2: %s - abandon stream id %d", t->peer_string,
+      gpr_log(GPR_INFO, "HTTP2: %s - abandon stream id %d", t->peer_string,
               s->id);
     }
     grpc_chttp2_cancel_stream(
diff --git a/src/core/ext/transport/chttp2/transport/frame_settings.cc b/src/core/ext/transport/chttp2/transport/frame_settings.cc
index 9ea27dc..987ac0e 100644
--- a/src/core/ext/transport/chttp2/transport/frame_settings.cc
+++ b/src/core/ext/transport/chttp2/transport/frame_settings.cc
@@ -217,14 +217,14 @@
             t->initial_window_update += static_cast<int64_t>(parser->value) -
                                         parser->incoming_settings[id];
             if (grpc_http_trace.enabled() || grpc_flowctl_trace.enabled()) {
-              gpr_log(GPR_DEBUG, "%p[%s] adding %d for initial_window change",
-                      t, t->is_client ? "cli" : "svr",
+              gpr_log(GPR_INFO, "%p[%s] adding %d for initial_window change", t,
+                      t->is_client ? "cli" : "svr",
                       static_cast<int>(t->initial_window_update));
             }
           }
           parser->incoming_settings[id] = parser->value;
           if (grpc_http_trace.enabled()) {
-            gpr_log(GPR_DEBUG, "CHTTP2:%s:%s: got setting %s = %d",
+            gpr_log(GPR_INFO, "CHTTP2:%s:%s: got setting %s = %d",
                     t->is_client ? "CLI" : "SVR", t->peer_string, sp->name,
                     parser->value);
           }
diff --git a/src/core/ext/transport/chttp2/transport/hpack_encoder.cc b/src/core/ext/transport/chttp2/transport/hpack_encoder.cc
index e4f3c1b..d5ef063 100644
--- a/src/core/ext/transport/chttp2/transport/hpack_encoder.cc
+++ b/src/core/ext/transport/chttp2/transport/hpack_encoder.cc
@@ -470,7 +470,7 @@
       v = grpc_slice_to_c_string(GRPC_MDVALUE(elem));
     }
     gpr_log(
-        GPR_DEBUG,
+        GPR_INFO,
         "Encode: '%s: %s', elem_interned=%d [%d], k_interned=%d, v_interned=%d",
         k, v, GRPC_MDELEM_IS_INTERNED(elem), GRPC_MDELEM_STORAGE(elem),
         grpc_slice_is_interned(GRPC_MDKEY(elem)),
@@ -654,7 +654,7 @@
   }
   c->advertise_table_size_change = 1;
   if (grpc_http_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "set max table size from encoder to %d", max_table_size);
+    gpr_log(GPR_INFO, "set max table size from encoder to %d", max_table_size);
   }
 }
 
diff --git a/src/core/ext/transport/chttp2/transport/hpack_parser.cc b/src/core/ext/transport/chttp2/transport/hpack_parser.cc
index fc96a8b..907ba71 100644
--- a/src/core/ext/transport/chttp2/transport/hpack_parser.cc
+++ b/src/core/ext/transport/chttp2/transport/hpack_parser.cc
@@ -633,7 +633,7 @@
       v = grpc_slice_to_c_string(GRPC_MDVALUE(md));
     }
     gpr_log(
-        GPR_DEBUG,
+        GPR_INFO,
         "Decode: '%s: %s', elem_interned=%d [%d], k_interned=%d, v_interned=%d",
         k, v, GRPC_MDELEM_IS_INTERNED(md), GRPC_MDELEM_STORAGE(md),
         grpc_slice_is_interned(GRPC_MDKEY(md)),
diff --git a/src/core/ext/transport/chttp2/transport/hpack_table.cc b/src/core/ext/transport/chttp2/transport/hpack_table.cc
index f050f50..7929258 100644
--- a/src/core/ext/transport/chttp2/transport/hpack_table.cc
+++ b/src/core/ext/transport/chttp2/transport/hpack_table.cc
@@ -247,7 +247,7 @@
     return;
   }
   if (grpc_http_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "Update hpack parser max size to %d", max_bytes);
+    gpr_log(GPR_INFO, "Update hpack parser max size to %d", max_bytes);
   }
   while (tbl->mem_used > max_bytes) {
     evict1(tbl);
@@ -270,7 +270,7 @@
     return err;
   }
   if (grpc_http_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "Update hpack parser table size to %d", bytes);
+    gpr_log(GPR_INFO, "Update hpack parser table size to %d", bytes);
   }
   while (tbl->mem_used > bytes) {
     evict1(tbl);
diff --git a/src/core/ext/transport/chttp2/transport/stream_lists.cc b/src/core/ext/transport/chttp2/transport/stream_lists.cc
index 5d3ec4b..6626170 100644
--- a/src/core/ext/transport/chttp2/transport/stream_lists.cc
+++ b/src/core/ext/transport/chttp2/transport/stream_lists.cc
@@ -68,7 +68,7 @@
   }
   *stream = s;
   if (s && grpc_trace_http2_stream_state.enabled()) {
-    gpr_log(GPR_DEBUG, "%p[%d][%s]: pop from %s", t, s->id,
+    gpr_log(GPR_INFO, "%p[%d][%s]: pop from %s", t, s->id,
             t->is_client ? "cli" : "svr", stream_list_id_string(id));
   }
   return s != nullptr;
@@ -90,7 +90,7 @@
     t->lists[id].tail = s->links[id].prev;
   }
   if (grpc_trace_http2_stream_state.enabled()) {
-    gpr_log(GPR_DEBUG, "%p[%d][%s]: remove from %s", t, s->id,
+    gpr_log(GPR_INFO, "%p[%d][%s]: remove from %s", t, s->id,
             t->is_client ? "cli" : "svr", stream_list_id_string(id));
   }
 }
@@ -122,7 +122,7 @@
   t->lists[id].tail = s;
   s->included[id] = 1;
   if (grpc_trace_http2_stream_state.enabled()) {
-    gpr_log(GPR_DEBUG, "%p[%d][%s]: add to %s", t, s->id,
+    gpr_log(GPR_INFO, "%p[%d][%s]: add to %s", t, s->id,
             t->is_client ? "cli" : "svr", stream_list_id_string(id));
   }
 }
diff --git a/src/core/ext/transport/chttp2/transport/writing.cc b/src/core/ext/transport/chttp2/transport/writing.cc
index 6f32397..85efe27 100644
--- a/src/core/ext/transport/chttp2/transport/writing.cc
+++ b/src/core/ext/transport/chttp2/transport/writing.cc
@@ -52,7 +52,7 @@
   if (!grpc_closure_list_empty(pq->lists[GRPC_CHTTP2_PCL_INFLIGHT])) {
     /* ping already in-flight: wait */
     if (grpc_http_trace.enabled() || grpc_bdp_estimator_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "%s: Ping delayed [%p]: already pinging",
+      gpr_log(GPR_INFO, "%s: Ping delayed [%p]: already pinging",
               t->is_client ? "CLIENT" : "SERVER", t->peer_string);
     }
     return;
@@ -61,7 +61,7 @@
       t->ping_policy.max_pings_without_data != 0) {
     /* need to receive something of substance before sending a ping again */
     if (grpc_http_trace.enabled() || grpc_bdp_estimator_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "%s: Ping delayed [%p]: too many recent pings: %d/%d",
+      gpr_log(GPR_INFO, "%s: Ping delayed [%p]: too many recent pings: %d/%d",
               t->is_client ? "CLIENT" : "SERVER", t->peer_string,
               t->ping_state.pings_before_data_required,
               t->ping_policy.max_pings_without_data);
@@ -81,7 +81,7 @@
   if (next_allowed_ping > now) {
     /* not enough elapsed time between successive pings */
     if (grpc_http_trace.enabled() || grpc_bdp_estimator_trace.enabled()) {
-      gpr_log(GPR_DEBUG,
+      gpr_log(GPR_INFO,
               "%s: Ping delayed [%p]: not enough time elapsed since last ping. "
               " Last ping %f: Next ping %f: Now %f",
               t->is_client ? "CLIENT" : "SERVER", t->peer_string,
@@ -107,7 +107,7 @@
   GRPC_STATS_INC_HTTP2_PINGS_SENT();
   t->ping_state.last_ping_sent_time = now;
   if (grpc_http_trace.enabled() || grpc_bdp_estimator_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "%s: Ping sent [%p]: %d/%d",
+    gpr_log(GPR_INFO, "%s: Ping sent [%p]: %d/%d",
             t->is_client ? "CLIENT" : "SERVER", t->peer_string,
             t->ping_state.pings_before_data_required,
             t->ping_policy.max_pings_without_data);
@@ -401,7 +401,7 @@
   StreamWriteContext(WriteContext* write_context, grpc_chttp2_stream* s)
       : write_context_(write_context), t_(write_context->transport()), s_(s) {
     GRPC_CHTTP2_IF_TRACING(
-        gpr_log(GPR_DEBUG, "W:%p %s[%d] im-(sent,send)=(%d,%d) announce=%d", t_,
+        gpr_log(GPR_INFO, "W:%p %s[%d] im-(sent,send)=(%d,%d) announce=%d", t_,
                 t_->is_client ? "CLIENT" : "SERVER", s->id,
                 s->sent_initial_metadata, s->send_initial_metadata != nullptr,
                 (int)(s->flow_control->local_window_delta() -
diff --git a/src/core/ext/transport/inproc/inproc_transport.cc b/src/core/ext/transport/inproc/inproc_transport.cc
index 67a3800..2c3bff5 100644
--- a/src/core/ext/transport/inproc/inproc_transport.cc
+++ b/src/core/ext/transport/inproc/inproc_transport.cc
@@ -125,12 +125,12 @@
 static void op_state_machine(void* arg, grpc_error* error);
 
 static void ref_transport(inproc_transport* t) {
-  INPROC_LOG(GPR_DEBUG, "ref_transport %p", t);
+  INPROC_LOG(GPR_INFO, "ref_transport %p", t);
   gpr_ref(&t->refs);
 }
 
 static void really_destroy_transport(inproc_transport* t) {
-  INPROC_LOG(GPR_DEBUG, "really_destroy_transport %p", t);
+  INPROC_LOG(GPR_INFO, "really_destroy_transport %p", t);
   grpc_connectivity_state_destroy(&t->connectivity);
   if (gpr_unref(&t->mu->refs)) {
     gpr_free(t->mu);
@@ -139,7 +139,7 @@
 }
 
 static void unref_transport(inproc_transport* t) {
-  INPROC_LOG(GPR_DEBUG, "unref_transport %p", t);
+  INPROC_LOG(GPR_INFO, "unref_transport %p", t);
   if (gpr_unref(&t->refs)) {
     really_destroy_transport(t);
   }
@@ -154,17 +154,17 @@
 #endif
 
 static void ref_stream(inproc_stream* s, const char* reason) {
-  INPROC_LOG(GPR_DEBUG, "ref_stream %p %s", s, reason);
+  INPROC_LOG(GPR_INFO, "ref_stream %p %s", s, reason);
   STREAM_REF(s->refs, reason);
 }
 
 static void unref_stream(inproc_stream* s, const char* reason) {
-  INPROC_LOG(GPR_DEBUG, "unref_stream %p %s", s, reason);
+  INPROC_LOG(GPR_INFO, "unref_stream %p %s", s, reason);
   STREAM_UNREF(s->refs, reason);
 }
 
 static void really_destroy_stream(inproc_stream* s) {
-  INPROC_LOG(GPR_DEBUG, "really_destroy_stream %p", s);
+  INPROC_LOG(GPR_INFO, "really_destroy_stream %p", s);
 
   GRPC_ERROR_UNREF(s->write_buffer_cancel_error);
   GRPC_ERROR_UNREF(s->cancel_self_error);
@@ -225,7 +225,7 @@
 static int init_stream(grpc_transport* gt, grpc_stream* gs,
                        grpc_stream_refcount* refcount, const void* server_data,
                        gpr_arena* arena) {
-  INPROC_LOG(GPR_DEBUG, "init_stream %p %p %p", gt, gs, server_data);
+  INPROC_LOG(GPR_INFO, "init_stream %p %p %p", gt, gs, server_data);
   inproc_transport* t = reinterpret_cast<inproc_transport*>(gt);
   inproc_stream* s = reinterpret_cast<inproc_stream*>(gs);
   s->arena = arena;
@@ -282,8 +282,8 @@
     // Pass the client-side stream address to the server-side for a ref
     ref_stream(s, "inproc_init_stream:clt");  // ref it now on behalf of server
                                               // side to avoid destruction
-    INPROC_LOG(GPR_DEBUG, "calling accept stream cb %p %p",
-               st->accept_stream_cb, st->accept_stream_data);
+    INPROC_LOG(GPR_INFO, "calling accept stream cb %p %p", st->accept_stream_cb,
+               st->accept_stream_data);
     (*st->accept_stream_cb)(st->accept_stream_data, &st->base, (void*)s);
   } else {
     // This is the server-side and is being called through accept_stream_cb
@@ -378,7 +378,7 @@
   int is_rtm = static_cast<int>(op == s->recv_trailing_md_op);
 
   if ((is_sm + is_stm + is_rim + is_rm + is_rtm) == 1) {
-    INPROC_LOG(GPR_DEBUG, "%s %p %p %p", msg, s, op, error);
+    INPROC_LOG(GPR_INFO, "%s %p %p %p", msg, s, op, error);
     GRPC_CLOSURE_SCHED(op->on_complete, GRPC_ERROR_REF(error));
   }
 }
@@ -393,7 +393,7 @@
 }
 
 static void fail_helper_locked(inproc_stream* s, grpc_error* error) {
-  INPROC_LOG(GPR_DEBUG, "op_state_machine %p fail_helper", s);
+  INPROC_LOG(GPR_INFO, "op_state_machine %p fail_helper", s);
   // If we're failing this side, we need to make sure that
   // we also send or have already sent trailing metadata
   if (!s->trailing_md_sent) {
@@ -458,7 +458,7 @@
       *s->recv_initial_md_op->payload->recv_initial_metadata
            .trailing_metadata_available = true;
     }
-    INPROC_LOG(GPR_DEBUG,
+    INPROC_LOG(GPR_INFO,
                "fail_helper %p scheduling initial-metadata-ready %p %p", s,
                error, err);
     GRPC_CLOSURE_SCHED(s->recv_initial_md_op->payload->recv_initial_metadata
@@ -472,7 +472,7 @@
     s->recv_initial_md_op = nullptr;
   }
   if (s->recv_message_op) {
-    INPROC_LOG(GPR_DEBUG, "fail_helper %p scheduling message-ready %p", s,
+    INPROC_LOG(GPR_INFO, "fail_helper %p scheduling message-ready %p", s,
                error);
     GRPC_CLOSURE_SCHED(
         s->recv_message_op->payload->recv_message.recv_message_ready,
@@ -496,9 +496,8 @@
     s->send_trailing_md_op = nullptr;
   }
   if (s->recv_trailing_md_op) {
-    INPROC_LOG(GPR_DEBUG,
-               "fail_helper %p scheduling trailing-md-on-complete %p", s,
-               error);
+    INPROC_LOG(GPR_INFO, "fail_helper %p scheduling trailing-md-on-complete %p",
+               s, error);
     complete_if_batch_end_locked(
         s, error, s->recv_trailing_md_op,
         "fail_helper scheduling recv-trailing-metadata-on-complete");
@@ -549,7 +548,7 @@
   receiver->recv_stream.Init(&receiver->recv_message, 0);
   receiver->recv_message_op->payload->recv_message.recv_message->reset(
       receiver->recv_stream.get());
-  INPROC_LOG(GPR_DEBUG, "message_transfer_locked %p scheduling message-ready",
+  INPROC_LOG(GPR_INFO, "message_transfer_locked %p scheduling message-ready",
              receiver);
   GRPC_CLOSURE_SCHED(
       receiver->recv_message_op->payload->recv_message.recv_message_ready,
@@ -577,7 +576,7 @@
 
   bool needs_close = false;
 
-  INPROC_LOG(GPR_DEBUG, "op_state_machine %p", arg);
+  INPROC_LOG(GPR_INFO, "op_state_machine %p", arg);
   inproc_stream* s = static_cast<inproc_stream*>(arg);
   gpr_mu* mu = &s->t->mu->mu;  // keep aside in case s gets closed
   gpr_mu_lock(mu);
@@ -626,7 +625,7 @@
                                           : &other->to_read_trailing_md_filled;
     if (*destfilled || s->trailing_md_sent) {
       // The buffer is already in use; that's an error!
-      INPROC_LOG(GPR_DEBUG, "Extra trailing metadata %p", s);
+      INPROC_LOG(GPR_INFO, "Extra trailing metadata %p", s);
       new_err = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Extra trailing metadata");
       fail_helper_locked(s, GRPC_ERROR_REF(new_err));
       goto done;
@@ -639,7 +638,7 @@
       }
       s->trailing_md_sent = true;
       if (!s->t->is_client && s->trailing_md_recvd && s->recv_trailing_md_op) {
-        INPROC_LOG(GPR_DEBUG,
+        INPROC_LOG(GPR_INFO,
                    "op_state_machine %p scheduling trailing-md-on-complete", s);
         GRPC_CLOSURE_SCHED(s->recv_trailing_md_op->on_complete,
                            GRPC_ERROR_NONE);
@@ -658,7 +657,7 @@
       new_err =
           GRPC_ERROR_CREATE_FROM_STATIC_STRING("Already recvd initial md");
       INPROC_LOG(
-          GPR_DEBUG,
+          GPR_INFO,
           "op_state_machine %p scheduling on_complete errors for already "
           "recvd initial md %p",
           s, new_err);
@@ -684,7 +683,7 @@
       }
       grpc_metadata_batch_clear(&s->to_read_initial_md);
       s->to_read_initial_md_filled = false;
-      INPROC_LOG(GPR_DEBUG,
+      INPROC_LOG(GPR_INFO,
                  "op_state_machine %p scheduling initial-metadata-ready %p", s,
                  new_err);
       GRPC_CLOSURE_SCHED(s->recv_initial_md_op->payload->recv_initial_metadata
@@ -696,7 +695,7 @@
       s->recv_initial_md_op = nullptr;
 
       if (new_err != GRPC_ERROR_NONE) {
-        INPROC_LOG(GPR_DEBUG,
+        INPROC_LOG(GPR_INFO,
                    "op_state_machine %p scheduling on_complete errors2 %p", s,
                    new_err);
         fail_helper_locked(s, GRPC_ERROR_REF(new_err));
@@ -719,7 +718,7 @@
       new_err =
           GRPC_ERROR_CREATE_FROM_STATIC_STRING("Already recvd trailing md");
       INPROC_LOG(
-          GPR_DEBUG,
+          GPR_INFO,
           "op_state_machine %p scheduling on_complete errors for already "
           "recvd trailing md %p",
           s, new_err);
@@ -729,7 +728,7 @@
     if (s->recv_message_op != nullptr) {
       // This message needs to be wrapped up because it will never be
       // satisfied
-      INPROC_LOG(GPR_DEBUG, "op_state_machine %p scheduling message-ready", s);
+      INPROC_LOG(GPR_INFO, "op_state_machine %p scheduling message-ready", s);
       GRPC_CLOSURE_SCHED(
           s->recv_message_op->payload->recv_message.recv_message_ready,
           GRPC_ERROR_NONE);
@@ -764,7 +763,7 @@
       //    (If the server hasn't already sent its trailing md, it doesn't have
       //     a final status, so don't mark this op complete)
       if (s->t->is_client || s->trailing_md_sent) {
-        INPROC_LOG(GPR_DEBUG,
+        INPROC_LOG(GPR_INFO,
                    "op_state_machine %p scheduling trailing-md-on-complete %p",
                    s, new_err);
         GRPC_CLOSURE_SCHED(s->recv_trailing_md_op->on_complete,
@@ -772,21 +771,21 @@
         s->recv_trailing_md_op = nullptr;
         needs_close = true;
       } else {
-        INPROC_LOG(GPR_DEBUG,
+        INPROC_LOG(GPR_INFO,
                    "op_state_machine %p server needs to delay handling "
                    "trailing-md-on-complete %p",
                    s, new_err);
       }
     } else {
       INPROC_LOG(
-          GPR_DEBUG,
+          GPR_INFO,
           "op_state_machine %p has trailing md but not yet waiting for it", s);
     }
   }
   if (s->trailing_md_recvd && s->recv_message_op) {
     // No further message will come on this stream, so finish off the
     // recv_message_op
-    INPROC_LOG(GPR_DEBUG, "op_state_machine %p scheduling message-ready", s);
+    INPROC_LOG(GPR_INFO, "op_state_machine %p scheduling message-ready", s);
     GRPC_CLOSURE_SCHED(
         s->recv_message_op->payload->recv_message.recv_message_ready,
         GRPC_ERROR_NONE);
@@ -810,7 +809,7 @@
     // Didn't get the item we wanted so we still need to get
     // rescheduled
     INPROC_LOG(
-        GPR_DEBUG, "op_state_machine %p still needs closure %p %p %p %p %p", s,
+        GPR_INFO, "op_state_machine %p still needs closure %p %p %p %p %p", s,
         s->send_message_op, s->send_trailing_md_op, s->recv_initial_md_op,
         s->recv_message_op, s->recv_trailing_md_op);
     s->ops_needed = true;
@@ -826,8 +825,7 @@
 
 static bool cancel_stream_locked(inproc_stream* s, grpc_error* error) {
   bool ret = false;  // was the cancel accepted
-  INPROC_LOG(GPR_DEBUG, "cancel_stream %p with %s", s,
-             grpc_error_string(error));
+  INPROC_LOG(GPR_INFO, "cancel_stream %p with %s", s, grpc_error_string(error));
   if (s->cancel_self_error == GRPC_ERROR_NONE) {
     ret = true;
     s->cancel_self_error = GRPC_ERROR_REF(error);
@@ -877,7 +875,7 @@
 
 static void perform_stream_op(grpc_transport* gt, grpc_stream* gs,
                               grpc_transport_stream_op_batch* op) {
-  INPROC_LOG(GPR_DEBUG, "perform_stream_op %p %p %p", gt, gs, op);
+  INPROC_LOG(GPR_INFO, "perform_stream_op %p %p %p", gt, gs, op);
   inproc_stream* s = reinterpret_cast<inproc_stream*>(gs);
   gpr_mu* mu = &s->t->mu->mu;  // save aside in case s gets closed
   gpr_mu_lock(mu);
@@ -907,7 +905,7 @@
     // already self-canceled so still give it an error
     error = GRPC_ERROR_REF(s->cancel_self_error);
   } else {
-    INPROC_LOG(GPR_DEBUG, "perform_stream_op %p %s%s%s%s%s%s%s", s,
+    INPROC_LOG(GPR_INFO, "perform_stream_op %p %s%s%s%s%s%s%s", s,
                s->t->is_client ? "client" : "server",
                op->send_initial_metadata ? " send_initial_metadata" : "",
                op->send_message ? " send_message" : "",
@@ -936,7 +934,7 @@
                                             : &other->to_read_initial_md_filled;
       if (*destfilled || s->initial_md_sent) {
         // The buffer is already in use; that's an error!
-        INPROC_LOG(GPR_DEBUG, "Extra initial metadata %p", s);
+        INPROC_LOG(GPR_INFO, "Extra initial metadata %p", s);
         error = GRPC_ERROR_CREATE_FROM_STATIC_STRING("Extra initial metadata");
       } else {
         if (!other || !other->closed) {
@@ -1013,7 +1011,7 @@
               true;
         }
         INPROC_LOG(
-            GPR_DEBUG,
+            GPR_INFO,
             "perform_stream_op error %p scheduling initial-metadata-ready %p",
             s, error);
         GRPC_CLOSURE_SCHED(
@@ -1022,14 +1020,14 @@
       }
       if (op->recv_message) {
         INPROC_LOG(
-            GPR_DEBUG,
+            GPR_INFO,
             "perform_stream_op error %p scheduling recv message-ready %p", s,
             error);
         GRPC_CLOSURE_SCHED(op->payload->recv_message.recv_message_ready,
                            GRPC_ERROR_REF(error));
       }
     }
-    INPROC_LOG(GPR_DEBUG, "perform_stream_op %p scheduling on_complete %p", s,
+    INPROC_LOG(GPR_INFO, "perform_stream_op %p scheduling on_complete %p", s,
                error);
     GRPC_CLOSURE_SCHED(on_complete, GRPC_ERROR_REF(error));
   }
@@ -1042,7 +1040,7 @@
 }
 
 static void close_transport_locked(inproc_transport* t) {
-  INPROC_LOG(GPR_DEBUG, "close_transport %p %d", t, t->is_closed);
+  INPROC_LOG(GPR_INFO, "close_transport %p %d", t, t->is_closed);
   grpc_connectivity_state_set(
       &t->connectivity, GRPC_CHANNEL_SHUTDOWN,
       GRPC_ERROR_CREATE_FROM_STATIC_STRING("Closing transport."),
@@ -1063,7 +1061,7 @@
 
 static void perform_transport_op(grpc_transport* gt, grpc_transport_op* op) {
   inproc_transport* t = reinterpret_cast<inproc_transport*>(gt);
-  INPROC_LOG(GPR_DEBUG, "perform_transport_op %p %p", t, op);
+  INPROC_LOG(GPR_INFO, "perform_transport_op %p %p", t, op);
   gpr_mu_lock(&t->mu->mu);
   if (op->on_connectivity_state_change) {
     grpc_connectivity_state_notify_on_state_change(
@@ -1096,7 +1094,7 @@
 
 static void destroy_stream(grpc_transport* gt, grpc_stream* gs,
                            grpc_closure* then_schedule_closure) {
-  INPROC_LOG(GPR_DEBUG, "destroy_stream %p %p", gs, then_schedule_closure);
+  INPROC_LOG(GPR_INFO, "destroy_stream %p %p", gs, then_schedule_closure);
   inproc_stream* s = reinterpret_cast<inproc_stream*>(gs);
   s->closure_at_destroy = then_schedule_closure;
   really_destroy_stream(s);
@@ -1104,7 +1102,7 @@
 
 static void destroy_transport(grpc_transport* gt) {
   inproc_transport* t = reinterpret_cast<inproc_transport*>(gt);
-  INPROC_LOG(GPR_DEBUG, "destroy_transport %p", t);
+  INPROC_LOG(GPR_INFO, "destroy_transport %p", t);
   gpr_mu_lock(&t->mu->mu);
   close_transport_locked(t);
   gpr_mu_unlock(&t->mu->mu);
@@ -1165,7 +1163,7 @@
                                      const grpc_channel_args* server_args,
                                      grpc_transport** client_transport,
                                      const grpc_channel_args* client_args) {
-  INPROC_LOG(GPR_DEBUG, "inproc_transports_create");
+  INPROC_LOG(GPR_INFO, "inproc_transports_create");
   inproc_transport* st =
       static_cast<inproc_transport*>(gpr_zalloc(sizeof(*st)));
   inproc_transport* ct =
diff --git a/src/core/lib/channel/channel_args.cc b/src/core/lib/channel/channel_args.cc
index 66a86c2..e49d532 100644
--- a/src/core/lib/channel/channel_args.cc
+++ b/src/core/lib/channel/channel_args.cc
@@ -411,3 +411,31 @@
   arg.value.pointer.vtable = vtable;
   return arg;
 }
+
+char* grpc_channel_args_string(const grpc_channel_args* args) {
+  if (args == nullptr) return nullptr;
+  gpr_strvec v;
+  gpr_strvec_init(&v);
+  for (size_t i = 0; i < args->num_args; ++i) {
+    const grpc_arg& arg = args->args[i];
+    char* s;
+    switch (arg.type) {
+      case GRPC_ARG_INTEGER:
+        gpr_asprintf(&s, "%s=%d", arg.key, arg.value.integer);
+        break;
+      case GRPC_ARG_STRING:
+        gpr_asprintf(&s, "%s=%s", arg.key, arg.value.string);
+        break;
+      case GRPC_ARG_POINTER:
+        gpr_asprintf(&s, "%s=%p", arg.key, arg.value.pointer.p);
+        break;
+      default:
+        gpr_asprintf(&s, "arg with unknown type");
+    }
+    gpr_strvec_add(&v, s);
+  }
+  char* result =
+      gpr_strjoin_sep(const_cast<const char**>(v.strs), v.count, ", ", nullptr);
+  gpr_strvec_destroy(&v);
+  return result;
+}
diff --git a/src/core/lib/channel/channel_args.h b/src/core/lib/channel/channel_args.h
index c0d6a17..5ff303a 100644
--- a/src/core/lib/channel/channel_args.h
+++ b/src/core/lib/channel/channel_args.h
@@ -124,4 +124,8 @@
 grpc_arg grpc_channel_arg_pointer_create(char* name, void* value,
                                          const grpc_arg_pointer_vtable* vtable);
 
+// Returns a string representing channel args in human-readable form.
+// Callers takes ownership of result.
+char* grpc_channel_args_string(const grpc_channel_args* args);
+
 #endif /* GRPC_CORE_LIB_CHANNEL_CHANNEL_ARGS_H */
diff --git a/src/core/lib/channel/handshaker.cc b/src/core/lib/channel/handshaker.cc
index 9b1af8d..2faeb64 100644
--- a/src/core/lib/channel/handshaker.cc
+++ b/src/core/lib/channel/handshaker.cc
@@ -22,11 +22,15 @@
 
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
 
 #include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/channel/handshaker.h"
+#include "src/core/lib/debug/trace.h"
 #include "src/core/lib/iomgr/timer.h"
 
+grpc_core::TraceFlag grpc_handshaker_trace(false, "handshaker");
+
 //
 // grpc_handshaker
 //
@@ -52,6 +56,10 @@
                                    args);
 }
 
+const char* grpc_handshaker_name(grpc_handshaker* handshaker) {
+  return handshaker->vtable->name;
+}
+
 //
 // grpc_handshake_manager
 //
@@ -127,6 +135,12 @@
 
 void grpc_handshake_manager_add(grpc_handshake_manager* mgr,
                                 grpc_handshaker* handshaker) {
+  if (grpc_handshaker_trace.enabled()) {
+    gpr_log(
+        GPR_INFO,
+        "handshake_manager %p: adding handshaker %s [%p] at index %" PRIuPTR,
+        mgr, grpc_handshaker_name(handshaker), handshaker, mgr->count);
+  }
   gpr_mu_lock(&mgr->mu);
   // To avoid allocating memory for each handshaker we add, we double
   // the number of elements every time we need more.
@@ -172,23 +186,56 @@
   GRPC_ERROR_UNREF(why);
 }
 
+static char* handshaker_args_string(grpc_handshaker_args* args) {
+  char* args_str = grpc_channel_args_string(args->args);
+  size_t num_args = args->args != nullptr ? args->args->num_args : 0;
+  size_t read_buffer_length =
+      args->read_buffer != nullptr ? args->read_buffer->length : 0;
+  char* str;
+  gpr_asprintf(&str,
+               "{endpoint=%p, args=%p {size=%" PRIuPTR
+               ": %s}, read_buffer=%p (length=%" PRIuPTR "), exit_early=%d}",
+               args->endpoint, args->args, num_args, args_str,
+               args->read_buffer, read_buffer_length, args->exit_early);
+  gpr_free(args_str);
+  return str;
+}
+
 // Helper function to call either the next handshaker or the
 // on_handshake_done callback.
 // Returns true if we've scheduled the on_handshake_done callback.
 static bool call_next_handshaker_locked(grpc_handshake_manager* mgr,
                                         grpc_error* error) {
+  if (grpc_handshaker_trace.enabled()) {
+    char* args_str = handshaker_args_string(&mgr->args);
+    gpr_log(GPR_INFO,
+            "handshake_manager %p: error=%s shutdown=%d index=%" PRIuPTR
+            ", args=%s",
+            mgr, grpc_error_string(error), mgr->shutdown, mgr->index, args_str);
+    gpr_free(args_str);
+  }
   GPR_ASSERT(mgr->index <= mgr->count);
   // If we got an error or we've been shut down or we're exiting early or
   // we've finished the last handshaker, invoke the on_handshake_done
   // callback.  Otherwise, call the next handshaker.
   if (error != GRPC_ERROR_NONE || mgr->shutdown || mgr->args.exit_early ||
       mgr->index == mgr->count) {
+    if (grpc_handshaker_trace.enabled()) {
+      gpr_log(GPR_INFO, "handshake_manager %p: handshaking complete", mgr);
+    }
     // Cancel deadline timer, since we're invoking the on_handshake_done
     // callback now.
     grpc_timer_cancel(&mgr->deadline_timer);
     GRPC_CLOSURE_SCHED(&mgr->on_handshake_done, error);
     mgr->shutdown = true;
   } else {
+    if (grpc_handshaker_trace.enabled()) {
+      gpr_log(
+          GPR_INFO,
+          "handshake_manager %p: calling handshaker %s [%p] at index %" PRIuPTR,
+          mgr, grpc_handshaker_name(mgr->handshakers[mgr->index]),
+          mgr->handshakers[mgr->index], mgr->index);
+    }
     grpc_handshaker_do_handshake(mgr->handshakers[mgr->index], mgr->acceptor,
                                  &mgr->call_next_handshaker, &mgr->args);
   }
diff --git a/src/core/lib/channel/handshaker.h b/src/core/lib/channel/handshaker.h
index dfecd81..be7fd12 100644
--- a/src/core/lib/channel/handshaker.h
+++ b/src/core/lib/channel/handshaker.h
@@ -84,6 +84,9 @@
                        grpc_tcp_server_acceptor* acceptor,
                        grpc_closure* on_handshake_done,
                        grpc_handshaker_args* args);
+
+  /// The name of the handshaker, for debugging purposes.
+  const char* name;
 } grpc_handshaker_vtable;
 
 /// Base struct.  To subclass, make this the first member of the
@@ -102,6 +105,7 @@
                                   grpc_tcp_server_acceptor* acceptor,
                                   grpc_closure* on_handshake_done,
                                   grpc_handshaker_args* args);
+const char* grpc_handshaker_name(grpc_handshaker* handshaker);
 
 ///
 /// grpc_handshake_manager
diff --git a/src/core/lib/debug/trace.cc b/src/core/lib/debug/trace.cc
index b0e0f2b..01c1e86 100644
--- a/src/core/lib/debug/trace.cc
+++ b/src/core/lib/debug/trace.cc
@@ -55,7 +55,8 @@
         found = true;
       }
     }
-    if (!found) {
+    // check for unknowns, but ignore "", to allow to GRPC_TRACE=
+    if (!found && 0 != strcmp(name, "")) {
       gpr_log(GPR_ERROR, "Unknown trace var: '%s'", name);
       return false; /* early return */
     }
diff --git a/src/core/lib/debug/trace.h b/src/core/lib/debug/trace.h
index bfec92c..28157c6 100644
--- a/src/core/lib/debug/trace.h
+++ b/src/core/lib/debug/trace.h
@@ -57,13 +57,22 @@
 
   const char* name() const { return name_; }
 
+// This following define may be commented out to ensure that the compiler
+// deletes any "if (tracer.enabled()) {...}" codeblocks. This is useful to
+// test the performance impact tracers have on the system.
+//
+// #define COMPILE_OUT_ALL_TRACERS_IN_OPT_BUILD
+#ifdef COMPILE_OUT_ALL_TRACERS_IN_OPT_BUILD
+  bool enabled() { return false; }
+#else
   bool enabled() {
 #ifdef GRPC_THREADSAFE_TRACER
     return gpr_atm_no_barrier_load(&value_) != 0;
 #else
     return value_;
-#endif
+#endif  // GRPC_THREADSAFE_TRACER
   }
+#endif  // COMPILE_OUT_ALL_TRACERS_IN_OPT_BUILD
 
  private:
   friend void grpc_core::testing::grpc_tracer_enable_flag(TraceFlag* flag);
diff --git a/src/core/lib/gpr/log.cc b/src/core/lib/gpr/log.cc
index 72787ab..01ef112 100644
--- a/src/core/lib/gpr/log.cc
+++ b/src/core/lib/gpr/log.cc
@@ -44,10 +44,16 @@
   GPR_UNREACHABLE_CODE(return "UNKNOWN");
 }
 
+int gpr_should_log(gpr_log_severity severity) {
+  return static_cast<gpr_atm>(severity) >=
+                 gpr_atm_no_barrier_load(&g_min_severity_to_print)
+             ? 1
+             : 0;
+}
+
 void gpr_log_message(const char* file, int line, gpr_log_severity severity,
                      const char* message) {
-  if (static_cast<gpr_atm>(severity) <
-      gpr_atm_no_barrier_load(&g_min_severity_to_print)) {
+  if (gpr_should_log(severity) == 0) {
     return;
   }
 
diff --git a/src/core/lib/gpr/log_android.cc b/src/core/lib/gpr/log_android.cc
index 0d3ac0f..40ef4c6 100644
--- a/src/core/lib/gpr/log_android.cc
+++ b/src/core/lib/gpr/log_android.cc
@@ -41,6 +41,10 @@
 
 void gpr_log(const char* file, int line, gpr_log_severity severity,
              const char* format, ...) {
+  /* Avoid message construction if gpr_log_message won't log */
+  if (gpr_should_log(severity) == 0) {
+    return;
+  }
   char* message = NULL;
   va_list args;
   va_start(args, format);
diff --git a/src/core/lib/gpr/log_linux.cc b/src/core/lib/gpr/log_linux.cc
index e4417d9..561276f 100644
--- a/src/core/lib/gpr/log_linux.cc
+++ b/src/core/lib/gpr/log_linux.cc
@@ -44,6 +44,10 @@
 
 void gpr_log(const char* file, int line, gpr_log_severity severity,
              const char* format, ...) {
+  /* Avoid message construction if gpr_log_message won't log */
+  if (gpr_should_log(severity) == 0) {
+    return;
+  }
   char* message = nullptr;
   va_list args;
   va_start(args, format);
diff --git a/src/core/lib/gpr/log_posix.cc b/src/core/lib/gpr/log_posix.cc
index 6f93cde..0acb225 100644
--- a/src/core/lib/gpr/log_posix.cc
+++ b/src/core/lib/gpr/log_posix.cc
@@ -34,6 +34,10 @@
 
 void gpr_log(const char* file, int line, gpr_log_severity severity,
              const char* format, ...) {
+  /* Avoid message construction if gpr_log_message won't log */
+  if (gpr_should_log(severity) == 0) {
+    return;
+  }
   char buf[64];
   char* allocated = nullptr;
   char* message = nullptr;
diff --git a/src/core/lib/gpr/log_windows.cc b/src/core/lib/gpr/log_windows.cc
index caaa973..060be57 100644
--- a/src/core/lib/gpr/log_windows.cc
+++ b/src/core/lib/gpr/log_windows.cc
@@ -34,6 +34,11 @@
 
 void gpr_log(const char* file, int line, gpr_log_severity severity,
              const char* format, ...) {
+  /* Avoid message construction if gpr_log_message won't log */
+  if (gpr_should_log(severity) == 0) {
+    return;
+  }
+
   char* message = NULL;
   va_list args;
   int ret;
diff --git a/src/core/lib/gprpp/inlined_vector.h b/src/core/lib/gprpp/inlined_vector.h
index ca95aec..f36f6cb 100644
--- a/src/core/lib/gprpp/inlined_vector.h
+++ b/src/core/lib/gprpp/inlined_vector.h
@@ -54,43 +54,43 @@
   InlinedVector(const InlinedVector&) = delete;
   InlinedVector& operator=(const InlinedVector&) = delete;
 
+  T* data() {
+    return dynamic_ != nullptr ? dynamic_ : reinterpret_cast<T*>(inline_);
+  }
+
+  const T* data() const {
+    return dynamic_ != nullptr ? dynamic_ : reinterpret_cast<const T*>(inline_);
+  }
+
   T& operator[](size_t offset) {
     assert(offset < size_);
-    if (offset < N) {
-      return *reinterpret_cast<T*>(inline_ + offset);
-    } else {
-      return dynamic_[offset - N];
-    }
+    return data()[offset];
   }
 
   const T& operator[](size_t offset) const {
     assert(offset < size_);
-    if (offset < N) {
-      return *reinterpret_cast<const T*>(inline_ + offset);
-    } else {
-      return dynamic_[offset - N];
+    return data()[offset];
+  }
+
+  void reserve(size_t capacity) {
+    if (capacity > capacity_) {
+      T* new_dynamic = static_cast<T*>(gpr_malloc(sizeof(T) * capacity));
+      for (size_t i = 0; i < size_; ++i) {
+        new (&new_dynamic[i]) T(std::move(data()[i]));
+        data()[i].~T();
+      }
+      gpr_free(dynamic_);
+      dynamic_ = new_dynamic;
+      capacity_ = capacity;
     }
   }
 
   template <typename... Args>
   void emplace_back(Args&&... args) {
-    if (size_ < N) {
-      new (&inline_[size_]) T(std::forward<Args>(args)...);
-    } else {
-      if (size_ - N == dynamic_capacity_) {
-        size_t new_capacity =
-            dynamic_capacity_ == 0 ? 2 : dynamic_capacity_ * 2;
-        T* new_dynamic = static_cast<T*>(gpr_malloc(sizeof(T) * new_capacity));
-        for (size_t i = 0; i < dynamic_capacity_; ++i) {
-          new (&new_dynamic[i]) T(std::move(dynamic_[i]));
-          dynamic_[i].~T();
-        }
-        gpr_free(dynamic_);
-        dynamic_ = new_dynamic;
-        dynamic_capacity_ = new_capacity;
-      }
-      new (&dynamic_[size_ - N]) T(std::forward<Args>(args)...);
+    if (size_ == capacity_) {
+      reserve(capacity_ * 2);
     }
+    new (&(data()[size_])) T(std::forward<Args>(args)...);
     ++size_;
   }
 
@@ -99,6 +99,7 @@
   void push_back(T&& value) { emplace_back(std::move(value)); }
 
   size_t size() const { return size_; }
+  size_t capacity() const { return capacity_; }
 
   void clear() {
     destroy_elements();
@@ -109,26 +110,21 @@
   void init_data() {
     dynamic_ = nullptr;
     size_ = 0;
-    dynamic_capacity_ = 0;
+    capacity_ = N;
   }
 
   void destroy_elements() {
-    for (size_t i = 0; i < size_ && i < N; ++i) {
-      T& value = *reinterpret_cast<T*>(inline_ + i);
+    for (size_t i = 0; i < size_; ++i) {
+      T& value = data()[i];
       value.~T();
     }
-    if (size_ > N) {  // Avoid subtracting two signed values.
-      for (size_t i = 0; i < size_ - N; ++i) {
-        dynamic_[i].~T();
-      }
-    }
     gpr_free(dynamic_);
   }
 
   typename std::aligned_storage<sizeof(T)>::type inline_[N];
   T* dynamic_;
   size_t size_;
-  size_t dynamic_capacity_;
+  size_t capacity_;
 };
 
 }  // namespace grpc_core
diff --git a/src/core/lib/gprpp/orphanable.h b/src/core/lib/gprpp/orphanable.h
index a5bc8d8..73a7399 100644
--- a/src/core/lib/gprpp/orphanable.h
+++ b/src/core/lib/gprpp/orphanable.h
@@ -100,7 +100,7 @@
 
   void Unref() {
     if (gpr_unref(&refs_)) {
-      Delete(this);
+      Delete(static_cast<Child*>(this));
     }
   }
 
@@ -159,7 +159,7 @@
                            const char* reason) GRPC_MUST_USE_RESULT {
     if (location.Log() && trace_flag_ != nullptr && trace_flag_->enabled()) {
       gpr_atm old_refs = gpr_atm_no_barrier_load(&refs_.count);
-      gpr_log(GPR_DEBUG, "%s:%p %s:%d ref %" PRIdPTR " -> %" PRIdPTR " %s",
+      gpr_log(GPR_INFO, "%s:%p %s:%d ref %" PRIdPTR " -> %" PRIdPTR " %s",
               trace_flag_->name(), this, location.file(), location.line(),
               old_refs, old_refs + 1, reason);
     }
@@ -173,14 +173,14 @@
 
   void Unref() {
     if (gpr_unref(&refs_)) {
-      Delete(this);
+      Delete(static_cast<Child*>(this));
     }
   }
 
   void Unref(const DebugLocation& location, const char* reason) {
     if (location.Log() && trace_flag_ != nullptr && trace_flag_->enabled()) {
       gpr_atm old_refs = gpr_atm_no_barrier_load(&refs_.count);
-      gpr_log(GPR_DEBUG, "%s:%p %s:%d unref %" PRIdPTR " -> %" PRIdPTR " %s",
+      gpr_log(GPR_INFO, "%s:%p %s:%d unref %" PRIdPTR " -> %" PRIdPTR " %s",
               trace_flag_->name(), this, location.file(), location.line(),
               old_refs, old_refs - 1, reason);
     }
diff --git a/src/core/lib/gprpp/ref_counted.h b/src/core/lib/gprpp/ref_counted.h
index 46bfaf7..c67e3f3 100644
--- a/src/core/lib/gprpp/ref_counted.h
+++ b/src/core/lib/gprpp/ref_counted.h
@@ -54,7 +54,7 @@
   // friend of this class.
   void Unref() {
     if (gpr_unref(&refs_)) {
-      Delete(this);
+      Delete(static_cast<Child*>(this));
     }
   }
 
@@ -100,7 +100,7 @@
                            const char* reason) GRPC_MUST_USE_RESULT {
     if (location.Log() && trace_flag_ != nullptr && trace_flag_->enabled()) {
       gpr_atm old_refs = gpr_atm_no_barrier_load(&refs_.count);
-      gpr_log(GPR_DEBUG, "%s:%p %s:%d ref %" PRIdPTR " -> %" PRIdPTR " %s",
+      gpr_log(GPR_INFO, "%s:%p %s:%d ref %" PRIdPTR " -> %" PRIdPTR " %s",
               trace_flag_->name(), this, location.file(), location.line(),
               old_refs, old_refs + 1, reason);
     }
@@ -114,14 +114,14 @@
 
   void Unref() {
     if (gpr_unref(&refs_)) {
-      Delete(this);
+      Delete(static_cast<Child*>(this));
     }
   }
 
   void Unref(const DebugLocation& location, const char* reason) {
     if (location.Log() && trace_flag_ != nullptr && trace_flag_->enabled()) {
       gpr_atm old_refs = gpr_atm_no_barrier_load(&refs_.count);
-      gpr_log(GPR_DEBUG, "%s:%p %s:%d unref %" PRIdPTR " -> %" PRIdPTR " %s",
+      gpr_log(GPR_INFO, "%s:%p %s:%d unref %" PRIdPTR " -> %" PRIdPTR " %s",
               trace_flag_->name(), this, location.file(), location.line(),
               old_refs, old_refs - 1, reason);
     }
diff --git a/src/core/lib/http/httpcli_security_connector.cc b/src/core/lib/http/httpcli_security_connector.cc
index 0b53d63..50078c3 100644
--- a/src/core/lib/http/httpcli_security_connector.cc
+++ b/src/core/lib/http/httpcli_security_connector.cc
@@ -32,7 +32,6 @@
 #include "src/core/lib/security/transport/security_handshaker.h"
 #include "src/core/lib/slice/slice_internal.h"
 #include "src/core/tsi/ssl_transport_security.h"
-#include "src/core/tsi/transport_security_adapter.h"
 
 typedef struct {
   grpc_channel_security_connector base;
@@ -65,8 +64,7 @@
     }
   }
   grpc_handshake_manager_add(
-      handshake_mgr, grpc_security_handshaker_create(
-                         tsi_create_adapter_handshaker(handshaker), &sc->base));
+      handshake_mgr, grpc_security_handshaker_create(handshaker, &sc->base));
 }
 
 static void httpcli_ssl_check_peer(grpc_security_connector* sc, tsi_peer peer,
diff --git a/src/core/lib/iomgr/call_combiner.cc b/src/core/lib/iomgr/call_combiner.cc
index 24e11b6..00a839b 100644
--- a/src/core/lib/iomgr/call_combiner.cc
+++ b/src/core/lib/iomgr/call_combiner.cc
@@ -64,7 +64,7 @@
                               const char* reason) {
   GPR_TIMER_SCOPE("call_combiner_start", 0);
   if (grpc_call_combiner_trace.enabled()) {
-    gpr_log(GPR_DEBUG,
+    gpr_log(GPR_INFO,
             "==> grpc_call_combiner_start() [%p] closure=%p [" DEBUG_FMT_STR
             "%s] error=%s",
             call_combiner, closure DEBUG_FMT_ARGS, reason,
@@ -73,7 +73,7 @@
   size_t prev_size = static_cast<size_t>(
       gpr_atm_full_fetch_add(&call_combiner->size, (gpr_atm)1));
   if (grpc_call_combiner_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "  size: %" PRIdPTR " -> %" PRIdPTR, prev_size,
+    gpr_log(GPR_INFO, "  size: %" PRIdPTR " -> %" PRIdPTR, prev_size,
             prev_size + 1);
   }
   GRPC_STATS_INC_CALL_COMBINER_LOCKS_SCHEDULED_ITEMS();
@@ -82,7 +82,7 @@
 
     GPR_TIMER_MARK("call_combiner_initiate", 0);
     if (grpc_call_combiner_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "  EXECUTING IMMEDIATELY");
+      gpr_log(GPR_INFO, "  EXECUTING IMMEDIATELY");
     }
     // Queue was empty, so execute this closure immediately.
     GRPC_CLOSURE_SCHED(closure, error);
@@ -101,21 +101,21 @@
                              const char* reason) {
   GPR_TIMER_SCOPE("call_combiner_stop", 0);
   if (grpc_call_combiner_trace.enabled()) {
-    gpr_log(GPR_DEBUG,
+    gpr_log(GPR_INFO,
             "==> grpc_call_combiner_stop() [%p] [" DEBUG_FMT_STR "%s]",
             call_combiner DEBUG_FMT_ARGS, reason);
   }
   size_t prev_size = static_cast<size_t>(
       gpr_atm_full_fetch_add(&call_combiner->size, (gpr_atm)-1));
   if (grpc_call_combiner_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "  size: %" PRIdPTR " -> %" PRIdPTR, prev_size,
+    gpr_log(GPR_INFO, "  size: %" PRIdPTR " -> %" PRIdPTR, prev_size,
             prev_size - 1);
   }
   GPR_ASSERT(prev_size >= 1);
   if (prev_size > 1) {
     while (true) {
       if (grpc_call_combiner_trace.enabled()) {
-        gpr_log(GPR_DEBUG, "  checking queue");
+        gpr_log(GPR_INFO, "  checking queue");
       }
       bool empty;
       grpc_closure* closure = reinterpret_cast<grpc_closure*>(
@@ -124,19 +124,19 @@
         // This can happen either due to a race condition within the mpscq
         // code or because of a race with grpc_call_combiner_start().
         if (grpc_call_combiner_trace.enabled()) {
-          gpr_log(GPR_DEBUG, "  queue returned no result; checking again");
+          gpr_log(GPR_INFO, "  queue returned no result; checking again");
         }
         continue;
       }
       if (grpc_call_combiner_trace.enabled()) {
-        gpr_log(GPR_DEBUG, "  EXECUTING FROM QUEUE: closure=%p error=%s",
+        gpr_log(GPR_INFO, "  EXECUTING FROM QUEUE: closure=%p error=%s",
                 closure, grpc_error_string(closure->error_data.error));
       }
       GRPC_CLOSURE_SCHED(closure, closure->error_data.error);
       break;
     }
   } else if (grpc_call_combiner_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "  queue empty");
+    gpr_log(GPR_INFO, "  queue empty");
   }
 }
 
@@ -151,7 +151,7 @@
     // Otherwise, store the new closure.
     if (original_error != GRPC_ERROR_NONE) {
       if (grpc_call_combiner_trace.enabled()) {
-        gpr_log(GPR_DEBUG,
+        gpr_log(GPR_INFO,
                 "call_combiner=%p: scheduling notify_on_cancel callback=%p "
                 "for pre-existing cancellation",
                 call_combiner, closure);
@@ -162,7 +162,7 @@
       if (gpr_atm_full_cas(&call_combiner->cancel_state, original_state,
                            (gpr_atm)closure)) {
         if (grpc_call_combiner_trace.enabled()) {
-          gpr_log(GPR_DEBUG, "call_combiner=%p: setting notify_on_cancel=%p",
+          gpr_log(GPR_INFO, "call_combiner=%p: setting notify_on_cancel=%p",
                   call_combiner, closure);
         }
         // If we replaced an earlier closure, invoke the original
@@ -171,7 +171,7 @@
         if (original_state != 0) {
           closure = (grpc_closure*)original_state;
           if (grpc_call_combiner_trace.enabled()) {
-            gpr_log(GPR_DEBUG,
+            gpr_log(GPR_INFO,
                     "call_combiner=%p: scheduling old cancel callback=%p",
                     call_combiner, closure);
           }
@@ -199,7 +199,7 @@
       if (original_state != 0) {
         grpc_closure* notify_on_cancel = (grpc_closure*)original_state;
         if (grpc_call_combiner_trace.enabled()) {
-          gpr_log(GPR_DEBUG,
+          gpr_log(GPR_INFO,
                   "call_combiner=%p: scheduling notify_on_cancel callback=%p",
                   call_combiner, notify_on_cancel);
         }
diff --git a/src/core/lib/iomgr/closure.h b/src/core/lib/iomgr/closure.h
index 64527d6..34a4944 100644
--- a/src/core/lib/iomgr/closure.h
+++ b/src/core/lib/iomgr/closure.h
@@ -253,8 +253,8 @@
     c->file_initiated = file;
     c->line_initiated = line;
     c->run = true;
+    GPR_ASSERT(c->cb != nullptr);
 #endif
-    assert(c->cb);
     c->scheduler->vtable->run(c, error);
   } else {
     GRPC_ERROR_UNREF(error);
@@ -292,8 +292,8 @@
     c->file_initiated = file;
     c->line_initiated = line;
     c->run = false;
+    GPR_ASSERT(c->cb != nullptr);
 #endif
-    assert(c->cb);
     c->scheduler->vtable->sched(c, error);
   } else {
     GRPC_ERROR_UNREF(error);
@@ -330,8 +330,8 @@
     c->file_initiated = file;
     c->line_initiated = line;
     c->run = false;
+    GPR_ASSERT(c->cb != nullptr);
 #endif
-    assert(c->cb);
     c->scheduler->vtable->sched(c, c->error_data.error);
     c = next;
   }
diff --git a/src/core/lib/iomgr/combiner.cc b/src/core/lib/iomgr/combiner.cc
index e66df03..9429842 100644
--- a/src/core/lib/iomgr/combiner.cc
+++ b/src/core/lib/iomgr/combiner.cc
@@ -83,12 +83,12 @@
   grpc_closure_list_init(&lock->final_list);
   GRPC_CLOSURE_INIT(&lock->offload, offload, lock,
                     grpc_executor_scheduler(GRPC_EXECUTOR_SHORT));
-  GRPC_COMBINER_TRACE(gpr_log(GPR_DEBUG, "C:%p create", lock));
+  GRPC_COMBINER_TRACE(gpr_log(GPR_INFO, "C:%p create", lock));
   return lock;
 }
 
 static void really_destroy(grpc_combiner* lock) {
-  GRPC_COMBINER_TRACE(gpr_log(GPR_DEBUG, "C:%p really_destroy", lock));
+  GRPC_COMBINER_TRACE(gpr_log(GPR_INFO, "C:%p really_destroy", lock));
   GPR_ASSERT(gpr_atm_no_barrier_load(&lock->state) == 0);
   gpr_mpscq_destroy(&lock->queue);
   gpr_free(lock);
@@ -97,7 +97,7 @@
 static void start_destroy(grpc_combiner* lock) {
   gpr_atm old_state = gpr_atm_full_fetch_add(&lock->state, -STATE_UNORPHANED);
   GRPC_COMBINER_TRACE(gpr_log(
-      GPR_DEBUG, "C:%p really_destroy old_state=%" PRIdPTR, lock, old_state));
+      GPR_INFO, "C:%p really_destroy old_state=%" PRIdPTR, lock, old_state));
   if (old_state == 1) {
     really_destroy(lock);
   }
@@ -159,7 +159,7 @@
   GRPC_STATS_INC_COMBINER_LOCKS_SCHEDULED_ITEMS();
   grpc_combiner* lock = COMBINER_FROM_CLOSURE_SCHEDULER(cl, scheduler);
   gpr_atm last = gpr_atm_full_fetch_add(&lock->state, STATE_ELEM_COUNT_LOW_BIT);
-  GRPC_COMBINER_TRACE(gpr_log(GPR_DEBUG,
+  GRPC_COMBINER_TRACE(gpr_log(GPR_INFO,
                               "C:%p grpc_combiner_execute c=%p last=%" PRIdPTR,
                               lock, cl, last));
   if (last == 1) {
@@ -203,7 +203,7 @@
 static void queue_offload(grpc_combiner* lock) {
   GRPC_STATS_INC_COMBINER_LOCKS_OFFLOADED();
   move_next();
-  GRPC_COMBINER_TRACE(gpr_log(GPR_DEBUG, "C:%p queue_offload", lock));
+  GRPC_COMBINER_TRACE(gpr_log(GPR_INFO, "C:%p queue_offload", lock));
   GRPC_CLOSURE_SCHED(&lock->offload, GRPC_ERROR_NONE);
 }
 
@@ -218,7 +218,7 @@
   bool contended =
       gpr_atm_no_barrier_load(&lock->initiating_exec_ctx_or_null) == 0;
 
-  GRPC_COMBINER_TRACE(gpr_log(GPR_DEBUG,
+  GRPC_COMBINER_TRACE(gpr_log(GPR_INFO,
                               "C:%p grpc_combiner_continue_exec_ctx "
                               "contended=%d "
                               "exec_ctx_ready_to_finish=%d "
@@ -242,7 +242,7 @@
       (gpr_atm_acq_load(&lock->state) >> 1) > 1) {
     gpr_mpscq_node* n = gpr_mpscq_pop(&lock->queue);
     GRPC_COMBINER_TRACE(
-        gpr_log(GPR_DEBUG, "C:%p maybe_finish_one n=%p", lock, n));
+        gpr_log(GPR_INFO, "C:%p maybe_finish_one n=%p", lock, n));
     if (n == nullptr) {
       // queue is in an inconsistent state: use this as a cue that we should
       // go off and do something else for a while (and come back later)
@@ -266,7 +266,7 @@
     while (c != nullptr) {
       GPR_TIMER_SCOPE("combiner.exec_1final", 0);
       GRPC_COMBINER_TRACE(
-          gpr_log(GPR_DEBUG, "C:%p execute_final[%d] c=%p", lock, loops, c));
+          gpr_log(GPR_INFO, "C:%p execute_final[%d] c=%p", lock, loops, c));
       grpc_closure* next = c->next_data.next;
       grpc_error* error = c->error_data.error;
 #ifndef NDEBUG
@@ -284,7 +284,7 @@
   gpr_atm old_state =
       gpr_atm_full_fetch_add(&lock->state, -STATE_ELEM_COUNT_LOW_BIT);
   GRPC_COMBINER_TRACE(
-      gpr_log(GPR_DEBUG, "C:%p finish old_state=%" PRIdPTR, lock, old_state));
+      gpr_log(GPR_INFO, "C:%p finish old_state=%" PRIdPTR, lock, old_state));
 // Define a macro to ease readability of the following switch statement.
 #define OLD_STATE_WAS(orphaned, elem_count) \
   (((orphaned) ? 0 : STATE_UNORPHANED) |    \
@@ -327,8 +327,8 @@
   grpc_combiner* lock =
       COMBINER_FROM_CLOSURE_SCHEDULER(closure, finally_scheduler);
   GRPC_COMBINER_TRACE(gpr_log(
-      GPR_DEBUG, "C:%p grpc_combiner_execute_finally c=%p; ac=%p", lock,
-      closure, grpc_core::ExecCtx::Get()->combiner_data()->active_combiner));
+      GPR_INFO, "C:%p grpc_combiner_execute_finally c=%p; ac=%p", lock, closure,
+      grpc_core::ExecCtx::Get()->combiner_data()->active_combiner));
   if (grpc_core::ExecCtx::Get()->combiner_data()->active_combiner != lock) {
     GPR_TIMER_MARK("slowpath", 0);
     GRPC_CLOSURE_SCHED(GRPC_CLOSURE_CREATE(enqueue_finally, closure,
diff --git a/src/core/lib/iomgr/ev_epoll1_linux.cc b/src/core/lib/iomgr/ev_epoll1_linux.cc
index 3ebaf18..e5db1be 100644
--- a/src/core/lib/iomgr/ev_epoll1_linux.cc
+++ b/src/core/lib/iomgr/ev_epoll1_linux.cc
@@ -658,7 +658,7 @@
   GRPC_STATS_INC_POLL_EVENTS_RETURNED(r);
 
   if (grpc_polling_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "ps: %p poll got %d events", ps, r);
+    gpr_log(GPR_INFO, "ps: %p poll got %d events", ps, r);
   }
 
   gpr_atm_rel_store(&g_epoll_set.num_events, r);
@@ -678,7 +678,7 @@
   pollset->begin_refs++;
 
   if (grpc_polling_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "PS:%p BEGIN_STARTS:%p", pollset, worker);
+    gpr_log(GPR_INFO, "PS:%p BEGIN_STARTS:%p", pollset, worker);
   }
 
   if (pollset->seen_inactive) {
@@ -697,7 +697,7 @@
     gpr_mu_lock(&neighborhood->mu);
     gpr_mu_lock(&pollset->mu);
     if (grpc_polling_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "PS:%p BEGIN_REORG:%p kick_state=%s is_reassigning=%d",
+      gpr_log(GPR_INFO, "PS:%p BEGIN_REORG:%p kick_state=%s is_reassigning=%d",
               pollset, worker, kick_state_string(worker->state),
               is_reassigning);
     }
@@ -749,7 +749,7 @@
     gpr_cv_init(&worker->cv);
     while (worker->state == UNKICKED && !pollset->shutting_down) {
       if (grpc_polling_trace.enabled()) {
-        gpr_log(GPR_DEBUG, "PS:%p BEGIN_WAIT:%p kick_state=%s shutdown=%d",
+        gpr_log(GPR_INFO, "PS:%p BEGIN_WAIT:%p kick_state=%s shutdown=%d",
                 pollset, worker, kick_state_string(worker->state),
                 pollset->shutting_down);
       }
@@ -766,7 +766,7 @@
   }
 
   if (grpc_polling_trace.enabled()) {
-    gpr_log(GPR_DEBUG,
+    gpr_log(GPR_INFO,
             "PS:%p BEGIN_DONE:%p kick_state=%s shutdown=%d "
             "kicked_without_poller: %d",
             pollset, worker, kick_state_string(worker->state),
@@ -809,7 +809,7 @@
             if (gpr_atm_no_barrier_cas(&g_active_poller, 0,
                                        (gpr_atm)inspect_worker)) {
               if (grpc_polling_trace.enabled()) {
-                gpr_log(GPR_DEBUG, " .. choose next poller to be %p",
+                gpr_log(GPR_INFO, " .. choose next poller to be %p",
                         inspect_worker);
               }
               SET_KICK_STATE(inspect_worker, DESIGNATED_POLLER);
@@ -820,7 +820,7 @@
               }
             } else {
               if (grpc_polling_trace.enabled()) {
-                gpr_log(GPR_DEBUG, " .. beaten to choose next poller");
+                gpr_log(GPR_INFO, " .. beaten to choose next poller");
               }
             }
             // even if we didn't win the cas, there's a worker, we can stop
@@ -838,7 +838,7 @@
     }
     if (!found_worker) {
       if (grpc_polling_trace.enabled()) {
-        gpr_log(GPR_DEBUG, " .. mark pollset %p inactive", inspect);
+        gpr_log(GPR_INFO, " .. mark pollset %p inactive", inspect);
       }
       inspect->seen_inactive = true;
       if (inspect == neighborhood->active_root) {
@@ -858,7 +858,7 @@
                        grpc_pollset_worker** worker_hdl) {
   GPR_TIMER_SCOPE("end_worker", 0);
   if (grpc_polling_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "PS:%p END_WORKER:%p", pollset, worker);
+    gpr_log(GPR_INFO, "PS:%p END_WORKER:%p", pollset, worker);
   }
   if (worker_hdl != nullptr) *worker_hdl = nullptr;
   /* Make sure we appear kicked */
@@ -868,7 +868,7 @@
   if (gpr_atm_no_barrier_load(&g_active_poller) == (gpr_atm)worker) {
     if (worker->next != worker && worker->next->state == UNKICKED) {
       if (grpc_polling_trace.enabled()) {
-        gpr_log(GPR_DEBUG, " .. choose next poller to be peer %p", worker);
+        gpr_log(GPR_INFO, " .. choose next poller to be peer %p", worker);
       }
       GPR_ASSERT(worker->next->initialized_cv);
       gpr_atm_no_barrier_store(&g_active_poller, (gpr_atm)worker->next);
@@ -920,7 +920,7 @@
     gpr_cv_destroy(&worker->cv);
   }
   if (grpc_polling_trace.enabled()) {
-    gpr_log(GPR_DEBUG, " .. remove worker");
+    gpr_log(GPR_INFO, " .. remove worker");
   }
   if (EMPTIED == worker_remove(pollset, worker)) {
     pollset_maybe_finish_shutdown(pollset);
@@ -1022,7 +1022,7 @@
         GRPC_STATS_INC_POLLSET_KICKED_WITHOUT_POLLER();
         pollset->kicked_without_poller = true;
         if (grpc_polling_trace.enabled()) {
-          gpr_log(GPR_DEBUG, " .. kicked_without_poller");
+          gpr_log(GPR_INFO, " .. kicked_without_poller");
         }
         goto done;
       }
@@ -1030,14 +1030,14 @@
       if (root_worker->state == KICKED) {
         GRPC_STATS_INC_POLLSET_KICKED_AGAIN();
         if (grpc_polling_trace.enabled()) {
-          gpr_log(GPR_DEBUG, " .. already kicked %p", root_worker);
+          gpr_log(GPR_INFO, " .. already kicked %p", root_worker);
         }
         SET_KICK_STATE(root_worker, KICKED);
         goto done;
       } else if (next_worker->state == KICKED) {
         GRPC_STATS_INC_POLLSET_KICKED_AGAIN();
         if (grpc_polling_trace.enabled()) {
-          gpr_log(GPR_DEBUG, " .. already kicked %p", next_worker);
+          gpr_log(GPR_INFO, " .. already kicked %p", next_worker);
         }
         SET_KICK_STATE(next_worker, KICKED);
         goto done;
@@ -1048,7 +1048,7 @@
                                     &g_active_poller)) {
         GRPC_STATS_INC_POLLSET_KICK_WAKEUP_FD();
         if (grpc_polling_trace.enabled()) {
-          gpr_log(GPR_DEBUG, " .. kicked %p", root_worker);
+          gpr_log(GPR_INFO, " .. kicked %p", root_worker);
         }
         SET_KICK_STATE(root_worker, KICKED);
         ret_err = grpc_wakeup_fd_wakeup(&global_wakeup_fd);
@@ -1056,7 +1056,7 @@
       } else if (next_worker->state == UNKICKED) {
         GRPC_STATS_INC_POLLSET_KICK_WAKEUP_CV();
         if (grpc_polling_trace.enabled()) {
-          gpr_log(GPR_DEBUG, " .. kicked %p", next_worker);
+          gpr_log(GPR_INFO, " .. kicked %p", next_worker);
         }
         GPR_ASSERT(next_worker->initialized_cv);
         SET_KICK_STATE(next_worker, KICKED);
@@ -1066,7 +1066,7 @@
         if (root_worker->state != DESIGNATED_POLLER) {
           if (grpc_polling_trace.enabled()) {
             gpr_log(
-                GPR_DEBUG,
+                GPR_INFO,
                 " .. kicked root non-poller %p (initialized_cv=%d) (poller=%p)",
                 root_worker, root_worker->initialized_cv, next_worker);
           }
@@ -1079,7 +1079,7 @@
         } else {
           GRPC_STATS_INC_POLLSET_KICK_WAKEUP_FD();
           if (grpc_polling_trace.enabled()) {
-            gpr_log(GPR_DEBUG, " .. non-root poller %p (root=%p)", next_worker,
+            gpr_log(GPR_INFO, " .. non-root poller %p (root=%p)", next_worker,
                     root_worker);
           }
           SET_KICK_STATE(next_worker, KICKED);
@@ -1095,7 +1095,7 @@
     } else {
       GRPC_STATS_INC_POLLSET_KICK_OWN_THREAD();
       if (grpc_polling_trace.enabled()) {
-        gpr_log(GPR_DEBUG, " .. kicked while waking up");
+        gpr_log(GPR_INFO, " .. kicked while waking up");
       }
       goto done;
     }
@@ -1105,14 +1105,14 @@
 
   if (specific_worker->state == KICKED) {
     if (grpc_polling_trace.enabled()) {
-      gpr_log(GPR_DEBUG, " .. specific worker already kicked");
+      gpr_log(GPR_INFO, " .. specific worker already kicked");
     }
     goto done;
   } else if (gpr_tls_get(&g_current_thread_worker) ==
              (intptr_t)specific_worker) {
     GRPC_STATS_INC_POLLSET_KICK_OWN_THREAD();
     if (grpc_polling_trace.enabled()) {
-      gpr_log(GPR_DEBUG, " .. mark %p kicked", specific_worker);
+      gpr_log(GPR_INFO, " .. mark %p kicked", specific_worker);
     }
     SET_KICK_STATE(specific_worker, KICKED);
     goto done;
@@ -1120,7 +1120,7 @@
              (grpc_pollset_worker*)gpr_atm_no_barrier_load(&g_active_poller)) {
     GRPC_STATS_INC_POLLSET_KICK_WAKEUP_FD();
     if (grpc_polling_trace.enabled()) {
-      gpr_log(GPR_DEBUG, " .. kick active poller");
+      gpr_log(GPR_INFO, " .. kick active poller");
     }
     SET_KICK_STATE(specific_worker, KICKED);
     ret_err = grpc_wakeup_fd_wakeup(&global_wakeup_fd);
@@ -1128,7 +1128,7 @@
   } else if (specific_worker->initialized_cv) {
     GRPC_STATS_INC_POLLSET_KICK_WAKEUP_CV();
     if (grpc_polling_trace.enabled()) {
-      gpr_log(GPR_DEBUG, " .. kick waiting worker");
+      gpr_log(GPR_INFO, " .. kick waiting worker");
     }
     SET_KICK_STATE(specific_worker, KICKED);
     gpr_cv_signal(&specific_worker->cv);
@@ -1136,7 +1136,7 @@
   } else {
     GRPC_STATS_INC_POLLSET_KICKED_AGAIN();
     if (grpc_polling_trace.enabled()) {
-      gpr_log(GPR_DEBUG, " .. kick non-waiting worker");
+      gpr_log(GPR_INFO, " .. kick non-waiting worker");
     }
     SET_KICK_STATE(specific_worker, KICKED);
     goto done;
diff --git a/src/core/lib/iomgr/ev_epollex_linux.cc b/src/core/lib/iomgr/ev_epollex_linux.cc
index 0ef7c03..65f1c91 100644
--- a/src/core/lib/iomgr/ev_epollex_linux.cc
+++ b/src/core/lib/iomgr/ev_epollex_linux.cc
@@ -59,7 +59,10 @@
 //#define GRPC_EPOLLEX_CREATE_WORKERS_ON_HEAP 1
 
 #define MAX_EPOLL_EVENTS 100
-#define MAX_EPOLL_EVENTS_HANDLED_EACH_POLL_CALL 1
+// TODO(juanlishen): We use a greater-than-one value here as a workaround fix to
+// a keepalive ping timeout issue. We may want to revert https://github
+// .com/grpc/grpc/pull/14943 once we figure out the root cause.
+#define MAX_EPOLL_EVENTS_HANDLED_EACH_POLL_CALL 16
 
 grpc_core::DebugOnlyTraceFlag grpc_trace_pollable_refcount(false,
                                                            "pollable_refcount");
@@ -198,6 +201,7 @@
 
 struct grpc_pollset {
   gpr_mu mu;
+  gpr_atm worker_count;
   pollable* active_pollable;
   bool kicked_without_poller;
   grpc_closure* shutdown_closure;
@@ -514,7 +518,7 @@
   const int epfd = p->epfd;
 
   if (grpc_polling_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "add fd %p (%d) to pollable %p", fd, fd->fd, p);
+    gpr_log(GPR_INFO, "add fd %p (%d) to pollable %p", fd, fd->fd, p);
   }
 
   struct epoll_event ev_fd;
@@ -556,7 +560,7 @@
 /* pollset->mu must be held while calling this function */
 static void pollset_maybe_finish_shutdown(grpc_pollset* pollset) {
   if (grpc_polling_trace.enabled()) {
-    gpr_log(GPR_DEBUG,
+    gpr_log(GPR_INFO,
             "PS:%p (pollable:%p) maybe_finish_shutdown sc=%p (target:!NULL) "
             "rw=%p (target:NULL) cpsc=%d (target:0)",
             pollset, pollset->active_pollable, pollset->shutdown_closure,
@@ -581,14 +585,14 @@
   GPR_ASSERT(specific_worker != nullptr);
   if (specific_worker->kicked) {
     if (grpc_polling_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "PS:%p kicked_specific_but_already_kicked", p);
+      gpr_log(GPR_INFO, "PS:%p kicked_specific_but_already_kicked", p);
     }
     GRPC_STATS_INC_POLLSET_KICKED_AGAIN();
     return GRPC_ERROR_NONE;
   }
   if (gpr_tls_get(&g_current_thread_worker) == (intptr_t)specific_worker) {
     if (grpc_polling_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "PS:%p kicked_specific_but_awake", p);
+      gpr_log(GPR_INFO, "PS:%p kicked_specific_but_awake", p);
     }
     GRPC_STATS_INC_POLLSET_KICK_OWN_THREAD();
     specific_worker->kicked = true;
@@ -597,7 +601,7 @@
   if (specific_worker == p->root_worker) {
     GRPC_STATS_INC_POLLSET_KICK_WAKEUP_FD();
     if (grpc_polling_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "PS:%p kicked_specific_via_wakeup_fd", p);
+      gpr_log(GPR_INFO, "PS:%p kicked_specific_via_wakeup_fd", p);
     }
     specific_worker->kicked = true;
     grpc_error* error = grpc_wakeup_fd_wakeup(&p->wakeup);
@@ -606,7 +610,7 @@
   if (specific_worker->initialized_cv) {
     GRPC_STATS_INC_POLLSET_KICK_WAKEUP_CV();
     if (grpc_polling_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "PS:%p kicked_specific_via_cv", p);
+      gpr_log(GPR_INFO, "PS:%p kicked_specific_via_cv", p);
     }
     specific_worker->kicked = true;
     gpr_cv_signal(&specific_worker->cv);
@@ -622,7 +626,7 @@
   GPR_TIMER_SCOPE("pollset_kick", 0);
   GRPC_STATS_INC_POLLSET_KICK();
   if (grpc_polling_trace.enabled()) {
-    gpr_log(GPR_DEBUG,
+    gpr_log(GPR_INFO,
             "PS:%p kick %p tls_pollset=%p tls_worker=%p pollset.root_worker=%p",
             pollset, specific_worker,
             (void*)gpr_tls_get(&g_current_thread_pollset),
@@ -632,7 +636,7 @@
     if (gpr_tls_get(&g_current_thread_pollset) != (intptr_t)pollset) {
       if (pollset->root_worker == nullptr) {
         if (grpc_polling_trace.enabled()) {
-          gpr_log(GPR_DEBUG, "PS:%p kicked_any_without_poller", pollset);
+          gpr_log(GPR_INFO, "PS:%p kicked_any_without_poller", pollset);
         }
         GRPC_STATS_INC_POLLSET_KICKED_WITHOUT_POLLER();
         pollset->kicked_without_poller = true;
@@ -658,7 +662,7 @@
       }
     } else {
       if (grpc_polling_trace.enabled()) {
-        gpr_log(GPR_DEBUG, "PS:%p kicked_any_but_awake", pollset);
+        gpr_log(GPR_INFO, "PS:%p kicked_any_but_awake", pollset);
       }
       GRPC_STATS_INC_POLLSET_KICK_OWN_THREAD();
       return GRPC_ERROR_NONE;
@@ -685,6 +689,7 @@
 
 static void pollset_init(grpc_pollset* pollset, gpr_mu** mu) {
   gpr_mu_init(&pollset->mu);
+  gpr_atm_no_barrier_store(&pollset->worker_count, 0);
   pollset->active_pollable = POLLABLE_REF(g_empty_pollable, "pollset");
   pollset->kicked_without_poller = false;
   pollset->shutdown_closure = nullptr;
@@ -758,8 +763,20 @@
                                            pollable* pollable_obj, bool drain) {
   GPR_TIMER_SCOPE("pollable_process_events", 0);
   static const char* err_desc = "pollset_process_events";
+  // Use a simple heuristic to determine how many fd events to process
+  // per loop iteration.  (events/workers)
+  int handle_count = 1;
+  int worker_count = gpr_atm_no_barrier_load(&pollset->worker_count);
+  GPR_ASSERT(worker_count > 0);
+  handle_count =
+      (pollable_obj->event_count - pollable_obj->event_cursor) / worker_count;
+  if (handle_count == 0) {
+    handle_count = 1;
+  } else if (handle_count > MAX_EPOLL_EVENTS_HANDLED_EACH_POLL_CALL) {
+    handle_count = MAX_EPOLL_EVENTS_HANDLED_EACH_POLL_CALL;
+  }
   grpc_error* error = GRPC_ERROR_NONE;
-  for (int i = 0; (drain || i < MAX_EPOLL_EVENTS_HANDLED_EACH_POLL_CALL) &&
+  for (int i = 0; (drain || i < handle_count) &&
                   pollable_obj->event_cursor != pollable_obj->event_count;
        i++) {
     int n = pollable_obj->event_cursor++;
@@ -767,7 +784,7 @@
     void* data_ptr = ev->data.ptr;
     if (1 & (intptr_t)data_ptr) {
       if (grpc_polling_trace.enabled()) {
-        gpr_log(GPR_DEBUG, "PS:%p got pollset_wakeup %p", pollset, data_ptr);
+        gpr_log(GPR_INFO, "PS:%p got pollset_wakeup %p", pollset, data_ptr);
       }
       append_error(&error,
                    grpc_wakeup_fd_consume_wakeup(
@@ -780,7 +797,7 @@
       bool read_ev = (ev->events & (EPOLLIN | EPOLLPRI)) != 0;
       bool write_ev = (ev->events & EPOLLOUT) != 0;
       if (grpc_polling_trace.enabled()) {
-        gpr_log(GPR_DEBUG,
+        gpr_log(GPR_INFO,
                 "PS:%p got fd %p: cancel=%d read=%d "
                 "write=%d",
                 pollset, fd, cancel, read_ev, write_ev);
@@ -810,7 +827,7 @@
 
   if (grpc_polling_trace.enabled()) {
     char* desc = pollable_desc(p);
-    gpr_log(GPR_DEBUG, "POLLABLE:%p[%s] poll for %dms", p, desc, timeout);
+    gpr_log(GPR_INFO, "POLLABLE:%p[%s] poll for %dms", p, desc, timeout);
     gpr_free(desc);
   }
 
@@ -829,7 +846,7 @@
   if (r < 0) return GRPC_OS_ERROR(errno, "epoll_wait");
 
   if (grpc_polling_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "POLLABLE:%p got %d events", p, r);
+    gpr_log(GPR_INFO, "POLLABLE:%p got %d events", p, r);
   }
 
   p->event_cursor = 0;
@@ -884,6 +901,7 @@
   GPR_TIMER_SCOPE("begin_worker", 0);
   bool do_poll =
       (pollset->shutdown_closure == nullptr && !pollset->already_shutdown);
+  gpr_atm_no_barrier_fetch_add(&pollset->worker_count, 1);
   if (worker_hdl != nullptr) *worker_hdl = worker;
   worker->initialized_cv = false;
   worker->kicked = false;
@@ -899,7 +917,7 @@
     gpr_mu_unlock(&pollset->mu);
     if (grpc_polling_trace.enabled() &&
         worker->pollable_obj->root_worker != worker) {
-      gpr_log(GPR_DEBUG, "PS:%p wait %p w=%p for %dms", pollset,
+      gpr_log(GPR_INFO, "PS:%p wait %p w=%p for %dms", pollset,
               worker->pollable_obj, worker,
               poll_deadline_to_millis_timeout(deadline));
     }
@@ -907,19 +925,19 @@
       if (gpr_cv_wait(&worker->cv, &worker->pollable_obj->mu,
                       grpc_millis_to_timespec(deadline, GPR_CLOCK_REALTIME))) {
         if (grpc_polling_trace.enabled()) {
-          gpr_log(GPR_DEBUG, "PS:%p timeout_wait %p w=%p", pollset,
+          gpr_log(GPR_INFO, "PS:%p timeout_wait %p w=%p", pollset,
                   worker->pollable_obj, worker);
         }
         do_poll = false;
       } else if (worker->kicked) {
         if (grpc_polling_trace.enabled()) {
-          gpr_log(GPR_DEBUG, "PS:%p wakeup %p w=%p", pollset,
+          gpr_log(GPR_INFO, "PS:%p wakeup %p w=%p", pollset,
                   worker->pollable_obj, worker);
         }
         do_poll = false;
       } else if (grpc_polling_trace.enabled() &&
                  worker->pollable_obj->root_worker != worker) {
-        gpr_log(GPR_DEBUG, "PS:%p spurious_wakeup %p w=%p", pollset,
+        gpr_log(GPR_INFO, "PS:%p spurious_wakeup %p w=%p", pollset,
                 worker->pollable_obj, worker);
       }
     }
@@ -964,6 +982,7 @@
   if (worker->initialized_cv) {
     gpr_cv_destroy(&worker->cv);
   }
+  gpr_atm_no_barrier_fetch_add(&pollset->worker_count, -1);
 }
 
 #ifndef NDEBUG
@@ -990,7 +1009,7 @@
   WORKER_PTR->originator = gettid();
 #endif
   if (grpc_polling_trace.enabled()) {
-    gpr_log(GPR_DEBUG,
+    gpr_log(GPR_INFO,
             "PS:%p work hdl=%p worker=%p now=%" PRIdPTR " deadline=%" PRIdPTR
             " kwp=%d pollable=%p",
             pollset, worker_hdl, WORKER_PTR, grpc_core::ExecCtx::Get()->Now(),
@@ -1031,7 +1050,7 @@
   static const char* err_desc = "pollset_transition_pollable_from_empty_to_fd";
   grpc_error* error = GRPC_ERROR_NONE;
   if (grpc_polling_trace.enabled()) {
-    gpr_log(GPR_DEBUG,
+    gpr_log(GPR_INFO,
             "PS:%p add fd %p (%d); transition pollable from empty to fd",
             pollset, fd, fd->fd);
   }
@@ -1048,7 +1067,7 @@
   grpc_error* error = GRPC_ERROR_NONE;
   if (grpc_polling_trace.enabled()) {
     gpr_log(
-        GPR_DEBUG,
+        GPR_INFO,
         "PS:%p add fd %p (%d); transition pollable from fd %p to multipoller",
         pollset, and_add_fd, and_add_fd ? and_add_fd->fd : -1,
         pollset->active_pollable->owner_fd);
@@ -1118,7 +1137,7 @@
       /* Any workers currently polling on this pollset must now be woked up so
        * that they can pick up the new active_pollable */
       if (grpc_polling_trace.enabled()) {
-        gpr_log(GPR_DEBUG,
+        gpr_log(GPR_INFO,
                 "PS:%p active pollable transition from empty to multi",
                 pollset);
       }
@@ -1205,7 +1224,7 @@
 static void pollset_set_add_fd(grpc_pollset_set* pss, grpc_fd* fd) {
   GPR_TIMER_SCOPE("pollset_set_add_fd", 0);
   if (grpc_polling_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "PSS:%p: add fd %p (%d)", pss, fd, fd->fd);
+    gpr_log(GPR_INFO, "PSS:%p: add fd %p (%d)", pss, fd, fd->fd);
   }
   grpc_error* error = GRPC_ERROR_NONE;
   static const char* err_desc = "pollset_set_add_fd";
@@ -1229,7 +1248,7 @@
 static void pollset_set_del_fd(grpc_pollset_set* pss, grpc_fd* fd) {
   GPR_TIMER_SCOPE("pollset_set_del_fd", 0);
   if (grpc_polling_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "PSS:%p: del fd %p", pss, fd);
+    gpr_log(GPR_INFO, "PSS:%p: del fd %p", pss, fd);
   }
   pss = pss_lock_adam(pss);
   size_t i;
@@ -1250,7 +1269,7 @@
 static void pollset_set_del_pollset(grpc_pollset_set* pss, grpc_pollset* ps) {
   GPR_TIMER_SCOPE("pollset_set_del_pollset", 0);
   if (grpc_polling_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "PSS:%p: del pollset %p", pss, ps);
+    gpr_log(GPR_INFO, "PSS:%p: del pollset %p", pss, ps);
   }
   pss = pss_lock_adam(pss);
   size_t i;
@@ -1302,7 +1321,7 @@
 static void pollset_set_add_pollset(grpc_pollset_set* pss, grpc_pollset* ps) {
   GPR_TIMER_SCOPE("pollset_set_add_pollset", 0);
   if (grpc_polling_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "PSS:%p: add pollset %p", pss, ps);
+    gpr_log(GPR_INFO, "PSS:%p: add pollset %p", pss, ps);
   }
   grpc_error* error = GRPC_ERROR_NONE;
   static const char* err_desc = "pollset_set_add_pollset";
@@ -1339,7 +1358,7 @@
                                         grpc_pollset_set* b) {
   GPR_TIMER_SCOPE("pollset_set_add_pollset_set", 0);
   if (grpc_polling_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "PSS: merge (%p, %p)", a, b);
+    gpr_log(GPR_INFO, "PSS: merge (%p, %p)", a, b);
   }
   grpc_error* error = GRPC_ERROR_NONE;
   static const char* err_desc = "pollset_set_add_fd";
@@ -1373,7 +1392,7 @@
     GPR_SWAP(grpc_pollset_set*, a, b);
   }
   if (grpc_polling_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "PSS: parent %p to %p", b, a);
+    gpr_log(GPR_INFO, "PSS: parent %p to %p", b, a);
   }
   gpr_ref(&a->refs);
   b->parent = a;
diff --git a/src/core/lib/iomgr/ev_epollsig_linux.cc b/src/core/lib/iomgr/ev_epollsig_linux.cc
index 1e30f66..494bc71 100644
--- a/src/core/lib/iomgr/ev_epollsig_linux.cc
+++ b/src/core/lib/iomgr/ev_epollsig_linux.cc
@@ -292,7 +292,7 @@
                            const char* file, int line) {
   if (grpc_polling_trace.enabled()) {
     gpr_atm old_cnt = gpr_atm_acq_load(&pi->ref_count);
-    gpr_log(GPR_DEBUG,
+    gpr_log(GPR_INFO,
             "Add ref pi: %p, old:%" PRIdPTR " -> new:%" PRIdPTR
             " (%s) - (%s, %d)",
             pi, old_cnt, old_cnt + 1, reason, file, line);
@@ -304,7 +304,7 @@
                          const char* file, int line) {
   if (grpc_polling_trace.enabled()) {
     gpr_atm old_cnt = gpr_atm_acq_load(&pi->ref_count);
-    gpr_log(GPR_DEBUG,
+    gpr_log(GPR_INFO,
             "Unref pi: %p, old:%" PRIdPTR " -> new:%" PRIdPTR
             " (%s) - (%s, %d)",
             pi, old_cnt, (old_cnt - 1), reason, file, line);
diff --git a/src/core/lib/iomgr/ev_poll_posix.cc b/src/core/lib/iomgr/ev_poll_posix.cc
index 2e375b4..504787e 100644
--- a/src/core/lib/iomgr/ev_poll_posix.cc
+++ b/src/core/lib/iomgr/ev_poll_posix.cc
@@ -983,7 +983,7 @@
       GRPC_SCHEDULING_END_BLOCKING_REGION;
 
       if (grpc_polling_trace.enabled()) {
-        gpr_log(GPR_DEBUG, "%p poll=%d", pollset, r);
+        gpr_log(GPR_INFO, "%p poll=%d", pollset, r);
       }
 
       if (r < 0) {
@@ -1007,7 +1007,7 @@
       } else {
         if (pfds[0].revents & POLLIN_CHECK) {
           if (grpc_polling_trace.enabled()) {
-            gpr_log(GPR_DEBUG, "%p: got_wakeup", pollset);
+            gpr_log(GPR_INFO, "%p: got_wakeup", pollset);
           }
           work_combine_error(
               &error, grpc_wakeup_fd_consume_wakeup(&worker.wakeup_fd->fd));
@@ -1017,7 +1017,7 @@
             fd_end_poll(&watchers[i], 0, 0, nullptr);
           } else {
             if (grpc_polling_trace.enabled()) {
-              gpr_log(GPR_DEBUG, "%p got_event: %d r:%d w:%d [%d]", pollset,
+              gpr_log(GPR_INFO, "%p got_event: %d r:%d w:%d [%d]", pollset,
                       pfds[i].fd, (pfds[i].revents & POLLIN_CHECK) != 0,
                       (pfds[i].revents & POLLOUT_CHECK) != 0, pfds[i].revents);
             }
@@ -1530,6 +1530,12 @@
 
 // This function overrides poll() to handle condition variable wakeup fds
 static int cvfd_poll(struct pollfd* fds, nfds_t nfds, int timeout) {
+  if (timeout == 0) {
+    // Don't bother using background threads for polling if timeout is 0,
+    // poll-cv might not wait for a poll to return otherwise.
+    // https://github.com/grpc/grpc/issues/13298
+    return poll(fds, nfds, 0);
+  }
   unsigned int i;
   int res, idx;
   grpc_cv_node* pollcv;
diff --git a/src/core/lib/iomgr/ev_posix.cc b/src/core/lib/iomgr/ev_posix.cc
index 8b80070..4ea63fc 100644
--- a/src/core/lib/iomgr/ev_posix.cc
+++ b/src/core/lib/iomgr/ev_posix.cc
@@ -46,9 +46,9 @@
 #ifndef NDEBUG
 
 // Polling API trace only enabled in debug builds
-#define GRPC_POLLING_API_TRACE(format, ...)                   \
-  if (grpc_polling_api_trace.enabled()) {                     \
-    gpr_log(GPR_DEBUG, "(polling-api) " format, __VA_ARGS__); \
+#define GRPC_POLLING_API_TRACE(format, ...)                  \
+  if (grpc_polling_api_trace.enabled()) {                    \
+    gpr_log(GPR_INFO, "(polling-api) " format, __VA_ARGS__); \
   }
 #else
 #define GRPC_POLLING_API_TRACE(...)
diff --git a/src/core/lib/iomgr/executor.cc b/src/core/lib/iomgr/executor.cc
index b017db5..f19f8cf 100644
--- a/src/core/lib/iomgr/executor.cc
+++ b/src/core/lib/iomgr/executor.cc
@@ -69,7 +69,7 @@
       gpr_log(GPR_DEBUG, "EXECUTOR: run %p [created by %s:%d]", c,
               c->file_created, c->line_created);
 #else
-      gpr_log(GPR_DEBUG, "EXECUTOR: run %p", c);
+      gpr_log(GPR_INFO, "EXECUTOR: run %p", c);
 #endif
     }
 #ifndef NDEBUG
@@ -150,7 +150,7 @@
   size_t subtract_depth = 0;
   for (;;) {
     if (executor_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "EXECUTOR[%d]: step (sub_depth=%" PRIdPTR ")",
+      gpr_log(GPR_INFO, "EXECUTOR[%d]: step (sub_depth=%" PRIdPTR ")",
               static_cast<int>(ts - g_thread_state), subtract_depth);
     }
     gpr_mu_lock(&ts->mu);
@@ -161,7 +161,7 @@
     }
     if (ts->shutdown) {
       if (executor_trace.enabled()) {
-        gpr_log(GPR_DEBUG, "EXECUTOR[%d]: shutdown",
+        gpr_log(GPR_INFO, "EXECUTOR[%d]: shutdown",
                 static_cast<int>(ts - g_thread_state));
       }
       gpr_mu_unlock(&ts->mu);
@@ -172,7 +172,7 @@
     ts->elems = GRPC_CLOSURE_LIST_INIT;
     gpr_mu_unlock(&ts->mu);
     if (executor_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "EXECUTOR[%d]: execute",
+      gpr_log(GPR_INFO, "EXECUTOR[%d]: execute",
               static_cast<int>(ts - g_thread_state));
     }
 
@@ -199,7 +199,7 @@
         gpr_log(GPR_DEBUG, "EXECUTOR: schedule %p (created %s:%d) inline",
                 closure, closure->file_created, closure->line_created);
 #else
-        gpr_log(GPR_DEBUG, "EXECUTOR: schedule %p inline", closure);
+        gpr_log(GPR_INFO, "EXECUTOR: schedule %p inline", closure);
 #endif
       }
       grpc_closure_list_append(grpc_core::ExecCtx::Get()->closure_list(),
@@ -225,7 +225,7 @@
             closure, is_short ? "short" : "long", closure->file_created,
             closure->line_created, static_cast<int>(ts - g_thread_state));
 #else
-        gpr_log(GPR_DEBUG, "EXECUTOR: try to schedule %p (%s) to thread %d",
+        gpr_log(GPR_INFO, "EXECUTOR: try to schedule %p (%s) to thread %d",
                 closure, is_short ? "short" : "long",
                 (int)(ts - g_thread_state));
 #endif
diff --git a/src/core/lib/iomgr/fork_posix.cc b/src/core/lib/iomgr/fork_posix.cc
index f8645ab..6c506eb 100644
--- a/src/core/lib/iomgr/fork_posix.cc
+++ b/src/core/lib/iomgr/fork_posix.cc
@@ -74,7 +74,6 @@
     grpc_timer_manager_set_threading(true);
     grpc_core::ExecCtx exec_ctx;
     grpc_executor_set_threading(true);
-    grpc_core::ExecCtx::Get()->Flush();
   }
 }
 
diff --git a/src/core/lib/iomgr/gevent_util.h b/src/core/lib/iomgr/gevent_util.h
new file mode 100644
index 0000000..de30543
--- /dev/null
+++ b/src/core/lib/iomgr/gevent_util.h
@@ -0,0 +1,46 @@
+/*
+ *
+ * Copyright 2018 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_LIB_IOMGR_GEVENT_UTIL_H
+#define GRPC_CORE_LIB_IOMGR_GEVENT_UTIL_H
+
+#include <grpc/support/port_platform.h>
+
+#include <grpc/impl/codegen/slice.h>
+#include <grpc/status.h>
+#include "src/core/lib/iomgr/error.h"
+
+// These are only used by the gRPC Python extension for gevent
+// support.  They are easier to define here (rather than in Cython)
+// because Cython doesn't handle #defines well.
+
+grpc_error* grpc_socket_error(char* error) {
+  return grpc_error_set_int(GRPC_ERROR_CREATE_FROM_COPIED_STRING(error),
+                            GRPC_ERROR_INT_GRPC_STATUS,
+                            GRPC_STATUS_UNAVAILABLE);
+}
+
+char* grpc_slice_buffer_start(grpc_slice_buffer* buffer, int i) {
+  return (char*)GRPC_SLICE_START_PTR(buffer->slices[i]);
+}
+
+int grpc_slice_buffer_length(grpc_slice_buffer* buffer, int i) {
+  return GRPC_SLICE_LENGTH(buffer->slices[i]);
+}
+
+#endif
diff --git a/src/core/lib/iomgr/iomgr_custom.h b/src/core/lib/iomgr/iomgr_custom.h
index ceb6c65..57cc2f9 100644
--- a/src/core/lib/iomgr/iomgr_custom.h
+++ b/src/core/lib/iomgr/iomgr_custom.h
@@ -37,7 +37,7 @@
   GPR_ASSERT(gpr_thd_currentid() == g_init_thread)
 #else
 #define GRPC_CUSTOM_IOMGR_ASSERT_SAME_THREAD()
-#endif /* GRPC_UV_THREAD_CHECK */
+#endif /* GRPC_CUSTOM_IOMGR_THREAD_CHECK */
 
 void grpc_custom_iomgr_init(grpc_socket_vtable* socket,
                             grpc_custom_resolver_vtable* resolver,
diff --git a/src/core/lib/iomgr/lockfree_event.h b/src/core/lib/iomgr/lockfree_event.h
index b507b94..d6a6c22 100644
--- a/src/core/lib/iomgr/lockfree_event.h
+++ b/src/core/lib/iomgr/lockfree_event.h
@@ -42,12 +42,23 @@
   void InitEvent();
   void DestroyEvent();
 
+  // Returns true if fd has been shutdown, false otherwise.
   bool IsShutdown() const {
     return (gpr_atm_no_barrier_load(&state_) & kShutdownBit) != 0;
   }
 
+  // Schedules \a closure when the event is received (see SetReady()) or the
+  // shutdown state has been set. Note that the event may have already been
+  // received, in which case the closure would be scheduled immediately.
+  // If the shutdown state has already been set, then \a closure is scheduled
+  // with the shutdown error.
   void NotifyOn(grpc_closure* closure);
+
+  // Sets the shutdown state. If a closure had been provided by NotifyOn and has
+  // not yet been scheduled, it will be scheduled with \a error.
   bool SetShutdown(grpc_error* error);
+
+  // Signals that the event has been received.
   void SetReady();
 
  private:
diff --git a/src/core/lib/iomgr/port.h b/src/core/lib/iomgr/port.h
index c1dcc52..a397012 100644
--- a/src/core/lib/iomgr/port.h
+++ b/src/core/lib/iomgr/port.h
@@ -22,8 +22,10 @@
 #define GRPC_CORE_LIB_IOMGR_PORT_H
 
 #ifdef GRPC_UV
+#ifndef GRPC_CUSTOM_SOCKET
 #define GRPC_CUSTOM_SOCKET
 #endif
+#endif
 #if defined(GRPC_CUSTOM_SOCKET)
 // Do Nothing
 #elif defined(GPR_MANYLINUX1)
diff --git a/src/core/lib/iomgr/resource_quota.cc b/src/core/lib/iomgr/resource_quota.cc
index 8c42dd7..8cf4fe9 100644
--- a/src/core/lib/iomgr/resource_quota.cc
+++ b/src/core/lib/iomgr/resource_quota.cc
@@ -289,7 +289,7 @@
                                           GRPC_RULIST_AWAITING_ALLOCATION))) {
     gpr_mu_lock(&resource_user->mu);
     if (grpc_resource_quota_trace.enabled()) {
-      gpr_log(GPR_DEBUG,
+      gpr_log(GPR_INFO,
               "RQ: check allocation for user %p shutdown=%" PRIdPTR
               " free_pool=%" PRId64,
               resource_user, gpr_atm_no_barrier_load(&resource_user->shutdown),
@@ -315,7 +315,7 @@
       resource_quota->free_pool -= amt;
       rq_update_estimate(resource_quota);
       if (grpc_resource_quota_trace.enabled()) {
-        gpr_log(GPR_DEBUG,
+        gpr_log(GPR_INFO,
                 "RQ %s %s: grant alloc %" PRId64
                 " bytes; rq_free_pool -> %" PRId64,
                 resource_quota->name, resource_user->name, amt,
@@ -323,7 +323,7 @@
       }
     } else if (grpc_resource_quota_trace.enabled() &&
                resource_user->free_pool >= 0) {
-      gpr_log(GPR_DEBUG, "RQ %s %s: discard already satisfied alloc request",
+      gpr_log(GPR_INFO, "RQ %s %s: discard already satisfied alloc request",
               resource_quota->name, resource_user->name);
     }
     if (resource_user->free_pool >= 0) {
@@ -353,7 +353,7 @@
       resource_quota->free_pool += amt;
       rq_update_estimate(resource_quota);
       if (grpc_resource_quota_trace.enabled()) {
-        gpr_log(GPR_DEBUG,
+        gpr_log(GPR_INFO,
                 "RQ %s %s: reclaim_from_per_user_free_pool %" PRId64
                 " bytes; rq_free_pool -> %" PRId64,
                 resource_quota->name, resource_user->name, amt,
@@ -376,9 +376,8 @@
   grpc_resource_user* resource_user = rulist_pop_head(resource_quota, list);
   if (resource_user == nullptr) return false;
   if (grpc_resource_quota_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "RQ %s %s: initiate %s reclamation",
-            resource_quota->name, resource_user->name,
-            destructive ? "destructive" : "benign");
+    gpr_log(GPR_INFO, "RQ %s %s: initiate %s reclamation", resource_quota->name,
+            resource_user->name, destructive ? "destructive" : "benign");
   }
   resource_quota->reclaiming = true;
   grpc_resource_quota_ref_internal(resource_quota);
@@ -506,7 +505,7 @@
 
 static void ru_shutdown(void* ru, grpc_error* error) {
   if (grpc_resource_quota_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "RU shutdown %p", ru);
+    gpr_log(GPR_INFO, "RU shutdown %p", ru);
   }
   grpc_resource_user* resource_user = static_cast<grpc_resource_user*>(ru);
   gpr_mu_lock(&resource_user->mu);
@@ -793,7 +792,7 @@
   resource_user->free_pool -= static_cast<int64_t>(size);
   resource_user->outstanding_allocations += static_cast<int64_t>(size);
   if (grpc_resource_quota_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "RQ %s %s: alloc %" PRIdPTR "; free_pool -> %" PRId64,
+    gpr_log(GPR_INFO, "RQ %s %s: alloc %" PRIdPTR "; free_pool -> %" PRId64,
             resource_user->resource_quota->name, resource_user->name, size,
             resource_user->free_pool);
   }
@@ -816,7 +815,7 @@
   bool was_zero_or_negative = resource_user->free_pool <= 0;
   resource_user->free_pool += static_cast<int64_t>(size);
   if (grpc_resource_quota_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "RQ %s %s: free %" PRIdPTR "; free_pool -> %" PRId64,
+    gpr_log(GPR_INFO, "RQ %s %s: free %" PRIdPTR "; free_pool -> %" PRId64,
             resource_user->resource_quota->name, resource_user->name, size,
             resource_user->free_pool);
   }
@@ -842,7 +841,7 @@
 
 void grpc_resource_user_finish_reclamation(grpc_resource_user* resource_user) {
   if (grpc_resource_quota_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "RQ %s %s: reclamation complete",
+    gpr_log(GPR_INFO, "RQ %s %s: reclamation complete",
             resource_user->resource_quota->name, resource_user->name);
   }
   GRPC_CLOSURE_SCHED(
diff --git a/src/core/lib/iomgr/sockaddr_utils.cc b/src/core/lib/iomgr/sockaddr_utils.cc
index df25f77..1b66dce 100644
--- a/src/core/lib/iomgr/sockaddr_utils.cc
+++ b/src/core/lib/iomgr/sockaddr_utils.cc
@@ -204,6 +204,8 @@
 
   if (grpc_inet_pton(GRPC_AF_INET6, addr, &addr6->sin6_addr) == 1) {
     addr6->sin6_family = GRPC_AF_INET6;
+    addr6->sin6_flowinfo = 0;
+    addr6->sin6_scope_id = 0;
     out->len = sizeof(grpc_sockaddr_in6);
   } else if (grpc_inet_pton(GRPC_AF_INET, addr, &addr4->sin_addr) == 1) {
     addr4->sin_family = GRPC_AF_INET;
diff --git a/src/core/lib/iomgr/socket_utils_common_posix.cc b/src/core/lib/iomgr/socket_utils_common_posix.cc
index c52e237..04a1767 100644
--- a/src/core/lib/iomgr/socket_utils_common_posix.cc
+++ b/src/core/lib/iomgr/socket_utils_common_posix.cc
@@ -181,6 +181,30 @@
 #endif
 }
 
+static gpr_once g_probe_so_reuesport_once = GPR_ONCE_INIT;
+static int g_support_so_reuseport = false;
+
+void probe_so_reuseport_once(void) {
+#ifndef GPR_MANYLINUX1
+  int s = socket(AF_INET, SOCK_STREAM, 0);
+  if (s < 0) {
+    /* This might be an ipv6-only environment in which case 'socket(AF_INET,..)'
+       call would fail. Try creating IPv6 socket in that case */
+    s = socket(AF_INET6, SOCK_STREAM, 0);
+  }
+  if (s >= 0) {
+    g_support_so_reuseport = GRPC_LOG_IF_ERROR(
+        "check for SO_REUSEPORT", grpc_set_socket_reuse_port(s, 1));
+    close(s);
+  }
+#endif
+}
+
+bool grpc_is_socket_reuse_port_supported() {
+  gpr_once_init(&g_probe_so_reuesport_once, probe_so_reuseport_once);
+  return g_support_so_reuseport;
+}
+
 /* disable nagle */
 grpc_error* grpc_set_socket_low_latency(int fd, int low_latency) {
   int val = (low_latency != 0);
diff --git a/src/core/lib/iomgr/socket_utils_linux.cc b/src/core/lib/iomgr/socket_utils_linux.cc
index f506329..34f93cc 100644
--- a/src/core/lib/iomgr/socket_utils_linux.cc
+++ b/src/core/lib/iomgr/socket_utils_linux.cc
@@ -33,8 +33,6 @@
 int grpc_accept4(int sockfd, grpc_resolved_address* resolved_addr, int nonblock,
                  int cloexec) {
   int flags = 0;
-  GPR_ASSERT(sizeof(socklen_t) <= sizeof(size_t));
-  GPR_ASSERT(resolved_addr->len <= (socklen_t)-1);
   flags |= nonblock ? SOCK_NONBLOCK : 0;
   flags |= cloexec ? SOCK_CLOEXEC : 0;
   return accept4(sockfd, reinterpret_cast<grpc_sockaddr*>(resolved_addr->addr),
diff --git a/src/core/lib/iomgr/socket_utils_posix.cc b/src/core/lib/iomgr/socket_utils_posix.cc
index d5d00af..c48da52 100644
--- a/src/core/lib/iomgr/socket_utils_posix.cc
+++ b/src/core/lib/iomgr/socket_utils_posix.cc
@@ -34,10 +34,8 @@
 int grpc_accept4(int sockfd, grpc_resolved_address* resolved_addr, int nonblock,
                  int cloexec) {
   int fd, flags;
-  GPR_ASSERT(sizeof(socklen_t) <= sizeof(size_t));
-  GPR_ASSERT(resolved_addr->len <= (socklen_t)-1);
-  fd = accept(sockfd, (grpc_sockaddr*)resolved_addr->addr,
-              (socklen_t*)&resolved_addr->len);
+  fd = accept(sockfd, reinterpret_cast<grpc_sockaddr*>(resolved_addr->addr),
+              &resolved_addr->len);
   if (fd >= 0) {
     if (nonblock) {
       flags = fcntl(fd, F_GETFL, 0);
diff --git a/src/core/lib/iomgr/socket_utils_posix.h b/src/core/lib/iomgr/socket_utils_posix.h
index 1f50e8d..b3fd58a 100644
--- a/src/core/lib/iomgr/socket_utils_posix.h
+++ b/src/core/lib/iomgr/socket_utils_posix.h
@@ -44,6 +44,9 @@
 /* set a socket to reuse old addresses */
 grpc_error* grpc_set_socket_reuse_addr(int fd, int reuse);
 
+/* return true if SO_REUSEPORT is supported */
+bool grpc_is_socket_reuse_port_supported();
+
 /* disable nagle */
 grpc_error* grpc_set_socket_low_latency(int fd, int low_latency);
 
diff --git a/src/core/lib/iomgr/socket_utils_uv.cc b/src/core/lib/iomgr/socket_utils_uv.cc
index 8538abc..7eba40c 100644
--- a/src/core/lib/iomgr/socket_utils_uv.cc
+++ b/src/core/lib/iomgr/socket_utils_uv.cc
@@ -38,8 +38,8 @@
 }
 
 const char* grpc_inet_ntop(int af, const void* src, char* dst, size_t size) {
-  /* Windows InetNtopA wants a mutable ip pointer */
-  return inet_ntop(af, src, dst, (socklen_t)size);
+  uv_inet_ntop(af, src, dst, size);
+  return dst;
 }
 
 #endif /* GRPC_UV */
diff --git a/src/core/lib/iomgr/tcp_client_custom.cc b/src/core/lib/iomgr/tcp_client_custom.cc
index 55632a5..932c79e 100644
--- a/src/core/lib/iomgr/tcp_client_custom.cc
+++ b/src/core/lib/iomgr/tcp_client_custom.cc
@@ -66,7 +66,7 @@
   grpc_custom_tcp_connect* connect = socket->connector;
   if (grpc_tcp_trace.enabled()) {
     const char* str = grpc_error_string(error);
-    gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: on_alarm: error=%s",
+    gpr_log(GPR_INFO, "CLIENT_CONNECT: %s: on_alarm: error=%s",
             connect->addr_name, str);
   }
   if (error == GRPC_ERROR_NONE) {
@@ -136,7 +136,7 @@
   connect->refs = 2;
 
   if (grpc_tcp_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %p %s: asynchronously connecting",
+    gpr_log(GPR_INFO, "CLIENT_CONNECT: %p %s: asynchronously connecting",
             socket, connect->addr_name);
   }
 
diff --git a/src/core/lib/iomgr/tcp_client_posix.cc b/src/core/lib/iomgr/tcp_client_posix.cc
index 9f19b83..6144d38 100644
--- a/src/core/lib/iomgr/tcp_client_posix.cc
+++ b/src/core/lib/iomgr/tcp_client_posix.cc
@@ -104,7 +104,7 @@
   async_connect* ac = static_cast<async_connect*>(acp);
   if (grpc_tcp_trace.enabled()) {
     const char* str = grpc_error_string(error);
-    gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: on_alarm: error=%s", ac->addr_str,
+    gpr_log(GPR_INFO, "CLIENT_CONNECT: %s: on_alarm: error=%s", ac->addr_str,
             str);
   }
   gpr_mu_lock(&ac->mu);
@@ -141,8 +141,8 @@
 
   if (grpc_tcp_trace.enabled()) {
     const char* str = grpc_error_string(error);
-    gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: on_writable: error=%s",
-            ac->addr_str, str);
+    gpr_log(GPR_INFO, "CLIENT_CONNECT: %s: on_writable: error=%s", ac->addr_str,
+            str);
   }
 
   gpr_mu_lock(&ac->mu);
@@ -325,7 +325,7 @@
   ac->channel_args = grpc_channel_args_copy(channel_args);
 
   if (grpc_tcp_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "CLIENT_CONNECT: %s: asynchronously connecting fd %p",
+    gpr_log(GPR_INFO, "CLIENT_CONNECT: %s: asynchronously connecting fd %p",
             ac->addr_str, fdobj);
   }
 
diff --git a/src/core/lib/iomgr/tcp_custom.cc b/src/core/lib/iomgr/tcp_custom.cc
index 2b1fc93..b3b2934 100644
--- a/src/core/lib/iomgr/tcp_custom.cc
+++ b/src/core/lib/iomgr/tcp_custom.cc
@@ -125,16 +125,16 @@
 static void call_read_cb(custom_tcp_endpoint* tcp, grpc_error* error) {
   grpc_closure* cb = tcp->read_cb;
   if (grpc_tcp_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "TCP:%p call_cb %p %p:%p", tcp->socket, cb, cb->cb,
+    gpr_log(GPR_INFO, "TCP:%p call_cb %p %p:%p", tcp->socket, cb, cb->cb,
             cb->cb_arg);
     size_t i;
     const char* str = grpc_error_string(error);
-    gpr_log(GPR_DEBUG, "read: error=%s", str);
+    gpr_log(GPR_INFO, "read: error=%s", str);
 
     for (i = 0; i < tcp->read_slices->count; i++) {
       char* dump = grpc_dump_slice(tcp->read_slices->slices[i],
                                    GPR_DUMP_HEX | GPR_DUMP_ASCII);
-      gpr_log(GPR_DEBUG, "READ %p (peer=%s): %s", tcp, tcp->peer_string, dump);
+      gpr_log(GPR_INFO, "READ %p (peer=%s): %s", tcp, tcp->peer_string, dump);
       gpr_free(dump);
     }
   }
@@ -171,7 +171,7 @@
 static void tcp_read_allocation_done(void* tcpp, grpc_error* error) {
   custom_tcp_endpoint* tcp = (custom_tcp_endpoint*)tcpp;
   if (grpc_tcp_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "TCP:%p read_allocation_done: %s", tcp->socket,
+    gpr_log(GPR_INFO, "TCP:%p read_allocation_done: %s", tcp->socket,
             grpc_error_string(error));
   }
   if (error == GRPC_ERROR_NONE) {
@@ -188,7 +188,7 @@
   }
   if (grpc_tcp_trace.enabled()) {
     const char* str = grpc_error_string(error);
-    gpr_log(GPR_DEBUG, "Initiating read on %p: error=%s", tcp->socket, str);
+    gpr_log(GPR_INFO, "Initiating read on %p: error=%s", tcp->socket, str);
   }
 }
 
@@ -214,7 +214,7 @@
   tcp->write_cb = nullptr;
   if (grpc_tcp_trace.enabled()) {
     const char* str = grpc_error_string(error);
-    gpr_log(GPR_DEBUG, "write complete on %p: error=%s", tcp->socket, str);
+    gpr_log(GPR_INFO, "write complete on %p: error=%s", tcp->socket, str);
   }
   TCP_UNREF(tcp, "write");
   GRPC_CLOSURE_SCHED(cb, error);
@@ -231,8 +231,8 @@
     for (j = 0; j < write_slices->count; j++) {
       char* data = grpc_dump_slice(write_slices->slices[j],
                                    GPR_DUMP_HEX | GPR_DUMP_ASCII);
-      gpr_log(GPR_DEBUG, "WRITE %p (peer=%s): %s", tcp->socket,
-              tcp->peer_string, data);
+      gpr_log(GPR_INFO, "WRITE %p (peer=%s): %s", tcp->socket, tcp->peer_string,
+              data);
       gpr_free(data);
     }
   }
@@ -283,7 +283,7 @@
   if (!tcp->shutting_down) {
     if (grpc_tcp_trace.enabled()) {
       const char* str = grpc_error_string(why);
-      gpr_log(GPR_DEBUG, "TCP %p shutdown why=%s", tcp->socket, str);
+      gpr_log(GPR_INFO, "TCP %p shutdown why=%s", tcp->socket, str);
     }
     tcp->shutting_down = true;
     // GRPC_CLOSURE_SCHED(tcp->read_cb, GRPC_ERROR_REF(why));
@@ -345,7 +345,7 @@
   grpc_core::ExecCtx exec_ctx;
 
   if (grpc_tcp_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "Creating TCP endpoint %p", socket);
+    gpr_log(GPR_INFO, "Creating TCP endpoint %p", socket);
   }
   memset(tcp, 0, sizeof(custom_tcp_endpoint));
   socket->refs++;
diff --git a/src/core/lib/iomgr/tcp_custom.h b/src/core/lib/iomgr/tcp_custom.h
index 22caa14..784ef84 100644
--- a/src/core/lib/iomgr/tcp_custom.h
+++ b/src/core/lib/iomgr/tcp_custom.h
@@ -62,8 +62,6 @@
                              const grpc_sockaddr* addr, int* len);
   grpc_error* (*getsockname)(grpc_custom_socket* socket,
                              const grpc_sockaddr* addr, int* len);
-  grpc_error* (*setsockopt)(grpc_custom_socket* socket, int level, int optname,
-                            const void* optval, uint32_t optlen);
   grpc_error* (*bind)(grpc_custom_socket* socket, const grpc_sockaddr* addr,
                       size_t len, int flags);
   grpc_error* (*listen)(grpc_custom_socket* socket);
diff --git a/src/core/lib/iomgr/tcp_posix.cc b/src/core/lib/iomgr/tcp_posix.cc
index 205af22..153be05 100644
--- a/src/core/lib/iomgr/tcp_posix.cc
+++ b/src/core/lib/iomgr/tcp_posix.cc
@@ -120,7 +120,7 @@
 static void done_poller(void* bp, grpc_error* error_ignored) {
   backup_poller* p = static_cast<backup_poller*>(bp);
   if (grpc_tcp_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "BACKUP_POLLER:%p destroy", p);
+    gpr_log(GPR_INFO, "BACKUP_POLLER:%p destroy", p);
   }
   grpc_pollset_destroy(BACKUP_POLLER_POLLSET(p));
   gpr_free(p);
@@ -129,7 +129,7 @@
 static void run_poller(void* bp, grpc_error* error_ignored) {
   backup_poller* p = static_cast<backup_poller*>(bp);
   if (grpc_tcp_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "BACKUP_POLLER:%p run", p);
+    gpr_log(GPR_INFO, "BACKUP_POLLER:%p run", p);
   }
   gpr_mu_lock(p->pollset_mu);
   grpc_millis deadline = grpc_core::ExecCtx::Get()->Now() + 10 * GPR_MS_PER_SEC;
@@ -145,18 +145,18 @@
     gpr_mu_lock(p->pollset_mu);
     bool cas_ok = gpr_atm_full_cas(&g_backup_poller, (gpr_atm)p, 0);
     if (grpc_tcp_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "BACKUP_POLLER:%p done cas_ok=%d", p, cas_ok);
+      gpr_log(GPR_INFO, "BACKUP_POLLER:%p done cas_ok=%d", p, cas_ok);
     }
     gpr_mu_unlock(p->pollset_mu);
     if (grpc_tcp_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "BACKUP_POLLER:%p shutdown", p);
+      gpr_log(GPR_INFO, "BACKUP_POLLER:%p shutdown", p);
     }
     grpc_pollset_shutdown(BACKUP_POLLER_POLLSET(p),
                           GRPC_CLOSURE_INIT(&p->run_poller, done_poller, p,
                                             grpc_schedule_on_exec_ctx));
   } else {
     if (grpc_tcp_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "BACKUP_POLLER:%p reschedule", p);
+      gpr_log(GPR_INFO, "BACKUP_POLLER:%p reschedule", p);
     }
     GRPC_CLOSURE_SCHED(&p->run_poller, GRPC_ERROR_NONE);
   }
@@ -167,7 +167,7 @@
   gpr_atm old_count =
       gpr_atm_no_barrier_fetch_add(&g_uncovered_notifications_pending, -1);
   if (grpc_tcp_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "BACKUP_POLLER:%p uncover cnt %d->%d", p,
+    gpr_log(GPR_INFO, "BACKUP_POLLER:%p uncover cnt %d->%d", p,
             static_cast<int>(old_count), static_cast<int>(old_count) - 1);
   }
   GPR_ASSERT(old_count != 1);
@@ -178,7 +178,7 @@
   gpr_atm old_count =
       gpr_atm_no_barrier_fetch_add(&g_uncovered_notifications_pending, 2);
   if (grpc_tcp_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "BACKUP_POLLER: cover cnt %d->%d",
+    gpr_log(GPR_INFO, "BACKUP_POLLER: cover cnt %d->%d",
             static_cast<int>(old_count), 2 + static_cast<int>(old_count));
   }
   if (old_count == 0) {
@@ -186,7 +186,7 @@
     p = static_cast<backup_poller*>(
         gpr_zalloc(sizeof(*p) + grpc_pollset_size()));
     if (grpc_tcp_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "BACKUP_POLLER:%p create", p);
+      gpr_log(GPR_INFO, "BACKUP_POLLER:%p create", p);
     }
     grpc_pollset_init(BACKUP_POLLER_POLLSET(p), &p->pollset_mu);
     gpr_atm_rel_store(&g_backup_poller, (gpr_atm)p);
@@ -201,7 +201,7 @@
     }
   }
   if (grpc_tcp_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "BACKUP_POLLER:%p add %p", p, tcp);
+    gpr_log(GPR_INFO, "BACKUP_POLLER:%p add %p", p, tcp);
   }
   grpc_pollset_add_fd(BACKUP_POLLER_POLLSET(p), tcp->em_fd);
   if (old_count != 0) {
@@ -211,7 +211,7 @@
 
 static void notify_on_read(grpc_tcp* tcp) {
   if (grpc_tcp_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "TCP:%p notify_on_read", tcp);
+    gpr_log(GPR_INFO, "TCP:%p notify_on_read", tcp);
   }
   GRPC_CLOSURE_INIT(&tcp->read_done_closure, tcp_handle_read, tcp,
                     grpc_schedule_on_exec_ctx);
@@ -220,7 +220,7 @@
 
 static void notify_on_write(grpc_tcp* tcp) {
   if (grpc_tcp_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "TCP:%p notify_on_write", tcp);
+    gpr_log(GPR_INFO, "TCP:%p notify_on_write", tcp);
   }
   cover_self(tcp);
   GRPC_CLOSURE_INIT(&tcp->write_done_closure,
@@ -231,7 +231,7 @@
 
 static void tcp_drop_uncovered_then_handle_write(void* arg, grpc_error* error) {
   if (grpc_tcp_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "TCP:%p got_write: %s", arg, grpc_error_string(error));
+    gpr_log(GPR_INFO, "TCP:%p got_write: %s", arg, grpc_error_string(error));
   }
   drop_uncovered(static_cast<grpc_tcp*>(arg));
   tcp_handle_write(arg, error);
@@ -351,15 +351,15 @@
   grpc_closure* cb = tcp->read_cb;
 
   if (grpc_tcp_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "TCP:%p call_cb %p %p:%p", tcp, cb, cb->cb, cb->cb_arg);
+    gpr_log(GPR_INFO, "TCP:%p call_cb %p %p:%p", tcp, cb, cb->cb, cb->cb_arg);
     size_t i;
     const char* str = grpc_error_string(error);
-    gpr_log(GPR_DEBUG, "read: error=%s", str);
+    gpr_log(GPR_INFO, "read: error=%s", str);
 
     for (i = 0; i < tcp->incoming_buffer->count; i++) {
       char* dump = grpc_dump_slice(tcp->incoming_buffer->slices[i],
                                    GPR_DUMP_HEX | GPR_DUMP_ASCII);
-      gpr_log(GPR_DEBUG, "READ %p (peer=%s): %s", tcp, tcp->peer_string, dump);
+      gpr_log(GPR_INFO, "READ %p (peer=%s): %s", tcp, tcp->peer_string, dump);
       gpr_free(dump);
     }
   }
@@ -371,7 +371,7 @@
 
 #define MAX_READ_IOVEC 4
 static void tcp_do_read(grpc_tcp* tcp) {
-  GPR_TIMER_SCOPE("tcp_continue_read", 0);
+  GPR_TIMER_SCOPE("tcp_do_read", 0);
   struct msghdr msg;
   struct iovec iov[MAX_READ_IOVEC];
   ssize_t read_bytes;
@@ -441,7 +441,7 @@
 static void tcp_read_allocation_done(void* tcpp, grpc_error* error) {
   grpc_tcp* tcp = static_cast<grpc_tcp*>(tcpp);
   if (grpc_tcp_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "TCP:%p read_allocation_done: %s", tcp,
+    gpr_log(GPR_INFO, "TCP:%p read_allocation_done: %s", tcp,
             grpc_error_string(error));
   }
   if (error != GRPC_ERROR_NONE) {
@@ -459,13 +459,13 @@
   if (tcp->incoming_buffer->length < target_read_size &&
       tcp->incoming_buffer->count < MAX_READ_IOVEC) {
     if (grpc_tcp_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "TCP:%p alloc_slices", tcp);
+      gpr_log(GPR_INFO, "TCP:%p alloc_slices", tcp);
     }
     grpc_resource_user_alloc_slices(&tcp->slice_allocator, target_read_size, 1,
                                     tcp->incoming_buffer);
   } else {
     if (grpc_tcp_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "TCP:%p do_read", tcp);
+      gpr_log(GPR_INFO, "TCP:%p do_read", tcp);
     }
     tcp_do_read(tcp);
   }
@@ -475,7 +475,7 @@
   grpc_tcp* tcp = static_cast<grpc_tcp*>(arg);
   GPR_ASSERT(!tcp->finished_edge);
   if (grpc_tcp_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "TCP:%p got_read: %s", tcp, grpc_error_string(error));
+    gpr_log(GPR_INFO, "TCP:%p got_read: %s", tcp, grpc_error_string(error));
   }
 
   if (error != GRPC_ERROR_NONE) {
@@ -618,7 +618,7 @@
 
   if (!tcp_flush(tcp, &error)) {
     if (grpc_tcp_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "write: delayed");
+      gpr_log(GPR_INFO, "write: delayed");
     }
     notify_on_write(tcp);
   } else {
@@ -626,7 +626,7 @@
     tcp->write_cb = nullptr;
     if (grpc_tcp_trace.enabled()) {
       const char* str = grpc_error_string(error);
-      gpr_log(GPR_DEBUG, "write: %s", str);
+      gpr_log(GPR_INFO, "write: %s", str);
     }
 
     GRPC_CLOSURE_RUN(cb, error);
@@ -646,7 +646,7 @@
     for (i = 0; i < buf->count; i++) {
       char* data =
           grpc_dump_slice(buf->slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII);
-      gpr_log(GPR_DEBUG, "WRITE %p (peer=%s): %s", tcp, tcp->peer_string, data);
+      gpr_log(GPR_INFO, "WRITE %p (peer=%s): %s", tcp, tcp->peer_string, data);
       gpr_free(data);
     }
   }
@@ -668,13 +668,13 @@
     TCP_REF(tcp, "write");
     tcp->write_cb = cb;
     if (grpc_tcp_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "write: delayed");
+      gpr_log(GPR_INFO, "write: delayed");
     }
     notify_on_write(tcp);
   } else {
     if (grpc_tcp_trace.enabled()) {
       const char* str = grpc_error_string(error);
-      gpr_log(GPR_DEBUG, "write: %s", str);
+      gpr_log(GPR_INFO, "write: %s", str);
     }
     GRPC_CLOSURE_SCHED(cb, error);
   }
diff --git a/src/core/lib/iomgr/tcp_server_custom.cc b/src/core/lib/iomgr/tcp_server_custom.cc
index be92e61..019b354 100644
--- a/src/core/lib/iomgr/tcp_server_custom.cc
+++ b/src/core/lib/iomgr/tcp_server_custom.cc
@@ -222,10 +222,10 @@
   }
   if (grpc_tcp_trace.enabled()) {
     if (peer_name_string) {
-      gpr_log(GPR_DEBUG, "SERVER_CONNECT: %p accepted connection: %s",
+      gpr_log(GPR_INFO, "SERVER_CONNECT: %p accepted connection: %s",
               sp->server, peer_name_string);
     } else {
-      gpr_log(GPR_DEBUG, "SERVER_CONNECT: %p accepted connection", sp->server);
+      gpr_log(GPR_INFO, "SERVER_CONNECT: %p accepted connection", sp->server);
     }
   }
   ep = custom_tcp_endpoint_create(socket, sp->server->resource_quota,
@@ -377,10 +377,10 @@
     grpc_sockaddr_to_string(&port_string, addr, 0);
     const char* str = grpc_error_string(error);
     if (port_string) {
-      gpr_log(GPR_DEBUG, "SERVER %p add_port %s error=%s", s, port_string, str);
+      gpr_log(GPR_INFO, "SERVER %p add_port %s error=%s", s, port_string, str);
       gpr_free(port_string);
     } else {
-      gpr_log(GPR_DEBUG, "SERVER %p add_port error=%s", s, str);
+      gpr_log(GPR_INFO, "SERVER %p add_port error=%s", s, str);
     }
   }
 
@@ -393,13 +393,6 @@
   grpc_custom_socket_vtable->init(socket, family);
 
   if (error == GRPC_ERROR_NONE) {
-#if defined(GPR_LINUX) && defined(SO_REUSEPORT)
-    if (family == AF_INET || family == AF_INET6) {
-      int enable = 1;
-      grpc_custom_socket_vtable->setsockopt(socket, SOL_SOCKET, SO_REUSEPORT,
-                                            &enable, sizeof(enable));
-    }
-#endif /* GPR_LINUX && SO_REUSEPORT */
     error = add_socket_to_server(s, socket, addr, port_index, &sp);
   }
   gpr_free(allocated_addr);
@@ -426,7 +419,7 @@
   (void)pollset_count;
   GRPC_CUSTOM_IOMGR_ASSERT_SAME_THREAD();
   if (grpc_tcp_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "SERVER_START %p", server);
+    gpr_log(GPR_INFO, "SERVER_START %p", server);
   }
   GPR_ASSERT(on_accept_cb);
   GPR_ASSERT(!server->on_accept_cb);
diff --git a/src/core/lib/iomgr/tcp_server_posix.cc b/src/core/lib/iomgr/tcp_server_posix.cc
index 4e1d90e..153ac63 100644
--- a/src/core/lib/iomgr/tcp_server_posix.cc
+++ b/src/core/lib/iomgr/tcp_server_posix.cc
@@ -55,39 +55,18 @@
 #include "src/core/lib/iomgr/tcp_server_utils_posix.h"
 #include "src/core/lib/iomgr/unix_sockets_posix.h"
 
-static gpr_once check_init = GPR_ONCE_INIT;
-static bool has_so_reuseport = false;
-
-static void init(void) {
-#ifndef GPR_MANYLINUX1
-  int s = socket(AF_INET, SOCK_STREAM, 0);
-  if (s < 0) {
-    /* This might be an ipv6-only environment in which case 'socket(AF_INET,..)'
-       call would fail. Try creating IPv6 socket in that case */
-    s = socket(AF_INET6, SOCK_STREAM, 0);
-  }
-  if (s >= 0) {
-    has_so_reuseport = GRPC_LOG_IF_ERROR("check for SO_REUSEPORT",
-                                         grpc_set_socket_reuse_port(s, 1));
-    close(s);
-  }
-#endif
-}
-
 static grpc_error* tcp_server_create(grpc_closure* shutdown_complete,
                                      const grpc_channel_args* args,
                                      grpc_tcp_server** server) {
-  gpr_once_init(&check_init, init);
-
   grpc_tcp_server* s =
       static_cast<grpc_tcp_server*>(gpr_zalloc(sizeof(grpc_tcp_server)));
-  s->so_reuseport = has_so_reuseport;
+  s->so_reuseport = grpc_is_socket_reuse_port_supported();
   s->expand_wildcard_addrs = false;
   for (size_t i = 0; i < (args == nullptr ? 0 : args->num_args); i++) {
     if (0 == strcmp(GRPC_ARG_ALLOW_REUSEPORT, args->args[i].key)) {
       if (args->args[i].type == GRPC_ARG_INTEGER) {
-        s->so_reuseport =
-            has_so_reuseport && (args->args[i].value.integer != 0);
+        s->so_reuseport = grpc_is_socket_reuse_port_supported() &&
+                          (args->args[i].value.integer != 0);
       } else {
         gpr_free(s);
         return GRPC_ERROR_CREATE_FROM_STATIC_STRING(GRPC_ARG_ALLOW_REUSEPORT
@@ -249,7 +228,7 @@
     gpr_asprintf(&name, "tcp-server-connection:%s", addr_str);
 
     if (grpc_tcp_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "SERVER_CONNECT: incoming connection: %s", addr_str);
+      gpr_log(GPR_INFO, "SERVER_CONNECT: incoming connection: %s", addr_str);
     }
 
     grpc_fd* fdobj = grpc_fd_create(fd, name);
@@ -367,7 +346,8 @@
     err = grpc_create_dualstack_socket(&listener->addr, SOCK_STREAM, 0, &dsmode,
                                        &fd);
     if (err != GRPC_ERROR_NONE) return err;
-    err = grpc_tcp_server_prepare_socket(fd, &listener->addr, true, &port);
+    err = grpc_tcp_server_prepare_socket(listener->server, fd, &listener->addr,
+                                         true, &port);
     if (err != GRPC_ERROR_NONE) return err;
     listener->server->nports++;
     grpc_sockaddr_to_string(&addr_str, &listener->addr, 1);
diff --git a/src/core/lib/iomgr/tcp_server_utils_posix.h b/src/core/lib/iomgr/tcp_server_utils_posix.h
index 34d6813..dd19909 100644
--- a/src/core/lib/iomgr/tcp_server_utils_posix.h
+++ b/src/core/lib/iomgr/tcp_server_utils_posix.h
@@ -113,7 +113,7 @@
                                                 int* out_port);
 
 /* Prepare a recently-created socket for listening. */
-grpc_error* grpc_tcp_server_prepare_socket(int fd,
+grpc_error* grpc_tcp_server_prepare_socket(grpc_tcp_server*, int fd,
                                            const grpc_resolved_address* addr,
                                            bool so_reuseport, int* port);
 /* Ruturn true if the platform supports ifaddrs */
diff --git a/src/core/lib/iomgr/tcp_server_utils_posix_common.cc b/src/core/lib/iomgr/tcp_server_utils_posix_common.cc
index 0734453..2d95aa6 100644
--- a/src/core/lib/iomgr/tcp_server_utils_posix_common.cc
+++ b/src/core/lib/iomgr/tcp_server_utils_posix_common.cc
@@ -87,7 +87,7 @@
   char* name;
 
   grpc_error* err =
-      grpc_tcp_server_prepare_socket(fd, addr, s->so_reuseport, &port);
+      grpc_tcp_server_prepare_socket(s, fd, addr, s->so_reuseport, &port);
   if (err == GRPC_ERROR_NONE) {
     GPR_ASSERT(port > 0);
     grpc_sockaddr_to_string(&addr_str, addr, 1);
@@ -144,7 +144,7 @@
 }
 
 /* Prepare a recently-created socket for listening. */
-grpc_error* grpc_tcp_server_prepare_socket(int fd,
+grpc_error* grpc_tcp_server_prepare_socket(grpc_tcp_server* s, int fd,
                                            const grpc_resolved_address* addr,
                                            bool so_reuseport, int* port) {
   grpc_resolved_address sockname_temp;
@@ -170,7 +170,18 @@
   err = grpc_set_socket_no_sigpipe_if_possible(fd);
   if (err != GRPC_ERROR_NONE) goto error;
 
-  GPR_ASSERT(addr->len < ~(socklen_t)0);
+  if (s->channel_args) {
+    for (size_t i = 0; i < s->channel_args->num_args; i++) {
+      if (0 == strcmp(s->channel_args->args[i].key, GRPC_ARG_SOCKET_MUTATOR)) {
+        GPR_ASSERT(s->channel_args->args[i].type == GRPC_ARG_POINTER);
+        grpc_socket_mutator* mutator = static_cast<grpc_socket_mutator*>(
+            s->channel_args->args[i].value.pointer.p);
+        err = grpc_set_socket_with_mutator(fd, mutator);
+        if (err != GRPC_ERROR_NONE) goto error;
+      }
+    }
+  }
+
   if (bind(fd, reinterpret_cast<grpc_sockaddr*>(const_cast<char*>(addr->addr)),
            addr->len) < 0) {
     err = GRPC_OS_ERROR(errno, "bind");
diff --git a/src/core/lib/iomgr/tcp_server_windows.cc b/src/core/lib/iomgr/tcp_server_windows.cc
index 77f3811..b01afdc 100644
--- a/src/core/lib/iomgr/tcp_server_windows.cc
+++ b/src/core/lib/iomgr/tcp_server_windows.cc
@@ -129,6 +129,7 @@
     gpr_free(sp);
   }
   grpc_channel_args_destroy(s->channel_args);
+  gpr_mu_destroy(&s->mu);
   gpr_free(s);
 }
 
diff --git a/src/core/lib/iomgr/tcp_uv.cc b/src/core/lib/iomgr/tcp_uv.cc
index 5e31669..8d0e4a5 100644
--- a/src/core/lib/iomgr/tcp_uv.cc
+++ b/src/core/lib/iomgr/tcp_uv.cc
@@ -192,9 +192,21 @@
   if (status != 0) {
     return tcp_error_create("Failed to initialize UV tcp handle", status);
   }
+#if defined(GPR_LINUX) && defined(SO_REUSEPORT)
+  if (domain == AF_INET || domain == AF_INET6) {
+    int enable = 1;
+    int fd;
+    uv_fileno((uv_handle_t*)tcp, &fd);
+    // TODO Handle error here.
+    setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &enable, sizeof(enable));
+  }
+#endif
   uv_socket->write_buffers = nullptr;
   uv_socket->read_len = 0;
   uv_tcp_nodelay(uv_socket->handle, 1);
+  // Node uses a garbage collector to call destructors, so we don't
+  // want to hold the uv loop open with active gRPC objects.
+  uv_unref((uv_handle_t*)uv_socket->handle);
   uv_socket->pending_connection = false;
   uv_socket->accept_socket = nullptr;
   uv_socket->accept_error = GRPC_ERROR_NONE;
@@ -299,17 +311,6 @@
   return tcp_error_create("Failed to listen to port", status);
 }
 
-static grpc_error* uv_socket_setsockopt(grpc_custom_socket* socket, int level,
-                                        int option_name, const void* optval,
-                                        socklen_t option_len) {
-  int fd;
-  uv_socket_t* uv_socket = (uv_socket_t*)socket->impl;
-  uv_fileno((uv_handle_t*)uv_socket->handle, &fd);
-  // TODO Handle error here.  Also, does this work on windows??
-  setsockopt(fd, level, option_name, &optval, (socklen_t)option_len);
-  return GRPC_ERROR_NONE;
-}
-
 static void uv_tc_on_connect(uv_connect_t* req, int status) {
   grpc_custom_socket* socket = (grpc_custom_socket*)req->data;
   uv_socket_t* uv_socket = (uv_socket_t*)socket->impl;
@@ -340,7 +341,6 @@
 static grpc_resolved_addresses* handle_addrinfo_result(
     struct addrinfo* result) {
   struct addrinfo* resp;
-  struct addrinfo* prev;
   size_t i;
   grpc_resolved_addresses* addresses =
       (grpc_resolved_addresses*)gpr_malloc(sizeof(grpc_resolved_addresses));
@@ -350,16 +350,13 @@
   }
   addresses->addrs = (grpc_resolved_address*)gpr_malloc(
       sizeof(grpc_resolved_address) * addresses->naddrs);
-  i = 0;
-  resp = result;
-  while (resp != nullptr) {
+  for (resp = result, i = 0; resp != nullptr; resp = resp->ai_next, i++) {
     memcpy(&addresses->addrs[i].addr, resp->ai_addr, resp->ai_addrlen);
     addresses->addrs[i].len = resp->ai_addrlen;
-    i++;
-    prev = resp;
-    resp = resp->ai_next;
-    gpr_free(prev);
   }
+  // addrinfo objects are allocated by libuv (e.g. in uv_getaddrinfo)
+  // and not by gpr_malloc
+  uv_freeaddrinfo(result);
   return addresses;
 }
 
@@ -415,10 +412,9 @@
 grpc_custom_resolver_vtable uv_resolver_vtable = {uv_resolve, uv_resolve_async};
 
 grpc_socket_vtable grpc_uv_socket_vtable = {
-    uv_socket_init,       uv_socket_connect,     uv_socket_destroy,
-    uv_socket_shutdown,   uv_socket_close,       uv_socket_write,
-    uv_socket_read,       uv_socket_getpeername, uv_socket_getsockname,
-    uv_socket_setsockopt, uv_socket_bind,        uv_socket_listen,
-    uv_socket_accept};
+    uv_socket_init,     uv_socket_connect,     uv_socket_destroy,
+    uv_socket_shutdown, uv_socket_close,       uv_socket_write,
+    uv_socket_read,     uv_socket_getpeername, uv_socket_getsockname,
+    uv_socket_bind,     uv_socket_listen,      uv_socket_accept};
 
 #endif
diff --git a/src/core/lib/iomgr/tcp_windows.cc b/src/core/lib/iomgr/tcp_windows.cc
index 04e6f11..5d316d4 100644
--- a/src/core/lib/iomgr/tcp_windows.cc
+++ b/src/core/lib/iomgr/tcp_windows.cc
@@ -74,12 +74,28 @@
              : GRPC_WSA_ERROR(WSAGetLastError(), "setsockopt(IPV6_V6ONLY)");
 }
 
+static grpc_error* enable_loopback_fast_path(SOCKET sock) {
+  int status;
+  uint32_t param = 1;
+  DWORD ret;
+  status = WSAIoctl(sock, /*SIO_LOOPBACK_FAST_PATH==*/_WSAIOW(IOC_VENDOR, 16),
+                    &param, sizeof(param), NULL, 0, &ret, 0, 0);
+  if (status == SOCKET_ERROR) {
+    status = WSAGetLastError();
+  }
+  return status == 0 || status == WSAEOPNOTSUPP
+             ? GRPC_ERROR_NONE
+             : GRPC_WSA_ERROR(status, "WSAIoctl(SIO_LOOPBACK_FAST_PATH)");
+}
+
 grpc_error* grpc_tcp_prepare_socket(SOCKET sock) {
   grpc_error* err;
   err = set_non_block(sock);
   if (err != GRPC_ERROR_NONE) return err;
   err = set_dualstack(sock);
   if (err != GRPC_ERROR_NONE) return err;
+  err = enable_loopback_fast_path(sock);
+  if (err != GRPC_ERROR_NONE) return err;
   return GRPC_ERROR_NONE;
 }
 
diff --git a/src/core/lib/iomgr/timer_generic.cc b/src/core/lib/iomgr/timer_generic.cc
index 93e654b..de2256f 100644
--- a/src/core/lib/iomgr/timer_generic.cc
+++ b/src/core/lib/iomgr/timer_generic.cc
@@ -97,6 +97,12 @@
   }
 }
 
+static void destroy_timer_ht() {
+  for (int i = 0; i < NUM_HASH_BUCKETS; i++) {
+    gpr_mu_destroy(&g_hash_mu[i]);
+  }
+}
+
 static bool is_in_ht(grpc_timer* t) {
   size_t i = GPR_HASH_POINTER(t, NUM_HASH_BUCKETS);
 
@@ -188,6 +194,7 @@
 }
 
 #define INIT_TIMER_HASH_TABLE() init_timer_ht()
+#define DESTROY_TIMER_HASH_TABLE() destroy_timer_ht()
 #define ADD_TO_HASH_TABLE(t) add_to_ht((t))
 #define REMOVE_FROM_HASH_TABLE(t) remove_from_ht((t))
 #define VALIDATE_NON_PENDING_TIMER(t) validate_non_pending_timer((t))
@@ -195,6 +202,7 @@
 #else
 
 #define INIT_TIMER_HASH_TABLE()
+#define DESTROY_TIMER_HASH_TABLE()
 #define ADD_TO_HASH_TABLE(t)
 #define REMOVE_FROM_HASH_TABLE(t)
 #define VALIDATE_NON_PENDING_TIMER(t)
@@ -283,6 +291,8 @@
   gpr_free(g_shards);
   gpr_free(g_shard_queue);
   g_shared_mutables.initialized = false;
+
+  DESTROY_TIMER_HASH_TABLE();
 }
 
 /* returns true if the first element in the list */
@@ -336,9 +346,9 @@
 #endif
 
   if (grpc_timer_trace.enabled()) {
-    gpr_log(GPR_DEBUG,
-            "TIMER %p: SET %" PRIdPTR " now %" PRIdPTR " call %p[%p]", timer,
-            deadline, grpc_core::ExecCtx::Get()->Now(), closure, closure->cb);
+    gpr_log(GPR_INFO, "TIMER %p: SET %" PRIdPTR " now %" PRIdPTR " call %p[%p]",
+            timer, deadline, grpc_core::ExecCtx::Get()->Now(), closure,
+            closure->cb);
   }
 
   if (!g_shared_mutables.initialized) {
@@ -372,7 +382,7 @@
     list_join(&shard->list, timer);
   }
   if (grpc_timer_trace.enabled()) {
-    gpr_log(GPR_DEBUG,
+    gpr_log(GPR_INFO,
             "  .. add to shard %d with queue_deadline_cap=%" PRIdPTR
             " => is_first_timer=%s",
             static_cast<int>(shard - g_shards), shard->queue_deadline_cap,
@@ -394,7 +404,7 @@
   if (is_first_timer) {
     gpr_mu_lock(&g_shared_mutables.mu);
     if (grpc_timer_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "  .. old shard min_deadline=%" PRIdPTR,
+      gpr_log(GPR_INFO, "  .. old shard min_deadline=%" PRIdPTR,
               shard->min_deadline);
     }
     if (deadline < shard->min_deadline) {
@@ -424,7 +434,7 @@
   timer_shard* shard = &g_shards[GPR_HASH_POINTER(timer, g_num_shards)];
   gpr_mu_lock(&shard->mu);
   if (grpc_timer_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "TIMER %p: CANCEL pending=%s", timer,
+    gpr_log(GPR_INFO, "TIMER %p: CANCEL pending=%s", timer,
             timer->pending ? "true" : "false");
   }
 
@@ -465,7 +475,7 @@
                      static_cast<gpr_atm>(deadline_delta * 1000.0));
 
   if (grpc_timer_check_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "  .. shard[%d]->queue_deadline_cap --> %" PRIdPTR,
+    gpr_log(GPR_INFO, "  .. shard[%d]->queue_deadline_cap --> %" PRIdPTR,
             static_cast<int>(shard - g_shards), shard->queue_deadline_cap);
   }
   for (timer = shard->list.next; timer != &shard->list; timer = next) {
@@ -473,7 +483,7 @@
 
     if (timer->deadline < shard->queue_deadline_cap) {
       if (grpc_timer_check_trace.enabled()) {
-        gpr_log(GPR_DEBUG, "  .. add timer with deadline %" PRIdPTR " to heap",
+        gpr_log(GPR_INFO, "  .. add timer with deadline %" PRIdPTR " to heap",
                 timer->deadline);
       }
       list_remove(timer);
@@ -490,7 +500,7 @@
   grpc_timer* timer;
   for (;;) {
     if (grpc_timer_check_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "  .. shard[%d]: heap_empty=%s",
+      gpr_log(GPR_INFO, "  .. shard[%d]: heap_empty=%s",
               static_cast<int>(shard - g_shards),
               grpc_timer_heap_is_empty(&shard->heap) ? "true" : "false");
     }
@@ -500,13 +510,13 @@
     }
     timer = grpc_timer_heap_top(&shard->heap);
     if (grpc_timer_check_trace.enabled()) {
-      gpr_log(GPR_DEBUG,
+      gpr_log(GPR_INFO,
               "  .. check top timer deadline=%" PRIdPTR " now=%" PRIdPTR,
               timer->deadline, now);
     }
     if (timer->deadline > now) return nullptr;
     if (grpc_timer_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "TIMER %p: FIRE %" PRIdPTR "ms late via %s scheduler",
+      gpr_log(GPR_INFO, "TIMER %p: FIRE %" PRIdPTR "ms late via %s scheduler",
               timer, now - timer->deadline,
               timer->closure->scheduler->vtable->name);
     }
@@ -530,7 +540,7 @@
   *new_min_deadline = compute_min_deadline(shard);
   gpr_mu_unlock(&shard->mu);
   if (grpc_timer_check_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "  .. shard[%d] popped %" PRIdPTR,
+    gpr_log(GPR_INFO, "  .. shard[%d] popped %" PRIdPTR,
             static_cast<int>(shard - g_shards), n);
   }
   return n;
@@ -553,7 +563,7 @@
     result = GRPC_TIMERS_CHECKED_AND_EMPTY;
 
     if (grpc_timer_check_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "  .. shard[%d]->min_deadline = %" PRIdPTR,
+      gpr_log(GPR_INFO, "  .. shard[%d]->min_deadline = %" PRIdPTR,
               static_cast<int>(g_shard_queue[0] - g_shards),
               g_shard_queue[0]->min_deadline);
     }
@@ -570,7 +580,7 @@
       }
 
       if (grpc_timer_check_trace.enabled()) {
-        gpr_log(GPR_DEBUG,
+        gpr_log(GPR_INFO,
                 "  .. result --> %d"
                 ", shard[%d]->min_deadline %" PRIdPTR " --> %" PRIdPTR
                 ", now=%" PRIdPTR,
@@ -614,7 +624,7 @@
       *next = GPR_MIN(*next, min_timer);
     }
     if (grpc_timer_check_trace.enabled()) {
-      gpr_log(GPR_DEBUG,
+      gpr_log(GPR_INFO,
               "TIMER CHECK SKIP: now=%" PRIdPTR " min_timer=%" PRIdPTR, now,
               min_timer);
     }
@@ -634,7 +644,7 @@
     } else {
       gpr_asprintf(&next_str, "%" PRIdPTR, *next);
     }
-    gpr_log(GPR_DEBUG,
+    gpr_log(GPR_INFO,
             "TIMER CHECK BEGIN: now=%" PRIdPTR " next=%s tls_min=%" PRIdPTR
             " glob_min=%" PRIdPTR,
             now, next_str, gpr_tls_get(&g_last_seen_min_timer),
@@ -652,7 +662,7 @@
     } else {
       gpr_asprintf(&next_str, "%" PRIdPTR, *next);
     }
-    gpr_log(GPR_DEBUG, "TIMER CHECK END: r=%d; next=%s", r, next_str);
+    gpr_log(GPR_INFO, "TIMER CHECK END: r=%d; next=%s", r, next_str);
     gpr_free(next_str);
   }
   return r;
diff --git a/src/core/lib/iomgr/timer_manager.cc b/src/core/lib/iomgr/timer_manager.cc
index 94f288a..35e7914 100644
--- a/src/core/lib/iomgr/timer_manager.cc
+++ b/src/core/lib/iomgr/timer_manager.cc
@@ -82,7 +82,7 @@
   ++g_thread_count;
   gpr_mu_unlock(&g_mu);
   if (grpc_timer_check_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "Spawn timer thread");
+    gpr_log(GPR_INFO, "Spawn timer thread");
   }
   completed_thread* ct =
       static_cast<completed_thread*>(gpr_malloc(sizeof(*ct)));
@@ -108,7 +108,7 @@
     // waiter so that the next deadline is not missed
     if (!g_has_timed_waiter) {
       if (grpc_timer_check_trace.enabled()) {
-        gpr_log(GPR_DEBUG, "kick untimed waiter");
+        gpr_log(GPR_INFO, "kick untimed waiter");
       }
       gpr_cv_signal(&g_cv_wait);
     }
@@ -116,7 +116,7 @@
   }
   // without our lock, flush the exec_ctx
   if (grpc_timer_check_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "flush exec_ctx");
+    gpr_log(GPR_INFO, "flush exec_ctx");
   }
   grpc_core::ExecCtx::Get()->Flush();
   gpr_mu_lock(&g_mu);
@@ -172,8 +172,7 @@
 
         if (grpc_timer_check_trace.enabled()) {
           grpc_millis wait_time = next - grpc_core::ExecCtx::Get()->Now();
-          gpr_log(GPR_DEBUG, "sleep for a %" PRIdPTR " milliseconds",
-                  wait_time);
+          gpr_log(GPR_INFO, "sleep for a %" PRIdPTR " milliseconds", wait_time);
         }
       } else {  // g_timed_waiter == true && next >= g_timed_waiter_deadline
         next = GRPC_MILLIS_INF_FUTURE;
@@ -181,14 +180,14 @@
     }
 
     if (grpc_timer_check_trace.enabled() && next == GRPC_MILLIS_INF_FUTURE) {
-      gpr_log(GPR_DEBUG, "sleep until kicked");
+      gpr_log(GPR_INFO, "sleep until kicked");
     }
 
     gpr_cv_wait(&g_cv_wait, &g_mu,
                 grpc_millis_to_timespec(next, GPR_CLOCK_MONOTONIC));
 
     if (grpc_timer_check_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "wait ended: was_timed:%d kicked:%d",
+      gpr_log(GPR_INFO, "wait ended: was_timed:%d kicked:%d",
               my_timed_waiter_generation == g_timed_waiter_generation,
               g_kicked);
     }
@@ -233,7 +232,7 @@
            Consequently, we can just sleep forever here and be happy at some
            saved wakeup cycles. */
         if (grpc_timer_check_trace.enabled()) {
-          gpr_log(GPR_DEBUG, "timers not checked: expect another thread to");
+          gpr_log(GPR_INFO, "timers not checked: expect another thread to");
         }
         next = GRPC_MILLIS_INF_FUTURE;
       /* fall through */
@@ -259,7 +258,7 @@
   g_completed_threads = ct;
   gpr_mu_unlock(&g_mu);
   if (grpc_timer_check_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "End timer thread");
+    gpr_log(GPR_INFO, "End timer thread");
   }
 }
 
@@ -301,18 +300,18 @@
 static void stop_threads(void) {
   gpr_mu_lock(&g_mu);
   if (grpc_timer_check_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "stop timer threads: threaded=%d", g_threaded);
+    gpr_log(GPR_INFO, "stop timer threads: threaded=%d", g_threaded);
   }
   if (g_threaded) {
     g_threaded = false;
     gpr_cv_broadcast(&g_cv_wait);
     if (grpc_timer_check_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "num timer threads: %d", g_thread_count);
+      gpr_log(GPR_INFO, "num timer threads: %d", g_thread_count);
     }
     while (g_thread_count > 0) {
       gpr_cv_wait(&g_cv_shutdown, &g_mu, gpr_inf_future(GPR_CLOCK_MONOTONIC));
       if (grpc_timer_check_trace.enabled()) {
-        gpr_log(GPR_DEBUG, "num timer threads: %d", g_thread_count);
+        gpr_log(GPR_INFO, "num timer threads: %d", g_thread_count);
       }
       gc_completed_threads();
     }
diff --git a/src/core/lib/iomgr/timer_uv.cc b/src/core/lib/iomgr/timer_uv.cc
index dadeb96..8b7c82e 100644
--- a/src/core/lib/iomgr/timer_uv.cc
+++ b/src/core/lib/iomgr/timer_uv.cc
@@ -52,6 +52,9 @@
   uv_timer->data = t;
   t->timer = (void*)uv_timer;
   uv_timer_start(uv_timer, run_expired_timer, t->timeout_ms, 0);
+  // Node uses a garbage collector to call destructors, so we don't
+  // want to hold the uv loop open with active gRPC objects.
+  uv_unref((uv_handle_t*)uv_timer);
 }
 
 static void timer_stop(grpc_custom_timer* t) {
diff --git a/src/core/lib/iomgr/udp_server.cc b/src/core/lib/iomgr/udp_server.cc
index 04716a2..51d17eb 100644
--- a/src/core/lib/iomgr/udp_server.cc
+++ b/src/core/lib/iomgr/udp_server.cc
@@ -191,6 +191,9 @@
   size_t pollset_count;
   /* opaque object to pass to callbacks */
   void* user_data;
+
+  /* latch has_so_reuseport during server creation */
+  bool so_reuseport;
 };
 
 static grpc_socket_factory* get_socket_factory(const grpc_channel_args* args) {
@@ -214,6 +217,7 @@
   s->active_ports = 0;
   s->destroyed_ports = 0;
   s->shutdown = 0;
+  s->so_reuseport = grpc_is_socket_reuse_port_supported();
   return s;
 }
 
@@ -353,7 +357,7 @@
 /* Prepare a recently-created socket for listening. */
 static int prepare_socket(grpc_socket_factory* socket_factory, int fd,
                           const grpc_resolved_address* addr, int rcv_buf_size,
-                          int snd_buf_size) {
+                          int snd_buf_size, bool so_reuseport) {
   grpc_resolved_address sockname_temp;
   grpc_sockaddr* addr_ptr =
       reinterpret_cast<grpc_sockaddr*>(const_cast<char*>(addr->addr));
@@ -381,22 +385,6 @@
     }
   }
 
-  GPR_ASSERT(addr->len < ~(socklen_t)0);
-  if (bind_socket(socket_factory, fd, addr) < 0) {
-    char* addr_str;
-    grpc_sockaddr_to_string(&addr_str, addr, 0);
-    gpr_log(GPR_ERROR, "bind addr=%s: %s", addr_str, strerror(errno));
-    gpr_free(addr_str);
-    goto error;
-  }
-
-  sockname_temp.len = static_cast<socklen_t>(sizeof(struct sockaddr_storage));
-
-  if (getsockname(fd, reinterpret_cast<grpc_sockaddr*>(sockname_temp.addr),
-                  &sockname_temp.len) < 0) {
-    goto error;
-  }
-
   if (grpc_set_socket_sndbuf(fd, snd_buf_size) != GRPC_ERROR_NONE) {
     gpr_log(GPR_ERROR, "Failed to set send buffer size to %d bytes",
             snd_buf_size);
@@ -416,6 +404,30 @@
       gpr_log(GPR_INFO, "Failed to set socket overflow support");
     }
   }
+
+  if (so_reuseport && !grpc_is_unix_socket(addr) &&
+      grpc_set_socket_reuse_port(fd, 1) != GRPC_ERROR_NONE) {
+    gpr_log(GPR_ERROR, "Failed to set SO_REUSEPORT for fd %d", fd);
+    goto error;
+  }
+
+  if (bind_socket(socket_factory, fd, addr) < 0) {
+    char* addr_str;
+    grpc_sockaddr_to_string(&addr_str, addr, 0);
+    gpr_log(GPR_ERROR, "bind addr=%s: %s", addr_str, strerror(errno));
+    gpr_free(addr_str);
+    goto error;
+  }
+
+  sockname_temp.len = static_cast<socklen_t>(sizeof(struct sockaddr_storage));
+
+  if (getsockname(fd, reinterpret_cast<grpc_sockaddr*>(sockname_temp.addr),
+                  &sockname_temp.len) < 0) {
+    gpr_log(GPR_ERROR, "Unable to get the address socket %d is bound to: %s",
+            fd, strerror(errno));
+    goto error;
+  }
+
   return grpc_sockaddr_get_port(&sockname_temp);
 
 error:
@@ -542,8 +554,8 @@
                                 int rcv_buf_size, int snd_buf_size) {
   gpr_log(GPR_DEBUG, "add socket %d to server", fd);
 
-  int port =
-      prepare_socket(s->socket_factory, fd, addr, rcv_buf_size, snd_buf_size);
+  int port = prepare_socket(s->socket_factory, fd, addr, rcv_buf_size,
+                            snd_buf_size, s->so_reuseport);
   if (port >= 0) {
     gpr_mu_lock(&s->mu);
     s->listeners.emplace_back(s, fd, addr);
@@ -558,7 +570,18 @@
 int grpc_udp_server_add_port(grpc_udp_server* s,
                              const grpc_resolved_address* addr,
                              int rcv_buf_size, int snd_buf_size,
-                             GrpcUdpHandlerFactory* handler_factory) {
+                             GrpcUdpHandlerFactory* handler_factory,
+                             size_t num_listeners) {
+  if (num_listeners > 1 && !s->so_reuseport) {
+    gpr_log(GPR_ERROR,
+            "Try to have multiple listeners on same port, but SO_REUSEPORT is "
+            "not supported. Only create 1 listener.");
+  }
+  char* addr_str;
+  grpc_sockaddr_to_string(&addr_str, addr, 1);
+  gpr_log(GPR_DEBUG, "add address: %s to server", addr_str);
+  gpr_free(addr_str);
+
   int allocated_port1 = -1;
   int allocated_port2 = -1;
   int fd;
@@ -569,11 +592,12 @@
   grpc_resolved_address addr4_copy;
   grpc_resolved_address* allocated_addr = nullptr;
   grpc_resolved_address sockname_temp;
-  int port;
+  int port = 0;
 
   /* Check if this is a wildcard port, and if so, try to keep the port the same
      as some previously created listener. */
   if (grpc_sockaddr_get_port(addr) == 0) {
+    /* Loop through existing listeners to find the port in use. */
     for (size_t i = 0; i < s->listeners.size(); ++i) {
       sockname_temp.len =
           static_cast<socklen_t>(sizeof(struct sockaddr_storage));
@@ -582,6 +606,7 @@
                            &sockname_temp.len)) {
         port = grpc_sockaddr_get_port(&sockname_temp);
         if (port > 0) {
+          /* Found such a port, update |addr| to reflects this port. */
           allocated_addr = static_cast<grpc_resolved_address*>(
               gpr_malloc(sizeof(grpc_resolved_address)));
           memcpy(allocated_addr, addr, sizeof(grpc_resolved_address));
@@ -598,44 +623,73 @@
   }
 
   s->handler_factory = handler_factory;
-  /* Treat :: or 0.0.0.0 as a family-agnostic wildcard. */
-  if (grpc_sockaddr_is_wildcard(addr, &port)) {
-    grpc_sockaddr_make_wildcards(port, &wild4, &wild6);
+  for (size_t i = 0; i < num_listeners; ++i) {
+    /* Treat :: or 0.0.0.0 as a family-agnostic wildcard. */
+    if (grpc_sockaddr_is_wildcard(addr, &port)) {
+      grpc_sockaddr_make_wildcards(port, &wild4, &wild6);
 
-    /* Try listening on IPv6 first. */
-    addr = &wild6;
+      /* Try listening on IPv6 first. */
+      addr = &wild6;
+      // TODO(rjshade): Test and propagate the returned grpc_error*:
+      GRPC_ERROR_UNREF(grpc_create_dualstack_socket_using_factory(
+          s->socket_factory, addr, SOCK_DGRAM, IPPROTO_UDP, &dsmode, &fd));
+      allocated_port1 =
+          add_socket_to_server(s, fd, addr, rcv_buf_size, snd_buf_size);
+      if (fd >= 0 && dsmode == GRPC_DSMODE_DUALSTACK) {
+        if (port == 0) {
+          /* This is the first time to bind to |addr|. If its port is still
+           * wildcard port, update |addr| with the ephermeral port returned by
+           * kernel. Thus |addr| can have a specific port in following
+           * iterations. */
+          grpc_sockaddr_set_port(addr, allocated_port1);
+          port = allocated_port1;
+        } else if (allocated_port1 >= 0) {
+          /* The following sucessfully created socket should have same port as
+           * the first one. */
+          GPR_ASSERT(port == allocated_port1);
+        }
+        /* A dualstack socket is created, no need to create corresponding IPV4
+         * socket. */
+        continue;
+      }
+
+      /* If we didn't get a dualstack socket, also listen on 0.0.0.0. */
+      if (port == 0 && allocated_port1 > 0) {
+        /* |port| hasn't been assigned to an emphemeral port yet, |wild4| must
+         * have a wildcard port. Update it with the emphemeral port created
+         * during binding.*/
+        grpc_sockaddr_set_port(&wild4, allocated_port1);
+        port = allocated_port1;
+      }
+      /* |wild4| should have been updated with an emphemeral port by now. Use
+       * this IPV4 address to create a IPV4 socket. */
+      addr = &wild4;
+    }
+
     // TODO(rjshade): Test and propagate the returned grpc_error*:
     GRPC_ERROR_UNREF(grpc_create_dualstack_socket_using_factory(
         s->socket_factory, addr, SOCK_DGRAM, IPPROTO_UDP, &dsmode, &fd));
-    allocated_port1 =
+    if (fd < 0) {
+      gpr_log(GPR_ERROR, "Unable to create socket: %s", strerror(errno));
+    }
+    if (dsmode == GRPC_DSMODE_IPV4 &&
+        grpc_sockaddr_is_v4mapped(addr, &addr4_copy)) {
+      addr = &addr4_copy;
+    }
+    allocated_port2 =
         add_socket_to_server(s, fd, addr, rcv_buf_size, snd_buf_size);
-    if (fd >= 0 && dsmode == GRPC_DSMODE_DUALSTACK) {
-      goto done;
+    if (port == 0) {
+      /* Update |addr| with the ephermeral port returned by kernel. So |addr|
+       * can have a specific port in following iterations. */
+      grpc_sockaddr_set_port(addr, allocated_port2);
+      port = allocated_port2;
+    } else if (allocated_port2 >= 0) {
+      GPR_ASSERT(port == allocated_port2);
     }
-
-    /* If we didn't get a dualstack socket, also listen on 0.0.0.0. */
-    if (port == 0 && allocated_port1 > 0) {
-      grpc_sockaddr_set_port(&wild4, allocated_port1);
-    }
-    addr = &wild4;
   }
 
-  // TODO(rjshade): Test and propagate the returned grpc_error*:
-  GRPC_ERROR_UNREF(grpc_create_dualstack_socket_using_factory(
-      s->socket_factory, addr, SOCK_DGRAM, IPPROTO_UDP, &dsmode, &fd));
-  if (fd < 0) {
-    gpr_log(GPR_ERROR, "Unable to create socket: %s", strerror(errno));
-  }
-  if (dsmode == GRPC_DSMODE_IPV4 &&
-      grpc_sockaddr_is_v4mapped(addr, &addr4_copy)) {
-    addr = &addr4_copy;
-  }
-  allocated_port2 =
-      add_socket_to_server(s, fd, addr, rcv_buf_size, snd_buf_size);
-
-done:
   gpr_free(allocated_addr);
-  return allocated_port1 >= 0 ? allocated_port1 : allocated_port2;
+  return port;
 }
 
 int grpc_udp_server_get_fd(grpc_udp_server* s, unsigned port_index) {
diff --git a/src/core/lib/iomgr/udp_server.h b/src/core/lib/iomgr/udp_server.h
index 4e384d2..3656791 100644
--- a/src/core/lib/iomgr/udp_server.h
+++ b/src/core/lib/iomgr/udp_server.h
@@ -86,17 +86,21 @@
 /* Add a port to the server, returning port number on success, or negative
    on failure.
 
+   Create |num_listeners| sockets for given address to listen on using
+   SO_REUSEPORT if supported.
+
    The :: and 0.0.0.0 wildcard addresses are treated identically, accepting
-   both IPv4 and IPv6 connections, but :: is the preferred style.  This usually
-   creates one socket, but possibly two on systems which support IPv6,
-   but not dualstack sockets. */
+   both IPv4 and IPv6 connections, but :: is the preferred style. This usually
+   creates |num_listeners| sockets, but possibly 2 * |num_listeners| on systems
+   which support IPv6, but not dualstack sockets. */
 
 /* TODO(ctiller): deprecate this, and make grpc_udp_server_add_ports to handle
                   all of the multiple socket port matching logic in one place */
 int grpc_udp_server_add_port(grpc_udp_server* s,
                              const grpc_resolved_address* addr,
                              int rcv_buf_size, int snd_buf_size,
-                             GrpcUdpHandlerFactory* handler_factory);
+                             GrpcUdpHandlerFactory* handler_factory,
+                             size_t num_listeners);
 
 void grpc_udp_server_destroy(grpc_udp_server* server, grpc_closure* on_done);
 
diff --git a/src/core/lib/profiling/basic_timers.cc b/src/core/lib/profiling/basic_timers.cc
index 652a498..b19ad9f 100644
--- a/src/core/lib/profiling/basic_timers.cc
+++ b/src/core/lib/profiling/basic_timers.cc
@@ -27,6 +27,7 @@
 #include <grpc/support/sync.h>
 #include <grpc/support/time.h>
 #include <inttypes.h>
+#include <pthread.h>
 #include <stdio.h>
 #include <string.h>
 
diff --git a/src/core/lib/security/credentials/alts/alts_credentials.h b/src/core/lib/security/credentials/alts/alts_credentials.h
index 621789c..810117f 100644
--- a/src/core/lib/security/credentials/alts/alts_credentials.h
+++ b/src/core/lib/security/credentials/alts/alts_credentials.h
@@ -41,26 +41,6 @@
 } grpc_alts_server_credentials;
 
 /**
- * This method creates an ALTS channel credential object.
- *
- * - options: grpc ALTS credentials options instance for client.
- *
- * It returns the created ALTS channel credential object.
- */
-grpc_channel_credentials* grpc_alts_credentials_create(
-    const grpc_alts_credentials_options* options);
-
-/**
- * This method creates an ALTS server credential object.
- *
- * - options: grpc ALTS credentials options instance for server.
- *
- * It returns the created ALTS server credential object.
- */
-grpc_server_credentials* grpc_alts_server_credentials_create(
-    const grpc_alts_credentials_options* options);
-
-/**
  * This method creates an ALTS channel credential object with customized
  * information provided by caller.
  *
diff --git a/src/core/lib/security/credentials/alts/grpc_alts_credentials_client_options.cc b/src/core/lib/security/credentials/alts/grpc_alts_credentials_client_options.cc
index 7d54e83..0a39c6c 100644
--- a/src/core/lib/security/credentials/alts/grpc_alts_credentials_client_options.cc
+++ b/src/core/lib/security/credentials/alts/grpc_alts_credentials_client_options.cc
@@ -44,20 +44,20 @@
   return sa;
 }
 
-bool grpc_alts_credentials_client_options_add_target_service_account(
-    grpc_alts_credentials_client_options* options,
-    const char* service_account) {
+void grpc_alts_credentials_client_options_add_target_service_account(
+    grpc_alts_credentials_options* options, const char* service_account) {
   if (options == nullptr || service_account == nullptr) {
     gpr_log(
         GPR_ERROR,
         "Invalid nullptr arguments to "
         "grpc_alts_credentials_client_options_add_target_service_account()");
-    return false;
+    return;
   }
+  auto client_options =
+      reinterpret_cast<grpc_alts_credentials_client_options*>(options);
   target_service_account* node = target_service_account_create(service_account);
-  node->next = options->target_account_list_head;
-  options->target_account_list_head = node;
-  return true;
+  node->next = client_options->target_account_list_head;
+  client_options->target_account_list_head = node;
 }
 
 static void target_service_account_destroy(
diff --git a/src/core/lib/security/credentials/alts/grpc_alts_credentials_options.h b/src/core/lib/security/credentials/alts/grpc_alts_credentials_options.h
index 4e46d9f..320af71 100644
--- a/src/core/lib/security/credentials/alts/grpc_alts_credentials_options.h
+++ b/src/core/lib/security/credentials/alts/grpc_alts_credentials_options.h
@@ -21,19 +21,10 @@
 
 #include <grpc/support/port_platform.h>
 
-#include <stdbool.h>
+#include <grpc/grpc_security.h>
 
 #include "src/core/tsi/alts/handshaker/transport_security_common_api.h"
 
-/**
- * Main interface for ALTS credentials options. The options will contain
- * information that will be passed from grpc to TSI layer such as RPC protocol
- * versions. ALTS client (channel) and server credentials will have their own
- * implementation of this interface. The APIs listed in this header are
- * thread-compatible.
- */
-typedef struct grpc_alts_credentials_options grpc_alts_credentials_options;
-
 /* V-table for grpc_alts_credentials_options */
 typedef struct grpc_alts_credentials_options_vtable {
   grpc_alts_credentials_options* (*copy)(
@@ -80,33 +71,5 @@
 grpc_alts_credentials_options* grpc_alts_credentials_options_copy(
     const grpc_alts_credentials_options* options);
 
-/**
- * This method destroys a grpc_alts_credentials_options instance by
- * de-allocating all of its occupied memory.
- *
- * - options: a grpc_alts_credentials_options instance that needs to be
- *   destroyed.
- */
-void grpc_alts_credentials_options_destroy(
-    grpc_alts_credentials_options* options);
-
-/* This method creates a grpc ALTS credentials client options instance. */
-grpc_alts_credentials_options* grpc_alts_credentials_client_options_create();
-
-/* This method creates a grpc ALTS credentials server options instance. */
-grpc_alts_credentials_options* grpc_alts_credentials_server_options_create();
-
-/**
- * This method adds a target service account to grpc ALTS credentials client
- * options instance.
- *
- * - options: grpc ALTS credentials client options instance.
- * - service_account: service account of target endpoint.
- *
- * It returns true on success and false on failure.
- */
-bool grpc_alts_credentials_client_options_add_target_service_account(
-    grpc_alts_credentials_client_options* options, const char* service_account);
-
 #endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_ALTS_GRPC_ALTS_CREDENTIALS_OPTIONS_H \
         */
diff --git a/src/core/lib/security/credentials/credentials.h b/src/core/lib/security/credentials/credentials.h
index b1421e8..b486d25 100644
--- a/src/core/lib/security/credentials/credentials.h
+++ b/src/core/lib/security/credentials/credentials.h
@@ -45,6 +45,7 @@
 #define GRPC_CHANNEL_CREDENTIALS_TYPE_SSL "Ssl"
 #define GRPC_CHANNEL_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY \
   "FakeTransportSecurity"
+#define GRPC_CHANNEL_CREDENTIALS_TYPE_GOOGLE_DEFAULT "GoogleDefault"
 
 #define GRPC_CALL_CREDENTIALS_TYPE_OAUTH2 "Oauth2"
 #define GRPC_CALL_CREDENTIALS_TYPE_JWT "Jwt"
diff --git a/src/core/lib/security/credentials/google_default/google_default_credentials.cc b/src/core/lib/security/credentials/google_default/google_default_credentials.cc
index 70d4c3e..4b267af 100644
--- a/src/core/lib/security/credentials/google_default/google_default_credentials.cc
+++ b/src/core/lib/security/credentials/google_default/google_default_credentials.cc
@@ -26,12 +26,15 @@
 #include <grpc/support/log.h>
 #include <grpc/support/sync.h>
 
+#include "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h"
+#include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/gpr/env.h"
 #include "src/core/lib/gpr/string.h"
 #include "src/core/lib/http/httpcli.h"
 #include "src/core/lib/http/parser.h"
 #include "src/core/lib/iomgr/load_file.h"
 #include "src/core/lib/iomgr/polling_entity.h"
+#include "src/core/lib/security/credentials/alts/alts_credentials.h"
 #include "src/core/lib/security/credentials/google_default/google_default_credentials.h"
 #include "src/core/lib/security/credentials/jwt/jwt_credentials.h"
 #include "src/core/lib/security/credentials/oauth2/oauth2_credentials.h"
@@ -45,8 +48,8 @@
 
 /* -- Default credentials. -- */
 
-static grpc_channel_credentials* default_credentials = nullptr;
-static int compute_engine_detection_done = 0;
+static grpc_channel_credentials* g_default_credentials = nullptr;
+static int g_compute_engine_detection_done = 0;
 static gpr_mu g_state_mu;
 static gpr_mu* g_polling_mu;
 static gpr_once g_once = GPR_ONCE_INIT;
@@ -60,6 +63,52 @@
   grpc_http_response response;
 } compute_engine_detector;
 
+static void google_default_credentials_destruct(
+    grpc_channel_credentials* creds) {
+  grpc_google_default_channel_credentials* c =
+      reinterpret_cast<grpc_google_default_channel_credentials*>(creds);
+  grpc_channel_credentials_unref(c->alts_creds);
+  grpc_channel_credentials_unref(c->ssl_creds);
+}
+
+static grpc_security_status google_default_create_security_connector(
+    grpc_channel_credentials* creds, grpc_call_credentials* call_creds,
+    const char* target, const grpc_channel_args* args,
+    grpc_channel_security_connector** sc, grpc_channel_args** new_args) {
+  grpc_google_default_channel_credentials* c =
+      reinterpret_cast<grpc_google_default_channel_credentials*>(creds);
+  bool is_grpclb_load_balancer = grpc_channel_arg_get_bool(
+      grpc_channel_args_find(args, GRPC_ARG_ADDRESS_IS_GRPCLB_LOAD_BALANCER),
+      false);
+  bool is_backend_from_grpclb_load_balancer = grpc_channel_arg_get_bool(
+      grpc_channel_args_find(
+          args, GRPC_ARG_ADDRESS_IS_BACKEND_FROM_GRPCLB_LOAD_BALANCER),
+      false);
+  bool use_alts =
+      is_grpclb_load_balancer || is_backend_from_grpclb_load_balancer;
+  grpc_security_status status = GRPC_SECURITY_ERROR;
+  status = use_alts ? c->alts_creds->vtable->create_security_connector(
+                          c->alts_creds, call_creds, target, args, sc, new_args)
+                    : c->ssl_creds->vtable->create_security_connector(
+                          c->ssl_creds, call_creds, target, args, sc, new_args);
+  /* grpclb-specific channel args are removed from the channel args set
+   * to ensure backends and fallback adresses will have the same set of channel
+   * args. By doing that, it guarantees the connections to backends will not be
+   * torn down and re-connected when switching in and out of fallback mode.
+   */
+  static const char* args_to_remove[] = {
+      GRPC_ARG_ADDRESS_IS_GRPCLB_LOAD_BALANCER,
+      GRPC_ARG_ADDRESS_IS_BACKEND_FROM_GRPCLB_LOAD_BALANCER,
+  };
+  *new_args = grpc_channel_args_copy_and_add_and_remove(
+      args, args_to_remove, GPR_ARRAY_SIZE(args_to_remove), nullptr, 0);
+  return status;
+}
+
+static grpc_channel_credentials_vtable google_default_credentials_vtable = {
+    google_default_credentials_destruct,
+    google_default_create_security_connector, nullptr};
+
 static void on_compute_engine_detection_http_response(void* user_data,
                                                       grpc_error* error) {
   compute_engine_detector* detector =
@@ -234,8 +283,8 @@
 
   gpr_mu_lock(&g_state_mu);
 
-  if (default_credentials != nullptr) {
-    result = grpc_channel_credentials_ref(default_credentials);
+  if (g_default_credentials != nullptr) {
+    result = grpc_channel_credentials_ref(g_default_credentials);
     goto end;
   }
 
@@ -253,9 +302,9 @@
 
   /* At last try to see if we're on compute engine (do the detection only once
      since it requires a network test). */
-  if (!compute_engine_detection_done) {
+  if (!g_compute_engine_detection_done) {
     int need_compute_engine_creds = is_stack_running_on_compute_engine();
-    compute_engine_detection_done = 1;
+    g_compute_engine_detection_done = 1;
     if (need_compute_engine_creds) {
       call_creds = grpc_google_compute_engine_credentials_create(nullptr);
       if (call_creds == nullptr) {
@@ -269,18 +318,25 @@
 end:
   if (result == nullptr) {
     if (call_creds != nullptr) {
-      /* Blend with default ssl credentials and add a global reference so that
-         it
-         can be cached and re-served. */
-      grpc_channel_credentials* ssl_creds =
-          grpc_ssl_credentials_create(nullptr, nullptr, nullptr);
-      default_credentials = grpc_channel_credentials_ref(
-          grpc_composite_channel_credentials_create(ssl_creds, call_creds,
-                                                    nullptr));
-      GPR_ASSERT(default_credentials != nullptr);
-      grpc_channel_credentials_unref(ssl_creds);
+      /* Create google default credentials. */
+      auto creds = static_cast<grpc_google_default_channel_credentials*>(
+          gpr_zalloc(sizeof(grpc_google_default_channel_credentials)));
+      creds->base.vtable = &google_default_credentials_vtable;
+      creds->base.type = GRPC_CHANNEL_CREDENTIALS_TYPE_GOOGLE_DEFAULT;
+      gpr_ref_init(&creds->base.refcount, 1);
+      creds->ssl_creds = grpc_ssl_credentials_create(nullptr, nullptr, nullptr);
+      GPR_ASSERT(creds->ssl_creds != nullptr);
+      grpc_alts_credentials_options* options =
+          grpc_alts_credentials_client_options_create();
+      creds->alts_creds = grpc_alts_credentials_create(options);
+      grpc_alts_credentials_options_destroy(options);
+      /* Add a global reference so that it can be cached and re-served. */
+      g_default_credentials = grpc_composite_channel_credentials_create(
+          &creds->base, call_creds, nullptr);
+      GPR_ASSERT(g_default_credentials != nullptr);
+      grpc_channel_credentials_unref(&creds->base);
       grpc_call_credentials_unref(call_creds);
-      result = default_credentials;
+      result = grpc_channel_credentials_ref(g_default_credentials);
     } else {
       gpr_log(GPR_ERROR, "Could not create google default credentials.");
     }
@@ -299,11 +355,11 @@
   grpc_core::ExecCtx exec_ctx;
   gpr_once_init(&g_once, init_default_credentials);
   gpr_mu_lock(&g_state_mu);
-  if (default_credentials != nullptr) {
-    grpc_channel_credentials_unref(default_credentials);
-    default_credentials = nullptr;
+  if (g_default_credentials != nullptr) {
+    grpc_channel_credentials_unref(g_default_credentials);
+    g_default_credentials = nullptr;
   }
-  compute_engine_detection_done = 0;
+  g_compute_engine_detection_done = 0;
   gpr_mu_unlock(&g_state_mu);
 }
 
diff --git a/src/core/lib/security/credentials/google_default/google_default_credentials.h b/src/core/lib/security/credentials/google_default/google_default_credentials.h
index b163e48..9b4063c 100644
--- a/src/core/lib/security/credentials/google_default/google_default_credentials.h
+++ b/src/core/lib/security/credentials/google_default/google_default_credentials.h
@@ -39,6 +39,12 @@
   "/" GRPC_GOOGLE_WELL_KNOWN_CREDENTIALS_FILE
 #endif
 
+typedef struct {
+  grpc_channel_credentials base;
+  grpc_channel_credentials* alts_creds;
+  grpc_channel_credentials* ssl_creds;
+} grpc_google_default_channel_credentials;
+
 void grpc_flush_cached_google_default_credentials(void);
 
 #endif /* GRPC_CORE_LIB_SECURITY_CREDENTIALS_GOOGLE_DEFAULT_GOOGLE_DEFAULT_CREDENTIALS_H \
diff --git a/src/core/lib/security/security_connector/security_connector.cc b/src/core/lib/security/security_connector/security_connector.cc
index 3967112..a306967 100644
--- a/src/core/lib/security/security_connector/security_connector.cc
+++ b/src/core/lib/security/security_connector/security_connector.cc
@@ -44,7 +44,6 @@
 #include "src/core/lib/security/transport/target_authority_table.h"
 #include "src/core/tsi/fake_transport_security.h"
 #include "src/core/tsi/ssl_transport_security.h"
-#include "src/core/tsi/transport_security_adapter.h"
 
 grpc_core::DebugOnlyTraceFlag grpc_trace_security_connector_refcount(
     false, "security_connector_refcount");
@@ -306,6 +305,7 @@
   char* target;
   char* expected_targets;
   bool is_lb_channel;
+  char* target_name_override;
 } grpc_fake_channel_security_connector;
 
 static void fake_channel_destroy(grpc_security_connector* sc) {
@@ -314,6 +314,7 @@
   grpc_call_credentials_unref(c->base.request_metadata_creds);
   gpr_free(c->target);
   gpr_free(c->expected_targets);
+  gpr_free(c->target_name_override);
   gpr_free(c);
 }
 
@@ -465,13 +466,36 @@
                                          grpc_error** error) {
   grpc_fake_channel_security_connector* c =
       reinterpret_cast<grpc_fake_channel_security_connector*>(sc);
-  if (c->is_lb_channel) {
-    // TODO(dgq): verify that the host (ie, authority header) matches that of
-    // the LB, as opposed to that of the backends.
-  } else {
-    // TODO(dgq): verify that the host (ie, authority header) matches that of
-    // the backend, not the LB's.
+  char* authority_hostname = nullptr;
+  char* authority_ignored_port = nullptr;
+  char* target_hostname = nullptr;
+  char* target_ignored_port = nullptr;
+  gpr_split_host_port(host, &authority_hostname, &authority_ignored_port);
+  gpr_split_host_port(c->target, &target_hostname, &target_ignored_port);
+  if (c->target_name_override != nullptr) {
+    char* fake_security_target_name_override_hostname = nullptr;
+    char* fake_security_target_name_override_ignored_port = nullptr;
+    gpr_split_host_port(c->target_name_override,
+                        &fake_security_target_name_override_hostname,
+                        &fake_security_target_name_override_ignored_port);
+    if (strcmp(authority_hostname,
+               fake_security_target_name_override_hostname) != 0) {
+      gpr_log(GPR_ERROR,
+              "Authority (host) '%s' != Fake Security Target override '%s'",
+              host, fake_security_target_name_override_hostname);
+      abort();
+    }
+    gpr_free(fake_security_target_name_override_hostname);
+    gpr_free(fake_security_target_name_override_ignored_port);
+  } else if (strcmp(authority_hostname, target_hostname) != 0) {
+    gpr_log(GPR_ERROR, "Authority (host) '%s' != Target '%s'",
+            authority_hostname, target_hostname);
+    abort();
   }
+  gpr_free(authority_hostname);
+  gpr_free(authority_ignored_port);
+  gpr_free(target_hostname);
+  gpr_free(target_ignored_port);
   return true;
 }
 
@@ -524,6 +548,12 @@
   const char* expected_targets = grpc_fake_transport_get_expected_targets(args);
   c->expected_targets = gpr_strdup(expected_targets);
   c->is_lb_channel = grpc_core::FindTargetAuthorityTableInArgs(args) != nullptr;
+  const grpc_arg* target_name_override_arg =
+      grpc_channel_args_find(args, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG);
+  if (target_name_override_arg != nullptr) {
+    c->target_name_override =
+        gpr_strdup(grpc_channel_arg_get_string(target_name_override_arg));
+  }
   return &c->base;
 }
 
@@ -642,8 +672,7 @@
   }
   // Create handshakers.
   grpc_handshake_manager_add(
-      handshake_mgr, grpc_security_handshaker_create(
-                         tsi_create_adapter_handshaker(tsi_hs), &sc->base));
+      handshake_mgr, grpc_security_handshaker_create(tsi_hs, &sc->base));
 }
 
 static const char** fill_alpn_protocol_strings(size_t* num_alpn_protocols) {
@@ -751,27 +780,29 @@
   }
   // Create handshakers.
   grpc_handshake_manager_add(
-      handshake_mgr, grpc_security_handshaker_create(
-                         tsi_create_adapter_handshaker(tsi_hs), &sc->base));
+      handshake_mgr, grpc_security_handshaker_create(tsi_hs, &sc->base));
 }
 
-static int ssl_host_matches_name(const tsi_peer* peer, const char* peer_name) {
+int grpc_ssl_host_matches_name(const tsi_peer* peer, const char* peer_name) {
   char* allocated_name = nullptr;
   int r;
 
-  if (strchr(peer_name, ':') != nullptr) {
-    char* ignored_port;
-    gpr_split_host_port(peer_name, &allocated_name, &ignored_port);
-    gpr_free(ignored_port);
-    peer_name = allocated_name;
-    if (!peer_name) return 0;
-  }
+  char* ignored_port;
+  gpr_split_host_port(peer_name, &allocated_name, &ignored_port);
+  gpr_free(ignored_port);
+  peer_name = allocated_name;
+  if (!peer_name) return 0;
+
+  // IPv6 zone-id should not be included in comparisons.
+  char* const zone_id = strchr(allocated_name, '%');
+  if (zone_id != nullptr) *zone_id = '\0';
+
   r = tsi_ssl_peer_matches_name(peer, peer_name);
   gpr_free(allocated_name);
   return r;
 }
 
-grpc_auth_context* tsi_ssl_peer_to_auth_context(const tsi_peer* peer) {
+grpc_auth_context* grpc_ssl_peer_to_auth_context(const tsi_peer* peer) {
   size_t i;
   grpc_auth_context* ctx = nullptr;
   const char* peer_identity_property_name = nullptr;
@@ -828,14 +859,14 @@
   }
 
   /* Check the peer name if specified. */
-  if (peer_name != nullptr && !ssl_host_matches_name(peer, peer_name)) {
+  if (peer_name != nullptr && !grpc_ssl_host_matches_name(peer, peer_name)) {
     char* msg;
     gpr_asprintf(&msg, "Peer name %s is not in peer certificate", peer_name);
     grpc_error* error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(msg);
     gpr_free(msg);
     return error;
   }
-  *auth_context = tsi_ssl_peer_to_auth_context(peer);
+  *auth_context = grpc_ssl_peer_to_auth_context(peer);
   return GRPC_ERROR_NONE;
 }
 
@@ -893,7 +924,7 @@
   tsi_prop->value.length = prop->value_length;
 }
 
-tsi_peer tsi_shallow_peer_from_ssl_auth_context(
+tsi_peer grpc_shallow_peer_from_ssl_auth_context(
     const grpc_auth_context* auth_context) {
   size_t max_num_props = 0;
   grpc_auth_property_iterator it;
@@ -924,7 +955,7 @@
   return peer;
 }
 
-void tsi_shallow_peer_destruct(tsi_peer* peer) {
+void grpc_shallow_peer_destruct(tsi_peer* peer) {
   if (peer->properties != nullptr) gpr_free(peer->properties);
 }
 
@@ -936,8 +967,8 @@
   grpc_ssl_channel_security_connector* c =
       reinterpret_cast<grpc_ssl_channel_security_connector*>(sc);
   grpc_security_status status = GRPC_SECURITY_ERROR;
-  tsi_peer peer = tsi_shallow_peer_from_ssl_auth_context(auth_context);
-  if (ssl_host_matches_name(&peer, host)) status = GRPC_SECURITY_OK;
+  tsi_peer peer = grpc_shallow_peer_from_ssl_auth_context(auth_context);
+  if (grpc_ssl_host_matches_name(&peer, host)) status = GRPC_SECURITY_OK;
   /* If the target name was overridden, then the original target_name was
      'checked' transitively during the previous peer check at the end of the
      handshake. */
@@ -949,7 +980,7 @@
     *error = GRPC_ERROR_CREATE_FROM_STATIC_STRING(
         "call host does not match SSL server name");
   }
-  tsi_shallow_peer_destruct(&peer);
+  grpc_shallow_peer_destruct(&peer);
   return true;
 }
 
@@ -1120,16 +1151,6 @@
                    GRPC_SLICE_START_PTR(default_pem_root_certs_);
 }
 
-void DefaultSslRootStore::Initialize() {
-  default_root_store_ = nullptr;
-  default_pem_root_certs_ = grpc_empty_slice();
-}
-
-void DefaultSslRootStore::Destroy() {
-  tsi_ssl_root_certs_store_destroy(default_root_store_);
-  grpc_slice_unref_internal(default_pem_root_certs_);
-}
-
 grpc_slice DefaultSslRootStore::ComputePemRootCerts() {
   grpc_slice result = grpc_empty_slice();
   // First try to load the roots from the environment.
diff --git a/src/core/lib/security/security_connector/security_connector.h b/src/core/lib/security/security_connector/security_connector.h
index 5d3d1e0..f972316 100644
--- a/src/core/lib/security/security_connector/security_connector.h
+++ b/src/core/lib/security/security_connector/security_connector.h
@@ -239,10 +239,11 @@
                                                        const char* name);
 
 /* Exposed for testing only. */
-grpc_auth_context* tsi_ssl_peer_to_auth_context(const tsi_peer* peer);
-tsi_peer tsi_shallow_peer_from_ssl_auth_context(
+grpc_auth_context* grpc_ssl_peer_to_auth_context(const tsi_peer* peer);
+tsi_peer grpc_shallow_peer_from_ssl_auth_context(
     const grpc_auth_context* auth_context);
-void tsi_shallow_peer_destruct(tsi_peer* peer);
+void grpc_shallow_peer_destruct(tsi_peer* peer);
+int grpc_ssl_host_matches_name(const tsi_peer* peer, const char* peer_name);
 
 /* --- Default SSL Root Store. --- */
 namespace grpc_core {
@@ -256,15 +257,6 @@
   // Gets the default PEM root certificate.
   static const char* GetPemRootCerts();
 
-  // Initializes the SSL root store's underlying data structure. It does not
-  // load default SSL root certificates. Should only be called by
-  // grpc_security_init().
-  static void Initialize();
-
-  // Destroys the default SSL root store. Should only be called by
-  // grpc_security_shutdown().
-  static void Destroy();
-
  protected:
   // Returns default PEM root certificates in nullptr terminated grpc_slice.
   // This function is protected instead of private, so that it can be tested.
diff --git a/src/core/lib/security/transport/secure_endpoint.cc b/src/core/lib/security/transport/secure_endpoint.cc
index 31b779e..840b2e7 100644
--- a/src/core/lib/security/transport/secure_endpoint.cc
+++ b/src/core/lib/security/transport/secure_endpoint.cc
@@ -133,7 +133,7 @@
     for (i = 0; i < ep->read_buffer->count; i++) {
       char* data = grpc_dump_slice(ep->read_buffer->slices[i],
                                    GPR_DUMP_HEX | GPR_DUMP_ASCII);
-      gpr_log(GPR_DEBUG, "READ %p: %s", ep, data);
+      gpr_log(GPR_INFO, "READ %p: %s", ep, data);
       gpr_free(data);
     }
   }
@@ -269,7 +269,7 @@
     for (i = 0; i < slices->count; i++) {
       char* data =
           grpc_dump_slice(slices->slices[i], GPR_DUMP_HEX | GPR_DUMP_ASCII);
-      gpr_log(GPR_DEBUG, "WRITE %p: %s", ep, data);
+      gpr_log(GPR_INFO, "WRITE %p: %s", ep, data);
       gpr_free(data);
     }
   }
diff --git a/src/core/lib/security/transport/security_handshaker.cc b/src/core/lib/security/transport/security_handshaker.cc
index 0c97dfa..aff723e 100644
--- a/src/core/lib/security/transport/security_handshaker.cc
+++ b/src/core/lib/security/transport/security_handshaker.cc
@@ -232,6 +232,10 @@
     const unsigned char* bytes_to_send, size_t bytes_to_send_size,
     tsi_handshaker_result* handshaker_result) {
   grpc_error* error = GRPC_ERROR_NONE;
+  // Handshaker was shutdown.
+  if (h->shutdown) {
+    return GRPC_ERROR_CREATE_FROM_STATIC_STRING("Handshaker shutdown");
+  }
   // Read more if we need to.
   if (result == TSI_INCOMPLETE_DATA) {
     GPR_ASSERT(bytes_to_send_size == 0);
@@ -376,6 +380,7 @@
   gpr_mu_lock(&h->mu);
   if (!h->shutdown) {
     h->shutdown = true;
+    tsi_handshaker_shutdown(h->handshaker);
     grpc_endpoint_shutdown(h->args->endpoint, GRPC_ERROR_REF(why));
     cleanup_args_for_failure_locked(h);
   }
@@ -406,7 +411,7 @@
 
 static const grpc_handshaker_vtable security_handshaker_vtable = {
     security_handshaker_destroy, security_handshaker_shutdown,
-    security_handshaker_do_handshake};
+    security_handshaker_do_handshake, "security"};
 
 static grpc_handshaker* security_handshaker_create(
     tsi_handshaker* handshaker, grpc_security_connector* connector) {
@@ -456,7 +461,7 @@
 
 static const grpc_handshaker_vtable fail_handshaker_vtable = {
     fail_handshaker_destroy, fail_handshaker_shutdown,
-    fail_handshaker_do_handshake};
+    fail_handshaker_do_handshake, "security_fail"};
 
 static grpc_handshaker* fail_handshaker_create() {
   grpc_handshaker* h = static_cast<grpc_handshaker*>(gpr_malloc(sizeof(*h)));
diff --git a/src/core/lib/slice/slice.cc b/src/core/lib/slice/slice.cc
index 585b41c..4194741 100644
--- a/src/core/lib/slice/slice.cc
+++ b/src/core/lib/slice/slice.cc
@@ -69,8 +69,12 @@
 
 /* Public API */
 void grpc_slice_unref(grpc_slice slice) {
-  grpc_core::ExecCtx exec_ctx;
-  grpc_slice_unref_internal(slice);
+  if (grpc_core::ExecCtx::Get() == nullptr) {
+    grpc_core::ExecCtx exec_ctx;
+    grpc_slice_unref_internal(slice);
+  } else {
+    grpc_slice_unref_internal(slice);
+  }
 }
 
 /* grpc_slice_from_static_string support structure - a refcount that does
diff --git a/src/core/lib/slice/slice_buffer.cc b/src/core/lib/slice/slice_buffer.cc
index 58ca495..fd56997 100644
--- a/src/core/lib/slice/slice_buffer.cc
+++ b/src/core/lib/slice/slice_buffer.cc
@@ -75,8 +75,12 @@
 }
 
 void grpc_slice_buffer_destroy(grpc_slice_buffer* sb) {
-  grpc_core::ExecCtx exec_ctx;
-  grpc_slice_buffer_destroy_internal(sb);
+  if (grpc_core::ExecCtx::Get() == nullptr) {
+    grpc_core::ExecCtx exec_ctx;
+    grpc_slice_buffer_destroy_internal(sb);
+  } else {
+    grpc_slice_buffer_destroy_internal(sb);
+  }
 }
 
 uint8_t* grpc_slice_buffer_tiny_add(grpc_slice_buffer* sb, size_t n) {
@@ -176,8 +180,12 @@
 }
 
 void grpc_slice_buffer_reset_and_unref(grpc_slice_buffer* sb) {
-  grpc_core::ExecCtx exec_ctx;
-  grpc_slice_buffer_reset_and_unref_internal(sb);
+  if (grpc_core::ExecCtx::Get() == nullptr) {
+    grpc_core::ExecCtx exec_ctx;
+    grpc_slice_buffer_reset_and_unref_internal(sb);
+  } else {
+    grpc_slice_buffer_reset_and_unref_internal(sb);
+  }
 }
 
 void grpc_slice_buffer_swap(grpc_slice_buffer* a, grpc_slice_buffer* b) {
diff --git a/src/core/lib/slice/slice_hash_table.h b/src/core/lib/slice/slice_hash_table.h
index fbe9cc5..4bbcf88 100644
--- a/src/core/lib/slice/slice_hash_table.h
+++ b/src/core/lib/slice/slice_hash_table.h
@@ -81,6 +81,10 @@
   template <typename T2, typename... Args>
   friend T2* New(Args&&... args);
 
+  // So Delete() can call our private dtor.
+  template <typename T2>
+  friend void Delete(T2*);
+
   SliceHashTable(size_t num_entries, Entry* entries, ValueCmp value_cmp);
   virtual ~SliceHashTable();
 
diff --git a/src/core/lib/slice/slice_weak_hash_table.h b/src/core/lib/slice/slice_weak_hash_table.h
index 9d0ddfc..dc3ccc5 100644
--- a/src/core/lib/slice/slice_weak_hash_table.h
+++ b/src/core/lib/slice/slice_weak_hash_table.h
@@ -65,6 +65,10 @@
   template <typename T2, typename... Args>
   friend T2* New(Args&&... args);
 
+  // So Delete() can call our private dtor.
+  template <typename T2>
+  friend void Delete(T2*);
+
   SliceWeakHashTable() = default;
   ~SliceWeakHashTable() = default;
 
diff --git a/src/core/lib/surface/call.cc b/src/core/lib/surface/call.cc
index c683cc0..da48803 100644
--- a/src/core/lib/surface/call.cc
+++ b/src/core/lib/surface/call.cc
@@ -610,7 +610,7 @@
 // This is called via the call combiner to start sending a batch down
 // the filter stack.
 static void execute_batch_in_call_combiner(void* arg, grpc_error* ignored) {
-  GPR_TIMER_SCOPE("execute_batch", 0);
+  GPR_TIMER_SCOPE("execute_batch_in_call_combiner", 0);
   grpc_transport_stream_op_batch* batch =
       static_cast<grpc_transport_stream_op_batch*>(arg);
   grpc_call* call = static_cast<grpc_call*>(batch->handler_private.extra_arg);
@@ -747,10 +747,10 @@
     status[i] = unpack_received_status(gpr_atm_acq_load(&call->status[i]));
   }
   if (grpc_call_error_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "get_final_status %s", call->is_client ? "CLI" : "SVR");
+    gpr_log(GPR_INFO, "get_final_status %s", call->is_client ? "CLI" : "SVR");
     for (i = 0; i < STATUS_SOURCE_COUNT; i++) {
       if (status[i].is_set) {
-        gpr_log(GPR_DEBUG, "  %d: %s", i, grpc_error_string(status[i].error));
+        gpr_log(GPR_INFO, "  %d: %s", i, grpc_error_string(status[i].error));
       }
     }
   }
@@ -878,8 +878,8 @@
     } else {
       char* accept_encoding_entry_str =
           grpc_slice_to_c_string(accept_encoding_entry_slice);
-      gpr_log(GPR_ERROR,
-              "Invalid entry in accept encoding metadata: '%s'. Ignoring.",
+      gpr_log(GPR_DEBUG,
+              "Unknown entry in accept encoding metadata: '%s'. Ignoring.",
               accept_encoding_entry_str);
       gpr_free(accept_encoding_entry_str);
     }
@@ -1539,7 +1539,7 @@
 static grpc_call_error call_start_batch(grpc_call* call, const grpc_op* ops,
                                         size_t nops, void* notify_tag,
                                         int is_notify_tag_closure) {
-  GPR_TIMER_SCOPE("grpc_call_start_batch", 0);
+  GPR_TIMER_SCOPE("call_start_batch", 0);
 
   size_t i;
   const grpc_op* op;
diff --git a/src/core/lib/surface/channel.cc b/src/core/lib/surface/channel.cc
index cecc15b..d740ebd 100644
--- a/src/core/lib/surface/channel.cc
+++ b/src/core/lib/surface/channel.cc
@@ -60,7 +60,6 @@
 struct grpc_channel {
   int is_client;
   grpc_compression_options compression_options;
-  grpc_mdelem default_authority;
 
   gpr_atm call_size_estimate;
 
@@ -117,40 +116,8 @@
 
   grpc_compression_options_init(&channel->compression_options);
   for (size_t i = 0; i < args->num_args; i++) {
-    if (0 == strcmp(args->args[i].key, GRPC_ARG_DEFAULT_AUTHORITY)) {
-      if (args->args[i].type != GRPC_ARG_STRING) {
-        gpr_log(GPR_ERROR, "%s ignored: it must be a string",
-                GRPC_ARG_DEFAULT_AUTHORITY);
-      } else {
-        if (!GRPC_MDISNULL(channel->default_authority)) {
-          /* setting this takes precedence over anything else */
-          GRPC_MDELEM_UNREF(channel->default_authority);
-        }
-        channel->default_authority = grpc_mdelem_from_slices(
-            GRPC_MDSTR_AUTHORITY,
-            grpc_slice_intern(
-                grpc_slice_from_static_string(args->args[i].value.string)));
-      }
-    } else if (0 ==
-               strcmp(args->args[i].key, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG)) {
-      if (args->args[i].type != GRPC_ARG_STRING) {
-        gpr_log(GPR_ERROR, "%s ignored: it must be a string",
-                GRPC_SSL_TARGET_NAME_OVERRIDE_ARG);
-      } else {
-        if (!GRPC_MDISNULL(channel->default_authority)) {
-          /* other ways of setting this (notably ssl) take precedence */
-          gpr_log(GPR_ERROR,
-                  "%s ignored: default host already set some other way",
-                  GRPC_SSL_TARGET_NAME_OVERRIDE_ARG);
-        } else {
-          channel->default_authority = grpc_mdelem_from_slices(
-              GRPC_MDSTR_AUTHORITY,
-              grpc_slice_intern(
-                  grpc_slice_from_static_string(args->args[i].value.string)));
-        }
-      }
-    } else if (0 == strcmp(args->args[i].key,
-                           GRPC_COMPRESSION_CHANNEL_DEFAULT_LEVEL)) {
+    if (0 ==
+        strcmp(args->args[i].key, GRPC_COMPRESSION_CHANNEL_DEFAULT_LEVEL)) {
       channel->compression_options.default_level.is_set = true;
       channel->compression_options.default_level.level =
           static_cast<grpc_compression_level>(grpc_channel_arg_get_integer(
@@ -189,6 +156,37 @@
   return channel;
 }
 
+static grpc_core::UniquePtr<char> get_default_authority(
+    const grpc_channel_args* input_args) {
+  bool has_default_authority = false;
+  char* ssl_override = nullptr;
+  grpc_core::UniquePtr<char> default_authority;
+  const size_t num_args = input_args != nullptr ? input_args->num_args : 0;
+  for (size_t i = 0; i < num_args; ++i) {
+    if (0 == strcmp(input_args->args[i].key, GRPC_ARG_DEFAULT_AUTHORITY)) {
+      has_default_authority = true;
+    } else if (0 == strcmp(input_args->args[i].key,
+                           GRPC_SSL_TARGET_NAME_OVERRIDE_ARG)) {
+      ssl_override = grpc_channel_arg_get_string(&input_args->args[i]);
+    }
+  }
+  if (!has_default_authority && ssl_override != nullptr) {
+    default_authority.reset(gpr_strdup(ssl_override));
+  }
+  return default_authority;
+}
+
+static grpc_channel_args* build_channel_args(
+    const grpc_channel_args* input_args, char* default_authority) {
+  grpc_arg new_args[1];
+  size_t num_new_args = 0;
+  if (default_authority != nullptr) {
+    new_args[num_new_args++] = grpc_channel_arg_string_create(
+        const_cast<char*>(GRPC_ARG_DEFAULT_AUTHORITY), default_authority);
+  }
+  return grpc_channel_args_copy_and_add(input_args, new_args, num_new_args);
+}
+
 char* grpc_channel_get_trace(grpc_channel* channel) {
   return channel->tracer->RenderTrace();
 }
@@ -202,7 +200,12 @@
                                   grpc_channel_stack_type channel_stack_type,
                                   grpc_transport* optional_transport) {
   grpc_channel_stack_builder* builder = grpc_channel_stack_builder_create();
-  grpc_channel_stack_builder_set_channel_arguments(builder, input_args);
+  const grpc_core::UniquePtr<char> default_authority =
+      get_default_authority(input_args);
+  grpc_channel_args* args =
+      build_channel_args(input_args, default_authority.get());
+  grpc_channel_stack_builder_set_channel_arguments(builder, args);
+  grpc_channel_args_destroy(args);
   grpc_channel_stack_builder_set_target(builder, target);
   grpc_channel_stack_builder_set_transport(builder, optional_transport);
   if (!grpc_channel_init_create_stack(builder, channel_stack_type)) {
@@ -274,8 +277,6 @@
   send_metadata[num_metadata++] = path_mdelem;
   if (!GRPC_MDISNULL(authority_mdelem)) {
     send_metadata[num_metadata++] = authority_mdelem;
-  } else if (!GRPC_MDISNULL(channel->default_authority)) {
-    send_metadata[num_metadata++] = GRPC_MDELEM_REF(channel->default_authority);
   }
 
   grpc_call_create_args args;
@@ -406,7 +407,6 @@
     gpr_free(rc);
   }
   channel->tracer.reset();
-  GRPC_MDELEM_UNREF(channel->default_authority);
   gpr_mu_destroy(&channel->registered_call_mu);
   gpr_free(channel->target);
   gpr_free(channel);
diff --git a/src/core/lib/surface/completion_queue.cc b/src/core/lib/surface/completion_queue.cc
index d036391..f751741 100644
--- a/src/core/lib/surface/completion_queue.cc
+++ b/src/core/lib/surface/completion_queue.cc
@@ -390,7 +390,6 @@
 
 static grpc_cq_completion* cq_event_queue_pop(grpc_cq_event_queue* q) {
   grpc_cq_completion* c = nullptr;
-  grpc_core::ExecCtx exec_ctx;
 
   if (gpr_spinlock_trylock(&q->queue_lock)) {
     GRPC_STATS_INC_CQ_EV_QUEUE_TRYLOCK_SUCCESSES();
diff --git a/src/core/lib/surface/init.cc b/src/core/lib/surface/init.cc
index 52e0ee1..bd436d6 100644
--- a/src/core/lib/surface/init.cc
+++ b/src/core/lib/surface/init.cc
@@ -172,7 +172,6 @@
           }
         }
       }
-      grpc_security_shutdown();
       grpc_iomgr_shutdown();
       gpr_timers_global_destroy();
       grpc_tracer_shutdown();
diff --git a/src/core/lib/surface/init.h b/src/core/lib/surface/init.h
index d8282b4..9353208 100644
--- a/src/core/lib/surface/init.h
+++ b/src/core/lib/surface/init.h
@@ -22,7 +22,6 @@
 void grpc_register_security_filters(void);
 void grpc_security_pre_init(void);
 void grpc_security_init(void);
-void grpc_security_shutdown(void);
 int grpc_is_initialized(void);
 
 #endif /* GRPC_CORE_LIB_SURFACE_INIT_H */
diff --git a/src/core/lib/surface/init_secure.cc b/src/core/lib/surface/init_secure.cc
index 3e4f1a8..28c6f7b 100644
--- a/src/core/lib/surface/init_secure.cc
+++ b/src/core/lib/surface/init_secure.cc
@@ -67,17 +67,15 @@
 }
 
 void grpc_register_security_filters(void) {
-  grpc_channel_init_register_stage(GRPC_CLIENT_SUBCHANNEL, INT_MAX,
+  // Register the auth client with a priority < INT_MAX to allow the authority
+  // filter -on which the auth filter depends- to be higher on the channel
+  // stack.
+  grpc_channel_init_register_stage(GRPC_CLIENT_SUBCHANNEL, INT_MAX - 1,
                                    maybe_prepend_client_auth_filter, nullptr);
-  grpc_channel_init_register_stage(GRPC_CLIENT_DIRECT_CHANNEL, INT_MAX,
+  grpc_channel_init_register_stage(GRPC_CLIENT_DIRECT_CHANNEL, INT_MAX - 1,
                                    maybe_prepend_client_auth_filter, nullptr);
   grpc_channel_init_register_stage(GRPC_SERVER_CHANNEL, INT_MAX,
                                    maybe_prepend_server_auth_filter, nullptr);
 }
 
-void grpc_security_init() {
-  grpc_security_register_handshaker_factories();
-  grpc_core::DefaultSslRootStore::Initialize();
-}
-
-void grpc_security_shutdown() { grpc_core::DefaultSslRootStore::Destroy(); }
+void grpc_security_init() { grpc_security_register_handshaker_factories(); }
diff --git a/src/core/lib/surface/init_unsecure.cc b/src/core/lib/surface/init_unsecure.cc
index 1c8d07b..2b3bc64 100644
--- a/src/core/lib/surface/init_unsecure.cc
+++ b/src/core/lib/surface/init_unsecure.cc
@@ -25,5 +25,3 @@
 void grpc_register_security_filters(void) {}
 
 void grpc_security_init(void) {}
-
-void grpc_security_shutdown(void) {}
diff --git a/src/core/lib/surface/server.cc b/src/core/lib/surface/server.cc
index f7505c8..cb34def 100644
--- a/src/core/lib/surface/server.cc
+++ b/src/core/lib/surface/server.cc
@@ -1161,6 +1161,22 @@
   gpr_mu_unlock(&server->mu_global);
 }
 
+/*
+  - Kills all pending requests-for-incoming-RPC-calls (i.e the requests made via
+    grpc_server_request_call and grpc_server_request_registered call will now be
+    cancelled). See 'kill_pending_work_locked()'
+
+  - Shuts down the listeners (i.e the server will no longer listen on the port
+    for new incoming channels).
+
+  - Iterates through all channels on the server and sends shutdown msg (see
+    'channel_broadcaster_shutdown()' for details) to the clients via the
+    transport layer. The transport layer then guarantees the following:
+     -- Sends shutdown to the client (for eg: HTTP2 transport sends GOAWAY)
+     -- If the server has outstanding calls that are in the process, the
+        connection is NOT closed until the server is done with all those calls
+     -- Once, there are no more calls in progress, the channel is closed
+ */
 void grpc_server_shutdown_and_notify(grpc_server* server,
                                      grpc_completion_queue* cq, void* tag) {
   listener* l;
diff --git a/src/core/lib/surface/version.cc b/src/core/lib/surface/version.cc
index be196a7..306b7c3 100644
--- a/src/core/lib/surface/version.cc
+++ b/src/core/lib/surface/version.cc
@@ -25,4 +25,4 @@
 
 const char* grpc_version_string(void) { return "6.0.0-dev"; }
 
-const char* grpc_g_stands_for(void) { return "gorgeous"; }
+const char* grpc_g_stands_for(void) { return "gloriosa"; }
diff --git a/src/core/lib/transport/bdp_estimator.cc b/src/core/lib/transport/bdp_estimator.cc
index 8130535..8e71f86 100644
--- a/src/core/lib/transport/bdp_estimator.cc
+++ b/src/core/lib/transport/bdp_estimator.cc
@@ -47,7 +47,7 @@
   double bw = dt > 0 ? (static_cast<double>(accumulator_) / dt) : 0;
   int start_inter_ping_delay = inter_ping_delay_;
   if (grpc_bdp_estimator_trace.enabled()) {
-    gpr_log(GPR_DEBUG,
+    gpr_log(GPR_INFO,
             "bdp[%s]:complete acc=%" PRId64 " est=%" PRId64
             " dt=%lf bw=%lfMbs bw_est=%lfMbs",
             name_, accumulator_, estimate_, dt, bw / 125000.0,
@@ -58,7 +58,7 @@
     estimate_ = GPR_MAX(accumulator_, estimate_ * 2);
     bw_est_ = bw;
     if (grpc_bdp_estimator_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "bdp[%s]: estimate increased to %" PRId64, name_,
+      gpr_log(GPR_INFO, "bdp[%s]: estimate increased to %" PRId64, name_,
               estimate_);
     }
     inter_ping_delay_ /= 2;  // if the ping estimate changes,
@@ -75,7 +75,7 @@
   if (start_inter_ping_delay != inter_ping_delay_) {
     stable_estimate_count_ = 0;
     if (grpc_bdp_estimator_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "bdp[%s]:update_inter_time to %dms", name_,
+      gpr_log(GPR_INFO, "bdp[%s]:update_inter_time to %dms", name_,
               inter_ping_delay_);
     }
   }
diff --git a/src/core/lib/transport/bdp_estimator.h b/src/core/lib/transport/bdp_estimator.h
index e703af1..ab13ae4 100644
--- a/src/core/lib/transport/bdp_estimator.h
+++ b/src/core/lib/transport/bdp_estimator.h
@@ -50,7 +50,7 @@
   // transport (but not necessarily started)
   void SchedulePing() {
     if (grpc_bdp_estimator_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "bdp[%s]:sched acc=%" PRId64 " est=%" PRId64, name_,
+      gpr_log(GPR_INFO, "bdp[%s]:sched acc=%" PRId64 " est=%" PRId64, name_,
               accumulator_, estimate_);
     }
     GPR_ASSERT(ping_state_ == PingState::UNSCHEDULED);
@@ -63,7 +63,7 @@
   // the ping is on the wire
   void StartPing() {
     if (grpc_bdp_estimator_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "bdp[%s]:start acc=%" PRId64 " est=%" PRId64, name_,
+      gpr_log(GPR_INFO, "bdp[%s]:start acc=%" PRId64 " est=%" PRId64, name_,
               accumulator_, estimate_);
     }
     GPR_ASSERT(ping_state_ == PingState::SCHEDULED);
diff --git a/src/core/lib/transport/connectivity_state.cc b/src/core/lib/transport/connectivity_state.cc
index 0122e77..db6b6c0 100644
--- a/src/core/lib/transport/connectivity_state.cc
+++ b/src/core/lib/transport/connectivity_state.cc
@@ -78,7 +78,7 @@
   grpc_connectivity_state cur = static_cast<grpc_connectivity_state>(
       gpr_atm_no_barrier_load(&tracker->current_state_atm));
   if (grpc_connectivity_state_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "CONWATCH: %p %s: get %s", tracker, tracker->name,
+    gpr_log(GPR_INFO, "CONWATCH: %p %s: get %s", tracker, tracker->name,
             grpc_connectivity_state_name(cur));
   }
   return cur;
@@ -89,7 +89,7 @@
   grpc_connectivity_state cur = static_cast<grpc_connectivity_state>(
       gpr_atm_no_barrier_load(&tracker->current_state_atm));
   if (grpc_connectivity_state_trace.enabled()) {
-    gpr_log(GPR_DEBUG, "CONWATCH: %p %s: get %s", tracker, tracker->name,
+    gpr_log(GPR_INFO, "CONWATCH: %p %s: get %s", tracker, tracker->name,
             grpc_connectivity_state_name(cur));
   }
   if (error != nullptr) {
@@ -110,10 +110,10 @@
       gpr_atm_no_barrier_load(&tracker->current_state_atm));
   if (grpc_connectivity_state_trace.enabled()) {
     if (current == nullptr) {
-      gpr_log(GPR_DEBUG, "CONWATCH: %p %s: unsubscribe notify=%p", tracker,
+      gpr_log(GPR_INFO, "CONWATCH: %p %s: unsubscribe notify=%p", tracker,
               tracker->name, notify);
     } else {
-      gpr_log(GPR_DEBUG, "CONWATCH: %p %s: from %s [cur=%s] notify=%p", tracker,
+      gpr_log(GPR_INFO, "CONWATCH: %p %s: from %s [cur=%s] notify=%p", tracker,
               tracker->name, grpc_connectivity_state_name(*current),
               grpc_connectivity_state_name(cur), notify);
     }
@@ -161,7 +161,7 @@
   grpc_connectivity_state_watcher* w;
   if (grpc_connectivity_state_trace.enabled()) {
     const char* error_string = grpc_error_string(error);
-    gpr_log(GPR_DEBUG, "SET: %p %s: %s --> %s [%s] error=%p %s", tracker,
+    gpr_log(GPR_INFO, "SET: %p %s: %s --> %s [%s] error=%p %s", tracker,
             tracker->name, grpc_connectivity_state_name(cur),
             grpc_connectivity_state_name(state), reason, error, error_string);
   }
@@ -187,8 +187,7 @@
     *w->current = state;
     tracker->watchers = w->next;
     if (grpc_connectivity_state_trace.enabled()) {
-      gpr_log(GPR_DEBUG, "NOTIFY: %p %s: %p", tracker, tracker->name,
-              w->notify);
+      gpr_log(GPR_INFO, "NOTIFY: %p %s: %p", tracker, tracker->name, w->notify);
     }
     GRPC_CLOSURE_SCHED(w->notify, GRPC_ERROR_REF(tracker->current_error));
     gpr_free(w);
diff --git a/src/core/plugin_registry/grpc_cronet_plugin_registry.cc b/src/core/plugin_registry/grpc_cronet_plugin_registry.cc
index 84228cb..49b9c7d 100644
--- a/src/core/plugin_registry/grpc_cronet_plugin_registry.cc
+++ b/src/core/plugin_registry/grpc_cronet_plugin_registry.cc
@@ -20,50 +20,30 @@
 
 #include <grpc/grpc.h>
 
-void grpc_deadline_filter_init(void);
-void grpc_deadline_filter_shutdown(void);
-void grpc_client_channel_init(void);
-void grpc_client_channel_shutdown(void);
-void grpc_lb_policy_pick_first_init(void);
-void grpc_lb_policy_pick_first_shutdown(void);
-void grpc_max_age_filter_init(void);
-void grpc_max_age_filter_shutdown(void);
-void grpc_message_size_filter_init(void);
-void grpc_message_size_filter_shutdown(void);
-void grpc_resolver_dns_native_init(void);
-void grpc_resolver_dns_native_shutdown(void);
-void grpc_resolver_sockaddr_init(void);
-void grpc_resolver_sockaddr_shutdown(void);
-void grpc_server_load_reporting_plugin_init(void);
-void grpc_server_load_reporting_plugin_shutdown(void);
 void grpc_http_filters_init(void);
 void grpc_http_filters_shutdown(void);
 void grpc_chttp2_plugin_init(void);
 void grpc_chttp2_plugin_shutdown(void);
+void grpc_deadline_filter_init(void);
+void grpc_deadline_filter_shutdown(void);
+void grpc_client_channel_init(void);
+void grpc_client_channel_shutdown(void);
 void grpc_tsi_alts_init(void);
 void grpc_tsi_alts_shutdown(void);
+void grpc_server_load_reporting_plugin_init(void);
+void grpc_server_load_reporting_plugin_shutdown(void);
 
 void grpc_register_built_in_plugins(void) {
-  grpc_register_plugin(grpc_deadline_filter_init,
-                       grpc_deadline_filter_shutdown);
-  grpc_register_plugin(grpc_client_channel_init,
-                       grpc_client_channel_shutdown);
-  grpc_register_plugin(grpc_lb_policy_pick_first_init,
-                       grpc_lb_policy_pick_first_shutdown);
-  grpc_register_plugin(grpc_max_age_filter_init,
-                       grpc_max_age_filter_shutdown);
-  grpc_register_plugin(grpc_message_size_filter_init,
-                       grpc_message_size_filter_shutdown);
-  grpc_register_plugin(grpc_resolver_dns_native_init,
-                       grpc_resolver_dns_native_shutdown);
-  grpc_register_plugin(grpc_resolver_sockaddr_init,
-                       grpc_resolver_sockaddr_shutdown);
-  grpc_register_plugin(grpc_server_load_reporting_plugin_init,
-                       grpc_server_load_reporting_plugin_shutdown);
   grpc_register_plugin(grpc_http_filters_init,
                        grpc_http_filters_shutdown);
   grpc_register_plugin(grpc_chttp2_plugin_init,
                        grpc_chttp2_plugin_shutdown);
+  grpc_register_plugin(grpc_deadline_filter_init,
+                       grpc_deadline_filter_shutdown);
+  grpc_register_plugin(grpc_client_channel_init,
+                       grpc_client_channel_shutdown);
   grpc_register_plugin(grpc_tsi_alts_init,
                        grpc_tsi_alts_shutdown);
+  grpc_register_plugin(grpc_server_load_reporting_plugin_init,
+                       grpc_server_load_reporting_plugin_shutdown);
 }
diff --git a/src/core/plugin_registry/grpc_plugin_registry.cc b/src/core/plugin_registry/grpc_plugin_registry.cc
index 6f11e6b..e371310 100644
--- a/src/core/plugin_registry/grpc_plugin_registry.cc
+++ b/src/core/plugin_registry/grpc_plugin_registry.cc
@@ -52,6 +52,8 @@
 void grpc_max_age_filter_shutdown(void);
 void grpc_message_size_filter_init(void);
 void grpc_message_size_filter_shutdown(void);
+void grpc_client_authority_filter_init(void);
+void grpc_client_authority_filter_shutdown(void);
 void grpc_workaround_cronet_compression_filter_init(void);
 void grpc_workaround_cronet_compression_filter_shutdown(void);
 
@@ -88,6 +90,8 @@
                        grpc_max_age_filter_shutdown);
   grpc_register_plugin(grpc_message_size_filter_init,
                        grpc_message_size_filter_shutdown);
+  grpc_register_plugin(grpc_client_authority_filter_init,
+                       grpc_client_authority_filter_shutdown);
   grpc_register_plugin(grpc_workaround_cronet_compression_filter_init,
                        grpc_workaround_cronet_compression_filter_shutdown);
 }
diff --git a/src/core/plugin_registry/grpc_unsecure_plugin_registry.cc b/src/core/plugin_registry/grpc_unsecure_plugin_registry.cc
index b08c5ce..283db5b 100644
--- a/src/core/plugin_registry/grpc_unsecure_plugin_registry.cc
+++ b/src/core/plugin_registry/grpc_unsecure_plugin_registry.cc
@@ -50,6 +50,8 @@
 void grpc_max_age_filter_shutdown(void);
 void grpc_message_size_filter_init(void);
 void grpc_message_size_filter_shutdown(void);
+void grpc_client_authority_filter_init(void);
+void grpc_client_authority_filter_shutdown(void);
 void grpc_workaround_cronet_compression_filter_init(void);
 void grpc_workaround_cronet_compression_filter_shutdown(void);
 
@@ -84,6 +86,8 @@
                        grpc_max_age_filter_shutdown);
   grpc_register_plugin(grpc_message_size_filter_init,
                        grpc_message_size_filter_shutdown);
+  grpc_register_plugin(grpc_client_authority_filter_init,
+                       grpc_client_authority_filter_shutdown);
   grpc_register_plugin(grpc_workaround_cronet_compression_filter_init,
                        grpc_workaround_cronet_compression_filter_shutdown);
 }
diff --git a/src/core/tsi/alts/handshaker/alts_handshaker_client.cc b/src/core/tsi/alts/handshaker/alts_handshaker_client.cc
index 40f30e4..b5268ad 100644
--- a/src/core/tsi/alts/handshaker/alts_handshaker_client.cc
+++ b/src/core/tsi/alts/handshaker/alts_handshaker_client.cc
@@ -118,8 +118,7 @@
 static tsi_result handshaker_client_start_client(alts_handshaker_client* client,
                                                  alts_tsi_event* event) {
   if (client == nullptr || event == nullptr) {
-    gpr_log(GPR_ERROR,
-            "Invalid arguments to alts_grpc_handshaker_client_start_client()");
+    gpr_log(GPR_ERROR, "Invalid arguments to handshaker_client_start_client()");
     return TSI_INVALID_ARGUMENT;
   }
   grpc_byte_buffer* buffer = get_serialized_start_client(event);
@@ -167,8 +166,7 @@
                                                  alts_tsi_event* event,
                                                  grpc_slice* bytes_received) {
   if (client == nullptr || event == nullptr || bytes_received == nullptr) {
-    gpr_log(GPR_ERROR,
-            "Invalid arguments to alts_grpc_handshaker_client_start_server()");
+    gpr_log(GPR_ERROR, "Invalid arguments to handshaker_client_start_server()");
     return TSI_INVALID_ARGUMENT;
   }
   grpc_byte_buffer* buffer = get_serialized_start_server(event, bytes_received);
@@ -206,8 +204,7 @@
                                          alts_tsi_event* event,
                                          grpc_slice* bytes_received) {
   if (client == nullptr || event == nullptr || bytes_received == nullptr) {
-    gpr_log(GPR_ERROR,
-            "Invalid arguments to alts_grpc_handshaker_client_next()");
+    gpr_log(GPR_ERROR, "Invalid arguments to handshaker_client_next()");
     return TSI_INVALID_ARGUMENT;
   }
   grpc_byte_buffer* buffer = get_serialized_next(bytes_received);
@@ -223,6 +220,13 @@
   return result;
 }
 
+static void handshaker_client_shutdown(alts_handshaker_client* client) {
+  GPR_ASSERT(client != nullptr);
+  alts_grpc_handshaker_client* grpc_client =
+      reinterpret_cast<alts_grpc_handshaker_client*>(client);
+  GPR_ASSERT(grpc_call_cancel(grpc_client->call, nullptr) == GRPC_CALL_OK);
+}
+
 static void handshaker_client_destruct(alts_handshaker_client* client) {
   if (client == nullptr) {
     return;
@@ -234,7 +238,8 @@
 
 static const alts_handshaker_client_vtable vtable = {
     handshaker_client_start_client, handshaker_client_start_server,
-    handshaker_client_next, handshaker_client_destruct};
+    handshaker_client_next, handshaker_client_shutdown,
+    handshaker_client_destruct};
 
 alts_handshaker_client* alts_grpc_handshaker_client_create(
     grpc_channel* channel, grpc_completion_queue* queue,
@@ -306,6 +311,13 @@
   return TSI_INVALID_ARGUMENT;
 }
 
+void alts_handshaker_client_shutdown(alts_handshaker_client* client) {
+  if (client != nullptr && client->vtable != nullptr &&
+      client->vtable->shutdown != nullptr) {
+    client->vtable->shutdown(client);
+  }
+}
+
 void alts_handshaker_client_destroy(alts_handshaker_client* client) {
   if (client != nullptr) {
     if (client->vtable != nullptr && client->vtable->destruct != nullptr) {
diff --git a/src/core/tsi/alts/handshaker/alts_handshaker_client.h b/src/core/tsi/alts/handshaker/alts_handshaker_client.h
index fb2d2cf..8dd8fe4 100644
--- a/src/core/tsi/alts/handshaker/alts_handshaker_client.h
+++ b/src/core/tsi/alts/handshaker/alts_handshaker_client.h
@@ -51,6 +51,7 @@
                              alts_tsi_event* event, grpc_slice* bytes_received);
   tsi_result (*next)(alts_handshaker_client* client, alts_tsi_event* event,
                      grpc_slice* bytes_received);
+  void (*shutdown)(alts_handshaker_client* client);
   void (*destruct)(alts_handshaker_client* client);
 } alts_handshaker_client_vtable;
 
@@ -100,6 +101,15 @@
                                        grpc_slice* bytes_received);
 
 /**
+ * This method cancels previously scheduled, but yet executed handshaker
+ * requests to ALTS handshaker service. After this operation, the handshake
+ * will be shutdown, and no more handshaker requests will get scheduled.
+ *
+ * - client: ALTS handshaker client instance.
+ */
+void alts_handshaker_client_shutdown(alts_handshaker_client* client);
+
+/**
  * This method destroys a ALTS handshaker client.
  *
  * - client: a ALTS handshaker client instance.
diff --git a/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc b/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc
index 529f210..9676085 100644
--- a/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc
+++ b/src/core/tsi/alts/handshaker/alts_tsi_handshaker.cc
@@ -241,6 +241,10 @@
     gpr_log(GPR_ERROR, "Invalid arguments to handshaker_next()");
     return TSI_INVALID_ARGUMENT;
   }
+  if (self->handshake_shutdown) {
+    gpr_log(GPR_ERROR, "TSI handshake shutdown");
+    return TSI_HANDSHAKE_SHUTDOWN;
+  }
   alts_tsi_handshaker* handshaker =
       reinterpret_cast<alts_tsi_handshaker*>(self);
   tsi_result ok = TSI_OK;
@@ -277,6 +281,16 @@
   return TSI_ASYNC;
 }
 
+static void handshaker_shutdown(tsi_handshaker* self) {
+  GPR_ASSERT(self != nullptr);
+  if (self->handshake_shutdown) {
+    return;
+  }
+  alts_tsi_handshaker* handshaker =
+      reinterpret_cast<alts_tsi_handshaker*>(self);
+  alts_handshaker_client_shutdown(handshaker->client);
+}
+
 static void handshaker_destroy(tsi_handshaker* self) {
   if (self == nullptr) {
     return;
@@ -292,8 +306,10 @@
 }
 
 static const tsi_handshaker_vtable handshaker_vtable = {
-    nullptr,        nullptr, nullptr, nullptr, nullptr, handshaker_destroy,
-    handshaker_next};
+    nullptr,         nullptr,
+    nullptr,         nullptr,
+    nullptr,         handshaker_destroy,
+    handshaker_next, handshaker_shutdown};
 
 static void thread_worker(void* arg) {
   while (true) {
@@ -401,6 +417,11 @@
     cb(TSI_INTERNAL_ERROR, user_data, nullptr, 0, nullptr);
     return;
   }
+  if (handshaker->base.handshake_shutdown) {
+    gpr_log(GPR_ERROR, "TSI handshake shutdown");
+    cb(TSI_HANDSHAKE_SHUTDOWN, user_data, nullptr, 0, nullptr);
+    return;
+  }
   /* Failed grpc call check. */
   if (!is_ok || status != GRPC_STATUS_OK) {
     gpr_log(GPR_ERROR, "grpc call made to handshaker service failed");
@@ -479,5 +500,10 @@
   handshaker->client = client;
 }
 
+alts_handshaker_client* alts_tsi_handshaker_get_client_for_testing(
+    alts_tsi_handshaker* handshaker) {
+  return handshaker->client;
+}
+
 }  // namespace internal
 }  // namespace grpc_core
diff --git a/src/core/tsi/alts/handshaker/alts_tsi_handshaker_private.h b/src/core/tsi/alts/handshaker/alts_tsi_handshaker_private.h
index 9b7b9bb..9612071 100644
--- a/src/core/tsi/alts/handshaker/alts_tsi_handshaker_private.h
+++ b/src/core/tsi/alts/handshaker/alts_tsi_handshaker_private.h
@@ -33,6 +33,9 @@
 void alts_tsi_handshaker_set_client_for_testing(alts_tsi_handshaker* handshaker,
                                                 alts_handshaker_client* client);
 
+alts_handshaker_client* alts_tsi_handshaker_get_client_for_testing(
+    alts_tsi_handshaker* handshaker);
+
 /* For testing only. */
 bool alts_tsi_handshaker_get_has_sent_start_message_for_testing(
     alts_tsi_handshaker* handshaker);
diff --git a/src/core/tsi/fake_transport_security.cc b/src/core/tsi/fake_transport_security.cc
index ad08b50..4d4c495 100644
--- a/src/core/tsi/fake_transport_security.cc
+++ b/src/core/tsi/fake_transport_security.cc
@@ -738,6 +738,7 @@
     nullptr, /* create_frame_protector    -- deprecated */
     fake_handshaker_destroy,
     fake_handshaker_next,
+    nullptr, /* shutdown */
 };
 
 tsi_handshaker* tsi_create_fake_handshaker(int is_client) {
diff --git a/src/core/tsi/ssl/session_cache/ssl_session_cache.h b/src/core/tsi/ssl/session_cache/ssl_session_cache.h
index 488638c..a90cca1 100644
--- a/src/core/tsi/ssl/session_cache/ssl_session_cache.h
+++ b/src/core/tsi/ssl/session_cache/ssl_session_cache.h
@@ -69,6 +69,10 @@
   template <typename T, typename... Args>
   friend T* grpc_core::New(Args&&... args);
 
+  // So Delete() can call our private dtor.
+  template <typename T>
+  friend void grpc_core::Delete(T*);
+
   class Node;
 
   explicit SslSessionLRUCache(size_t capacity);
diff --git a/src/core/tsi/ssl_transport_security.cc b/src/core/tsi/ssl_transport_security.cc
index 0ba6587..8065a8b 100644
--- a/src/core/tsi/ssl_transport_security.cc
+++ b/src/core/tsi/ssl_transport_security.cc
@@ -57,6 +57,7 @@
 
 #define TSI_SSL_MAX_PROTECTED_FRAME_SIZE_UPPER_BOUND 16384
 #define TSI_SSL_MAX_PROTECTED_FRAME_SIZE_LOWER_BOUND 1024
+#define TSI_SSL_HANDSHAKER_OUTGOING_BUFFER_INITIAL_SIZE 1024
 
 /* Putting a macro like this and littering the source file with #if is really
    bad practice.
@@ -105,10 +106,20 @@
   SSL* ssl;
   BIO* network_io;
   tsi_result result;
+  unsigned char* outgoing_bytes_buffer;
+  size_t outgoing_bytes_buffer_size;
   tsi_ssl_handshaker_factory* factory_ref;
 } tsi_ssl_handshaker;
 
 typedef struct {
+  tsi_handshaker_result base;
+  SSL* ssl;
+  BIO* network_io;
+  unsigned char* unused_bytes;
+  size_t unused_bytes_size;
+} tsi_ssl_handshaker_result;
+
+typedef struct {
   tsi_frame_protector base;
   SSL* ssl;
   BIO* network_io;
@@ -120,12 +131,14 @@
 /* --- Library Initialization. ---*/
 
 static gpr_once g_init_openssl_once = GPR_ONCE_INIT;
-static gpr_mu* g_openssl_mutexes = nullptr;
 static int g_ssl_ctx_ex_factory_index = -1;
+static const unsigned char kSslSessionIdContext[] = {'g', 'r', 'p', 'c'};
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000
+static gpr_mu* g_openssl_mutexes = nullptr;
 static void openssl_locking_cb(int mode, int type, const char* file,
                                int line) GRPC_UNUSED;
 static unsigned long openssl_thread_id_cb(void) GRPC_UNUSED;
-static const unsigned char kSslSessionIdContext[] = {'g', 'r', 'p', 'c'};
 
 static void openssl_locking_cb(int mode, int type, const char* file, int line) {
   if (mode & CRYPTO_LOCK) {
@@ -138,22 +151,27 @@
 static unsigned long openssl_thread_id_cb(void) {
   return static_cast<unsigned long>(gpr_thd_currentid());
 }
+#endif
 
 static void init_openssl(void) {
-  int i;
-  int num_locks;
   SSL_library_init();
   SSL_load_error_strings();
   OpenSSL_add_all_algorithms();
-  num_locks = CRYPTO_num_locks();
-  GPR_ASSERT(num_locks > 0);
-  g_openssl_mutexes = static_cast<gpr_mu*>(
-      gpr_malloc(static_cast<size_t>(num_locks) * sizeof(gpr_mu)));
-  for (i = 0; i < CRYPTO_num_locks(); i++) {
-    gpr_mu_init(&g_openssl_mutexes[i]);
+#if OPENSSL_VERSION_NUMBER < 0x10100000
+  if (!CRYPTO_get_locking_callback()) {
+    int num_locks = CRYPTO_num_locks();
+    GPR_ASSERT(num_locks > 0);
+    g_openssl_mutexes = static_cast<gpr_mu*>(
+        gpr_malloc(static_cast<size_t>(num_locks) * sizeof(gpr_mu)));
+    for (int i = 0; i < num_locks; i++) {
+      gpr_mu_init(&g_openssl_mutexes[i]);
+    }
+    CRYPTO_set_locking_callback(openssl_locking_cb);
+    CRYPTO_set_id_callback(openssl_thread_id_cb);
+  } else {
+    gpr_log(GPR_INFO, "OpenSSL callback has already been set.");
   }
-  CRYPTO_set_locking_callback(openssl_locking_cb);
-  CRYPTO_set_id_callback(openssl_thread_id_cb);
+#endif
   g_ssl_ctx_ex_factory_index =
       SSL_CTX_get_ex_new_index(0, nullptr, nullptr, nullptr, nullptr);
   GPR_ASSERT(g_ssl_ctx_ex_factory_index != -1);
@@ -987,94 +1005,15 @@
   gpr_ref_init(&factory->refcount, 1);
 }
 
-/* --- tsi_handshaker methods implementation. ---*/
+/* --- tsi_handshaker_result methods implementation. ---*/
 
-static tsi_result ssl_handshaker_get_bytes_to_send_to_peer(tsi_handshaker* self,
-                                                           unsigned char* bytes,
-                                                           size_t* bytes_size) {
-  tsi_ssl_handshaker* impl = reinterpret_cast<tsi_ssl_handshaker*>(self);
-  int bytes_read_from_ssl = 0;
-  if (bytes == nullptr || bytes_size == nullptr || *bytes_size == 0 ||
-      *bytes_size > INT_MAX) {
-    return TSI_INVALID_ARGUMENT;
-  }
-  GPR_ASSERT(*bytes_size <= INT_MAX);
-  bytes_read_from_ssl =
-      BIO_read(impl->network_io, bytes, static_cast<int>(*bytes_size));
-  if (bytes_read_from_ssl < 0) {
-    *bytes_size = 0;
-    if (!BIO_should_retry(impl->network_io)) {
-      impl->result = TSI_INTERNAL_ERROR;
-      return impl->result;
-    } else {
-      return TSI_OK;
-    }
-  }
-  *bytes_size = static_cast<size_t>(bytes_read_from_ssl);
-  return BIO_pending(impl->network_io) == 0 ? TSI_OK : TSI_INCOMPLETE_DATA;
-}
-
-static tsi_result ssl_handshaker_get_result(tsi_handshaker* self) {
-  tsi_ssl_handshaker* impl = reinterpret_cast<tsi_ssl_handshaker*>(self);
-  if ((impl->result == TSI_HANDSHAKE_IN_PROGRESS) &&
-      SSL_is_init_finished(impl->ssl)) {
-    impl->result = TSI_OK;
-  }
-  return impl->result;
-}
-
-static tsi_result ssl_handshaker_process_bytes_from_peer(
-    tsi_handshaker* self, const unsigned char* bytes, size_t* bytes_size) {
-  tsi_ssl_handshaker* impl = reinterpret_cast<tsi_ssl_handshaker*>(self);
-  int bytes_written_into_ssl_size = 0;
-  if (bytes == nullptr || bytes_size == nullptr || *bytes_size > INT_MAX) {
-    return TSI_INVALID_ARGUMENT;
-  }
-  GPR_ASSERT(*bytes_size <= INT_MAX);
-  bytes_written_into_ssl_size =
-      BIO_write(impl->network_io, bytes, static_cast<int>(*bytes_size));
-  if (bytes_written_into_ssl_size < 0) {
-    gpr_log(GPR_ERROR, "Could not write to memory BIO.");
-    impl->result = TSI_INTERNAL_ERROR;
-    return impl->result;
-  }
-  *bytes_size = static_cast<size_t>(bytes_written_into_ssl_size);
-
-  if (!tsi_handshaker_is_in_progress(self)) {
-    impl->result = TSI_OK;
-    return impl->result;
-  } else {
-    /* Get ready to get some bytes from SSL. */
-    int ssl_result = SSL_do_handshake(impl->ssl);
-    ssl_result = SSL_get_error(impl->ssl, ssl_result);
-    switch (ssl_result) {
-      case SSL_ERROR_WANT_READ:
-        if (BIO_pending(impl->network_io) == 0) {
-          /* We need more data. */
-          return TSI_INCOMPLETE_DATA;
-        } else {
-          return TSI_OK;
-        }
-      case SSL_ERROR_NONE:
-        return TSI_OK;
-      default: {
-        char err_str[256];
-        ERR_error_string_n(ERR_get_error(), err_str, sizeof(err_str));
-        gpr_log(GPR_ERROR, "Handshake failed with fatal error %s: %s.",
-                ssl_error_string(ssl_result), err_str);
-        impl->result = TSI_PROTOCOL_FAILURE;
-        return impl->result;
-      }
-    }
-  }
-}
-
-static tsi_result ssl_handshaker_extract_peer(tsi_handshaker* self,
-                                              tsi_peer* peer) {
+static tsi_result ssl_handshaker_result_extract_peer(
+    const tsi_handshaker_result* self, tsi_peer* peer) {
   tsi_result result = TSI_OK;
   const unsigned char* alpn_selected = nullptr;
   unsigned int alpn_selected_len;
-  tsi_ssl_handshaker* impl = reinterpret_cast<tsi_ssl_handshaker*>(self);
+  const tsi_ssl_handshaker_result* impl =
+      reinterpret_cast<const tsi_ssl_handshaker_result*>(self);
   X509* peer_cert = SSL_get_peer_certificate(impl->ssl);
   if (peer_cert != nullptr) {
     result = peer_from_x509(peer_cert, 1, peer);
@@ -1120,12 +1059,14 @@
   return result;
 }
 
-static tsi_result ssl_handshaker_create_frame_protector(
-    tsi_handshaker* self, size_t* max_output_protected_frame_size,
+static tsi_result ssl_handshaker_result_create_frame_protector(
+    const tsi_handshaker_result* self, size_t* max_output_protected_frame_size,
     tsi_frame_protector** protector) {
   size_t actual_max_output_protected_frame_size =
       TSI_SSL_MAX_PROTECTED_FRAME_SIZE_UPPER_BOUND;
-  tsi_ssl_handshaker* impl = reinterpret_cast<tsi_ssl_handshaker*>(self);
+  tsi_ssl_handshaker_result* impl =
+      reinterpret_cast<tsi_ssl_handshaker_result*>(
+          const_cast<tsi_handshaker_result*>(self));
   tsi_ssl_frame_protector* protector_impl =
       static_cast<tsi_ssl_frame_protector*>(
           gpr_zalloc(sizeof(*protector_impl)));
@@ -1153,35 +1094,218 @@
     return TSI_INTERNAL_ERROR;
   }
 
-  /* Transfer ownership of ssl and network_io to the frame protector. It is OK
-   * as the caller cannot call anything else but destroy on the handshaker
-   * after this call. */
+  /* Transfer ownership of ssl and network_io to the frame protector. */
   protector_impl->ssl = impl->ssl;
   impl->ssl = nullptr;
   protector_impl->network_io = impl->network_io;
   impl->network_io = nullptr;
-
   protector_impl->base.vtable = &frame_protector_vtable;
   *protector = &protector_impl->base;
   return TSI_OK;
 }
 
+static tsi_result ssl_handshaker_result_get_unused_bytes(
+    const tsi_handshaker_result* self, const unsigned char** bytes,
+    size_t* bytes_size) {
+  const tsi_ssl_handshaker_result* impl =
+      reinterpret_cast<const tsi_ssl_handshaker_result*>(self);
+  *bytes_size = impl->unused_bytes_size;
+  *bytes = impl->unused_bytes;
+  return TSI_OK;
+}
+
+static void ssl_handshaker_result_destroy(tsi_handshaker_result* self) {
+  tsi_ssl_handshaker_result* impl =
+      reinterpret_cast<tsi_ssl_handshaker_result*>(self);
+  SSL_free(impl->ssl);
+  BIO_free(impl->network_io);
+  gpr_free(impl->unused_bytes);
+  gpr_free(impl);
+}
+
+static const tsi_handshaker_result_vtable handshaker_result_vtable = {
+    ssl_handshaker_result_extract_peer,
+    nullptr, /* create_zero_copy_grpc_protector */
+    ssl_handshaker_result_create_frame_protector,
+    ssl_handshaker_result_get_unused_bytes,
+    ssl_handshaker_result_destroy,
+};
+
+static tsi_result ssl_handshaker_result_create(
+    tsi_ssl_handshaker* handshaker, const unsigned char* unused_bytes,
+    size_t unused_bytes_size, tsi_handshaker_result** handshaker_result) {
+  if (handshaker == nullptr || handshaker_result == nullptr ||
+      (unused_bytes_size > 0 && unused_bytes == nullptr)) {
+    return TSI_INVALID_ARGUMENT;
+  }
+  tsi_ssl_handshaker_result* result =
+      static_cast<tsi_ssl_handshaker_result*>(gpr_zalloc(sizeof(*result)));
+  result->base.vtable = &handshaker_result_vtable;
+  /* Transfer ownership of ssl and network_io to the handshaker result. */
+  result->ssl = handshaker->ssl;
+  handshaker->ssl = nullptr;
+  result->network_io = handshaker->network_io;
+  handshaker->network_io = nullptr;
+  if (unused_bytes_size > 0) {
+    result->unused_bytes =
+        static_cast<unsigned char*>(gpr_malloc(unused_bytes_size));
+    memcpy(result->unused_bytes, unused_bytes, unused_bytes_size);
+  }
+  result->unused_bytes_size = unused_bytes_size;
+  *handshaker_result = &result->base;
+  return TSI_OK;
+}
+
+/* --- tsi_handshaker methods implementation. ---*/
+
+static tsi_result ssl_handshaker_get_bytes_to_send_to_peer(
+    tsi_ssl_handshaker* impl, unsigned char* bytes, size_t* bytes_size) {
+  int bytes_read_from_ssl = 0;
+  if (bytes == nullptr || bytes_size == nullptr || *bytes_size == 0 ||
+      *bytes_size > INT_MAX) {
+    return TSI_INVALID_ARGUMENT;
+  }
+  GPR_ASSERT(*bytes_size <= INT_MAX);
+  bytes_read_from_ssl =
+      BIO_read(impl->network_io, bytes, static_cast<int>(*bytes_size));
+  if (bytes_read_from_ssl < 0) {
+    *bytes_size = 0;
+    if (!BIO_should_retry(impl->network_io)) {
+      impl->result = TSI_INTERNAL_ERROR;
+      return impl->result;
+    } else {
+      return TSI_OK;
+    }
+  }
+  *bytes_size = static_cast<size_t>(bytes_read_from_ssl);
+  return BIO_pending(impl->network_io) == 0 ? TSI_OK : TSI_INCOMPLETE_DATA;
+}
+
+static tsi_result ssl_handshaker_get_result(tsi_ssl_handshaker* impl) {
+  if ((impl->result == TSI_HANDSHAKE_IN_PROGRESS) &&
+      SSL_is_init_finished(impl->ssl)) {
+    impl->result = TSI_OK;
+  }
+  return impl->result;
+}
+
+static tsi_result ssl_handshaker_process_bytes_from_peer(
+    tsi_ssl_handshaker* impl, const unsigned char* bytes, size_t* bytes_size) {
+  int bytes_written_into_ssl_size = 0;
+  if (bytes == nullptr || bytes_size == nullptr || *bytes_size > INT_MAX) {
+    return TSI_INVALID_ARGUMENT;
+  }
+  GPR_ASSERT(*bytes_size <= INT_MAX);
+  bytes_written_into_ssl_size =
+      BIO_write(impl->network_io, bytes, static_cast<int>(*bytes_size));
+  if (bytes_written_into_ssl_size < 0) {
+    gpr_log(GPR_ERROR, "Could not write to memory BIO.");
+    impl->result = TSI_INTERNAL_ERROR;
+    return impl->result;
+  }
+  *bytes_size = static_cast<size_t>(bytes_written_into_ssl_size);
+
+  if (ssl_handshaker_get_result(impl) != TSI_HANDSHAKE_IN_PROGRESS) {
+    impl->result = TSI_OK;
+    return impl->result;
+  } else {
+    /* Get ready to get some bytes from SSL. */
+    int ssl_result = SSL_do_handshake(impl->ssl);
+    ssl_result = SSL_get_error(impl->ssl, ssl_result);
+    switch (ssl_result) {
+      case SSL_ERROR_WANT_READ:
+        if (BIO_pending(impl->network_io) == 0) {
+          /* We need more data. */
+          return TSI_INCOMPLETE_DATA;
+        } else {
+          return TSI_OK;
+        }
+      case SSL_ERROR_NONE:
+        return TSI_OK;
+      default: {
+        char err_str[256];
+        ERR_error_string_n(ERR_get_error(), err_str, sizeof(err_str));
+        gpr_log(GPR_ERROR, "Handshake failed with fatal error %s: %s.",
+                ssl_error_string(ssl_result), err_str);
+        impl->result = TSI_PROTOCOL_FAILURE;
+        return impl->result;
+      }
+    }
+  }
+}
+
 static void ssl_handshaker_destroy(tsi_handshaker* self) {
   tsi_ssl_handshaker* impl = reinterpret_cast<tsi_ssl_handshaker*>(self);
   SSL_free(impl->ssl);
   BIO_free(impl->network_io);
+  gpr_free(impl->outgoing_bytes_buffer);
   tsi_ssl_handshaker_factory_unref(impl->factory_ref);
   gpr_free(impl);
 }
 
+static tsi_result ssl_handshaker_next(
+    tsi_handshaker* self, const unsigned char* received_bytes,
+    size_t received_bytes_size, const unsigned char** bytes_to_send,
+    size_t* bytes_to_send_size, tsi_handshaker_result** handshaker_result,
+    tsi_handshaker_on_next_done_cb cb, void* user_data) {
+  /* Input sanity check.  */
+  if ((received_bytes_size > 0 && received_bytes == nullptr) ||
+      bytes_to_send == nullptr || bytes_to_send_size == nullptr ||
+      handshaker_result == nullptr) {
+    return TSI_INVALID_ARGUMENT;
+  }
+  /* If there are received bytes, process them first.  */
+  tsi_ssl_handshaker* impl = reinterpret_cast<tsi_ssl_handshaker*>(self);
+  tsi_result status = TSI_OK;
+  size_t bytes_consumed = received_bytes_size;
+  if (received_bytes_size > 0) {
+    status = ssl_handshaker_process_bytes_from_peer(impl, received_bytes,
+                                                    &bytes_consumed);
+    if (status != TSI_OK) return status;
+  }
+  /* Get bytes to send to the peer, if available.  */
+  size_t offset = 0;
+  do {
+    size_t to_send_size = impl->outgoing_bytes_buffer_size - offset;
+    status = ssl_handshaker_get_bytes_to_send_to_peer(
+        impl, impl->outgoing_bytes_buffer + offset, &to_send_size);
+    offset += to_send_size;
+    if (status == TSI_INCOMPLETE_DATA) {
+      impl->outgoing_bytes_buffer_size *= 2;
+      impl->outgoing_bytes_buffer = static_cast<unsigned char*>(gpr_realloc(
+          impl->outgoing_bytes_buffer, impl->outgoing_bytes_buffer_size));
+    }
+  } while (status == TSI_INCOMPLETE_DATA);
+  if (status != TSI_OK) return status;
+  *bytes_to_send = impl->outgoing_bytes_buffer;
+  *bytes_to_send_size = offset;
+  /* If handshake completes, create tsi_handshaker_result.  */
+  if (ssl_handshaker_get_result(impl) == TSI_HANDSHAKE_IN_PROGRESS) {
+    *handshaker_result = nullptr;
+  } else {
+    size_t unused_bytes_size = received_bytes_size - bytes_consumed;
+    const unsigned char* unused_bytes =
+        unused_bytes_size == 0 ? nullptr : received_bytes + bytes_consumed;
+    status = ssl_handshaker_result_create(impl, unused_bytes, unused_bytes_size,
+                                          handshaker_result);
+    if (status == TSI_OK) {
+      /* Indicates that the handshake has completed and that a handshaker_result
+       * has been created. */
+      self->handshaker_result_created = true;
+    }
+  }
+  return status;
+}
+
 static const tsi_handshaker_vtable handshaker_vtable = {
-    ssl_handshaker_get_bytes_to_send_to_peer,
-    ssl_handshaker_process_bytes_from_peer,
-    ssl_handshaker_get_result,
-    ssl_handshaker_extract_peer,
-    ssl_handshaker_create_frame_protector,
+    nullptr, /* get_bytes_to_send_to_peer -- deprecated */
+    nullptr, /* process_bytes_from_peer   -- deprecated */
+    nullptr, /* get_result                -- deprecated */
+    nullptr, /* extract_peer              -- deprecated */
+    nullptr, /* create_frame_protector    -- deprecated */
     ssl_handshaker_destroy,
-    nullptr,
+    ssl_handshaker_next,
+    nullptr, /* shutdown */
 };
 
 /* --- tsi_ssl_handshaker_factory common methods. --- */
@@ -1259,6 +1383,10 @@
   impl->ssl = ssl;
   impl->network_io = network_io;
   impl->result = TSI_HANDSHAKE_IN_PROGRESS;
+  impl->outgoing_bytes_buffer_size =
+      TSI_SSL_HANDSHAKER_OUTGOING_BUFFER_INITIAL_SIZE;
+  impl->outgoing_bytes_buffer =
+      static_cast<unsigned char*>(gpr_zalloc(impl->outgoing_bytes_buffer_size));
   impl->base.vtable = &handshaker_vtable;
   impl->factory_ref = tsi_ssl_handshaker_factory_ref(factory);
 
diff --git a/src/core/tsi/transport_security.cc b/src/core/tsi/transport_security.cc
index 129533f..99b3229 100644
--- a/src/core/tsi/transport_security.cc
+++ b/src/core/tsi/transport_security.cc
@@ -136,6 +136,7 @@
     return TSI_INVALID_ARGUMENT;
   }
   if (self->frame_protector_created) return TSI_FAILED_PRECONDITION;
+  if (self->handshake_shutdown) return TSI_HANDSHAKE_SHUTDOWN;
   if (self->vtable->get_bytes_to_send_to_peer == nullptr)
     return TSI_UNIMPLEMENTED;
   return self->vtable->get_bytes_to_send_to_peer(self, bytes, bytes_size);
@@ -149,6 +150,7 @@
     return TSI_INVALID_ARGUMENT;
   }
   if (self->frame_protector_created) return TSI_FAILED_PRECONDITION;
+  if (self->handshake_shutdown) return TSI_HANDSHAKE_SHUTDOWN;
   if (self->vtable->process_bytes_from_peer == nullptr)
     return TSI_UNIMPLEMENTED;
   return self->vtable->process_bytes_from_peer(self, bytes, bytes_size);
@@ -157,6 +159,7 @@
 tsi_result tsi_handshaker_get_result(tsi_handshaker* self) {
   if (self == nullptr || self->vtable == nullptr) return TSI_INVALID_ARGUMENT;
   if (self->frame_protector_created) return TSI_FAILED_PRECONDITION;
+  if (self->handshake_shutdown) return TSI_HANDSHAKE_SHUTDOWN;
   if (self->vtable->get_result == nullptr) return TSI_UNIMPLEMENTED;
   return self->vtable->get_result(self);
 }
@@ -167,6 +170,7 @@
   }
   memset(peer, 0, sizeof(tsi_peer));
   if (self->frame_protector_created) return TSI_FAILED_PRECONDITION;
+  if (self->handshake_shutdown) return TSI_HANDSHAKE_SHUTDOWN;
   if (tsi_handshaker_get_result(self) != TSI_OK) {
     return TSI_FAILED_PRECONDITION;
   }
@@ -182,6 +186,7 @@
     return TSI_INVALID_ARGUMENT;
   }
   if (self->frame_protector_created) return TSI_FAILED_PRECONDITION;
+  if (self->handshake_shutdown) return TSI_HANDSHAKE_SHUTDOWN;
   if (tsi_handshaker_get_result(self) != TSI_OK) return TSI_FAILED_PRECONDITION;
   if (self->vtable->create_frame_protector == nullptr) return TSI_UNIMPLEMENTED;
   result = self->vtable->create_frame_protector(self, max_protected_frame_size,
@@ -199,12 +204,21 @@
     tsi_handshaker_on_next_done_cb cb, void* user_data) {
   if (self == nullptr || self->vtable == nullptr) return TSI_INVALID_ARGUMENT;
   if (self->handshaker_result_created) return TSI_FAILED_PRECONDITION;
+  if (self->handshake_shutdown) return TSI_HANDSHAKE_SHUTDOWN;
   if (self->vtable->next == nullptr) return TSI_UNIMPLEMENTED;
   return self->vtable->next(self, received_bytes, received_bytes_size,
                             bytes_to_send, bytes_to_send_size,
                             handshaker_result, cb, user_data);
 }
 
+void tsi_handshaker_shutdown(tsi_handshaker* self) {
+  if (self == nullptr || self->vtable == nullptr) return;
+  self->handshake_shutdown = true;
+  if (self->vtable->shutdown != nullptr) {
+    self->vtable->shutdown(self);
+  }
+}
+
 void tsi_handshaker_destroy(tsi_handshaker* self) {
   if (self == nullptr) return;
   self->vtable->destroy(self);
diff --git a/src/core/tsi/transport_security.h b/src/core/tsi/transport_security.h
index b1ec82d..1923a70 100644
--- a/src/core/tsi/transport_security.h
+++ b/src/core/tsi/transport_security.h
@@ -73,12 +73,14 @@
                      size_t* bytes_to_send_size,
                      tsi_handshaker_result** handshaker_result,
                      tsi_handshaker_on_next_done_cb cb, void* user_data);
+  void (*shutdown)(tsi_handshaker* self);
 } tsi_handshaker_vtable;
 
 struct tsi_handshaker {
   const tsi_handshaker_vtable* vtable;
   bool frame_protector_created;
   bool handshaker_result_created;
+  bool handshake_shutdown;
 };
 
 /* Base for tsi_handshaker_result implementations.
diff --git a/src/core/tsi/transport_security_adapter.cc b/src/core/tsi/transport_security_adapter.cc
deleted file mode 100644
index 25608f0..0000000
--- a/src/core/tsi/transport_security_adapter.cc
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- *
- * Copyright 2017 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.
- *
- */
-
-#include <grpc/support/port_platform.h>
-
-#include "src/core/tsi/transport_security_adapter.h"
-
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include "src/core/tsi/transport_security.h"
-
-#define TSI_ADAPTER_INITIAL_BUFFER_SIZE 256
-
-/* --- tsi_adapter_handshaker_result implementation ---*/
-
-typedef struct {
-  tsi_handshaker_result base;
-  tsi_handshaker* wrapped;
-  unsigned char* unused_bytes;
-  size_t unused_bytes_size;
-} tsi_adapter_handshaker_result;
-
-static tsi_result adapter_result_extract_peer(const tsi_handshaker_result* self,
-                                              tsi_peer* peer) {
-  tsi_adapter_handshaker_result* impl = (tsi_adapter_handshaker_result*)self;
-  return tsi_handshaker_extract_peer(impl->wrapped, peer);
-}
-
-static tsi_result adapter_result_create_frame_protector(
-    const tsi_handshaker_result* self, size_t* max_output_protected_frame_size,
-    tsi_frame_protector** protector) {
-  tsi_adapter_handshaker_result* impl = (tsi_adapter_handshaker_result*)self;
-  return tsi_handshaker_create_frame_protector(
-      impl->wrapped, max_output_protected_frame_size, protector);
-}
-
-static tsi_result adapter_result_get_unused_bytes(
-    const tsi_handshaker_result* self, const unsigned char** bytes,
-    size_t* byte_size) {
-  tsi_adapter_handshaker_result* impl = (tsi_adapter_handshaker_result*)self;
-  *bytes = impl->unused_bytes;
-  *byte_size = impl->unused_bytes_size;
-  return TSI_OK;
-}
-
-static void adapter_result_destroy(tsi_handshaker_result* self) {
-  tsi_adapter_handshaker_result* impl =
-      reinterpret_cast<tsi_adapter_handshaker_result*>(self);
-  tsi_handshaker_destroy(impl->wrapped);
-  gpr_free(impl->unused_bytes);
-  gpr_free(self);
-}
-
-static const tsi_handshaker_result_vtable result_vtable = {
-    adapter_result_extract_peer,
-    nullptr, /* create_zero_copy_grpc_protector */
-    adapter_result_create_frame_protector,
-    adapter_result_get_unused_bytes,
-    adapter_result_destroy,
-};
-
-/* Ownership of wrapped tsi_handshaker is transferred to the result object.  */
-static tsi_result tsi_adapter_create_handshaker_result(
-    tsi_handshaker* wrapped, const unsigned char* unused_bytes,
-    size_t unused_bytes_size, tsi_handshaker_result** handshaker_result) {
-  if (wrapped == nullptr ||
-      (unused_bytes_size > 0 && unused_bytes == nullptr)) {
-    return TSI_INVALID_ARGUMENT;
-  }
-  tsi_adapter_handshaker_result* impl =
-      static_cast<tsi_adapter_handshaker_result*>(gpr_zalloc(sizeof(*impl)));
-  impl->base.vtable = &result_vtable;
-  impl->wrapped = wrapped;
-  impl->unused_bytes_size = unused_bytes_size;
-  if (unused_bytes_size > 0) {
-    impl->unused_bytes =
-        static_cast<unsigned char*>(gpr_malloc(unused_bytes_size));
-    memcpy(impl->unused_bytes, unused_bytes, unused_bytes_size);
-  } else {
-    impl->unused_bytes = nullptr;
-  }
-  *handshaker_result = &impl->base;
-  return TSI_OK;
-}
-
-/* --- tsi_adapter_handshaker implementation ---*/
-
-typedef struct {
-  tsi_handshaker base;
-  tsi_handshaker* wrapped;
-  unsigned char* adapter_buffer;
-  size_t adapter_buffer_size;
-} tsi_adapter_handshaker;
-
-static tsi_result adapter_get_bytes_to_send_to_peer(tsi_handshaker* self,
-                                                    unsigned char* bytes,
-                                                    size_t* bytes_size) {
-  return tsi_handshaker_get_bytes_to_send_to_peer(
-      tsi_adapter_handshaker_get_wrapped(self), bytes, bytes_size);
-}
-
-static tsi_result adapter_process_bytes_from_peer(tsi_handshaker* self,
-                                                  const unsigned char* bytes,
-                                                  size_t* bytes_size) {
-  return tsi_handshaker_process_bytes_from_peer(
-      tsi_adapter_handshaker_get_wrapped(self), bytes, bytes_size);
-}
-
-static tsi_result adapter_get_result(tsi_handshaker* self) {
-  return tsi_handshaker_get_result(tsi_adapter_handshaker_get_wrapped(self));
-}
-
-static tsi_result adapter_extract_peer(tsi_handshaker* self, tsi_peer* peer) {
-  return tsi_handshaker_extract_peer(tsi_adapter_handshaker_get_wrapped(self),
-                                     peer);
-}
-
-static tsi_result adapter_create_frame_protector(
-    tsi_handshaker* self, size_t* max_protected_frame_size,
-    tsi_frame_protector** protector) {
-  return tsi_handshaker_create_frame_protector(
-      tsi_adapter_handshaker_get_wrapped(self), max_protected_frame_size,
-      protector);
-}
-
-static void adapter_destroy(tsi_handshaker* self) {
-  tsi_adapter_handshaker* impl =
-      reinterpret_cast<tsi_adapter_handshaker*>(self);
-  tsi_handshaker_destroy(impl->wrapped);
-  gpr_free(impl->adapter_buffer);
-  gpr_free(self);
-}
-
-static tsi_result adapter_next(
-    tsi_handshaker* self, const unsigned char* received_bytes,
-    size_t received_bytes_size, const unsigned char** bytes_to_send,
-    size_t* bytes_to_send_size, tsi_handshaker_result** handshaker_result,
-    tsi_handshaker_on_next_done_cb cb, void* user_data) {
-  /* Input sanity check.  */
-  if ((received_bytes_size > 0 && received_bytes == nullptr) ||
-      bytes_to_send == nullptr || bytes_to_send_size == nullptr ||
-      handshaker_result == nullptr) {
-    return TSI_INVALID_ARGUMENT;
-  }
-
-  /* If there are received bytes, process them first.  */
-  tsi_adapter_handshaker* impl =
-      reinterpret_cast<tsi_adapter_handshaker*>(self);
-  tsi_result status = TSI_OK;
-  size_t bytes_consumed = received_bytes_size;
-  if (received_bytes_size > 0) {
-    status = tsi_handshaker_process_bytes_from_peer(
-        impl->wrapped, received_bytes, &bytes_consumed);
-    if (status != TSI_OK) return status;
-  }
-
-  /* Get bytes to send to the peer, if available.  */
-  size_t offset = 0;
-  do {
-    size_t to_send_size = impl->adapter_buffer_size - offset;
-    status = tsi_handshaker_get_bytes_to_send_to_peer(
-        impl->wrapped, impl->adapter_buffer + offset, &to_send_size);
-    offset += to_send_size;
-    if (status == TSI_INCOMPLETE_DATA) {
-      impl->adapter_buffer_size *= 2;
-      impl->adapter_buffer = static_cast<unsigned char*>(
-          gpr_realloc(impl->adapter_buffer, impl->adapter_buffer_size));
-    }
-  } while (status == TSI_INCOMPLETE_DATA);
-  if (status != TSI_OK) return status;
-  *bytes_to_send = impl->adapter_buffer;
-  *bytes_to_send_size = offset;
-
-  /* If handshake completes, create tsi_handshaker_result.  */
-  if (tsi_handshaker_is_in_progress(impl->wrapped)) {
-    *handshaker_result = nullptr;
-  } else {
-    size_t unused_bytes_size = received_bytes_size - bytes_consumed;
-    const unsigned char* unused_bytes =
-        unused_bytes_size == 0 ? nullptr : received_bytes + bytes_consumed;
-    status = tsi_adapter_create_handshaker_result(
-        impl->wrapped, unused_bytes, unused_bytes_size, handshaker_result);
-    if (status == TSI_OK) {
-      impl->base.handshaker_result_created = true;
-      impl->wrapped = nullptr;
-    }
-  }
-  return status;
-}
-
-static const tsi_handshaker_vtable handshaker_vtable = {
-    adapter_get_bytes_to_send_to_peer,
-    adapter_process_bytes_from_peer,
-    adapter_get_result,
-    adapter_extract_peer,
-    adapter_create_frame_protector,
-    adapter_destroy,
-    adapter_next,
-};
-
-tsi_handshaker* tsi_create_adapter_handshaker(tsi_handshaker* wrapped) {
-  GPR_ASSERT(wrapped != nullptr);
-  tsi_adapter_handshaker* impl =
-      static_cast<tsi_adapter_handshaker*>(gpr_zalloc(sizeof(*impl)));
-  impl->base.vtable = &handshaker_vtable;
-  impl->wrapped = wrapped;
-  impl->adapter_buffer_size = TSI_ADAPTER_INITIAL_BUFFER_SIZE;
-  impl->adapter_buffer =
-      static_cast<unsigned char*>(gpr_malloc(impl->adapter_buffer_size));
-  return &impl->base;
-}
-
-tsi_handshaker* tsi_adapter_handshaker_get_wrapped(tsi_handshaker* adapter) {
-  if (adapter == nullptr) return nullptr;
-  tsi_adapter_handshaker* impl =
-      reinterpret_cast<tsi_adapter_handshaker*>(adapter);
-  return impl->wrapped;
-}
diff --git a/src/core/tsi/transport_security_adapter.h b/src/core/tsi/transport_security_adapter.h
deleted file mode 100644
index f83ecc5..0000000
--- a/src/core/tsi/transport_security_adapter.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- *
- * Copyright 2017 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_TSI_TRANSPORT_SECURITY_ADAPTER_H
-#define GRPC_CORE_TSI_TRANSPORT_SECURITY_ADAPTER_H
-
-#include <grpc/support/port_platform.h>
-
-#include "src/core/tsi/transport_security_interface.h"
-
-/* Create a tsi handshaker that takes an implementation of old interface and
-   converts into an implementation of new interface. In the old interface,
-   there are get_bytes_to_send_to_peer, process_bytes_from_peer, get_result,
-   extract_peer, and create_frame_protector. In the new interface, only next
-   method is needed. See transport_security_interface.h for details. Note that
-   this tsi adapter handshaker is temporary. It will be removed once TSI has
-   been fully migrated to the new interface.
-   Ownership of input tsi_handshaker is transferred to this new adapter.  */
-tsi_handshaker* tsi_create_adapter_handshaker(tsi_handshaker* wrapped);
-
-/* Given a tsi adapter handshaker, return the original wrapped handshaker. The
-   adapter still owns the wrapped handshaker which should not be destroyed by
-   the caller. */
-tsi_handshaker* tsi_adapter_handshaker_get_wrapped(tsi_handshaker* adapter);
-
-#endif /* GRPC_CORE_TSI_TRANSPORT_SECURITY_ADAPTER_H */
diff --git a/src/core/tsi/transport_security_interface.h b/src/core/tsi/transport_security_interface.h
index 8c10866..7a0cdc3 100644
--- a/src/core/tsi/transport_security_interface.h
+++ b/src/core/tsi/transport_security_interface.h
@@ -42,7 +42,8 @@
   TSI_PROTOCOL_FAILURE = 10,
   TSI_HANDSHAKE_IN_PROGRESS = 11,
   TSI_OUT_OF_RESOURCES = 12,
-  TSI_ASYNC = 13
+  TSI_ASYNC = 13,
+  TSI_HANDSHAKE_SHUTDOWN = 14,
 } tsi_result;
 
 typedef enum {
@@ -332,6 +333,8 @@
    ------------------------------------------------------------------------   */
 typedef struct tsi_handshaker tsi_handshaker;
 
+/* TODO(jiangtaoli2016): Cleans up deprecated methods when we are ready. */
+
 /* TO BE DEPRECATED SOON. Use tsi_handshaker_next instead.
    Gets bytes that need to be sent to the peer.
    - bytes is the buffer that will be written with the data to be sent to the
@@ -440,6 +443,13 @@
     size_t* bytes_to_send_size, tsi_handshaker_result** handshaker_result,
     tsi_handshaker_on_next_done_cb cb, void* user_data);
 
+/* This method shuts down a TSI handshake that is in progress.
+ *
+ * This method will be invoked when TSI handshake should be terminated before
+ * being finished in order to free any resources being used.
+ */
+void tsi_handshaker_shutdown(tsi_handshaker* self);
+
 /* This method releases the tsi_handshaker object. After this method is called,
    no other method can be called on the object.  */
 void tsi_handshaker_destroy(tsi_handshaker* self);
diff --git a/src/cpp/client/secure_credentials.cc b/src/cpp/client/secure_credentials.cc
index 19d67c2..00245b3 100644
--- a/src/cpp/client/secure_credentials.cc
+++ b/src/cpp/client/secure_credentials.cc
@@ -87,6 +87,27 @@
   return WrapChannelCredentials(c_creds);
 }
 
+namespace experimental {
+
+// Builds ALTS Credentials given ALTS specific options
+std::shared_ptr<ChannelCredentials> AltsCredentials(
+    const AltsCredentialsOptions& options) {
+  GrpcLibraryCodegen init;  // To call grpc_init().
+  grpc_alts_credentials_options* c_options =
+      grpc_alts_credentials_client_options_create();
+  for (auto service_account = options.target_service_accounts.begin();
+       service_account != options.target_service_accounts.end();
+       service_account++) {
+    grpc_alts_credentials_client_options_add_target_service_account(
+        c_options, service_account->c_str());
+  }
+  grpc_channel_credentials* c_creds = grpc_alts_credentials_create(c_options);
+  grpc_alts_credentials_options_destroy(c_options);
+  return WrapChannelCredentials(c_creds);
+}
+
+}  // namespace experimental
+
 // Builds credentials for use when running in GCE
 std::shared_ptr<CallCredentials> GoogleComputeEngineCredentials() {
   GrpcLibraryCodegen init;  // To call grpc_init().
diff --git a/src/cpp/common/core_codegen.cc b/src/cpp/common/core_codegen.cc
index aa9788d..619aaca 100644
--- a/src/cpp/common/core_codegen.cc
+++ b/src/cpp/common/core_codegen.cc
@@ -98,6 +98,10 @@
   ::grpc_byte_buffer_destroy(bb);
 }
 
+size_t CoreCodegen::grpc_byte_buffer_length(grpc_byte_buffer* bb) {
+  return ::grpc_byte_buffer_length(bb);
+}
+
 grpc_call_error CoreCodegen::grpc_call_cancel_with_status(
     grpc_call* call, grpc_status_code status, const char* description,
     void* reserved) {
@@ -135,6 +139,12 @@
   return ::grpc_slice_new_with_user_data(p, len, destroy, user_data);
 }
 
+grpc_slice CoreCodegen::grpc_slice_new_with_len(void* p, size_t len,
+                                                void (*destroy)(void*,
+                                                                size_t)) {
+  return ::grpc_slice_new_with_len(p, len, destroy);
+}
+
 grpc_slice CoreCodegen::grpc_empty_slice() { return ::grpc_empty_slice(); }
 
 grpc_slice CoreCodegen::grpc_slice_malloc(size_t length) {
diff --git a/src/cpp/common/version_cc.cc b/src/cpp/common/version_cc.cc
index fb1723c..54cd207 100644
--- a/src/cpp/common/version_cc.cc
+++ b/src/cpp/common/version_cc.cc
@@ -22,5 +22,5 @@
 #include <grpcpp/grpcpp.h>
 
 namespace grpc {
-grpc::string Version() { return "1.11.0-dev"; }
+grpc::string Version() { return "1.13.0-dev"; }
 }  // namespace grpc
diff --git a/src/cpp/server/load_reporter/load_data_store.cc b/src/cpp/server/load_reporter/load_data_store.cc
new file mode 100644
index 0000000..70f12c1
--- /dev/null
+++ b/src/cpp/server/load_reporter/load_data_store.cc
@@ -0,0 +1,273 @@
+/*
+ *
+ * Copyright 2018 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.
+ *
+ */
+
+#include <cstdlib>
+#include <set>
+#include <unordered_map>
+#include <vector>
+
+#include "src/cpp/server/load_reporter/load_data_store.h"
+
+namespace grpc {
+namespace load_reporter {
+
+// Some helper functions.
+namespace {
+
+// Given a map from type K to a set of value type V, finds the set associated
+// with the given key and erases the value from the set. If the set becomes
+// empty, also erases the key-set pair. Returns true if the value is erased
+// successfully.
+template <typename K, typename V>
+bool UnorderedMapOfSetEraseKeyValue(std::unordered_map<K, std::set<V>>& map,
+                                    const K& key, const V& value) {
+  auto it = map.find(key);
+  if (it != map.end()) {
+    size_t erased = it->second.erase(value);
+    if (it->second.size() == 0) {
+      map.erase(it);
+    }
+    return erased;
+  }
+  return false;
+};
+
+// Given a map from type K to a set of value type V, removes the given key and
+// the associated set, and returns the set. Returns an empty set if the key is
+// not found.
+template <typename K, typename V>
+std::set<V> UnorderedMapOfSetExtract(std::unordered_map<K, std::set<V>>& map,
+                                     const K& key) {
+  auto it = map.find(key);
+  if (it != map.end()) {
+    auto set = std::move(it->second);
+    map.erase(it);
+    return set;
+  }
+  return {};
+};
+
+// From a non-empty container, returns a pointer to a random element.
+template <typename C>
+const typename C::value_type* RandomElement(const C& container) {
+  GPR_ASSERT(!container.empty());
+  auto it = container.begin();
+  std::advance(it, std::rand() % container.size());
+  return &(*it);
+}
+
+}  // namespace
+
+void PerBalancerStore::MergeRow(const LoadRecordKey& key,
+                                const LoadRecordValue& value) {
+  // During suspension, the load data received will be dropped.
+  if (!suspended_) {
+    load_record_map_[key].MergeFrom(value);
+    gpr_log(GPR_DEBUG,
+            "[PerBalancerStore %p] Load data merged (Key: %s, Value: %s).",
+            this, key.ToString().c_str(), value.ToString().c_str());
+  } else {
+    gpr_log(GPR_DEBUG,
+            "[PerBalancerStore %p] Load data dropped (Key: %s, Value: %s).",
+            this, key.ToString().c_str(), value.ToString().c_str());
+  }
+  // We always keep track of num_calls_in_progress_, so that when this
+  // store is resumed, we still have a correct value of
+  // num_calls_in_progress_.
+  GPR_ASSERT(static_cast<int64_t>(num_calls_in_progress_) +
+                 value.GetNumCallsInProgressDelta() >=
+             0);
+  num_calls_in_progress_ += value.GetNumCallsInProgressDelta();
+}
+
+void PerBalancerStore::Suspend() {
+  suspended_ = true;
+  load_record_map_.clear();
+  gpr_log(GPR_DEBUG, "[PerBalancerStore %p] Suspended.", this);
+}
+
+void PerBalancerStore::Resume() {
+  suspended_ = false;
+  gpr_log(GPR_DEBUG, "[PerBalancerStore %p] Resumed.", this);
+}
+
+uint64_t PerBalancerStore::GetNumCallsInProgressForReport() {
+  GPR_ASSERT(!suspended_);
+  last_reported_num_calls_in_progress_ = num_calls_in_progress_;
+  return num_calls_in_progress_;
+}
+
+void PerHostStore::ReportStreamCreated(const grpc::string& lb_id,
+                                       const grpc::string& load_key) {
+  GPR_ASSERT(lb_id != kInvalidLbId);
+  SetUpForNewLbId(lb_id, load_key);
+  // Prior to this one, there was no load balancer receiving report, so we may
+  // have unassigned orphaned stores to assign to this new balancer.
+  // TODO(juanlishen): If the load key of this new stream is the same with
+  // some previously adopted orphan store, we may want to take the orphan to
+  // this stream. Need to discuss with LB team.
+  if (assigned_stores_.size() == 1) {
+    for (const auto& p : per_balancer_stores_) {
+      const grpc::string& other_lb_id = p.first;
+      const std::unique_ptr<PerBalancerStore>& orphaned_store = p.second;
+      if (other_lb_id != lb_id) {
+        orphaned_store->Resume();
+        AssignOrphanedStore(orphaned_store.get(), lb_id);
+      }
+    }
+  }
+  // The first connected balancer will adopt the kInvalidLbId.
+  if (per_balancer_stores_.size() == 1) {
+    SetUpForNewLbId(kInvalidLbId, "");
+    ReportStreamClosed(kInvalidLbId);
+  }
+}
+
+void PerHostStore::ReportStreamClosed(const grpc::string& lb_id) {
+  auto it_store_for_gone_lb = per_balancer_stores_.find(lb_id);
+  GPR_ASSERT(it_store_for_gone_lb != per_balancer_stores_.end());
+  // Remove this closed stream from our records.
+  GPR_ASSERT(UnorderedMapOfSetEraseKeyValue(
+      load_key_to_receiving_lb_ids_, it_store_for_gone_lb->second->load_key(),
+      lb_id));
+  std::set<PerBalancerStore*> orphaned_stores =
+      UnorderedMapOfSetExtract(assigned_stores_, lb_id);
+  // The stores that were assigned to this balancer are orphaned now. They
+  // should be re-assigned to other balancers which are still receiving reports.
+  for (PerBalancerStore* orphaned_store : orphaned_stores) {
+    const grpc::string* new_receiver = nullptr;
+    auto it = load_key_to_receiving_lb_ids_.find(orphaned_store->load_key());
+    if (it != load_key_to_receiving_lb_ids_.end()) {
+      // First, try to pick from the active balancers with the same load key.
+      new_receiver = RandomElement(it->second);
+    } else if (!assigned_stores_.empty()) {
+      // If failed, pick from all the remaining active balancers.
+      new_receiver = &(RandomElement(assigned_stores_)->first);
+    }
+    if (new_receiver != nullptr) {
+      AssignOrphanedStore(orphaned_store, *new_receiver);
+    } else {
+      // Load data for an LB ID that can't be assigned to any stream should
+      // be dropped.
+      orphaned_store->Suspend();
+    }
+  }
+}
+
+PerBalancerStore* PerHostStore::FindPerBalancerStore(
+    const grpc::string& lb_id) const {
+  return per_balancer_stores_.find(lb_id) != per_balancer_stores_.end()
+             ? per_balancer_stores_.find(lb_id)->second.get()
+             : nullptr;
+}
+
+const std::set<PerBalancerStore*>* PerHostStore::GetAssignedStores(
+    const grpc::string& lb_id) const {
+  auto it = assigned_stores_.find(lb_id);
+  if (it == assigned_stores_.end()) return nullptr;
+  return &(it->second);
+}
+
+void PerHostStore::AssignOrphanedStore(PerBalancerStore* orphaned_store,
+                                       const grpc::string& new_receiver) {
+  auto it = assigned_stores_.find(new_receiver);
+  GPR_ASSERT(it != assigned_stores_.end());
+  it->second.insert(orphaned_store);
+  gpr_log(GPR_INFO,
+          "[PerHostStore %p] Re-assigned orphaned store (%p) with original LB"
+          " ID of %s to new receiver %s",
+          this, orphaned_store, orphaned_store->lb_id().c_str(),
+          new_receiver.c_str());
+}
+
+void PerHostStore::SetUpForNewLbId(const grpc::string& lb_id,
+                                   const grpc::string& load_key) {
+  // The top-level caller (i.e., LoadReportService) should guarantee the
+  // lb_id is unique for each reporting stream.
+  GPR_ASSERT(per_balancer_stores_.find(lb_id) == per_balancer_stores_.end());
+  GPR_ASSERT(assigned_stores_.find(lb_id) == assigned_stores_.end());
+  load_key_to_receiving_lb_ids_[load_key].insert(lb_id);
+  std::unique_ptr<PerBalancerStore> per_balancer_store(
+      new PerBalancerStore(lb_id, load_key));
+  assigned_stores_[lb_id] = {per_balancer_store.get()};
+  per_balancer_stores_[lb_id] = std::move(per_balancer_store);
+}
+
+PerBalancerStore* LoadDataStore::FindPerBalancerStore(
+    const string& hostname, const string& lb_id) const {
+  auto it = per_host_stores_.find(hostname);
+  if (it != per_host_stores_.end()) {
+    const PerHostStore& per_host_store = it->second;
+    return per_host_store.FindPerBalancerStore(lb_id);
+  } else {
+    return nullptr;
+  }
+}
+
+void LoadDataStore::MergeRow(const grpc::string& hostname,
+                             const LoadRecordKey& key,
+                             const LoadRecordValue& value) {
+  PerBalancerStore* per_balancer_store =
+      FindPerBalancerStore(hostname, key.lb_id());
+  if (per_balancer_store != nullptr) {
+    per_balancer_store->MergeRow(key, value);
+    return;
+  }
+  // Unknown LB ID. Track it until its number of in-progress calls drops to
+  // zero.
+  int64_t in_progress_delta = value.GetNumCallsInProgressDelta();
+  if (in_progress_delta != 0) {
+    auto it_tracker = unknown_balancer_id_trackers_.find(key.lb_id());
+    if (it_tracker == unknown_balancer_id_trackers_.end()) {
+      gpr_log(
+          GPR_DEBUG,
+          "[LoadDataStore %p] Start tracking unknown balancer (lb_id_: %s).",
+          this, key.lb_id().c_str());
+      unknown_balancer_id_trackers_.insert(
+          {key.lb_id(), static_cast<uint64_t>(in_progress_delta)});
+    } else if ((it_tracker->second += in_progress_delta) == 0) {
+      unknown_balancer_id_trackers_.erase(it_tracker);
+      gpr_log(GPR_DEBUG,
+              "[LoadDataStore %p] Stop tracking unknown balancer (lb_id_: %s).",
+              this, key.lb_id().c_str());
+    }
+  }
+}
+
+const std::set<PerBalancerStore*>* LoadDataStore::GetAssignedStores(
+    const grpc::string& hostname, const grpc::string& lb_id) {
+  auto it = per_host_stores_.find(hostname);
+  if (it == per_host_stores_.end()) return nullptr;
+  return it->second.GetAssignedStores(lb_id);
+}
+
+void LoadDataStore::ReportStreamCreated(const grpc::string& hostname,
+                                        const grpc::string& lb_id,
+                                        const grpc::string& load_key) {
+  per_host_stores_[hostname].ReportStreamCreated(lb_id, load_key);
+}
+
+void LoadDataStore::ReportStreamClosed(const grpc::string& hostname,
+                                       const grpc::string& lb_id) {
+  auto it_per_host_store = per_host_stores_.find(hostname);
+  GPR_ASSERT(it_per_host_store != per_host_stores_.end());
+  it_per_host_store->second.ReportStreamClosed(lb_id);
+}
+
+}  // namespace load_reporter
+}  // namespace grpc
diff --git a/src/cpp/server/load_reporter/load_data_store.h b/src/cpp/server/load_reporter/load_data_store.h
new file mode 100644
index 0000000..feb8b2f
--- /dev/null
+++ b/src/cpp/server/load_reporter/load_data_store.h
@@ -0,0 +1,339 @@
+/*
+ *
+ * Copyright 2018 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_SRC_CPP_SERVER_LOAD_REPORTER_LOAD_DATA_STORE_H
+#define GRPC_SRC_CPP_SERVER_LOAD_REPORTER_LOAD_DATA_STORE_H
+
+#include <grpc/support/port_platform.h>
+
+#include <memory>
+#include <set>
+#include <unordered_map>
+
+#include <grpc/support/log.h>
+#include <grpcpp/impl/codegen/config.h>
+
+namespace grpc {
+namespace load_reporter {
+
+constexpr char kInvalidLbId[] = "<INVALID_LBID_238dsb234890rb>";
+constexpr uint8_t kLbIdLen = 8;
+
+// The load data storage is organized in hierarchy. The LoadDataStore is the
+// top-level data store. In LoadDataStore, for each host we keep a
+// PerHostStore, in which for each balancer we keep a PerBalancerStore. Each
+// PerBalancerStore maintains a map of load records, mapping from LoadRecordKey
+// to LoadRecordValue. The LoadRecordValue contains a map of customized call
+// metrics, mapping from a call metric name to the CallMetricValue.
+
+// The value of a customized call metric.
+class CallMetricValue {
+ public:
+  explicit CallMetricValue(uint64_t num_calls = 0,
+                           double total_metric_value = 0)
+      : num_calls_(num_calls), total_metric_value_(total_metric_value) {}
+
+  void MergeFrom(CallMetricValue other) {
+    num_calls_ += other.num_calls_;
+    total_metric_value_ += other.total_metric_value_;
+  }
+
+  // Getters.
+  uint64_t num_calls() const { return num_calls_; }
+  double total_metric_value() const { return total_metric_value_; }
+
+ private:
+  // The number of calls that finished with this metric.
+  uint64_t num_calls_ = 0;
+  // The sum of metric values across all the calls that finished with this
+  // metric.
+  double total_metric_value_ = 0;
+};
+
+// The key of a load record.
+class LoadRecordKey {
+ public:
+  explicit LoadRecordKey(grpc::string lb_id, grpc::string lb_tag,
+                         grpc::string user_id, grpc::string client_ip_hex)
+      : lb_id_(std::move(lb_id)),
+        lb_tag_(std::move(lb_tag)),
+        user_id_(std::move(user_id)),
+        client_ip_hex_(std::move(client_ip_hex)) {}
+
+  grpc::string ToString() const {
+    return "[lb_id_=" + lb_id_ + ", lb_tag_=" + lb_tag_ +
+           ", user_id_=" + user_id_ + ", client_ip_hex_=" + client_ip_hex_ +
+           "]";
+  }
+
+  bool operator==(const LoadRecordKey& other) const {
+    return lb_id_ == other.lb_id_ && lb_tag_ == other.lb_tag_ &&
+           user_id_ == other.user_id_ && client_ip_hex_ == other.client_ip_hex_;
+  }
+
+  // Getters.
+  const grpc::string& lb_id() const { return lb_id_; }
+  const grpc::string& lb_tag() const { return lb_tag_; }
+  const grpc::string& user_id() const { return user_id_; }
+  const grpc::string& client_ip_hex() const { return client_ip_hex_; }
+
+  struct Hasher {
+    void hash_combine(size_t* seed, const grpc::string& k) const {
+      *seed ^= std::hash<grpc::string>()(k) + 0x9e3779b9 + (*seed << 6) +
+               (*seed >> 2);
+    }
+
+    size_t operator()(const LoadRecordKey& k) const {
+      size_t h = 0;
+      hash_combine(&h, k.lb_id_);
+      hash_combine(&h, k.lb_tag_);
+      hash_combine(&h, k.user_id_);
+      hash_combine(&h, k.client_ip_hex_);
+      return h;
+    }
+  };
+
+ private:
+  grpc::string lb_id_;
+  grpc::string lb_tag_;
+  grpc::string user_id_;
+  grpc::string client_ip_hex_;
+};
+
+// The value of a load record.
+class LoadRecordValue {
+ public:
+  explicit LoadRecordValue(uint64_t start_count = 0, uint64_t ok_count = 0,
+                           uint64_t error_count = 0, double bytes_sent = 0,
+                           double bytes_recv = 0, double latency_ms = 0)
+      : start_count_(start_count),
+        ok_count_(ok_count),
+        error_count_(error_count),
+        bytes_sent_(bytes_sent),
+        bytes_recv_(bytes_recv),
+        latency_ms_(latency_ms) {}
+
+  void MergeFrom(const LoadRecordValue& other) {
+    start_count_ += other.start_count_;
+    ok_count_ += other.ok_count_;
+    error_count_ += other.error_count_;
+    bytes_sent_ += other.bytes_sent_;
+    bytes_recv_ += other.bytes_recv_;
+    latency_ms_ += other.latency_ms_;
+    for (const auto& p : other.call_metrics_) {
+      const grpc::string& key = p.first;
+      const CallMetricValue& value = p.second;
+      call_metrics_[key].MergeFrom(value);
+    }
+  }
+
+  int64_t GetNumCallsInProgressDelta() const {
+    return static_cast<int64_t>(start_count_ - ok_count_ - error_count_);
+  }
+
+  grpc::string ToString() const {
+    return "[start_count_=" + grpc::to_string(start_count_) +
+           ", ok_count_=" + grpc::to_string(ok_count_) +
+           ", error_count_=" + grpc::to_string(error_count_) +
+           ", bytes_sent_=" + grpc::to_string(bytes_sent_) +
+           ", bytes_recv_=" + grpc::to_string(bytes_recv_) +
+           ", latency_ms_=" + grpc::to_string(latency_ms_) + "]";
+  }
+
+  bool InsertCallMetric(const grpc::string& metric_name,
+                        const CallMetricValue& metric_value) {
+    return call_metrics_.insert({metric_name, metric_value}).second;
+  }
+
+  // Getters.
+  uint64_t start_count() const { return start_count_; }
+  uint64_t ok_count() const { return ok_count_; }
+  uint64_t error_count() const { return error_count_; }
+  double bytes_sent() const { return bytes_sent_; }
+  double bytes_recv() const { return bytes_recv_; }
+  double latency_ms() const { return latency_ms_; }
+  const std::unordered_map<grpc::string, CallMetricValue>& call_metrics()
+      const {
+    return call_metrics_;
+  }
+
+ private:
+  uint64_t start_count_ = 0;
+  uint64_t ok_count_ = 0;
+  uint64_t error_count_ = 0;
+  double bytes_sent_ = 0;
+  double bytes_recv_ = 0;
+  double latency_ms_ = 0;
+  std::unordered_map<grpc::string, CallMetricValue> call_metrics_;
+};
+
+// Stores the data associated with a particular LB ID.
+class PerBalancerStore {
+ public:
+  using LoadRecordMap =
+      std::unordered_map<LoadRecordKey, LoadRecordValue, LoadRecordKey::Hasher>;
+
+  PerBalancerStore(grpc::string lb_id, grpc::string load_key)
+      : lb_id_(std::move(lb_id)), load_key_(std::move(load_key)) {}
+
+  // Merge a load record with the given key and value if the store is not
+  // suspended.
+  void MergeRow(const LoadRecordKey& key, const LoadRecordValue& value);
+
+  // Suspend this store, so that no detailed load data will be recorded.
+  void Suspend();
+  // Resume this store from suspension.
+  void Resume();
+  // Is this store suspended or not?
+  bool IsSuspended() const { return suspended_; }
+
+  bool IsNumCallsInProgressChangedSinceLastReport() const {
+    return num_calls_in_progress_ != last_reported_num_calls_in_progress_;
+  }
+
+  uint64_t GetNumCallsInProgressForReport();
+
+  grpc::string ToString() {
+    return "[PerBalancerStore lb_id_=" + lb_id_ + " load_key_=" + load_key_ +
+           "]";
+  }
+
+  void ClearLoadRecordMap() { load_record_map_.clear(); }
+
+  // Getters.
+  const grpc::string& lb_id() const { return lb_id_; }
+  const grpc::string& load_key() const { return load_key_; }
+  const LoadRecordMap& load_record_map() const { return load_record_map_; }
+
+ private:
+  grpc::string lb_id_;
+  // TODO(juanlishen): Use bytestring protobuf type?
+  grpc::string load_key_;
+  LoadRecordMap load_record_map_;
+  uint64_t num_calls_in_progress_ = 0;
+  uint64_t last_reported_num_calls_in_progress_ = 0;
+  bool suspended_ = false;
+};
+
+// Stores the data associated with a particular host.
+class PerHostStore {
+ public:
+  // When a report stream is created, a PerBalancerStore is created for the
+  // LB ID (guaranteed unique) associated with that stream. If it is the only
+  // active store, adopt all the orphaned stores. If it is the first created
+  // store, adopt the store of kInvalidLbId.
+  void ReportStreamCreated(const grpc::string& lb_id,
+                           const grpc::string& load_key);
+
+  // When a report stream is closed, the PerBalancerStores assigned to the
+  // associate LB ID need to be re-assigned to other active balancers,
+  // ideally with the same load key. If there is no active balancer, we have
+  // to suspend those stores and drop the incoming load data until they are
+  // resumed.
+  void ReportStreamClosed(const grpc::string& lb_id);
+
+  // Returns null if not found. Caller doesn't own the returned store.
+  PerBalancerStore* FindPerBalancerStore(const grpc::string& lb_id) const;
+
+  // Returns null if lb_id is not found. The returned pointer points to the
+  // underlying data structure, which is not owned by the caller.
+  const std::set<PerBalancerStore*>* GetAssignedStores(
+      const grpc::string& lb_id) const;
+
+ private:
+  // Creates a PerBalancerStore for the given LB ID, assigns the store to
+  // itself, and records the LB ID to the load key.
+  void SetUpForNewLbId(const grpc::string& lb_id, const grpc::string& load_key);
+
+  void AssignOrphanedStore(PerBalancerStore* orphaned_store,
+                           const grpc::string& new_receiver);
+
+  std::unordered_map<grpc::string, std::set<grpc::string>>
+      load_key_to_receiving_lb_ids_;
+
+  // Key: LB ID. The key set includes all the LB IDs that have been
+  // allocated for reporting streams so far.
+  // Value: the unique pointer to the PerBalancerStore of the LB ID.
+  std::unordered_map<grpc::string, std::unique_ptr<PerBalancerStore>>
+      per_balancer_stores_;
+
+  // Key: LB ID. The key set includes the LB IDs of the balancers that are
+  // currently receiving report.
+  // Value: the set of raw pointers to the PerBalancerStores assigned to the LB
+  // ID. Note that the sets in assigned_stores_ form a division of the value set
+  // of per_balancer_stores_.
+  std::unordered_map<grpc::string, std::set<PerBalancerStore*>>
+      assigned_stores_;
+};
+
+// Thread-unsafe two-level bookkeeper of all the load data.
+// Note: We never remove any store objects from this class, as per the
+// current spec. That's because premature removal of the store objects
+// may lead to loss of critical information, e.g., mapping from lb_id to
+// load_key, and the number of in-progress calls. Such loss will cause
+// information inconsistency when the balancer is re-connected. Keeping
+// all the stores should be fine for PerHostStore, since we assume there
+// should only be a few hostnames. But it's a potential problem for
+// PerBalancerStore.
+class LoadDataStore {
+ public:
+  // Returns null if not found. Caller doesn't own the returned store.
+  PerBalancerStore* FindPerBalancerStore(const grpc::string& hostname,
+                                         const grpc::string& lb_id) const;
+
+  // Returns null if hostname or lb_id is not found. The returned pointer points
+  // to the underlying data structure, which is not owned by the caller.
+  const std::set<PerBalancerStore*>* GetAssignedStores(const string& hostname,
+                                                       const string& lb_id);
+
+  // If a PerBalancerStore can be found by the hostname and LB ID in
+  // LoadRecordKey, the load data will be merged to that store. Otherwise,
+  // only track the number of the in-progress calls for this unknown LB ID.
+  void MergeRow(const grpc::string& hostname, const LoadRecordKey& key,
+                const LoadRecordValue& value);
+
+  // Is the given lb_id a tracked unknown LB ID (i.e., the LB ID was associated
+  // with some received load data but unknown to this load data store)?
+  bool IsTrackedUnknownBalancerId(const grpc::string& lb_id) const {
+    return unknown_balancer_id_trackers_.find(lb_id) !=
+           unknown_balancer_id_trackers_.end();
+  }
+
+  // Wrapper around PerHostStore::ReportStreamCreated.
+  void ReportStreamCreated(const grpc::string& hostname,
+                           const grpc::string& lb_id,
+                           const grpc::string& load_key);
+
+  // Wrapper around PerHostStore::ReportStreamClosed.
+  void ReportStreamClosed(const grpc::string& hostname,
+                          const grpc::string& lb_id);
+
+ private:
+  // Buffered data that was fetched from Census but hasn't been sent to
+  // balancer. We need to keep this data ourselves because Census will
+  // delete the data once it's returned.
+  std::unordered_map<grpc::string, PerHostStore> per_host_stores_;
+
+  // Tracks the number of in-progress calls for each unknown LB ID.
+  std::unordered_map<grpc::string, uint64_t> unknown_balancer_id_trackers_;
+};
+
+}  // namespace load_reporter
+}  // namespace grpc
+
+#endif  // GRPC_SRC_CPP_SERVER_LOAD_REPORTER_LOAD_DATA_STORE_H
diff --git a/src/cpp/server/secure_server_credentials.cc b/src/cpp/server/secure_server_credentials.cc
index 1887109..a5af257 100644
--- a/src/cpp/server/secure_server_credentials.cc
+++ b/src/cpp/server/secure_server_credentials.cc
@@ -126,4 +126,18 @@
       new SecureServerCredentials(c_creds));
 }
 
+namespace experimental {
+
+std::shared_ptr<ServerCredentials> AltsServerCredentials(
+    const AltsServerCredentialsOptions& options) {
+  grpc_alts_credentials_options* c_options =
+      grpc_alts_credentials_server_options_create();
+  grpc_server_credentials* c_creds =
+      grpc_alts_server_credentials_create(c_options);
+  grpc_alts_credentials_options_destroy(c_options);
+  return std::shared_ptr<ServerCredentials>(
+      new SecureServerCredentials(c_creds));
+}
+
+}  // namespace experimental
 }  // namespace grpc
diff --git a/src/cpp/util/byte_buffer_cc.cc b/src/cpp/util/byte_buffer_cc.cc
index fbc1768..8700f96 100644
--- a/src/cpp/util/byte_buffer_cc.cc
+++ b/src/cpp/util/byte_buffer_cc.cc
@@ -25,32 +25,6 @@
 
 static internal::GrpcLibraryInitializer g_gli_initializer;
 
-ByteBuffer::ByteBuffer(const Slice* slices, size_t nslices) {
-  // The following assertions check that the representation of a grpc::Slice is
-  // identical to that of a grpc_slice:  it has a grpc_slice field, and nothing
-  // else.
-  static_assert(std::is_same<decltype(slices[0].slice_), grpc_slice>::value,
-                "Slice must have same representation as grpc_slice");
-  static_assert(sizeof(Slice) == sizeof(grpc_slice),
-                "Slice must have same representation as grpc_slice");
-  // The following assertions check that the representation of a ByteBuffer is
-  // identical to grpc_byte_buffer*:  it has a grpc_byte_buffer* field,
-  // and nothing else.
-  static_assert(std::is_same<decltype(buffer_), grpc_byte_buffer*>::value,
-                "ByteBuffer must have same representation as "
-                "grpc_byte_buffer*");
-  static_assert(sizeof(ByteBuffer) == sizeof(grpc_byte_buffer*),
-                "ByteBuffer must have same representation as "
-                "grpc_byte_buffer*");
-  g_gli_initializer.summon();  // Make sure that initializer linked in
-  // The const_cast is legal if grpc_raw_byte_buffer_create() does no more
-  // than its advertised side effect of increasing the reference count of the
-  // slices it processes, and such an increase does not affect the semantics
-  // seen by the caller of this constructor.
-  buffer_ = grpc_raw_byte_buffer_create(
-      reinterpret_cast<grpc_slice*>(const_cast<Slice*>(slices)), nslices);
-}
-
 Status ByteBuffer::Dump(std::vector<Slice>* slices) const {
   slices->clear();
   if (!buffer_) {
@@ -69,14 +43,6 @@
   return Status::OK;
 }
 
-size_t ByteBuffer::Length() const {
-  if (buffer_) {
-    return grpc_byte_buffer_length(buffer_);
-  } else {
-    return 0;
-  }
-}
-
 ByteBuffer::ByteBuffer(const ByteBuffer& buf)
     : buffer_(grpc_byte_buffer_copy(buf.buffer_)) {}
 
@@ -90,10 +56,4 @@
   return *this;
 }
 
-void ByteBuffer::Swap(ByteBuffer* other) {
-  grpc_byte_buffer* tmp = other->buffer_;
-  other->buffer_ = buffer_;
-  buffer_ = tmp;
-}
-
 }  // namespace grpc
diff --git a/src/cpp/util/slice_cc.cc b/src/cpp/util/slice_cc.cc
deleted file mode 100644
index c72dbdb..0000000
--- a/src/cpp/util/slice_cc.cc
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- *
- * Copyright 2015 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.
- *
- */
-
-#include <grpc/slice.h>
-#include <grpcpp/support/slice.h>
-
-namespace grpc {
-
-Slice::Slice() : slice_(grpc_empty_slice()) {}
-
-Slice::~Slice() { grpc_slice_unref(slice_); }
-
-Slice::Slice(grpc_slice slice, AddRef) : slice_(grpc_slice_ref(slice)) {}
-
-Slice::Slice(grpc_slice slice, StealRef) : slice_(slice) {}
-
-Slice::Slice(size_t len) : slice_(grpc_slice_malloc(len)) {}
-
-Slice::Slice(const void* buf, size_t len)
-    : slice_(
-          grpc_slice_from_copied_buffer(static_cast<const char*>(buf), len)) {}
-
-Slice::Slice(const grpc::string& str)
-    : slice_(grpc_slice_from_copied_buffer(str.c_str(), str.length())) {}
-
-Slice::Slice(const void* buf, size_t len, StaticSlice)
-    : slice_(
-          grpc_slice_from_static_buffer(static_cast<const char*>(buf), len)) {}
-
-Slice::Slice(const Slice& other) : slice_(grpc_slice_ref(other.slice_)) {}
-
-Slice::Slice(void* buf, size_t len, void (*destroy)(void*), void* user_data)
-    : slice_(grpc_slice_new_with_user_data(buf, len, destroy, user_data)) {}
-
-Slice::Slice(void* buf, size_t len, void (*destroy)(void*, size_t))
-    : slice_(grpc_slice_new_with_len(buf, len, destroy)) {}
-
-grpc_slice Slice::c_slice() const { return grpc_slice_ref(slice_); }
-
-}  // namespace grpc
diff --git a/src/csharp/.editorconfig b/src/csharp/.editorconfig
index 7bc2bcc..fabce7f 100644
--- a/src/csharp/.editorconfig
+++ b/src/csharp/.editorconfig
@@ -1,5 +1,6 @@
 root = true
 [**]
+charset = utf-8  ; Implies no BOM.
 end_of_line = LF
 indent_style = space
 indent_size = 4
diff --git a/src/csharp/.gitignore b/src/csharp/.gitignore
index fc2875a..6fd7648 100644
--- a/src/csharp/.gitignore
+++ b/src/csharp/.gitignore
@@ -1,15 +1,17 @@
-*.xproj.user
 *.userprefs
-*.csproj.user
+*.user
 *.lock.json
+/*.suo
+/*.sdf
+/.vs/
+bin/
+obj/
+*.nupkg
 StyleCop.Cache
-test-results
-packages
-Grpc.v12.suo
-Grpc.sdf
+/packages/
+/protoc_plugins/
 
+test-results/
 TestResult.xml
 coverage_results.xml
 /TestResults
-.vs/
-*.nupkg
diff --git a/src/csharp/Grpc.Core.Testing/TestServerCallContext.cs b/src/csharp/Grpc.Core.Testing/TestServerCallContext.cs
new file mode 100644
index 0000000..5418417
--- /dev/null
+++ b/src/csharp/Grpc.Core.Testing/TestServerCallContext.cs
@@ -0,0 +1,58 @@
+#region Copyright notice and license
+
+// Copyright 2015 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.
+
+#endregion
+
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using Grpc.Core;
+
+namespace Grpc.Core.Testing
+{
+    /// <summary>
+    /// Creates test doubles for <c>ServerCallContext</c>.
+    /// </summary>
+    public static class TestServerCallContext
+    {
+        /// <summary>
+        /// Creates a test double for <c>ServerCallContext</c>. Only for testing.
+        /// Note: experimental API that can change or be removed without any prior notice.
+        /// </summary>
+        public static ServerCallContext Create(string method, string host, DateTime deadline, Metadata requestHeaders, CancellationToken cancellationToken,
+            string peer, AuthContext authContext, ContextPropagationToken contextPropagationToken,
+            Func<Metadata, Task> writeHeadersFunc, Func<WriteOptions> writeOptionsGetter, Action<WriteOptions> writeOptionsSetter)
+        {
+            return new ServerCallContext(null, method, host, deadline, requestHeaders, cancellationToken,
+                writeHeadersFunc, new WriteOptionsHolder(writeOptionsGetter, writeOptionsSetter),
+                () => peer, () => authContext, () => contextPropagationToken);
+        }
+
+        private class WriteOptionsHolder : IHasWriteOptions
+        {
+            Func<WriteOptions> writeOptionsGetter;
+            Action<WriteOptions> writeOptionsSetter;
+
+            public WriteOptionsHolder(Func<WriteOptions> writeOptionsGetter, Action<WriteOptions> writeOptionsSetter)
+            {
+                this.writeOptionsGetter = writeOptionsGetter;
+                this.writeOptionsSetter = writeOptionsSetter;
+            }
+
+            public WriteOptions WriteOptions { get => writeOptionsGetter(); set => writeOptionsSetter(value); }
+        }
+    }
+}
diff --git a/src/csharp/Grpc.Core/NativeDeps.Mac.csproj.include b/src/csharp/Grpc.Core/NativeDeps.Mac.csproj.include
index f1b85c3..309e33d 100644
--- a/src/csharp/Grpc.Core/NativeDeps.Mac.csproj.include
+++ b/src/csharp/Grpc.Core/NativeDeps.Mac.csproj.include
@@ -1,13 +1,5 @@
 <Project>
   <ItemGroup>
-    <!-- We are relying on run_tests.py to build grpc_csharp_ext with the right bitness
-    and we copy it as both x86 (needed by net45) and x64 (needed by netcoreapp1.0) as we don't
-    know which one will be needed to run the tests. -->
-    <Content Include="..\..\..\libs\$(NativeDependenciesConfigurationUnix)\libgrpc_csharp_ext.dylib">
-      <Link>libgrpc_csharp_ext.x86.dylib</Link>
-      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
-      <Pack>false</Pack>
-    </Content>
     <Content Include="..\..\..\libs\$(NativeDependenciesConfigurationUnix)\libgrpc_csharp_ext.dylib">
       <Link>libgrpc_csharp_ext.x64.dylib</Link>
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
diff --git a/src/csharp/Grpc.Core/RpcException.cs b/src/csharp/Grpc.Core/RpcException.cs
index d2c912e..94429d7 100644
--- a/src/csharp/Grpc.Core/RpcException.cs
+++ b/src/csharp/Grpc.Core/RpcException.cs
@@ -73,6 +73,17 @@
         }
 
         /// <summary>
+        /// Returns the status code of the call, as a convenient alternative to <see cref="StatusCode">Status.StatusCode</see>.
+        /// </summary>
+        public StatusCode StatusCode
+        {
+            get
+            {
+                return status.StatusCode;
+            }
+        }
+
+        /// <summary>
         /// Gets the call trailing metadata.
         /// Trailers only have meaningful content for client-side calls (in which case they represent the trailing metadata sent by the server when closing the call).
         /// Instances of <c>RpcException</c> thrown by the server-side part of the stack will have trailers always set to empty.
diff --git a/src/csharp/Grpc.Core/ServerCallContext.cs b/src/csharp/Grpc.Core/ServerCallContext.cs
index c63a4c4..74a7dea 100644
--- a/src/csharp/Grpc.Core/ServerCallContext.cs
+++ b/src/csharp/Grpc.Core/ServerCallContext.cs
@@ -36,14 +36,25 @@
         private readonly Metadata requestHeaders;
         private readonly CancellationToken cancellationToken;
         private readonly Metadata responseTrailers = new Metadata();
+        private readonly Func<Metadata, Task> writeHeadersFunc;
+        private readonly IHasWriteOptions writeOptionsHolder;
+        private readonly Lazy<AuthContext> authContext;
+        private readonly Func<string> testingOnlyPeerGetter;
+        private readonly Func<AuthContext> testingOnlyAuthContextGetter;
+        private readonly Func<ContextPropagationToken> testingOnlyContextPropagationTokenFactory;
 
         private Status status = Status.DefaultSuccess;
-        private Func<Metadata, Task> writeHeadersFunc;
-        private IHasWriteOptions writeOptionsHolder;
-        private Lazy<AuthContext> authContext;
 
         internal ServerCallContext(CallSafeHandle callHandle, string method, string host, DateTime deadline, Metadata requestHeaders, CancellationToken cancellationToken,
             Func<Metadata, Task> writeHeadersFunc, IHasWriteOptions writeOptionsHolder)
+            : this(callHandle, method, host, deadline, requestHeaders, cancellationToken, writeHeadersFunc, writeOptionsHolder, null, null, null)
+        {
+        }
+
+        // Additional constructor params should be used for testing only
+        internal ServerCallContext(CallSafeHandle callHandle, string method, string host, DateTime deadline, Metadata requestHeaders, CancellationToken cancellationToken,
+            Func<Metadata, Task> writeHeadersFunc, IHasWriteOptions writeOptionsHolder,
+            Func<string> testingOnlyPeerGetter, Func<AuthContext> testingOnlyAuthContextGetter, Func<ContextPropagationToken> testingOnlyContextPropagationTokenFactory)
         {
             this.callHandle = callHandle;
             this.method = method;
@@ -54,6 +65,9 @@
             this.writeHeadersFunc = writeHeadersFunc;
             this.writeOptionsHolder = writeOptionsHolder;
             this.authContext = new Lazy<AuthContext>(GetAuthContextEager);
+            this.testingOnlyPeerGetter = testingOnlyPeerGetter;
+            this.testingOnlyAuthContextGetter = testingOnlyAuthContextGetter;
+            this.testingOnlyContextPropagationTokenFactory = testingOnlyContextPropagationTokenFactory;
         }
 
         /// <summary>
@@ -73,6 +87,10 @@
         /// </summary>
         public ContextPropagationToken CreatePropagationToken(ContextPropagationOptions options = null)
         {
+            if (testingOnlyContextPropagationTokenFactory != null)
+            {
+                return testingOnlyContextPropagationTokenFactory();
+            }
             return new ContextPropagationToken(callHandle, deadline, cancellationToken, options);
         }
             
@@ -99,6 +117,10 @@
         {
             get
             {
+                if (testingOnlyPeerGetter != null)
+                {
+                    return testingOnlyPeerGetter();
+                }
                 // Getting the peer lazily is fine as the native call is guaranteed
                 // not to be disposed before user-supplied server side handler returns.
                 // Most users won't need to read this field anyway.
@@ -182,6 +204,10 @@
         {
             get
             {
+                if (testingOnlyAuthContextGetter != null)
+                {
+                    return testingOnlyAuthContextGetter();
+                }
                 return authContext.Value;
             }
         }
@@ -198,7 +224,7 @@
     /// <summary>
     /// Allows sharing write options between ServerCallContext and other objects.
     /// </summary>
-    public interface IHasWriteOptions
+    internal interface IHasWriteOptions
     {
         /// <summary>
         /// Gets or sets the write options.
diff --git a/src/csharp/Grpc.Core/Version.csproj.include b/src/csharp/Grpc.Core/Version.csproj.include
index 9b55f24..f5d63b7 100755
--- a/src/csharp/Grpc.Core/Version.csproj.include
+++ b/src/csharp/Grpc.Core/Version.csproj.include
@@ -1,7 +1,7 @@
 <!-- This file is generated -->
 <Project>
   <PropertyGroup>
-    <GrpcCsharpVersion>1.11.0-dev</GrpcCsharpVersion>
-    <GoogleProtobufVersion>3.3.0</GoogleProtobufVersion>
+    <GrpcCsharpVersion>1.13.0-dev</GrpcCsharpVersion>
+    <GoogleProtobufVersion>3.5.1</GoogleProtobufVersion>
   </PropertyGroup>
 </Project>
diff --git a/src/csharp/Grpc.Core/VersionInfo.cs b/src/csharp/Grpc.Core/VersionInfo.cs
index 2902aee..87eddda 100644
--- a/src/csharp/Grpc.Core/VersionInfo.cs
+++ b/src/csharp/Grpc.Core/VersionInfo.cs
@@ -33,11 +33,11 @@
         /// <summary>
         /// Current <c>AssemblyFileVersion</c> of gRPC C# assemblies
         /// </summary>
-        public const string CurrentAssemblyFileVersion = "1.11.0.0";
+        public const string CurrentAssemblyFileVersion = "1.13.0.0";
 
         /// <summary>
         /// Current version of gRPC C#
         /// </summary>
-        public const string CurrentVersion = "1.11.0-dev";
+        public const string CurrentVersion = "1.13.0-dev";
     }
 }
diff --git a/src/csharp/Grpc.Examples/Math.cs b/src/csharp/Grpc.Examples/Math.cs
index e5b76f8..4c3879f 100644
--- a/src/csharp/Grpc.Examples/Math.cs
+++ b/src/csharp/Grpc.Examples/Math.cs
@@ -1,5 +1,7 @@
-// Generated by the protocol buffer compiler.  DO NOT EDIT!
-// source: math/math.proto
+// <auto-generated>
+//     Generated by the protocol buffer compiler.  DO NOT EDIT!
+//     source: math/math.proto
+// </auto-generated>
 #pragma warning disable 1591, 0612, 3021
 #region Designer generated code
 
@@ -47,6 +49,7 @@
   #region Messages
   public sealed partial class DivArgs : pb::IMessage<DivArgs> {
     private static readonly pb::MessageParser<DivArgs> _parser = new pb::MessageParser<DivArgs>(() => new DivArgs());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<DivArgs> Parser { get { return _parser; } }
 
@@ -71,6 +74,7 @@
     public DivArgs(DivArgs other) : this() {
       dividend_ = other.dividend_;
       divisor_ = other.divisor_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -115,7 +119,7 @@
       }
       if (Dividend != other.Dividend) return false;
       if (Divisor != other.Divisor) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -123,6 +127,9 @@
       int hash = 1;
       if (Dividend != 0L) hash ^= Dividend.GetHashCode();
       if (Divisor != 0L) hash ^= Divisor.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -141,6 +148,9 @@
         output.WriteRawTag(16);
         output.WriteInt64(Divisor);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -152,6 +162,9 @@
       if (Divisor != 0L) {
         size += 1 + pb::CodedOutputStream.ComputeInt64Size(Divisor);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -166,6 +179,7 @@
       if (other.Divisor != 0L) {
         Divisor = other.Divisor;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -174,7 +188,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 8: {
             Dividend = input.ReadInt64();
@@ -192,6 +206,7 @@
 
   public sealed partial class DivReply : pb::IMessage<DivReply> {
     private static readonly pb::MessageParser<DivReply> _parser = new pb::MessageParser<DivReply>(() => new DivReply());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<DivReply> Parser { get { return _parser; } }
 
@@ -216,6 +231,7 @@
     public DivReply(DivReply other) : this() {
       quotient_ = other.quotient_;
       remainder_ = other.remainder_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -260,7 +276,7 @@
       }
       if (Quotient != other.Quotient) return false;
       if (Remainder != other.Remainder) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -268,6 +284,9 @@
       int hash = 1;
       if (Quotient != 0L) hash ^= Quotient.GetHashCode();
       if (Remainder != 0L) hash ^= Remainder.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -286,6 +305,9 @@
         output.WriteRawTag(16);
         output.WriteInt64(Remainder);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -297,6 +319,9 @@
       if (Remainder != 0L) {
         size += 1 + pb::CodedOutputStream.ComputeInt64Size(Remainder);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -311,6 +336,7 @@
       if (other.Remainder != 0L) {
         Remainder = other.Remainder;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -319,7 +345,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 8: {
             Quotient = input.ReadInt64();
@@ -337,6 +363,7 @@
 
   public sealed partial class FibArgs : pb::IMessage<FibArgs> {
     private static readonly pb::MessageParser<FibArgs> _parser = new pb::MessageParser<FibArgs>(() => new FibArgs());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<FibArgs> Parser { get { return _parser; } }
 
@@ -360,6 +387,7 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public FibArgs(FibArgs other) : this() {
       limit_ = other.limit_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -392,13 +420,16 @@
         return true;
       }
       if (Limit != other.Limit) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
       if (Limit != 0L) hash ^= Limit.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -413,6 +444,9 @@
         output.WriteRawTag(8);
         output.WriteInt64(Limit);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -421,6 +455,9 @@
       if (Limit != 0L) {
         size += 1 + pb::CodedOutputStream.ComputeInt64Size(Limit);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -432,6 +469,7 @@
       if (other.Limit != 0L) {
         Limit = other.Limit;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -440,7 +478,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 8: {
             Limit = input.ReadInt64();
@@ -454,6 +492,7 @@
 
   public sealed partial class Num : pb::IMessage<Num> {
     private static readonly pb::MessageParser<Num> _parser = new pb::MessageParser<Num>(() => new Num());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<Num> Parser { get { return _parser; } }
 
@@ -477,6 +516,7 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public Num(Num other) : this() {
       num_ = other.num_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -509,13 +549,16 @@
         return true;
       }
       if (Num_ != other.Num_) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
       if (Num_ != 0L) hash ^= Num_.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -530,6 +573,9 @@
         output.WriteRawTag(8);
         output.WriteInt64(Num_);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -538,6 +584,9 @@
       if (Num_ != 0L) {
         size += 1 + pb::CodedOutputStream.ComputeInt64Size(Num_);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -549,6 +598,7 @@
       if (other.Num_ != 0L) {
         Num_ = other.Num_;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -557,7 +607,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 8: {
             Num_ = input.ReadInt64();
@@ -571,6 +621,7 @@
 
   public sealed partial class FibReply : pb::IMessage<FibReply> {
     private static readonly pb::MessageParser<FibReply> _parser = new pb::MessageParser<FibReply>(() => new FibReply());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<FibReply> Parser { get { return _parser; } }
 
@@ -594,6 +645,7 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public FibReply(FibReply other) : this() {
       count_ = other.count_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -626,13 +678,16 @@
         return true;
       }
       if (Count != other.Count) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
       if (Count != 0L) hash ^= Count.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -647,6 +702,9 @@
         output.WriteRawTag(8);
         output.WriteInt64(Count);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -655,6 +713,9 @@
       if (Count != 0L) {
         size += 1 + pb::CodedOutputStream.ComputeInt64Size(Count);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -666,6 +727,7 @@
       if (other.Count != 0L) {
         Count = other.Count;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -674,7 +736,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 8: {
             Count = input.ReadInt64();
diff --git a/src/csharp/Grpc.HealthCheck/Health.cs b/src/csharp/Grpc.HealthCheck/Health.cs
index b9880d9..a90f261 100644
--- a/src/csharp/Grpc.HealthCheck/Health.cs
+++ b/src/csharp/Grpc.HealthCheck/Health.cs
@@ -1,5 +1,7 @@
-// Generated by the protocol buffer compiler.  DO NOT EDIT!
-// source: grpc/health/v1/health.proto
+// <auto-generated>
+//     Generated by the protocol buffer compiler.  DO NOT EDIT!
+//     source: grpc/health/v1/health.proto
+// </auto-generated>
 #pragma warning disable 1591, 0612, 3021
 #region Designer generated code
 
@@ -29,7 +31,9 @@
             "ZXJ2aW5nU3RhdHVzEgsKB1VOS05PV04QABILCgdTRVJWSU5HEAESDwoLTk9U",
             "X1NFUlZJTkcQAjJaCgZIZWFsdGgSUAoFQ2hlY2sSIi5ncnBjLmhlYWx0aC52",
             "MS5IZWFsdGhDaGVja1JlcXVlc3QaIy5ncnBjLmhlYWx0aC52MS5IZWFsdGhD",
-            "aGVja1Jlc3BvbnNlQhGqAg5HcnBjLkhlYWx0aC5WMWIGcHJvdG8z"));
+            "aGVja1Jlc3BvbnNlQmEKEWlvLmdycGMuaGVhbHRoLnYxQgtIZWFsdGhQcm90",
+            "b1ABWixnb29nbGUuZ29sYW5nLm9yZy9ncnBjL2hlYWx0aC9ncnBjX2hlYWx0",
+            "aF92MaoCDkdycGMuSGVhbHRoLlYxYgZwcm90bzM="));
       descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
           new pbr::FileDescriptor[] { },
           new pbr::GeneratedClrTypeInfo(null, new pbr::GeneratedClrTypeInfo[] {
@@ -43,6 +47,7 @@
   #region Messages
   public sealed partial class HealthCheckRequest : pb::IMessage<HealthCheckRequest> {
     private static readonly pb::MessageParser<HealthCheckRequest> _parser = new pb::MessageParser<HealthCheckRequest>(() => new HealthCheckRequest());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<HealthCheckRequest> Parser { get { return _parser; } }
 
@@ -66,6 +71,7 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public HealthCheckRequest(HealthCheckRequest other) : this() {
       service_ = other.service_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -98,13 +104,16 @@
         return true;
       }
       if (Service != other.Service) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
       if (Service.Length != 0) hash ^= Service.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -119,6 +128,9 @@
         output.WriteRawTag(10);
         output.WriteString(Service);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -127,6 +139,9 @@
       if (Service.Length != 0) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(Service);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -138,6 +153,7 @@
       if (other.Service.Length != 0) {
         Service = other.Service;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -146,7 +162,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             Service = input.ReadString();
@@ -160,6 +176,7 @@
 
   public sealed partial class HealthCheckResponse : pb::IMessage<HealthCheckResponse> {
     private static readonly pb::MessageParser<HealthCheckResponse> _parser = new pb::MessageParser<HealthCheckResponse>(() => new HealthCheckResponse());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<HealthCheckResponse> Parser { get { return _parser; } }
 
@@ -183,6 +200,7 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public HealthCheckResponse(HealthCheckResponse other) : this() {
       status_ = other.status_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -215,13 +233,16 @@
         return true;
       }
       if (Status != other.Status) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
       if (Status != 0) hash ^= Status.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -236,6 +257,9 @@
         output.WriteRawTag(8);
         output.WriteEnum((int) Status);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -244,6 +268,9 @@
       if (Status != 0) {
         size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Status);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -255,6 +282,7 @@
       if (other.Status != 0) {
         Status = other.Status;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -263,7 +291,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 8: {
             status_ = (global::Grpc.Health.V1.HealthCheckResponse.Types.ServingStatus) input.ReadEnum();
diff --git a/src/csharp/Grpc.HealthCheck/HealthGrpc.cs b/src/csharp/Grpc.HealthCheck/HealthGrpc.cs
index 1d80bcd..a26f483 100644
--- a/src/csharp/Grpc.HealthCheck/HealthGrpc.cs
+++ b/src/csharp/Grpc.HealthCheck/HealthGrpc.cs
@@ -3,7 +3,7 @@
 //     source: grpc/health/v1/health.proto
 // </auto-generated>
 // Original file comments:
-// Copyright 2015 gRPC authors.
+// Copyright 2015 The gRPC Authors
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -17,6 +17,9 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 //
+// The canonical version of this proto can be found at
+// https://github.com/grpc/grpc-proto/blob/master/grpc/health/v1/health.proto
+//
 #pragma warning disable 1591
 #region Designer generated code
 
diff --git a/src/csharp/Grpc.IntegrationTesting/BenchmarkService.cs b/src/csharp/Grpc.IntegrationTesting/BenchmarkService.cs
new file mode 100644
index 0000000..bc8c103
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/BenchmarkService.cs
@@ -0,0 +1,48 @@
+// <auto-generated>
+//     Generated by the protocol buffer compiler.  DO NOT EDIT!
+//     source: src/proto/grpc/testing/benchmark_service.proto
+// </auto-generated>
+#pragma warning disable 1591, 0612, 3021
+#region Designer generated code
+
+using pb = global::Google.Protobuf;
+using pbc = global::Google.Protobuf.Collections;
+using pbr = global::Google.Protobuf.Reflection;
+using scg = global::System.Collections.Generic;
+namespace Grpc.Testing {
+
+  /// <summary>Holder for reflection information generated from src/proto/grpc/testing/benchmark_service.proto</summary>
+  public static partial class BenchmarkServiceReflection {
+
+    #region Descriptor
+    /// <summary>File descriptor for src/proto/grpc/testing/benchmark_service.proto</summary>
+    public static pbr::FileDescriptor Descriptor {
+      get { return descriptor; }
+    }
+    private static pbr::FileDescriptor descriptor;
+
+    static BenchmarkServiceReflection() {
+      byte[] descriptorData = global::System.Convert.FromBase64String(
+          string.Concat(
+            "Ci5zcmMvcHJvdG8vZ3JwYy90ZXN0aW5nL2JlbmNobWFya19zZXJ2aWNlLnBy",
+            "b3RvEgxncnBjLnRlc3RpbmcaJXNyYy9wcm90by9ncnBjL3Rlc3RpbmcvbWVz",
+            "c2FnZXMucHJvdG8ypgMKEEJlbmNobWFya1NlcnZpY2USRgoJVW5hcnlDYWxs",
+            "EhsuZ3JwYy50ZXN0aW5nLlNpbXBsZVJlcXVlc3QaHC5ncnBjLnRlc3Rpbmcu",
+            "U2ltcGxlUmVzcG9uc2USTgoNU3RyZWFtaW5nQ2FsbBIbLmdycGMudGVzdGlu",
+            "Zy5TaW1wbGVSZXF1ZXN0GhwuZ3JwYy50ZXN0aW5nLlNpbXBsZVJlc3BvbnNl",
+            "KAEwARJSChNTdHJlYW1pbmdGcm9tQ2xpZW50EhsuZ3JwYy50ZXN0aW5nLlNp",
+            "bXBsZVJlcXVlc3QaHC5ncnBjLnRlc3RpbmcuU2ltcGxlUmVzcG9uc2UoARJS",
+            "ChNTdHJlYW1pbmdGcm9tU2VydmVyEhsuZ3JwYy50ZXN0aW5nLlNpbXBsZVJl",
+            "cXVlc3QaHC5ncnBjLnRlc3RpbmcuU2ltcGxlUmVzcG9uc2UwARJSChFTdHJl",
+            "YW1pbmdCb3RoV2F5cxIbLmdycGMudGVzdGluZy5TaW1wbGVSZXF1ZXN0Ghwu",
+            "Z3JwYy50ZXN0aW5nLlNpbXBsZVJlc3BvbnNlKAEwAWIGcHJvdG8z"));
+      descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
+          new pbr::FileDescriptor[] { global::Grpc.Testing.MessagesReflection.Descriptor, },
+          new pbr::GeneratedClrTypeInfo(null, null));
+    }
+    #endregion
+
+  }
+}
+
+#endregion Designer generated code
diff --git a/src/csharp/Grpc.IntegrationTesting/BenchmarkServiceGrpc.cs b/src/csharp/Grpc.IntegrationTesting/BenchmarkServiceGrpc.cs
new file mode 100644
index 0000000..20b933f
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/BenchmarkServiceGrpc.cs
@@ -0,0 +1,329 @@
+// <auto-generated>
+//     Generated by the protocol buffer compiler.  DO NOT EDIT!
+//     source: src/proto/grpc/testing/benchmark_service.proto
+// </auto-generated>
+// Original file comments:
+// Copyright 2015 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.
+//
+// An integration test service that covers all the method signature permutations
+// of unary/streaming requests/responses.
+#pragma warning disable 1591
+#region Designer generated code
+
+using grpc = global::Grpc.Core;
+
+namespace Grpc.Testing {
+  public static partial class BenchmarkService
+  {
+    static readonly string __ServiceName = "grpc.testing.BenchmarkService";
+
+    static readonly grpc::Marshaller<global::Grpc.Testing.SimpleRequest> __Marshaller_SimpleRequest = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.SimpleRequest.Parser.ParseFrom);
+    static readonly grpc::Marshaller<global::Grpc.Testing.SimpleResponse> __Marshaller_SimpleResponse = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.SimpleResponse.Parser.ParseFrom);
+
+    static readonly grpc::Method<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> __Method_UnaryCall = new grpc::Method<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse>(
+        grpc::MethodType.Unary,
+        __ServiceName,
+        "UnaryCall",
+        __Marshaller_SimpleRequest,
+        __Marshaller_SimpleResponse);
+
+    static readonly grpc::Method<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> __Method_StreamingCall = new grpc::Method<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse>(
+        grpc::MethodType.DuplexStreaming,
+        __ServiceName,
+        "StreamingCall",
+        __Marshaller_SimpleRequest,
+        __Marshaller_SimpleResponse);
+
+    static readonly grpc::Method<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> __Method_StreamingFromClient = new grpc::Method<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse>(
+        grpc::MethodType.ClientStreaming,
+        __ServiceName,
+        "StreamingFromClient",
+        __Marshaller_SimpleRequest,
+        __Marshaller_SimpleResponse);
+
+    static readonly grpc::Method<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> __Method_StreamingFromServer = new grpc::Method<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse>(
+        grpc::MethodType.ServerStreaming,
+        __ServiceName,
+        "StreamingFromServer",
+        __Marshaller_SimpleRequest,
+        __Marshaller_SimpleResponse);
+
+    static readonly grpc::Method<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> __Method_StreamingBothWays = new grpc::Method<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse>(
+        grpc::MethodType.DuplexStreaming,
+        __ServiceName,
+        "StreamingBothWays",
+        __Marshaller_SimpleRequest,
+        __Marshaller_SimpleResponse);
+
+    /// <summary>Service descriptor</summary>
+    public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
+    {
+      get { return global::Grpc.Testing.BenchmarkServiceReflection.Descriptor.Services[0]; }
+    }
+
+    /// <summary>Base class for server-side implementations of BenchmarkService</summary>
+    public abstract partial class BenchmarkServiceBase
+    {
+      /// <summary>
+      /// One request followed by one response.
+      /// The server returns the client payload as-is.
+      /// </summary>
+      /// <param name="request">The request received from the client.</param>
+      /// <param name="context">The context of the server-side call handler being invoked.</param>
+      /// <returns>The response to send back to the client (wrapped by a task).</returns>
+      public virtual global::System.Threading.Tasks.Task<global::Grpc.Testing.SimpleResponse> UnaryCall(global::Grpc.Testing.SimpleRequest request, grpc::ServerCallContext context)
+      {
+        throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
+      }
+
+      /// <summary>
+      /// Repeated sequence of one request followed by one response.
+      /// Should be called streaming ping-pong
+      /// The server returns the client payload as-is on each response
+      /// </summary>
+      /// <param name="requestStream">Used for reading requests from the client.</param>
+      /// <param name="responseStream">Used for sending responses back to the client.</param>
+      /// <param name="context">The context of the server-side call handler being invoked.</param>
+      /// <returns>A task indicating completion of the handler.</returns>
+      public virtual global::System.Threading.Tasks.Task StreamingCall(grpc::IAsyncStreamReader<global::Grpc.Testing.SimpleRequest> requestStream, grpc::IServerStreamWriter<global::Grpc.Testing.SimpleResponse> responseStream, grpc::ServerCallContext context)
+      {
+        throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
+      }
+
+      /// <summary>
+      /// Single-sided unbounded streaming from client to server
+      /// The server returns the client payload as-is once the client does WritesDone
+      /// </summary>
+      /// <param name="requestStream">Used for reading requests from the client.</param>
+      /// <param name="context">The context of the server-side call handler being invoked.</param>
+      /// <returns>The response to send back to the client (wrapped by a task).</returns>
+      public virtual global::System.Threading.Tasks.Task<global::Grpc.Testing.SimpleResponse> StreamingFromClient(grpc::IAsyncStreamReader<global::Grpc.Testing.SimpleRequest> requestStream, grpc::ServerCallContext context)
+      {
+        throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
+      }
+
+      /// <summary>
+      /// Single-sided unbounded streaming from server to client
+      /// The server repeatedly returns the client payload as-is
+      /// </summary>
+      /// <param name="request">The request received from the client.</param>
+      /// <param name="responseStream">Used for sending responses back to the client.</param>
+      /// <param name="context">The context of the server-side call handler being invoked.</param>
+      /// <returns>A task indicating completion of the handler.</returns>
+      public virtual global::System.Threading.Tasks.Task StreamingFromServer(global::Grpc.Testing.SimpleRequest request, grpc::IServerStreamWriter<global::Grpc.Testing.SimpleResponse> responseStream, grpc::ServerCallContext context)
+      {
+        throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
+      }
+
+      /// <summary>
+      /// Two-sided unbounded streaming between server to client
+      /// Both sides send the content of their own choice to the other
+      /// </summary>
+      /// <param name="requestStream">Used for reading requests from the client.</param>
+      /// <param name="responseStream">Used for sending responses back to the client.</param>
+      /// <param name="context">The context of the server-side call handler being invoked.</param>
+      /// <returns>A task indicating completion of the handler.</returns>
+      public virtual global::System.Threading.Tasks.Task StreamingBothWays(grpc::IAsyncStreamReader<global::Grpc.Testing.SimpleRequest> requestStream, grpc::IServerStreamWriter<global::Grpc.Testing.SimpleResponse> responseStream, grpc::ServerCallContext context)
+      {
+        throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
+      }
+
+    }
+
+    /// <summary>Client for BenchmarkService</summary>
+    public partial class BenchmarkServiceClient : grpc::ClientBase<BenchmarkServiceClient>
+    {
+      /// <summary>Creates a new client for BenchmarkService</summary>
+      /// <param name="channel">The channel to use to make remote calls.</param>
+      public BenchmarkServiceClient(grpc::Channel channel) : base(channel)
+      {
+      }
+      /// <summary>Creates a new client for BenchmarkService that uses a custom <c>CallInvoker</c>.</summary>
+      /// <param name="callInvoker">The callInvoker to use to make remote calls.</param>
+      public BenchmarkServiceClient(grpc::CallInvoker callInvoker) : base(callInvoker)
+      {
+      }
+      /// <summary>Protected parameterless constructor to allow creation of test doubles.</summary>
+      protected BenchmarkServiceClient() : base()
+      {
+      }
+      /// <summary>Protected constructor to allow creation of configured clients.</summary>
+      /// <param name="configuration">The client configuration.</param>
+      protected BenchmarkServiceClient(ClientBaseConfiguration configuration) : base(configuration)
+      {
+      }
+
+      /// <summary>
+      /// One request followed by one response.
+      /// The server returns the client payload as-is.
+      /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
+      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
+      /// <param name="cancellationToken">An optional token for canceling the call.</param>
+      /// <returns>The response received from the server.</returns>
+      public virtual global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
+      {
+        return UnaryCall(request, new grpc::CallOptions(headers, deadline, cancellationToken));
+      }
+      /// <summary>
+      /// One request followed by one response.
+      /// The server returns the client payload as-is.
+      /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="options">The options for the call.</param>
+      /// <returns>The response received from the server.</returns>
+      public virtual global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, grpc::CallOptions options)
+      {
+        return CallInvoker.BlockingUnaryCall(__Method_UnaryCall, null, options, request);
+      }
+      /// <summary>
+      /// One request followed by one response.
+      /// The server returns the client payload as-is.
+      /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
+      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
+      /// <param name="cancellationToken">An optional token for canceling the call.</param>
+      /// <returns>The call object.</returns>
+      public virtual grpc::AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
+      {
+        return UnaryCallAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken));
+      }
+      /// <summary>
+      /// One request followed by one response.
+      /// The server returns the client payload as-is.
+      /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="options">The options for the call.</param>
+      /// <returns>The call object.</returns>
+      public virtual grpc::AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, grpc::CallOptions options)
+      {
+        return CallInvoker.AsyncUnaryCall(__Method_UnaryCall, null, options, request);
+      }
+      /// <summary>
+      /// Repeated sequence of one request followed by one response.
+      /// Should be called streaming ping-pong
+      /// The server returns the client payload as-is on each response
+      /// </summary>
+      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
+      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
+      /// <param name="cancellationToken">An optional token for canceling the call.</param>
+      /// <returns>The call object.</returns>
+      public virtual grpc::AsyncDuplexStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingCall(grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
+      {
+        return StreamingCall(new grpc::CallOptions(headers, deadline, cancellationToken));
+      }
+      /// <summary>
+      /// Repeated sequence of one request followed by one response.
+      /// Should be called streaming ping-pong
+      /// The server returns the client payload as-is on each response
+      /// </summary>
+      /// <param name="options">The options for the call.</param>
+      /// <returns>The call object.</returns>
+      public virtual grpc::AsyncDuplexStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingCall(grpc::CallOptions options)
+      {
+        return CallInvoker.AsyncDuplexStreamingCall(__Method_StreamingCall, null, options);
+      }
+      /// <summary>
+      /// Single-sided unbounded streaming from client to server
+      /// The server returns the client payload as-is once the client does WritesDone
+      /// </summary>
+      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
+      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
+      /// <param name="cancellationToken">An optional token for canceling the call.</param>
+      /// <returns>The call object.</returns>
+      public virtual grpc::AsyncClientStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingFromClient(grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
+      {
+        return StreamingFromClient(new grpc::CallOptions(headers, deadline, cancellationToken));
+      }
+      /// <summary>
+      /// Single-sided unbounded streaming from client to server
+      /// The server returns the client payload as-is once the client does WritesDone
+      /// </summary>
+      /// <param name="options">The options for the call.</param>
+      /// <returns>The call object.</returns>
+      public virtual grpc::AsyncClientStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingFromClient(grpc::CallOptions options)
+      {
+        return CallInvoker.AsyncClientStreamingCall(__Method_StreamingFromClient, null, options);
+      }
+      /// <summary>
+      /// Single-sided unbounded streaming from server to client
+      /// The server repeatedly returns the client payload as-is
+      /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
+      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
+      /// <param name="cancellationToken">An optional token for canceling the call.</param>
+      /// <returns>The call object.</returns>
+      public virtual grpc::AsyncServerStreamingCall<global::Grpc.Testing.SimpleResponse> StreamingFromServer(global::Grpc.Testing.SimpleRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
+      {
+        return StreamingFromServer(request, new grpc::CallOptions(headers, deadline, cancellationToken));
+      }
+      /// <summary>
+      /// Single-sided unbounded streaming from server to client
+      /// The server repeatedly returns the client payload as-is
+      /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="options">The options for the call.</param>
+      /// <returns>The call object.</returns>
+      public virtual grpc::AsyncServerStreamingCall<global::Grpc.Testing.SimpleResponse> StreamingFromServer(global::Grpc.Testing.SimpleRequest request, grpc::CallOptions options)
+      {
+        return CallInvoker.AsyncServerStreamingCall(__Method_StreamingFromServer, null, options, request);
+      }
+      /// <summary>
+      /// Two-sided unbounded streaming between server to client
+      /// Both sides send the content of their own choice to the other
+      /// </summary>
+      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
+      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
+      /// <param name="cancellationToken">An optional token for canceling the call.</param>
+      /// <returns>The call object.</returns>
+      public virtual grpc::AsyncDuplexStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingBothWays(grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
+      {
+        return StreamingBothWays(new grpc::CallOptions(headers, deadline, cancellationToken));
+      }
+      /// <summary>
+      /// Two-sided unbounded streaming between server to client
+      /// Both sides send the content of their own choice to the other
+      /// </summary>
+      /// <param name="options">The options for the call.</param>
+      /// <returns>The call object.</returns>
+      public virtual grpc::AsyncDuplexStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingBothWays(grpc::CallOptions options)
+      {
+        return CallInvoker.AsyncDuplexStreamingCall(__Method_StreamingBothWays, null, options);
+      }
+      /// <summary>Creates a new instance of client from given <c>ClientBaseConfiguration</c>.</summary>
+      protected override BenchmarkServiceClient NewInstance(ClientBaseConfiguration configuration)
+      {
+        return new BenchmarkServiceClient(configuration);
+      }
+    }
+
+    /// <summary>Creates service definition that can be registered with a server</summary>
+    /// <param name="serviceImpl">An object implementing the server-side handling logic.</param>
+    public static grpc::ServerServiceDefinition BindService(BenchmarkServiceBase serviceImpl)
+    {
+      return grpc::ServerServiceDefinition.CreateBuilder()
+          .AddMethod(__Method_UnaryCall, serviceImpl.UnaryCall)
+          .AddMethod(__Method_StreamingCall, serviceImpl.StreamingCall)
+          .AddMethod(__Method_StreamingFromClient, serviceImpl.StreamingFromClient)
+          .AddMethod(__Method_StreamingFromServer, serviceImpl.StreamingFromServer)
+          .AddMethod(__Method_StreamingBothWays, serviceImpl.StreamingBothWays).Build();
+    }
+
+  }
+}
+#endregion
diff --git a/src/csharp/Grpc.IntegrationTesting/Control.cs b/src/csharp/Grpc.IntegrationTesting/Control.cs
index 8795728..f3284a5 100644
--- a/src/csharp/Grpc.IntegrationTesting/Control.cs
+++ b/src/csharp/Grpc.IntegrationTesting/Control.cs
@@ -1,5 +1,7 @@
-// Generated by the protocol buffer compiler.  DO NOT EDIT!
-// source: src/proto/grpc/testing/control.proto
+// <auto-generated>
+//     Generated by the protocol buffer compiler.  DO NOT EDIT!
+//     source: src/proto/grpc/testing/control.proto
+// </auto-generated>
 #pragma warning disable 1591, 0612, 3021
 #region Designer generated code
 
@@ -167,6 +169,7 @@
   /// </summary>
   public sealed partial class PoissonParams : pb::IMessage<PoissonParams> {
     private static readonly pb::MessageParser<PoissonParams> _parser = new pb::MessageParser<PoissonParams>(() => new PoissonParams());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<PoissonParams> Parser { get { return _parser; } }
 
@@ -190,6 +193,7 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public PoissonParams(PoissonParams other) : this() {
       offeredLoad_ = other.offeredLoad_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -224,14 +228,17 @@
       if (ReferenceEquals(other, this)) {
         return true;
       }
-      if (OfferedLoad != other.OfferedLoad) return false;
-      return true;
+      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(OfferedLoad, other.OfferedLoad)) return false;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
-      if (OfferedLoad != 0D) hash ^= OfferedLoad.GetHashCode();
+      if (OfferedLoad != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(OfferedLoad);
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -246,6 +253,9 @@
         output.WriteRawTag(9);
         output.WriteDouble(OfferedLoad);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -254,6 +264,9 @@
       if (OfferedLoad != 0D) {
         size += 1 + 8;
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -265,6 +278,7 @@
       if (other.OfferedLoad != 0D) {
         OfferedLoad = other.OfferedLoad;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -273,7 +287,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 9: {
             OfferedLoad = input.ReadDouble();
@@ -291,6 +305,7 @@
   /// </summary>
   public sealed partial class ClosedLoopParams : pb::IMessage<ClosedLoopParams> {
     private static readonly pb::MessageParser<ClosedLoopParams> _parser = new pb::MessageParser<ClosedLoopParams>(() => new ClosedLoopParams());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<ClosedLoopParams> Parser { get { return _parser; } }
 
@@ -313,6 +328,7 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public ClosedLoopParams(ClosedLoopParams other) : this() {
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -333,12 +349,15 @@
       if (ReferenceEquals(other, this)) {
         return true;
       }
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -349,11 +368,17 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public void WriteTo(pb::CodedOutputStream output) {
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public int CalculateSize() {
       int size = 0;
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -362,6 +387,7 @@
       if (other == null) {
         return;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -370,7 +396,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
         }
       }
@@ -380,6 +406,7 @@
 
   public sealed partial class LoadParams : pb::IMessage<LoadParams> {
     private static readonly pb::MessageParser<LoadParams> _parser = new pb::MessageParser<LoadParams>(() => new LoadParams());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<LoadParams> Parser { get { return _parser; } }
 
@@ -411,6 +438,7 @@
           break;
       }
 
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -475,7 +503,7 @@
       if (!object.Equals(ClosedLoop, other.ClosedLoop)) return false;
       if (!object.Equals(Poisson, other.Poisson)) return false;
       if (LoadCase != other.LoadCase) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -484,6 +512,9 @@
       if (loadCase_ == LoadOneofCase.ClosedLoop) hash ^= ClosedLoop.GetHashCode();
       if (loadCase_ == LoadOneofCase.Poisson) hash ^= Poisson.GetHashCode();
       hash ^= (int) loadCase_;
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -502,6 +533,9 @@
         output.WriteRawTag(18);
         output.WriteMessage(Poisson);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -513,6 +547,9 @@
       if (loadCase_ == LoadOneofCase.Poisson) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(Poisson);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -536,6 +573,7 @@
           break;
       }
 
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -544,7 +582,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             global::Grpc.Testing.ClosedLoopParams subBuilder = new global::Grpc.Testing.ClosedLoopParams();
@@ -575,6 +613,7 @@
   /// </summary>
   public sealed partial class SecurityParams : pb::IMessage<SecurityParams> {
     private static readonly pb::MessageParser<SecurityParams> _parser = new pb::MessageParser<SecurityParams>(() => new SecurityParams());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<SecurityParams> Parser { get { return _parser; } }
 
@@ -600,6 +639,7 @@
       useTestCa_ = other.useTestCa_;
       serverHostOverride_ = other.serverHostOverride_;
       credType_ = other.credType_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -656,7 +696,7 @@
       if (UseTestCa != other.UseTestCa) return false;
       if (ServerHostOverride != other.ServerHostOverride) return false;
       if (CredType != other.CredType) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -665,6 +705,9 @@
       if (UseTestCa != false) hash ^= UseTestCa.GetHashCode();
       if (ServerHostOverride.Length != 0) hash ^= ServerHostOverride.GetHashCode();
       if (CredType.Length != 0) hash ^= CredType.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -687,6 +730,9 @@
         output.WriteRawTag(26);
         output.WriteString(CredType);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -701,6 +747,9 @@
       if (CredType.Length != 0) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(CredType);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -718,6 +767,7 @@
       if (other.CredType.Length != 0) {
         CredType = other.CredType;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -726,7 +776,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 8: {
             UseTestCa = input.ReadBool();
@@ -748,6 +798,7 @@
 
   public sealed partial class ChannelArg : pb::IMessage<ChannelArg> {
     private static readonly pb::MessageParser<ChannelArg> _parser = new pb::MessageParser<ChannelArg>(() => new ChannelArg());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<ChannelArg> Parser { get { return _parser; } }
 
@@ -780,6 +831,7 @@
           break;
       }
 
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -856,7 +908,7 @@
       if (StrValue != other.StrValue) return false;
       if (IntValue != other.IntValue) return false;
       if (ValueCase != other.ValueCase) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -866,6 +918,9 @@
       if (valueCase_ == ValueOneofCase.StrValue) hash ^= StrValue.GetHashCode();
       if (valueCase_ == ValueOneofCase.IntValue) hash ^= IntValue.GetHashCode();
       hash ^= (int) valueCase_;
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -888,6 +943,9 @@
         output.WriteRawTag(24);
         output.WriteInt32(IntValue);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -902,6 +960,9 @@
       if (valueCase_ == ValueOneofCase.IntValue) {
         size += 1 + pb::CodedOutputStream.ComputeInt32Size(IntValue);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -922,6 +983,7 @@
           break;
       }
 
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -930,7 +992,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             Name = input.ReadString();
@@ -952,6 +1014,7 @@
 
   public sealed partial class ClientConfig : pb::IMessage<ClientConfig> {
     private static readonly pb::MessageParser<ClientConfig> _parser = new pb::MessageParser<ClientConfig>(() => new ClientConfig());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<ClientConfig> Parser { get { return _parser; } }
 
@@ -991,6 +1054,7 @@
       threadsPerCq_ = other.threadsPerCq_;
       messagesPerStream_ = other.messagesPerStream_;
       useCoalesceApi_ = other.useCoalesceApi_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1244,7 +1308,7 @@
       if (ThreadsPerCq != other.ThreadsPerCq) return false;
       if (MessagesPerStream != other.MessagesPerStream) return false;
       if (UseCoalesceApi != other.UseCoalesceApi) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1267,6 +1331,9 @@
       if (ThreadsPerCq != 0) hash ^= ThreadsPerCq.GetHashCode();
       if (MessagesPerStream != 0) hash ^= MessagesPerStream.GetHashCode();
       if (UseCoalesceApi != false) hash ^= UseCoalesceApi.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -1336,6 +1403,9 @@
         output.WriteRawTag(152, 1);
         output.WriteBool(UseCoalesceApi);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1386,6 +1456,9 @@
       if (UseCoalesceApi != false) {
         size += 2 + 1;
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -1451,6 +1524,7 @@
       if (other.UseCoalesceApi != false) {
         UseCoalesceApi = other.UseCoalesceApi;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1459,7 +1533,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             serverTargets_.AddEntriesFrom(input, _repeated_serverTargets_codec);
@@ -1550,6 +1624,7 @@
 
   public sealed partial class ClientStatus : pb::IMessage<ClientStatus> {
     private static readonly pb::MessageParser<ClientStatus> _parser = new pb::MessageParser<ClientStatus>(() => new ClientStatus());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<ClientStatus> Parser { get { return _parser; } }
 
@@ -1573,6 +1648,7 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public ClientStatus(ClientStatus other) : this() {
       Stats = other.stats_ != null ? other.Stats.Clone() : null;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1605,13 +1681,16 @@
         return true;
       }
       if (!object.Equals(Stats, other.Stats)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
       if (stats_ != null) hash ^= Stats.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -1626,6 +1705,9 @@
         output.WriteRawTag(10);
         output.WriteMessage(Stats);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1634,6 +1716,9 @@
       if (stats_ != null) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(Stats);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -1648,6 +1733,7 @@
         }
         Stats.MergeFrom(other.Stats);
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1656,7 +1742,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             if (stats_ == null) {
@@ -1676,6 +1762,7 @@
   /// </summary>
   public sealed partial class Mark : pb::IMessage<Mark> {
     private static readonly pb::MessageParser<Mark> _parser = new pb::MessageParser<Mark>(() => new Mark());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<Mark> Parser { get { return _parser; } }
 
@@ -1699,6 +1786,7 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public Mark(Mark other) : this() {
       reset_ = other.reset_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1734,13 +1822,16 @@
         return true;
       }
       if (Reset != other.Reset) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
       if (Reset != false) hash ^= Reset.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -1755,6 +1846,9 @@
         output.WriteRawTag(8);
         output.WriteBool(Reset);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1763,6 +1857,9 @@
       if (Reset != false) {
         size += 1 + 1;
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -1774,6 +1871,7 @@
       if (other.Reset != false) {
         Reset = other.Reset;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1782,7 +1880,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 8: {
             Reset = input.ReadBool();
@@ -1796,6 +1894,7 @@
 
   public sealed partial class ClientArgs : pb::IMessage<ClientArgs> {
     private static readonly pb::MessageParser<ClientArgs> _parser = new pb::MessageParser<ClientArgs>(() => new ClientArgs());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<ClientArgs> Parser { get { return _parser; } }
 
@@ -1827,6 +1926,7 @@
           break;
       }
 
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1891,7 +1991,7 @@
       if (!object.Equals(Setup, other.Setup)) return false;
       if (!object.Equals(Mark, other.Mark)) return false;
       if (ArgtypeCase != other.ArgtypeCase) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1900,6 +2000,9 @@
       if (argtypeCase_ == ArgtypeOneofCase.Setup) hash ^= Setup.GetHashCode();
       if (argtypeCase_ == ArgtypeOneofCase.Mark) hash ^= Mark.GetHashCode();
       hash ^= (int) argtypeCase_;
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -1918,6 +2021,9 @@
         output.WriteRawTag(18);
         output.WriteMessage(Mark);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1929,6 +2035,9 @@
       if (argtypeCase_ == ArgtypeOneofCase.Mark) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(Mark);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -1952,6 +2061,7 @@
           break;
       }
 
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1960,7 +2070,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             global::Grpc.Testing.ClientConfig subBuilder = new global::Grpc.Testing.ClientConfig();
@@ -1988,6 +2098,7 @@
 
   public sealed partial class ServerConfig : pb::IMessage<ServerConfig> {
     private static readonly pb::MessageParser<ServerConfig> _parser = new pb::MessageParser<ServerConfig>(() => new ServerConfig());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<ServerConfig> Parser { get { return _parser; } }
 
@@ -2021,6 +2132,7 @@
       threadsPerCq_ = other.threadsPerCq_;
       resourceQuotaSize_ = other.resourceQuotaSize_;
       channelArgs_ = other.channelArgs_.Clone();
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2198,7 +2310,7 @@
       if (ThreadsPerCq != other.ThreadsPerCq) return false;
       if (ResourceQuotaSize != other.ResourceQuotaSize) return false;
       if(!channelArgs_.Equals(other.channelArgs_)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2215,6 +2327,9 @@
       if (ThreadsPerCq != 0) hash ^= ThreadsPerCq.GetHashCode();
       if (ResourceQuotaSize != 0) hash ^= ResourceQuotaSize.GetHashCode();
       hash ^= channelArgs_.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -2263,6 +2378,9 @@
         output.WriteInt32(ResourceQuotaSize);
       }
       channelArgs_.WriteTo(output, _repeated_channelArgs_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2297,6 +2415,9 @@
         size += 2 + pb::CodedOutputStream.ComputeInt32Size(ResourceQuotaSize);
       }
       size += channelArgs_.CalculateSize(_repeated_channelArgs_codec);
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -2340,6 +2461,7 @@
         ResourceQuotaSize = other.ResourceQuotaSize;
       }
       channelArgs_.Add(other.channelArgs_);
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2348,7 +2470,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 8: {
             serverType_ = (global::Grpc.Testing.ServerType) input.ReadEnum();
@@ -2409,6 +2531,7 @@
 
   public sealed partial class ServerArgs : pb::IMessage<ServerArgs> {
     private static readonly pb::MessageParser<ServerArgs> _parser = new pb::MessageParser<ServerArgs>(() => new ServerArgs());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<ServerArgs> Parser { get { return _parser; } }
 
@@ -2440,6 +2563,7 @@
           break;
       }
 
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2504,7 +2628,7 @@
       if (!object.Equals(Setup, other.Setup)) return false;
       if (!object.Equals(Mark, other.Mark)) return false;
       if (ArgtypeCase != other.ArgtypeCase) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2513,6 +2637,9 @@
       if (argtypeCase_ == ArgtypeOneofCase.Setup) hash ^= Setup.GetHashCode();
       if (argtypeCase_ == ArgtypeOneofCase.Mark) hash ^= Mark.GetHashCode();
       hash ^= (int) argtypeCase_;
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -2531,6 +2658,9 @@
         output.WriteRawTag(18);
         output.WriteMessage(Mark);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2542,6 +2672,9 @@
       if (argtypeCase_ == ArgtypeOneofCase.Mark) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(Mark);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -2565,6 +2698,7 @@
           break;
       }
 
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2573,7 +2707,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             global::Grpc.Testing.ServerConfig subBuilder = new global::Grpc.Testing.ServerConfig();
@@ -2601,6 +2735,7 @@
 
   public sealed partial class ServerStatus : pb::IMessage<ServerStatus> {
     private static readonly pb::MessageParser<ServerStatus> _parser = new pb::MessageParser<ServerStatus>(() => new ServerStatus());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<ServerStatus> Parser { get { return _parser; } }
 
@@ -2626,6 +2761,7 @@
       Stats = other.stats_ != null ? other.Stats.Clone() : null;
       port_ = other.port_;
       cores_ = other.cores_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2688,7 +2824,7 @@
       if (!object.Equals(Stats, other.Stats)) return false;
       if (Port != other.Port) return false;
       if (Cores != other.Cores) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2697,6 +2833,9 @@
       if (stats_ != null) hash ^= Stats.GetHashCode();
       if (Port != 0) hash ^= Port.GetHashCode();
       if (Cores != 0) hash ^= Cores.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -2719,6 +2858,9 @@
         output.WriteRawTag(24);
         output.WriteInt32(Cores);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2733,6 +2875,9 @@
       if (Cores != 0) {
         size += 1 + pb::CodedOutputStream.ComputeInt32Size(Cores);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -2753,6 +2898,7 @@
       if (other.Cores != 0) {
         Cores = other.Cores;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2761,7 +2907,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             if (stats_ == null) {
@@ -2786,6 +2932,7 @@
 
   public sealed partial class CoreRequest : pb::IMessage<CoreRequest> {
     private static readonly pb::MessageParser<CoreRequest> _parser = new pb::MessageParser<CoreRequest>(() => new CoreRequest());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<CoreRequest> Parser { get { return _parser; } }
 
@@ -2808,6 +2955,7 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public CoreRequest(CoreRequest other) : this() {
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2828,12 +2976,15 @@
       if (ReferenceEquals(other, this)) {
         return true;
       }
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -2844,11 +2995,17 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public void WriteTo(pb::CodedOutputStream output) {
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public int CalculateSize() {
       int size = 0;
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -2857,6 +3014,7 @@
       if (other == null) {
         return;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2865,7 +3023,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
         }
       }
@@ -2875,6 +3033,7 @@
 
   public sealed partial class CoreResponse : pb::IMessage<CoreResponse> {
     private static readonly pb::MessageParser<CoreResponse> _parser = new pb::MessageParser<CoreResponse>(() => new CoreResponse());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<CoreResponse> Parser { get { return _parser; } }
 
@@ -2898,6 +3057,7 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public CoreResponse(CoreResponse other) : this() {
       cores_ = other.cores_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2933,13 +3093,16 @@
         return true;
       }
       if (Cores != other.Cores) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
       if (Cores != 0) hash ^= Cores.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -2954,6 +3117,9 @@
         output.WriteRawTag(8);
         output.WriteInt32(Cores);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2962,6 +3128,9 @@
       if (Cores != 0) {
         size += 1 + pb::CodedOutputStream.ComputeInt32Size(Cores);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -2973,6 +3142,7 @@
       if (other.Cores != 0) {
         Cores = other.Cores;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2981,7 +3151,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 8: {
             Cores = input.ReadInt32();
@@ -2995,6 +3165,7 @@
 
   public sealed partial class Void : pb::IMessage<Void> {
     private static readonly pb::MessageParser<Void> _parser = new pb::MessageParser<Void>(() => new Void());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<Void> Parser { get { return _parser; } }
 
@@ -3017,6 +3188,7 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public Void(Void other) : this() {
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -3037,12 +3209,15 @@
       if (ReferenceEquals(other, this)) {
         return true;
       }
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -3053,11 +3228,17 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public void WriteTo(pb::CodedOutputStream output) {
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public int CalculateSize() {
       int size = 0;
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -3066,6 +3247,7 @@
       if (other == null) {
         return;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -3074,7 +3256,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
         }
       }
@@ -3087,6 +3269,7 @@
   /// </summary>
   public sealed partial class Scenario : pb::IMessage<Scenario> {
     private static readonly pb::MessageParser<Scenario> _parser = new pb::MessageParser<Scenario>(() => new Scenario());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<Scenario> Parser { get { return _parser; } }
 
@@ -3117,6 +3300,7 @@
       warmupSeconds_ = other.warmupSeconds_;
       benchmarkSeconds_ = other.benchmarkSeconds_;
       spawnLocalWorkerCount_ = other.spawnLocalWorkerCount_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -3257,7 +3441,7 @@
       if (WarmupSeconds != other.WarmupSeconds) return false;
       if (BenchmarkSeconds != other.BenchmarkSeconds) return false;
       if (SpawnLocalWorkerCount != other.SpawnLocalWorkerCount) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -3271,6 +3455,9 @@
       if (WarmupSeconds != 0) hash ^= WarmupSeconds.GetHashCode();
       if (BenchmarkSeconds != 0) hash ^= BenchmarkSeconds.GetHashCode();
       if (SpawnLocalWorkerCount != 0) hash ^= SpawnLocalWorkerCount.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -3313,6 +3500,9 @@
         output.WriteRawTag(64);
         output.WriteInt32(SpawnLocalWorkerCount);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -3342,6 +3532,9 @@
       if (SpawnLocalWorkerCount != 0) {
         size += 1 + pb::CodedOutputStream.ComputeInt32Size(SpawnLocalWorkerCount);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -3380,6 +3573,7 @@
       if (other.SpawnLocalWorkerCount != 0) {
         SpawnLocalWorkerCount = other.SpawnLocalWorkerCount;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -3388,7 +3582,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             Name = input.ReadString();
@@ -3439,6 +3633,7 @@
   /// </summary>
   public sealed partial class Scenarios : pb::IMessage<Scenarios> {
     private static readonly pb::MessageParser<Scenarios> _parser = new pb::MessageParser<Scenarios>(() => new Scenarios());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<Scenarios> Parser { get { return _parser; } }
 
@@ -3462,6 +3657,7 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public Scenarios(Scenarios other) : this() {
       scenarios_ = other.scenarios_.Clone();
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -3493,13 +3689,16 @@
         return true;
       }
       if(!scenarios_.Equals(other.scenarios_)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
       hash ^= scenarios_.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -3511,12 +3710,18 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public void WriteTo(pb::CodedOutputStream output) {
       scenarios_.WriteTo(output, _repeated_scenarios_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public int CalculateSize() {
       int size = 0;
       size += scenarios_.CalculateSize(_repeated_scenarios_codec);
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -3526,6 +3731,7 @@
         return;
       }
       scenarios_.Add(other.scenarios_);
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -3534,7 +3740,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             scenarios_.AddEntriesFrom(input, _repeated_scenarios_codec);
@@ -3552,6 +3758,7 @@
   /// </summary>
   public sealed partial class ScenarioResultSummary : pb::IMessage<ScenarioResultSummary> {
     private static readonly pb::MessageParser<ScenarioResultSummary> _parser = new pb::MessageParser<ScenarioResultSummary>(() => new ScenarioResultSummary());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<ScenarioResultSummary> Parser { get { return _parser; } }
 
@@ -3592,6 +3799,7 @@
       serverPollsPerRequest_ = other.serverPollsPerRequest_;
       serverQueriesPerCpuSec_ = other.serverQueriesPerCpuSec_;
       clientQueriesPerCpuSec_ = other.clientQueriesPerCpuSec_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -3843,48 +4051,51 @@
       if (ReferenceEquals(other, this)) {
         return true;
       }
-      if (Qps != other.Qps) return false;
-      if (QpsPerServerCore != other.QpsPerServerCore) return false;
-      if (ServerSystemTime != other.ServerSystemTime) return false;
-      if (ServerUserTime != other.ServerUserTime) return false;
-      if (ClientSystemTime != other.ClientSystemTime) return false;
-      if (ClientUserTime != other.ClientUserTime) return false;
-      if (Latency50 != other.Latency50) return false;
-      if (Latency90 != other.Latency90) return false;
-      if (Latency95 != other.Latency95) return false;
-      if (Latency99 != other.Latency99) return false;
-      if (Latency999 != other.Latency999) return false;
-      if (ServerCpuUsage != other.ServerCpuUsage) return false;
-      if (SuccessfulRequestsPerSecond != other.SuccessfulRequestsPerSecond) return false;
-      if (FailedRequestsPerSecond != other.FailedRequestsPerSecond) return false;
-      if (ClientPollsPerRequest != other.ClientPollsPerRequest) return false;
-      if (ServerPollsPerRequest != other.ServerPollsPerRequest) return false;
-      if (ServerQueriesPerCpuSec != other.ServerQueriesPerCpuSec) return false;
-      if (ClientQueriesPerCpuSec != other.ClientQueriesPerCpuSec) return false;
-      return true;
+      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(Qps, other.Qps)) return false;
+      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(QpsPerServerCore, other.QpsPerServerCore)) return false;
+      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(ServerSystemTime, other.ServerSystemTime)) return false;
+      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(ServerUserTime, other.ServerUserTime)) return false;
+      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(ClientSystemTime, other.ClientSystemTime)) return false;
+      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(ClientUserTime, other.ClientUserTime)) return false;
+      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(Latency50, other.Latency50)) return false;
+      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(Latency90, other.Latency90)) return false;
+      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(Latency95, other.Latency95)) return false;
+      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(Latency99, other.Latency99)) return false;
+      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(Latency999, other.Latency999)) return false;
+      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(ServerCpuUsage, other.ServerCpuUsage)) return false;
+      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(SuccessfulRequestsPerSecond, other.SuccessfulRequestsPerSecond)) return false;
+      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(FailedRequestsPerSecond, other.FailedRequestsPerSecond)) return false;
+      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(ClientPollsPerRequest, other.ClientPollsPerRequest)) return false;
+      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(ServerPollsPerRequest, other.ServerPollsPerRequest)) return false;
+      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(ServerQueriesPerCpuSec, other.ServerQueriesPerCpuSec)) return false;
+      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(ClientQueriesPerCpuSec, other.ClientQueriesPerCpuSec)) return false;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
-      if (Qps != 0D) hash ^= Qps.GetHashCode();
-      if (QpsPerServerCore != 0D) hash ^= QpsPerServerCore.GetHashCode();
-      if (ServerSystemTime != 0D) hash ^= ServerSystemTime.GetHashCode();
-      if (ServerUserTime != 0D) hash ^= ServerUserTime.GetHashCode();
-      if (ClientSystemTime != 0D) hash ^= ClientSystemTime.GetHashCode();
-      if (ClientUserTime != 0D) hash ^= ClientUserTime.GetHashCode();
-      if (Latency50 != 0D) hash ^= Latency50.GetHashCode();
-      if (Latency90 != 0D) hash ^= Latency90.GetHashCode();
-      if (Latency95 != 0D) hash ^= Latency95.GetHashCode();
-      if (Latency99 != 0D) hash ^= Latency99.GetHashCode();
-      if (Latency999 != 0D) hash ^= Latency999.GetHashCode();
-      if (ServerCpuUsage != 0D) hash ^= ServerCpuUsage.GetHashCode();
-      if (SuccessfulRequestsPerSecond != 0D) hash ^= SuccessfulRequestsPerSecond.GetHashCode();
-      if (FailedRequestsPerSecond != 0D) hash ^= FailedRequestsPerSecond.GetHashCode();
-      if (ClientPollsPerRequest != 0D) hash ^= ClientPollsPerRequest.GetHashCode();
-      if (ServerPollsPerRequest != 0D) hash ^= ServerPollsPerRequest.GetHashCode();
-      if (ServerQueriesPerCpuSec != 0D) hash ^= ServerQueriesPerCpuSec.GetHashCode();
-      if (ClientQueriesPerCpuSec != 0D) hash ^= ClientQueriesPerCpuSec.GetHashCode();
+      if (Qps != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(Qps);
+      if (QpsPerServerCore != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(QpsPerServerCore);
+      if (ServerSystemTime != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(ServerSystemTime);
+      if (ServerUserTime != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(ServerUserTime);
+      if (ClientSystemTime != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(ClientSystemTime);
+      if (ClientUserTime != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(ClientUserTime);
+      if (Latency50 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(Latency50);
+      if (Latency90 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(Latency90);
+      if (Latency95 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(Latency95);
+      if (Latency99 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(Latency99);
+      if (Latency999 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(Latency999);
+      if (ServerCpuUsage != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(ServerCpuUsage);
+      if (SuccessfulRequestsPerSecond != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(SuccessfulRequestsPerSecond);
+      if (FailedRequestsPerSecond != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(FailedRequestsPerSecond);
+      if (ClientPollsPerRequest != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(ClientPollsPerRequest);
+      if (ServerPollsPerRequest != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(ServerPollsPerRequest);
+      if (ServerQueriesPerCpuSec != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(ServerQueriesPerCpuSec);
+      if (ClientQueriesPerCpuSec != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(ClientQueriesPerCpuSec);
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -3967,6 +4178,9 @@
         output.WriteRawTag(145, 1);
         output.WriteDouble(ClientQueriesPerCpuSec);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -4026,6 +4240,9 @@
       if (ClientQueriesPerCpuSec != 0D) {
         size += 2 + 8;
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -4088,6 +4305,7 @@
       if (other.ClientQueriesPerCpuSec != 0D) {
         ClientQueriesPerCpuSec = other.ClientQueriesPerCpuSec;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -4096,7 +4314,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 9: {
             Qps = input.ReadDouble();
@@ -4181,6 +4399,7 @@
   /// </summary>
   public sealed partial class ScenarioResult : pb::IMessage<ScenarioResult> {
     private static readonly pb::MessageParser<ScenarioResult> _parser = new pb::MessageParser<ScenarioResult>(() => new ScenarioResult());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<ScenarioResult> Parser { get { return _parser; } }
 
@@ -4212,6 +4431,7 @@
       clientSuccess_ = other.clientSuccess_.Clone();
       serverSuccess_ = other.serverSuccess_.Clone();
       requestResults_ = other.requestResults_.Clone();
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -4358,7 +4578,7 @@
       if(!clientSuccess_.Equals(other.clientSuccess_)) return false;
       if(!serverSuccess_.Equals(other.serverSuccess_)) return false;
       if(!requestResults_.Equals(other.requestResults_)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -4373,6 +4593,9 @@
       hash ^= clientSuccess_.GetHashCode();
       hash ^= serverSuccess_.GetHashCode();
       hash ^= requestResults_.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -4401,6 +4624,9 @@
       clientSuccess_.WriteTo(output, _repeated_clientSuccess_codec);
       serverSuccess_.WriteTo(output, _repeated_serverSuccess_codec);
       requestResults_.WriteTo(output, _repeated_requestResults_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -4421,6 +4647,9 @@
       size += clientSuccess_.CalculateSize(_repeated_clientSuccess_codec);
       size += serverSuccess_.CalculateSize(_repeated_serverSuccess_codec);
       size += requestResults_.CalculateSize(_repeated_requestResults_codec);
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -4453,6 +4682,7 @@
       clientSuccess_.Add(other.clientSuccess_);
       serverSuccess_.Add(other.serverSuccess_);
       requestResults_.Add(other.requestResults_);
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -4461,7 +4691,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             if (scenario_ == null) {
diff --git a/src/csharp/Grpc.IntegrationTesting/CoreStats/Stats.cs b/src/csharp/Grpc.IntegrationTesting/CoreStats/Stats.cs
index 380294e..4ff56cd 100644
--- a/src/csharp/Grpc.IntegrationTesting/CoreStats/Stats.cs
+++ b/src/csharp/Grpc.IntegrationTesting/CoreStats/Stats.cs
@@ -1,5 +1,7 @@
-// Generated by the protocol buffer compiler.  DO NOT EDIT!
-// source: grpc/core/stats.proto
+// <auto-generated>
+//     Generated by the protocol buffer compiler.  DO NOT EDIT!
+//     source: grpc/core/stats.proto
+// </auto-generated>
 #pragma warning disable 1591, 0612, 3021
 #region Designer generated code
 
@@ -43,6 +45,7 @@
   #region Messages
   public sealed partial class Bucket : pb::IMessage<Bucket> {
     private static readonly pb::MessageParser<Bucket> _parser = new pb::MessageParser<Bucket>(() => new Bucket());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<Bucket> Parser { get { return _parser; } }
 
@@ -67,6 +70,7 @@
     public Bucket(Bucket other) : this() {
       start_ = other.start_;
       count_ = other.count_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -109,16 +113,19 @@
       if (ReferenceEquals(other, this)) {
         return true;
       }
-      if (Start != other.Start) return false;
+      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(Start, other.Start)) return false;
       if (Count != other.Count) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
-      if (Start != 0D) hash ^= Start.GetHashCode();
+      if (Start != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(Start);
       if (Count != 0UL) hash ^= Count.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -137,6 +144,9 @@
         output.WriteRawTag(16);
         output.WriteUInt64(Count);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -148,6 +158,9 @@
       if (Count != 0UL) {
         size += 1 + pb::CodedOutputStream.ComputeUInt64Size(Count);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -162,6 +175,7 @@
       if (other.Count != 0UL) {
         Count = other.Count;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -170,7 +184,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 9: {
             Start = input.ReadDouble();
@@ -188,6 +202,7 @@
 
   public sealed partial class Histogram : pb::IMessage<Histogram> {
     private static readonly pb::MessageParser<Histogram> _parser = new pb::MessageParser<Histogram>(() => new Histogram());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<Histogram> Parser { get { return _parser; } }
 
@@ -211,6 +226,7 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public Histogram(Histogram other) : this() {
       buckets_ = other.buckets_.Clone();
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -242,13 +258,16 @@
         return true;
       }
       if(!buckets_.Equals(other.buckets_)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
       hash ^= buckets_.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -260,12 +279,18 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public void WriteTo(pb::CodedOutputStream output) {
       buckets_.WriteTo(output, _repeated_buckets_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public int CalculateSize() {
       int size = 0;
       size += buckets_.CalculateSize(_repeated_buckets_codec);
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -275,6 +300,7 @@
         return;
       }
       buckets_.Add(other.buckets_);
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -283,7 +309,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             buckets_.AddEntriesFrom(input, _repeated_buckets_codec);
@@ -297,6 +323,7 @@
 
   public sealed partial class Metric : pb::IMessage<Metric> {
     private static readonly pb::MessageParser<Metric> _parser = new pb::MessageParser<Metric>(() => new Metric());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<Metric> Parser { get { return _parser; } }
 
@@ -329,6 +356,7 @@
           break;
       }
 
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -405,7 +433,7 @@
       if (Count != other.Count) return false;
       if (!object.Equals(Histogram, other.Histogram)) return false;
       if (ValueCase != other.ValueCase) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -415,6 +443,9 @@
       if (valueCase_ == ValueOneofCase.Count) hash ^= Count.GetHashCode();
       if (valueCase_ == ValueOneofCase.Histogram) hash ^= Histogram.GetHashCode();
       hash ^= (int) valueCase_;
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -437,6 +468,9 @@
         output.WriteRawTag(90);
         output.WriteMessage(Histogram);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -451,6 +485,9 @@
       if (valueCase_ == ValueOneofCase.Histogram) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(Histogram);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -474,6 +511,7 @@
           break;
       }
 
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -482,7 +520,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             Name = input.ReadString();
@@ -509,6 +547,7 @@
 
   public sealed partial class Stats : pb::IMessage<Stats> {
     private static readonly pb::MessageParser<Stats> _parser = new pb::MessageParser<Stats>(() => new Stats());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<Stats> Parser { get { return _parser; } }
 
@@ -532,6 +571,7 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public Stats(Stats other) : this() {
       metrics_ = other.metrics_.Clone();
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -563,13 +603,16 @@
         return true;
       }
       if(!metrics_.Equals(other.metrics_)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
       hash ^= metrics_.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -581,12 +624,18 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public void WriteTo(pb::CodedOutputStream output) {
       metrics_.WriteTo(output, _repeated_metrics_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public int CalculateSize() {
       int size = 0;
       size += metrics_.CalculateSize(_repeated_metrics_codec);
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -596,6 +645,7 @@
         return;
       }
       metrics_.Add(other.metrics_);
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -604,7 +654,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             metrics_.AddEntriesFrom(input, _repeated_metrics_codec);
diff --git a/src/csharp/Grpc.IntegrationTesting/EchoMessages.cs b/src/csharp/Grpc.IntegrationTesting/EchoMessages.cs
index 9581ade..39c3d76 100644
--- a/src/csharp/Grpc.IntegrationTesting/EchoMessages.cs
+++ b/src/csharp/Grpc.IntegrationTesting/EchoMessages.cs
@@ -1,5 +1,7 @@
-// Generated by the protocol buffer compiler.  DO NOT EDIT!
-// source: src/proto/grpc/testing/echo_messages.proto
+// <auto-generated>
+//     Generated by the protocol buffer compiler.  DO NOT EDIT!
+//     source: src/proto/grpc/testing/echo_messages.proto
+// </auto-generated>
 #pragma warning disable 1591, 0612, 3021
 #region Designer generated code
 
@@ -63,6 +65,7 @@
   /// </summary>
   public sealed partial class DebugInfo : pb::IMessage<DebugInfo> {
     private static readonly pb::MessageParser<DebugInfo> _parser = new pb::MessageParser<DebugInfo>(() => new DebugInfo());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<DebugInfo> Parser { get { return _parser; } }
 
@@ -87,6 +90,7 @@
     public DebugInfo(DebugInfo other) : this() {
       stackEntries_ = other.stackEntries_.Clone();
       detail_ = other.detail_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -130,7 +134,7 @@
       }
       if(!stackEntries_.Equals(other.stackEntries_)) return false;
       if (Detail != other.Detail) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -138,6 +142,9 @@
       int hash = 1;
       hash ^= stackEntries_.GetHashCode();
       if (Detail.Length != 0) hash ^= Detail.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -153,6 +160,9 @@
         output.WriteRawTag(18);
         output.WriteString(Detail);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -162,6 +172,9 @@
       if (Detail.Length != 0) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(Detail);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -174,6 +187,7 @@
       if (other.Detail.Length != 0) {
         Detail = other.Detail;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -182,7 +196,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             stackEntries_.AddEntriesFrom(input, _repeated_stackEntries_codec);
@@ -203,6 +217,7 @@
   /// </summary>
   public sealed partial class ErrorStatus : pb::IMessage<ErrorStatus> {
     private static readonly pb::MessageParser<ErrorStatus> _parser = new pb::MessageParser<ErrorStatus>(() => new ErrorStatus());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<ErrorStatus> Parser { get { return _parser; } }
 
@@ -228,6 +243,7 @@
       code_ = other.code_;
       errorMessage_ = other.errorMessage_;
       binaryErrorDetails_ = other.binaryErrorDetails_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -284,7 +300,7 @@
       if (Code != other.Code) return false;
       if (ErrorMessage != other.ErrorMessage) return false;
       if (BinaryErrorDetails != other.BinaryErrorDetails) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -293,6 +309,9 @@
       if (Code != 0) hash ^= Code.GetHashCode();
       if (ErrorMessage.Length != 0) hash ^= ErrorMessage.GetHashCode();
       if (BinaryErrorDetails.Length != 0) hash ^= BinaryErrorDetails.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -315,6 +334,9 @@
         output.WriteRawTag(26);
         output.WriteString(BinaryErrorDetails);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -329,6 +351,9 @@
       if (BinaryErrorDetails.Length != 0) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(BinaryErrorDetails);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -346,6 +371,7 @@
       if (other.BinaryErrorDetails.Length != 0) {
         BinaryErrorDetails = other.BinaryErrorDetails;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -354,7 +380,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 8: {
             Code = input.ReadInt32();
@@ -376,6 +402,7 @@
 
   public sealed partial class RequestParams : pb::IMessage<RequestParams> {
     private static readonly pb::MessageParser<RequestParams> _parser = new pb::MessageParser<RequestParams>(() => new RequestParams());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<RequestParams> Parser { get { return _parser; } }
 
@@ -413,6 +440,7 @@
       binaryErrorDetails_ = other.binaryErrorDetails_;
       ExpectedError = other.expectedError_ != null ? other.ExpectedError.Clone() : null;
       serverSleepUs_ = other.serverSleepUs_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -622,7 +650,7 @@
       if (BinaryErrorDetails != other.BinaryErrorDetails) return false;
       if (!object.Equals(ExpectedError, other.ExpectedError)) return false;
       if (ServerSleepUs != other.ServerSleepUs) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -643,6 +671,9 @@
       if (BinaryErrorDetails.Length != 0) hash ^= BinaryErrorDetails.GetHashCode();
       if (expectedError_ != null) hash ^= ExpectedError.GetHashCode();
       if (ServerSleepUs != 0) hash ^= ServerSleepUs.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -713,6 +744,9 @@
         output.WriteRawTag(120);
         output.WriteInt32(ServerSleepUs);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -763,6 +797,9 @@
       if (ServerSleepUs != 0) {
         size += 1 + pb::CodedOutputStream.ComputeInt32Size(ServerSleepUs);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -822,6 +859,7 @@
       if (other.ServerSleepUs != 0) {
         ServerSleepUs = other.ServerSleepUs;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -830,7 +868,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 8: {
             EchoDeadline = input.ReadBool();
@@ -906,6 +944,7 @@
 
   public sealed partial class EchoRequest : pb::IMessage<EchoRequest> {
     private static readonly pb::MessageParser<EchoRequest> _parser = new pb::MessageParser<EchoRequest>(() => new EchoRequest());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<EchoRequest> Parser { get { return _parser; } }
 
@@ -930,6 +969,7 @@
     public EchoRequest(EchoRequest other) : this() {
       message_ = other.message_;
       Param = other.param_ != null ? other.Param.Clone() : null;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -974,7 +1014,7 @@
       }
       if (Message != other.Message) return false;
       if (!object.Equals(Param, other.Param)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -982,6 +1022,9 @@
       int hash = 1;
       if (Message.Length != 0) hash ^= Message.GetHashCode();
       if (param_ != null) hash ^= Param.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -1000,6 +1043,9 @@
         output.WriteRawTag(18);
         output.WriteMessage(Param);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1011,6 +1057,9 @@
       if (param_ != null) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(Param);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -1028,6 +1077,7 @@
         }
         Param.MergeFrom(other.Param);
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1036,7 +1086,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             Message = input.ReadString();
@@ -1057,6 +1107,7 @@
 
   public sealed partial class ResponseParams : pb::IMessage<ResponseParams> {
     private static readonly pb::MessageParser<ResponseParams> _parser = new pb::MessageParser<ResponseParams>(() => new ResponseParams());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<ResponseParams> Parser { get { return _parser; } }
 
@@ -1082,6 +1133,7 @@
       requestDeadline_ = other.requestDeadline_;
       host_ = other.host_;
       peer_ = other.peer_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1138,7 +1190,7 @@
       if (RequestDeadline != other.RequestDeadline) return false;
       if (Host != other.Host) return false;
       if (Peer != other.Peer) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1147,6 +1199,9 @@
       if (RequestDeadline != 0L) hash ^= RequestDeadline.GetHashCode();
       if (Host.Length != 0) hash ^= Host.GetHashCode();
       if (Peer.Length != 0) hash ^= Peer.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -1169,6 +1224,9 @@
         output.WriteRawTag(26);
         output.WriteString(Peer);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1183,6 +1241,9 @@
       if (Peer.Length != 0) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(Peer);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -1200,6 +1261,7 @@
       if (other.Peer.Length != 0) {
         Peer = other.Peer;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1208,7 +1270,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 8: {
             RequestDeadline = input.ReadInt64();
@@ -1230,6 +1292,7 @@
 
   public sealed partial class EchoResponse : pb::IMessage<EchoResponse> {
     private static readonly pb::MessageParser<EchoResponse> _parser = new pb::MessageParser<EchoResponse>(() => new EchoResponse());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<EchoResponse> Parser { get { return _parser; } }
 
@@ -1254,6 +1317,7 @@
     public EchoResponse(EchoResponse other) : this() {
       message_ = other.message_;
       Param = other.param_ != null ? other.Param.Clone() : null;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1298,7 +1362,7 @@
       }
       if (Message != other.Message) return false;
       if (!object.Equals(Param, other.Param)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1306,6 +1370,9 @@
       int hash = 1;
       if (Message.Length != 0) hash ^= Message.GetHashCode();
       if (param_ != null) hash ^= Param.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -1324,6 +1391,9 @@
         output.WriteRawTag(18);
         output.WriteMessage(Param);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1335,6 +1405,9 @@
       if (param_ != null) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(Param);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -1352,6 +1425,7 @@
         }
         Param.MergeFrom(other.Param);
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1360,7 +1434,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             Message = input.ReadString();
diff --git a/src/csharp/Grpc.IntegrationTesting/Empty.cs b/src/csharp/Grpc.IntegrationTesting/Empty.cs
index 24ffd61..0d4c28b 100644
--- a/src/csharp/Grpc.IntegrationTesting/Empty.cs
+++ b/src/csharp/Grpc.IntegrationTesting/Empty.cs
@@ -1,5 +1,7 @@
-// Generated by the protocol buffer compiler.  DO NOT EDIT!
-// source: src/proto/grpc/testing/empty.proto
+// <auto-generated>
+//     Generated by the protocol buffer compiler.  DO NOT EDIT!
+//     source: src/proto/grpc/testing/empty.proto
+// </auto-generated>
 #pragma warning disable 1591, 0612, 3021
 #region Designer generated code
 
@@ -45,6 +47,7 @@
   /// </summary>
   public sealed partial class Empty : pb::IMessage<Empty> {
     private static readonly pb::MessageParser<Empty> _parser = new pb::MessageParser<Empty>(() => new Empty());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<Empty> Parser { get { return _parser; } }
 
@@ -67,6 +70,7 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public Empty(Empty other) : this() {
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -87,12 +91,15 @@
       if (ReferenceEquals(other, this)) {
         return true;
       }
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -103,11 +110,17 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public void WriteTo(pb::CodedOutputStream output) {
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public int CalculateSize() {
       int size = 0;
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -116,6 +129,7 @@
       if (other == null) {
         return;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -124,7 +138,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
         }
       }
diff --git a/src/csharp/Grpc.IntegrationTesting/Messages.cs b/src/csharp/Grpc.IntegrationTesting/Messages.cs
index 278ef66..b5c93ba 100644
--- a/src/csharp/Grpc.IntegrationTesting/Messages.cs
+++ b/src/csharp/Grpc.IntegrationTesting/Messages.cs
@@ -1,5 +1,7 @@
-// Generated by the protocol buffer compiler.  DO NOT EDIT!
-// source: src/proto/grpc/testing/messages.proto
+// <auto-generated>
+//     Generated by the protocol buffer compiler.  DO NOT EDIT!
+//     source: src/proto/grpc/testing/messages.proto
+// </auto-generated>
 #pragma warning disable 1591, 0612, 3021
 #region Designer generated code
 
@@ -95,6 +97,7 @@
   /// </summary>
   public sealed partial class BoolValue : pb::IMessage<BoolValue> {
     private static readonly pb::MessageParser<BoolValue> _parser = new pb::MessageParser<BoolValue>(() => new BoolValue());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<BoolValue> Parser { get { return _parser; } }
 
@@ -118,6 +121,7 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public BoolValue(BoolValue other) : this() {
       value_ = other.value_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -153,13 +157,16 @@
         return true;
       }
       if (Value != other.Value) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
       if (Value != false) hash ^= Value.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -174,6 +181,9 @@
         output.WriteRawTag(8);
         output.WriteBool(Value);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -182,6 +192,9 @@
       if (Value != false) {
         size += 1 + 1;
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -193,6 +206,7 @@
       if (other.Value != false) {
         Value = other.Value;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -201,7 +215,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 8: {
             Value = input.ReadBool();
@@ -218,6 +232,7 @@
   /// </summary>
   public sealed partial class Payload : pb::IMessage<Payload> {
     private static readonly pb::MessageParser<Payload> _parser = new pb::MessageParser<Payload>(() => new Payload());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<Payload> Parser { get { return _parser; } }
 
@@ -242,6 +257,7 @@
     public Payload(Payload other) : this() {
       type_ = other.type_;
       body_ = other.body_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -293,7 +309,7 @@
       }
       if (Type != other.Type) return false;
       if (Body != other.Body) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -301,6 +317,9 @@
       int hash = 1;
       if (Type != 0) hash ^= Type.GetHashCode();
       if (Body.Length != 0) hash ^= Body.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -319,6 +338,9 @@
         output.WriteRawTag(18);
         output.WriteBytes(Body);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -330,6 +352,9 @@
       if (Body.Length != 0) {
         size += 1 + pb::CodedOutputStream.ComputeBytesSize(Body);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -344,6 +369,7 @@
       if (other.Body.Length != 0) {
         Body = other.Body;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -352,7 +378,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 8: {
             type_ = (global::Grpc.Testing.PayloadType) input.ReadEnum();
@@ -374,6 +400,7 @@
   /// </summary>
   public sealed partial class EchoStatus : pb::IMessage<EchoStatus> {
     private static readonly pb::MessageParser<EchoStatus> _parser = new pb::MessageParser<EchoStatus>(() => new EchoStatus());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<EchoStatus> Parser { get { return _parser; } }
 
@@ -398,6 +425,7 @@
     public EchoStatus(EchoStatus other) : this() {
       code_ = other.code_;
       message_ = other.message_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -442,7 +470,7 @@
       }
       if (Code != other.Code) return false;
       if (Message != other.Message) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -450,6 +478,9 @@
       int hash = 1;
       if (Code != 0) hash ^= Code.GetHashCode();
       if (Message.Length != 0) hash ^= Message.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -468,6 +499,9 @@
         output.WriteRawTag(18);
         output.WriteString(Message);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -479,6 +513,9 @@
       if (Message.Length != 0) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(Message);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -493,6 +530,7 @@
       if (other.Message.Length != 0) {
         Message = other.Message;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -501,7 +539,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 8: {
             Code = input.ReadInt32();
@@ -522,6 +560,7 @@
   /// </summary>
   public sealed partial class SimpleRequest : pb::IMessage<SimpleRequest> {
     private static readonly pb::MessageParser<SimpleRequest> _parser = new pb::MessageParser<SimpleRequest>(() => new SimpleRequest());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<SimpleRequest> Parser { get { return _parser; } }
 
@@ -552,6 +591,7 @@
       ResponseCompressed = other.responseCompressed_ != null ? other.ResponseCompressed.Clone() : null;
       ResponseStatus = other.responseStatus_ != null ? other.ResponseStatus.Clone() : null;
       ExpectCompressed = other.expectCompressed_ != null ? other.ExpectCompressed.Clone() : null;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -697,7 +737,7 @@
       if (!object.Equals(ResponseCompressed, other.ResponseCompressed)) return false;
       if (!object.Equals(ResponseStatus, other.ResponseStatus)) return false;
       if (!object.Equals(ExpectCompressed, other.ExpectCompressed)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -711,6 +751,9 @@
       if (responseCompressed_ != null) hash ^= ResponseCompressed.GetHashCode();
       if (responseStatus_ != null) hash ^= ResponseStatus.GetHashCode();
       if (expectCompressed_ != null) hash ^= ExpectCompressed.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -753,6 +796,9 @@
         output.WriteRawTag(66);
         output.WriteMessage(ExpectCompressed);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -782,6 +828,9 @@
       if (expectCompressed_ != null) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(ExpectCompressed);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -826,6 +875,7 @@
         }
         ExpectCompressed.MergeFrom(other.ExpectCompressed);
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -834,7 +884,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 8: {
             responseType_ = (global::Grpc.Testing.PayloadType) input.ReadEnum();
@@ -891,6 +941,7 @@
   /// </summary>
   public sealed partial class SimpleResponse : pb::IMessage<SimpleResponse> {
     private static readonly pb::MessageParser<SimpleResponse> _parser = new pb::MessageParser<SimpleResponse>(() => new SimpleResponse());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<SimpleResponse> Parser { get { return _parser; } }
 
@@ -916,6 +967,7 @@
       Payload = other.payload_ != null ? other.Payload.Clone() : null;
       username_ = other.username_;
       oauthScope_ = other.oauthScope_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -982,7 +1034,7 @@
       if (!object.Equals(Payload, other.Payload)) return false;
       if (Username != other.Username) return false;
       if (OauthScope != other.OauthScope) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -991,6 +1043,9 @@
       if (payload_ != null) hash ^= Payload.GetHashCode();
       if (Username.Length != 0) hash ^= Username.GetHashCode();
       if (OauthScope.Length != 0) hash ^= OauthScope.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -1013,6 +1068,9 @@
         output.WriteRawTag(26);
         output.WriteString(OauthScope);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1027,6 +1085,9 @@
       if (OauthScope.Length != 0) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(OauthScope);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -1047,6 +1108,7 @@
       if (other.OauthScope.Length != 0) {
         OauthScope = other.OauthScope;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1055,7 +1117,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             if (payload_ == null) {
@@ -1083,6 +1145,7 @@
   /// </summary>
   public sealed partial class StreamingInputCallRequest : pb::IMessage<StreamingInputCallRequest> {
     private static readonly pb::MessageParser<StreamingInputCallRequest> _parser = new pb::MessageParser<StreamingInputCallRequest>(() => new StreamingInputCallRequest());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<StreamingInputCallRequest> Parser { get { return _parser; } }
 
@@ -1107,6 +1170,7 @@
     public StreamingInputCallRequest(StreamingInputCallRequest other) : this() {
       Payload = other.payload_ != null ? other.Payload.Clone() : null;
       ExpectCompressed = other.expectCompressed_ != null ? other.ExpectCompressed.Clone() : null;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1160,7 +1224,7 @@
       }
       if (!object.Equals(Payload, other.Payload)) return false;
       if (!object.Equals(ExpectCompressed, other.ExpectCompressed)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1168,6 +1232,9 @@
       int hash = 1;
       if (payload_ != null) hash ^= Payload.GetHashCode();
       if (expectCompressed_ != null) hash ^= ExpectCompressed.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -1186,6 +1253,9 @@
         output.WriteRawTag(18);
         output.WriteMessage(ExpectCompressed);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1197,6 +1267,9 @@
       if (expectCompressed_ != null) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(ExpectCompressed);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -1217,6 +1290,7 @@
         }
         ExpectCompressed.MergeFrom(other.ExpectCompressed);
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1225,7 +1299,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             if (payload_ == null) {
@@ -1252,6 +1326,7 @@
   /// </summary>
   public sealed partial class StreamingInputCallResponse : pb::IMessage<StreamingInputCallResponse> {
     private static readonly pb::MessageParser<StreamingInputCallResponse> _parser = new pb::MessageParser<StreamingInputCallResponse>(() => new StreamingInputCallResponse());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<StreamingInputCallResponse> Parser { get { return _parser; } }
 
@@ -1275,6 +1350,7 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public StreamingInputCallResponse(StreamingInputCallResponse other) : this() {
       aggregatedPayloadSize_ = other.aggregatedPayloadSize_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1310,13 +1386,16 @@
         return true;
       }
       if (AggregatedPayloadSize != other.AggregatedPayloadSize) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
       if (AggregatedPayloadSize != 0) hash ^= AggregatedPayloadSize.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -1331,6 +1410,9 @@
         output.WriteRawTag(8);
         output.WriteInt32(AggregatedPayloadSize);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1339,6 +1421,9 @@
       if (AggregatedPayloadSize != 0) {
         size += 1 + pb::CodedOutputStream.ComputeInt32Size(AggregatedPayloadSize);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -1350,6 +1435,7 @@
       if (other.AggregatedPayloadSize != 0) {
         AggregatedPayloadSize = other.AggregatedPayloadSize;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1358,7 +1444,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 8: {
             AggregatedPayloadSize = input.ReadInt32();
@@ -1375,6 +1461,7 @@
   /// </summary>
   public sealed partial class ResponseParameters : pb::IMessage<ResponseParameters> {
     private static readonly pb::MessageParser<ResponseParameters> _parser = new pb::MessageParser<ResponseParameters>(() => new ResponseParameters());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<ResponseParameters> Parser { get { return _parser; } }
 
@@ -1400,6 +1487,7 @@
       size_ = other.size_;
       intervalUs_ = other.intervalUs_;
       Compressed = other.compressed_ != null ? other.Compressed.Clone() : null;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1469,7 +1557,7 @@
       if (Size != other.Size) return false;
       if (IntervalUs != other.IntervalUs) return false;
       if (!object.Equals(Compressed, other.Compressed)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1478,6 +1566,9 @@
       if (Size != 0) hash ^= Size.GetHashCode();
       if (IntervalUs != 0) hash ^= IntervalUs.GetHashCode();
       if (compressed_ != null) hash ^= Compressed.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -1500,6 +1591,9 @@
         output.WriteRawTag(26);
         output.WriteMessage(Compressed);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1514,6 +1608,9 @@
       if (compressed_ != null) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(Compressed);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -1534,6 +1631,7 @@
         }
         Compressed.MergeFrom(other.Compressed);
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1542,7 +1640,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 8: {
             Size = input.ReadInt32();
@@ -1570,6 +1668,7 @@
   /// </summary>
   public sealed partial class StreamingOutputCallRequest : pb::IMessage<StreamingOutputCallRequest> {
     private static readonly pb::MessageParser<StreamingOutputCallRequest> _parser = new pb::MessageParser<StreamingOutputCallRequest>(() => new StreamingOutputCallRequest());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<StreamingOutputCallRequest> Parser { get { return _parser; } }
 
@@ -1596,6 +1695,7 @@
       responseParameters_ = other.responseParameters_.Clone();
       Payload = other.payload_ != null ? other.Payload.Clone() : null;
       ResponseStatus = other.responseStatus_ != null ? other.ResponseStatus.Clone() : null;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1679,7 +1779,7 @@
       if(!responseParameters_.Equals(other.responseParameters_)) return false;
       if (!object.Equals(Payload, other.Payload)) return false;
       if (!object.Equals(ResponseStatus, other.ResponseStatus)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1689,6 +1789,9 @@
       hash ^= responseParameters_.GetHashCode();
       if (payload_ != null) hash ^= Payload.GetHashCode();
       if (responseStatus_ != null) hash ^= ResponseStatus.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -1712,6 +1815,9 @@
         output.WriteRawTag(58);
         output.WriteMessage(ResponseStatus);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1727,6 +1833,9 @@
       if (responseStatus_ != null) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(ResponseStatus);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -1751,6 +1860,7 @@
         }
         ResponseStatus.MergeFrom(other.ResponseStatus);
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1759,7 +1869,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 8: {
             responseType_ = (global::Grpc.Testing.PayloadType) input.ReadEnum();
@@ -1794,6 +1904,7 @@
   /// </summary>
   public sealed partial class StreamingOutputCallResponse : pb::IMessage<StreamingOutputCallResponse> {
     private static readonly pb::MessageParser<StreamingOutputCallResponse> _parser = new pb::MessageParser<StreamingOutputCallResponse>(() => new StreamingOutputCallResponse());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<StreamingOutputCallResponse> Parser { get { return _parser; } }
 
@@ -1817,6 +1928,7 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public StreamingOutputCallResponse(StreamingOutputCallResponse other) : this() {
       Payload = other.payload_ != null ? other.Payload.Clone() : null;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1852,13 +1964,16 @@
         return true;
       }
       if (!object.Equals(Payload, other.Payload)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
       if (payload_ != null) hash ^= Payload.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -1873,6 +1988,9 @@
         output.WriteRawTag(10);
         output.WriteMessage(Payload);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1881,6 +1999,9 @@
       if (payload_ != null) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(Payload);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -1895,6 +2016,7 @@
         }
         Payload.MergeFrom(other.Payload);
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1903,7 +2025,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             if (payload_ == null) {
@@ -1924,6 +2046,7 @@
   /// </summary>
   public sealed partial class ReconnectParams : pb::IMessage<ReconnectParams> {
     private static readonly pb::MessageParser<ReconnectParams> _parser = new pb::MessageParser<ReconnectParams>(() => new ReconnectParams());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<ReconnectParams> Parser { get { return _parser; } }
 
@@ -1947,6 +2070,7 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public ReconnectParams(ReconnectParams other) : this() {
       maxReconnectBackoffMs_ = other.maxReconnectBackoffMs_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1979,13 +2103,16 @@
         return true;
       }
       if (MaxReconnectBackoffMs != other.MaxReconnectBackoffMs) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
       if (MaxReconnectBackoffMs != 0) hash ^= MaxReconnectBackoffMs.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -2000,6 +2127,9 @@
         output.WriteRawTag(8);
         output.WriteInt32(MaxReconnectBackoffMs);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2008,6 +2138,9 @@
       if (MaxReconnectBackoffMs != 0) {
         size += 1 + pb::CodedOutputStream.ComputeInt32Size(MaxReconnectBackoffMs);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -2019,6 +2152,7 @@
       if (other.MaxReconnectBackoffMs != 0) {
         MaxReconnectBackoffMs = other.MaxReconnectBackoffMs;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2027,7 +2161,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 8: {
             MaxReconnectBackoffMs = input.ReadInt32();
@@ -2046,6 +2180,7 @@
   /// </summary>
   public sealed partial class ReconnectInfo : pb::IMessage<ReconnectInfo> {
     private static readonly pb::MessageParser<ReconnectInfo> _parser = new pb::MessageParser<ReconnectInfo>(() => new ReconnectInfo());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<ReconnectInfo> Parser { get { return _parser; } }
 
@@ -2070,6 +2205,7 @@
     public ReconnectInfo(ReconnectInfo other) : this() {
       passed_ = other.passed_;
       backoffMs_ = other.backoffMs_.Clone();
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2113,7 +2249,7 @@
       }
       if (Passed != other.Passed) return false;
       if(!backoffMs_.Equals(other.backoffMs_)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2121,6 +2257,9 @@
       int hash = 1;
       if (Passed != false) hash ^= Passed.GetHashCode();
       hash ^= backoffMs_.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -2136,6 +2275,9 @@
         output.WriteBool(Passed);
       }
       backoffMs_.WriteTo(output, _repeated_backoffMs_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2145,6 +2287,9 @@
         size += 1 + 1;
       }
       size += backoffMs_.CalculateSize(_repeated_backoffMs_codec);
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -2157,6 +2302,7 @@
         Passed = other.Passed;
       }
       backoffMs_.Add(other.backoffMs_);
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -2165,7 +2311,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 8: {
             Passed = input.ReadBool();
diff --git a/src/csharp/Grpc.IntegrationTesting/Metrics.cs b/src/csharp/Grpc.IntegrationTesting/Metrics.cs
index 84eb09a..b5d8b87 100644
--- a/src/csharp/Grpc.IntegrationTesting/Metrics.cs
+++ b/src/csharp/Grpc.IntegrationTesting/Metrics.cs
@@ -1,5 +1,7 @@
-// Generated by the protocol buffer compiler.  DO NOT EDIT!
-// source: src/proto/grpc/testing/metrics.proto
+// <auto-generated>
+//     Generated by the protocol buffer compiler.  DO NOT EDIT!
+//     source: src/proto/grpc/testing/metrics.proto
+// </auto-generated>
 #pragma warning disable 1591, 0612, 3021
 #region Designer generated code
 
@@ -48,6 +50,7 @@
   /// </summary>
   public sealed partial class GaugeResponse : pb::IMessage<GaugeResponse> {
     private static readonly pb::MessageParser<GaugeResponse> _parser = new pb::MessageParser<GaugeResponse>(() => new GaugeResponse());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<GaugeResponse> Parser { get { return _parser; } }
 
@@ -83,6 +86,7 @@
           break;
       }
 
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -169,10 +173,10 @@
       }
       if (Name != other.Name) return false;
       if (LongValue != other.LongValue) return false;
-      if (DoubleValue != other.DoubleValue) return false;
+      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleValue, other.DoubleValue)) return false;
       if (StringValue != other.StringValue) return false;
       if (ValueCase != other.ValueCase) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -180,9 +184,12 @@
       int hash = 1;
       if (Name.Length != 0) hash ^= Name.GetHashCode();
       if (valueCase_ == ValueOneofCase.LongValue) hash ^= LongValue.GetHashCode();
-      if (valueCase_ == ValueOneofCase.DoubleValue) hash ^= DoubleValue.GetHashCode();
+      if (valueCase_ == ValueOneofCase.DoubleValue) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleValue);
       if (valueCase_ == ValueOneofCase.StringValue) hash ^= StringValue.GetHashCode();
       hash ^= (int) valueCase_;
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -209,6 +216,9 @@
         output.WriteRawTag(34);
         output.WriteString(StringValue);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -226,6 +236,9 @@
       if (valueCase_ == ValueOneofCase.StringValue) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(StringValue);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -249,6 +262,7 @@
           break;
       }
 
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -257,7 +271,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             Name = input.ReadString();
@@ -286,6 +300,7 @@
   /// </summary>
   public sealed partial class GaugeRequest : pb::IMessage<GaugeRequest> {
     private static readonly pb::MessageParser<GaugeRequest> _parser = new pb::MessageParser<GaugeRequest>(() => new GaugeRequest());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<GaugeRequest> Parser { get { return _parser; } }
 
@@ -309,6 +324,7 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public GaugeRequest(GaugeRequest other) : this() {
       name_ = other.name_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -341,13 +357,16 @@
         return true;
       }
       if (Name != other.Name) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
       if (Name.Length != 0) hash ^= Name.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -362,6 +381,9 @@
         output.WriteRawTag(10);
         output.WriteString(Name);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -370,6 +392,9 @@
       if (Name.Length != 0) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -381,6 +406,7 @@
       if (other.Name.Length != 0) {
         Name = other.Name;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -389,7 +415,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             Name = input.ReadString();
@@ -403,6 +429,7 @@
 
   public sealed partial class EmptyMessage : pb::IMessage<EmptyMessage> {
     private static readonly pb::MessageParser<EmptyMessage> _parser = new pb::MessageParser<EmptyMessage>(() => new EmptyMessage());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<EmptyMessage> Parser { get { return _parser; } }
 
@@ -425,6 +452,7 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public EmptyMessage(EmptyMessage other) : this() {
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -445,12 +473,15 @@
       if (ReferenceEquals(other, this)) {
         return true;
       }
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -461,11 +492,17 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public void WriteTo(pb::CodedOutputStream output) {
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public int CalculateSize() {
       int size = 0;
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -474,6 +511,7 @@
       if (other == null) {
         return;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -482,7 +520,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
         }
       }
diff --git a/src/csharp/Grpc.IntegrationTesting/Payloads.cs b/src/csharp/Grpc.IntegrationTesting/Payloads.cs
index fca8cda..25f34ff 100644
--- a/src/csharp/Grpc.IntegrationTesting/Payloads.cs
+++ b/src/csharp/Grpc.IntegrationTesting/Payloads.cs
@@ -1,5 +1,7 @@
-// Generated by the protocol buffer compiler.  DO NOT EDIT!
-// source: src/proto/grpc/testing/payloads.proto
+// <auto-generated>
+//     Generated by the protocol buffer compiler.  DO NOT EDIT!
+//     source: src/proto/grpc/testing/payloads.proto
+// </auto-generated>
 #pragma warning disable 1591, 0612, 3021
 #region Designer generated code
 
@@ -46,6 +48,7 @@
   #region Messages
   public sealed partial class ByteBufferParams : pb::IMessage<ByteBufferParams> {
     private static readonly pb::MessageParser<ByteBufferParams> _parser = new pb::MessageParser<ByteBufferParams>(() => new ByteBufferParams());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<ByteBufferParams> Parser { get { return _parser; } }
 
@@ -70,6 +73,7 @@
     public ByteBufferParams(ByteBufferParams other) : this() {
       reqSize_ = other.reqSize_;
       respSize_ = other.respSize_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -114,7 +118,7 @@
       }
       if (ReqSize != other.ReqSize) return false;
       if (RespSize != other.RespSize) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -122,6 +126,9 @@
       int hash = 1;
       if (ReqSize != 0) hash ^= ReqSize.GetHashCode();
       if (RespSize != 0) hash ^= RespSize.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -140,6 +147,9 @@
         output.WriteRawTag(16);
         output.WriteInt32(RespSize);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -151,6 +161,9 @@
       if (RespSize != 0) {
         size += 1 + pb::CodedOutputStream.ComputeInt32Size(RespSize);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -165,6 +178,7 @@
       if (other.RespSize != 0) {
         RespSize = other.RespSize;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -173,7 +187,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 8: {
             ReqSize = input.ReadInt32();
@@ -191,6 +205,7 @@
 
   public sealed partial class SimpleProtoParams : pb::IMessage<SimpleProtoParams> {
     private static readonly pb::MessageParser<SimpleProtoParams> _parser = new pb::MessageParser<SimpleProtoParams>(() => new SimpleProtoParams());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<SimpleProtoParams> Parser { get { return _parser; } }
 
@@ -215,6 +230,7 @@
     public SimpleProtoParams(SimpleProtoParams other) : this() {
       reqSize_ = other.reqSize_;
       respSize_ = other.respSize_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -259,7 +275,7 @@
       }
       if (ReqSize != other.ReqSize) return false;
       if (RespSize != other.RespSize) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -267,6 +283,9 @@
       int hash = 1;
       if (ReqSize != 0) hash ^= ReqSize.GetHashCode();
       if (RespSize != 0) hash ^= RespSize.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -285,6 +304,9 @@
         output.WriteRawTag(16);
         output.WriteInt32(RespSize);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -296,6 +318,9 @@
       if (RespSize != 0) {
         size += 1 + pb::CodedOutputStream.ComputeInt32Size(RespSize);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -310,6 +335,7 @@
       if (other.RespSize != 0) {
         RespSize = other.RespSize;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -318,7 +344,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 8: {
             ReqSize = input.ReadInt32();
@@ -340,6 +366,7 @@
   /// </summary>
   public sealed partial class ComplexProtoParams : pb::IMessage<ComplexProtoParams> {
     private static readonly pb::MessageParser<ComplexProtoParams> _parser = new pb::MessageParser<ComplexProtoParams>(() => new ComplexProtoParams());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<ComplexProtoParams> Parser { get { return _parser; } }
 
@@ -362,6 +389,7 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public ComplexProtoParams(ComplexProtoParams other) : this() {
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -382,12 +410,15 @@
       if (ReferenceEquals(other, this)) {
         return true;
       }
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -398,11 +429,17 @@
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public void WriteTo(pb::CodedOutputStream output) {
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public int CalculateSize() {
       int size = 0;
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -411,6 +448,7 @@
       if (other == null) {
         return;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -419,7 +457,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
         }
       }
@@ -429,6 +467,7 @@
 
   public sealed partial class PayloadConfig : pb::IMessage<PayloadConfig> {
     private static readonly pb::MessageParser<PayloadConfig> _parser = new pb::MessageParser<PayloadConfig>(() => new PayloadConfig());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<PayloadConfig> Parser { get { return _parser; } }
 
@@ -463,6 +502,7 @@
           break;
       }
 
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -540,7 +580,7 @@
       if (!object.Equals(SimpleParams, other.SimpleParams)) return false;
       if (!object.Equals(ComplexParams, other.ComplexParams)) return false;
       if (PayloadCase != other.PayloadCase) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -550,6 +590,9 @@
       if (payloadCase_ == PayloadOneofCase.SimpleParams) hash ^= SimpleParams.GetHashCode();
       if (payloadCase_ == PayloadOneofCase.ComplexParams) hash ^= ComplexParams.GetHashCode();
       hash ^= (int) payloadCase_;
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -572,6 +615,9 @@
         output.WriteRawTag(26);
         output.WriteMessage(ComplexParams);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -586,6 +632,9 @@
       if (payloadCase_ == PayloadOneofCase.ComplexParams) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(ComplexParams);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -615,6 +664,7 @@
           break;
       }
 
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -623,7 +673,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             global::Grpc.Testing.ByteBufferParams subBuilder = new global::Grpc.Testing.ByteBufferParams();
diff --git a/src/csharp/Grpc.IntegrationTesting/ReportQpsScenarioService.cs b/src/csharp/Grpc.IntegrationTesting/ReportQpsScenarioService.cs
new file mode 100644
index 0000000..707c443
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/ReportQpsScenarioService.cs
@@ -0,0 +1,41 @@
+// <auto-generated>
+//     Generated by the protocol buffer compiler.  DO NOT EDIT!
+//     source: src/proto/grpc/testing/report_qps_scenario_service.proto
+// </auto-generated>
+#pragma warning disable 1591, 0612, 3021
+#region Designer generated code
+
+using pb = global::Google.Protobuf;
+using pbc = global::Google.Protobuf.Collections;
+using pbr = global::Google.Protobuf.Reflection;
+using scg = global::System.Collections.Generic;
+namespace Grpc.Testing {
+
+  /// <summary>Holder for reflection information generated from src/proto/grpc/testing/report_qps_scenario_service.proto</summary>
+  public static partial class ReportQpsScenarioServiceReflection {
+
+    #region Descriptor
+    /// <summary>File descriptor for src/proto/grpc/testing/report_qps_scenario_service.proto</summary>
+    public static pbr::FileDescriptor Descriptor {
+      get { return descriptor; }
+    }
+    private static pbr::FileDescriptor descriptor;
+
+    static ReportQpsScenarioServiceReflection() {
+      byte[] descriptorData = global::System.Convert.FromBase64String(
+          string.Concat(
+            "CjhzcmMvcHJvdG8vZ3JwYy90ZXN0aW5nL3JlcG9ydF9xcHNfc2NlbmFyaW9f",
+            "c2VydmljZS5wcm90bxIMZ3JwYy50ZXN0aW5nGiRzcmMvcHJvdG8vZ3JwYy90",
+            "ZXN0aW5nL2NvbnRyb2wucHJvdG8yXgoYUmVwb3J0UXBzU2NlbmFyaW9TZXJ2",
+            "aWNlEkIKDlJlcG9ydFNjZW5hcmlvEhwuZ3JwYy50ZXN0aW5nLlNjZW5hcmlv",
+            "UmVzdWx0GhIuZ3JwYy50ZXN0aW5nLlZvaWRiBnByb3RvMw=="));
+      descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
+          new pbr::FileDescriptor[] { global::Grpc.Testing.ControlReflection.Descriptor, },
+          new pbr::GeneratedClrTypeInfo(null, null));
+    }
+    #endregion
+
+  }
+}
+
+#endregion Designer generated code
diff --git a/src/csharp/Grpc.IntegrationTesting/ReportQpsScenarioServiceGrpc.cs b/src/csharp/Grpc.IntegrationTesting/ReportQpsScenarioServiceGrpc.cs
new file mode 100644
index 0000000..c9c6f75
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/ReportQpsScenarioServiceGrpc.cs
@@ -0,0 +1,148 @@
+// <auto-generated>
+//     Generated by the protocol buffer compiler.  DO NOT EDIT!
+//     source: src/proto/grpc/testing/report_qps_scenario_service.proto
+// </auto-generated>
+// Original file comments:
+// Copyright 2015 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.
+//
+// An integration test service that covers all the method signature permutations
+// of unary/streaming requests/responses.
+#pragma warning disable 1591
+#region Designer generated code
+
+using grpc = global::Grpc.Core;
+
+namespace Grpc.Testing {
+  public static partial class ReportQpsScenarioService
+  {
+    static readonly string __ServiceName = "grpc.testing.ReportQpsScenarioService";
+
+    static readonly grpc::Marshaller<global::Grpc.Testing.ScenarioResult> __Marshaller_ScenarioResult = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.ScenarioResult.Parser.ParseFrom);
+    static readonly grpc::Marshaller<global::Grpc.Testing.Void> __Marshaller_Void = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.Void.Parser.ParseFrom);
+
+    static readonly grpc::Method<global::Grpc.Testing.ScenarioResult, global::Grpc.Testing.Void> __Method_ReportScenario = new grpc::Method<global::Grpc.Testing.ScenarioResult, global::Grpc.Testing.Void>(
+        grpc::MethodType.Unary,
+        __ServiceName,
+        "ReportScenario",
+        __Marshaller_ScenarioResult,
+        __Marshaller_Void);
+
+    /// <summary>Service descriptor</summary>
+    public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
+    {
+      get { return global::Grpc.Testing.ReportQpsScenarioServiceReflection.Descriptor.Services[0]; }
+    }
+
+    /// <summary>Base class for server-side implementations of ReportQpsScenarioService</summary>
+    public abstract partial class ReportQpsScenarioServiceBase
+    {
+      /// <summary>
+      /// Report results of a QPS test benchmark scenario.
+      /// </summary>
+      /// <param name="request">The request received from the client.</param>
+      /// <param name="context">The context of the server-side call handler being invoked.</param>
+      /// <returns>The response to send back to the client (wrapped by a task).</returns>
+      public virtual global::System.Threading.Tasks.Task<global::Grpc.Testing.Void> ReportScenario(global::Grpc.Testing.ScenarioResult request, grpc::ServerCallContext context)
+      {
+        throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
+      }
+
+    }
+
+    /// <summary>Client for ReportQpsScenarioService</summary>
+    public partial class ReportQpsScenarioServiceClient : grpc::ClientBase<ReportQpsScenarioServiceClient>
+    {
+      /// <summary>Creates a new client for ReportQpsScenarioService</summary>
+      /// <param name="channel">The channel to use to make remote calls.</param>
+      public ReportQpsScenarioServiceClient(grpc::Channel channel) : base(channel)
+      {
+      }
+      /// <summary>Creates a new client for ReportQpsScenarioService that uses a custom <c>CallInvoker</c>.</summary>
+      /// <param name="callInvoker">The callInvoker to use to make remote calls.</param>
+      public ReportQpsScenarioServiceClient(grpc::CallInvoker callInvoker) : base(callInvoker)
+      {
+      }
+      /// <summary>Protected parameterless constructor to allow creation of test doubles.</summary>
+      protected ReportQpsScenarioServiceClient() : base()
+      {
+      }
+      /// <summary>Protected constructor to allow creation of configured clients.</summary>
+      /// <param name="configuration">The client configuration.</param>
+      protected ReportQpsScenarioServiceClient(ClientBaseConfiguration configuration) : base(configuration)
+      {
+      }
+
+      /// <summary>
+      /// Report results of a QPS test benchmark scenario.
+      /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
+      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
+      /// <param name="cancellationToken">An optional token for canceling the call.</param>
+      /// <returns>The response received from the server.</returns>
+      public virtual global::Grpc.Testing.Void ReportScenario(global::Grpc.Testing.ScenarioResult request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
+      {
+        return ReportScenario(request, new grpc::CallOptions(headers, deadline, cancellationToken));
+      }
+      /// <summary>
+      /// Report results of a QPS test benchmark scenario.
+      /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="options">The options for the call.</param>
+      /// <returns>The response received from the server.</returns>
+      public virtual global::Grpc.Testing.Void ReportScenario(global::Grpc.Testing.ScenarioResult request, grpc::CallOptions options)
+      {
+        return CallInvoker.BlockingUnaryCall(__Method_ReportScenario, null, options, request);
+      }
+      /// <summary>
+      /// Report results of a QPS test benchmark scenario.
+      /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
+      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
+      /// <param name="cancellationToken">An optional token for canceling the call.</param>
+      /// <returns>The call object.</returns>
+      public virtual grpc::AsyncUnaryCall<global::Grpc.Testing.Void> ReportScenarioAsync(global::Grpc.Testing.ScenarioResult request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
+      {
+        return ReportScenarioAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken));
+      }
+      /// <summary>
+      /// Report results of a QPS test benchmark scenario.
+      /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="options">The options for the call.</param>
+      /// <returns>The call object.</returns>
+      public virtual grpc::AsyncUnaryCall<global::Grpc.Testing.Void> ReportScenarioAsync(global::Grpc.Testing.ScenarioResult request, grpc::CallOptions options)
+      {
+        return CallInvoker.AsyncUnaryCall(__Method_ReportScenario, null, options, request);
+      }
+      /// <summary>Creates a new instance of client from given <c>ClientBaseConfiguration</c>.</summary>
+      protected override ReportQpsScenarioServiceClient NewInstance(ClientBaseConfiguration configuration)
+      {
+        return new ReportQpsScenarioServiceClient(configuration);
+      }
+    }
+
+    /// <summary>Creates service definition that can be registered with a server</summary>
+    /// <param name="serviceImpl">An object implementing the server-side handling logic.</param>
+    public static grpc::ServerServiceDefinition BindService(ReportQpsScenarioServiceBase serviceImpl)
+    {
+      return grpc::ServerServiceDefinition.CreateBuilder()
+          .AddMethod(__Method_ReportScenario, serviceImpl.ReportScenario).Build();
+    }
+
+  }
+}
+#endregion
diff --git a/src/csharp/Grpc.IntegrationTesting/Services.cs b/src/csharp/Grpc.IntegrationTesting/Services.cs
deleted file mode 100644
index 4b76170..0000000
--- a/src/csharp/Grpc.IntegrationTesting/Services.cs
+++ /dev/null
@@ -1,55 +0,0 @@
-// Generated by the protocol buffer compiler.  DO NOT EDIT!
-// source: src/proto/grpc/testing/services.proto
-#pragma warning disable 1591, 0612, 3021
-#region Designer generated code
-
-using pb = global::Google.Protobuf;
-using pbc = global::Google.Protobuf.Collections;
-using pbr = global::Google.Protobuf.Reflection;
-using scg = global::System.Collections.Generic;
-namespace Grpc.Testing {
-
-  /// <summary>Holder for reflection information generated from src/proto/grpc/testing/services.proto</summary>
-  public static partial class ServicesReflection {
-
-    #region Descriptor
-    /// <summary>File descriptor for src/proto/grpc/testing/services.proto</summary>
-    public static pbr::FileDescriptor Descriptor {
-      get { return descriptor; }
-    }
-    private static pbr::FileDescriptor descriptor;
-
-    static ServicesReflection() {
-      byte[] descriptorData = global::System.Convert.FromBase64String(
-          string.Concat(
-            "CiVzcmMvcHJvdG8vZ3JwYy90ZXN0aW5nL3NlcnZpY2VzLnByb3RvEgxncnBj",
-            "LnRlc3RpbmcaJXNyYy9wcm90by9ncnBjL3Rlc3RpbmcvbWVzc2FnZXMucHJv",
-            "dG8aJHNyYy9wcm90by9ncnBjL3Rlc3RpbmcvY29udHJvbC5wcm90bzKmAwoQ",
-            "QmVuY2htYXJrU2VydmljZRJGCglVbmFyeUNhbGwSGy5ncnBjLnRlc3Rpbmcu",
-            "U2ltcGxlUmVxdWVzdBocLmdycGMudGVzdGluZy5TaW1wbGVSZXNwb25zZRJO",
-            "Cg1TdHJlYW1pbmdDYWxsEhsuZ3JwYy50ZXN0aW5nLlNpbXBsZVJlcXVlc3Qa",
-            "HC5ncnBjLnRlc3RpbmcuU2ltcGxlUmVzcG9uc2UoATABElIKE1N0cmVhbWlu",
-            "Z0Zyb21DbGllbnQSGy5ncnBjLnRlc3RpbmcuU2ltcGxlUmVxdWVzdBocLmdy",
-            "cGMudGVzdGluZy5TaW1wbGVSZXNwb25zZSgBElIKE1N0cmVhbWluZ0Zyb21T",
-            "ZXJ2ZXISGy5ncnBjLnRlc3RpbmcuU2ltcGxlUmVxdWVzdBocLmdycGMudGVz",
-            "dGluZy5TaW1wbGVSZXNwb25zZTABElIKEVN0cmVhbWluZ0JvdGhXYXlzEhsu",
-            "Z3JwYy50ZXN0aW5nLlNpbXBsZVJlcXVlc3QaHC5ncnBjLnRlc3RpbmcuU2lt",
-            "cGxlUmVzcG9uc2UoATABMpcCCg1Xb3JrZXJTZXJ2aWNlEkUKCVJ1blNlcnZl",
-            "chIYLmdycGMudGVzdGluZy5TZXJ2ZXJBcmdzGhouZ3JwYy50ZXN0aW5nLlNl",
-            "cnZlclN0YXR1cygBMAESRQoJUnVuQ2xpZW50EhguZ3JwYy50ZXN0aW5nLkNs",
-            "aWVudEFyZ3MaGi5ncnBjLnRlc3RpbmcuQ2xpZW50U3RhdHVzKAEwARJCCglD",
-            "b3JlQ291bnQSGS5ncnBjLnRlc3RpbmcuQ29yZVJlcXVlc3QaGi5ncnBjLnRl",
-            "c3RpbmcuQ29yZVJlc3BvbnNlEjQKClF1aXRXb3JrZXISEi5ncnBjLnRlc3Rp",
-            "bmcuVm9pZBoSLmdycGMudGVzdGluZy5Wb2lkMl4KGFJlcG9ydFFwc1NjZW5h",
-            "cmlvU2VydmljZRJCCg5SZXBvcnRTY2VuYXJpbxIcLmdycGMudGVzdGluZy5T",
-            "Y2VuYXJpb1Jlc3VsdBoSLmdycGMudGVzdGluZy5Wb2lkYgZwcm90bzM="));
-      descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
-          new pbr::FileDescriptor[] { global::Grpc.Testing.MessagesReflection.Descriptor, global::Grpc.Testing.ControlReflection.Descriptor, },
-          new pbr::GeneratedClrTypeInfo(null, null));
-    }
-    #endregion
-
-  }
-}
-
-#endregion Designer generated code
diff --git a/src/csharp/Grpc.IntegrationTesting/ServicesGrpc.cs b/src/csharp/Grpc.IntegrationTesting/ServicesGrpc.cs
deleted file mode 100644
index 46b328a..0000000
--- a/src/csharp/Grpc.IntegrationTesting/ServicesGrpc.cs
+++ /dev/null
@@ -1,745 +0,0 @@
-// <auto-generated>
-//     Generated by the protocol buffer compiler.  DO NOT EDIT!
-//     source: src/proto/grpc/testing/services.proto
-// </auto-generated>
-// Original file comments:
-// Copyright 2015 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.
-//
-// An integration test service that covers all the method signature permutations
-// of unary/streaming requests/responses.
-#pragma warning disable 1591
-#region Designer generated code
-
-using grpc = global::Grpc.Core;
-
-namespace Grpc.Testing {
-  public static partial class BenchmarkService
-  {
-    static readonly string __ServiceName = "grpc.testing.BenchmarkService";
-
-    static readonly grpc::Marshaller<global::Grpc.Testing.SimpleRequest> __Marshaller_SimpleRequest = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.SimpleRequest.Parser.ParseFrom);
-    static readonly grpc::Marshaller<global::Grpc.Testing.SimpleResponse> __Marshaller_SimpleResponse = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.SimpleResponse.Parser.ParseFrom);
-
-    static readonly grpc::Method<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> __Method_UnaryCall = new grpc::Method<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse>(
-        grpc::MethodType.Unary,
-        __ServiceName,
-        "UnaryCall",
-        __Marshaller_SimpleRequest,
-        __Marshaller_SimpleResponse);
-
-    static readonly grpc::Method<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> __Method_StreamingCall = new grpc::Method<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse>(
-        grpc::MethodType.DuplexStreaming,
-        __ServiceName,
-        "StreamingCall",
-        __Marshaller_SimpleRequest,
-        __Marshaller_SimpleResponse);
-
-    static readonly grpc::Method<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> __Method_StreamingFromClient = new grpc::Method<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse>(
-        grpc::MethodType.ClientStreaming,
-        __ServiceName,
-        "StreamingFromClient",
-        __Marshaller_SimpleRequest,
-        __Marshaller_SimpleResponse);
-
-    static readonly grpc::Method<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> __Method_StreamingFromServer = new grpc::Method<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse>(
-        grpc::MethodType.ServerStreaming,
-        __ServiceName,
-        "StreamingFromServer",
-        __Marshaller_SimpleRequest,
-        __Marshaller_SimpleResponse);
-
-    static readonly grpc::Method<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> __Method_StreamingBothWays = new grpc::Method<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse>(
-        grpc::MethodType.DuplexStreaming,
-        __ServiceName,
-        "StreamingBothWays",
-        __Marshaller_SimpleRequest,
-        __Marshaller_SimpleResponse);
-
-    /// <summary>Service descriptor</summary>
-    public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
-    {
-      get { return global::Grpc.Testing.ServicesReflection.Descriptor.Services[0]; }
-    }
-
-    /// <summary>Base class for server-side implementations of BenchmarkService</summary>
-    public abstract partial class BenchmarkServiceBase
-    {
-      /// <summary>
-      /// One request followed by one response.
-      /// The server returns the client payload as-is.
-      /// </summary>
-      /// <param name="request">The request received from the client.</param>
-      /// <param name="context">The context of the server-side call handler being invoked.</param>
-      /// <returns>The response to send back to the client (wrapped by a task).</returns>
-      public virtual global::System.Threading.Tasks.Task<global::Grpc.Testing.SimpleResponse> UnaryCall(global::Grpc.Testing.SimpleRequest request, grpc::ServerCallContext context)
-      {
-        throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
-      }
-
-      /// <summary>
-      /// Repeated sequence of one request followed by one response.
-      /// Should be called streaming ping-pong
-      /// The server returns the client payload as-is on each response
-      /// </summary>
-      /// <param name="requestStream">Used for reading requests from the client.</param>
-      /// <param name="responseStream">Used for sending responses back to the client.</param>
-      /// <param name="context">The context of the server-side call handler being invoked.</param>
-      /// <returns>A task indicating completion of the handler.</returns>
-      public virtual global::System.Threading.Tasks.Task StreamingCall(grpc::IAsyncStreamReader<global::Grpc.Testing.SimpleRequest> requestStream, grpc::IServerStreamWriter<global::Grpc.Testing.SimpleResponse> responseStream, grpc::ServerCallContext context)
-      {
-        throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
-      }
-
-      /// <summary>
-      /// Single-sided unbounded streaming from client to server
-      /// The server returns the client payload as-is once the client does WritesDone
-      /// </summary>
-      /// <param name="requestStream">Used for reading requests from the client.</param>
-      /// <param name="context">The context of the server-side call handler being invoked.</param>
-      /// <returns>The response to send back to the client (wrapped by a task).</returns>
-      public virtual global::System.Threading.Tasks.Task<global::Grpc.Testing.SimpleResponse> StreamingFromClient(grpc::IAsyncStreamReader<global::Grpc.Testing.SimpleRequest> requestStream, grpc::ServerCallContext context)
-      {
-        throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
-      }
-
-      /// <summary>
-      /// Single-sided unbounded streaming from server to client
-      /// The server repeatedly returns the client payload as-is
-      /// </summary>
-      /// <param name="request">The request received from the client.</param>
-      /// <param name="responseStream">Used for sending responses back to the client.</param>
-      /// <param name="context">The context of the server-side call handler being invoked.</param>
-      /// <returns>A task indicating completion of the handler.</returns>
-      public virtual global::System.Threading.Tasks.Task StreamingFromServer(global::Grpc.Testing.SimpleRequest request, grpc::IServerStreamWriter<global::Grpc.Testing.SimpleResponse> responseStream, grpc::ServerCallContext context)
-      {
-        throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
-      }
-
-      /// <summary>
-      /// Two-sided unbounded streaming between server to client
-      /// Both sides send the content of their own choice to the other
-      /// </summary>
-      /// <param name="requestStream">Used for reading requests from the client.</param>
-      /// <param name="responseStream">Used for sending responses back to the client.</param>
-      /// <param name="context">The context of the server-side call handler being invoked.</param>
-      /// <returns>A task indicating completion of the handler.</returns>
-      public virtual global::System.Threading.Tasks.Task StreamingBothWays(grpc::IAsyncStreamReader<global::Grpc.Testing.SimpleRequest> requestStream, grpc::IServerStreamWriter<global::Grpc.Testing.SimpleResponse> responseStream, grpc::ServerCallContext context)
-      {
-        throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
-      }
-
-    }
-
-    /// <summary>Client for BenchmarkService</summary>
-    public partial class BenchmarkServiceClient : grpc::ClientBase<BenchmarkServiceClient>
-    {
-      /// <summary>Creates a new client for BenchmarkService</summary>
-      /// <param name="channel">The channel to use to make remote calls.</param>
-      public BenchmarkServiceClient(grpc::Channel channel) : base(channel)
-      {
-      }
-      /// <summary>Creates a new client for BenchmarkService that uses a custom <c>CallInvoker</c>.</summary>
-      /// <param name="callInvoker">The callInvoker to use to make remote calls.</param>
-      public BenchmarkServiceClient(grpc::CallInvoker callInvoker) : base(callInvoker)
-      {
-      }
-      /// <summary>Protected parameterless constructor to allow creation of test doubles.</summary>
-      protected BenchmarkServiceClient() : base()
-      {
-      }
-      /// <summary>Protected constructor to allow creation of configured clients.</summary>
-      /// <param name="configuration">The client configuration.</param>
-      protected BenchmarkServiceClient(ClientBaseConfiguration configuration) : base(configuration)
-      {
-      }
-
-      /// <summary>
-      /// One request followed by one response.
-      /// The server returns the client payload as-is.
-      /// </summary>
-      /// <param name="request">The request to send to the server.</param>
-      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
-      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
-      /// <param name="cancellationToken">An optional token for canceling the call.</param>
-      /// <returns>The response received from the server.</returns>
-      public virtual global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
-      {
-        return UnaryCall(request, new grpc::CallOptions(headers, deadline, cancellationToken));
-      }
-      /// <summary>
-      /// One request followed by one response.
-      /// The server returns the client payload as-is.
-      /// </summary>
-      /// <param name="request">The request to send to the server.</param>
-      /// <param name="options">The options for the call.</param>
-      /// <returns>The response received from the server.</returns>
-      public virtual global::Grpc.Testing.SimpleResponse UnaryCall(global::Grpc.Testing.SimpleRequest request, grpc::CallOptions options)
-      {
-        return CallInvoker.BlockingUnaryCall(__Method_UnaryCall, null, options, request);
-      }
-      /// <summary>
-      /// One request followed by one response.
-      /// The server returns the client payload as-is.
-      /// </summary>
-      /// <param name="request">The request to send to the server.</param>
-      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
-      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
-      /// <param name="cancellationToken">An optional token for canceling the call.</param>
-      /// <returns>The call object.</returns>
-      public virtual grpc::AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
-      {
-        return UnaryCallAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken));
-      }
-      /// <summary>
-      /// One request followed by one response.
-      /// The server returns the client payload as-is.
-      /// </summary>
-      /// <param name="request">The request to send to the server.</param>
-      /// <param name="options">The options for the call.</param>
-      /// <returns>The call object.</returns>
-      public virtual grpc::AsyncUnaryCall<global::Grpc.Testing.SimpleResponse> UnaryCallAsync(global::Grpc.Testing.SimpleRequest request, grpc::CallOptions options)
-      {
-        return CallInvoker.AsyncUnaryCall(__Method_UnaryCall, null, options, request);
-      }
-      /// <summary>
-      /// Repeated sequence of one request followed by one response.
-      /// Should be called streaming ping-pong
-      /// The server returns the client payload as-is on each response
-      /// </summary>
-      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
-      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
-      /// <param name="cancellationToken">An optional token for canceling the call.</param>
-      /// <returns>The call object.</returns>
-      public virtual grpc::AsyncDuplexStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingCall(grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
-      {
-        return StreamingCall(new grpc::CallOptions(headers, deadline, cancellationToken));
-      }
-      /// <summary>
-      /// Repeated sequence of one request followed by one response.
-      /// Should be called streaming ping-pong
-      /// The server returns the client payload as-is on each response
-      /// </summary>
-      /// <param name="options">The options for the call.</param>
-      /// <returns>The call object.</returns>
-      public virtual grpc::AsyncDuplexStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingCall(grpc::CallOptions options)
-      {
-        return CallInvoker.AsyncDuplexStreamingCall(__Method_StreamingCall, null, options);
-      }
-      /// <summary>
-      /// Single-sided unbounded streaming from client to server
-      /// The server returns the client payload as-is once the client does WritesDone
-      /// </summary>
-      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
-      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
-      /// <param name="cancellationToken">An optional token for canceling the call.</param>
-      /// <returns>The call object.</returns>
-      public virtual grpc::AsyncClientStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingFromClient(grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
-      {
-        return StreamingFromClient(new grpc::CallOptions(headers, deadline, cancellationToken));
-      }
-      /// <summary>
-      /// Single-sided unbounded streaming from client to server
-      /// The server returns the client payload as-is once the client does WritesDone
-      /// </summary>
-      /// <param name="options">The options for the call.</param>
-      /// <returns>The call object.</returns>
-      public virtual grpc::AsyncClientStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingFromClient(grpc::CallOptions options)
-      {
-        return CallInvoker.AsyncClientStreamingCall(__Method_StreamingFromClient, null, options);
-      }
-      /// <summary>
-      /// Single-sided unbounded streaming from server to client
-      /// The server repeatedly returns the client payload as-is
-      /// </summary>
-      /// <param name="request">The request to send to the server.</param>
-      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
-      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
-      /// <param name="cancellationToken">An optional token for canceling the call.</param>
-      /// <returns>The call object.</returns>
-      public virtual grpc::AsyncServerStreamingCall<global::Grpc.Testing.SimpleResponse> StreamingFromServer(global::Grpc.Testing.SimpleRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
-      {
-        return StreamingFromServer(request, new grpc::CallOptions(headers, deadline, cancellationToken));
-      }
-      /// <summary>
-      /// Single-sided unbounded streaming from server to client
-      /// The server repeatedly returns the client payload as-is
-      /// </summary>
-      /// <param name="request">The request to send to the server.</param>
-      /// <param name="options">The options for the call.</param>
-      /// <returns>The call object.</returns>
-      public virtual grpc::AsyncServerStreamingCall<global::Grpc.Testing.SimpleResponse> StreamingFromServer(global::Grpc.Testing.SimpleRequest request, grpc::CallOptions options)
-      {
-        return CallInvoker.AsyncServerStreamingCall(__Method_StreamingFromServer, null, options, request);
-      }
-      /// <summary>
-      /// Two-sided unbounded streaming between server to client
-      /// Both sides send the content of their own choice to the other
-      /// </summary>
-      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
-      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
-      /// <param name="cancellationToken">An optional token for canceling the call.</param>
-      /// <returns>The call object.</returns>
-      public virtual grpc::AsyncDuplexStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingBothWays(grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
-      {
-        return StreamingBothWays(new grpc::CallOptions(headers, deadline, cancellationToken));
-      }
-      /// <summary>
-      /// Two-sided unbounded streaming between server to client
-      /// Both sides send the content of their own choice to the other
-      /// </summary>
-      /// <param name="options">The options for the call.</param>
-      /// <returns>The call object.</returns>
-      public virtual grpc::AsyncDuplexStreamingCall<global::Grpc.Testing.SimpleRequest, global::Grpc.Testing.SimpleResponse> StreamingBothWays(grpc::CallOptions options)
-      {
-        return CallInvoker.AsyncDuplexStreamingCall(__Method_StreamingBothWays, null, options);
-      }
-      /// <summary>Creates a new instance of client from given <c>ClientBaseConfiguration</c>.</summary>
-      protected override BenchmarkServiceClient NewInstance(ClientBaseConfiguration configuration)
-      {
-        return new BenchmarkServiceClient(configuration);
-      }
-    }
-
-    /// <summary>Creates service definition that can be registered with a server</summary>
-    /// <param name="serviceImpl">An object implementing the server-side handling logic.</param>
-    public static grpc::ServerServiceDefinition BindService(BenchmarkServiceBase serviceImpl)
-    {
-      return grpc::ServerServiceDefinition.CreateBuilder()
-          .AddMethod(__Method_UnaryCall, serviceImpl.UnaryCall)
-          .AddMethod(__Method_StreamingCall, serviceImpl.StreamingCall)
-          .AddMethod(__Method_StreamingFromClient, serviceImpl.StreamingFromClient)
-          .AddMethod(__Method_StreamingFromServer, serviceImpl.StreamingFromServer)
-          .AddMethod(__Method_StreamingBothWays, serviceImpl.StreamingBothWays).Build();
-    }
-
-  }
-  public static partial class WorkerService
-  {
-    static readonly string __ServiceName = "grpc.testing.WorkerService";
-
-    static readonly grpc::Marshaller<global::Grpc.Testing.ServerArgs> __Marshaller_ServerArgs = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.ServerArgs.Parser.ParseFrom);
-    static readonly grpc::Marshaller<global::Grpc.Testing.ServerStatus> __Marshaller_ServerStatus = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.ServerStatus.Parser.ParseFrom);
-    static readonly grpc::Marshaller<global::Grpc.Testing.ClientArgs> __Marshaller_ClientArgs = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.ClientArgs.Parser.ParseFrom);
-    static readonly grpc::Marshaller<global::Grpc.Testing.ClientStatus> __Marshaller_ClientStatus = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.ClientStatus.Parser.ParseFrom);
-    static readonly grpc::Marshaller<global::Grpc.Testing.CoreRequest> __Marshaller_CoreRequest = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.CoreRequest.Parser.ParseFrom);
-    static readonly grpc::Marshaller<global::Grpc.Testing.CoreResponse> __Marshaller_CoreResponse = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.CoreResponse.Parser.ParseFrom);
-    static readonly grpc::Marshaller<global::Grpc.Testing.Void> __Marshaller_Void = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.Void.Parser.ParseFrom);
-
-    static readonly grpc::Method<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> __Method_RunServer = new grpc::Method<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus>(
-        grpc::MethodType.DuplexStreaming,
-        __ServiceName,
-        "RunServer",
-        __Marshaller_ServerArgs,
-        __Marshaller_ServerStatus);
-
-    static readonly grpc::Method<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus> __Method_RunClient = new grpc::Method<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus>(
-        grpc::MethodType.DuplexStreaming,
-        __ServiceName,
-        "RunClient",
-        __Marshaller_ClientArgs,
-        __Marshaller_ClientStatus);
-
-    static readonly grpc::Method<global::Grpc.Testing.CoreRequest, global::Grpc.Testing.CoreResponse> __Method_CoreCount = new grpc::Method<global::Grpc.Testing.CoreRequest, global::Grpc.Testing.CoreResponse>(
-        grpc::MethodType.Unary,
-        __ServiceName,
-        "CoreCount",
-        __Marshaller_CoreRequest,
-        __Marshaller_CoreResponse);
-
-    static readonly grpc::Method<global::Grpc.Testing.Void, global::Grpc.Testing.Void> __Method_QuitWorker = new grpc::Method<global::Grpc.Testing.Void, global::Grpc.Testing.Void>(
-        grpc::MethodType.Unary,
-        __ServiceName,
-        "QuitWorker",
-        __Marshaller_Void,
-        __Marshaller_Void);
-
-    /// <summary>Service descriptor</summary>
-    public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
-    {
-      get { return global::Grpc.Testing.ServicesReflection.Descriptor.Services[1]; }
-    }
-
-    /// <summary>Base class for server-side implementations of WorkerService</summary>
-    public abstract partial class WorkerServiceBase
-    {
-      /// <summary>
-      /// Start server with specified workload.
-      /// First request sent specifies the ServerConfig followed by ServerStatus
-      /// response. After that, a "Mark" can be sent anytime to request the latest
-      /// stats. Closing the stream will initiate shutdown of the test server
-      /// and once the shutdown has finished, the OK status is sent to terminate
-      /// this RPC.
-      /// </summary>
-      /// <param name="requestStream">Used for reading requests from the client.</param>
-      /// <param name="responseStream">Used for sending responses back to the client.</param>
-      /// <param name="context">The context of the server-side call handler being invoked.</param>
-      /// <returns>A task indicating completion of the handler.</returns>
-      public virtual global::System.Threading.Tasks.Task RunServer(grpc::IAsyncStreamReader<global::Grpc.Testing.ServerArgs> requestStream, grpc::IServerStreamWriter<global::Grpc.Testing.ServerStatus> responseStream, grpc::ServerCallContext context)
-      {
-        throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
-      }
-
-      /// <summary>
-      /// Start client with specified workload.
-      /// First request sent specifies the ClientConfig followed by ClientStatus
-      /// response. After that, a "Mark" can be sent anytime to request the latest
-      /// stats. Closing the stream will initiate shutdown of the test client
-      /// and once the shutdown has finished, the OK status is sent to terminate
-      /// this RPC.
-      /// </summary>
-      /// <param name="requestStream">Used for reading requests from the client.</param>
-      /// <param name="responseStream">Used for sending responses back to the client.</param>
-      /// <param name="context">The context of the server-side call handler being invoked.</param>
-      /// <returns>A task indicating completion of the handler.</returns>
-      public virtual global::System.Threading.Tasks.Task RunClient(grpc::IAsyncStreamReader<global::Grpc.Testing.ClientArgs> requestStream, grpc::IServerStreamWriter<global::Grpc.Testing.ClientStatus> responseStream, grpc::ServerCallContext context)
-      {
-        throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
-      }
-
-      /// <summary>
-      /// Just return the core count - unary call
-      /// </summary>
-      /// <param name="request">The request received from the client.</param>
-      /// <param name="context">The context of the server-side call handler being invoked.</param>
-      /// <returns>The response to send back to the client (wrapped by a task).</returns>
-      public virtual global::System.Threading.Tasks.Task<global::Grpc.Testing.CoreResponse> CoreCount(global::Grpc.Testing.CoreRequest request, grpc::ServerCallContext context)
-      {
-        throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
-      }
-
-      /// <summary>
-      /// Quit this worker
-      /// </summary>
-      /// <param name="request">The request received from the client.</param>
-      /// <param name="context">The context of the server-side call handler being invoked.</param>
-      /// <returns>The response to send back to the client (wrapped by a task).</returns>
-      public virtual global::System.Threading.Tasks.Task<global::Grpc.Testing.Void> QuitWorker(global::Grpc.Testing.Void request, grpc::ServerCallContext context)
-      {
-        throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
-      }
-
-    }
-
-    /// <summary>Client for WorkerService</summary>
-    public partial class WorkerServiceClient : grpc::ClientBase<WorkerServiceClient>
-    {
-      /// <summary>Creates a new client for WorkerService</summary>
-      /// <param name="channel">The channel to use to make remote calls.</param>
-      public WorkerServiceClient(grpc::Channel channel) : base(channel)
-      {
-      }
-      /// <summary>Creates a new client for WorkerService that uses a custom <c>CallInvoker</c>.</summary>
-      /// <param name="callInvoker">The callInvoker to use to make remote calls.</param>
-      public WorkerServiceClient(grpc::CallInvoker callInvoker) : base(callInvoker)
-      {
-      }
-      /// <summary>Protected parameterless constructor to allow creation of test doubles.</summary>
-      protected WorkerServiceClient() : base()
-      {
-      }
-      /// <summary>Protected constructor to allow creation of configured clients.</summary>
-      /// <param name="configuration">The client configuration.</param>
-      protected WorkerServiceClient(ClientBaseConfiguration configuration) : base(configuration)
-      {
-      }
-
-      /// <summary>
-      /// Start server with specified workload.
-      /// First request sent specifies the ServerConfig followed by ServerStatus
-      /// response. After that, a "Mark" can be sent anytime to request the latest
-      /// stats. Closing the stream will initiate shutdown of the test server
-      /// and once the shutdown has finished, the OK status is sent to terminate
-      /// this RPC.
-      /// </summary>
-      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
-      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
-      /// <param name="cancellationToken">An optional token for canceling the call.</param>
-      /// <returns>The call object.</returns>
-      public virtual grpc::AsyncDuplexStreamingCall<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> RunServer(grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
-      {
-        return RunServer(new grpc::CallOptions(headers, deadline, cancellationToken));
-      }
-      /// <summary>
-      /// Start server with specified workload.
-      /// First request sent specifies the ServerConfig followed by ServerStatus
-      /// response. After that, a "Mark" can be sent anytime to request the latest
-      /// stats. Closing the stream will initiate shutdown of the test server
-      /// and once the shutdown has finished, the OK status is sent to terminate
-      /// this RPC.
-      /// </summary>
-      /// <param name="options">The options for the call.</param>
-      /// <returns>The call object.</returns>
-      public virtual grpc::AsyncDuplexStreamingCall<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> RunServer(grpc::CallOptions options)
-      {
-        return CallInvoker.AsyncDuplexStreamingCall(__Method_RunServer, null, options);
-      }
-      /// <summary>
-      /// Start client with specified workload.
-      /// First request sent specifies the ClientConfig followed by ClientStatus
-      /// response. After that, a "Mark" can be sent anytime to request the latest
-      /// stats. Closing the stream will initiate shutdown of the test client
-      /// and once the shutdown has finished, the OK status is sent to terminate
-      /// this RPC.
-      /// </summary>
-      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
-      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
-      /// <param name="cancellationToken">An optional token for canceling the call.</param>
-      /// <returns>The call object.</returns>
-      public virtual grpc::AsyncDuplexStreamingCall<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus> RunClient(grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
-      {
-        return RunClient(new grpc::CallOptions(headers, deadline, cancellationToken));
-      }
-      /// <summary>
-      /// Start client with specified workload.
-      /// First request sent specifies the ClientConfig followed by ClientStatus
-      /// response. After that, a "Mark" can be sent anytime to request the latest
-      /// stats. Closing the stream will initiate shutdown of the test client
-      /// and once the shutdown has finished, the OK status is sent to terminate
-      /// this RPC.
-      /// </summary>
-      /// <param name="options">The options for the call.</param>
-      /// <returns>The call object.</returns>
-      public virtual grpc::AsyncDuplexStreamingCall<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus> RunClient(grpc::CallOptions options)
-      {
-        return CallInvoker.AsyncDuplexStreamingCall(__Method_RunClient, null, options);
-      }
-      /// <summary>
-      /// Just return the core count - unary call
-      /// </summary>
-      /// <param name="request">The request to send to the server.</param>
-      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
-      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
-      /// <param name="cancellationToken">An optional token for canceling the call.</param>
-      /// <returns>The response received from the server.</returns>
-      public virtual global::Grpc.Testing.CoreResponse CoreCount(global::Grpc.Testing.CoreRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
-      {
-        return CoreCount(request, new grpc::CallOptions(headers, deadline, cancellationToken));
-      }
-      /// <summary>
-      /// Just return the core count - unary call
-      /// </summary>
-      /// <param name="request">The request to send to the server.</param>
-      /// <param name="options">The options for the call.</param>
-      /// <returns>The response received from the server.</returns>
-      public virtual global::Grpc.Testing.CoreResponse CoreCount(global::Grpc.Testing.CoreRequest request, grpc::CallOptions options)
-      {
-        return CallInvoker.BlockingUnaryCall(__Method_CoreCount, null, options, request);
-      }
-      /// <summary>
-      /// Just return the core count - unary call
-      /// </summary>
-      /// <param name="request">The request to send to the server.</param>
-      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
-      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
-      /// <param name="cancellationToken">An optional token for canceling the call.</param>
-      /// <returns>The call object.</returns>
-      public virtual grpc::AsyncUnaryCall<global::Grpc.Testing.CoreResponse> CoreCountAsync(global::Grpc.Testing.CoreRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
-      {
-        return CoreCountAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken));
-      }
-      /// <summary>
-      /// Just return the core count - unary call
-      /// </summary>
-      /// <param name="request">The request to send to the server.</param>
-      /// <param name="options">The options for the call.</param>
-      /// <returns>The call object.</returns>
-      public virtual grpc::AsyncUnaryCall<global::Grpc.Testing.CoreResponse> CoreCountAsync(global::Grpc.Testing.CoreRequest request, grpc::CallOptions options)
-      {
-        return CallInvoker.AsyncUnaryCall(__Method_CoreCount, null, options, request);
-      }
-      /// <summary>
-      /// Quit this worker
-      /// </summary>
-      /// <param name="request">The request to send to the server.</param>
-      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
-      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
-      /// <param name="cancellationToken">An optional token for canceling the call.</param>
-      /// <returns>The response received from the server.</returns>
-      public virtual global::Grpc.Testing.Void QuitWorker(global::Grpc.Testing.Void request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
-      {
-        return QuitWorker(request, new grpc::CallOptions(headers, deadline, cancellationToken));
-      }
-      /// <summary>
-      /// Quit this worker
-      /// </summary>
-      /// <param name="request">The request to send to the server.</param>
-      /// <param name="options">The options for the call.</param>
-      /// <returns>The response received from the server.</returns>
-      public virtual global::Grpc.Testing.Void QuitWorker(global::Grpc.Testing.Void request, grpc::CallOptions options)
-      {
-        return CallInvoker.BlockingUnaryCall(__Method_QuitWorker, null, options, request);
-      }
-      /// <summary>
-      /// Quit this worker
-      /// </summary>
-      /// <param name="request">The request to send to the server.</param>
-      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
-      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
-      /// <param name="cancellationToken">An optional token for canceling the call.</param>
-      /// <returns>The call object.</returns>
-      public virtual grpc::AsyncUnaryCall<global::Grpc.Testing.Void> QuitWorkerAsync(global::Grpc.Testing.Void request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
-      {
-        return QuitWorkerAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken));
-      }
-      /// <summary>
-      /// Quit this worker
-      /// </summary>
-      /// <param name="request">The request to send to the server.</param>
-      /// <param name="options">The options for the call.</param>
-      /// <returns>The call object.</returns>
-      public virtual grpc::AsyncUnaryCall<global::Grpc.Testing.Void> QuitWorkerAsync(global::Grpc.Testing.Void request, grpc::CallOptions options)
-      {
-        return CallInvoker.AsyncUnaryCall(__Method_QuitWorker, null, options, request);
-      }
-      /// <summary>Creates a new instance of client from given <c>ClientBaseConfiguration</c>.</summary>
-      protected override WorkerServiceClient NewInstance(ClientBaseConfiguration configuration)
-      {
-        return new WorkerServiceClient(configuration);
-      }
-    }
-
-    /// <summary>Creates service definition that can be registered with a server</summary>
-    /// <param name="serviceImpl">An object implementing the server-side handling logic.</param>
-    public static grpc::ServerServiceDefinition BindService(WorkerServiceBase serviceImpl)
-    {
-      return grpc::ServerServiceDefinition.CreateBuilder()
-          .AddMethod(__Method_RunServer, serviceImpl.RunServer)
-          .AddMethod(__Method_RunClient, serviceImpl.RunClient)
-          .AddMethod(__Method_CoreCount, serviceImpl.CoreCount)
-          .AddMethod(__Method_QuitWorker, serviceImpl.QuitWorker).Build();
-    }
-
-  }
-  public static partial class ReportQpsScenarioService
-  {
-    static readonly string __ServiceName = "grpc.testing.ReportQpsScenarioService";
-
-    static readonly grpc::Marshaller<global::Grpc.Testing.ScenarioResult> __Marshaller_ScenarioResult = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.ScenarioResult.Parser.ParseFrom);
-    static readonly grpc::Marshaller<global::Grpc.Testing.Void> __Marshaller_Void = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.Void.Parser.ParseFrom);
-
-    static readonly grpc::Method<global::Grpc.Testing.ScenarioResult, global::Grpc.Testing.Void> __Method_ReportScenario = new grpc::Method<global::Grpc.Testing.ScenarioResult, global::Grpc.Testing.Void>(
-        grpc::MethodType.Unary,
-        __ServiceName,
-        "ReportScenario",
-        __Marshaller_ScenarioResult,
-        __Marshaller_Void);
-
-    /// <summary>Service descriptor</summary>
-    public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
-    {
-      get { return global::Grpc.Testing.ServicesReflection.Descriptor.Services[2]; }
-    }
-
-    /// <summary>Base class for server-side implementations of ReportQpsScenarioService</summary>
-    public abstract partial class ReportQpsScenarioServiceBase
-    {
-      /// <summary>
-      /// Report results of a QPS test benchmark scenario.
-      /// </summary>
-      /// <param name="request">The request received from the client.</param>
-      /// <param name="context">The context of the server-side call handler being invoked.</param>
-      /// <returns>The response to send back to the client (wrapped by a task).</returns>
-      public virtual global::System.Threading.Tasks.Task<global::Grpc.Testing.Void> ReportScenario(global::Grpc.Testing.ScenarioResult request, grpc::ServerCallContext context)
-      {
-        throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
-      }
-
-    }
-
-    /// <summary>Client for ReportQpsScenarioService</summary>
-    public partial class ReportQpsScenarioServiceClient : grpc::ClientBase<ReportQpsScenarioServiceClient>
-    {
-      /// <summary>Creates a new client for ReportQpsScenarioService</summary>
-      /// <param name="channel">The channel to use to make remote calls.</param>
-      public ReportQpsScenarioServiceClient(grpc::Channel channel) : base(channel)
-      {
-      }
-      /// <summary>Creates a new client for ReportQpsScenarioService that uses a custom <c>CallInvoker</c>.</summary>
-      /// <param name="callInvoker">The callInvoker to use to make remote calls.</param>
-      public ReportQpsScenarioServiceClient(grpc::CallInvoker callInvoker) : base(callInvoker)
-      {
-      }
-      /// <summary>Protected parameterless constructor to allow creation of test doubles.</summary>
-      protected ReportQpsScenarioServiceClient() : base()
-      {
-      }
-      /// <summary>Protected constructor to allow creation of configured clients.</summary>
-      /// <param name="configuration">The client configuration.</param>
-      protected ReportQpsScenarioServiceClient(ClientBaseConfiguration configuration) : base(configuration)
-      {
-      }
-
-      /// <summary>
-      /// Report results of a QPS test benchmark scenario.
-      /// </summary>
-      /// <param name="request">The request to send to the server.</param>
-      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
-      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
-      /// <param name="cancellationToken">An optional token for canceling the call.</param>
-      /// <returns>The response received from the server.</returns>
-      public virtual global::Grpc.Testing.Void ReportScenario(global::Grpc.Testing.ScenarioResult request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
-      {
-        return ReportScenario(request, new grpc::CallOptions(headers, deadline, cancellationToken));
-      }
-      /// <summary>
-      /// Report results of a QPS test benchmark scenario.
-      /// </summary>
-      /// <param name="request">The request to send to the server.</param>
-      /// <param name="options">The options for the call.</param>
-      /// <returns>The response received from the server.</returns>
-      public virtual global::Grpc.Testing.Void ReportScenario(global::Grpc.Testing.ScenarioResult request, grpc::CallOptions options)
-      {
-        return CallInvoker.BlockingUnaryCall(__Method_ReportScenario, null, options, request);
-      }
-      /// <summary>
-      /// Report results of a QPS test benchmark scenario.
-      /// </summary>
-      /// <param name="request">The request to send to the server.</param>
-      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
-      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
-      /// <param name="cancellationToken">An optional token for canceling the call.</param>
-      /// <returns>The call object.</returns>
-      public virtual grpc::AsyncUnaryCall<global::Grpc.Testing.Void> ReportScenarioAsync(global::Grpc.Testing.ScenarioResult request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
-      {
-        return ReportScenarioAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken));
-      }
-      /// <summary>
-      /// Report results of a QPS test benchmark scenario.
-      /// </summary>
-      /// <param name="request">The request to send to the server.</param>
-      /// <param name="options">The options for the call.</param>
-      /// <returns>The call object.</returns>
-      public virtual grpc::AsyncUnaryCall<global::Grpc.Testing.Void> ReportScenarioAsync(global::Grpc.Testing.ScenarioResult request, grpc::CallOptions options)
-      {
-        return CallInvoker.AsyncUnaryCall(__Method_ReportScenario, null, options, request);
-      }
-      /// <summary>Creates a new instance of client from given <c>ClientBaseConfiguration</c>.</summary>
-      protected override ReportQpsScenarioServiceClient NewInstance(ClientBaseConfiguration configuration)
-      {
-        return new ReportQpsScenarioServiceClient(configuration);
-      }
-    }
-
-    /// <summary>Creates service definition that can be registered with a server</summary>
-    /// <param name="serviceImpl">An object implementing the server-side handling logic.</param>
-    public static grpc::ServerServiceDefinition BindService(ReportQpsScenarioServiceBase serviceImpl)
-    {
-      return grpc::ServerServiceDefinition.CreateBuilder()
-          .AddMethod(__Method_ReportScenario, serviceImpl.ReportScenario).Build();
-    }
-
-  }
-}
-#endregion
diff --git a/src/csharp/Grpc.IntegrationTesting/Stats.cs b/src/csharp/Grpc.IntegrationTesting/Stats.cs
index e082ae7..8160646 100644
--- a/src/csharp/Grpc.IntegrationTesting/Stats.cs
+++ b/src/csharp/Grpc.IntegrationTesting/Stats.cs
@@ -1,5 +1,7 @@
-// Generated by the protocol buffer compiler.  DO NOT EDIT!
-// source: src/proto/grpc/testing/stats.proto
+// <auto-generated>
+//     Generated by the protocol buffer compiler.  DO NOT EDIT!
+//     source: src/proto/grpc/testing/stats.proto
+// </auto-generated>
 #pragma warning disable 1591, 0612, 3021
 #region Designer generated code
 
@@ -55,6 +57,7 @@
   #region Messages
   public sealed partial class ServerStats : pb::IMessage<ServerStats> {
     private static readonly pb::MessageParser<ServerStats> _parser = new pb::MessageParser<ServerStats>(() => new ServerStats());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<ServerStats> Parser { get { return _parser; } }
 
@@ -84,6 +87,7 @@
       idleCpuTime_ = other.idleCpuTime_;
       cqPollCount_ = other.cqPollCount_;
       CoreStats = other.coreStats_ != null ? other.CoreStats.Clone() : null;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -203,26 +207,29 @@
       if (ReferenceEquals(other, this)) {
         return true;
       }
-      if (TimeElapsed != other.TimeElapsed) return false;
-      if (TimeUser != other.TimeUser) return false;
-      if (TimeSystem != other.TimeSystem) return false;
+      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(TimeElapsed, other.TimeElapsed)) return false;
+      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(TimeUser, other.TimeUser)) return false;
+      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(TimeSystem, other.TimeSystem)) return false;
       if (TotalCpuTime != other.TotalCpuTime) return false;
       if (IdleCpuTime != other.IdleCpuTime) return false;
       if (CqPollCount != other.CqPollCount) return false;
       if (!object.Equals(CoreStats, other.CoreStats)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
-      if (TimeElapsed != 0D) hash ^= TimeElapsed.GetHashCode();
-      if (TimeUser != 0D) hash ^= TimeUser.GetHashCode();
-      if (TimeSystem != 0D) hash ^= TimeSystem.GetHashCode();
+      if (TimeElapsed != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(TimeElapsed);
+      if (TimeUser != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(TimeUser);
+      if (TimeSystem != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(TimeSystem);
       if (TotalCpuTime != 0UL) hash ^= TotalCpuTime.GetHashCode();
       if (IdleCpuTime != 0UL) hash ^= IdleCpuTime.GetHashCode();
       if (CqPollCount != 0UL) hash ^= CqPollCount.GetHashCode();
       if (coreStats_ != null) hash ^= CoreStats.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -261,6 +268,9 @@
         output.WriteRawTag(58);
         output.WriteMessage(CoreStats);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -287,6 +297,9 @@
       if (coreStats_ != null) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(CoreStats);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -319,6 +332,7 @@
         }
         CoreStats.MergeFrom(other.CoreStats);
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -327,7 +341,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 9: {
             TimeElapsed = input.ReadDouble();
@@ -371,6 +385,7 @@
   /// </summary>
   public sealed partial class HistogramParams : pb::IMessage<HistogramParams> {
     private static readonly pb::MessageParser<HistogramParams> _parser = new pb::MessageParser<HistogramParams>(() => new HistogramParams());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<HistogramParams> Parser { get { return _parser; } }
 
@@ -395,6 +410,7 @@
     public HistogramParams(HistogramParams other) : this() {
       resolution_ = other.resolution_;
       maxPossible_ = other.maxPossible_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -443,16 +459,19 @@
       if (ReferenceEquals(other, this)) {
         return true;
       }
-      if (Resolution != other.Resolution) return false;
-      if (MaxPossible != other.MaxPossible) return false;
-      return true;
+      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(Resolution, other.Resolution)) return false;
+      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(MaxPossible, other.MaxPossible)) return false;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
-      if (Resolution != 0D) hash ^= Resolution.GetHashCode();
-      if (MaxPossible != 0D) hash ^= MaxPossible.GetHashCode();
+      if (Resolution != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(Resolution);
+      if (MaxPossible != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(MaxPossible);
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -471,6 +490,9 @@
         output.WriteRawTag(17);
         output.WriteDouble(MaxPossible);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -482,6 +504,9 @@
       if (MaxPossible != 0D) {
         size += 1 + 8;
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -496,6 +521,7 @@
       if (other.MaxPossible != 0D) {
         MaxPossible = other.MaxPossible;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -504,7 +530,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 9: {
             Resolution = input.ReadDouble();
@@ -525,6 +551,7 @@
   /// </summary>
   public sealed partial class HistogramData : pb::IMessage<HistogramData> {
     private static readonly pb::MessageParser<HistogramData> _parser = new pb::MessageParser<HistogramData>(() => new HistogramData());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<HistogramData> Parser { get { return _parser; } }
 
@@ -553,6 +580,7 @@
       sum_ = other.sum_;
       sumOfSquares_ = other.sumOfSquares_;
       count_ = other.count_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -639,23 +667,26 @@
         return true;
       }
       if(!bucket_.Equals(other.bucket_)) return false;
-      if (MinSeen != other.MinSeen) return false;
-      if (MaxSeen != other.MaxSeen) return false;
-      if (Sum != other.Sum) return false;
-      if (SumOfSquares != other.SumOfSquares) return false;
-      if (Count != other.Count) return false;
-      return true;
+      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(MinSeen, other.MinSeen)) return false;
+      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(MaxSeen, other.MaxSeen)) return false;
+      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(Sum, other.Sum)) return false;
+      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(SumOfSquares, other.SumOfSquares)) return false;
+      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(Count, other.Count)) return false;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
       hash ^= bucket_.GetHashCode();
-      if (MinSeen != 0D) hash ^= MinSeen.GetHashCode();
-      if (MaxSeen != 0D) hash ^= MaxSeen.GetHashCode();
-      if (Sum != 0D) hash ^= Sum.GetHashCode();
-      if (SumOfSquares != 0D) hash ^= SumOfSquares.GetHashCode();
-      if (Count != 0D) hash ^= Count.GetHashCode();
+      if (MinSeen != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(MinSeen);
+      if (MaxSeen != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(MaxSeen);
+      if (Sum != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(Sum);
+      if (SumOfSquares != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(SumOfSquares);
+      if (Count != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(Count);
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -687,6 +718,9 @@
         output.WriteRawTag(49);
         output.WriteDouble(Count);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -708,6 +742,9 @@
       if (Count != 0D) {
         size += 1 + 8;
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -732,6 +769,7 @@
       if (other.Count != 0D) {
         Count = other.Count;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -740,7 +778,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10:
           case 8: {
@@ -775,6 +813,7 @@
 
   public sealed partial class RequestResultCount : pb::IMessage<RequestResultCount> {
     private static readonly pb::MessageParser<RequestResultCount> _parser = new pb::MessageParser<RequestResultCount>(() => new RequestResultCount());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<RequestResultCount> Parser { get { return _parser; } }
 
@@ -799,6 +838,7 @@
     public RequestResultCount(RequestResultCount other) : this() {
       statusCode_ = other.statusCode_;
       count_ = other.count_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -843,7 +883,7 @@
       }
       if (StatusCode != other.StatusCode) return false;
       if (Count != other.Count) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -851,6 +891,9 @@
       int hash = 1;
       if (StatusCode != 0) hash ^= StatusCode.GetHashCode();
       if (Count != 0L) hash ^= Count.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -869,6 +912,9 @@
         output.WriteRawTag(16);
         output.WriteInt64(Count);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -880,6 +926,9 @@
       if (Count != 0L) {
         size += 1 + pb::CodedOutputStream.ComputeInt64Size(Count);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -894,6 +943,7 @@
       if (other.Count != 0L) {
         Count = other.Count;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -902,7 +952,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 8: {
             StatusCode = input.ReadInt32();
@@ -920,6 +970,7 @@
 
   public sealed partial class ClientStats : pb::IMessage<ClientStats> {
     private static readonly pb::MessageParser<ClientStats> _parser = new pb::MessageParser<ClientStats>(() => new ClientStats());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<ClientStats> Parser { get { return _parser; } }
 
@@ -949,6 +1000,7 @@
       requestResults_ = other.requestResults_.Clone();
       cqPollCount_ = other.cqPollCount_;
       CoreStats = other.coreStats_ != null ? other.CoreStats.Clone() : null;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1061,25 +1113,28 @@
         return true;
       }
       if (!object.Equals(Latencies, other.Latencies)) return false;
-      if (TimeElapsed != other.TimeElapsed) return false;
-      if (TimeUser != other.TimeUser) return false;
-      if (TimeSystem != other.TimeSystem) return false;
+      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(TimeElapsed, other.TimeElapsed)) return false;
+      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(TimeUser, other.TimeUser)) return false;
+      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(TimeSystem, other.TimeSystem)) return false;
       if(!requestResults_.Equals(other.requestResults_)) return false;
       if (CqPollCount != other.CqPollCount) return false;
       if (!object.Equals(CoreStats, other.CoreStats)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
       if (latencies_ != null) hash ^= Latencies.GetHashCode();
-      if (TimeElapsed != 0D) hash ^= TimeElapsed.GetHashCode();
-      if (TimeUser != 0D) hash ^= TimeUser.GetHashCode();
-      if (TimeSystem != 0D) hash ^= TimeSystem.GetHashCode();
+      if (TimeElapsed != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(TimeElapsed);
+      if (TimeUser != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(TimeUser);
+      if (TimeSystem != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(TimeSystem);
       hash ^= requestResults_.GetHashCode();
       if (CqPollCount != 0UL) hash ^= CqPollCount.GetHashCode();
       if (coreStats_ != null) hash ^= CoreStats.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -1115,6 +1170,9 @@
         output.WriteRawTag(58);
         output.WriteMessage(CoreStats);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1139,6 +1197,9 @@
       if (coreStats_ != null) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(CoreStats);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -1172,6 +1233,7 @@
         }
         CoreStats.MergeFrom(other.CoreStats);
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1180,7 +1242,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             if (latencies_ == null) {
diff --git a/src/csharp/Grpc.IntegrationTesting/Test.cs b/src/csharp/Grpc.IntegrationTesting/Test.cs
index d2fa9f8..03f92c7 100644
--- a/src/csharp/Grpc.IntegrationTesting/Test.cs
+++ b/src/csharp/Grpc.IntegrationTesting/Test.cs
@@ -1,5 +1,7 @@
-// Generated by the protocol buffer compiler.  DO NOT EDIT!
-// source: src/proto/grpc/testing/test.proto
+// <auto-generated>
+//     Generated by the protocol buffer compiler.  DO NOT EDIT!
+//     source: src/proto/grpc/testing/test.proto
+// </auto-generated>
 #pragma warning disable 1591, 0612, 3021
 #region Designer generated code
 
diff --git a/src/csharp/Grpc.IntegrationTesting/WorkerService.cs b/src/csharp/Grpc.IntegrationTesting/WorkerService.cs
new file mode 100644
index 0000000..6de3193
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/WorkerService.cs
@@ -0,0 +1,45 @@
+// <auto-generated>
+//     Generated by the protocol buffer compiler.  DO NOT EDIT!
+//     source: src/proto/grpc/testing/worker_service.proto
+// </auto-generated>
+#pragma warning disable 1591, 0612, 3021
+#region Designer generated code
+
+using pb = global::Google.Protobuf;
+using pbc = global::Google.Protobuf.Collections;
+using pbr = global::Google.Protobuf.Reflection;
+using scg = global::System.Collections.Generic;
+namespace Grpc.Testing {
+
+  /// <summary>Holder for reflection information generated from src/proto/grpc/testing/worker_service.proto</summary>
+  public static partial class WorkerServiceReflection {
+
+    #region Descriptor
+    /// <summary>File descriptor for src/proto/grpc/testing/worker_service.proto</summary>
+    public static pbr::FileDescriptor Descriptor {
+      get { return descriptor; }
+    }
+    private static pbr::FileDescriptor descriptor;
+
+    static WorkerServiceReflection() {
+      byte[] descriptorData = global::System.Convert.FromBase64String(
+          string.Concat(
+            "CitzcmMvcHJvdG8vZ3JwYy90ZXN0aW5nL3dvcmtlcl9zZXJ2aWNlLnByb3Rv",
+            "EgxncnBjLnRlc3RpbmcaJHNyYy9wcm90by9ncnBjL3Rlc3RpbmcvY29udHJv",
+            "bC5wcm90bzKXAgoNV29ya2VyU2VydmljZRJFCglSdW5TZXJ2ZXISGC5ncnBj",
+            "LnRlc3RpbmcuU2VydmVyQXJncxoaLmdycGMudGVzdGluZy5TZXJ2ZXJTdGF0",
+            "dXMoATABEkUKCVJ1bkNsaWVudBIYLmdycGMudGVzdGluZy5DbGllbnRBcmdz",
+            "GhouZ3JwYy50ZXN0aW5nLkNsaWVudFN0YXR1cygBMAESQgoJQ29yZUNvdW50",
+            "EhkuZ3JwYy50ZXN0aW5nLkNvcmVSZXF1ZXN0GhouZ3JwYy50ZXN0aW5nLkNv",
+            "cmVSZXNwb25zZRI0CgpRdWl0V29ya2VyEhIuZ3JwYy50ZXN0aW5nLlZvaWQa",
+            "Ei5ncnBjLnRlc3RpbmcuVm9pZGIGcHJvdG8z"));
+      descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
+          new pbr::FileDescriptor[] { global::Grpc.Testing.ControlReflection.Descriptor, },
+          new pbr::GeneratedClrTypeInfo(null, null));
+    }
+    #endregion
+
+  }
+}
+
+#endregion Designer generated code
diff --git a/src/csharp/Grpc.IntegrationTesting/WorkerServiceGrpc.cs b/src/csharp/Grpc.IntegrationTesting/WorkerServiceGrpc.cs
new file mode 100644
index 0000000..ede3ace
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/WorkerServiceGrpc.cs
@@ -0,0 +1,326 @@
+// <auto-generated>
+//     Generated by the protocol buffer compiler.  DO NOT EDIT!
+//     source: src/proto/grpc/testing/worker_service.proto
+// </auto-generated>
+// Original file comments:
+// Copyright 2015 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.
+//
+// An integration test service that covers all the method signature permutations
+// of unary/streaming requests/responses.
+#pragma warning disable 1591
+#region Designer generated code
+
+using grpc = global::Grpc.Core;
+
+namespace Grpc.Testing {
+  public static partial class WorkerService
+  {
+    static readonly string __ServiceName = "grpc.testing.WorkerService";
+
+    static readonly grpc::Marshaller<global::Grpc.Testing.ServerArgs> __Marshaller_ServerArgs = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.ServerArgs.Parser.ParseFrom);
+    static readonly grpc::Marshaller<global::Grpc.Testing.ServerStatus> __Marshaller_ServerStatus = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.ServerStatus.Parser.ParseFrom);
+    static readonly grpc::Marshaller<global::Grpc.Testing.ClientArgs> __Marshaller_ClientArgs = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.ClientArgs.Parser.ParseFrom);
+    static readonly grpc::Marshaller<global::Grpc.Testing.ClientStatus> __Marshaller_ClientStatus = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.ClientStatus.Parser.ParseFrom);
+    static readonly grpc::Marshaller<global::Grpc.Testing.CoreRequest> __Marshaller_CoreRequest = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.CoreRequest.Parser.ParseFrom);
+    static readonly grpc::Marshaller<global::Grpc.Testing.CoreResponse> __Marshaller_CoreResponse = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.CoreResponse.Parser.ParseFrom);
+    static readonly grpc::Marshaller<global::Grpc.Testing.Void> __Marshaller_Void = grpc::Marshallers.Create((arg) => global::Google.Protobuf.MessageExtensions.ToByteArray(arg), global::Grpc.Testing.Void.Parser.ParseFrom);
+
+    static readonly grpc::Method<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> __Method_RunServer = new grpc::Method<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus>(
+        grpc::MethodType.DuplexStreaming,
+        __ServiceName,
+        "RunServer",
+        __Marshaller_ServerArgs,
+        __Marshaller_ServerStatus);
+
+    static readonly grpc::Method<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus> __Method_RunClient = new grpc::Method<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus>(
+        grpc::MethodType.DuplexStreaming,
+        __ServiceName,
+        "RunClient",
+        __Marshaller_ClientArgs,
+        __Marshaller_ClientStatus);
+
+    static readonly grpc::Method<global::Grpc.Testing.CoreRequest, global::Grpc.Testing.CoreResponse> __Method_CoreCount = new grpc::Method<global::Grpc.Testing.CoreRequest, global::Grpc.Testing.CoreResponse>(
+        grpc::MethodType.Unary,
+        __ServiceName,
+        "CoreCount",
+        __Marshaller_CoreRequest,
+        __Marshaller_CoreResponse);
+
+    static readonly grpc::Method<global::Grpc.Testing.Void, global::Grpc.Testing.Void> __Method_QuitWorker = new grpc::Method<global::Grpc.Testing.Void, global::Grpc.Testing.Void>(
+        grpc::MethodType.Unary,
+        __ServiceName,
+        "QuitWorker",
+        __Marshaller_Void,
+        __Marshaller_Void);
+
+    /// <summary>Service descriptor</summary>
+    public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor
+    {
+      get { return global::Grpc.Testing.WorkerServiceReflection.Descriptor.Services[0]; }
+    }
+
+    /// <summary>Base class for server-side implementations of WorkerService</summary>
+    public abstract partial class WorkerServiceBase
+    {
+      /// <summary>
+      /// Start server with specified workload.
+      /// First request sent specifies the ServerConfig followed by ServerStatus
+      /// response. After that, a "Mark" can be sent anytime to request the latest
+      /// stats. Closing the stream will initiate shutdown of the test server
+      /// and once the shutdown has finished, the OK status is sent to terminate
+      /// this RPC.
+      /// </summary>
+      /// <param name="requestStream">Used for reading requests from the client.</param>
+      /// <param name="responseStream">Used for sending responses back to the client.</param>
+      /// <param name="context">The context of the server-side call handler being invoked.</param>
+      /// <returns>A task indicating completion of the handler.</returns>
+      public virtual global::System.Threading.Tasks.Task RunServer(grpc::IAsyncStreamReader<global::Grpc.Testing.ServerArgs> requestStream, grpc::IServerStreamWriter<global::Grpc.Testing.ServerStatus> responseStream, grpc::ServerCallContext context)
+      {
+        throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
+      }
+
+      /// <summary>
+      /// Start client with specified workload.
+      /// First request sent specifies the ClientConfig followed by ClientStatus
+      /// response. After that, a "Mark" can be sent anytime to request the latest
+      /// stats. Closing the stream will initiate shutdown of the test client
+      /// and once the shutdown has finished, the OK status is sent to terminate
+      /// this RPC.
+      /// </summary>
+      /// <param name="requestStream">Used for reading requests from the client.</param>
+      /// <param name="responseStream">Used for sending responses back to the client.</param>
+      /// <param name="context">The context of the server-side call handler being invoked.</param>
+      /// <returns>A task indicating completion of the handler.</returns>
+      public virtual global::System.Threading.Tasks.Task RunClient(grpc::IAsyncStreamReader<global::Grpc.Testing.ClientArgs> requestStream, grpc::IServerStreamWriter<global::Grpc.Testing.ClientStatus> responseStream, grpc::ServerCallContext context)
+      {
+        throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
+      }
+
+      /// <summary>
+      /// Just return the core count - unary call
+      /// </summary>
+      /// <param name="request">The request received from the client.</param>
+      /// <param name="context">The context of the server-side call handler being invoked.</param>
+      /// <returns>The response to send back to the client (wrapped by a task).</returns>
+      public virtual global::System.Threading.Tasks.Task<global::Grpc.Testing.CoreResponse> CoreCount(global::Grpc.Testing.CoreRequest request, grpc::ServerCallContext context)
+      {
+        throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
+      }
+
+      /// <summary>
+      /// Quit this worker
+      /// </summary>
+      /// <param name="request">The request received from the client.</param>
+      /// <param name="context">The context of the server-side call handler being invoked.</param>
+      /// <returns>The response to send back to the client (wrapped by a task).</returns>
+      public virtual global::System.Threading.Tasks.Task<global::Grpc.Testing.Void> QuitWorker(global::Grpc.Testing.Void request, grpc::ServerCallContext context)
+      {
+        throw new grpc::RpcException(new grpc::Status(grpc::StatusCode.Unimplemented, ""));
+      }
+
+    }
+
+    /// <summary>Client for WorkerService</summary>
+    public partial class WorkerServiceClient : grpc::ClientBase<WorkerServiceClient>
+    {
+      /// <summary>Creates a new client for WorkerService</summary>
+      /// <param name="channel">The channel to use to make remote calls.</param>
+      public WorkerServiceClient(grpc::Channel channel) : base(channel)
+      {
+      }
+      /// <summary>Creates a new client for WorkerService that uses a custom <c>CallInvoker</c>.</summary>
+      /// <param name="callInvoker">The callInvoker to use to make remote calls.</param>
+      public WorkerServiceClient(grpc::CallInvoker callInvoker) : base(callInvoker)
+      {
+      }
+      /// <summary>Protected parameterless constructor to allow creation of test doubles.</summary>
+      protected WorkerServiceClient() : base()
+      {
+      }
+      /// <summary>Protected constructor to allow creation of configured clients.</summary>
+      /// <param name="configuration">The client configuration.</param>
+      protected WorkerServiceClient(ClientBaseConfiguration configuration) : base(configuration)
+      {
+      }
+
+      /// <summary>
+      /// Start server with specified workload.
+      /// First request sent specifies the ServerConfig followed by ServerStatus
+      /// response. After that, a "Mark" can be sent anytime to request the latest
+      /// stats. Closing the stream will initiate shutdown of the test server
+      /// and once the shutdown has finished, the OK status is sent to terminate
+      /// this RPC.
+      /// </summary>
+      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
+      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
+      /// <param name="cancellationToken">An optional token for canceling the call.</param>
+      /// <returns>The call object.</returns>
+      public virtual grpc::AsyncDuplexStreamingCall<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> RunServer(grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
+      {
+        return RunServer(new grpc::CallOptions(headers, deadline, cancellationToken));
+      }
+      /// <summary>
+      /// Start server with specified workload.
+      /// First request sent specifies the ServerConfig followed by ServerStatus
+      /// response. After that, a "Mark" can be sent anytime to request the latest
+      /// stats. Closing the stream will initiate shutdown of the test server
+      /// and once the shutdown has finished, the OK status is sent to terminate
+      /// this RPC.
+      /// </summary>
+      /// <param name="options">The options for the call.</param>
+      /// <returns>The call object.</returns>
+      public virtual grpc::AsyncDuplexStreamingCall<global::Grpc.Testing.ServerArgs, global::Grpc.Testing.ServerStatus> RunServer(grpc::CallOptions options)
+      {
+        return CallInvoker.AsyncDuplexStreamingCall(__Method_RunServer, null, options);
+      }
+      /// <summary>
+      /// Start client with specified workload.
+      /// First request sent specifies the ClientConfig followed by ClientStatus
+      /// response. After that, a "Mark" can be sent anytime to request the latest
+      /// stats. Closing the stream will initiate shutdown of the test client
+      /// and once the shutdown has finished, the OK status is sent to terminate
+      /// this RPC.
+      /// </summary>
+      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
+      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
+      /// <param name="cancellationToken">An optional token for canceling the call.</param>
+      /// <returns>The call object.</returns>
+      public virtual grpc::AsyncDuplexStreamingCall<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus> RunClient(grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
+      {
+        return RunClient(new grpc::CallOptions(headers, deadline, cancellationToken));
+      }
+      /// <summary>
+      /// Start client with specified workload.
+      /// First request sent specifies the ClientConfig followed by ClientStatus
+      /// response. After that, a "Mark" can be sent anytime to request the latest
+      /// stats. Closing the stream will initiate shutdown of the test client
+      /// and once the shutdown has finished, the OK status is sent to terminate
+      /// this RPC.
+      /// </summary>
+      /// <param name="options">The options for the call.</param>
+      /// <returns>The call object.</returns>
+      public virtual grpc::AsyncDuplexStreamingCall<global::Grpc.Testing.ClientArgs, global::Grpc.Testing.ClientStatus> RunClient(grpc::CallOptions options)
+      {
+        return CallInvoker.AsyncDuplexStreamingCall(__Method_RunClient, null, options);
+      }
+      /// <summary>
+      /// Just return the core count - unary call
+      /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
+      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
+      /// <param name="cancellationToken">An optional token for canceling the call.</param>
+      /// <returns>The response received from the server.</returns>
+      public virtual global::Grpc.Testing.CoreResponse CoreCount(global::Grpc.Testing.CoreRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
+      {
+        return CoreCount(request, new grpc::CallOptions(headers, deadline, cancellationToken));
+      }
+      /// <summary>
+      /// Just return the core count - unary call
+      /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="options">The options for the call.</param>
+      /// <returns>The response received from the server.</returns>
+      public virtual global::Grpc.Testing.CoreResponse CoreCount(global::Grpc.Testing.CoreRequest request, grpc::CallOptions options)
+      {
+        return CallInvoker.BlockingUnaryCall(__Method_CoreCount, null, options, request);
+      }
+      /// <summary>
+      /// Just return the core count - unary call
+      /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
+      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
+      /// <param name="cancellationToken">An optional token for canceling the call.</param>
+      /// <returns>The call object.</returns>
+      public virtual grpc::AsyncUnaryCall<global::Grpc.Testing.CoreResponse> CoreCountAsync(global::Grpc.Testing.CoreRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
+      {
+        return CoreCountAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken));
+      }
+      /// <summary>
+      /// Just return the core count - unary call
+      /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="options">The options for the call.</param>
+      /// <returns>The call object.</returns>
+      public virtual grpc::AsyncUnaryCall<global::Grpc.Testing.CoreResponse> CoreCountAsync(global::Grpc.Testing.CoreRequest request, grpc::CallOptions options)
+      {
+        return CallInvoker.AsyncUnaryCall(__Method_CoreCount, null, options, request);
+      }
+      /// <summary>
+      /// Quit this worker
+      /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
+      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
+      /// <param name="cancellationToken">An optional token for canceling the call.</param>
+      /// <returns>The response received from the server.</returns>
+      public virtual global::Grpc.Testing.Void QuitWorker(global::Grpc.Testing.Void request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
+      {
+        return QuitWorker(request, new grpc::CallOptions(headers, deadline, cancellationToken));
+      }
+      /// <summary>
+      /// Quit this worker
+      /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="options">The options for the call.</param>
+      /// <returns>The response received from the server.</returns>
+      public virtual global::Grpc.Testing.Void QuitWorker(global::Grpc.Testing.Void request, grpc::CallOptions options)
+      {
+        return CallInvoker.BlockingUnaryCall(__Method_QuitWorker, null, options, request);
+      }
+      /// <summary>
+      /// Quit this worker
+      /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="headers">The initial metadata to send with the call. This parameter is optional.</param>
+      /// <param name="deadline">An optional deadline for the call. The call will be cancelled if deadline is hit.</param>
+      /// <param name="cancellationToken">An optional token for canceling the call.</param>
+      /// <returns>The call object.</returns>
+      public virtual grpc::AsyncUnaryCall<global::Grpc.Testing.Void> QuitWorkerAsync(global::Grpc.Testing.Void request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken))
+      {
+        return QuitWorkerAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken));
+      }
+      /// <summary>
+      /// Quit this worker
+      /// </summary>
+      /// <param name="request">The request to send to the server.</param>
+      /// <param name="options">The options for the call.</param>
+      /// <returns>The call object.</returns>
+      public virtual grpc::AsyncUnaryCall<global::Grpc.Testing.Void> QuitWorkerAsync(global::Grpc.Testing.Void request, grpc::CallOptions options)
+      {
+        return CallInvoker.AsyncUnaryCall(__Method_QuitWorker, null, options, request);
+      }
+      /// <summary>Creates a new instance of client from given <c>ClientBaseConfiguration</c>.</summary>
+      protected override WorkerServiceClient NewInstance(ClientBaseConfiguration configuration)
+      {
+        return new WorkerServiceClient(configuration);
+      }
+    }
+
+    /// <summary>Creates service definition that can be registered with a server</summary>
+    /// <param name="serviceImpl">An object implementing the server-side handling logic.</param>
+    public static grpc::ServerServiceDefinition BindService(WorkerServiceBase serviceImpl)
+    {
+      return grpc::ServerServiceDefinition.CreateBuilder()
+          .AddMethod(__Method_RunServer, serviceImpl.RunServer)
+          .AddMethod(__Method_RunClient, serviceImpl.RunClient)
+          .AddMethod(__Method_CoreCount, serviceImpl.CoreCount)
+          .AddMethod(__Method_QuitWorker, serviceImpl.QuitWorker).Build();
+    }
+
+  }
+}
+#endregion
diff --git a/src/csharp/Grpc.Reflection/Reflection.cs b/src/csharp/Grpc.Reflection/Reflection.cs
index 60090e5..84b2a0a 100644
--- a/src/csharp/Grpc.Reflection/Reflection.cs
+++ b/src/csharp/Grpc.Reflection/Reflection.cs
@@ -1,5 +1,7 @@
-// Generated by the protocol buffer compiler.  DO NOT EDIT!
-// source: grpc/reflection/v1alpha/reflection.proto
+// <auto-generated>
+//     Generated by the protocol buffer compiler.  DO NOT EDIT!
+//     source: grpc/reflection/v1alpha/reflection.proto
+// </auto-generated>
 #pragma warning disable 1591, 0612, 3021
 #region Designer generated code
 
@@ -74,6 +76,7 @@
   /// </summary>
   public sealed partial class ServerReflectionRequest : pb::IMessage<ServerReflectionRequest> {
     private static readonly pb::MessageParser<ServerReflectionRequest> _parser = new pb::MessageParser<ServerReflectionRequest>(() => new ServerReflectionRequest());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<ServerReflectionRequest> Parser { get { return _parser; } }
 
@@ -115,6 +118,7 @@
           break;
       }
 
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -256,7 +260,7 @@
       if (AllExtensionNumbersOfType != other.AllExtensionNumbersOfType) return false;
       if (ListServices != other.ListServices) return false;
       if (MessageRequestCase != other.MessageRequestCase) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -269,6 +273,9 @@
       if (messageRequestCase_ == MessageRequestOneofCase.AllExtensionNumbersOfType) hash ^= AllExtensionNumbersOfType.GetHashCode();
       if (messageRequestCase_ == MessageRequestOneofCase.ListServices) hash ^= ListServices.GetHashCode();
       hash ^= (int) messageRequestCase_;
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -303,6 +310,9 @@
         output.WriteRawTag(58);
         output.WriteString(ListServices);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -326,6 +336,9 @@
       if (messageRequestCase_ == MessageRequestOneofCase.ListServices) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(ListServices);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -358,6 +371,7 @@
           break;
       }
 
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -366,7 +380,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             Host = input.ReadString();
@@ -409,6 +423,7 @@
   /// </summary>
   public sealed partial class ExtensionRequest : pb::IMessage<ExtensionRequest> {
     private static readonly pb::MessageParser<ExtensionRequest> _parser = new pb::MessageParser<ExtensionRequest>(() => new ExtensionRequest());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<ExtensionRequest> Parser { get { return _parser; } }
 
@@ -433,6 +448,7 @@
     public ExtensionRequest(ExtensionRequest other) : this() {
       containingType_ = other.containingType_;
       extensionNumber_ = other.extensionNumber_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -480,7 +496,7 @@
       }
       if (ContainingType != other.ContainingType) return false;
       if (ExtensionNumber != other.ExtensionNumber) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -488,6 +504,9 @@
       int hash = 1;
       if (ContainingType.Length != 0) hash ^= ContainingType.GetHashCode();
       if (ExtensionNumber != 0) hash ^= ExtensionNumber.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -506,6 +525,9 @@
         output.WriteRawTag(16);
         output.WriteInt32(ExtensionNumber);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -517,6 +539,9 @@
       if (ExtensionNumber != 0) {
         size += 1 + pb::CodedOutputStream.ComputeInt32Size(ExtensionNumber);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -531,6 +556,7 @@
       if (other.ExtensionNumber != 0) {
         ExtensionNumber = other.ExtensionNumber;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -539,7 +565,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             ContainingType = input.ReadString();
@@ -560,6 +586,7 @@
   /// </summary>
   public sealed partial class ServerReflectionResponse : pb::IMessage<ServerReflectionResponse> {
     private static readonly pb::MessageParser<ServerReflectionResponse> _parser = new pb::MessageParser<ServerReflectionResponse>(() => new ServerReflectionResponse());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<ServerReflectionResponse> Parser { get { return _parser; } }
 
@@ -599,6 +626,7 @@
           break;
       }
 
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -730,7 +758,7 @@
       if (!object.Equals(ListServicesResponse, other.ListServicesResponse)) return false;
       if (!object.Equals(ErrorResponse, other.ErrorResponse)) return false;
       if (MessageResponseCase != other.MessageResponseCase) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -743,6 +771,9 @@
       if (messageResponseCase_ == MessageResponseOneofCase.ListServicesResponse) hash ^= ListServicesResponse.GetHashCode();
       if (messageResponseCase_ == MessageResponseOneofCase.ErrorResponse) hash ^= ErrorResponse.GetHashCode();
       hash ^= (int) messageResponseCase_;
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -777,6 +808,9 @@
         output.WriteRawTag(58);
         output.WriteMessage(ErrorResponse);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -800,6 +834,9 @@
       if (messageResponseCase_ == MessageResponseOneofCase.ErrorResponse) {
         size += 1 + pb::CodedOutputStream.ComputeMessageSize(ErrorResponse);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -844,6 +881,7 @@
           break;
       }
 
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -852,7 +890,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             ValidHost = input.ReadString();
@@ -914,6 +952,7 @@
   /// </summary>
   public sealed partial class FileDescriptorResponse : pb::IMessage<FileDescriptorResponse> {
     private static readonly pb::MessageParser<FileDescriptorResponse> _parser = new pb::MessageParser<FileDescriptorResponse>(() => new FileDescriptorResponse());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<FileDescriptorResponse> Parser { get { return _parser; } }
 
@@ -937,6 +976,7 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public FileDescriptorResponse(FileDescriptorResponse other) : this() {
       fileDescriptorProto_ = other.fileDescriptorProto_.Clone();
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -973,13 +1013,16 @@
         return true;
       }
       if(!fileDescriptorProto_.Equals(other.fileDescriptorProto_)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
       hash ^= fileDescriptorProto_.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -991,12 +1034,18 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public void WriteTo(pb::CodedOutputStream output) {
       fileDescriptorProto_.WriteTo(output, _repeated_fileDescriptorProto_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public int CalculateSize() {
       int size = 0;
       size += fileDescriptorProto_.CalculateSize(_repeated_fileDescriptorProto_codec);
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -1006,6 +1055,7 @@
         return;
       }
       fileDescriptorProto_.Add(other.fileDescriptorProto_);
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1014,7 +1064,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             fileDescriptorProto_.AddEntriesFrom(input, _repeated_fileDescriptorProto_codec);
@@ -1032,6 +1082,7 @@
   /// </summary>
   public sealed partial class ExtensionNumberResponse : pb::IMessage<ExtensionNumberResponse> {
     private static readonly pb::MessageParser<ExtensionNumberResponse> _parser = new pb::MessageParser<ExtensionNumberResponse>(() => new ExtensionNumberResponse());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<ExtensionNumberResponse> Parser { get { return _parser; } }
 
@@ -1056,6 +1107,7 @@
     public ExtensionNumberResponse(ExtensionNumberResponse other) : this() {
       baseTypeName_ = other.baseTypeName_;
       extensionNumber_ = other.extensionNumber_.Clone();
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1103,7 +1155,7 @@
       }
       if (BaseTypeName != other.BaseTypeName) return false;
       if(!extensionNumber_.Equals(other.extensionNumber_)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1111,6 +1163,9 @@
       int hash = 1;
       if (BaseTypeName.Length != 0) hash ^= BaseTypeName.GetHashCode();
       hash ^= extensionNumber_.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -1126,6 +1181,9 @@
         output.WriteString(BaseTypeName);
       }
       extensionNumber_.WriteTo(output, _repeated_extensionNumber_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1135,6 +1193,9 @@
         size += 1 + pb::CodedOutputStream.ComputeStringSize(BaseTypeName);
       }
       size += extensionNumber_.CalculateSize(_repeated_extensionNumber_codec);
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -1147,6 +1208,7 @@
         BaseTypeName = other.BaseTypeName;
       }
       extensionNumber_.Add(other.extensionNumber_);
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1155,7 +1217,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             BaseTypeName = input.ReadString();
@@ -1177,6 +1239,7 @@
   /// </summary>
   public sealed partial class ListServiceResponse : pb::IMessage<ListServiceResponse> {
     private static readonly pb::MessageParser<ListServiceResponse> _parser = new pb::MessageParser<ListServiceResponse>(() => new ListServiceResponse());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<ListServiceResponse> Parser { get { return _parser; } }
 
@@ -1200,6 +1263,7 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public ListServiceResponse(ListServiceResponse other) : this() {
       service_ = other.service_.Clone();
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1235,13 +1299,16 @@
         return true;
       }
       if(!service_.Equals(other.service_)) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
       hash ^= service_.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -1253,12 +1320,18 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public void WriteTo(pb::CodedOutputStream output) {
       service_.WriteTo(output, _repeated_service_codec);
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public int CalculateSize() {
       int size = 0;
       size += service_.CalculateSize(_repeated_service_codec);
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -1268,6 +1341,7 @@
         return;
       }
       service_.Add(other.service_);
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1276,7 +1350,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             service_.AddEntriesFrom(input, _repeated_service_codec);
@@ -1294,6 +1368,7 @@
   /// </summary>
   public sealed partial class ServiceResponse : pb::IMessage<ServiceResponse> {
     private static readonly pb::MessageParser<ServiceResponse> _parser = new pb::MessageParser<ServiceResponse>(() => new ServiceResponse());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<ServiceResponse> Parser { get { return _parser; } }
 
@@ -1317,6 +1392,7 @@
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public ServiceResponse(ServiceResponse other) : this() {
       name_ = other.name_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1353,13 +1429,16 @@
         return true;
       }
       if (Name != other.Name) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public override int GetHashCode() {
       int hash = 1;
       if (Name.Length != 0) hash ^= Name.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -1374,6 +1453,9 @@
         output.WriteRawTag(10);
         output.WriteString(Name);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1382,6 +1464,9 @@
       if (Name.Length != 0) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -1393,6 +1478,7 @@
       if (other.Name.Length != 0) {
         Name = other.Name;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1401,7 +1487,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 10: {
             Name = input.ReadString();
@@ -1418,6 +1504,7 @@
   /// </summary>
   public sealed partial class ErrorResponse : pb::IMessage<ErrorResponse> {
     private static readonly pb::MessageParser<ErrorResponse> _parser = new pb::MessageParser<ErrorResponse>(() => new ErrorResponse());
+    private pb::UnknownFieldSet _unknownFields;
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     public static pb::MessageParser<ErrorResponse> Parser { get { return _parser; } }
 
@@ -1442,6 +1529,7 @@
     public ErrorResponse(ErrorResponse other) : this() {
       errorCode_ = other.errorCode_;
       errorMessage_ = other.errorMessage_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1489,7 +1577,7 @@
       }
       if (ErrorCode != other.ErrorCode) return false;
       if (ErrorMessage != other.ErrorMessage) return false;
-      return true;
+      return Equals(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1497,6 +1585,9 @@
       int hash = 1;
       if (ErrorCode != 0) hash ^= ErrorCode.GetHashCode();
       if (ErrorMessage.Length != 0) hash ^= ErrorMessage.GetHashCode();
+      if (_unknownFields != null) {
+        hash ^= _unknownFields.GetHashCode();
+      }
       return hash;
     }
 
@@ -1515,6 +1606,9 @@
         output.WriteRawTag(18);
         output.WriteString(ErrorMessage);
       }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1526,6 +1620,9 @@
       if (ErrorMessage.Length != 0) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(ErrorMessage);
       }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
       return size;
     }
 
@@ -1540,6 +1637,7 @@
       if (other.ErrorMessage.Length != 0) {
         ErrorMessage = other.ErrorMessage;
       }
+      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -1548,7 +1646,7 @@
       while ((tag = input.ReadTag()) != 0) {
         switch(tag) {
           default:
-            input.SkipLastField();
+            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
             break;
           case 8: {
             ErrorCode = input.ReadInt32();
diff --git a/src/csharp/README.md b/src/csharp/README.md
index 6821ad2..e117e66 100644
--- a/src/csharp/README.md
+++ b/src/csharp/README.md
@@ -16,16 +16,17 @@
 
 When using gRPC C# under .NET Core you only need to [install .NET Core](https://www.microsoft.com/net/core).
 
-- Windows: .NET Framework 4.5+, Visual Studio 2013, 2015, 2017
-- Linux: Mono 4+, MonoDevelop 5.9+ (with NuGet add-in installed)
-- Mac OS X: Xamarin Studio 5.9+
+In addition to that, you can also use gRPC C# with these runtimes / IDEs
+- Windows: .NET Framework 4.5+, Visual Studio 2013, 2015, 2017, Visual Studio Code
+- Linux: Mono 4+, Visual Studio Code, MonoDevelop 5.9+ 
+- Mac OS X: Mono 4+, Visual Studio Code, Xamarin Studio 5.9+
 
 HOW TO USE
 --------------
 
 **Windows, Linux, Mac OS X**
 
-- Open Visual Studio / MonoDevelop / Xamarin Studio and start a new project/solution.
+- Open Visual Studio / MonoDevelop / Xamarin Studio and start a new project/solution (alternatively, you can create a new project from command line with `dotnet` SDK)
 
 - Add the [Grpc](https://www.nuget.org/packages/Grpc/) NuGet package as a dependency (Project options -> Manage NuGet Packages). 
 
@@ -37,12 +38,23 @@
 You only need to go through these steps if you are planning to develop gRPC C#.
 If you are a user of gRPC C#, go to Usage section above.
 
+**Prerequisites for contributors**
+
+- [dotnet SDK](https://www.microsoft.com/net/core)
+- [Mono 4+](https://www.mono-project.com/) (only needed for Linux and MacOS)
+- Prerequisites mentioned in [INSTALL.md](../../INSTALL.md#pre-requisites)
+  to be able to compile the native code.
+
 **Windows, Linux or Mac OS X**
 
-- The easiest way to build is using the `run_tests.py` script that will take care of building the `grpc_csharp_ext` native library:
+- The easiest way to build is using the `run_tests.py` script that will take care of building the `grpc_csharp_ext` native library.
+  
   ```
+  # NOTE: make sure all necessary git submodules with dependencies 
+  # are available by running "git submodule update --init"
+  
   # from the gRPC repository root
-  $ python tools/run_tests/run_tests.py -c dbg -l csharp --build_only
+  $ python tools/run_tests/run_tests.py -l csharp -c dbg --build_only
   ```
 
 - Use Visual Studio 2017 (on Windows) to open the solution `Grpc.sln` or use Visual Studio Code with C# extension (on Linux and Mac). gRPC C# code has been migrated to
@@ -57,11 +69,12 @@
 Under Visual Studio, make sure NUnit test adapter is installed (under "Extensions and Updates").
 Then you should be able to run all the tests using Test Explorer.
 
-gRPC team uses a Python script to simplify facilitate running tests for
+gRPC team uses a Python script to facilitate running tests for
 different languages.
 
 ```
-tools/run_tests/run_tests.py -l csharp
+# from the gRPC repository root
+$ python tools/run_tests/run_tests.py -l csharp -c dbg
 ```
 
 DOCUMENTATION
diff --git a/src/csharp/build_packages_dotnetcli.bat b/src/csharp/build_packages_dotnetcli.bat
index 7639173..924d7b1 100755
--- a/src/csharp/build_packages_dotnetcli.bat
+++ b/src/csharp/build_packages_dotnetcli.bat
@@ -13,7 +13,7 @@
 @rem limitations under the License.
 
 @rem Current package versions
-set VERSION=1.11.0-dev
+set VERSION=1.13.0-dev
 
 @rem Adjust the location of nuget.exe
 set NUGET=C:\nuget\nuget.exe
diff --git a/src/csharp/build_packages_dotnetcli.sh b/src/csharp/build_packages_dotnetcli.sh
index 1b73614..5c73a8f 100755
--- a/src/csharp/build_packages_dotnetcli.sh
+++ b/src/csharp/build_packages_dotnetcli.sh
@@ -45,7 +45,7 @@
 dotnet pack --configuration Release Grpc.HealthCheck --output ../../../artifacts
 dotnet pack --configuration Release Grpc.Reflection --output ../../../artifacts
 
-nuget pack Grpc.nuspec -Version "1.11.0-dev" -OutputDirectory ../../artifacts
-nuget pack Grpc.Tools.nuspec -Version "1.11.0-dev" -OutputDirectory ../../artifacts
+nuget pack Grpc.nuspec -Version "1.13.0-dev" -OutputDirectory ../../artifacts
+nuget pack Grpc.Tools.nuspec -Version "1.13.0-dev" -OutputDirectory ../../artifacts
 
 (cd ../../artifacts && zip csharp_nugets_dotnetcli.zip *.nupkg)
diff --git a/src/csharp/experimental/build_native_ext_for_android.sh b/src/csharp/experimental/build_native_ext_for_android.sh
index 958778e..8197df7 100755
--- a/src/csharp/experimental/build_native_ext_for_android.sh
+++ b/src/csharp/experimental/build_native_ext_for_android.sh
@@ -23,7 +23,7 @@
 cd build
 
 # set to the location where Android SDK is installed
-ANDROID_NDK_PATH="$HOME/android-ndk-r16b"
+# e.g. ANDROID_NDK_PATH="$HOME/android-ndk-r16b"
 
 cmake ../.. \
   -DCMAKE_SYSTEM_NAME=Android \
diff --git a/src/csharp/generate_proto_csharp.sh b/src/csharp/generate_proto_csharp.sh
index 299dc3f..1a38f86 100755
--- a/src/csharp/generate_proto_csharp.sh
+++ b/src/csharp/generate_proto_csharp.sh
@@ -42,4 +42,4 @@
 # don't match the package names. Setting -I to the correct value src/proto
 # breaks the code generation.
 $PROTOC --plugin=$PLUGIN --csharp_out=$TESTING_DIR --grpc_out=$TESTING_DIR \
-    -I . src/proto/grpc/testing/{control,echo_messages,empty,messages,metrics,payloads,services,stats,test}.proto
+    -I . src/proto/grpc/testing/{control,echo_messages,empty,messages,metrics,payloads,benchmark_service,report_qps_scenario_service,worker_service,stats,test}.proto
diff --git a/src/csharp/global.json b/src/csharp/global.json
deleted file mode 100644
index 815be4b..0000000
--- a/src/csharp/global.json
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-  "sdk": {
-    "version": "2.1.4"
-  }
-}
diff --git "a/src/objective-c/\041ProtoCompiler-gRPCPlugin.podspec" "b/src/objective-c/\041ProtoCompiler-gRPCPlugin.podspec"
index 954beed..515dc91 100644
--- "a/src/objective-c/\041ProtoCompiler-gRPCPlugin.podspec"
+++ "b/src/objective-c/\041ProtoCompiler-gRPCPlugin.podspec"
@@ -42,7 +42,7 @@
   # exclamation mark ensures that other "regular" pods will be able to find it as it'll be installed
   # before them.
   s.name     = '!ProtoCompiler-gRPCPlugin'
-  v = '1.11.0-dev'
+  v = '1.13.0-dev'
   s.version  = v
   s.summary  = 'The gRPC ProtoC plugin generates Objective-C files from .proto services.'
   s.description = <<-DESC
diff --git a/src/objective-c/BoringSSL.podspec b/src/objective-c/BoringSSL.podspec
index 8a32e97..ff55320 100644
--- a/src/objective-c/BoringSSL.podspec
+++ b/src/objective-c/BoringSSL.podspec
@@ -31,7 +31,7 @@
 
 Pod::Spec.new do |s|
   s.name     = 'BoringSSL'
-  version = '10.0'
+  version = '10.0.2'
   s.version  = version
   s.summary  = 'BoringSSL is a fork of OpenSSL that is designed to meet Google’s needs.'
   # Adapted from the homepage:
@@ -67,11 +67,9 @@
   # "The name and email addresses of the library maintainers, not the Podspec maintainer."
   s.authors  = 'Adam Langley', 'David Benjamin', 'Matt Braithwaite'
 
-  versions = version.split('.')
-  major_version = versions[0] + '.0'
   s.source = {
     :git => 'https://boringssl.googlesource.com/boringssl',
-    :tag => "version_for_cocoapods_#{major_version}",
+    :commit => "a20bb7ff8bb5057065a2e7941249773f9676cf45",
   }
 
   s.ios.deployment_target = '5.0'
@@ -123,7 +121,8 @@
                       'ssl/**/*.{h,cc}',
                       '*.{h,c}',
                       'crypto/*.{h,c}',
-                      'crypto/**/*.{h,c}'
+                      'crypto/**/*.{h,c}',
+                      'third_party/fiat/*.{h,c}'
     ss.private_header_files = 'ssl/*.h',
                               'ssl/**/*.h',
                               '*.h',
diff --git a/src/objective-c/GRPCClient/GRPCCall+ChannelArg.h b/src/objective-c/GRPCClient/GRPCCall+ChannelArg.h
index 18d4597..c05ba54 100644
--- a/src/objective-c/GRPCClient/GRPCCall+ChannelArg.h
+++ b/src/objective-c/GRPCClient/GRPCCall+ChannelArg.h
@@ -39,11 +39,20 @@
 /** The default response size limit is 4MB. Set this to override that default. */
 + (void)setResponseSizeLimit:(NSUInteger)limit forHost:(nonnull NSString *)host;
 
-+ (void)closeOpenConnections DEPRECATED_MSG_ATTRIBUTE("The API for this feature is experimental, "
-                                                      "and might be removed or modified at any "
-                                                      "time.");
++ (void)closeOpenConnections DEPRECATED_MSG_ATTRIBUTE(
+    "The API for this feature is experimental, "
+    "and might be removed or modified at any "
+    "time.");
 
-+ (void)setDefaultCompressMethod:(GRPCCompressAlgorithm)algorithm
-                         forhost:(nonnull NSString *)host;
++ (void)setDefaultCompressMethod:(GRPCCompressAlgorithm)algorithm forhost:(nonnull NSString *)host;
+
+/** Enable keepalive and configure keepalive parameters. A user should call this function once to
+ * enable keepalive for a particular host. gRPC client sends a ping after every \a interval ms to
+ * check if the transport is still alive. After waiting for \a timeout ms, if the client does not
+ * receive the ping ack, it closes the transport; all pending calls to this host will fail with
+ * error GRPC_STATUS_INTERNAL with error information "keepalive watchdog timeout". */
++ (void)setKeepaliveWithInterval:(int)interval
+                         timeout:(int)timeout
+                         forHost:(nonnull NSString *)host;
 
 @end
diff --git a/src/objective-c/GRPCClient/GRPCCall+ChannelArg.m b/src/objective-c/GRPCClient/GRPCCall+ChannelArg.m
index 805e54b..8f9c1b9 100644
--- a/src/objective-c/GRPCClient/GRPCCall+ChannelArg.m
+++ b/src/objective-c/GRPCClient/GRPCCall+ChannelArg.m
@@ -38,8 +38,7 @@
   [GRPCHost flushChannelCache];
 }
 
-+ (void)setDefaultCompressMethod:(GRPCCompressAlgorithm)algorithm
-                         forhost:(nonnull NSString *)host {
++ (void)setDefaultCompressMethod:(GRPCCompressAlgorithm)algorithm forhost:(nonnull NSString *)host {
   GRPCHost *hostConfig = [GRPCHost hostWithAddress:host];
   switch (algorithm) {
     case GRPCCompressNone:
@@ -57,4 +56,12 @@
   }
 }
 
++ (void)setKeepaliveWithInterval:(int)interval
+                         timeout:(int)timeout
+                         forHost:(nonnull NSString *)host {
+  GRPCHost *hostConfig = [GRPCHost hostWithAddress:host];
+  hostConfig.keepaliveInterval = interval;
+  hostConfig.keepaliveTimeout = timeout;
+}
+
 @end
diff --git a/src/objective-c/GRPCClient/GRPCCall+ChannelCredentials.h b/src/objective-c/GRPCClient/GRPCCall+ChannelCredentials.h
index c0d36b5..d7d15c4 100644
--- a/src/objective-c/GRPCClient/GRPCCall+ChannelCredentials.h
+++ b/src/objective-c/GRPCClient/GRPCCall+ChannelCredentials.h
@@ -26,7 +26,7 @@
  */
 + (BOOL)setTLSPEMRootCerts:(nullable NSString *)pemRootCert
                    forHost:(nonnull NSString *)host
-                     error:(NSError * _Nullable * _Nullable)errorPtr;
+                     error:(NSError *_Nullable *_Nullable)errorPtr;
 /**
  * Configures @c host with TLS/SSL Client Credentials and optionally trusted root Certificate
  * Authorities. If @c pemRootCerts is nil, the default CA Certificates bundled with gRPC will be
@@ -36,6 +36,6 @@
             withPrivateKey:(nullable NSString *)pemPrivateKey
              withCertChain:(nullable NSString *)pemCertChain
                    forHost:(nonnull NSString *)host
-                     error:(NSError * _Nullable * _Nullable)errorPtr;
+                     error:(NSError *_Nullable *_Nullable)errorPtr;
 
 @end
diff --git a/src/objective-c/GRPCClient/GRPCCall+ChannelCredentials.m b/src/objective-c/GRPCClient/GRPCCall+ChannelCredentials.m
index 00f3e4e..2689ec2 100644
--- a/src/objective-c/GRPCClient/GRPCCall+ChannelCredentials.m
+++ b/src/objective-c/GRPCClient/GRPCCall+ChannelCredentials.m
@@ -28,24 +28,23 @@
                    forHost:(nonnull NSString *)host
                      error:(NSError **)errorPtr {
   if (!host) {
-    [NSException raise:NSInvalidArgumentException
-                format:@"host must be provided."];
+    [NSException raise:NSInvalidArgumentException format:@"host must be provided."];
   }
   GRPCHost *hostConfig = [GRPCHost hostWithAddress:host];
   return [hostConfig setTLSPEMRootCerts:pemRootCerts
-                 withPrivateKey:pemPrivateKey
-                  withCertChain:pemCertChain
-                          error:errorPtr];
+                         withPrivateKey:pemPrivateKey
+                          withCertChain:pemCertChain
+                                  error:errorPtr];
 }
 
 + (BOOL)setTLSPEMRootCerts:(nullable NSString *)pemRootCerts
                    forHost:(nonnull NSString *)host
                      error:(NSError **)errorPtr {
   return [GRPCCall setTLSPEMRootCerts:pemRootCerts
-               withPrivateKey:nil
-                withCertChain:nil
-                      forHost:host
-                      error:errorPtr];
+                       withPrivateKey:nil
+                        withCertChain:nil
+                              forHost:host
+                                error:errorPtr];
 }
 
 @end
diff --git a/src/objective-c/GRPCClient/GRPCCall+Cronet.h b/src/objective-c/GRPCClient/GRPCCall+Cronet.h
index e084bf1..2a5f6e9 100644
--- a/src/objective-c/GRPCClient/GRPCCall+Cronet.h
+++ b/src/objective-c/GRPCClient/GRPCCall+Cronet.h
@@ -32,11 +32,11 @@
  * all subsequent RPCs will use Cronet transport. The method is not thread
  * safe.
  */
-+(void)useCronetWithEngine:(stream_engine *)engine;
++ (void)useCronetWithEngine:(stream_engine*)engine;
 
-+(stream_engine *)cronetEngine;
++ (stream_engine*)cronetEngine;
 
-+(BOOL)isUsingCronet;
++ (BOOL)isUsingCronet;
 
 @end
 #endif
diff --git a/src/objective-c/GRPCClient/GRPCCall+GID.h b/src/objective-c/GRPCClient/GRPCCall+GID.h
index 3ee732e..8293e92 100644
--- a/src/objective-c/GRPCClient/GRPCCall+GID.h
+++ b/src/objective-c/GRPCClient/GRPCCall+GID.h
@@ -16,14 +16,14 @@
  *
  */
 
-#import "GRPCCall.h"
 #import "GRPCCall+OAuth2.h"
+#import "GRPCCall.h"
 
 #import <Google/SignIn.h>
 
 /**
  * Extend GIDSignIn class to comply GRPCAuthorizationProtocol
  */
-@interface GIDSignIn (GRPC) <GRPCAuthorizationProtocol>
+@interface GIDSignIn (GRPC)<GRPCAuthorizationProtocol>
 - (void)getTokenWithHandler:(void (^)(NSString *token))hander;
 @end
diff --git a/src/objective-c/GRPCClient/GRPCCall+OAuth2.m b/src/objective-c/GRPCClient/GRPCCall+OAuth2.m
index 8451ebe..3292b6c 100644
--- a/src/objective-c/GRPCClient/GRPCCall+OAuth2.m
+++ b/src/objective-c/GRPCClient/GRPCCall+OAuth2.m
@@ -20,9 +20,9 @@
 
 #import "GRPCCall+OAuth2.h"
 
-static NSString * const kAuthorizationHeader = @"authorization";
-static NSString * const kBearerPrefix = @"Bearer ";
-static NSString * const kChallengeHeader = @"www-authenticate";
+static NSString *const kAuthorizationHeader = @"authorization";
+static NSString *const kBearerPrefix = @"Bearer ";
+static NSString *const kChallengeHeader = @"www-authenticate";
 
 @implementation GRPCCall (OAuth2)
 @dynamic tokenProvider;
diff --git a/src/objective-c/GRPCClient/GRPCCall+Tests.m b/src/objective-c/GRPCClient/GRPCCall+Tests.m
index aa9af9f..0db3ad6 100644
--- a/src/objective-c/GRPCClient/GRPCCall+Tests.m
+++ b/src/objective-c/GRPCClient/GRPCCall+Tests.m
@@ -29,11 +29,10 @@
     [NSException raise:NSInvalidArgumentException format:@"host, path and name must be provided."];
   }
   NSError *error = nil;
-  NSString *certs = [NSString stringWithContentsOfFile:certsPath
-                                                      encoding:NSUTF8StringEncoding
-                                                      error:&error];
+  NSString *certs =
+      [NSString stringWithContentsOfFile:certsPath encoding:NSUTF8StringEncoding error:&error];
   if (error != nil) {
-      [NSException raise:[error localizedDescription] format:@"failed to load certs"];
+    [NSException raise:[error localizedDescription] format:@"failed to load certs"];
   }
 
   GRPCHost *hostConfig = [GRPCHost hostWithAddress:host];
diff --git a/src/objective-c/GRPCClient/GRPCCall.h b/src/objective-c/GRPCClient/GRPCCall.h
index df563ca..e0ef8b1 100644
--- a/src/objective-c/GRPCClient/GRPCCall.h
+++ b/src/objective-c/GRPCClient/GRPCCall.h
@@ -147,7 +147,8 @@
   GRPCCallSafetyDefault = 0,
   /** Signal that the call is idempotent. gRPC is free to use PUT verb. */
   GRPCCallSafetyIdempotentRequest = 1,
-  /** Signal that the call is cacheable and will not affect server state. gRPC is free to use GET verb. */
+  /** Signal that the call is cacheable and will not affect server state. gRPC is free to use GET
+     verb. */
   GRPCCallSafetyCacheableRequest = 2,
 };
 
@@ -167,7 +168,7 @@
  * The authority for the RPC. If nil, the default authority will be used. This property must be nil
  * when Cronet transport is enabled.
  */
-@property (atomic, copy, readwrite) NSString *serverName;
+@property(atomic, copy, readwrite) NSString *serverName;
 
 /**
  * The timeout for the RPC call in seconds. If set to 0, the call will not timeout. If set to
@@ -265,7 +266,7 @@
 
 /** This protocol is kept for backwards compatibility with existing code. */
 DEPRECATED_MSG_ATTRIBUTE("Use NSDictionary or NSMutableDictionary instead.")
-@protocol GRPCRequestHeaders <NSObject>
+@protocol GRPCRequestHeaders<NSObject>
 @property(nonatomic, readonly) NSUInteger count;
 
 - (id)objectForKeyedSubscript:(id)key;
@@ -278,6 +279,6 @@
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wdeprecated"
 /** This is only needed for backwards-compatibility. */
-@interface NSMutableDictionary (GRPCRequestHeaders) <GRPCRequestHeaders>
+@interface NSMutableDictionary (GRPCRequestHeaders)<GRPCRequestHeaders>
 @end
 #pragma clang diagnostic pop
diff --git a/src/objective-c/GRPCClient/GRPCCall.m b/src/objective-c/GRPCClient/GRPCCall.m
index ea658bc..75dda9d 100644
--- a/src/objective-c/GRPCClient/GRPCCall.m
+++ b/src/objective-c/GRPCClient/GRPCCall.m
@@ -20,10 +20,10 @@
 
 #import "GRPCCall+OAuth2.h"
 
-#include <grpc/grpc.h>
-#include <grpc/support/time.h>
 #import <RxLibrary/GRXConcurrentWriteable.h>
 #import <RxLibrary/GRXImmediateSingleWriter.h>
+#include <grpc/grpc.h>
+#include <grpc/support/time.h>
 
 #import "private/GRPCConnectivityMonitor.h"
 #import "private/GRPCHost.h"
@@ -38,14 +38,14 @@
 // and RECV_STATUS_ON_CLIENT.
 NSInteger kMaxClientBatch = 6;
 
-NSString * const kGRPCHeadersKey = @"io.grpc.HeadersKey";
-NSString * const kGRPCTrailersKey = @"io.grpc.TrailersKey";
+NSString *const kGRPCHeadersKey = @"io.grpc.HeadersKey";
+NSString *const kGRPCTrailersKey = @"io.grpc.TrailersKey";
 static NSMutableDictionary *callFlags;
 
-static NSString * const kAuthorizationHeader = @"authorization";
-static NSString * const kBearerPrefix = @"Bearer ";
+static NSString *const kAuthorizationHeader = @"authorization";
+static NSString *const kBearerPrefix = @"Bearer ";
 
-@interface GRPCCall () <GRXWriteable>
+@interface GRPCCall ()<GRXWriteable>
 // Make them read-write.
 @property(atomic, strong) NSDictionary *responseHeaders;
 @property(atomic, strong) NSDictionary *responseTrailers;
@@ -196,9 +196,6 @@
     _state = GRXWriterStateFinished;
   }
 
-  // If the call isn't retained anywhere else, it can be deallocated now.
-  _retainSelf = nil;
-
   // If there were still request messages coming, stop them.
   @synchronized(_requestWriter) {
     _requestWriter.state = GRXWriterStateFinished;
@@ -211,6 +208,9 @@
   }
 
   [GRPCConnectivityMonitor unregisterObserver:self];
+
+  // If the call isn't retained anywhere else, it can be deallocated now.
+  _retainSelf = nil;
 }
 
 - (void)cancelCall {
@@ -219,9 +219,11 @@
 }
 
 - (void)cancel {
-  [self maybeFinishWithError:[NSError errorWithDomain:kGRPCErrorDomain
-                                                 code:GRPCErrorCodeCancelled
-                                             userInfo:@{NSLocalizedDescriptionKey: @"Canceled by app"}]];
+  [self
+      maybeFinishWithError:[NSError
+                               errorWithDomain:kGRPCErrorDomain
+                                          code:GRPCErrorCodeCancelled
+                                      userInfo:@{NSLocalizedDescriptionKey : @"Canceled by app"}]];
 
   if (!self.isWaitingForToken) {
     [self cancelCall];
@@ -254,9 +256,9 @@
 
 // Only called from the call queue.
 // The handler will be called from the network queue.
-- (void)startReadWithHandler:(void(^)(grpc_byte_buffer *))handler {
+- (void)startReadWithHandler:(void (^)(grpc_byte_buffer *))handler {
   // TODO(jcanizales): Add error handlers for async failures
-  [_wrappedCall startBatchWithOperations:@[[[GRPCOpRecvMessage alloc] initWithHandler:handler]]];
+  [_wrappedCall startBatchWithOperations:@[ [[GRPCOpRecvMessage alloc] initWithHandler:handler] ]];
 }
 
 // Called initially from the network queue once response headers are received,
@@ -287,15 +289,21 @@
         // don't want to throw, because the app shouldn't crash for a behavior
         // that's on the hands of any server to have. Instead we finish and ask
         // the server to cancel.
-        [strongSelf maybeFinishWithError:[NSError errorWithDomain:kGRPCErrorDomain
-                                                             code:GRPCErrorCodeResourceExhausted
-                                                         userInfo:@{NSLocalizedDescriptionKey: @"Client does not have enough memory to hold the server response."}]];
+        [strongSelf
+            maybeFinishWithError:[NSError errorWithDomain:kGRPCErrorDomain
+                                                     code:GRPCErrorCodeResourceExhausted
+                                                 userInfo:@{
+                                                   NSLocalizedDescriptionKey :
+                                                       @"Client does not have enough memory to "
+                                                       @"hold the server response."
+                                                 }]];
         [strongSelf cancelCall];
         return;
       }
-      [strongWriteable enqueueValue:data completionHandler:^{
-        [strongSelf startNextRead];
-      }];
+      [strongWriteable enqueueValue:data
+                  completionHandler:^{
+                    [strongSelf startNextRead];
+                  }];
     }];
   });
 }
@@ -304,11 +312,12 @@
 
 - (void)sendHeaders:(NSDictionary *)headers {
   // TODO(jcanizales): Add error handlers for async failures
-  GRPCOpSendMetadata *op = [[GRPCOpSendMetadata alloc] initWithMetadata:headers
-                                                                  flags:[GRPCCall callFlagsForHost:_host path:_path]
-                                                                handler:nil];  // No clean-up needed after SEND_INITIAL_METADATA
+  GRPCOpSendMetadata *op = [[GRPCOpSendMetadata alloc]
+      initWithMetadata:headers
+                 flags:[GRPCCall callFlagsForHost:_host path:_path]
+               handler:nil];  // No clean-up needed after SEND_INITIAL_METADATA
   if (!_unaryCall) {
-    [_wrappedCall startBatchWithOperations:@[op]];
+    [_wrappedCall startBatchWithOperations:@[ op ]];
   } else {
     [_unaryOpBatch addObject:op];
   }
@@ -321,9 +330,8 @@
 // If the call is a unary call, parameter \a errorHandler will be ignored and
 // the error handler of GRPCOpSendClose will be executed in case of error.
 - (void)writeMessage:(NSData *)message withErrorHandler:(void (^)(void))errorHandler {
-
   __weak GRPCCall *weakSelf = self;
-  void(^resumingHandler)(void) = ^{
+  void (^resumingHandler)(void) = ^{
     // Resume the request writer.
     GRPCCall *strongSelf = weakSelf;
     if (strongSelf) {
@@ -333,11 +341,10 @@
     }
   };
 
-  GRPCOpSendMessage *op = [[GRPCOpSendMessage alloc] initWithMessage:message
-                                                             handler:resumingHandler];
+  GRPCOpSendMessage *op =
+      [[GRPCOpSendMessage alloc] initWithMessage:message handler:resumingHandler];
   if (!_unaryCall) {
-    [_wrappedCall startBatchWithOperations:@[op]
-                              errorHandler:errorHandler];
+    [_wrappedCall startBatchWithOperations:@[ op ] errorHandler:errorHandler];
   } else {
     // Ignored errorHandler since it is the same as the one for GRPCOpSendClose.
     // TODO (mxyan): unify the error handlers of all Ops into a single closure.
@@ -355,17 +362,8 @@
   }
 
   dispatch_async(_callQueue, ^{
-    __weak GRPCCall *weakSelf = self;
-    [self writeMessage:value withErrorHandler:^{
-      __strong GRPCCall *strongSelf = weakSelf;
-      if (strongSelf != nil) {
-        [strongSelf maybeFinishWithError:[NSError errorWithDomain:kGRPCErrorDomain
-                                                             code:GRPCErrorCodeInternal
-                                                         userInfo:nil]];
-        // Wrapped call must be canceled when error is reported to upper layers
-        [strongSelf cancelCall];
-      }
-    }];
+    // Write error is not processed here. It is handled by op batch of GRPC_OP_RECV_STATUS_ON_CLIENT
+    [self writeMessage:value withErrorHandler:nil];
   });
 }
 
@@ -373,12 +371,11 @@
 // network queue if the requests stream couldn't be closed successfully.
 - (void)finishRequestWithErrorHandler:(void (^)(void))errorHandler {
   if (!_unaryCall) {
-    [_wrappedCall startBatchWithOperations:@[[[GRPCOpSendClose alloc] init]]
+    [_wrappedCall startBatchWithOperations:@[ [[GRPCOpSendClose alloc] init] ]
                               errorHandler:errorHandler];
   } else {
     [_unaryOpBatch addObject:[[GRPCOpSendClose alloc] init]];
-    [_wrappedCall startBatchWithOperations:_unaryOpBatch
-                              errorHandler:errorHandler];
+    [_wrappedCall startBatchWithOperations:_unaryOpBatch errorHandler:errorHandler];
   }
 }
 
@@ -387,15 +384,8 @@
     [self cancel];
   } else {
     dispatch_async(_callQueue, ^{
-      __weak GRPCCall *weakSelf = self;
-      [self finishRequestWithErrorHandler:^{
-        __strong GRPCCall *strongSelf = weakSelf;
-        [strongSelf maybeFinishWithError:[NSError errorWithDomain:kGRPCErrorDomain
-                                                             code:GRPCErrorCodeInternal
-                                                         userInfo:nil]];
-        // Wrapped call must be canceled when error is reported to upper layers
-        [strongSelf cancelCall];
-      }];
+      // EOS error is not processed here. It is handled by op batch of GRPC_OP_RECV_STATUS_ON_CLIENT
+      [self finishRequestWithErrorHandler:nil];
     });
   }
 }
@@ -406,13 +396,13 @@
 // after this.
 // The first one (headersHandler), when the response headers are received.
 // The second one (completionHandler), whenever the RPC finishes for any reason.
-- (void)invokeCallWithHeadersHandler:(void(^)(NSDictionary *))headersHandler
-                    completionHandler:(void(^)(NSError *, NSDictionary *))completionHandler {
+- (void)invokeCallWithHeadersHandler:(void (^)(NSDictionary *))headersHandler
+                   completionHandler:(void (^)(NSError *, NSDictionary *))completionHandler {
   // TODO(jcanizales): Add error handlers for async failures
-  [_wrappedCall startBatchWithOperations:@[[[GRPCOpRecvMetadata alloc]
-                                            initWithHandler:headersHandler]]];
-  [_wrappedCall startBatchWithOperations:@[[[GRPCOpRecvStatus alloc]
-                                            initWithHandler:completionHandler]]];
+  [_wrappedCall
+      startBatchWithOperations:@[ [[GRPCOpRecvMetadata alloc] initWithHandler:headersHandler] ]];
+  [_wrappedCall
+      startBatchWithOperations:@[ [[GRPCOpRecvStatus alloc] initWithHandler:completionHandler] ]];
 }
 
 - (void)invokeCall {
@@ -424,30 +414,31 @@
       strongSelf.responseHeaders = headers;
       [strongSelf startNextRead];
     }
-  } completionHandler:^(NSError *error, NSDictionary *trailers) {
-    __strong GRPCCall *strongSelf = weakSelf;
-    if (strongSelf) {
-      strongSelf.responseTrailers = trailers;
+  }
+      completionHandler:^(NSError *error, NSDictionary *trailers) {
+        __strong GRPCCall *strongSelf = weakSelf;
+        if (strongSelf) {
+          strongSelf.responseTrailers = trailers;
 
-      if (error) {
-        NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
-        if (error.userInfo) {
-          [userInfo addEntriesFromDictionary:error.userInfo];
+          if (error) {
+            NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
+            if (error.userInfo) {
+              [userInfo addEntriesFromDictionary:error.userInfo];
+            }
+            userInfo[kGRPCTrailersKey] = strongSelf.responseTrailers;
+            // TODO(jcanizales): The C gRPC library doesn't guarantee that the headers block will be
+            // called before this one, so an error might end up with trailers but no headers. We
+            // shouldn't call finishWithError until ater both blocks are called. It is also when
+            // this is done that we can provide a merged view of response headers and trailers in a
+            // thread-safe way.
+            if (strongSelf.responseHeaders) {
+              userInfo[kGRPCHeadersKey] = strongSelf.responseHeaders;
+            }
+            error = [NSError errorWithDomain:error.domain code:error.code userInfo:userInfo];
+          }
+          [strongSelf maybeFinishWithError:error];
         }
-        userInfo[kGRPCTrailersKey] = strongSelf.responseTrailers;
-        // TODO(jcanizales): The C gRPC library doesn't guarantee that the headers block will be
-        // called before this one, so an error might end up with trailers but no headers. We
-        // shouldn't call finishWithError until ater both blocks are called. It is also when this is
-        // done that we can provide a merged view of response headers and trailers in a thread-safe
-        // way.
-        if (strongSelf.responseHeaders) {
-          userInfo[kGRPCHeadersKey] = strongSelf.responseHeaders;
-        }
-        error = [NSError errorWithDomain:error.domain code:error.code userInfo:userInfo];
-      }
-      [strongSelf maybeFinishWithError:error];
-    }
-  }];
+      }];
   // Now that the RPC has been initiated, request writes can start.
   @synchronized(_requestWriter) {
     [_requestWriter startWithWriteable:self];
@@ -457,8 +448,8 @@
 #pragma mark GRXWriter implementation
 
 - (void)startCallWithWriteable:(id<GRXWriteable>)writeable {
-  _responseWriteable = [[GRXConcurrentWriteable alloc] initWithWriteable:writeable
-                                                           dispatchQueue:_responseQueue];
+  _responseWriteable =
+      [[GRXConcurrentWriteable alloc] initWithWriteable:writeable dispatchQueue:_responseQueue];
 
   _wrappedCall = [[GRPCWrappedCall alloc] initWithHost:_host
                                             serverName:_serverName
@@ -469,8 +460,7 @@
   [self sendHeaders:_requestHeaders];
   [self invokeCall];
 
-  [GRPCConnectivityMonitor registerObserver:self
-                                   selector:@selector(connectivityChanged:)];
+  [GRPCConnectivityMonitor registerObserver:self selector:@selector(connectivityChanged:)];
 }
 
 - (void)startWithWriteable:(id<GRXWriteable>)writeable {
@@ -488,7 +478,7 @@
   if (self.tokenProvider != nil) {
     self.isWaitingForToken = YES;
     __weak typeof(self) weakSelf = self;
-    [self.tokenProvider getTokenWithHandler:^(NSString *token){
+    [self.tokenProvider getTokenWithHandler:^(NSString *token) {
       typeof(self) strongSelf = weakSelf;
       if (strongSelf && strongSelf.isWaitingForToken) {
         if (token) {
@@ -537,7 +527,9 @@
 - (void)connectivityChanged:(NSNotification *)note {
   [self maybeFinishWithError:[NSError errorWithDomain:kGRPCErrorDomain
                                                  code:GRPCErrorCodeUnavailable
-                                             userInfo:@{ NSLocalizedDescriptionKey : @"Connectivity lost." }]];
+                                             userInfo:@{
+                                               NSLocalizedDescriptionKey : @"Connectivity lost."
+                                             }]];
   // Cancel underlying call upon this notification
   [self cancelCall];
 }
diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.h b/src/objective-c/GRPCClient/private/GRPCChannel.h
index d37182f..6499d43 100644
--- a/src/objective-c/GRPCClient/private/GRPCChannel.h
+++ b/src/objective-c/GRPCClient/private/GRPCChannel.h
@@ -23,7 +23,6 @@
 @class GRPCCompletionQueue;
 struct grpc_channel_credentials;
 
-
 /**
  * Each separate instance of this class represents at least one TCP connection to the provided host.
  */
@@ -52,8 +51,9 @@
  * @c channelArgs. Only in tests should @c GRPC_SSL_TARGET_NAME_OVERRIDE_ARG channel arg be set.
  */
 + (nonnull GRPCChannel *)secureChannelWithHost:(nonnull NSString *)host
-    credentials:(nonnull struct grpc_channel_credentials *)credentials
-    channelArgs:(nullable NSDictionary *)channelArgs;
+                                   credentials:
+                                       (nonnull struct grpc_channel_credentials *)credentials
+                                   channelArgs:(nullable NSDictionary *)channelArgs;
 
 /**
  * Creates an insecure channel to the specified @c host using the specified @c channelArgs.
diff --git a/src/objective-c/GRPCClient/private/GRPCChannel.m b/src/objective-c/GRPCClient/private/GRPCChannel.m
index b53d841..a49a489 100644
--- a/src/objective-c/GRPCClient/private/GRPCChannel.m
+++ b/src/objective-c/GRPCClient/private/GRPCChannel.m
@@ -32,7 +32,7 @@
 #endif
 #import "GRPCCompletionQueue.h"
 
-static void* copy_pointer_arg(void *p) {
+static void *copy_pointer_arg(void *p) {
   // Add ref count to the object when making copy
   id obj = (__bridge id)p;
   return (__bridge_retained void *)obj;
@@ -43,12 +43,10 @@
   CFRelease((CFTreeRef)p);
 }
 
-static int cmp_pointer_arg(void *p, void *q) {
-  return p == q;
-}
+static int cmp_pointer_arg(void *p, void *q) { return p == q; }
 
-static const grpc_arg_pointer_vtable objc_arg_vtable = {
-  copy_pointer_arg, destroy_pointer_arg, cmp_pointer_arg};
+static const grpc_arg_pointer_vtable objc_arg_vtable = {copy_pointer_arg, destroy_pointer_arg,
+                                                        cmp_pointer_arg};
 
 static void FreeChannelArgs(grpc_channel_args *channel_args) {
   for (size_t i = 0; i < channel_args->num_args; ++i) {
@@ -124,10 +122,8 @@
   if (self = [super init]) {
     _channelArgs = BuildChannelArgs(channelArgs);
     _host = [host copy];
-    _unmanagedChannel = grpc_cronet_secure_channel_create(cronetEngine,
-                                                          _host.UTF8String,
-                                                          _channelArgs,
-                                                          NULL);
+    _unmanagedChannel =
+        grpc_cronet_secure_channel_create(cronetEngine, _host.UTF8String, _channelArgs, NULL);
   }
 
   return self;
@@ -150,8 +146,8 @@
     _channelArgs = BuildChannelArgs(channelArgs);
     _host = [host copy];
     if (secure) {
-      _unmanagedChannel = grpc_secure_channel_create(credentials, _host.UTF8String, _channelArgs,
-                                                     NULL);
+      _unmanagedChannel =
+          grpc_secure_channel_create(credentials, _host.UTF8String, _channelArgs, NULL);
     } else {
       _unmanagedChannel = grpc_insecure_channel_create(_host.UTF8String, _channelArgs, NULL);
     }
@@ -172,8 +168,7 @@
                                  channelArgs:(NSDictionary *)channelArgs {
   stream_engine *engine = [GRPCCall cronetEngine];
   if (!engine) {
-    [NSException raise:NSInvalidArgumentException
-                format:@"cronet_engine is NULL. Set it first."];
+    [NSException raise:NSInvalidArgumentException format:@"cronet_engine is NULL. Set it first."];
     return nil;
   }
   return [[GRPCChannel alloc] initWithHost:host cronetEngine:engine channelArgs:channelArgs];
@@ -191,15 +186,10 @@
                                     secure:YES
                                credentials:credentials
                                channelArgs:channelArgs];
-
 }
 
-+ (GRPCChannel *)insecureChannelWithHost:(NSString *)host
-                             channelArgs:(NSDictionary *)channelArgs {
-  return [[GRPCChannel alloc] initWithHost:host
-                                    secure:NO
-                               credentials:NULL
-                               channelArgs:channelArgs];
++ (GRPCChannel *)insecureChannelWithHost:(NSString *)host channelArgs:(NSDictionary *)channelArgs {
+  return [[GRPCChannel alloc] initWithHost:host secure:NO credentials:NULL channelArgs:channelArgs];
 }
 
 - (grpc_call *)unmanagedCallWithPath:(NSString *)path
@@ -215,17 +205,13 @@
     host_slice = grpc_slice_from_copied_string(serverName.UTF8String);
   }
   grpc_slice path_slice = grpc_slice_from_copied_string(path.UTF8String);
-  gpr_timespec deadline_ms = timeout == 0 ?
-                                gpr_inf_future(GPR_CLOCK_REALTIME) :
-                                gpr_time_add(
-                                    gpr_now(GPR_CLOCK_MONOTONIC),
-                                    gpr_time_from_millis((int64_t)(timeout * 1000), GPR_TIMESPAN));
-  grpc_call *call = grpc_channel_create_call(_unmanagedChannel,
-                                             NULL, GRPC_PROPAGATE_DEFAULTS,
-                                             queue.unmanagedQueue,
-                                             path_slice,
-                                             serverName ? &host_slice : NULL,
-                                             deadline_ms, NULL);
+  gpr_timespec deadline_ms =
+      timeout == 0 ? gpr_inf_future(GPR_CLOCK_REALTIME)
+                   : gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
+                                  gpr_time_from_millis((int64_t)(timeout * 1000), GPR_TIMESPAN));
+  grpc_call *call = grpc_channel_create_call(_unmanagedChannel, NULL, GRPC_PROPAGATE_DEFAULTS,
+                                             queue.unmanagedQueue, path_slice,
+                                             serverName ? &host_slice : NULL, deadline_ms, NULL);
   if (serverName) {
     grpc_slice_unref(host_slice);
   }
diff --git a/src/objective-c/GRPCClient/private/GRPCCompletionQueue.h b/src/objective-c/GRPCClient/private/GRPCCompletionQueue.h
index 41f5da3..5b017b4 100644
--- a/src/objective-c/GRPCClient/private/GRPCCompletionQueue.h
+++ b/src/objective-c/GRPCClient/private/GRPCCompletionQueue.h
@@ -19,7 +19,7 @@
 #import <Foundation/Foundation.h>
 #include <grpc/grpc.h>
 
-typedef void(^GRPCQueueCompletionHandler)(bool success);
+typedef void (^GRPCQueueCompletionHandler)(bool success);
 
 /**
  * This class lets one more easily use |grpc_completion_queue|. To use it, pass the value of the
diff --git a/src/objective-c/GRPCClient/private/GRPCCompletionQueue.m b/src/objective-c/GRPCClient/private/GRPCCompletionQueue.m
index 7ba1978..57dbde8 100644
--- a/src/objective-c/GRPCClient/private/GRPCCompletionQueue.m
+++ b/src/objective-c/GRPCClient/private/GRPCCompletionQueue.m
@@ -53,9 +53,8 @@
     dispatch_async(gDefaultConcurrentQueue, ^{
       while (YES) {
         // The following call blocks until an event is available.
-        grpc_event event = grpc_completion_queue_next(unmanagedQueue,
-                                                      gpr_inf_future(GPR_CLOCK_REALTIME),
-                                                      NULL);
+        grpc_event event =
+            grpc_completion_queue_next(unmanagedQueue, gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
         GRPCQueueCompletionHandler handler;
         switch (event.type) {
           case GRPC_OP_COMPLETE:
diff --git a/src/objective-c/GRPCClient/private/GRPCConnectivityMonitor.h b/src/objective-c/GRPCClient/private/GRPCConnectivityMonitor.h
index 394d217..d4b49b1 100644
--- a/src/objective-c/GRPCClient/private/GRPCConnectivityMonitor.h
+++ b/src/objective-c/GRPCClient/private/GRPCConnectivityMonitor.h
@@ -26,7 +26,7 @@
   GRPCConnectivityWiFi = 3,
 };
 
-extern NSString * _Nonnull kGRPCConnectivityNotification;
+extern NSString* _Nonnull kGRPCConnectivityNotification;
 
 // This interface monitors OS reachability interface for any network status
 // change. Parties interested in these events should register themselves as
@@ -39,8 +39,7 @@
 // must have a notification method with one parameter of type
 // (NSNotification *) and should pass it to parameter \a selector. The
 // parameter of this notification method is not used for now.
-+ (void)registerObserver:(_Nonnull id)observer
-                selector:(_Nonnull SEL)selector;
++ (void)registerObserver:(_Nonnull id)observer selector:(_Nonnull SEL)selector;
 
 // Ungegister an object from observers of network status change.
 + (void)unregisterObserver:(_Nonnull id)observer;
diff --git a/src/objective-c/GRPCClient/private/GRPCConnectivityMonitor.m b/src/objective-c/GRPCClient/private/GRPCConnectivityMonitor.m
index 7f31c7e..a36788b 100644
--- a/src/objective-c/GRPCClient/private/GRPCConnectivityMonitor.m
+++ b/src/objective-c/GRPCClient/private/GRPCConnectivityMonitor.m
@@ -41,8 +41,8 @@
   return result;
 }
 
-static void ReachabilityCallback(
-    SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info) {
+static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags,
+                                 void *info) {
   GRPCConnectivityStatus newStatus = CalculateConnectivityStatus(flags);
 
   if (newStatus != currentStatus) {
@@ -69,15 +69,14 @@
 
     SCNetworkReachabilityContext context = {0, (__bridge void *)(self), NULL, NULL, NULL};
     if (!SCNetworkReachabilitySetCallback(reachability, ReachabilityCallback, &context) ||
-        !SCNetworkReachabilityScheduleWithRunLoop(
-            reachability, CFRunLoopGetMain(), kCFRunLoopCommonModes)) {
+        !SCNetworkReachabilityScheduleWithRunLoop(reachability, CFRunLoopGetMain(),
+                                                  kCFRunLoopCommonModes)) {
       NSLog(@"gRPC connectivity monitor fail to set");
     }
   }
 }
 
-+ (void)registerObserver:(_Nonnull id)observer
-                selector:(SEL)selector {
++ (void)registerObserver:(_Nonnull id)observer selector:(SEL)selector {
   [[NSNotificationCenter defaultCenter] addObserver:observer
                                            selector:selector
                                                name:kGRPCConnectivityNotification
diff --git a/src/objective-c/GRPCClient/private/GRPCHost.h b/src/objective-c/GRPCClient/private/GRPCHost.h
index 0215db8..6697f61 100644
--- a/src/objective-c/GRPCClient/private/GRPCHost.h
+++ b/src/objective-c/GRPCClient/private/GRPCHost.h
@@ -35,6 +35,8 @@
 @property(nonatomic, copy, nullable) NSString *userAgentPrefix;
 @property(nonatomic, nullable) struct grpc_channel_credentials *channelCreds;
 @property(nonatomic) grpc_compression_algorithm compressAlgorithm;
+@property(nonatomic) int keepaliveInterval;
+@property(nonatomic) int keepaliveTimeout;
 
 /** The following properties should only be modified for testing: */
 
@@ -45,7 +47,6 @@
 /** The default response size limit is 4MB. Set this to override that default. */
 @property(nonatomic, strong, nullable) NSNumber *responseSizeLimitOverride;
 
-
 - (nullable instancetype)init NS_UNAVAILABLE;
 /** Host objects initialized with the same address are the same. */
 + (nullable instancetype)hostWithAddress:(NSString *)address;
diff --git a/src/objective-c/GRPCClient/private/GRPCHost.m b/src/objective-c/GRPCClient/private/GRPCHost.m
index 8568e33..bfb1fd3 100644
--- a/src/objective-c/GRPCClient/private/GRPCHost.m
+++ b/src/objective-c/GRPCClient/private/GRPCHost.m
@@ -18,10 +18,10 @@
 
 #import "GRPCHost.h"
 
+#import <GRPCClient/GRPCCall+MobileLog.h>
+#import <GRPCClient/GRPCCall.h>
 #include <grpc/grpc.h>
 #include <grpc/grpc_security.h>
-#import <GRPCClient/GRPCCall.h>
-#import <GRPCClient/GRPCCall+MobileLog.h>
 #ifdef GRPC_COMPILE_WITH_CRONET
 #import <GRPCClient/GRPCCall+ChannelArg.h>
 #import <GRPCClient/GRPCCall+Cronet.h>
@@ -91,16 +91,15 @@
 
 + (void)flushChannelCache {
   @synchronized(kHostCache) {
-    [kHostCache enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key,
-                                                    GRPCHost * _Nonnull host,
-                                                    BOOL * _Nonnull stop) {
+    [kHostCache enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, GRPCHost *_Nonnull host,
+                                                    BOOL *_Nonnull stop) {
       [host disconnect];
     }];
   }
 }
 
 + (void)resetAllHostSettings {
-  @synchronized (kHostCache) {
+  @synchronized(kHostCache) {
     kHostCache = [NSMutableDictionary dictionary];
   }
 }
@@ -109,7 +108,10 @@
                                    serverName:(NSString *)serverName
                                       timeout:(NSTimeInterval)timeout
                               completionQueue:(GRPCCompletionQueue *)queue {
-  GRPCChannel *channel;
+  // The __block attribute is to allow channel take refcount inside @synchronized block. Without
+  // this attribute, retain of channel object happens after objc_sync_exit in release builds, which
+  // may result in channel released before used. See grpc/#15033.
+  __block GRPCChannel *channel;
   // This is racing -[GRPCHost disconnect].
   @synchronized(self) {
     if (!_channel) {
@@ -131,38 +133,38 @@
   static NSError *kDefaultRootsError;
   static dispatch_once_t loading;
   dispatch_once(&loading, ^{
-    NSString *defaultPath = @"gRPCCertificates.bundle/roots"; // .pem
+    NSString *defaultPath = @"gRPCCertificates.bundle/roots";  // .pem
     // Do not use NSBundle.mainBundle, as it's nil for tests of library projects.
     NSBundle *bundle = [NSBundle bundleForClass:self.class];
     NSString *path = [bundle pathForResource:defaultPath ofType:@"pem"];
     NSError *error;
     // Files in PEM format can have non-ASCII characters in their comments (e.g. for the name of the
     // issuer). Load them as UTF8 and produce an ASCII equivalent.
-    NSString *contentInUTF8 = [NSString stringWithContentsOfFile:path
-                                                        encoding:NSUTF8StringEncoding
-                                                           error:&error];
+    NSString *contentInUTF8 =
+        [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&error];
     if (contentInUTF8 == nil) {
       kDefaultRootsError = error;
       return;
     }
-    kDefaultRootsASCII = [contentInUTF8 dataUsingEncoding:NSASCIIStringEncoding
-                                     allowLossyConversion:YES];
+    kDefaultRootsASCII =
+        [contentInUTF8 dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
   });
 
   NSData *rootsASCII;
   if (pemRootCerts != nil) {
-    rootsASCII = [pemRootCerts dataUsingEncoding:NSASCIIStringEncoding
-                            allowLossyConversion:YES];
+    rootsASCII = [pemRootCerts dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
   } else {
     if (kDefaultRootsASCII == nil) {
       if (errorPtr) {
         *errorPtr = kDefaultRootsError;
       }
-      NSAssert(kDefaultRootsASCII, @"Could not read gRPCCertificates.bundle/roots.pem. This file, "
-               "with the root certificates, is needed to establish secure (TLS) connections. "
-               "Because the file is distributed with the gRPC library, this error is usually a sign "
-               "that the library wasn't configured correctly for your project. Error: %@",
-                kDefaultRootsError);
+      NSAssert(
+          kDefaultRootsASCII,
+          @"Could not read gRPCCertificates.bundle/roots.pem. This file, "
+           "with the root certificates, is needed to establish secure (TLS) connections. "
+           "Because the file is distributed with the gRPC library, this error is usually a sign "
+           "that the library wasn't configured correctly for your project. Error: %@",
+          kDefaultRootsError);
       return NO;
     }
     rootsASCII = kDefaultRootsASCII;
@@ -173,10 +175,10 @@
     creds = grpc_ssl_credentials_create(rootsASCII.bytes, NULL, NULL);
   } else {
     grpc_ssl_pem_key_cert_pair key_cert_pair;
-    NSData *privateKeyASCII = [pemPrivateKey dataUsingEncoding:NSASCIIStringEncoding
-                                       allowLossyConversion:YES];
-    NSData *certChainASCII = [pemCertChain dataUsingEncoding:NSASCIIStringEncoding
-                                     allowLossyConversion:YES];
+    NSData *privateKeyASCII =
+        [pemPrivateKey dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
+    NSData *certChainASCII =
+        [pemCertChain dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
     key_cert_pair.private_key = privateKeyASCII.bytes;
     key_cert_pair.cert_chain = certChainASCII.bytes;
     creds = grpc_ssl_credentials_create(rootsASCII.bytes, &key_cert_pair, NULL);
@@ -192,7 +194,7 @@
   return YES;
 }
 
-- (NSDictionary *)channelArgs {
+- (NSDictionary *)channelArgsUsingCronet:(BOOL)useCronet {
   NSMutableDictionary *args = [NSMutableDictionary dictionary];
 
   // TODO(jcanizales): Add OS and device information (see
@@ -212,8 +214,12 @@
   }
 
   if (_compressAlgorithm != GRPC_COMPRESS_NONE) {
-    args[@GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM] =
-        [NSNumber numberWithInt:_compressAlgorithm];
+    args[@GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM] = [NSNumber numberWithInt:_compressAlgorithm];
+  }
+
+  if (_keepaliveInterval != 0) {
+    args[@GRPC_ARG_KEEPALIVE_TIME_MS] = [NSNumber numberWithInt:_keepaliveInterval];
+    args[@GRPC_ARG_KEEPALIVE_TIMEOUT_MS] = [NSNumber numberWithInt:_keepaliveTimeout];
   }
 
   id logConfig = [GRPCCall logConfig];
@@ -221,14 +227,19 @@
     args[@GRPC_ARG_MOBILE_LOG_CONFIG] = logConfig;
   }
 
+  if (useCronet) {
+    args[@GRPC_ARG_DISABLE_CLIENT_AUTHORITY_FILTER] = [NSNumber numberWithInt:1];
+  }
+
   return args;
 }
 
 - (GRPCChannel *)newChannel {
-  NSDictionary *args = [self channelArgs];
+  BOOL useCronet = NO;
 #ifdef GRPC_COMPILE_WITH_CRONET
-  BOOL useCronet = [GRPCCall isUsingCronet];
+  useCronet = [GRPCCall isUsingCronet];
 #endif
+  NSDictionary *args = [self channelArgsUsingCronet:useCronet];
   if (_secure) {
     GRPCChannel *channel;
     @synchronized(self) {
@@ -237,14 +248,12 @@
       }
 #ifdef GRPC_COMPILE_WITH_CRONET
       if (useCronet) {
-        channel = [GRPCChannel secureCronetChannelWithHost:_address
-                                               channelArgs:args];
+        channel = [GRPCChannel secureCronetChannelWithHost:_address channelArgs:args];
       } else
 #endif
       {
-        channel = [GRPCChannel secureChannelWithHost:_address
-                                         credentials:_channelCreds
-                                         channelArgs:args];
+        channel =
+            [GRPCChannel secureChannelWithHost:_address credentials:_channelCreds channelArgs:args];
       }
     }
     return channel;
diff --git a/src/objective-c/GRPCClient/private/GRPCOpBatchLog.h b/src/objective-c/GRPCClient/private/GRPCOpBatchLog.h
index ca4b6c5..700d19a 100644
--- a/src/objective-c/GRPCClient/private/GRPCOpBatchLog.h
+++ b/src/objective-c/GRPCClient/private/GRPCOpBatchLog.h
@@ -16,7 +16,6 @@
  *
  */
 
-
 #ifdef GRPC_TEST_OBJC
 
 /**
diff --git a/src/objective-c/GRPCClient/private/GRPCOpBatchLog.m b/src/objective-c/GRPCClient/private/GRPCOpBatchLog.m
index fdf0fcd..0082324 100644
--- a/src/objective-c/GRPCClient/private/GRPCOpBatchLog.m
+++ b/src/objective-c/GRPCClient/private/GRPCOpBatchLog.m
@@ -25,7 +25,7 @@
 @implementation GRPCOpBatchLog
 
 + (void)enableOpBatchLog:(BOOL)enabled {
-  @synchronized (opBatchLog) {
+  @synchronized(opBatchLog) {
     if (enabled) {
       if (!opBatchLog) {
         opBatchLog = [NSMutableArray array];
@@ -39,13 +39,13 @@
 }
 
 + (void)addOpBatchToLog:(NSArray *)batch {
-  @synchronized (opBatchLog) {
+  @synchronized(opBatchLog) {
     [opBatchLog addObject:batch];
   }
 }
 
 + (NSArray *)obtainAndCleanOpBatchLog {
-  @synchronized (opBatchLog) {
+  @synchronized(opBatchLog) {
     NSArray *out = opBatchLog;
     opBatchLog = [NSMutableArray array];
     return out;
diff --git a/src/objective-c/GRPCClient/private/GRPCReachabilityFlagNames.xmacro.h b/src/objective-c/GRPCClient/private/GRPCReachabilityFlagNames.xmacro.h
index 9e32fb5..2e8e34e 100644
--- a/src/objective-c/GRPCClient/private/GRPCReachabilityFlagNames.xmacro.h
+++ b/src/objective-c/GRPCClient/private/GRPCReachabilityFlagNames.xmacro.h
@@ -17,7 +17,8 @@
  */
 
 /**
- * "X-macro" file that lists the flags names of Apple's Network Reachability API, along with a nice
+ * "X-macro" file that lists the flags names of Apple's Network Reachability
+API, along with a nice
  * Objective-C method name used to query each of them.
  *
  * Example usage: To generate a dictionary from flag value to name, one can do:
@@ -29,7 +30,8 @@
 #undef GRPC_XMACRO_ITEM
   };
 
-  XCTAssertEqualObjects(flagNames[@(kSCNetworkReachabilityFlagsIsWWAN)], @"isCell");
+  XCTAssertEqualObjects(flagNames[@(kSCNetworkReachabilityFlagsIsWWAN)],
+@"isCell");
 
  */
 
diff --git a/src/objective-c/GRPCClient/private/GRPCRequestHeaders.m b/src/objective-c/GRPCClient/private/GRPCRequestHeaders.m
index 5de1d8f..fa4f022 100644
--- a/src/objective-c/GRPCClient/private/GRPCRequestHeaders.m
+++ b/src/objective-c/GRPCClient/private/GRPCRequestHeaders.m
@@ -23,7 +23,7 @@
 #import "NSDictionary+GRPC.h"
 
 // Used by the setter.
-static void CheckIsNonNilASCII(NSString *name, NSString* value) {
+static void CheckIsNonNilASCII(NSString *name, NSString *value) {
   if (!value) {
     [NSException raise:NSInvalidArgumentException format:@"%@ cannot be nil", name];
   }
@@ -38,14 +38,18 @@
   if ([key hasSuffix:@"-bin"]) {
     if (![value isKindOfClass:NSData.class]) {
       [NSException raise:NSInvalidArgumentException
-                  format:@"Expected NSData value for header %@ ending in \"-bin\", "
-       @"instead got %@", key, value];
+                  format:
+                      @"Expected NSData value for header %@ ending in \"-bin\", "
+                      @"instead got %@",
+                      key, value];
     }
   } else {
     if (![value isKindOfClass:NSString.class]) {
       [NSException raise:NSInvalidArgumentException
-                  format:@"Expected NSString value for header %@ not ending in \"-bin\", "
-       @"instead got %@", key, value];
+                  format:
+                      @"Expected NSString value for header %@ not ending in \"-bin\", "
+                      @"instead got %@",
+                      key, value];
     }
     CheckIsNonNilASCII(@"Text header value", (NSString *)value);
   }
@@ -85,8 +89,8 @@
   return self;
 }
 
-- (instancetype)initWithObjects:(const id  _Nonnull __unsafe_unretained *)objects
-                        forKeys:(const id<NSCopying>  _Nonnull __unsafe_unretained *)keys
+- (instancetype)initWithObjects:(const id _Nonnull __unsafe_unretained *)objects
+                        forKeys:(const id<NSCopying> _Nonnull __unsafe_unretained *)keys
                           count:(NSUInteger)cnt {
   return [self init];
 }
@@ -118,7 +122,7 @@
   return _delegate.count;
 }
 
-- (NSEnumerator * _Nonnull)keyEnumerator {
+- (NSEnumerator *_Nonnull)keyEnumerator {
   return [_delegate keyEnumerator];
 }
 
diff --git a/src/objective-c/GRPCClient/private/GRPCWrappedCall.h b/src/objective-c/GRPCClient/private/GRPCWrappedCall.h
index f569895..f711850 100644
--- a/src/objective-c/GRPCClient/private/GRPCWrappedCall.h
+++ b/src/objective-c/GRPCClient/private/GRPCWrappedCall.h
@@ -29,43 +29,42 @@
 
 @interface GRPCOpSendMetadata : GRPCOperation
 
-- (instancetype)initWithMetadata:(NSDictionary *)metadata
-                         handler:(void(^)(void))handler;
+- (instancetype)initWithMetadata:(NSDictionary *)metadata handler:(void (^)(void))handler;
 
 - (instancetype)initWithMetadata:(NSDictionary *)metadata
                            flags:(uint32_t)flags
-                         handler:(void(^)(void))handler NS_DESIGNATED_INITIALIZER;
+                         handler:(void (^)(void))handler NS_DESIGNATED_INITIALIZER;
 
 @end
 
 @interface GRPCOpSendMessage : GRPCOperation
 
 - (instancetype)initWithMessage:(NSData *)message
-                        handler:(void(^)(void))handler NS_DESIGNATED_INITIALIZER;
+                        handler:(void (^)(void))handler NS_DESIGNATED_INITIALIZER;
 
 @end
 
 @interface GRPCOpSendClose : GRPCOperation
 
-- (instancetype)initWithHandler:(void(^)(void))handler NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithHandler:(void (^)(void))handler NS_DESIGNATED_INITIALIZER;
 
 @end
 
 @interface GRPCOpRecvMetadata : GRPCOperation
 
-- (instancetype)initWithHandler:(void(^)(NSDictionary *))handler NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithHandler:(void (^)(NSDictionary *))handler NS_DESIGNATED_INITIALIZER;
 
 @end
 
 @interface GRPCOpRecvMessage : GRPCOperation
 
-- (instancetype)initWithHandler:(void(^)(grpc_byte_buffer *))handler NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithHandler:(void (^)(grpc_byte_buffer *))handler NS_DESIGNATED_INITIALIZER;
 
 @end
 
 @interface GRPCOpRecvStatus : GRPCOperation
 
-- (instancetype)initWithHandler:(void(^)(NSError *, NSDictionary *))handler
+- (instancetype)initWithHandler:(void (^)(NSError *, NSDictionary *))handler
     NS_DESIGNATED_INITIALIZER;
 
 @end
@@ -79,7 +78,7 @@
                         path:(NSString *)path
                      timeout:(NSTimeInterval)timeout NS_DESIGNATED_INITIALIZER;
 
-- (void)startBatchWithOperations:(NSArray *)ops errorHandler:(void(^)(void))errorHandler;
+- (void)startBatchWithOperations:(NSArray *)ops errorHandler:(void (^)(void))errorHandler;
 
 - (void)startBatchWithOperations:(NSArray *)ops;
 
diff --git a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m
index 9a0fa59..f28e494 100644
--- a/src/objective-c/GRPCClient/private/GRPCWrappedCall.m
+++ b/src/objective-c/GRPCClient/private/GRPCWrappedCall.m
@@ -19,29 +19,29 @@
 #import "GRPCWrappedCall.h"
 
 #import <Foundation/Foundation.h>
-#include <grpc/grpc.h>
 #include <grpc/byte_buffer.h>
+#include <grpc/grpc.h>
 #include <grpc/support/alloc.h>
 
 #import "GRPCCompletionQueue.h"
 #import "GRPCHost.h"
-#import "NSDictionary+GRPC.h"
 #import "NSData+GRPC.h"
+#import "NSDictionary+GRPC.h"
 #import "NSError+GRPC.h"
 
 #import "GRPCOpBatchLog.h"
 
 @implementation GRPCOperation {
-@protected
+ @protected
   // Most operation subclasses don't set any flags in the grpc_op, and rely on the flag member being
   // initialized to zero.
   grpc_op _op;
-  void(^_handler)(void);
+  void (^_handler)(void);
 }
 
 - (void)finish {
   if (_handler) {
-    void(^handler)(void) = _handler;
+    void (^handler)(void) = _handler;
     _handler = nil;
     handler();
   }
@@ -54,8 +54,7 @@
   return [self initWithMetadata:nil flags:0 handler:nil];
 }
 
-- (instancetype)initWithMetadata:(NSDictionary *)metadata
-                         handler:(void (^)(void))handler {
+- (instancetype)initWithMetadata:(NSDictionary *)metadata handler:(void (^)(void))handler {
   return [self initWithMetadata:metadata flags:0 handler:handler];
 }
 
@@ -128,11 +127,11 @@
   grpc_metadata_array _headers;
 }
 
-- (instancetype) init {
+- (instancetype)init {
   return [self initWithHandler:nil];
 }
 
-- (instancetype) initWithHandler:(void (^)(NSDictionary *))handler {
+- (instancetype)initWithHandler:(void (^)(NSDictionary *))handler {
   if (self = [super init]) {
     _op.op = GRPC_OP_RECV_INITIAL_METADATA;
     grpc_metadata_array_init(&_headers);
@@ -142,8 +141,8 @@
       __weak typeof(self) weakSelf = self;
       _handler = ^{
         __strong typeof(self) strongSelf = weakSelf;
-        NSDictionary *metadata = [NSDictionary
-                                  grpc_dictionaryFromMetadataArray:strongSelf->_headers];
+        NSDictionary *metadata =
+            [NSDictionary grpc_dictionaryFromMetadataArray:strongSelf->_headers];
         handler(metadata);
       };
     }
@@ -157,7 +156,7 @@
 
 @end
 
-@implementation GRPCOpRecvMessage{
+@implementation GRPCOpRecvMessage {
   grpc_byte_buffer *_receivedMessage;
 }
 
@@ -183,18 +182,18 @@
 
 @end
 
-@implementation GRPCOpRecvStatus{
+@implementation GRPCOpRecvStatus {
   grpc_status_code _statusCode;
   grpc_slice _details;
   size_t _detailsCapacity;
   grpc_metadata_array _trailers;
 }
 
-- (instancetype) init {
+- (instancetype)init {
   return [self initWithHandler:nil];
 }
 
-- (instancetype) initWithHandler:(void (^)(NSError *, NSDictionary *))handler {
+- (instancetype)initWithHandler:(void (^)(NSError *, NSDictionary *))handler {
   if (self = [super init]) {
     _op.op = GRPC_OP_RECV_STATUS_ON_CLIENT;
     _op.data.recv_status_on_client.status = &_statusCode;
@@ -208,10 +207,10 @@
         __strong typeof(self) strongSelf = weakSelf;
         if (strongSelf) {
           char *details = grpc_slice_to_c_string(strongSelf->_details);
-          NSError *error = [NSError grpc_errorFromStatusCode:strongSelf->_statusCode
-                                                     details:details];
-          NSDictionary *trailers = [NSDictionary
-                                    grpc_dictionaryFromMetadataArray:strongSelf->_trailers];
+          NSError *error =
+              [NSError grpc_errorFromStatusCode:strongSelf->_statusCode details:details];
+          NSDictionary *trailers =
+              [NSDictionary grpc_dictionaryFromMetadataArray:strongSelf->_trailers];
           handler(error, trailers);
           gpr_free(details);
         }
@@ -244,8 +243,7 @@
                         path:(NSString *)path
                      timeout:(NSTimeInterval)timeout {
   if (!path || !host) {
-    [NSException raise:NSInvalidArgumentException
-                format:@"path and host cannot be nil."];
+    [NSException raise:NSInvalidArgumentException format:@"path and host cannot be nil."];
   }
 
   if (self = [super init]) {
@@ -270,8 +268,8 @@
 }
 
 - (void)startBatchWithOperations:(NSArray *)operations errorHandler:(void (^)(void))errorHandler {
-  // Keep logs of op batches when we are running tests. Disabled when in production for improved
-  // performance.
+// Keep logs of op batches when we are running tests. Disabled when in production for improved
+// performance.
 #ifdef GRPC_TEST_OBJC
   [GRPCOpBatchLog addOpBatchToLog:operations];
 #endif
@@ -282,25 +280,26 @@
   for (GRPCOperation *operation in operations) {
     ops_array[i++] = operation.op;
   }
-  grpc_call_error error = grpc_call_start_batch(_call, ops_array, nops,
-                                                (__bridge_retained void *)(^(bool success){
-    if (!success) {
-      if (errorHandler) {
-        errorHandler();
-      } else {
-        return;
-      }
-    }
-    for (GRPCOperation *operation in operations) {
-      [operation finish];
-    }
-  }), NULL);
+  grpc_call_error error =
+      grpc_call_start_batch(_call, ops_array, nops, (__bridge_retained void *)(^(bool success) {
+                              if (!success) {
+                                if (errorHandler) {
+                                  errorHandler();
+                                } else {
+                                  return;
+                                }
+                              }
+                              for (GRPCOperation *operation in operations) {
+                                [operation finish];
+                              }
+                            }),
+                            NULL);
   gpr_free(ops_array);
 
   if (error != GRPC_CALL_OK) {
-    [NSException raise:NSInternalInconsistencyException
-                format:@"A precondition for calling grpc_call_start_batch wasn't met. Error %i",
-     error];
+    [NSException
+         raise:NSInternalInconsistencyException
+        format:@"A precondition for calling grpc_call_start_batch wasn't met. Error %i", error];
   }
 }
 
diff --git a/src/objective-c/GRPCClient/private/NSData+GRPC.m b/src/objective-c/GRPCClient/private/NSData+GRPC.m
index 7c46594..5064da3 100644
--- a/src/objective-c/GRPCClient/private/NSData+GRPC.m
+++ b/src/objective-c/GRPCClient/private/NSData+GRPC.m
@@ -24,8 +24,8 @@
 
 // TODO(jcanizales): Move these two incantations to the C library.
 
-static void MallocAndCopyByteBufferToCharArray(grpc_byte_buffer *buffer,
-                                               size_t *length, char **array) {
+static void MallocAndCopyByteBufferToCharArray(grpc_byte_buffer *buffer, size_t *length,
+                                               char **array) {
   grpc_byte_buffer_reader reader;
   if (!grpc_byte_buffer_reader_init(&reader, buffer)) {
     // grpc_byte_buffer_reader_init can fail if the data sent by the server
@@ -51,8 +51,7 @@
   grpc_byte_buffer_reader_destroy(&reader);
 }
 
-static grpc_byte_buffer *CopyCharArrayToNewByteBuffer(const char *array,
-                                                      size_t length) {
+static grpc_byte_buffer *CopyCharArrayToNewByteBuffer(const char *array, size_t length) {
   grpc_slice slice = grpc_slice_from_copied_buffer(array, length);
   grpc_byte_buffer *buffer = grpc_raw_byte_buffer_create(&slice, 1);
   grpc_slice_unref(slice);
@@ -89,7 +88,6 @@
   // to create an array of grpc_slice objects to pass to
   // grpc_raw_byte_buffer_create.
   // That would make it do exactly one copy, always.
-  return CopyCharArrayToNewByteBuffer((const char *)self.bytes,
-                                      (size_t)self.length);
+  return CopyCharArrayToNewByteBuffer((const char *)self.bytes, (size_t)self.length);
 }
 @end
diff --git a/src/objective-c/GRPCClient/private/NSDictionary+GRPC.m b/src/objective-c/GRPCClient/private/NSDictionary+GRPC.m
index 4af7cb9..af1ce0b 100644
--- a/src/objective-c/GRPCClient/private/NSDictionary+GRPC.m
+++ b/src/objective-c/GRPCClient/private/NSDictionary+GRPC.m
@@ -74,8 +74,7 @@
   NSMutableDictionary *metadata = [NSMutableDictionary dictionaryWithCapacity:count];
   for (grpc_metadata *entry = entries; entry < entries + count; entry++) {
     char *key = grpc_slice_to_c_string(entry->key);
-    NSString *name = [NSString stringWithCString:key
-                                        encoding:NSASCIIStringEncoding];
+    NSString *name = [NSString stringWithCString:key encoding:NSASCIIStringEncoding];
     gpr_free(key);
     if (!name || metadata[name]) {
       // Log if name is nil?
@@ -97,7 +96,7 @@
 - (grpc_metadata *)grpc_metadataArray {
   grpc_metadata *metadata = gpr_malloc([self count] * sizeof(grpc_metadata));
   grpc_metadata *current = metadata;
-  for (NSString* key in self) {
+  for (NSString *key in self) {
     id value = self[key];
     current->key = grpc_slice_from_copied_string(key.UTF8String);
     if ([value respondsToSelector:@selector(grpc_initMetadata:)]) {
diff --git a/src/objective-c/GRPCClient/private/NSError+GRPC.m b/src/objective-c/GRPCClient/private/NSError+GRPC.m
index 6ba7235..74cfa94 100644
--- a/src/objective-c/GRPCClient/private/NSError+GRPC.m
+++ b/src/objective-c/GRPCClient/private/NSError+GRPC.m
@@ -20,7 +20,7 @@
 
 #include <grpc/grpc.h>
 
-NSString * const kGRPCErrorDomain = @"io.grpc";
+NSString *const kGRPCErrorDomain = @"io.grpc";
 
 @implementation NSError (GRPC)
 + (instancetype)grpc_errorFromStatusCode:(grpc_status_code)statusCode details:(char *)details {
@@ -30,6 +30,6 @@
   NSString *message = [NSString stringWithCString:details encoding:NSASCIIStringEncoding];
   return [NSError errorWithDomain:kGRPCErrorDomain
                              code:statusCode
-                         userInfo:@{NSLocalizedDescriptionKey: message}];
+                         userInfo:@{NSLocalizedDescriptionKey : message}];
 }
 @end
diff --git a/src/objective-c/GRPCClient/private/version.h b/src/objective-c/GRPCClient/private/version.h
index 405c2ff..6fe4a7d 100644
--- a/src/objective-c/GRPCClient/private/version.h
+++ b/src/objective-c/GRPCClient/private/version.h
@@ -22,5 +22,4 @@
 // instead. This file can be regenerated from the template by running
 // `tools/buildgen/generate_projects.sh`.
 
-
-#define GRPC_OBJC_VERSION_STRING @"1.11.0-dev"
+#define GRPC_OBJC_VERSION_STRING @"1.13.0-dev"
diff --git a/src/objective-c/ProtoRPC/ProtoMethod.h b/src/objective-c/ProtoRPC/ProtoMethod.h
index 227154c..3ba0f70 100644
--- a/src/objective-c/ProtoRPC/ProtoMethod.h
+++ b/src/objective-c/ProtoRPC/ProtoMethod.h
@@ -22,9 +22,8 @@
  * A fully-qualified proto service method name. Full qualification is needed because a gRPC endpoint
  * can implement multiple services.
  */
-__attribute__((deprecated("Please use GRPCProtoMethod.")))
-@interface ProtoMethod : NSObject
-@property(nonatomic, readonly) NSString *package;
+__attribute__((deprecated("Please use GRPCProtoMethod."))) @interface ProtoMethod
+    : NSObject @property(nonatomic, readonly) NSString *package;
 @property(nonatomic, readonly) NSString *service;
 @property(nonatomic, readonly) NSString *method;
 
@@ -41,7 +40,7 @@
  */
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
-@interface GRPCProtoMethod : ProtoMethod
+    @interface GRPCProtoMethod : ProtoMethod
 #pragma clang diagnostic pop
 
-@end
+                                 @end
diff --git a/src/objective-c/ProtoRPC/ProtoRPC.h b/src/objective-c/ProtoRPC/ProtoRPC.h
index 2546edc..45d3526 100644
--- a/src/objective-c/ProtoRPC/ProtoRPC.h
+++ b/src/objective-c/ProtoRPC/ProtoRPC.h
@@ -21,18 +21,18 @@
 
 #import "ProtoMethod.h"
 
-__attribute__((deprecated("Please use GRPCProtoCall.")))
-@interface ProtoRPC : GRPCCall
+__attribute__((deprecated("Please use GRPCProtoCall."))) @interface ProtoRPC
+    : GRPCCall
 
-/**
- * host parameter should not contain the scheme (http:// or https://), only the name or IP addr
- * and the port number, for example @"localhost:5050".
- */
-- (instancetype)initWithHost:(NSString *)host
-                      method:(GRPCProtoMethod *)method
-              requestsWriter:(GRXWriter *)requestsWriter
-               responseClass:(Class)responseClass
-          responsesWriteable:(id<GRXWriteable>)responsesWriteable NS_DESIGNATED_INITIALIZER;
+      /**
+       * host parameter should not contain the scheme (http:// or https://), only the name or IP
+       * addr and the port number, for example @"localhost:5050".
+       */
+      -
+      (instancetype)initWithHost : (NSString *)host method
+    : (GRPCProtoMethod *)method requestsWriter : (GRXWriter *)requestsWriter responseClass
+    : (Class)responseClass responsesWriteable
+    : (id<GRXWriteable>)responsesWriteable NS_DESIGNATED_INITIALIZER;
 
 - (void)start;
 @end
@@ -43,7 +43,7 @@
  */
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
-@interface GRPCProtoCall : ProtoRPC
+    @interface GRPCProtoCall : ProtoRPC
 #pragma clang diagnostic pop
 
-@end
+                               @end
diff --git a/src/objective-c/ProtoRPC/ProtoRPC.m b/src/objective-c/ProtoRPC/ProtoRPC.m
index 20b9d04..5dca971 100644
--- a/src/objective-c/ProtoRPC/ProtoRPC.m
+++ b/src/objective-c/ProtoRPC/ProtoRPC.m
@@ -19,27 +19,26 @@
 #import "ProtoRPC.h"
 
 #if GPB_USE_PROTOBUF_FRAMEWORK_IMPORTS
- #import <Protobuf/GPBProtocolBuffers.h>
+#import <Protobuf/GPBProtocolBuffers.h>
 #else
- #import <GPBProtocolBuffers.h>
+#import <GPBProtocolBuffers.h>
 #endif
 #import <RxLibrary/GRXWriteable.h>
 #import <RxLibrary/GRXWriter+Transformations.h>
 
 static NSError *ErrorForBadProto(id proto, Class expectedClass, NSError *parsingError) {
   NSDictionary *info = @{
-                         NSLocalizedDescriptionKey: @"Unable to parse response from the server",
-                         NSLocalizedRecoverySuggestionErrorKey: @"If this RPC is idempotent, retry "
-                         @"with exponential backoff. Otherwise, query the server status before "
-                         @"retrying.",
-                         NSUnderlyingErrorKey: parsingError,
-                         @"Expected class": expectedClass,
-                         @"Received value": proto,
-                         };
+    NSLocalizedDescriptionKey : @"Unable to parse response from the server",
+    NSLocalizedRecoverySuggestionErrorKey :
+        @"If this RPC is idempotent, retry "
+        @"with exponential backoff. Otherwise, query the server status before "
+        @"retrying.",
+    NSUnderlyingErrorKey : parsingError,
+    @"Expected class" : expectedClass,
+    @"Received value" : proto,
+  };
   // TODO(jcanizales): Use kGRPCErrorDomain and GRPCErrorCodeInternal when they're public.
-  return [NSError errorWithDomain:@"io.grpc"
-                             code:13
-                         userInfo:info];
+  return [NSError errorWithDomain:@"io.grpc" code:13 userInfo:info];
 }
 
 #pragma clang diagnostic push
@@ -92,9 +91,10 @@
       } else {
         [weakSelf finishWithError:ErrorForBadProto(value, responseClass, error)];
       }
-    } completionHandler:^(NSError *errorOrNil) {
-      [responsesWriteable writesFinishedWithError:errorOrNil];
-    }];
+    }
+        completionHandler:^(NSError *errorOrNil) {
+          [responsesWriteable writesFinishedWithError:errorOrNil];
+        }];
   }
   return self;
 }
diff --git a/src/objective-c/ProtoRPC/ProtoService.h b/src/objective-c/ProtoRPC/ProtoService.h
index 3537896..29c4e9b 100644
--- a/src/objective-c/ProtoRPC/ProtoService.h
+++ b/src/objective-c/ProtoRPC/ProtoService.h
@@ -22,27 +22,24 @@
 @protocol GRXWriteable;
 @class GRXWriter;
 
-
-__attribute__((deprecated("Please use GRPCProtoService.")))
-@interface ProtoService : NSObject
-- (instancetype)initWithHost:(NSString *)host
-                 packageName:(NSString *)packageName
-                 serviceName:(NSString *)serviceName NS_DESIGNATED_INITIALIZER;
+__attribute__((deprecated("Please use GRPCProtoService."))) @interface ProtoService
+    : NSObject -
+      (instancetype)initWithHost : (NSString *)host packageName
+    : (NSString *)packageName serviceName : (NSString *)serviceName NS_DESIGNATED_INITIALIZER;
 
 - (GRPCProtoCall *)RPCToMethod:(NSString *)method
-           requestsWriter:(GRXWriter *)requestsWriter
-  	        responseClass:(Class)responseClass
-  	   responsesWriteable:(id<GRXWriteable>)responsesWriteable;
+                requestsWriter:(GRXWriter *)requestsWriter
+                 responseClass:(Class)responseClass
+            responsesWriteable:(id<GRXWriteable>)responsesWriteable;
 @end
 
-
 /**
  * This subclass is empty now. Eventually we'll remove ProtoService class
  * to avoid potential naming conflict
  */
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
-@interface GRPCProtoService : ProtoService
+    @interface GRPCProtoService : ProtoService
 #pragma clang diagnostic pop
 
-@end
+                                  @end
diff --git a/src/objective-c/ProtoRPC/ProtoService.m b/src/objective-c/ProtoRPC/ProtoService.m
index 611cee4..3e9cc5c 100644
--- a/src/objective-c/ProtoRPC/ProtoService.m
+++ b/src/objective-c/ProtoRPC/ProtoService.m
@@ -57,9 +57,8 @@
                 requestsWriter:(GRXWriter *)requestsWriter
                  responseClass:(Class)responseClass
             responsesWriteable:(id<GRXWriteable>)responsesWriteable {
-  GRPCProtoMethod *methodName = [[GRPCProtoMethod alloc] initWithPackage:_packageName
-                                                                 service:_serviceName
-                                                                  method:method];
+  GRPCProtoMethod *methodName =
+      [[GRPCProtoMethod alloc] initWithPackage:_packageName service:_serviceName method:method];
   return [[GRPCProtoCall alloc] initWithHost:_host
                                       method:methodName
                               requestsWriter:requestsWriter
diff --git a/src/objective-c/RxLibrary/GRXBufferedPipe.m b/src/objective-c/RxLibrary/GRXBufferedPipe.m
index 577a5e9..546d46c 100644
--- a/src/objective-c/RxLibrary/GRXBufferedPipe.m
+++ b/src/objective-c/RxLibrary/GRXBufferedPipe.m
@@ -67,7 +67,7 @@
 #pragma mark GRXWriter implementation
 
 - (void)setState:(GRXWriterState)newState {
-  @synchronized (self) {
+  @synchronized(self) {
     // Manual transitions are only allowed from the started or paused states.
     if (_state == GRXWriterStateNotStarted || _state == GRXWriterStateFinished) {
       return;
@@ -112,8 +112,7 @@
 
 - (void)dealloc {
   GRXWriterState state = self.state;
-  if (state == GRXWriterStateNotStarted ||
-      state == GRXWriterStatePaused) {
+  if (state == GRXWriterStateNotStarted || state == GRXWriterStatePaused) {
     dispatch_resume(_writeQueue);
   }
 }
diff --git a/src/objective-c/RxLibrary/GRXConcurrentWriteable.h b/src/objective-c/RxLibrary/GRXConcurrentWriteable.h
index f16a3d0..abb831e 100644
--- a/src/objective-c/RxLibrary/GRXConcurrentWriteable.h
+++ b/src/objective-c/RxLibrary/GRXConcurrentWriteable.h
@@ -18,8 +18,8 @@
 
 #import <Foundation/Foundation.h>
 
-#import "GRXWriter.h"
 #import "GRXWriteable.h"
+#import "GRXWriter.h"
 
 /**
  * This is a thread-safe wrapper over a GRXWriteable instance. It lets one enqueue calls to a
diff --git a/src/objective-c/RxLibrary/GRXConcurrentWriteable.m b/src/objective-c/RxLibrary/GRXConcurrentWriteable.m
index c262313..523c59c 100644
--- a/src/objective-c/RxLibrary/GRXConcurrentWriteable.m
+++ b/src/objective-c/RxLibrary/GRXConcurrentWriteable.m
@@ -46,8 +46,7 @@
 }
 
 - (instancetype)initWithWriteable:(id<GRXWriteable>)writeable {
-  return [self initWithWriteable:writeable
-                   dispatchQueue:dispatch_get_main_queue()];
+  return [self initWithWriteable:writeable dispatchQueue:dispatch_get_main_queue()];
 }
 
 - (void)enqueueValue:(id)value completionHandler:(void (^)(void))handler {
@@ -69,7 +68,7 @@
     typeof(self) strongSelf = weakSelf;
     if (strongSelf) {
       BOOL finished = NO;
-      @synchronized (self) {
+      @synchronized(self) {
         if (!strongSelf->_alreadyFinished) {
           strongSelf->_alreadyFinished = YES;
         } else {
@@ -90,7 +89,7 @@
 - (void)cancelWithError:(NSError *)error {
   NSAssert(error, @"For a successful completion, use enqueueSuccessfulCompletion.");
   BOOL finished = NO;
-  @synchronized (self) {
+  @synchronized(self) {
     if (!_alreadyFinished) {
       _alreadyFinished = YES;
     } else {
@@ -112,7 +111,7 @@
 
 - (void)cancelSilently {
   BOOL finished = NO;
-  @synchronized (self) {
+  @synchronized(self) {
     if (!_alreadyFinished) {
       _alreadyFinished = YES;
     } else {
diff --git a/src/objective-c/RxLibrary/GRXForwardingWriter.m b/src/objective-c/RxLibrary/GRXForwardingWriter.m
index e7365d3..3e522ef 100644
--- a/src/objective-c/RxLibrary/GRXForwardingWriter.m
+++ b/src/objective-c/RxLibrary/GRXForwardingWriter.m
@@ -18,7 +18,7 @@
 
 #import "GRXForwardingWriter.h"
 
-@interface GRXForwardingWriter () <GRXWriteable>
+@interface GRXForwardingWriter ()<GRXWriteable>
 @end
 
 @implementation GRXForwardingWriter {
diff --git a/src/objective-c/RxLibrary/GRXImmediateWriter.m b/src/objective-c/RxLibrary/GRXImmediateWriter.m
index c5d6d13..0456961 100644
--- a/src/objective-c/RxLibrary/GRXImmediateWriter.m
+++ b/src/objective-c/RxLibrary/GRXImmediateWriter.m
@@ -28,8 +28,8 @@
 
 @synthesize state = _state;
 
-- (instancetype) init {
-  return [self initWithEnumerator:nil error:nil]; // results in an empty writer.
+- (instancetype)init {
+  return [self initWithEnumerator:nil error:nil];  // results in an empty writer.
 }
 
 // Designated initializer
@@ -57,7 +57,8 @@
 }
 
 + (GRXWriter *)writerWithContainer:(id<NSFastEnumeration>)container {
-  return [self writerWithEnumerator:[NSEnumerator grx_enumeratorWithContainer:container]];;
+  return [self writerWithEnumerator:[NSEnumerator grx_enumeratorWithContainer:container]];
+  ;
 }
 
 + (GRXWriter *)writerWithValue:(id)value {
diff --git a/src/objective-c/RxLibrary/GRXWriteable.h b/src/objective-c/RxLibrary/GRXWriteable.h
index d150bc8..71b5979 100644
--- a/src/objective-c/RxLibrary/GRXWriteable.h
+++ b/src/objective-c/RxLibrary/GRXWriteable.h
@@ -22,7 +22,7 @@
  * A GRXWriteable is an object to which a sequence of values can be sent. The
  * sequence finishes with an optional error.
  */
-@protocol GRXWriteable <NSObject>
+@protocol GRXWriteable<NSObject>
 
 /** Push the next value of the sequence to the receiving object. */
 - (void)writeValue:(id)value;
diff --git a/src/objective-c/RxLibrary/GRXWriteable.m b/src/objective-c/RxLibrary/GRXWriteable.m
index fcdf3ba..e6c4c81 100644
--- a/src/objective-c/RxLibrary/GRXWriteable.m
+++ b/src/objective-c/RxLibrary/GRXWriteable.m
@@ -42,9 +42,8 @@
     } else if (error) {
       singleHandler(nil, error);
     } else {
-      NSDictionary *userInfo = @{
-        NSLocalizedDescriptionKey: @"The writer finished without producing any value."
-      };
+      NSDictionary *userInfo =
+          @{NSLocalizedDescriptionKey : @"The writer finished without producing any value."};
       // Even though RxLibrary is independent of gRPC, the domain and code here are, for the moment,
       // set to the values of kGRPCErrorDomain and GRPCErrorCodeInternal. This way, the error formed
       // is the one user of gRPC would expect if the server failed to produce a response.
@@ -55,9 +54,9 @@
       // the two domains.
       static NSString *kGRPCErrorDomain = @"io.grpc";
       static NSUInteger kGRPCErrorCodeInternal = 13;
-      singleHandler(nil, [NSError errorWithDomain:kGRPCErrorDomain
-                                             code:kGRPCErrorCodeInternal
-                                         userInfo:userInfo]);
+      singleHandler(
+          nil,
+          [NSError errorWithDomain:kGRPCErrorDomain code:kGRPCErrorCodeInternal userInfo:userInfo]);
     }
   };
   return [self writeableWithEventHandler:^(BOOL done, id value, NSError *error) {
@@ -73,9 +72,10 @@
   }
   return [[self alloc] initWithValueHandler:^(id value) {
     handler(NO, value, nil);
-  } completionHandler:^(NSError *errorOrNil) {
-    handler(YES, nil, errorOrNil);
-  }];
+  }
+      completionHandler:^(NSError *errorOrNil) {
+        handler(YES, nil, errorOrNil);
+      }];
 }
 
 - (instancetype)init {
diff --git a/src/objective-c/RxLibrary/GRXWriter+Immediate.m b/src/objective-c/RxLibrary/GRXWriter+Immediate.m
index a36a567..58cd8dd 100644
--- a/src/objective-c/RxLibrary/GRXWriter+Immediate.m
+++ b/src/objective-c/RxLibrary/GRXWriter+Immediate.m
@@ -18,8 +18,8 @@
 
 #import "GRXWriter+Immediate.h"
 
-#import "GRXImmediateWriter.h"
 #import "GRXImmediateSingleWriter.h"
+#import "GRXImmediateWriter.h"
 
 @implementation GRXWriter (Immediate)
 
diff --git a/src/objective-c/RxLibrary/transformations/GRXMappingWriter.h b/src/objective-c/RxLibrary/transformations/GRXMappingWriter.h
index 39fe7e1..a344f96 100644
--- a/src/objective-c/RxLibrary/transformations/GRXMappingWriter.h
+++ b/src/objective-c/RxLibrary/transformations/GRXMappingWriter.h
@@ -18,8 +18,9 @@
 
 #import "RxLibrary/GRXForwardingWriter.h"
 
-/** A "proxy" writer that transforms all the values of its input writer by using a mapping function. */
+/** A "proxy" writer that transforms all the values of its input writer by using a mapping function.
+ */
 @interface GRXMappingWriter : GRXForwardingWriter
-- (instancetype)initWithWriter:(GRXWriter *)writer map:(id (^)(id value))map
-    NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithWriter:(GRXWriter *)writer
+                           map:(id (^)(id value))map NS_DESIGNATED_INITIALIZER;
 @end
diff --git a/src/objective-c/RxLibrary/transformations/GRXMappingWriter.m b/src/objective-c/RxLibrary/transformations/GRXMappingWriter.m
index baad4ab..108ed86 100644
--- a/src/objective-c/RxLibrary/transformations/GRXMappingWriter.m
+++ b/src/objective-c/RxLibrary/transformations/GRXMappingWriter.m
@@ -18,7 +18,7 @@
 
 #import "GRXMappingWriter.h"
 
-@interface GRXForwardingWriter () <GRXWriteable>
+@interface GRXForwardingWriter ()<GRXWriteable>
 @end
 
 @implementation GRXMappingWriter {
diff --git a/src/objective-c/examples/Sample/Sample/AppDelegate.h b/src/objective-c/examples/Sample/Sample/AppDelegate.h
index c345a54..2707c8b 100644
--- a/src/objective-c/examples/Sample/Sample/AppDelegate.h
+++ b/src/objective-c/examples/Sample/Sample/AppDelegate.h
@@ -18,6 +18,6 @@
 
 #import <UIKit/UIKit.h>
 
-@interface AppDelegate : UIResponder <UIApplicationDelegate>
-@property (strong, nonatomic) UIWindow *window;
+@interface AppDelegate : UIResponder<UIApplicationDelegate>
+@property(strong, nonatomic) UIWindow* window;
 @end
diff --git a/src/objective-c/examples/Sample/Sample/ViewController.m b/src/objective-c/examples/Sample/Sample/ViewController.m
index a0778df..9bcb002 100644
--- a/src/objective-c/examples/Sample/Sample/ViewController.m
+++ b/src/objective-c/examples/Sample/Sample/ViewController.m
@@ -22,15 +22,15 @@
 #import <ProtoRPC/ProtoMethod.h>
 #import <RemoteTest/Messages.pbobjc.h>
 #import <RemoteTest/Test.pbrpc.h>
-#import <RxLibrary/GRXWriter+Immediate.h>
 #import <RxLibrary/GRXWriteable.h>
+#import <RxLibrary/GRXWriter+Immediate.h>
 
 @implementation ViewController
 
 - (void)viewDidLoad {
   [super viewDidLoad];
 
-  NSString * const kRemoteHost = @"grpc-test.sandbox.googleapis.com";
+  NSString *const kRemoteHost = @"grpc-test.sandbox.googleapis.com";
 
   RMTSimpleRequest *request = [[RMTSimpleRequest alloc] init];
   request.responseSize = 10;
@@ -40,14 +40,14 @@
   // Example gRPC call using a generated proto client library:
 
   RMTTestService *service = [[RMTTestService alloc] initWithHost:kRemoteHost];
-  [service unaryCallWithRequest:request handler:^(RMTSimpleResponse *response, NSError *error) {
-    if (response) {
-      NSLog(@"Finished successfully with response:\n%@", response);
-    } else if (error) {
-      NSLog(@"Finished with error: %@", error);
-    }
-  }];
-
+  [service unaryCallWithRequest:request
+                        handler:^(RMTSimpleResponse *response, NSError *error) {
+                          if (response) {
+                            NSLog(@"Finished successfully with response:\n%@", response);
+                          } else if (error) {
+                            NSLog(@"Finished with error: %@", error);
+                          }
+                        }];
 
   // Same example call using the generic gRPC client library:
 
@@ -61,16 +61,18 @@
                                              path:method.HTTPPath
                                    requestsWriter:requestsWriter];
 
-  id<GRXWriteable> responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) {
-    RMTSimpleResponse *response = [RMTSimpleResponse parseFromData:value error:NULL];
-    NSLog(@"Received response:\n%@", response);
-  } completionHandler:^(NSError *errorOrNil) {
-    if (errorOrNil) {
-      NSLog(@"Finished with error: %@", errorOrNil);
-    } else {
-      NSLog(@"Finished successfully.");
-    }
-  }];
+  id<GRXWriteable> responsesWriteable =
+      [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) {
+        RMTSimpleResponse *response = [RMTSimpleResponse parseFromData:value error:NULL];
+        NSLog(@"Received response:\n%@", response);
+      }
+          completionHandler:^(NSError *errorOrNil) {
+            if (errorOrNil) {
+              NSLog(@"Finished with error: %@", errorOrNil);
+            } else {
+              NSLog(@"Finished successfully.");
+            }
+          }];
 
   [call startWithWriteable:responsesWriteable];
 }
diff --git a/src/objective-c/examples/Sample/Sample/main.m b/src/objective-c/examples/Sample/Sample/main.m
index aa89f7b..852f55f 100644
--- a/src/objective-c/examples/Sample/Sample/main.m
+++ b/src/objective-c/examples/Sample/Sample/main.m
@@ -19,8 +19,8 @@
 #import <UIKit/UIKit.h>
 #import "AppDelegate.h"
 
-int main(int argc, char * argv[]) {
+int main(int argc, char* argv[]) {
   @autoreleasepool {
-      return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
+    return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
   }
 }
diff --git a/src/objective-c/examples/SwiftSample/SwiftSample.xcodeproj/project.pbxproj b/src/objective-c/examples/SwiftSample/SwiftSample.xcodeproj/project.pbxproj
index 6247d0b..0113d9c 100644
--- a/src/objective-c/examples/SwiftSample/SwiftSample.xcodeproj/project.pbxproj
+++ b/src/objective-c/examples/SwiftSample/SwiftSample.xcodeproj/project.pbxproj
@@ -168,13 +168,16 @@
 			files = (
 			);
 			inputPaths = (
+				"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+				"${PODS_ROOT}/Manifest.lock",
 			);
 			name = "[CP] Check Pods Manifest.lock";
 			outputPaths = (
+				"$(DERIVED_FILE_DIR)/Pods-SwiftSample-checkManifestLockResult.txt",
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
-			shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n    cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n    exit 1\nfi\n";
+			shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
 			showEnvVarsInLog = 0;
 		};
 		A1738A987353B0BF2C64F0F7 /* [CP] Embed Pods Frameworks */ = {
@@ -183,9 +186,26 @@
 			files = (
 			);
 			inputPaths = (
+				"${SRCROOT}/Pods/Target Support Files/Pods-SwiftSample/Pods-SwiftSample-frameworks.sh",
+				"${BUILT_PRODUCTS_DIR}/BoringSSL/openssl.framework",
+				"${BUILT_PRODUCTS_DIR}/Protobuf/Protobuf.framework",
+				"${BUILT_PRODUCTS_DIR}/RemoteTest/RemoteTest.framework",
+				"${BUILT_PRODUCTS_DIR}/gRPC/GRPCClient.framework",
+				"${BUILT_PRODUCTS_DIR}/gRPC-Core/grpc.framework",
+				"${BUILT_PRODUCTS_DIR}/gRPC-ProtoRPC/ProtoRPC.framework",
+				"${BUILT_PRODUCTS_DIR}/gRPC-RxLibrary/RxLibrary.framework",
+				"${BUILT_PRODUCTS_DIR}/nanopb/nanopb.framework",
 			);
 			name = "[CP] Embed Pods Frameworks";
 			outputPaths = (
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/openssl.framework",
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Protobuf.framework",
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RemoteTest.framework",
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GRPCClient.framework",
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/grpc.framework",
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ProtoRPC.framework",
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RxLibrary.framework",
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/nanopb.framework",
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
@@ -329,7 +349,7 @@
 				PRODUCT_BUNDLE_IDENTIFIER = "io.grpc.$(PRODUCT_NAME:rfc1034identifier)";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SWIFT_OBJC_BRIDGING_HEADER = "";
-				SWIFT_VERSION = 2.3;
+				SWIFT_VERSION = 4.0;
 				USER_HEADER_SEARCH_PATHS = "";
 			};
 			name = Debug;
@@ -344,7 +364,7 @@
 				PRODUCT_BUNDLE_IDENTIFIER = "io.grpc.$(PRODUCT_NAME:rfc1034identifier)";
 				PRODUCT_NAME = "$(TARGET_NAME)";
 				SWIFT_OBJC_BRIDGING_HEADER = "";
-				SWIFT_VERSION = 2.3;
+				SWIFT_VERSION = 4.0;
 				USER_HEADER_SEARCH_PATHS = "";
 			};
 			name = Release;
diff --git a/src/objective-c/examples/SwiftSample/ViewController.swift b/src/objective-c/examples/SwiftSample/ViewController.swift
index 5931914..0ba6e21 100644
--- a/src/objective-c/examples/SwiftSample/ViewController.swift
+++ b/src/objective-c/examples/SwiftSample/ViewController.swift
@@ -36,7 +36,7 @@
     // Example gRPC call using a generated proto client library:
 
     let service = RMTTestService(host: RemoteHost)
-    service.unaryCallWithRequest(request) { response, error in
+    service.unaryCall(with: request) { response, error in
       if let response = response {
         NSLog("1. Finished successfully with response:\n\(response)")
       } else {
@@ -48,7 +48,7 @@
     // Same but manipulating headers:
 
     var RPC : GRPCProtoCall! // Needed to convince Swift to capture by reference (__block)
-    RPC = service.RPCToUnaryCallWithRequest(request) { response, error in
+    RPC = service.rpcToUnaryCall(with: request) { response, error in
       if let response = response {
         NSLog("2. Finished successfully with response:\n\(response)")
       } else {
@@ -59,23 +59,23 @@
     }
 
     // TODO(jcanizales): Revert to using subscript syntax once XCode 8 is released.
-    RPC.requestHeaders.setObject("My value", forKey: "My-Header")
+    RPC.requestHeaders["My-Header"] = "My value"
 
     RPC.start()
 
 
     // Same example call using the generic gRPC client library:
 
-    let method = GRPCProtoMethod(package: "grpc.testing", service: "TestService", method: "UnaryCall")
+    let method = GRPCProtoMethod(package: "grpc.testing", service: "TestService", method: "UnaryCall")!
 
     let requestsWriter = GRXWriter(value: request.data())
 
-    let call = GRPCCall(host: RemoteHost, path: method.HTTPPath, requestsWriter: requestsWriter)
+    let call = GRPCCall(host: RemoteHost, path: method.httpPath, requestsWriter: requestsWriter)!
 
-    call.requestHeaders.setObject("My value", forKey: "My-Header")
+    call.requestHeaders["My-Header"] = "My value"
 
-    call.startWithWriteable(GRXWriteable { response, error in
-      if let response = response as? NSData {
+    call.start(with: GRXWriteable { response, error in
+      if let response = response as? Data {
         NSLog("3. Received response:\n\(try! RMTSimpleResponse(data: response))")
       } else {
         NSLog("3. Finished with error: \(error!)")
diff --git a/src/objective-c/tests/Connectivity/ConnectivityTestingApp/ViewController.m b/src/objective-c/tests/Connectivity/ConnectivityTestingApp/ViewController.m
index f91d2a6..88780e3 100644
--- a/src/objective-c/tests/Connectivity/ConnectivityTestingApp/ViewController.m
+++ b/src/objective-c/tests/Connectivity/ConnectivityTestingApp/ViewController.m
@@ -20,9 +20,9 @@
 
 #import <GRPCClient/GRPCCall.h>
 #import <ProtoRPC/ProtoMethod.h>
+#import <RxLibrary/GRXBufferedPipe.h>
 #import <RxLibrary/GRXWriter+Immediate.h>
 #import <RxLibrary/GRXWriter+Transformations.h>
-#import <RxLibrary/GRXBufferedPipe.h>
 
 #import "src/objective-c/GRPCClient/private/GRPCConnectivityMonitor.h"
 
@@ -35,8 +35,7 @@
 - (void)viewDidLoad {
   [super viewDidLoad];
 
-  [GRPCConnectivityMonitor registerObserver:self
-                                   selector:@selector(reachabilityChanged:)];
+  [GRPCConnectivityMonitor registerObserver:self selector:@selector(reachabilityChanged:)];
 }
 
 - (void)reachabilityChanged:(NSNotification *)note {
@@ -52,23 +51,21 @@
   GRPCProtoMethod *method = [[GRPCProtoMethod alloc] initWithPackage:@"grpc.testing"
                                                              service:@"TestService"
                                                               method:@"UnaryCall"];
-  GRXWriter *loggingRequestWriter =
-      [[GRXWriter writerWithValue:[NSData dataWithBytes:bytes length:sizeof(bytes)]]
-                              map:^id(id value) {
-                                NSLog(@"Sending request.");
-                                return value;
-                              }];
-  GRPCCall *call = [[GRPCCall alloc] initWithHost:host
-                                             path:method.HTTPPath
-                                   requestsWriter:loggingRequestWriter];
+  GRXWriter *loggingRequestWriter = [[GRXWriter
+      writerWithValue:[NSData dataWithBytes:bytes length:sizeof(bytes)]] map:^id(id value) {
+    NSLog(@"Sending request.");
+    return value;
+  }];
+  GRPCCall *call =
+      [[GRPCCall alloc] initWithHost:host path:method.HTTPPath requestsWriter:loggingRequestWriter];
 
-  [call startWithWriteable:[GRXWriteable writeableWithEventHandler:^(BOOL done, id value,
-                                                                       NSError *error) {
-    if (!done) {
-      return;
-    }
-    NSLog(@"Unary call finished with error: %@", error);
-  }]];
+  [call startWithWriteable:[GRXWriteable
+                               writeableWithEventHandler:^(BOOL done, id value, NSError *error) {
+                                 if (!done) {
+                                   return;
+                                 }
+                                 NSLog(@"Unary call finished with error: %@", error);
+                               }]];
 }
 
 - (IBAction)tapStreaming:(id)sender {
@@ -85,17 +82,16 @@
 
   [requestsBuffer writeValue:[NSData dataWithBytes:bytes length:sizeof(bytes)]];
 
-  GRPCCall *call = [[GRPCCall alloc] initWithHost:host
-                                             path:method.HTTPPath
-                                   requestsWriter:requestsBuffer];
+  GRPCCall *call =
+      [[GRPCCall alloc] initWithHost:host path:method.HTTPPath requestsWriter:requestsBuffer];
 
-  [call startWithWriteable:[GRXWriteable writeableWithEventHandler:^(BOOL done, id value,
-                                                                     NSError *error) {
-    if (!done) {
-      return;
-    }
-    NSLog(@"Streaming call finished with error: %@", error);
-  }]];
+  [call startWithWriteable:[GRXWriteable
+                               writeableWithEventHandler:^(BOOL done, id value, NSError *error) {
+                                 if (!done) {
+                                   return;
+                                 }
+                                 NSLog(@"Streaming call finished with error: %@", error);
+                               }]];
 }
 
 @end
diff --git a/src/objective-c/tests/Connectivity/ConnectivityTestingApp/main.m b/src/objective-c/tests/Connectivity/ConnectivityTestingApp/main.m
index 1642fdb..010789e 100644
--- a/src/objective-c/tests/Connectivity/ConnectivityTestingApp/main.m
+++ b/src/objective-c/tests/Connectivity/ConnectivityTestingApp/main.m
@@ -18,14 +18,14 @@
 
 #import <UIKit/UIKit.h>
 
-@interface AppDelegate : UIResponder <UIApplicationDelegate>
-@property (strong, nonatomic) UIWindow *window;
+@interface AppDelegate : UIResponder<UIApplicationDelegate>
+@property(strong, nonatomic) UIWindow *window;
 @end
 @implementation AppDelegate
 @end
 
-int main(int argc, char * argv[]) {
+int main(int argc, char *argv[]) {
   @autoreleasepool {
-      return UIApplicationMain(argc, argv, nil, NSStringFromClass(AppDelegate.class));
+    return UIApplicationMain(argc, argv, nil, NSStringFromClass(AppDelegate.class));
   }
 }
diff --git a/src/objective-c/tests/CoreCronetEnd2EndTests/CoreCronetEnd2EndTests.mm b/src/objective-c/tests/CoreCronetEnd2EndTests/CoreCronetEnd2EndTests.mm
index 33ccdb5..80fa0f4 100644
--- a/src/objective-c/tests/CoreCronetEnd2EndTests/CoreCronetEnd2EndTests.mm
+++ b/src/objective-c/tests/CoreCronetEnd2EndTests/CoreCronetEnd2EndTests.mm
@@ -37,11 +37,11 @@
 #include <grpc/support/log.h>
 
 #include "src/core/lib/channel/channel_args.h"
-#include "src/core/lib/security/credentials/credentials.h"
 #include "src/core/lib/gpr/env.h"
 #include "src/core/lib/gpr/host_port.h"
 #include "src/core/lib/gpr/string.h"
 #include "src/core/lib/gpr/tmpfile.h"
+#include "src/core/lib/security/credentials/credentials.h"
 #include "test/core/end2end/data/ssl_test_data.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
@@ -58,7 +58,7 @@
   grpc_end2end_test_fixture f;
   int port = grpc_pick_unused_port_or_die();
   fullstack_secure_fixture_data *ffd =
-      (fullstack_secure_fixture_data*)gpr_malloc(sizeof(fullstack_secure_fixture_data));
+      (fullstack_secure_fixture_data *)gpr_malloc(sizeof(fullstack_secure_fixture_data));
   memset(&f, 0, sizeof(f));
 
   gpr_join_host_port(&ffd->localaddr, "127.0.0.1", port);
@@ -70,9 +70,8 @@
   return f;
 }
 
-static void process_auth_failure(void *state, grpc_auth_context *ctx,
-                                 const grpc_metadata *md, size_t md_count,
-                                 grpc_process_auth_metadata_done_cb cb,
+static void process_auth_failure(void *state, grpc_auth_context *ctx, const grpc_metadata *md,
+                                 size_t md_count, grpc_process_auth_metadata_done_cb cb,
                                  void *user_data) {
   GPR_ASSERT(state == NULL);
   cb(user_data, NULL, 0, NULL, 0, GRPC_STATUS_UNAUTHENTICATED, NULL);
@@ -82,22 +81,26 @@
                                                 grpc_channel_args *client_args,
                                                 stream_engine *cronetEngine) {
   fullstack_secure_fixture_data *ffd = (fullstack_secure_fixture_data *)f->fixture_data;
-  f->client = grpc_cronet_secure_channel_create(cronetEngine, ffd->localaddr,
-                                                client_args, NULL);
+  grpc_arg arg;
+  arg.key = const_cast<char *>(GRPC_ARG_DISABLE_CLIENT_AUTHORITY_FILTER);
+  arg.type = GRPC_ARG_INTEGER;
+  arg.value.integer = 1;
+  client_args = grpc_channel_args_copy_and_add(client_args, &arg, 1);
+  f->client = grpc_cronet_secure_channel_create(cronetEngine, ffd->localaddr, client_args, NULL);
+  grpc_channel_args_destroy(client_args);
   GPR_ASSERT(f->client != NULL);
 }
 
-static void chttp2_init_server_secure_fullstack(
-    grpc_end2end_test_fixture *f, grpc_channel_args *server_args,
-    grpc_server_credentials *server_creds) {
+static void chttp2_init_server_secure_fullstack(grpc_end2end_test_fixture *f,
+                                                grpc_channel_args *server_args,
+                                                grpc_server_credentials *server_creds) {
   fullstack_secure_fixture_data *ffd = (fullstack_secure_fixture_data *)f->fixture_data;
   if (f->server) {
     grpc_server_destroy(f->server);
   }
   f->server = grpc_server_create(server_args, NULL);
   grpc_server_register_completion_queue(f->server, f->cq, NULL);
-  GPR_ASSERT(grpc_server_add_secure_http2_port(f->server, ffd->localaddr,
-                                               server_creds));
+  GPR_ASSERT(grpc_server_add_secure_http2_port(f->server, ffd->localaddr, server_creds));
   grpc_server_credentials_release(server_creds);
   grpc_server_start(f->server);
 }
@@ -108,8 +111,8 @@
   gpr_free(ffd);
 }
 
-static void cronet_init_client_simple_ssl_secure_fullstack(
-    grpc_end2end_test_fixture *f, grpc_channel_args *client_args) {
+static void cronet_init_client_simple_ssl_secure_fullstack(grpc_end2end_test_fixture *f,
+                                                           grpc_channel_args *client_args) {
   grpc_core::ExecCtx exec_ctx;
   stream_engine *cronetEngine = [Cronet getGlobalEngine];
 
@@ -122,18 +125,16 @@
   size_t i;
   if (server_args == NULL) return 0;
   for (i = 0; i < server_args->num_args; i++) {
-    if (strcmp(server_args->args[i].key, FAIL_AUTH_CHECK_SERVER_ARG_NAME) ==
-        0) {
+    if (strcmp(server_args->args[i].key, FAIL_AUTH_CHECK_SERVER_ARG_NAME) == 0) {
       return 1;
     }
   }
   return 0;
 }
 
-static void chttp2_init_server_simple_ssl_secure_fullstack(
-    grpc_end2end_test_fixture *f, grpc_channel_args *server_args) {
-  grpc_ssl_pem_key_cert_pair pem_cert_key_pair = {test_server1_key,
-                                                  test_server1_cert};
+static void chttp2_init_server_simple_ssl_secure_fullstack(grpc_end2end_test_fixture *f,
+                                                           grpc_channel_args *server_args) {
+  grpc_ssl_pem_key_cert_pair pem_cert_key_pair = {test_server1_key, test_server1_cert};
   grpc_server_credentials *ssl_creds =
       grpc_ssl_server_credentials_create(NULL, &pem_cert_key_pair, 1, 0, NULL);
   if (fail_server_auth_check(server_args)) {
@@ -147,12 +148,9 @@
 
 static grpc_end2end_test_config configs[] = {
     {"chttp2/simple_ssl_fullstack",
-     FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
-         FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS,
-     chttp2_create_fixture_secure_fullstack,
-     cronet_init_client_simple_ssl_secure_fullstack,
-     chttp2_init_server_simple_ssl_secure_fullstack,
-     chttp2_tear_down_secure_fullstack},
+     FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION | FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS, nullptr,
+     chttp2_create_fixture_secure_fullstack, cronet_init_client_simple_ssl_secure_fullstack,
+     chttp2_init_server_simple_ssl_secure_fullstack, chttp2_tear_down_secure_fullstack},
 };
 
 static char *roots_filename;
@@ -186,9 +184,8 @@
 
   [Cronet setHttp2Enabled:YES];
   [Cronet enableTestCertVerifierForTesting];
-  NSURL *url = [[[NSFileManager defaultManager]
-      URLsForDirectory:NSDocumentDirectory
-             inDomains:NSUserDomainMask] lastObject];
+  NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory
+                                                       inDomains:NSUserDomainMask] lastObject];
   NSLog(@"Documents directory: %@", url);
   [Cronet start];
   [Cronet startNetLogToFile:@"cronet_netlog.json" logBytes:YES];
diff --git a/src/objective-c/tests/CronetUnitTests/CronetUnitTests.m b/src/objective-c/tests/CronetUnitTests/CronetUnitTests.m
index 28414b8..a6dfb15 100644
--- a/src/objective-c/tests/CronetUnitTests/CronetUnitTests.m
+++ b/src/objective-c/tests/CronetUnitTests/CronetUnitTests.m
@@ -42,8 +42,7 @@
 static void drain_cq(grpc_completion_queue *cq) {
   grpc_event ev;
   do {
-    ev = grpc_completion_queue_next(cq, grpc_timeout_seconds_to_deadline(5),
-                                    NULL);
+    ev = grpc_completion_queue_next(cq, grpc_timeout_seconds_to_deadline(5), NULL);
   } while (ev.type != GRPC_QUEUE_SHUTDOWN);
 }
 
@@ -64,9 +63,8 @@
   [Cronet setHttp2Enabled:YES];
   [Cronet setSslKeyLogFileName:@"Documents/key"];
   [Cronet enableTestCertVerifierForTesting];
-  NSURL *url = [[[NSFileManager defaultManager]
-      URLsForDirectory:NSDocumentDirectory
-             inDomains:NSUserDomainMask] lastObject];
+  NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory
+                                                       inDomains:NSUserDomainMask] lastObject];
   NSLog(@"Documents directory: %@", url);
   [Cronet start];
   [Cronet startNetLogToFile:@"Documents/cronet_netlog.json" logBytes:YES];
@@ -88,8 +86,8 @@
 
 void cleanup_ssl(void) { EVP_cleanup(); }
 
-int alpn_cb(SSL *ssl, const unsigned char **out, unsigned char *outlen,
-            const unsigned char *in, unsigned int inlen, void *arg) {
+int alpn_cb(SSL *ssl, const unsigned char **out, unsigned char *outlen, const unsigned char *in,
+            unsigned int inlen, void *arg) {
   // Always select "h2" as the ALPN protocol to be used
   *out = (const unsigned char *)"h2";
   *outlen = 2;
@@ -98,16 +96,14 @@
 
 void init_ctx(SSL_CTX *ctx) {
   // Install server certificate
-  BIO *pem = BIO_new_mem_buf((void *)test_server1_cert,
-                             (int)strlen(test_server1_cert));
+  BIO *pem = BIO_new_mem_buf((void *)test_server1_cert, (int)strlen(test_server1_cert));
   X509 *cert = PEM_read_bio_X509_AUX(pem, NULL, NULL, (char *)"");
   SSL_CTX_use_certificate(ctx, cert);
   X509_free(cert);
   BIO_free(pem);
 
   // Install server private key
-  pem =
-      BIO_new_mem_buf((void *)test_server1_key, (int)strlen(test_server1_key));
+  pem = BIO_new_mem_buf((void *)test_server1_key, (int)strlen(test_server1_key));
   EVP_PKEY *key = PEM_read_bio_PrivateKey(pem, NULL, NULL, (char *)"");
   SSL_CTX_use_PrivateKey(ctx, key);
   EVP_PKEY_free(key);
@@ -126,12 +122,18 @@
          ((unsigned int)(unsigned char)(field[2]));
 }
 
+grpc_channel_args *add_disable_client_authority_filter_args(grpc_channel_args *args) {
+  grpc_arg arg;
+  arg.key = const_cast<char *>(GRPC_ARG_DISABLE_CLIENT_AUTHORITY_FILTER);
+  arg.type = GRPC_ARG_INTEGER;
+  arg.value.integer = 1;
+  return grpc_channel_args_copy_and_add(args, &arg, 1);
+}
+
 - (void)testInternalError {
   grpc_call *c;
-  grpc_slice request_payload_slice =
-      grpc_slice_from_copied_string("hello world");
-  grpc_byte_buffer *request_payload =
-      grpc_raw_byte_buffer_create(&request_payload_slice, 1);
+  grpc_slice request_payload_slice = grpc_slice_from_copied_string("hello world");
+  grpc_byte_buffer *request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1);
   gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5);
   grpc_metadata meta_c[2] = {{grpc_slice_from_static_string("key1"),
                               grpc_slice_from_static_string("val1"),
@@ -147,8 +149,9 @@
   gpr_join_host_port(&addr, "127.0.0.1", port);
   grpc_completion_queue *cq = grpc_completion_queue_create_for_next(NULL);
   stream_engine *cronetEngine = [Cronet getGlobalEngine];
-  grpc_channel *client =
-      grpc_cronet_secure_channel_create(cronetEngine, addr, NULL, NULL);
+  grpc_channel_args *client_args = add_disable_client_authority_filter_args(NULL);
+  grpc_channel *client = grpc_cronet_secure_channel_create(cronetEngine, addr, client_args, NULL);
+  grpc_channel_args_destroy(client_args);
 
   cq_verifier *cqv = cq_verifier_create(cq);
   grpc_op ops[6];
@@ -163,8 +166,7 @@
   grpc_slice details;
 
   c = grpc_channel_create_call(client, NULL, GRPC_PROPAGATE_DEFAULTS, cq,
-                               grpc_slice_from_static_string("/foo"), NULL,
-                               deadline, NULL);
+                               grpc_slice_from_static_string("/foo"), NULL, deadline, NULL);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -221,16 +223,15 @@
   error = grpc_call_start_batch(c, ops, (size_t)(op - ops), (void *)1, NULL);
   GPR_ASSERT(GRPC_CALL_OK == error);
 
-  dispatch_async(
-      dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
-        int s = accept(sl, NULL, NULL);
-        GPR_ASSERT(s >= 0);
+  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
+    int s = accept(sl, NULL, NULL);
+    GPR_ASSERT(s >= 0);
 
-        // Close the connection after 1 second to trigger Cronet's on_failed()
-        sleep(1);
-        close(s);
-        close(sl);
-      });
+    // Close the connection after 1 second to trigger Cronet's on_failed()
+    sleep(1);
+    close(s);
+    close(sl);
+  });
 
   CQ_EXPECT_COMPLETION(cqv, (void *)1, 1);
   cq_verify(cqv);
@@ -262,11 +263,11 @@
   arg.type = GRPC_ARG_INTEGER;
   arg.value.integer = useCoalescing ? 1 : 0;
   grpc_channel_args *args = grpc_channel_args_copy_and_add(NULL, &arg, 1);
+  args = add_disable_client_authority_filter_args(args);
+
   grpc_call *c;
-  grpc_slice request_payload_slice =
-      grpc_slice_from_copied_string("hello world");
-  grpc_byte_buffer *request_payload =
-      grpc_raw_byte_buffer_create(&request_payload_slice, 1);
+  grpc_slice request_payload_slice = grpc_slice_from_copied_string("hello world");
+  grpc_byte_buffer *request_payload = grpc_raw_byte_buffer_create(&request_payload_slice, 1);
   gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5);
   grpc_metadata meta_c[2] = {{grpc_slice_from_static_string("key1"),
                               grpc_slice_from_static_string("val1"),
@@ -282,8 +283,7 @@
   gpr_join_host_port(&addr, "127.0.0.1", port);
   grpc_completion_queue *cq = grpc_completion_queue_create_for_next(NULL);
   stream_engine *cronetEngine = [Cronet getGlobalEngine];
-  grpc_channel *client =
-      grpc_cronet_secure_channel_create(cronetEngine, addr, args, NULL);
+  grpc_channel *client = grpc_cronet_secure_channel_create(cronetEngine, addr, args, NULL);
 
   cq_verifier *cqv = cq_verifier_create(cq);
   grpc_op ops[6];
@@ -298,8 +298,7 @@
   grpc_slice details;
 
   c = grpc_channel_create_call(client, NULL, GRPC_PROPAGATE_DEFAULTS, cq,
-                               grpc_slice_from_static_string("/foo"), NULL,
-                               deadline, NULL);
+                               grpc_slice_from_static_string("/foo"), NULL, deadline, NULL);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -307,8 +306,7 @@
   grpc_metadata_array_init(&request_metadata_recv);
   grpc_call_details_init(&call_details);
 
-  __weak XCTestExpectation *expectation =
-      [self expectationWithDescription:@"Coalescing"];
+  __weak XCTestExpectation *expectation = [self expectationWithDescription:@"Coalescing"];
 
   int sl = socket(AF_INET, SOCK_STREAM, 0);
   GPR_ASSERT(sl >= 0);
@@ -320,61 +318,60 @@
   GPR_ASSERT(0 == bind(sl, (struct sockaddr *)&s_addr, sizeof(s_addr)));
   GPR_ASSERT(0 == listen(sl, 5));
 
-  dispatch_async(
-      dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
-        int s = accept(sl, NULL, NULL);
-        GPR_ASSERT(s >= 0);
-        struct timeval tv;
-        tv.tv_sec = 2;
-        tv.tv_usec = 0;
-        setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
+  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
+    int s = accept(sl, NULL, NULL);
+    GPR_ASSERT(s >= 0);
+    struct timeval tv;
+    tv.tv_sec = 2;
+    tv.tv_usec = 0;
+    setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
 
-        // Make an TLS endpoint to receive Cronet's transmission
-        SSL_CTX *ctx = SSL_CTX_new(TLSv1_2_server_method());
-        init_ctx(ctx);
-        SSL *ssl = SSL_new(ctx);
-        SSL_set_fd(ssl, s);
-        SSL_accept(ssl);
+    // Make an TLS endpoint to receive Cronet's transmission
+    SSL_CTX *ctx = SSL_CTX_new(TLSv1_2_server_method());
+    init_ctx(ctx);
+    SSL *ssl = SSL_new(ctx);
+    SSL_set_fd(ssl, s);
+    SSL_accept(ssl);
 
-        const char magic[] = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n";
+    const char magic[] = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n";
 
-        char buf[4096];
-        long len;
-        BOOL coalesced = NO;
-        while ((len = SSL_read(ssl, buf, sizeof(buf))) > 0) {
-          gpr_log(GPR_DEBUG, "Read len: %ld", len);
+    char buf[4096];
+    long len;
+    BOOL coalesced = NO;
+    while ((len = SSL_read(ssl, buf, sizeof(buf))) > 0) {
+      gpr_log(GPR_DEBUG, "Read len: %ld", len);
 
-          // Analyze the HTTP/2 frames in the same TLS PDU to identify if
-          // coalescing is successful
-          unsigned int p = 0;
-          while (p < len) {
-            if (len - p >= 24 && 0 == memcmp(&buf[p], magic, 24)) {
-              p += 24;
-              continue;
-            }
-
-            if (buf[p + 3] == 0 &&                   // Type is DATA
-                parse_h2_length(&buf[p]) == 0x10 &&  // Length is correct
-                (buf[p + 4] & 1) != 0 &&             // EOS bit is set
-                0 == memcmp("hello world", &buf[p + 14],
-                            11)) {  // Message is correct
-              coalesced = YES;
-              break;
-            }
-            p += (parse_h2_length(&buf[p]) + 9);
-          }
-          if (coalesced) {
-            break;
-          }
+      // Analyze the HTTP/2 frames in the same TLS PDU to identify if
+      // coalescing is successful
+      unsigned int p = 0;
+      while (p < len) {
+        if (len - p >= 24 && 0 == memcmp(&buf[p], magic, 24)) {
+          p += 24;
+          continue;
         }
 
-        XCTAssert(coalesced == useCoalescing);
-        SSL_free(ssl);
-        SSL_CTX_free(ctx);
-        close(s);
-        close(sl);
-        [expectation fulfill];
-      });
+        if (buf[p + 3] == 0 &&                   // Type is DATA
+            parse_h2_length(&buf[p]) == 0x10 &&  // Length is correct
+            (buf[p + 4] & 1) != 0 &&             // EOS bit is set
+            0 == memcmp("hello world", &buf[p + 14],
+                        11)) {  // Message is correct
+          coalesced = YES;
+          break;
+        }
+        p += (parse_h2_length(&buf[p]) + 9);
+      }
+      if (coalesced) {
+        break;
+      }
+    }
+
+    XCTAssert(coalesced == useCoalescing);
+    SSL_free(ssl);
+    SSL_CTX_free(ctx);
+    close(s);
+    close(sl);
+    [expectation fulfill];
+  });
 
   memset(ops, 0, sizeof(ops));
   op = ops;
diff --git a/src/objective-c/tests/GRPCClientTests.m b/src/objective-c/tests/GRPCClientTests.m
index 3bab7f6..5cd0231 100644
--- a/src/objective-c/tests/GRPCClientTests.m
+++ b/src/objective-c/tests/GRPCClientTests.m
@@ -20,25 +20,27 @@
 #import <XCTest/XCTest.h>
 #import <grpc/grpc.h>
 
-#import <GRPCClient/GRPCCall.h>
 #import <GRPCClient/GRPCCall+ChannelArg.h>
 #import <GRPCClient/GRPCCall+OAuth2.h>
 #import <GRPCClient/GRPCCall+Tests.h>
+#import <GRPCClient/GRPCCall.h>
 #import <GRPCClient/internal_testing/GRPCCall+InternalTests.h>
 #import <ProtoRPC/ProtoMethod.h>
 #import <RemoteTest/Messages.pbobjc.h>
+#import <RxLibrary/GRXBufferedPipe.h>
 #import <RxLibrary/GRXWriteable.h>
 #import <RxLibrary/GRXWriter+Immediate.h>
-#import <RxLibrary/GRXBufferedPipe.h>
+
+#include <netinet/in.h>
 
 #import "version.h"
 
 #define TEST_TIMEOUT 16
 
-static NSString * const kHostAddress = @"localhost:5050";
-static NSString * const kPackage = @"grpc.testing";
-static NSString * const kService = @"TestService";
-static NSString * const kRemoteSSLHost = @"grpc-test.sandbox.googleapis.com";
+static NSString *const kHostAddress = @"localhost:5050";
+static NSString *const kPackage = @"grpc.testing";
+static NSString *const kService = @"TestService";
+static NSString *const kRemoteSSLHost = @"grpc-test.sandbox.googleapis.com";
 
 static GRPCProtoMethod *kInexistentMethod;
 static GRPCProtoMethod *kEmptyCallMethod;
@@ -47,15 +49,17 @@
 
 /** Observer class for testing that responseMetadata is KVO-compliant */
 @interface PassthroughObserver : NSObject
-- (instancetype) initWithCallback:(void (^)(NSString*, id, NSDictionary*))callback
+- (instancetype)initWithCallback:(void (^)(NSString *, id, NSDictionary *))callback
     NS_DESIGNATED_INITIALIZER;
 
-- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change
+- (void)observeValueForKeyPath:(NSString *)keyPath
+                      ofObject:(id)object
+                        change:(NSDictionary *)change
                        context:(void *)context;
 @end
 
 @implementation PassthroughObserver {
-  void (^_callback)(NSString*, id, NSDictionary*);
+  void (^_callback)(NSString *, id, NSDictionary *);
 }
 
 - (instancetype)init {
@@ -82,7 +86,7 @@
 
 @end
 
-# pragma mark Tests
+#pragma mark Tests
 
 /**
  * A few tests similar to InteropTests, but which use the generic gRPC client (GRPCCall) rather than
@@ -106,18 +110,14 @@
   [GRPCCall useInsecureConnectionsForHost:kHostAddress];
 
   // This method isn't implemented by the remote server.
-  kInexistentMethod = [[GRPCProtoMethod alloc] initWithPackage:kPackage
-                                                       service:kService
-                                                        method:@"Inexistent"];
-  kEmptyCallMethod = [[GRPCProtoMethod alloc] initWithPackage:kPackage
-                                                      service:kService
-                                                       method:@"EmptyCall"];
-  kUnaryCallMethod = [[GRPCProtoMethod alloc] initWithPackage:kPackage
-                                                      service:kService
-                                                       method:@"UnaryCall"];
-  kFullDuplexCallMethod = [[GRPCProtoMethod alloc] initWithPackage:kPackage
-                                                           service:kService
-                                                            method:@"FullDuplexCall"];
+  kInexistentMethod =
+      [[GRPCProtoMethod alloc] initWithPackage:kPackage service:kService method:@"Inexistent"];
+  kEmptyCallMethod =
+      [[GRPCProtoMethod alloc] initWithPackage:kPackage service:kService method:@"EmptyCall"];
+  kUnaryCallMethod =
+      [[GRPCProtoMethod alloc] initWithPackage:kPackage service:kService method:@"UnaryCall"];
+  kFullDuplexCallMethod =
+      [[GRPCProtoMethod alloc] initWithPackage:kPackage service:kService method:@"FullDuplexCall"];
 }
 
 - (void)testConnectionToRemoteServer {
@@ -127,13 +127,15 @@
                                              path:kInexistentMethod.HTTPPath
                                    requestsWriter:[GRXWriter writerWithValue:[NSData data]]];
 
-  id<GRXWriteable> responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) {
-    XCTFail(@"Received unexpected response: %@", value);
-  } completionHandler:^(NSError *errorOrNil) {
-    XCTAssertNotNil(errorOrNil, @"Finished without error!");
-    XCTAssertEqual(errorOrNil.code, 12, @"Finished with unexpected error: %@", errorOrNil);
-    [expectation fulfill];
-  }];
+  id<GRXWriteable> responsesWriteable =
+      [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) {
+        XCTFail(@"Received unexpected response: %@", value);
+      }
+          completionHandler:^(NSError *errorOrNil) {
+            XCTAssertNotNil(errorOrNil, @"Finished without error!");
+            XCTAssertEqual(errorOrNil.code, 12, @"Finished with unexpected error: %@", errorOrNil);
+            [expectation fulfill];
+          }];
 
   [call startWithWriteable:responsesWriteable];
 
@@ -141,21 +143,24 @@
 }
 
 - (void)testEmptyRPC {
-  __weak XCTestExpectation *response = [self expectationWithDescription:@"Empty response received."];
+  __weak XCTestExpectation *response =
+      [self expectationWithDescription:@"Empty response received."];
   __weak XCTestExpectation *completion = [self expectationWithDescription:@"Empty RPC completed."];
 
   GRPCCall *call = [[GRPCCall alloc] initWithHost:kHostAddress
                                              path:kEmptyCallMethod.HTTPPath
                                    requestsWriter:[GRXWriter writerWithValue:[NSData data]]];
 
-  id<GRXWriteable> responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) {
-    XCTAssertNotNil(value, @"nil value received as response.");
-    XCTAssertEqual([value length], 0, @"Non-empty response received: %@", value);
-    [response fulfill];
-  } completionHandler:^(NSError *errorOrNil) {
-    XCTAssertNil(errorOrNil, @"Finished with unexpected error: %@", errorOrNil);
-    [completion fulfill];
-  }];
+  id<GRXWriteable> responsesWriteable =
+      [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) {
+        XCTAssertNotNil(value, @"nil value received as response.");
+        XCTAssertEqual([value length], 0, @"Non-empty response received: %@", value);
+        [response fulfill];
+      }
+          completionHandler:^(NSError *errorOrNil) {
+            XCTAssertNil(errorOrNil, @"Finished with unexpected error: %@", errorOrNil);
+            [completion fulfill];
+          }];
 
   [call startWithWriteable:responsesWriteable];
 
@@ -176,18 +181,20 @@
                                              path:kUnaryCallMethod.HTTPPath
                                    requestsWriter:requestsWriter];
 
-  id<GRXWriteable> responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) {
-    XCTAssertNotNil(value, @"nil value received as response.");
-    XCTAssertGreaterThan(value.length, 0, @"Empty response received.");
-    RMTSimpleResponse *responseProto = [RMTSimpleResponse parseFromData:value error:NULL];
-    // We expect empty strings, not nil:
-    XCTAssertNotNil(responseProto.username, @"Response's username is nil.");
-    XCTAssertNotNil(responseProto.oauthScope, @"Response's OAuth scope is nil.");
-    [response fulfill];
-  } completionHandler:^(NSError *errorOrNil) {
-    XCTAssertNil(errorOrNil, @"Finished with unexpected error: %@", errorOrNil);
-    [completion fulfill];
-  }];
+  id<GRXWriteable> responsesWriteable =
+      [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) {
+        XCTAssertNotNil(value, @"nil value received as response.");
+        XCTAssertGreaterThan(value.length, 0, @"Empty response received.");
+        RMTSimpleResponse *responseProto = [RMTSimpleResponse parseFromData:value error:NULL];
+        // We expect empty strings, not nil:
+        XCTAssertNotNil(responseProto.username, @"Response's username is nil.");
+        XCTAssertNotNil(responseProto.oauthScope, @"Response's OAuth scope is nil.");
+        [response fulfill];
+      }
+          completionHandler:^(NSError *errorOrNil) {
+            XCTAssertNil(errorOrNil, @"Finished with unexpected error: %@", errorOrNil);
+            [completion fulfill];
+          }];
 
   [call startWithWriteable:responsesWriteable];
 
@@ -208,20 +215,22 @@
 
   call.oauth2AccessToken = @"bogusToken";
 
-  id<GRXWriteable> responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) {
-    XCTFail(@"Received unexpected response: %@", value);
-  } completionHandler:^(NSError *errorOrNil) {
-    XCTAssertNotNil(errorOrNil, @"Finished without error!");
-    XCTAssertEqual(errorOrNil.code, 16, @"Finished with unexpected error: %@", errorOrNil);
-    XCTAssertEqualObjects(call.responseHeaders, errorOrNil.userInfo[kGRPCHeadersKey],
-                          @"Headers in the NSError object and call object differ.");
-    XCTAssertEqualObjects(call.responseTrailers, errorOrNil.userInfo[kGRPCTrailersKey],
-                          @"Trailers in the NSError object and call object differ.");
-    NSString *challengeHeader = call.oauth2ChallengeHeader;
-    XCTAssertGreaterThan(challengeHeader.length, 0,
-                         @"No challenge in response headers %@", call.responseHeaders);
-    [expectation fulfill];
-  }];
+  id<GRXWriteable> responsesWriteable =
+      [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) {
+        XCTFail(@"Received unexpected response: %@", value);
+      }
+          completionHandler:^(NSError *errorOrNil) {
+            XCTAssertNotNil(errorOrNil, @"Finished without error!");
+            XCTAssertEqual(errorOrNil.code, 16, @"Finished with unexpected error: %@", errorOrNil);
+            XCTAssertEqualObjects(call.responseHeaders, errorOrNil.userInfo[kGRPCHeadersKey],
+                                  @"Headers in the NSError object and call object differ.");
+            XCTAssertEqualObjects(call.responseTrailers, errorOrNil.userInfo[kGRPCTrailersKey],
+                                  @"Trailers in the NSError object and call object differ.");
+            NSString *challengeHeader = call.oauth2ChallengeHeader;
+            XCTAssertGreaterThan(challengeHeader.length, 0, @"No challenge in response headers %@",
+                                 call.responseHeaders);
+            [expectation fulfill];
+          }];
 
   [call startWithWriteable:responsesWriteable];
 
@@ -229,38 +238,43 @@
 }
 
 - (void)testResponseMetadataKVO {
-  __weak XCTestExpectation *response = [self expectationWithDescription:@"Empty response received."];
+  __weak XCTestExpectation *response =
+      [self expectationWithDescription:@"Empty response received."];
   __weak XCTestExpectation *completion = [self expectationWithDescription:@"Empty RPC completed."];
   __weak XCTestExpectation *metadata = [self expectationWithDescription:@"Metadata changed."];
-  
+
   GRPCCall *call = [[GRPCCall alloc] initWithHost:kHostAddress
                                              path:kEmptyCallMethod.HTTPPath
                                    requestsWriter:[GRXWriter writerWithValue:[NSData data]]];
-  
-  PassthroughObserver *observer = [[PassthroughObserver alloc] initWithCallback:^(NSString *keypath, id object, NSDictionary * change) {
-    if ([keypath isEqual: @"responseHeaders"]) {
-      [metadata fulfill];
-    }
-  }];
-  
+
+  PassthroughObserver *observer = [[PassthroughObserver alloc]
+      initWithCallback:^(NSString *keypath, id object, NSDictionary *change) {
+        if ([keypath isEqual:@"responseHeaders"]) {
+          [metadata fulfill];
+        }
+      }];
+
   [call addObserver:observer forKeyPath:@"responseHeaders" options:0 context:NULL];
-  
-  id<GRXWriteable> responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) {
-    XCTAssertNotNil(value, @"nil value received as response.");
-    XCTAssertEqual([value length], 0, @"Non-empty response received: %@", value);
-    [response fulfill];
-  } completionHandler:^(NSError *errorOrNil) {
-    XCTAssertNil(errorOrNil, @"Finished with unexpected error: %@", errorOrNil);
-    [completion fulfill];
-  }];
-  
+
+  id<GRXWriteable> responsesWriteable =
+      [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) {
+        XCTAssertNotNil(value, @"nil value received as response.");
+        XCTAssertEqual([value length], 0, @"Non-empty response received: %@", value);
+        [response fulfill];
+      }
+          completionHandler:^(NSError *errorOrNil) {
+            XCTAssertNil(errorOrNil, @"Finished with unexpected error: %@", errorOrNil);
+            [completion fulfill];
+          }];
+
   [call startWithWriteable:responsesWriteable];
-  
+
   [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
 }
 
 - (void)testUserAgentPrefix {
-  __weak XCTestExpectation *response = [self expectationWithDescription:@"Empty response received."];
+  __weak XCTestExpectation *response =
+      [self expectationWithDescription:@"Empty response received."];
   __weak XCTestExpectation *completion = [self expectationWithDescription:@"Empty RPC completed."];
 
   GRPCCall *call = [[GRPCCall alloc] initWithHost:kHostAddress
@@ -270,46 +284,45 @@
   // user-agent value, which we confirm.
   call.requestHeaders[@"x-grpc-test-echo-useragent"] = @"";
 
-  id<GRXWriteable> responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) {
-    XCTAssertNotNil(value, @"nil value received as response.");
-    XCTAssertEqual([value length], 0, @"Non-empty response received: %@", value);
+  id<GRXWriteable> responsesWriteable =
+      [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) {
+        XCTAssertNotNil(value, @"nil value received as response.");
+        XCTAssertEqual([value length], 0, @"Non-empty response received: %@", value);
 
-    NSString *userAgent = call.responseHeaders[@"x-grpc-test-echo-useragent"];
-    NSError *error = nil;
+        NSString *userAgent = call.responseHeaders[@"x-grpc-test-echo-useragent"];
+        NSError *error = nil;
 
-    // Test the regex is correct
-    NSString *expectedUserAgent = @"Foo grpc-objc/";
-    expectedUserAgent =
-        [expectedUserAgent stringByAppendingString:GRPC_OBJC_VERSION_STRING];
-    expectedUserAgent =
-        [expectedUserAgent stringByAppendingString:@" grpc-c/"];
-    expectedUserAgent =
-        [expectedUserAgent stringByAppendingString:GRPC_C_VERSION_STRING];
-    expectedUserAgent =
-        [expectedUserAgent stringByAppendingString:@" (ios; chttp2; "];
-    expectedUserAgent =
-        [expectedUserAgent stringByAppendingString:[NSString stringWithUTF8String:grpc_g_stands_for()]];
-    expectedUserAgent = [expectedUserAgent stringByAppendingString:@")"];
-    XCTAssertEqualObjects(userAgent, expectedUserAgent);
+        // Test the regex is correct
+        NSString *expectedUserAgent = @"Foo grpc-objc/";
+        expectedUserAgent = [expectedUserAgent stringByAppendingString:GRPC_OBJC_VERSION_STRING];
+        expectedUserAgent = [expectedUserAgent stringByAppendingString:@" grpc-c/"];
+        expectedUserAgent = [expectedUserAgent stringByAppendingString:GRPC_C_VERSION_STRING];
+        expectedUserAgent = [expectedUserAgent stringByAppendingString:@" (ios; chttp2; "];
+        expectedUserAgent = [expectedUserAgent
+            stringByAppendingString:[NSString stringWithUTF8String:grpc_g_stands_for()]];
+        expectedUserAgent = [expectedUserAgent stringByAppendingString:@")"];
+        XCTAssertEqualObjects(userAgent, expectedUserAgent);
 
-    // Change in format of user-agent field in a direction that does not match the regex will likely
-    // cause problem for certain gRPC users. For details, refer to internal doc https://goo.gl/c2diBc
-    NSRegularExpression *regex =
-        [NSRegularExpression regularExpressionWithPattern:@" grpc-[a-zA-Z0-9]+(-[a-zA-Z0-9]+)?/[^ ,]+( \\([^)]*\\))?"
-                                                  options:0
-                                                    error:&error];
-    NSString *customUserAgent =
-        [regex stringByReplacingMatchesInString:userAgent
-                                        options:0
-                                          range:NSMakeRange(0, [userAgent length])
-                                   withTemplate:@""];
-    XCTAssertEqualObjects(customUserAgent, @"Foo");
+        // Change in format of user-agent field in a direction that does not match the regex will
+        // likely cause problem for certain gRPC users. For details, refer to internal doc
+        // https://goo.gl/c2diBc
+        NSRegularExpression *regex = [NSRegularExpression
+            regularExpressionWithPattern:@" grpc-[a-zA-Z0-9]+(-[a-zA-Z0-9]+)?/[^ ,]+( \\([^)]*\\))?"
+                                 options:0
+                                   error:&error];
+        NSString *customUserAgent =
+            [regex stringByReplacingMatchesInString:userAgent
+                                            options:0
+                                              range:NSMakeRange(0, [userAgent length])
+                                       withTemplate:@""];
+        XCTAssertEqualObjects(customUserAgent, @"Foo");
 
-    [response fulfill];
-  } completionHandler:^(NSError *errorOrNil) {
-    XCTAssertNil(errorOrNil, @"Finished with unexpected error: %@", errorOrNil);
-    [completion fulfill];
-  }];
+        [response fulfill];
+      }
+          completionHandler:^(NSError *errorOrNil) {
+            XCTAssertNil(errorOrNil, @"Finished with unexpected error: %@", errorOrNil);
+            [completion fulfill];
+          }];
 
   [call startWithWriteable:responsesWriteable];
 
@@ -317,7 +330,8 @@
 }
 
 - (void)testTrailers {
-  __weak XCTestExpectation *response = [self expectationWithDescription:@"Empty response received."];
+  __weak XCTestExpectation *response =
+      [self expectationWithDescription:@"Empty response received."];
   __weak XCTestExpectation *completion = [self expectationWithDescription:@"Empty RPC completed."];
 
   GRPCCall *call = [[GRPCCall alloc] initWithHost:kHostAddress
@@ -325,21 +339,22 @@
                                    requestsWriter:[GRXWriter writerWithValue:[NSData data]]];
   // Setting this special key in the header will cause the interop server to echo back the
   // trailer data.
-  const unsigned char raw_bytes[] = {1,2,3,4};
+  const unsigned char raw_bytes[] = {1, 2, 3, 4};
   NSData *trailer_data = [NSData dataWithBytes:raw_bytes length:sizeof(raw_bytes)];
   call.requestHeaders[@"x-grpc-test-echo-trailing-bin"] = trailer_data;
 
-  id<GRXWriteable> responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) {
-    XCTAssertNotNil(value, @"nil value received as response.");
-    XCTAssertEqual([value length], 0, @"Non-empty response received: %@", value);
-    [response fulfill];
-  } completionHandler:^(NSError *errorOrNil) {
-    XCTAssertNil(errorOrNil, @"Finished with unexpected error: %@", errorOrNil);
-    XCTAssertEqualObjects((NSData *)call.responseTrailers[@"x-grpc-test-echo-trailing-bin"],
-                          trailer_data,
-                          @"Did not receive expected trailer");
-    [completion fulfill];
-  }];
+  id<GRXWriteable> responsesWriteable =
+      [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) {
+        XCTAssertNotNil(value, @"nil value received as response.");
+        XCTAssertEqual([value length], 0, @"Non-empty response received: %@", value);
+        [response fulfill];
+      }
+          completionHandler:^(NSError *errorOrNil) {
+            XCTAssertNil(errorOrNil, @"Finished with unexpected error: %@", errorOrNil);
+            XCTAssertEqualObjects((NSData *)call.responseTrailers[@"x-grpc-test-echo-trailing-bin"],
+                                  trailer_data, @"Did not receive expected trailer");
+            [completion fulfill];
+          }];
 
   [call startWithWriteable:responsesWriteable];
   [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
@@ -349,15 +364,12 @@
 - (void)testExceptions {
   // Try to set parameters to nil for GRPCCall. This should cause an exception
   @try {
-    (void)[[GRPCCall alloc] initWithHost:nil
-                                    path:nil
-                          requestsWriter:nil];
+    (void)[[GRPCCall alloc] initWithHost:nil path:nil requestsWriter:nil];
     XCTFail(@"Did not receive an exception when parameters are nil");
-  } @catch(NSException *theException) {
+  } @catch (NSException *theException) {
     NSLog(@"Received exception as expected: %@", theException.name);
   }
 
-
   // Set state to Finished by force
   GRXWriter *requestsWriter = [GRXWriter emptyWriter];
   [requestsWriter finishWithError:nil];
@@ -366,10 +378,9 @@
                                     path:kUnaryCallMethod.HTTPPath
                           requestsWriter:requestsWriter];
     XCTFail(@"Did not receive an exception when GRXWriter has incorrect state.");
-  } @catch(NSException *theException) {
+  } @catch (NSException *theException) {
     NSLog(@"Received exception as expected: %@", theException.name);
   }
-
 }
 
 - (void)testIdempotentProtoRPC {
@@ -385,20 +396,24 @@
   GRPCCall *call = [[GRPCCall alloc] initWithHost:kHostAddress
                                              path:kUnaryCallMethod.HTTPPath
                                    requestsWriter:requestsWriter];
-  [GRPCCall setCallSafety:GRPCCallSafetyIdempotentRequest host:kHostAddress path:kUnaryCallMethod.HTTPPath];
+  [GRPCCall setCallSafety:GRPCCallSafetyIdempotentRequest
+                     host:kHostAddress
+                     path:kUnaryCallMethod.HTTPPath];
 
-  id<GRXWriteable> responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) {
-    XCTAssertNotNil(value, @"nil value received as response.");
-    XCTAssertGreaterThan(value.length, 0, @"Empty response received.");
-    RMTSimpleResponse *responseProto = [RMTSimpleResponse parseFromData:value error:NULL];
-    // We expect empty strings, not nil:
-    XCTAssertNotNil(responseProto.username, @"Response's username is nil.");
-    XCTAssertNotNil(responseProto.oauthScope, @"Response's OAuth scope is nil.");
-    [response fulfill];
-  } completionHandler:^(NSError *errorOrNil) {
-    XCTAssertNil(errorOrNil, @"Finished with unexpected error: %@", errorOrNil);
-    [completion fulfill];
-  }];
+  id<GRXWriteable> responsesWriteable =
+      [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) {
+        XCTAssertNotNil(value, @"nil value received as response.");
+        XCTAssertGreaterThan(value.length, 0, @"Empty response received.");
+        RMTSimpleResponse *responseProto = [RMTSimpleResponse parseFromData:value error:NULL];
+        // We expect empty strings, not nil:
+        XCTAssertNotNil(responseProto.username, @"Response's username is nil.");
+        XCTAssertNotNil(responseProto.oauthScope, @"Response's OAuth scope is nil.");
+        [response fulfill];
+      }
+          completionHandler:^(NSError *errorOrNil) {
+            XCTAssertNil(errorOrNil, @"Finished with unexpected error: %@", errorOrNil);
+            [completion fulfill];
+          }];
 
   [call startWithWriteable:responsesWriteable];
 
@@ -410,10 +425,12 @@
   RMTSimpleRequest *request = [RMTSimpleRequest message];
   request.responseSize = kPayloadSize;
 
-  __weak XCTestExpectation *expectation1 = [self expectationWithDescription:@"AlternateDispatchQueue1"];
+  __weak XCTestExpectation *expectation1 =
+      [self expectationWithDescription:@"AlternateDispatchQueue1"];
 
   // Use default (main) dispatch queue
-  NSString *main_queue_label = [NSString stringWithUTF8String:dispatch_queue_get_label(dispatch_get_main_queue())];
+  NSString *main_queue_label =
+      [NSString stringWithUTF8String:dispatch_queue_get_label(dispatch_get_main_queue())];
 
   GRXWriter *requestsWriter1 = [GRXWriter writerWithValue:[request data]];
 
@@ -421,20 +438,24 @@
                                               path:kUnaryCallMethod.HTTPPath
                                     requestsWriter:requestsWriter1];
 
-  id<GRXWriteable> responsesWriteable1 = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) {
-    NSString *label = [NSString stringWithUTF8String:dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL)];
-    XCTAssert([label isEqualToString:main_queue_label]);
+  id<GRXWriteable> responsesWriteable1 =
+      [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) {
+        NSString *label =
+            [NSString stringWithUTF8String:dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL)];
+        XCTAssert([label isEqualToString:main_queue_label]);
 
-    [expectation1 fulfill];
-  } completionHandler:^(NSError *errorOrNil) {
-  }];
+        [expectation1 fulfill];
+      }
+                               completionHandler:^(NSError *errorOrNil){
+                               }];
 
   [call1 startWithWriteable:responsesWriteable1];
 
   [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
 
   // Use a custom  queue
-  __weak XCTestExpectation *expectation2 = [self expectationWithDescription:@"AlternateDispatchQueue2"];
+  __weak XCTestExpectation *expectation2 =
+      [self expectationWithDescription:@"AlternateDispatchQueue2"];
 
   NSString *queue_label = @"test.queue1";
   dispatch_queue_t queue = dispatch_queue_create([queue_label UTF8String], DISPATCH_QUEUE_SERIAL);
@@ -447,13 +468,16 @@
 
   [call2 setResponseDispatchQueue:queue];
 
-  id<GRXWriteable> responsesWriteable2 = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) {
-    NSString *label = [NSString stringWithUTF8String:dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL)];
-    XCTAssert([label isEqualToString:queue_label]);
+  id<GRXWriteable> responsesWriteable2 =
+      [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) {
+        NSString *label =
+            [NSString stringWithUTF8String:dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL)];
+        XCTAssert([label isEqualToString:queue_label]);
 
-    [expectation2 fulfill];
-  } completionHandler:^(NSError *errorOrNil) {
-  }];
+        [expectation2 fulfill];
+      }
+                               completionHandler:^(NSError *errorOrNil){
+                               }];
 
   [call2 startWithWriteable:responsesWriteable2];
 
@@ -468,13 +492,16 @@
                                              path:kFullDuplexCallMethod.HTTPPath
                                    requestsWriter:pipe];
 
-  id<GRXWriteable> responsesWriteable = [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) {
-    XCTAssert(0, @"Failure: response received; Expect: no response received.");
-  } completionHandler:^(NSError *errorOrNil) {
-    XCTAssertNotNil(errorOrNil, @"Failure: no error received; Expect: receive deadline exceeded.");
-    XCTAssertEqual(errorOrNil.code, GRPCErrorCodeDeadlineExceeded);
-    [completion fulfill];
-  }];
+  id<GRXWriteable> responsesWriteable =
+      [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) {
+        XCTAssert(0, @"Failure: response received; Expect: no response received.");
+      }
+          completionHandler:^(NSError *errorOrNil) {
+            XCTAssertNotNil(errorOrNil,
+                            @"Failure: no error received; Expect: receive deadline exceeded.");
+            XCTAssertEqual(errorOrNil.code, GRPCErrorCodeDeadlineExceeded);
+            [completion fulfill];
+          }];
 
   call.timeout = 0.001;
   [call startWithWriteable:responsesWriteable];
@@ -482,4 +509,42 @@
   [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
 }
 
+- (int)findFreePort {
+  struct sockaddr_in addr;
+  unsigned int addr_len = sizeof(addr);
+  memset(&addr, 0, sizeof(addr));
+  addr.sin_family = AF_INET;
+  int fd = socket(AF_INET, SOCK_STREAM, 0);
+  XCTAssertEqual(bind(fd, (struct sockaddr *)&addr, sizeof(addr)), 0);
+  XCTAssertEqual(getsockname(fd, (struct sockaddr *)&addr, &addr_len), 0);
+  XCTAssertEqual(addr_len, sizeof(addr));
+  close(fd);
+  return addr.sin_port;
+}
+
+- (void)testErrorCode {
+  int port = [self findFreePort];
+  NSString *const kDummyAddress = [NSString stringWithFormat:@"localhost:%d", port];
+  __weak XCTestExpectation *completion = [self expectationWithDescription:@"Empty RPC completed."];
+
+  GRPCCall *call = [[GRPCCall alloc] initWithHost:kDummyAddress
+                                             path:kEmptyCallMethod.HTTPPath
+                                   requestsWriter:[GRXWriter writerWithValue:[NSData data]]];
+
+  id<GRXWriteable> responsesWriteable =
+      [[GRXWriteable alloc] initWithValueHandler:^(NSData *value) {
+        // Should not reach here
+        XCTAssert(NO);
+      }
+          completionHandler:^(NSError *errorOrNil) {
+            XCTAssertNotNil(errorOrNil, @"Finished with no error");
+            XCTAssertEqual(errorOrNil.code, GRPC_STATUS_UNAVAILABLE);
+            [completion fulfill];
+          }];
+
+  [call startWithWriteable:responsesWriteable];
+
+  [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
+}
+
 @end
diff --git a/src/objective-c/tests/InteropTests.m b/src/objective-c/tests/InteropTests.m
index dfa874a..1e1da2d 100644
--- a/src/objective-c/tests/InteropTests.m
+++ b/src/objective-c/tests/InteropTests.m
@@ -22,17 +22,17 @@
 
 #import <Cronet/Cronet.h>
 #import <GRPCClient/GRPCCall+ChannelArg.h>
+#import <GRPCClient/GRPCCall+Cronet.h>
 #import <GRPCClient/GRPCCall+Tests.h>
 #import <GRPCClient/internal_testing/GRPCCall+InternalTests.h>
-#import <GRPCClient/GRPCCall+Cronet.h>
 #import <ProtoRPC/ProtoRPC.h>
 #import <RemoteTest/Messages.pbobjc.h>
 #import <RemoteTest/Test.pbobjc.h>
 #import <RemoteTest/Test.pbrpc.h>
 #import <RxLibrary/GRXBufferedPipe.h>
 #import <RxLibrary/GRXWriter+Immediate.h>
-#import <grpc/support/log.h>
 #import <grpc/grpc.h>
+#import <grpc/support/log.h>
 
 #define TEST_TIMEOUT 32
 
@@ -61,7 +61,7 @@
 
 @implementation RMTStreamingOutputCallResponse (Constructors)
 + (instancetype)messageWithPayloadSize:(NSNumber *)payloadSize {
-  RMTStreamingOutputCallResponse * response = [self message];
+  RMTStreamingOutputCallResponse *response = [self message];
   response.payload.type = RMTPayloadType_Compressable;
   response.payload.body = [NSMutableData dataWithLength:payloadSize.unsignedIntegerValue];
   return response;
@@ -113,14 +113,15 @@
 
   GPBEmpty *request = [GPBEmpty message];
 
-  [_service emptyCallWithRequest:request handler:^(GPBEmpty *response, NSError *error) {
-    XCTAssertNil(error, @"Finished with unexpected error: %@", error);
+  [_service emptyCallWithRequest:request
+                         handler:^(GPBEmpty *response, NSError *error) {
+                           XCTAssertNil(error, @"Finished with unexpected error: %@", error);
 
-    id expectedResponse = [GPBEmpty message];
-    XCTAssertEqualObjects(response, expectedResponse);
+                           id expectedResponse = [GPBEmpty message];
+                           XCTAssertEqualObjects(response, expectedResponse);
 
-    [expectation fulfill];
-  }];
+                           [expectation fulfill];
+                         }];
 
   [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
 }
@@ -134,16 +135,17 @@
   request.responseSize = 314159;
   request.payload.body = [NSMutableData dataWithLength:271828];
 
-  [_service unaryCallWithRequest:request handler:^(RMTSimpleResponse *response, NSError *error) {
-    XCTAssertNil(error, @"Finished with unexpected error: %@", error);
+  [_service unaryCallWithRequest:request
+                         handler:^(RMTSimpleResponse *response, NSError *error) {
+                           XCTAssertNil(error, @"Finished with unexpected error: %@", error);
 
-    RMTSimpleResponse *expectedResponse = [RMTSimpleResponse message];
-    expectedResponse.payload.type = RMTPayloadType_Compressable;
-    expectedResponse.payload.body = [NSMutableData dataWithLength:314159];
-    XCTAssertEqualObjects(response, expectedResponse);
+                           RMTSimpleResponse *expectedResponse = [RMTSimpleResponse message];
+                           expectedResponse.payload.type = RMTPayloadType_Compressable;
+                           expectedResponse.payload.body = [NSMutableData dataWithLength:314159];
+                           XCTAssertEqualObjects(response, expectedResponse);
 
-    [expectation fulfill];
-  }];
+                           [expectation fulfill];
+                         }];
 
   [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
 }
@@ -158,29 +160,30 @@
   request.payload.body = [NSMutableData dataWithLength:10];
 
   [GRPCCall enableOpBatchLog:YES];
-  [_service unaryCallWithRequest:request handler:^(RMTSimpleResponse *response, NSError *error) {
-    XCTAssertNil(error, @"Finished with unexpected error: %@", error);
+  [_service unaryCallWithRequest:request
+                         handler:^(RMTSimpleResponse *response, NSError *error) {
+                           XCTAssertNil(error, @"Finished with unexpected error: %@", error);
 
-    RMTSimpleResponse *expectedResponse = [RMTSimpleResponse message];
-    expectedResponse.payload.type = RMTPayloadType_Compressable;
-    expectedResponse.payload.body = [NSMutableData dataWithLength:10];
-    XCTAssertEqualObjects(response, expectedResponse);
+                           RMTSimpleResponse *expectedResponse = [RMTSimpleResponse message];
+                           expectedResponse.payload.type = RMTPayloadType_Compressable;
+                           expectedResponse.payload.body = [NSMutableData dataWithLength:10];
+                           XCTAssertEqualObjects(response, expectedResponse);
 
-    // The test is a success if there is a batch of exactly 3 ops (SEND_INITIAL_METADATA,
-    // SEND_MESSAGE, SEND_CLOSE_FROM_CLIENT). Without packet coalescing each batch of ops contains
-    // only one op.
-    NSArray *opBatches = [GRPCCall obtainAndCleanOpBatchLog];
-    const NSInteger kExpectedOpBatchSize = 3;
-    for (NSObject *o in opBatches) {
-      if ([o isKindOfClass:[NSArray class]]) {
-        NSArray *batch = (NSArray *)o;
-        if ([batch count] == kExpectedOpBatchSize) {
-          [expectation fulfill];
-          break;
-        }
-      }
-    }
-  }];
+                           // The test is a success if there is a batch of exactly 3 ops
+                           // (SEND_INITIAL_METADATA, SEND_MESSAGE, SEND_CLOSE_FROM_CLIENT). Without
+                           // packet coalescing each batch of ops contains only one op.
+                           NSArray *opBatches = [GRPCCall obtainAndCleanOpBatchLog];
+                           const NSInteger kExpectedOpBatchSize = 3;
+                           for (NSObject *o in opBatches) {
+                             if ([o isKindOfClass:[NSArray class]]) {
+                               NSArray *batch = (NSArray *)o;
+                               if ([batch count] == kExpectedOpBatchSize) {
+                                 [expectation fulfill];
+                                 break;
+                               }
+                             }
+                           }
+                         }];
 
   [self waitForExpectationsWithTimeout:16 handler:nil];
   [GRPCCall enableOpBatchLog:NO];
@@ -191,14 +194,15 @@
   __weak XCTestExpectation *expectation = [self expectationWithDescription:@"MaxResponseSize"];
 
   RMTSimpleRequest *request = [RMTSimpleRequest message];
-  const int32_t kPayloadSize = 4 * 1024 * 1024 - self.encodingOverhead; // 4MB - encoding overhead
+  const int32_t kPayloadSize = 4 * 1024 * 1024 - self.encodingOverhead;  // 4MB - encoding overhead
   request.responseSize = kPayloadSize;
 
-  [_service unaryCallWithRequest:request handler:^(RMTSimpleResponse *response, NSError *error) {
-    XCTAssertNil(error, @"Finished with unexpected error: %@", error);
-    XCTAssertEqual(response.payload.body.length, kPayloadSize);
-    [expectation fulfill];
-  }];
+  [_service unaryCallWithRequest:request
+                         handler:^(RMTSimpleResponse *response, NSError *error) {
+                           XCTAssertNil(error, @"Finished with unexpected error: %@", error);
+                           XCTAssertEqual(response.payload.body.length, kPayloadSize);
+                           [expectation fulfill];
+                         }];
 
   [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
 }
@@ -208,18 +212,23 @@
   __weak XCTestExpectation *expectation = [self expectationWithDescription:@"ResponseOverMaxSize"];
 
   RMTSimpleRequest *request = [RMTSimpleRequest message];
-  const int32_t kPayloadSize = 4 * 1024 * 1024 - self.encodingOverhead + 1; // 1B over max size
+  const int32_t kPayloadSize = 4 * 1024 * 1024 - self.encodingOverhead + 1;  // 1B over max size
   request.responseSize = kPayloadSize;
 
-  [_service unaryCallWithRequest:request handler:^(RMTSimpleResponse *response, NSError *error) {
-    // TODO(jcanizales): Catch the error and rethrow it with an actionable message:
-    // - Use +[GRPCCall setResponseSizeLimit:forHost:] to set a higher limit.
-    // - If you're developing the server, consider using response streaming, or let clients filter
-    //   responses by setting a google.protobuf.FieldMask in the request:
-    //   https://github.com/google/protobuf/blob/master/src/google/protobuf/field_mask.proto
-    XCTAssertEqualObjects(error.localizedDescription, @"Received message larger than max (4194305 vs. 4194304)");
-    [expectation fulfill];
-  }];
+  [_service unaryCallWithRequest:request
+                         handler:^(RMTSimpleResponse *response, NSError *error) {
+                           // TODO(jcanizales): Catch the error and rethrow it with an actionable
+                           // message:
+                           // - Use +[GRPCCall setResponseSizeLimit:forHost:] to set a higher limit.
+                           // - If you're developing the server, consider using response streaming,
+                           // or let clients filter
+                           //   responses by setting a google.protobuf.FieldMask in the request:
+                           //   https://github.com/google/protobuf/blob/master/src/google/protobuf/field_mask.proto
+                           XCTAssertEqualObjects(
+                               error.localizedDescription,
+                               @"Received message larger than max (4194305 vs. 4194304)");
+                           [expectation fulfill];
+                         }];
 
   [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
 }
@@ -230,16 +239,17 @@
       [self expectationWithDescription:@"HigherResponseSizeLimit"];
 
   RMTSimpleRequest *request = [RMTSimpleRequest message];
-  const size_t kPayloadSize = 5 * 1024 * 1024; // 5MB
+  const size_t kPayloadSize = 5 * 1024 * 1024;  // 5MB
   request.responseSize = kPayloadSize;
 
   [GRPCCall setResponseSizeLimit:6 * 1024 * 1024 forHost:self.class.host];
 
-  [_service unaryCallWithRequest:request handler:^(RMTSimpleResponse *response, NSError *error) {
-    XCTAssertNil(error, @"Finished with unexpected error: %@", error);
-    XCTAssertEqual(response.payload.body.length, kPayloadSize);
-    [expectation fulfill];
-  }];
+  [_service unaryCallWithRequest:request
+                         handler:^(RMTSimpleResponse *response, NSError *error) {
+                           XCTAssertNil(error, @"Finished with unexpected error: %@", error);
+                           XCTAssertEqual(response.payload.body.length, kPayloadSize);
+                           [expectation fulfill];
+                         }];
 
   [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
 }
@@ -260,19 +270,21 @@
   RMTStreamingInputCallRequest *request4 = [RMTStreamingInputCallRequest message];
   request4.payload.body = [NSMutableData dataWithLength:45904];
 
-  GRXWriter *writer = [GRXWriter writerWithContainer:@[request1, request2, request3, request4]];
+  GRXWriter *writer = [GRXWriter writerWithContainer:@[ request1, request2, request3, request4 ]];
 
   [_service streamingInputCallWithRequestsWriter:writer
                                          handler:^(RMTStreamingInputCallResponse *response,
                                                    NSError *error) {
-    XCTAssertNil(error, @"Finished with unexpected error: %@", error);
+                                           XCTAssertNil(
+                                               error, @"Finished with unexpected error: %@", error);
 
-    RMTStreamingInputCallResponse *expectedResponse = [RMTStreamingInputCallResponse message];
-    expectedResponse.aggregatedPayloadSize = 74922;
-    XCTAssertEqualObjects(response, expectedResponse);
+                                           RMTStreamingInputCallResponse *expectedResponse =
+                                               [RMTStreamingInputCallResponse message];
+                                           expectedResponse.aggregatedPayloadSize = 74922;
+                                           XCTAssertEqualObjects(response, expectedResponse);
 
-    [expectation fulfill];
-  }];
+                                           [expectation fulfill];
+                                         }];
 
   [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
 }
@@ -281,7 +293,7 @@
   XCTAssertNotNil(self.class.host);
   __weak XCTestExpectation *expectation = [self expectationWithDescription:@"ServerStreaming"];
 
-  NSArray *expectedSizes = @[@31415, @9, @2653, @58979];
+  NSArray *expectedSizes = @[ @31415, @9, @2653, @58979 ];
 
   RMTStreamingOutputCallRequest *request = [RMTStreamingOutputCallRequest message];
   for (NSNumber *size in expectedSizes) {
@@ -291,25 +303,27 @@
   }
 
   __block int index = 0;
-  [_service streamingOutputCallWithRequest:request
-                              eventHandler:^(BOOL done,
-                                             RMTStreamingOutputCallResponse *response,
-                                             NSError *error){
-    XCTAssertNil(error, @"Finished with unexpected error: %@", error);
-    XCTAssertTrue(done || response, @"Event handler called without an event.");
+  [_service
+      streamingOutputCallWithRequest:request
+                        eventHandler:^(BOOL done, RMTStreamingOutputCallResponse *response,
+                                       NSError *error) {
+                          XCTAssertNil(error, @"Finished with unexpected error: %@", error);
+                          XCTAssertTrue(done || response,
+                                        @"Event handler called without an event.");
 
-    if (response) {
-      XCTAssertLessThan(index, 4, @"More than 4 responses received.");
-      id expected = [RMTStreamingOutputCallResponse messageWithPayloadSize:expectedSizes[index]];
-      XCTAssertEqualObjects(response, expected);
-      index += 1;
-    }
+                          if (response) {
+                            XCTAssertLessThan(index, 4, @"More than 4 responses received.");
+                            id expected = [RMTStreamingOutputCallResponse
+                                messageWithPayloadSize:expectedSizes[index]];
+                            XCTAssertEqualObjects(response, expected);
+                            index += 1;
+                          }
 
-    if (done) {
-      XCTAssertEqual(index, 4, @"Received %i responses instead of 4.", index);
-      [expectation fulfill];
-    }
-  }];
+                          if (done) {
+                            XCTAssertEqual(index, 4, @"Received %i responses instead of 4.", index);
+                            [expectation fulfill];
+                          }
+                        }];
 
   [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
 }
@@ -318,8 +332,8 @@
   XCTAssertNotNil(self.class.host);
   __weak XCTestExpectation *expectation = [self expectationWithDescription:@"PingPong"];
 
-  NSArray *requests = @[@27182, @8, @1828, @45904];
-  NSArray *responses = @[@31415, @9, @2653, @58979];
+  NSArray *requests = @[ @27182, @8, @1828, @45904 ];
+  NSArray *responses = @[ @31415, @9, @2653, @58979 ];
 
   GRXBufferedPipe *requestsBuffer = [[GRXBufferedPipe alloc] init];
 
@@ -330,31 +344,34 @@
   [requestsBuffer writeValue:request];
 
   [_service fullDuplexCallWithRequestsWriter:requestsBuffer
-                                eventHandler:^(BOOL done,
-                                               RMTStreamingOutputCallResponse *response,
+                                eventHandler:^(BOOL done, RMTStreamingOutputCallResponse *response,
                                                NSError *error) {
-    XCTAssertNil(error, @"Finished with unexpected error: %@", error);
-    XCTAssertTrue(done || response, @"Event handler called without an event.");
+                                  XCTAssertNil(error, @"Finished with unexpected error: %@", error);
+                                  XCTAssertTrue(done || response,
+                                                @"Event handler called without an event.");
 
-    if (response) {
-      XCTAssertLessThan(index, 4, @"More than 4 responses received.");
-      id expected = [RMTStreamingOutputCallResponse messageWithPayloadSize:responses[index]];
-      XCTAssertEqualObjects(response, expected);
-      index += 1;
-      if (index < 4) {
-        id request = [RMTStreamingOutputCallRequest messageWithPayloadSize:requests[index]
-                                                     requestedResponseSize:responses[index]];
-        [requestsBuffer writeValue:request];
-      } else {
-        [requestsBuffer writesFinishedWithError:nil];
-      }
-    }
+                                  if (response) {
+                                    XCTAssertLessThan(index, 4, @"More than 4 responses received.");
+                                    id expected = [RMTStreamingOutputCallResponse
+                                        messageWithPayloadSize:responses[index]];
+                                    XCTAssertEqualObjects(response, expected);
+                                    index += 1;
+                                    if (index < 4) {
+                                      id request = [RMTStreamingOutputCallRequest
+                                          messageWithPayloadSize:requests[index]
+                                           requestedResponseSize:responses[index]];
+                                      [requestsBuffer writeValue:request];
+                                    } else {
+                                      [requestsBuffer writesFinishedWithError:nil];
+                                    }
+                                  }
 
-    if (done) {
-      XCTAssertEqual(index, 4, @"Received %i responses instead of 4.", index);
-      [expectation fulfill];
-    }
-  }];
+                                  if (done) {
+                                    XCTAssertEqual(index, 4, @"Received %i responses instead of 4.",
+                                                   index);
+                                    [expectation fulfill];
+                                  }
+                                }];
   [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
 }
 
@@ -362,13 +379,12 @@
   XCTAssertNotNil(self.class.host);
   __weak XCTestExpectation *expectation = [self expectationWithDescription:@"EmptyStream"];
   [_service fullDuplexCallWithRequestsWriter:[GRXWriter emptyWriter]
-                                eventHandler:^(BOOL done,
-                                               RMTStreamingOutputCallResponse *response,
+                                eventHandler:^(BOOL done, RMTStreamingOutputCallResponse *response,
                                                NSError *error) {
-    XCTAssertNil(error, @"Finished with unexpected error: %@", error);
-    XCTAssert(done, @"Unexpected response: %@", response);
-    [expectation fulfill];
-  }];
+                                  XCTAssertNil(error, @"Finished with unexpected error: %@", error);
+                                  XCTAssert(done, @"Unexpected response: %@", response);
+                                  [expectation fulfill];
+                                }];
   [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
 }
 
@@ -379,13 +395,13 @@
   // A buffered pipe to which we never write any value acts as a writer that just hangs.
   GRXBufferedPipe *requestsBuffer = [[GRXBufferedPipe alloc] init];
 
-  GRPCProtoCall *call =
-      [_service RPCToStreamingInputCallWithRequestsWriter:requestsBuffer
-                                                  handler:^(RMTStreamingInputCallResponse *response,
-                                                            NSError *error) {
-    XCTAssertEqual(error.code, GRPC_STATUS_CANCELLED);
-    [expectation fulfill];
-  }];
+  GRPCProtoCall *call = [_service
+      RPCToStreamingInputCallWithRequestsWriter:requestsBuffer
+                                        handler:^(RMTStreamingInputCallResponse *response,
+                                                  NSError *error) {
+                                          XCTAssertEqual(error.code, GRPC_STATUS_CANCELLED);
+                                          [expectation fulfill];
+                                        }];
   XCTAssertEqual(call.state, GRXWriterStateNotStarted);
 
   [call start];
@@ -399,35 +415,36 @@
 
 - (void)testCancelAfterFirstResponseRPC {
   XCTAssertNotNil(self.class.host);
-  __weak XCTestExpectation *expectation = [self expectationWithDescription:@"CancelAfterFirstResponse"];
+  __weak XCTestExpectation *expectation =
+      [self expectationWithDescription:@"CancelAfterFirstResponse"];
 
   // A buffered pipe to which we write a single value but never close
   GRXBufferedPipe *requestsBuffer = [[GRXBufferedPipe alloc] init];
 
   __block BOOL receivedResponse = NO;
 
-  id request = [RMTStreamingOutputCallRequest messageWithPayloadSize:@21782
-                                               requestedResponseSize:@31415];
+  id request =
+      [RMTStreamingOutputCallRequest messageWithPayloadSize:@21782 requestedResponseSize:@31415];
 
   [requestsBuffer writeValue:request];
 
-  __block GRPCProtoCall *call =
-      [_service RPCToFullDuplexCallWithRequestsWriter:requestsBuffer
-                                         eventHandler:^(BOOL done,
-                                                        RMTStreamingOutputCallResponse *response,
-                                                        NSError *error) {
-    if (receivedResponse) {
-      XCTAssert(done, @"Unexpected extra response %@", response);
-      XCTAssertEqual(error.code, GRPC_STATUS_CANCELLED);
-      [expectation fulfill];
-    } else {
-      XCTAssertNil(error, @"Finished with unexpected error: %@", error);
-      XCTAssertFalse(done, @"Finished without response");
-      XCTAssertNotNil(response);
-      receivedResponse = YES;
-      [call cancel];
-    }
-  }];
+  __block GRPCProtoCall *call = [_service
+      RPCToFullDuplexCallWithRequestsWriter:requestsBuffer
+                               eventHandler:^(BOOL done, RMTStreamingOutputCallResponse *response,
+                                              NSError *error) {
+                                 if (receivedResponse) {
+                                   XCTAssert(done, @"Unexpected extra response %@", response);
+                                   XCTAssertEqual(error.code, GRPC_STATUS_CANCELLED);
+                                   [expectation fulfill];
+                                 } else {
+                                   XCTAssertNil(error, @"Finished with unexpected error: %@",
+                                                error);
+                                   XCTAssertFalse(done, @"Finished without response");
+                                   XCTAssertNotNil(response);
+                                   receivedResponse = YES;
+                                   [call cancel];
+                                 }
+                               }];
   [call start];
   [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
 }
@@ -439,19 +456,25 @@
 
   GPBEmpty *request = [GPBEmpty message];
 
-  [_service emptyCallWithRequest:request handler:^(GPBEmpty *response, NSError *error) {
-    XCTAssertNil(error, @"First RPC finished with unexpected error: %@", error);
+  [_service
+      emptyCallWithRequest:request
+                   handler:^(GPBEmpty *response, NSError *error) {
+                     XCTAssertNil(error, @"First RPC finished with unexpected error: %@", error);
 
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
-    [GRPCCall closeOpenConnections];
+                     [GRPCCall closeOpenConnections];
 #pragma clang diagnostic pop
 
-    [_service emptyCallWithRequest:request handler:^(GPBEmpty *response, NSError *error) {
-      XCTAssertNil(error, @"Second RPC finished with unexpected error: %@", error);
-      [expectation fulfill];
-    }];
-  }];
+                     [_service
+                         emptyCallWithRequest:request
+                                      handler:^(GPBEmpty *response, NSError *error) {
+                                        XCTAssertNil(
+                                            error, @"Second RPC finished with unexpected error: %@",
+                                            error);
+                                        [expectation fulfill];
+                                      }];
+                   }];
 
   [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
 }
@@ -472,18 +495,62 @@
   request.expectCompressed.value = YES;
   [GRPCCall setDefaultCompressMethod:GRPCCompressGzip forhost:self.class.host];
 
-  [_service unaryCallWithRequest:request handler:^(RMTSimpleResponse *response, NSError *error) {
-    XCTAssertNil(error, @"Finished with unexpected error: %@", error);
+  [_service unaryCallWithRequest:request
+                         handler:^(RMTSimpleResponse *response, NSError *error) {
+                           XCTAssertNil(error, @"Finished with unexpected error: %@", error);
 
-    RMTSimpleResponse *expectedResponse = [RMTSimpleResponse message];
-    expectedResponse.payload.type = RMTPayloadType_Compressable;
-    expectedResponse.payload.body = [NSMutableData dataWithLength:314159];
-    XCTAssertEqualObjects(response, expectedResponse);
+                           RMTSimpleResponse *expectedResponse = [RMTSimpleResponse message];
+                           expectedResponse.payload.type = RMTPayloadType_Compressable;
+                           expectedResponse.payload.body = [NSMutableData dataWithLength:314159];
+                           XCTAssertEqualObjects(response, expectedResponse);
 
-    [expectation fulfill];
-  }];
+                           [expectation fulfill];
+                         }];
 
   [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
 }
 
+#ifndef GRPC_COMPILE_WITH_CRONET
+- (void)testKeepalive {
+  XCTAssertNotNil(self.class.host);
+  __weak XCTestExpectation *expectation = [self expectationWithDescription:@"Keepalive"];
+
+  [GRPCCall setKeepaliveWithInterval:1500 timeout:0 forHost:self.class.host];
+
+  NSArray *requests = @[ @27182, @8 ];
+  NSArray *responses = @[ @31415, @9 ];
+
+  GRXBufferedPipe *requestsBuffer = [[GRXBufferedPipe alloc] init];
+
+  __block int index = 0;
+
+  id request = [RMTStreamingOutputCallRequest messageWithPayloadSize:requests[index]
+                                               requestedResponseSize:responses[index]];
+  [requestsBuffer writeValue:request];
+
+  [_service
+      fullDuplexCallWithRequestsWriter:requestsBuffer
+                          eventHandler:^(BOOL done, RMTStreamingOutputCallResponse *response,
+                                         NSError *error) {
+                            if (index == 0) {
+                              XCTAssertNil(error, @"Finished with unexpected error: %@", error);
+                              XCTAssertTrue(response, @"Event handler called without an event.");
+                              XCTAssertFalse(done);
+                              index++;
+                            } else {
+                              // Keepalive should kick after 1s elapsed and fails the call.
+                              XCTAssertNotNil(error);
+                              XCTAssertEqual(error.code, GRPC_STATUS_INTERNAL);
+                              XCTAssertEqualObjects(
+                                  error.localizedDescription, @"keepalive watchdog timeout",
+                                  @"Unexpected failure that is not keepalive watchdog timeout.");
+                              XCTAssertTrue(done);
+                              [expectation fulfill];
+                            }
+                          }];
+
+  [self waitForExpectationsWithTimeout:TEST_TIMEOUT handler:nil];
+}
+#endif
+
 @end
diff --git a/src/objective-c/tests/InteropTestsLocalCleartext.m b/src/objective-c/tests/InteropTestsLocalCleartext.m
index aba9868..d49e875 100644
--- a/src/objective-c/tests/InteropTestsLocalCleartext.m
+++ b/src/objective-c/tests/InteropTestsLocalCleartext.m
@@ -25,7 +25,7 @@
 // in turn derived from environment variable of the same name.
 #define NSStringize_helper(x) #x
 #define NSStringize(x) @NSStringize_helper(x)
-static NSString * const kLocalCleartextHost = NSStringize(HOST_PORT_LOCAL);
+static NSString *const kLocalCleartextHost = NSStringize(HOST_PORT_LOCAL);
 
 // The Protocol Buffers encoding overhead of local interop server. Acquired
 // by experiment. Adjust this when server's proto file changes.
@@ -42,7 +42,7 @@
 }
 
 - (int32_t)encodingOverhead {
-  return kLocalInteropServerOverhead; // bytes
+  return kLocalInteropServerOverhead;  // bytes
 }
 
 - (void)setUp {
diff --git a/src/objective-c/tests/InteropTestsLocalSSL.m b/src/objective-c/tests/InteropTestsLocalSSL.m
index 06176cc..a8c4dc7 100644
--- a/src/objective-c/tests/InteropTestsLocalSSL.m
+++ b/src/objective-c/tests/InteropTestsLocalSSL.m
@@ -24,7 +24,7 @@
 // in turn derived from environment variable of the same name.
 #define NSStringize_helper(x) #x
 #define NSStringize(x) @NSStringize_helper(x)
-static NSString * const kLocalSSLHost = NSStringize(HOST_PORT_LOCALSSL);
+static NSString *const kLocalSSLHost = NSStringize(HOST_PORT_LOCALSSL);
 
 // The Protocol Buffers encoding overhead of local interop server. Acquired
 // by experiment. Adjust this when server's proto file changes.
@@ -41,7 +41,7 @@
 }
 
 - (int32_t)encodingOverhead {
-  return kLocalInteropServerOverhead; // bytes
+  return kLocalInteropServerOverhead;  // bytes
 }
 
 - (void)setUp {
@@ -49,8 +49,8 @@
 
   // Register test server certificates and name.
   NSBundle *bundle = [NSBundle bundleForClass:self.class];
-  NSString *certsPath = [bundle pathForResource:@"TestCertificates.bundle/test-certificates"
-                                         ofType:@"pem"];
+  NSString *certsPath =
+      [bundle pathForResource:@"TestCertificates.bundle/test-certificates" ofType:@"pem"];
   [GRPCCall useTestCertsPath:certsPath testName:@"foo.test.google.fr" forHost:kLocalSSLHost];
 }
 
@@ -60,7 +60,7 @@
   @try {
     [GRPCCall useTestCertsPath:nil testName:nil forHost:nil];
     XCTFail(@"Did not receive an exception when parameters are nil");
-  } @catch(NSException *theException) {
+  } @catch (NSException *theException) {
     NSLog(@"Received exception as expected: %@", theException.name);
   }
 }
diff --git a/src/objective-c/tests/InteropTestsRemote.m b/src/objective-c/tests/InteropTestsRemote.m
index f8133e8..e5738aa 100644
--- a/src/objective-c/tests/InteropTestsRemote.m
+++ b/src/objective-c/tests/InteropTestsRemote.m
@@ -25,7 +25,7 @@
 // in turn derived from environment variable of the same name.
 #define NSStringize_helper(x) #x
 #define NSStringize(x) @NSStringize_helper(x)
-static NSString * const kRemoteSSLHost = NSStringize(HOST_PORT_REMOTE);
+static NSString *const kRemoteSSLHost = NSStringize(HOST_PORT_REMOTE);
 
 // The Protocol Buffers encoding overhead of remote interop server. Acquired
 // by experiment. Adjust this when server's proto file changes.
@@ -42,7 +42,7 @@
 }
 
 - (int32_t)encodingOverhead {
-  return kRemoteInteropServerOverhead; // bytes
+  return kRemoteInteropServerOverhead;  // bytes
 }
 
 @end
diff --git a/src/objective-c/tests/InteropTestsRemoteWithCronet/InteropTestsRemoteWithCronet.m b/src/objective-c/tests/InteropTestsRemoteWithCronet/InteropTestsRemoteWithCronet.m
index d4eb522..25041ae 100644
--- a/src/objective-c/tests/InteropTestsRemoteWithCronet/InteropTestsRemoteWithCronet.m
+++ b/src/objective-c/tests/InteropTestsRemoteWithCronet/InteropTestsRemoteWithCronet.m
@@ -28,8 +28,7 @@
 // in turn derived from environment variable of the same name.
 #define NSStringize_helper(x) #x
 #define NSStringize(x) @NSStringize_helper(x)
-static NSString * const kRemoteSSLHost = NSStringize(HOST_PORT_REMOTE);
-
+static NSString *const kRemoteSSLHost = NSStringize(HOST_PORT_REMOTE);
 
 // The Protocol Buffers encoding overhead of remote interop server. Acquired
 // by experiment. Adjust this when server's proto file changes.
@@ -46,7 +45,7 @@
 }
 
 - (int32_t)encodingOverhead {
-  return kRemoteInteropServerOverhead; // bytes
+  return kRemoteInteropServerOverhead;  // bytes
 }
 
 @end
diff --git a/src/objective-c/tests/Podfile b/src/objective-c/tests/Podfile
index 6e17d9a..b6e3897 100644
--- a/src/objective-c/tests/Podfile
+++ b/src/objective-c/tests/Podfile
@@ -26,8 +26,8 @@
     pod 'gRPC',           :path => GRPC_LOCAL_SRC
     pod 'gRPC-Core',      :path => GRPC_LOCAL_SRC
     pod 'gRPC-RxLibrary', :path => GRPC_LOCAL_SRC
-    pod 'gRPC-ProtoRPC',  :path => GRPC_LOCAL_SRC
-    pod 'RemoteTest', :path => "RemoteTestClient"
+    pod 'gRPC-ProtoRPC',  :path => GRPC_LOCAL_SRC, :inhibit_warnings => true
+    pod 'RemoteTest', :path => "RemoteTestClient", :inhibit_warnings => true
 
     if target_name == 'InteropTestsRemoteWithCronet'
       pod 'gRPC-Core/Cronet-Implementation', :path => GRPC_LOCAL_SRC
@@ -43,8 +43,10 @@
   target target_name do
     pod 'BoringSSL', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c", :inhibit_warnings => true
     pod 'CronetFramework', :podspec => "#{GRPC_LOCAL_SRC}/src/objective-c"
+    pod 'gRPC-Core', :path => GRPC_LOCAL_SRC
+    pod 'gRPC-Core/Cronet-Interface', :path => GRPC_LOCAL_SRC
     pod 'gRPC-Core/Cronet-Implementation', :path => GRPC_LOCAL_SRC
-    pod 'gRPC-Core/Cronet-Tests', :path => GRPC_LOCAL_SRC
+    pod 'gRPC-Core/Tests', :path => GRPC_LOCAL_SRC
   end
 end
 
diff --git a/src/objective-c/tests/RxLibraryUnitTests.m b/src/objective-c/tests/RxLibraryUnitTests.m
index aa178f8..ecd914c 100644
--- a/src/objective-c/tests/RxLibraryUnitTests.m
+++ b/src/objective-c/tests/RxLibraryUnitTests.m
@@ -30,10 +30,10 @@
 //
 // TODO(jcanizales): Move this to a test util library, and add tests for it.
 @interface CapturingSingleValueHandler : NSObject
-@property (nonatomic, readonly) void (^block)(id value, NSError *errorOrNil);
-@property (nonatomic, readonly) NSUInteger timesCalled;
-@property (nonatomic, readonly) id value;
-@property (nonatomic, readonly) NSError *errorOrNil;
+@property(nonatomic, readonly) void (^block)(id value, NSError *errorOrNil);
+@property(nonatomic, readonly) NSUInteger timesCalled;
+@property(nonatomic, readonly) id value;
+@property(nonatomic, readonly) NSError *errorOrNil;
 + (instancetype)handler;
 @end
 
@@ -149,10 +149,11 @@
   __weak XCTestExpectation *expectation = [self expectationWithDescription:@"Response received"];
   // Given:
   CapturingSingleValueHandler *handler = [CapturingSingleValueHandler handler];
-  id<GRXWriteable> writeable = [GRXWriteable writeableWithSingleHandler:^(id value, NSError *errorOrNil) {
-    handler.block(value, errorOrNil);
-    [expectation fulfill];
-  }];
+  id<GRXWriteable> writeable =
+      [GRXWriteable writeableWithSingleHandler:^(id value, NSError *errorOrNil) {
+        handler.block(value, errorOrNil);
+        [expectation fulfill];
+      }];
 
   id anyValue = @7;
 
@@ -167,17 +168,17 @@
   XCTAssertEqual(handler.timesCalled, 1);
   XCTAssertEqualObjects(handler.value, anyValue);
   XCTAssertEqualObjects(handler.errorOrNil, nil);
-
 }
 
 - (void)testBufferedPipePropagatesError {
   __weak XCTestExpectation *expectation = [self expectationWithDescription:@"Response received"];
   // Given:
   CapturingSingleValueHandler *handler = [CapturingSingleValueHandler handler];
-  id<GRXWriteable> writeable = [GRXWriteable writeableWithSingleHandler:^(id value, NSError *errorOrNil) {
-    handler.block(value, errorOrNil);
-    [expectation fulfill];
-  }];
+  id<GRXWriteable> writeable =
+      [GRXWriteable writeableWithSingleHandler:^(id value, NSError *errorOrNil) {
+        handler.block(value, errorOrNil);
+        [expectation fulfill];
+      }];
   NSError *anyError = [NSError errorWithDomain:@"domain" code:7 userInfo:nil];
 
   // If:
@@ -196,10 +197,11 @@
   __weak XCTestExpectation *expectation = [self expectationWithDescription:@"Response received"];
   // Given:
   CapturingSingleValueHandler *handler = [CapturingSingleValueHandler handler];
-  id<GRXWriteable> writeable = [GRXWriteable writeableWithSingleHandler:^(id value, NSError *errorOrNil) {
-    handler.block(value, errorOrNil);
-    [expectation fulfill];
-  }];
+  id<GRXWriteable> writeable =
+      [GRXWriteable writeableWithSingleHandler:^(id value, NSError *errorOrNil) {
+        handler.block(value, errorOrNil);
+        [expectation fulfill];
+      }];
   id anyValue = @7;
 
   // If:
@@ -220,8 +222,9 @@
 #define WRITE_ROUNDS (1000)
 - (void)testBufferedPipeResumeWhenDealloc {
   id anyValue = @7;
-  id<GRXWriteable> writeable = [GRXWriteable  writeableWithSingleHandler:^(id value, NSError *errorOrNil) {
-  }];
+  id<GRXWriteable> writeable =
+      [GRXWriteable writeableWithSingleHandler:^(id value, NSError *errorOrNil){
+      }];
 
   // Release after alloc;
   GRXBufferedPipe *pipe = [GRXBufferedPipe pipe];
diff --git a/src/objective-c/tests/version.h b/src/objective-c/tests/version.h
index 6f6cd25..e963709 100644
--- a/src/objective-c/tests/version.h
+++ b/src/objective-c/tests/version.h
@@ -22,6 +22,5 @@
 // instead. This file can be regenerated from the template by running
 // `tools/buildgen/generate_projects.sh`.
 
-
-#define GRPC_OBJC_VERSION_STRING @"1.11.0-dev"
+#define GRPC_OBJC_VERSION_STRING @"1.13.0-dev"
 #define GRPC_C_VERSION_STRING @"6.0.0-dev"
diff --git a/src/php/bin/run_tests.sh b/src/php/bin/run_tests.sh
index c4712ea..b913166 100755
--- a/src/php/bin/run_tests.sh
+++ b/src/php/bin/run_tests.sh
@@ -21,6 +21,6 @@
 cd src/php/bin
 source ./determine_extension_dir.sh
 # in some jenkins macos machine, somehow the PHP build script can't find libgrpc.dylib
-export DYLD_LIBRARY_PATH=$root/libs/$config
+export DYLD_LIBRARY_PATH=$root/libs/$CONFIG
 php $extension_dir -d max_execution_time=300 $(which phpunit) -v --debug \
   ../tests/unit_tests
diff --git a/src/php/composer.json b/src/php/composer.json
index dbf0cc3..03dffb4 100644
--- a/src/php/composer.json
+++ b/src/php/composer.json
@@ -2,7 +2,7 @@
   "name": "grpc/grpc-dev",
   "description": "gRPC library for PHP - for Developement use only",
   "license": "Apache-2.0",
-  "version": "1.11.0",
+  "version": "1.13.0",
   "require": {
     "php": ">=5.5.0",
     "google/protobuf": "^v3.3.0"
diff --git a/src/php/ext/grpc/channel.c b/src/php/ext/grpc/channel.c
index 4054723..35adf6b 100644
--- a/src/php/ext/grpc/channel.c
+++ b/src/php/ext/grpc/channel.c
@@ -54,12 +54,12 @@
 #endif
 static gpr_mu global_persistent_list_mu;
 int le_plink;
+extern HashTable grpc_persistent_list;
 
 /* Frees and destroys an instance of wrapped_grpc_channel */
 PHP_GRPC_FREE_WRAPPED_FUNC_START(wrapped_grpc_channel)
-  bool is_last_wrapper = false;
-  // In_persistent_list is used when the user don't close the channel.
-  // In this case, le in the list won't be freed.
+  // In_persistent_list is used when the user don't close the channel,
+  // In this case, channels not in the list should be freed.
   bool in_persistent_list = true;
   if (p->wrapper != NULL) {
     gpr_mu_lock(&p->wrapper->mu);
@@ -69,51 +69,32 @@
         php_grpc_int key_len = strlen(p->wrapper->key);
         // only destroy the channel here if not found in the persistent list
         gpr_mu_lock(&global_persistent_list_mu);
-        if (!(PHP_GRPC_PERSISTENT_LIST_FIND(&EG(persistent_list), p->wrapper->key,
+        if (!(PHP_GRPC_PERSISTENT_LIST_FIND(&grpc_persistent_list, p->wrapper->key,
                                             key_len, rsrc))) {
           in_persistent_list = false;
           grpc_channel_destroy(p->wrapper->wrapped);
           free(p->wrapper->target);
           free(p->wrapper->args_hashstr);
-          if(p->wrapper->creds_hashstr != NULL){
+          if (p->wrapper->creds_hashstr != NULL) {
             free(p->wrapper->creds_hashstr);
             p->wrapper->creds_hashstr = NULL;
           }
+          free(p->wrapper->key);
+          p->wrapper->wrapped = NULL;
+          p->wrapper->target = NULL;
+          p->wrapper->args_hashstr = NULL;
+          p->wrapper->key = NULL;
         }
         gpr_mu_unlock(&global_persistent_list_mu);
       }
     }
     p->wrapper->ref_count -= 1;
-    if (p->wrapper->ref_count == 0) {
-      is_last_wrapper = true;
-    }
     gpr_mu_unlock(&p->wrapper->mu);
-    if (is_last_wrapper) {
-      if (in_persistent_list) {
-        // If ref_count==0 and the key still in the list, it means the user
-        // don't call channel->close().persistent list should free the
-        // allocation in such case, as well as related wrapped channel.
-        if (p->wrapper->wrapped != NULL) {
-          gpr_mu_lock(&p->wrapper->mu);
-          grpc_channel_destroy(p->wrapper->wrapped);
-          free(p->wrapper->target);
-          free(p->wrapper->args_hashstr);
-          if(p->wrapper->creds_hashstr != NULL){
-            free(p->wrapper->creds_hashstr);
-            p->wrapper->creds_hashstr = NULL;
-          }
-          p->wrapper->wrapped = NULL;
-          php_grpc_delete_persistent_list_entry(p->wrapper->key,
-                                                strlen(p->wrapper->key)
-                                                TSRMLS_CC);
-          gpr_mu_unlock(&p->wrapper->mu);
-        }
-      }
+    if (!in_persistent_list) {
       gpr_mu_destroy(&p->wrapper->mu);
-      free(p->wrapper->key);
       free(p->wrapper);
+      p->wrapper = NULL;
     }
-    p->wrapper = NULL;
   }
 PHP_GRPC_FREE_WRAPPED_FUNC_END()
 
@@ -214,7 +195,7 @@
   le->channel = channel->wrapper;
   new_rsrc.ptr = le;
   gpr_mu_lock(&global_persistent_list_mu);
-  PHP_GRPC_PERSISTENT_LIST_UPDATE(&EG(persistent_list), key, key_len,
+  PHP_GRPC_PERSISTENT_LIST_UPDATE(&grpc_persistent_list, key, key_len,
                                   (void *)&new_rsrc);
   gpr_mu_unlock(&global_persistent_list_mu);
 }
@@ -330,13 +311,12 @@
 
   gpr_mu_init(&channel->wrapper->mu);
   smart_str_free(&buf);
-
   if (force_new || (creds != NULL && creds->has_call_creds)) {
     // If the ChannelCredentials object was composed with a CallCredentials
     // object, there is no way we can tell them apart. Do NOT persist
     // them. They should be individually destroyed.
     create_channel(channel, target, args, creds);
-  } else if (!(PHP_GRPC_PERSISTENT_LIST_FIND(&EG(persistent_list), key,
+  } else if (!(PHP_GRPC_PERSISTENT_LIST_FIND(&grpc_persistent_list, key,
                                              key_len, rsrc))) {
     create_and_add_channel_to_persistent_list(
         channel, target, args, creds, key, key_len TSRMLS_CC);
@@ -352,7 +332,7 @@
           channel, target, args, creds, key, key_len TSRMLS_CC);
     } else {
       efree(args.args);
-      if (channel->wrapper->creds_hashstr != NULL){
+      if (channel->wrapper->creds_hashstr != NULL) {
         free(channel->wrapper->creds_hashstr);
         channel->wrapper->creds_hashstr = NULL;
       }
@@ -481,10 +461,10 @@
         grpc_channel_destroy(channel->wrapper->wrapped);
         free(channel->wrapper->target);
         free(channel->wrapper->args_hashstr);
-        if(channel->wrapper->creds_hashstr != NULL){
-          free(channel->wrapper->creds_hashstr);
-          channel->wrapper->creds_hashstr = NULL;
-        }
+        free(channel->wrapper->creds_hashstr);
+        channel->wrapper->creds_hashstr = NULL;
+        channel->wrapper->target = NULL;
+        channel->wrapper->args_hashstr = NULL;
         channel->wrapper->wrapped = NULL;
         channel->wrapper->is_valid = false;
 
@@ -494,7 +474,7 @@
       }
     }
     channel->wrapper->ref_count -= 1;
-    if(channel->wrapper->ref_count == 0){
+    if (channel->wrapper->ref_count == 0) {
       // Mark that the wrapper can be freed because mu should be
       // destroyed outside the lock.
       is_last_wrapper = true;
@@ -519,12 +499,12 @@
                                            TSRMLS_DC) {
   php_grpc_zend_resource *rsrc;
   gpr_mu_lock(&global_persistent_list_mu);
-  if (PHP_GRPC_PERSISTENT_LIST_FIND(&EG(persistent_list), key,
+  if (PHP_GRPC_PERSISTENT_LIST_FIND(&grpc_persistent_list, key,
                                     key_len, rsrc)) {
     channel_persistent_le_t *le;
     le = (channel_persistent_le_t *)rsrc->ptr;
     le->channel = NULL;
-    php_grpc_zend_hash_del(&EG(persistent_list), key, key_len+1);
+    php_grpc_zend_hash_del(&grpc_persistent_list, key, key_len+1);
     free(le);
   }
   gpr_mu_unlock(&global_persistent_list_mu);
@@ -534,12 +514,19 @@
 static void php_grpc_channel_plink_dtor(php_grpc_zend_resource *rsrc
                                         TSRMLS_DC) {
   channel_persistent_le_t *le = (channel_persistent_le_t *)rsrc->ptr;
+  if (le == NULL) {
+    return;
+  }
   if (le->channel != NULL) {
     gpr_mu_lock(&le->channel->mu);
     if (le->channel->wrapped != NULL) {
       grpc_channel_destroy(le->channel->wrapped);
-      free(le->channel->target);
       free(le->channel->args_hashstr);
+      le->channel->wrapped = NULL;
+      le->channel->target = NULL;
+      le->channel->args_hashstr = NULL;
+      free(le->channel->key);
+      le->channel->key = NULL;
     }
     gpr_mu_unlock(&le->channel->mu);
   }
@@ -587,6 +574,8 @@
   gpr_mu_init(&global_persistent_list_mu);
   le_plink = zend_register_list_destructors_ex(
       NULL, php_grpc_channel_plink_dtor, "Persistent Channel", module_number);
+  zend_hash_init_ex(&grpc_persistent_list, 20, NULL,
+                    EG(persistent_list).pDestructor, 1, 0);
   PHP_GRPC_INIT_HANDLER(wrapped_grpc_channel, channel_ce_handlers);
   return SUCCESS;
 }
diff --git a/src/php/ext/grpc/php7_wrapper.h b/src/php/ext/grpc/php7_wrapper.h
index 2f4a536..0239e04 100644
--- a/src/php/ext/grpc/php7_wrapper.h
+++ b/src/php/ext/grpc/php7_wrapper.h
@@ -30,6 +30,8 @@
   add_property_string(arg, name, context, b)
 #define php_grpc_add_property_stringl(res, name, str, len, b) \
   add_property_stringl(res, name, str, len, b)
+#define php_grpc_add_property_zval(res, name, val) \
+  add_property_zval(res, name, val)
 #define php_grpc_add_next_index_stringl(data, str, len, b) \
   add_next_index_stringl(data, str, len, b)
 
@@ -38,6 +40,12 @@
 #define PHP_GRPC_MAKE_STD_ZVAL(pzv) MAKE_STD_ZVAL(pzv)
 #define PHP_GRPC_FREE_STD_ZVAL(pzv)
 #define PHP_GRPC_DELREF(zv) Z_DELREF_P(zv)
+#define PHP_GRPC_ADD_STRING_TO_ARRAY(val, key, key_len, str, dup) \
+   add_assoc_string_ex(val, key, key_len , str, dup);
+#define PHP_GRPC_ADD_LONG_TO_ARRAY(val, key, key_len, str) \
+   add_assoc_long_ex(val, key, key_len, str);
+#define PHP_GRPC_ADD_BOOL_TO_ARRAY(val, key, key_len, str) \
+   add_assoc_bool_ex(val, key, key_len, str);
 
 #define RETURN_DESTROY_ZVAL(val) \
   RETURN_ZVAL(val, false /* Don't execute copy constructor */, \
@@ -88,6 +96,9 @@
                                          0, NULL); \
     data = *tmp##key;
 
+#define PHP_GRPC_HASH_VALPTR_TO_VAL(data) \
+  &data;
+
 #define PHP_GRPC_HASH_FOREACH_LONG_KEY_VAL_START(ht, key, key_type, index,\
                                                  data) \
   zval **tmp##key = NULL; \
@@ -128,6 +139,8 @@
 #define PHP_GRPC_PERSISTENT_LIST_UPDATE(plist, key, len, rsrc) \
   zend_hash_update(plist, key, len+1, rsrc, sizeof(php_grpc_zend_resource), \
                    NULL)
+#define PHP_GRPC_PERSISTENT_LIST_SIZE(plist) \
+  plist.nTableSize
 
 #define PHP_GRPC_GET_CLASS_ENTRY(object) zend_get_class_entry(object TSRMLS_CC)
 
@@ -143,6 +156,11 @@
   add_property_string(arg, name, context)
 #define php_grpc_add_property_stringl(res, name, str, len, b) \
   add_property_stringl(res, name, str, len)
+#define php_grpc_add_property_zval(res, name, val) do { \
+  zval tmp; \
+  tmp = *val; \
+  add_property_zval(res, name, &tmp); \
+  } while(0)
 #define php_grpc_add_next_index_stringl(data, str, len, b) \
   add_next_index_stringl(data, str, len)
 
@@ -152,6 +170,12 @@
   pzv = (zval *)emalloc(sizeof(zval));
 #define PHP_GRPC_FREE_STD_ZVAL(pzv) efree(pzv);
 #define PHP_GRPC_DELREF(zv)
+#define PHP_GRPC_ADD_STRING_TO_ARRAY(val, key, key_len, str, dup) \
+   add_assoc_string_ex(val, key, key_len - 1, str);
+#define PHP_GRPC_ADD_LONG_TO_ARRAY(val, key, key_len, str) \
+   add_assoc_long_ex(val, key, key_len - 1, str);
+#define PHP_GRPC_ADD_BOOL_TO_ARRAY(val, key, key_len, str) \
+   add_assoc_bool_ex(val, key, key_len - 1, str);
 
 #define RETURN_DESTROY_ZVAL(val) \
   RETVAL_ZVAL(val, false /* Don't execute copy constructor */, \
@@ -193,6 +217,9 @@
     if ((zs_##key) == NULL) {key = NULL; key_type = HASH_KEY_IS_LONG;} \
     else {key = (zs_##key)->val; key_type = HASH_KEY_IS_STRING;}
 
+#define PHP_GRPC_HASH_VALPTR_TO_VAL(data) \
+  Z_PTR_P(data);
+
 #define PHP_GRPC_HASH_FOREACH_LONG_KEY_VAL_START(ht, key, key_type, index, \
                                                  data) \
   zend_string *(zs_##key); \
@@ -230,6 +257,8 @@
 #define PHP_GRPC_PERSISTENT_LIST_UPDATE(plist, key, len, rsrc) \
   zend_hash_str_update_mem(plist, key, len, rsrc, \
                            sizeof(php_grpc_zend_resource))
+#define PHP_GRPC_PERSISTENT_LIST_SIZE(plist) \
+  zend_array_count(plist)
 
 #define PHP_GRPC_GET_CLASS_ENTRY(object) Z_OBJ_P(object)->ce
 
diff --git a/src/php/ext/grpc/php_grpc.c b/src/php/ext/grpc/php_grpc.c
index 5971bab..883ee6f 100644
--- a/src/php/ext/grpc/php_grpc.c
+++ b/src/php/ext/grpc/php_grpc.c
@@ -36,7 +36,7 @@
 
 ZEND_DECLARE_MODULE_GLOBALS(grpc)
 static PHP_GINIT_FUNCTION(grpc);
-
+HashTable grpc_persistent_list;
 /* {{{ grpc_functions[]
  *
  * Every user visible function must have an entry in grpc_functions[].
@@ -240,6 +240,8 @@
   // WARNING: This function IS being called by PHP when the extension
   // is unloaded but the logs were somehow suppressed.
   if (GRPC_G(initialized)) {
+    zend_hash_clean(&grpc_persistent_list);
+    zend_hash_destroy(&grpc_persistent_list);
     grpc_shutdown_timeval(TSRMLS_C);
     grpc_php_shutdown_completion_queue(TSRMLS_C);
     grpc_shutdown();
@@ -256,7 +258,6 @@
   php_info_print_table_row(2, "grpc support", "enabled");
   php_info_print_table_row(2, "grpc module version", PHP_GRPC_VERSION);
   php_info_print_table_end();
-
   /* Remove comments if you have entries in php.ini
      DISPLAY_INI_ENTRIES();
   */
diff --git a/src/php/ext/grpc/server.c b/src/php/ext/grpc/server.c
index a65d233..292d512 100644
--- a/src/php/ext/grpc/server.c
+++ b/src/php/ext/grpc/server.c
@@ -89,8 +89,6 @@
   if (args_array == NULL) {
     server->wrapped = grpc_server_create(NULL, NULL);
   } else {
-    //TODO(thinkerou): deal it if key of array is long, crash now on php7
-    // and update unit test case
     php_grpc_read_args_array(args_array, &args TSRMLS_CC);
     server->wrapped = grpc_server_create(&args, NULL);
     efree(args.args);
@@ -118,8 +116,8 @@
   grpc_call_details_init(&details);
   grpc_metadata_array_init(&metadata);
   error_code =
-      grpc_server_request_call(server->wrapped, &call, &details, &metadata,
-                               completion_queue, completion_queue, NULL);
+    grpc_server_request_call(server->wrapped, &call, &details, &metadata,
+                             completion_queue, completion_queue, NULL);
   if (error_code != GRPC_CALL_OK) {
     zend_throw_exception(spl_ce_LogicException, "request_call failed",
                          (long)error_code TSRMLS_CC);
@@ -140,25 +138,12 @@
   php_grpc_add_property_string(result, "host", host_text, true);
   gpr_free(method_text);
   gpr_free(host_text);
-#if PHP_MAJOR_VERSION < 7
-  add_property_zval(result, "call", grpc_php_wrap_call(call, true TSRMLS_CC));
-  add_property_zval(result, "absolute_deadline",
-                    grpc_php_wrap_timeval(details.deadline TSRMLS_CC));
-  add_property_zval(result, "metadata", grpc_parse_metadata_array(&metadata
-                                                                  TSRMLS_CC));
-#else
-  zval zv_call;
-  zval zv_timeval;
-  zval zv_md;
-  //TODO(thinkerou): why use zval* to unit test error?
-  zv_call = *grpc_php_wrap_call(call, true);
-  zv_timeval = *grpc_php_wrap_timeval(details.deadline);
-  zv_md = *grpc_parse_metadata_array(&metadata);
-
-  add_property_zval(result, "call", &zv_call);
-  add_property_zval(result, "absolute_deadline", &zv_timeval);
-  add_property_zval(result, "metadata", &zv_md);
-#endif
+  php_grpc_add_property_zval(result, "call",
+                             grpc_php_wrap_call(call, true TSRMLS_CC));
+  php_grpc_add_property_zval(result, "absolute_deadline",
+                             grpc_php_wrap_timeval(details.deadline TSRMLS_CC));
+  php_grpc_add_property_zval(result, "metadata",
+                             grpc_parse_metadata_array(&metadata TSRMLS_CC));
 
  cleanup:
   grpc_call_details_destroy(&details);
@@ -202,9 +187,9 @@
   if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sO", &addr, &addr_len,
                             &creds_obj, grpc_ce_server_credentials) ==
       FAILURE) {
-    zend_throw_exception(
-        spl_ce_InvalidArgumentException,
-        "add_http2_port expects a string and a ServerCredentials", 1 TSRMLS_CC);
+    zend_throw_exception(spl_ce_InvalidArgumentException,
+                         "add_http2_port expects a string and a "
+                         "ServerCredentials", 1 TSRMLS_CC);
     return;
   }
   wrapped_grpc_server_credentials *creds =
diff --git a/src/php/ext/grpc/version.h b/src/php/ext/grpc/version.h
index dd2a701..407d634 100644
--- a/src/php/ext/grpc/version.h
+++ b/src/php/ext/grpc/version.h
@@ -20,6 +20,6 @@
 #ifndef VERSION_H
 #define VERSION_H
 
-#define PHP_GRPC_VERSION "1.11.0dev"
+#define PHP_GRPC_VERSION "1.13.0dev"
 
 #endif /* VERSION_H */
diff --git a/src/php/lib/Grpc/BaseStub.php b/src/php/lib/Grpc/BaseStub.php
index 5f3a96f..7860233 100644
--- a/src/php/lib/Grpc/BaseStub.php
+++ b/src/php/lib/Grpc/BaseStub.php
@@ -38,12 +38,13 @@
      *  - 'update_metadata': (optional) a callback function which takes in a
      * metadata array, and returns an updated metadata array
      *  - 'grpc.primary_user_agent': (optional) a user-agent string
-     * @param Channel $channel An already created Channel object (optional)
+     * @param Channel|InterceptorChannel $channel An already created Channel or InterceptorChannel object (optional)
      */
-    public function __construct($hostname, $opts, Channel $channel = null)
+    public function __construct($hostname, $opts, $channel = null)
     {
         $ssl_roots = file_get_contents(
-            dirname(__FILE__).'/../../../../etc/roots.pem');
+            dirname(__FILE__).'/../../../../etc/roots.pem'
+        );
         ChannelCredentials::setDefaultRootsPem($ssl_roots);
 
         $this->hostname = $hostname;
@@ -58,16 +59,20 @@
             $this->hostname_override = $opts['grpc.ssl_target_name_override'];
         }
         if ($channel) {
-            if (!is_a($channel, 'Grpc\Channel')) {
-                throw new \Exception('The channel argument is not a'.
-                                     'Channel object');
+            if (!is_a($channel, 'Grpc\Channel') &&
+                !is_a($channel, 'Grpc\InterceptorChannel')) {
+                throw new \Exception('The channel argument is not a Channel object '.
+                    'or an InterceptorChannel object created by '.
+                    'Interceptor::intercept($channel, Interceptor|Interceptor[] $interceptors)');
             }
             $this->channel = $channel;
             return;
         }
 
         $package_config = json_decode(
-            file_get_contents(dirname(__FILE__).'/../../composer.json'), true);
+            file_get_contents(dirname(__FILE__).'/../../composer.json'),
+            true
+        );
         if (!empty($opts['grpc.primary_user_agent'])) {
             $opts['grpc.primary_user_agent'] .= ' ';
         } else {
@@ -77,8 +82,8 @@
             'grpc-php/'.$package_config['version'];
         if (!array_key_exists('credentials', $opts)) {
             throw new \Exception("The opts['credentials'] key is now ".
-                                 'required. Please see one of the '.
-                                 'ChannelCredentials::create methods');
+                'required. Please see one of the '.
+                'ChannelCredentials::create methods');
         }
         $this->channel = new Channel($hostname, $opts);
     }
@@ -169,7 +174,8 @@
         $last_slash_idx = strrpos($method, '/');
         if ($last_slash_idx === false) {
             throw new \InvalidArgumentException(
-                'service name must have a slash');
+                'service name must have a slash'
+            );
         }
         $service_name = substr($method, 0, $last_slash_idx);
 
@@ -197,7 +203,8 @@
             if (!preg_match('/^[A-Za-z\d_-]+$/', $key)) {
                 throw new \InvalidArgumentException(
                     'Metadata keys must be nonempty strings containing only '.
-                    'alphanumeric characters, hyphens and underscores');
+                    'alphanumeric characters, hyphens and underscores'
+                );
             }
             $metadata_copy[strtolower($key)] = $value;
         }
@@ -205,9 +212,255 @@
         return $metadata_copy;
     }
 
+    /**
+     * Create a function which can be used to create UnaryCall
+     *
+     * @param Channel|InterceptorChannel   $channel
+     * @param callable $deserialize A function that deserializes the response
+     *
+     * @return \Closure
+     */
+    private function _GrpcUnaryUnary($channel, $deserialize)
+    {
+        return function ($method,
+                         $argument,
+                         array $metadata = [],
+                         array $options = []) use ($channel, $deserialize) {
+            $call = new UnaryCall(
+                $channel,
+                $method,
+                $deserialize,
+                $options
+            );
+            $jwt_aud_uri = $this->_get_jwt_aud_uri($method);
+            if (is_callable($this->update_metadata)) {
+                $metadata = call_user_func(
+                    $this->update_metadata,
+                    $metadata,
+                    $jwt_aud_uri
+                );
+            }
+            $metadata = $this->_validate_and_normalize_metadata(
+                $metadata
+            );
+            $call->start($argument, $metadata, $options);
+            return $call;
+        };
+    }
+
+    /**
+     * Create a function which can be used to create ServerStreamingCall
+     *
+     * @param Channel|InterceptorChannel   $channel
+     * @param callable $deserialize A function that deserializes the response
+     *
+     * @return \Closure
+     */
+    private function _GrpcStreamUnary($channel, $deserialize)
+    {
+        return function ($method,
+                         array $metadata = [],
+                         array $options = []) use ($channel, $deserialize) {
+            $call = new ClientStreamingCall(
+                $channel,
+                $method,
+                $deserialize,
+                $options
+            );
+            $jwt_aud_uri = $this->_get_jwt_aud_uri($method);
+            if (is_callable($this->update_metadata)) {
+                $metadata = call_user_func(
+                    $this->update_metadata,
+                    $metadata,
+                    $jwt_aud_uri
+                );
+            }
+            $metadata = $this->_validate_and_normalize_metadata(
+                $metadata
+            );
+            $call->start($metadata);
+            return $call;
+        };
+    }
+
+    /**
+     * Create a function which can be used to create ClientStreamingCall
+     *
+     * @param Channel|InterceptorChannel   $channel
+     * @param callable $deserialize A function that deserializes the response
+     *
+     * @return \Closure
+     */
+    private function _GrpcUnaryStream($channel, $deserialize)
+    {
+        return function ($method,
+                         $argument,
+                         array $metadata = [],
+                         array $options = []) use ($channel, $deserialize) {
+            $call = new ServerStreamingCall(
+                $channel,
+                $method,
+                $deserialize,
+                $options
+            );
+            $jwt_aud_uri = $this->_get_jwt_aud_uri($method);
+            if (is_callable($this->update_metadata)) {
+                $metadata = call_user_func(
+                    $this->update_metadata,
+                    $metadata,
+                    $jwt_aud_uri
+                );
+            }
+            $metadata = $this->_validate_and_normalize_metadata(
+                $metadata
+            );
+            $call->start($argument, $metadata, $options);
+            return $call;
+        };
+    }
+
+    /**
+     * Create a function which can be used to create BidiStreamingCall
+     *
+     * @param Channel|InterceptorChannel   $channel
+     * @param callable $deserialize A function that deserializes the response
+     *
+     * @return \Closure
+     */
+    private function _GrpcStreamStream($channel, $deserialize)
+    {
+        return function ($method,
+                         array $metadata = [],
+                         array $options = []) use ($channel ,$deserialize) {
+            $call = new BidiStreamingCall(
+                $channel,
+                $method,
+                $deserialize,
+                $options
+            );
+            $jwt_aud_uri = $this->_get_jwt_aud_uri($method);
+            if (is_callable($this->update_metadata)) {
+                $metadata = call_user_func(
+                    $this->update_metadata,
+                    $metadata,
+                    $jwt_aud_uri
+                );
+            }
+            $metadata = $this->_validate_and_normalize_metadata(
+                $metadata
+            );
+            $call->start($metadata);
+
+            return $call;
+        };
+    }
+
+    /**
+     * Create a function which can be used to create UnaryCall
+     *
+     * @param Channel|InterceptorChannel   $channel
+     * @param callable $deserialize A function that deserializes the response
+     *
+     * @return \Closure
+     */
+    private function _UnaryUnaryCallFactory($channel, $deserialize)
+    {
+        if (is_a($channel, 'Grpc\InterceptorChannel')) {
+            return function ($method,
+                             $argument,
+                             array $metadata = [],
+                             array $options = []) use ($channel, $deserialize) {
+                return $channel->getInterceptor()->interceptUnaryUnary(
+                    $method,
+                    $argument,
+                    $metadata,
+                    $options,
+                    $this->_UnaryUnaryCallFactory($channel->getNext(), $deserialize)
+                );
+            };
+        }
+        return $this->_GrpcUnaryUnary($channel, $deserialize);
+    }
+
+    /**
+     * Create a function which can be used to create ServerStreamingCall
+     *
+     * @param Channel|InterceptorChannel   $channel
+     * @param callable $deserialize A function that deserializes the response
+     *
+     * @return \Closure
+     */
+    private function _UnaryStreamCallFactory($channel, $deserialize)
+    {
+        if (is_a($channel, 'Grpc\InterceptorChannel')) {
+            return function ($method,
+                             $argument,
+                             array $metadata = [],
+                             array $options = []) use ($channel, $deserialize) {
+                return $channel->getInterceptor()->interceptUnaryStream(
+                    $method,
+                    $argument,
+                    $metadata,
+                    $options,
+                    $this->_UnaryStreamCallFactory($channel->getNext(), $deserialize)
+                );
+            };
+        }
+        return $this->_GrpcUnaryStream($channel, $deserialize);
+    }
+
+    /**
+     * Create a function which can be used to create ClientStreamingCall
+     *
+     * @param Channel|InterceptorChannel   $channel
+     * @param callable $deserialize A function that deserializes the response
+     *
+     * @return \Closure
+     */
+    private function _StreamUnaryCallFactory($channel, $deserialize)
+    {
+        if (is_a($channel, 'Grpc\InterceptorChannel')) {
+            return function ($method,
+                             array $metadata = [],
+                             array $options = []) use ($channel, $deserialize) {
+                return $channel->getInterceptor()->interceptStreamUnary(
+                    $method,
+                    $metadata,
+                    $options,
+                    $this->_StreamUnaryCallFactory($channel->getNext(), $deserialize)
+                );
+            };
+        }
+        return $this->_GrpcStreamUnary($channel, $deserialize);
+    }
+
+    /**
+     * Create a function which can be used to create BidiStreamingCall
+     *
+     * @param Channel|InterceptorChannel   $channel
+     * @param callable $deserialize A function that deserializes the response
+     *
+     * @return \Closure
+     */
+    private function _StreamStreamCallFactory($channel, $deserialize)
+    {
+        if (is_a($channel, 'Grpc\InterceptorChannel')) {
+            return function ($method,
+                             array $metadata = [],
+                             array $options = []) use ($channel, $deserialize) {
+                return $channel->getInterceptor()->interceptStreamStream(
+                    $method,
+                    $metadata,
+                    $options,
+                    $this->_StreamStreamCallFactory($channel->getNext(), $deserialize)
+                );
+            };
+        }
+        return $this->_GrpcStreamStream($channel, $deserialize);
+    }
+
     /* This class is intended to be subclassed by generated code, so
      * all functions begin with "_" to avoid name collisions. */
-
     /**
      * Call a remote method that takes a single argument and has a
      * single output.
@@ -221,26 +474,15 @@
      *
      * @return UnaryCall The active call object
      */
-    protected function _simpleRequest($method,
-                                   $argument,
-                                   $deserialize,
-                                   array $metadata = [],
-                                   array $options = [])
-    {
-        $call = new UnaryCall($this->channel,
-                              $method,
-                              $deserialize,
-                              $options);
-        $jwt_aud_uri = $this->_get_jwt_aud_uri($method);
-        if (is_callable($this->update_metadata)) {
-            $metadata = call_user_func($this->update_metadata,
-                                        $metadata,
-                                        $jwt_aud_uri);
-        }
-        $metadata = $this->_validate_and_normalize_metadata(
-            $metadata);
-        $call->start($argument, $metadata, $options);
-
+    protected function _simpleRequest(
+        $method,
+        $argument,
+        $deserialize,
+        array $metadata = [],
+        array $options = []
+    ) {
+        $call_factory = $this->_UnaryUnaryCallFactory($this->channel, $deserialize);
+        $call = $call_factory($method, $argument, $metadata, $options);
         return $call;
     }
 
@@ -256,25 +498,14 @@
      *
      * @return ClientStreamingCall The active call object
      */
-    protected function _clientStreamRequest($method,
-                                         $deserialize,
-                                         array $metadata = [],
-                                         array $options = [])
-    {
-        $call = new ClientStreamingCall($this->channel,
-                                        $method,
-                                        $deserialize,
-                                        $options);
-        $jwt_aud_uri = $this->_get_jwt_aud_uri($method);
-        if (is_callable($this->update_metadata)) {
-            $metadata = call_user_func($this->update_metadata,
-                                        $metadata,
-                                        $jwt_aud_uri);
-        }
-        $metadata = $this->_validate_and_normalize_metadata(
-            $metadata);
-        $call->start($metadata);
-
+    protected function _clientStreamRequest(
+        $method,
+        $deserialize,
+        array $metadata = [],
+        array $options = []
+    ) {
+        $call_factory = $this->_StreamUnaryCallFactory($this->channel, $deserialize);
+        $call = $call_factory($method, $metadata, $options);
         return $call;
     }
 
@@ -291,26 +522,15 @@
      *
      * @return ServerStreamingCall The active call object
      */
-    protected function _serverStreamRequest($method,
-                                         $argument,
-                                         $deserialize,
-                                         array $metadata = [],
-                                         array $options = [])
-    {
-        $call = new ServerStreamingCall($this->channel,
-                                        $method,
-                                        $deserialize,
-                                        $options);
-        $jwt_aud_uri = $this->_get_jwt_aud_uri($method);
-        if (is_callable($this->update_metadata)) {
-            $metadata = call_user_func($this->update_metadata,
-                                        $metadata,
-                                        $jwt_aud_uri);
-        }
-        $metadata = $this->_validate_and_normalize_metadata(
-            $metadata);
-        $call->start($argument, $metadata, $options);
-
+    protected function _serverStreamRequest(
+        $method,
+        $argument,
+        $deserialize,
+        array $metadata = [],
+        array $options = []
+    ) {
+        $call_factory = $this->_UnaryStreamCallFactory($this->channel, $deserialize);
+        $call = $call_factory($method, $argument, $metadata, $options);
         return $call;
     }
 
@@ -325,25 +545,14 @@
      *
      * @return BidiStreamingCall The active call object
      */
-    protected function _bidiRequest($method,
-                                 $deserialize,
-                                 array $metadata = [],
-                                 array $options = [])
-    {
-        $call = new BidiStreamingCall($this->channel,
-                                      $method,
-                                      $deserialize,
-                                      $options);
-        $jwt_aud_uri = $this->_get_jwt_aud_uri($method);
-        if (is_callable($this->update_metadata)) {
-            $metadata = call_user_func($this->update_metadata,
-                                        $metadata,
-                                        $jwt_aud_uri);
-        }
-        $metadata = $this->_validate_and_normalize_metadata(
-            $metadata);
-        $call->start($metadata);
-
+    protected function _bidiRequest(
+        $method,
+        $deserialize,
+        array $metadata = [],
+        array $options = []
+    ) {
+        $call_factory = $this->_StreamStreamCallFactory($this->channel, $deserialize);
+        $call = $call_factory($method, $metadata, $options);
         return $call;
     }
 }
diff --git a/src/php/lib/Grpc/Interceptor.php b/src/php/lib/Grpc/Interceptor.php
new file mode 100644
index 0000000..9c1b561
--- /dev/null
+++ b/src/php/lib/Grpc/Interceptor.php
@@ -0,0 +1,86 @@
+<?php
+/*
+ *
+ * Copyright 2018 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.
+ *
+ */
+
+namespace Grpc;
+
+/**
+ * Represents an interceptor that intercept RPC invocations before call starts.
+ * This is an EXPERIMENTAL API.
+ */
+class Interceptor
+{
+    public function interceptUnaryUnary(
+        $method,
+        $argument,
+        array $metadata = [],
+        array $options = [],
+        $continuation
+    ) {
+        return $continuation($method, $argument, $metadata, $options);
+    }
+
+    public function interceptStreamUnary(
+        $method,
+        array $metadata = [],
+        array $options = [],
+        $continuation
+    ) {
+        return $continuation($method, $metadata, $options);
+    }
+
+    public function interceptUnaryStream(
+        $method,
+        $argument,
+        array $metadata = [],
+        array $options = [],
+        $continuation
+    ) {
+        return $continuation($method, $argument, $metadata, $options);
+    }
+
+    public function interceptStreamStream(
+        $method,
+        array $metadata = [],
+        array $options = [],
+        $continuation
+    ) {
+        return $continuation($method, $metadata, $options);
+    }
+
+    /**
+     * Intercept the methods with Channel
+     *
+     * @param Channel|InterceptorChannel $channel An already created Channel or InterceptorChannel object (optional)
+     * @param Interceptor|Interceptor[] $interceptors interceptors to be added
+     *
+     * @return InterceptorChannel
+     */
+    public static function intercept($channel, $interceptors)
+    {
+        if (is_array($interceptors)) {
+            for ($i = count($interceptors) - 1; $i >= 0; $i--) {
+                $channel = new InterceptorChannel($channel, $interceptors[$i]);
+            }
+        } else {
+            $channel =  new InterceptorChannel($channel, $interceptors);
+        }
+        return $channel;
+    }
+}
+
diff --git a/src/php/lib/Grpc/Internal/InterceptorChannel.php b/src/php/lib/Grpc/Internal/InterceptorChannel.php
new file mode 100644
index 0000000..9ac0574
--- /dev/null
+++ b/src/php/lib/Grpc/Internal/InterceptorChannel.php
@@ -0,0 +1,76 @@
+<?php
+/*
+ *
+ * Copyright 2018 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.
+ *
+ */
+
+namespace Grpc;
+
+/**
+ * This is a PRIVATE API and can change without notice.
+ */
+class InterceptorChannel
+{
+    private $next = null;
+    private $interceptor;
+
+    /**
+     * @param Channel|InterceptorChannel $channel An already created Channel
+     * or InterceptorChannel object (optional)
+     * @param Interceptor  $interceptor
+     */
+    public function __construct($channel, $interceptor)
+    {
+        if (!is_a($channel, 'Grpc\Channel') &&
+            !is_a($channel, 'Grpc\InterceptorChannel')) {
+            throw new \Exception('The channel argument is not a Channel object '.
+                'or an InterceptorChannel object created by '.
+                'Interceptor::intercept($channel, Interceptor|Interceptor[] $interceptors)');
+        }
+        $this->interceptor = $interceptor;
+        $this->next = $channel;
+    }
+
+    public function getNext()
+    {
+        return $this->next;
+    }
+
+    public function getInterceptor()
+    {
+        return $this->interceptor;
+    }
+
+    public function getTarget()
+    {
+        return $this->getNext()->getTarget();
+    }
+
+    public function watchConnectivityState($new_state, $deadline)
+    {
+        return $this->getNext()->watchConnectivityState($new_state, $deadline);
+    }
+
+    public function getConnectivityState($try_to_connect = false)
+    {
+        return $this->getNext()->getConnectivityState($try_to_connect);
+    }
+
+    public function close()
+    {
+        return $this->getNext()->close();
+    }
+}
diff --git a/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/BenchmarkService.php b/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/BenchmarkService.php
new file mode 100644
index 0000000..906f6a2
--- /dev/null
+++ b/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/BenchmarkService.php
@@ -0,0 +1,41 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/testing/benchmark_service.proto
+
+namespace GPBMetadata\Src\Proto\Grpc\Testing;
+
+class BenchmarkService
+{
+    public static $is_initialized = false;
+
+    public static function initOnce() {
+        $pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool();
+
+        if (static::$is_initialized == true) {
+          return;
+        }
+        \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce();
+        $pool->internalAddGeneratedFile(hex2bin(
+            "0aef030a2e7372632f70726f746f2f677270632f74657374696e672f6265" .
+            "6e63686d61726b5f736572766963652e70726f746f120c677270632e7465" .
+            "7374696e6732a6030a1042656e63686d61726b5365727669636512460a09" .
+            "556e61727943616c6c121b2e677270632e74657374696e672e53696d706c" .
+            "65526571756573741a1c2e677270632e74657374696e672e53696d706c65" .
+            "526573706f6e7365124e0a0d53747265616d696e6743616c6c121b2e6772" .
+            "70632e74657374696e672e53696d706c65526571756573741a1c2e677270" .
+            "632e74657374696e672e53696d706c65526573706f6e7365280130011252" .
+            "0a1353747265616d696e6746726f6d436c69656e74121b2e677270632e74" .
+            "657374696e672e53696d706c65526571756573741a1c2e677270632e7465" .
+            "7374696e672e53696d706c65526573706f6e7365280112520a1353747265" .
+            "616d696e6746726f6d536572766572121b2e677270632e74657374696e67" .
+            "2e53696d706c65526571756573741a1c2e677270632e74657374696e672e" .
+            "53696d706c65526573706f6e7365300112520a1153747265616d696e6742" .
+            "6f746857617973121b2e677270632e74657374696e672e53696d706c6552" .
+            "6571756573741a1c2e677270632e74657374696e672e53696d706c655265" .
+            "73706f6e736528013001620670726f746f33"
+        ));
+
+        static::$is_initialized = true;
+    }
+}
+
diff --git a/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/CompilerTest.php b/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/CompilerTest.php
new file mode 100644
index 0000000..2c4fe92
--- /dev/null
+++ b/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/CompilerTest.php
@@ -0,0 +1,37 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/testing/compiler_test.proto
+
+namespace GPBMetadata\Src\Proto\Grpc\Testing;
+
+class CompilerTest
+{
+    public static $is_initialized = false;
+
+    public static function initOnce() {
+        $pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool();
+
+        if (static::$is_initialized == true) {
+          return;
+        }
+        $pool->internalAddGeneratedFile(hex2bin(
+            "0aa1030a2a7372632f70726f746f2f677270632f74657374696e672f636f" .
+            "6d70696c65725f746573742e70726f746f120c677270632e74657374696e" .
+            "6722090a0752657175657374220a0a08526573706f6e736532fe010a0853" .
+            "6572766963654112390a084d6574686f64413112152e677270632e746573" .
+            "74696e672e526571756573741a162e677270632e74657374696e672e5265" .
+            "73706f6e7365123b0a084d6574686f64413212152e677270632e74657374" .
+            "696e672e526571756573741a162e677270632e74657374696e672e526573" .
+            "706f6e73652801123b0a084d6574686f64413312152e677270632e746573" .
+            "74696e672e526571756573741a162e677270632e74657374696e672e5265" .
+            "73706f6e73653001123d0a084d6574686f64413412152e677270632e7465" .
+            "7374696e672e526571756573741a162e677270632e74657374696e672e52" .
+            "6573706f6e73652801300132450a08536572766963654212390a084d6574" .
+            "686f64423112152e677270632e74657374696e672e526571756573741a16" .
+            "2e677270632e74657374696e672e526573706f6e7365620670726f746f33"
+        ));
+
+        static::$is_initialized = true;
+    }
+}
+
diff --git a/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Control.php b/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Control.php
index 9b3a752..2319bcd 100644
--- a/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Control.php
+++ b/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Control.php
@@ -17,7 +17,7 @@
         \GPBMetadata\Src\Proto\Grpc\Testing\Payloads::initOnce();
         \GPBMetadata\Src\Proto\Grpc\Testing\Stats::initOnce();
         $pool->internalAddGeneratedFile(hex2bin(
-            "0aa21a0a247372632f70726f746f2f677270632f74657374696e672f636f" .
+            "0abc1a0a247372632f70726f746f2f677270632f74657374696e672f636f" .
             "6e74726f6c2e70726f746f120c677270632e74657374696e671a22737263" .
             "2f70726f746f2f677270632f74657374696e672f73746174732e70726f74" .
             "6f22250a0d506f6973736f6e506172616d7312140a0c6f6666657265645f" .
@@ -31,7 +31,7 @@
             "6f7665727269646518022001280912110a09637265645f74797065180320" .
             "012809224d0a0a4368616e6e656c417267120c0a046e616d651801200128" .
             "0912130a097374725f76616c7565180220012809480012130a09696e745f" .
-            "76616c7565180320012805480042070a0576616c756522d5040a0c436c69" .
+            "76616c7565180320012805480042070a0576616c756522ef040a0c436c69" .
             "656e74436f6e66696712160a0e7365727665725f74617267657473180120" .
             "032809122d0a0b636c69656e745f7479706518022001280e32182e677270" .
             "632e74657374696e672e436c69656e745479706512350a0f736563757269" .
@@ -51,85 +51,86 @@
             "745f617069180f20012809122e0a0c6368616e6e656c5f61726773181020" .
             "03280b32182e677270632e74657374696e672e4368616e6e656c41726712" .
             "160a0e746872656164735f7065725f6371181120012805121b0a136d6573" .
-            "73616765735f7065725f73747265616d18122001280522380a0c436c6965" .
-            "6e7453746174757312280a05737461747318012001280b32192e67727063" .
-            "2e74657374696e672e436c69656e74537461747322150a044d61726b120d" .
-            "0a05726573657418012001280822680a0a436c69656e7441726773122b0a" .
-            "05736574757018012001280b321a2e677270632e74657374696e672e436c" .
-            "69656e74436f6e666967480012220a046d61726b18022001280b32122e67" .
-            "7270632e74657374696e672e4d61726b480042090a076172677479706522" .
-            "fd020a0c536572766572436f6e666967122d0a0b7365727665725f747970" .
-            "6518012001280e32182e677270632e74657374696e672e53657276657254" .
-            "79706512350a0f73656375726974795f706172616d7318022001280b321c" .
-            "2e677270632e74657374696e672e5365637572697479506172616d73120c" .
-            "0a04706f7274180420012805121c0a146173796e635f7365727665725f74" .
-            "68726561647318072001280512120a0a636f72655f6c696d697418082001" .
-            "280512330a0e7061796c6f61645f636f6e66696718092001280b321b2e67" .
-            "7270632e74657374696e672e5061796c6f6164436f6e66696712110a0963" .
-            "6f72655f6c697374180a2003280512180a106f746865725f736572766572" .
-            "5f617069180b2001280912160a0e746872656164735f7065725f6371180c" .
-            "20012805121c0a137265736f757263655f71756f74615f73697a6518e907" .
-            "20012805122f0a0c6368616e6e656c5f6172677318ea072003280b32182e" .
-            "677270632e74657374696e672e4368616e6e656c41726722680a0a536572" .
-            "76657241726773122b0a05736574757018012001280b321a2e677270632e" .
-            "74657374696e672e536572766572436f6e666967480012220a046d61726b" .
-            "18022001280b32122e677270632e74657374696e672e4d61726b48004209" .
-            "0a076172677479706522550a0c53657276657253746174757312280a0573" .
-            "7461747318012001280b32192e677270632e74657374696e672e53657276" .
-            "65725374617473120c0a04706f7274180220012805120d0a05636f726573" .
-            "180320012805220d0a0b436f726552657175657374221d0a0c436f726552" .
-            "6573706f6e7365120d0a05636f72657318012001280522060a04566f6964" .
-            "22fd010a085363656e6172696f120c0a046e616d6518012001280912310a" .
-            "0d636c69656e745f636f6e66696718022001280b321a2e677270632e7465" .
-            "7374696e672e436c69656e74436f6e66696712130a0b6e756d5f636c6965" .
-            "6e747318032001280512310a0d7365727665725f636f6e66696718042001" .
-            "280b321a2e677270632e74657374696e672e536572766572436f6e666967" .
-            "12130a0b6e756d5f7365727665727318052001280512160a0e7761726d75" .
-            "705f7365636f6e647318062001280512190a1162656e63686d61726b5f73" .
-            "65636f6e647318072001280512200a18737061776e5f6c6f63616c5f776f" .
-            "726b65725f636f756e7418082001280522360a095363656e6172696f7312" .
-            "290a097363656e6172696f7318012003280b32162e677270632e74657374" .
-            "696e672e5363656e6172696f2284040a155363656e6172696f526573756c" .
-            "7453756d6d617279120b0a03717073180120012801121b0a137170735f70" .
-            "65725f7365727665725f636f7265180220012801121a0a12736572766572" .
-            "5f73797374656d5f74696d6518032001280112180a107365727665725f75" .
-            "7365725f74696d65180420012801121a0a12636c69656e745f7379737465" .
-            "6d5f74696d6518052001280112180a10636c69656e745f757365725f7469" .
-            "6d6518062001280112120a0a6c6174656e63795f35301807200128011212" .
-            "0a0a6c6174656e63795f393018082001280112120a0a6c6174656e63795f" .
-            "393518092001280112120a0a6c6174656e63795f3939180a200128011213" .
-            "0a0b6c6174656e63795f393939180b2001280112180a107365727665725f" .
-            "6370755f7573616765180c2001280112260a1e7375636365737366756c5f" .
-            "72657175657374735f7065725f7365636f6e64180d2001280112220a1a66" .
-            "61696c65645f72657175657374735f7065725f7365636f6e64180e200128" .
-            "0112200a18636c69656e745f706f6c6c735f7065725f7265717565737418" .
-            "0f2001280112200a187365727665725f706f6c6c735f7065725f72657175" .
-            "65737418102001280112220a1a7365727665725f717565726965735f7065" .
-            "725f6370755f73656318112001280112220a1a636c69656e745f71756572" .
-            "6965735f7065725f6370755f7365631812200128012283030a0e5363656e" .
-            "6172696f526573756c7412280a087363656e6172696f18012001280b3216" .
-            "2e677270632e74657374696e672e5363656e6172696f122e0a096c617465" .
-            "6e6369657318022001280b321b2e677270632e74657374696e672e486973" .
-            "746f6772616d44617461122f0a0c636c69656e745f737461747318032003" .
-            "280b32192e677270632e74657374696e672e436c69656e74537461747312" .
-            "2f0a0c7365727665725f737461747318042003280b32192e677270632e74" .
-            "657374696e672e536572766572537461747312140a0c7365727665725f63" .
-            "6f72657318052003280512340a0773756d6d61727918062001280b32232e" .
-            "677270632e74657374696e672e5363656e6172696f526573756c7453756d" .
-            "6d61727912160a0e636c69656e745f737563636573731807200328081216" .
-            "0a0e7365727665725f7375636365737318082003280812390a0f72657175" .
-            "6573745f726573756c747318092003280b32202e677270632e7465737469" .
-            "6e672e52657175657374526573756c74436f756e742a410a0a436c69656e" .
-            "7454797065120f0a0b53594e435f434c49454e54100012100a0c4153594e" .
-            "435f434c49454e54100112100a0c4f544845525f434c49454e5410022a5b" .
-            "0a0a53657276657254797065120f0a0b53594e435f534552564552100012" .
-            "100a0c4153594e435f534552564552100112180a144153594e435f47454e" .
-            "455249435f534552564552100212100a0c4f544845525f53455256455210" .
-            "032a720a075270635479706512090a05554e4152591000120d0a09535452" .
-            "45414d494e47100112190a1553545245414d494e475f46524f4d5f434c49" .
-            "454e54100212190a1553545245414d494e475f46524f4d5f534552564552" .
-            "100312170a1353545245414d494e475f424f54485f574159531004620670" .
-            "726f746f33"
+            "73616765735f7065725f73747265616d18122001280512180a107573655f" .
+            "636f616c657363655f61706918132001280822380a0c436c69656e745374" .
+            "6174757312280a05737461747318012001280b32192e677270632e746573" .
+            "74696e672e436c69656e74537461747322150a044d61726b120d0a057265" .
+            "73657418012001280822680a0a436c69656e7441726773122b0a05736574" .
+            "757018012001280b321a2e677270632e74657374696e672e436c69656e74" .
+            "436f6e666967480012220a046d61726b18022001280b32122e677270632e" .
+            "74657374696e672e4d61726b480042090a076172677479706522fd020a0c" .
+            "536572766572436f6e666967122d0a0b7365727665725f74797065180120" .
+            "01280e32182e677270632e74657374696e672e5365727665725479706512" .
+            "350a0f73656375726974795f706172616d7318022001280b321c2e677270" .
+            "632e74657374696e672e5365637572697479506172616d73120c0a04706f" .
+            "7274180420012805121c0a146173796e635f7365727665725f7468726561" .
+            "647318072001280512120a0a636f72655f6c696d69741808200128051233" .
+            "0a0e7061796c6f61645f636f6e66696718092001280b321b2e677270632e" .
+            "74657374696e672e5061796c6f6164436f6e66696712110a09636f72655f" .
+            "6c697374180a2003280512180a106f746865725f7365727665725f617069" .
+            "180b2001280912160a0e746872656164735f7065725f6371180c20012805" .
+            "121c0a137265736f757263655f71756f74615f73697a6518e90720012805" .
+            "122f0a0c6368616e6e656c5f6172677318ea072003280b32182e67727063" .
+            "2e74657374696e672e4368616e6e656c41726722680a0a53657276657241" .
+            "726773122b0a05736574757018012001280b321a2e677270632e74657374" .
+            "696e672e536572766572436f6e666967480012220a046d61726b18022001" .
+            "280b32122e677270632e74657374696e672e4d61726b480042090a076172" .
+            "677479706522550a0c53657276657253746174757312280a057374617473" .
+            "18012001280b32192e677270632e74657374696e672e5365727665725374" .
+            "617473120c0a04706f7274180220012805120d0a05636f72657318032001" .
+            "2805220d0a0b436f726552657175657374221d0a0c436f7265526573706f" .
+            "6e7365120d0a05636f72657318012001280522060a04566f696422fd010a" .
+            "085363656e6172696f120c0a046e616d6518012001280912310a0d636c69" .
+            "656e745f636f6e66696718022001280b321a2e677270632e74657374696e" .
+            "672e436c69656e74436f6e66696712130a0b6e756d5f636c69656e747318" .
+            "032001280512310a0d7365727665725f636f6e66696718042001280b321a" .
+            "2e677270632e74657374696e672e536572766572436f6e66696712130a0b" .
+            "6e756d5f7365727665727318052001280512160a0e7761726d75705f7365" .
+            "636f6e647318062001280512190a1162656e63686d61726b5f7365636f6e" .
+            "647318072001280512200a18737061776e5f6c6f63616c5f776f726b6572" .
+            "5f636f756e7418082001280522360a095363656e6172696f7312290a0973" .
+            "63656e6172696f7318012003280b32162e677270632e74657374696e672e" .
+            "5363656e6172696f2284040a155363656e6172696f526573756c7453756d" .
+            "6d617279120b0a03717073180120012801121b0a137170735f7065725f73" .
+            "65727665725f636f7265180220012801121a0a127365727665725f737973" .
+            "74656d5f74696d6518032001280112180a107365727665725f757365725f" .
+            "74696d65180420012801121a0a12636c69656e745f73797374656d5f7469" .
+            "6d6518052001280112180a10636c69656e745f757365725f74696d651806" .
+            "2001280112120a0a6c6174656e63795f353018072001280112120a0a6c61" .
+            "74656e63795f393018082001280112120a0a6c6174656e63795f39351809" .
+            "2001280112120a0a6c6174656e63795f3939180a2001280112130a0b6c61" .
+            "74656e63795f393939180b2001280112180a107365727665725f6370755f" .
+            "7573616765180c2001280112260a1e7375636365737366756c5f72657175" .
+            "657374735f7065725f7365636f6e64180d2001280112220a1a6661696c65" .
+            "645f72657175657374735f7065725f7365636f6e64180e2001280112200a" .
+            "18636c69656e745f706f6c6c735f7065725f72657175657374180f200128" .
+            "0112200a187365727665725f706f6c6c735f7065725f7265717565737418" .
+            "102001280112220a1a7365727665725f717565726965735f7065725f6370" .
+            "755f73656318112001280112220a1a636c69656e745f717565726965735f" .
+            "7065725f6370755f7365631812200128012283030a0e5363656e6172696f" .
+            "526573756c7412280a087363656e6172696f18012001280b32162e677270" .
+            "632e74657374696e672e5363656e6172696f122e0a096c6174656e636965" .
+            "7318022001280b321b2e677270632e74657374696e672e486973746f6772" .
+            "616d44617461122f0a0c636c69656e745f737461747318032003280b3219" .
+            "2e677270632e74657374696e672e436c69656e745374617473122f0a0c73" .
+            "65727665725f737461747318042003280b32192e677270632e7465737469" .
+            "6e672e536572766572537461747312140a0c7365727665725f636f726573" .
+            "18052003280512340a0773756d6d61727918062001280b32232e67727063" .
+            "2e74657374696e672e5363656e6172696f526573756c7453756d6d617279" .
+            "12160a0e636c69656e745f7375636365737318072003280812160a0e7365" .
+            "727665725f7375636365737318082003280812390a0f726571756573745f" .
+            "726573756c747318092003280b32202e677270632e74657374696e672e52" .
+            "657175657374526573756c74436f756e742a410a0a436c69656e74547970" .
+            "65120f0a0b53594e435f434c49454e54100012100a0c4153594e435f434c" .
+            "49454e54100112100a0c4f544845525f434c49454e5410022a5b0a0a5365" .
+            "7276657254797065120f0a0b53594e435f534552564552100012100a0c41" .
+            "53594e435f534552564552100112180a144153594e435f47454e45524943" .
+            "5f534552564552100212100a0c4f544845525f53455256455210032a720a" .
+            "075270635479706512090a05554e4152591000120d0a0953545245414d49" .
+            "4e47100112190a1553545245414d494e475f46524f4d5f434c49454e5410" .
+            "0212190a1553545245414d494e475f46524f4d5f53455256455210031217" .
+            "0a1353545245414d494e475f424f54485f574159531004620670726f746f" .
+            "33"
         ));
 
         static::$is_initialized = true;
diff --git a/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Echo.php b/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Echo.php
new file mode 100644
index 0000000..77c5230
--- /dev/null
+++ b/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Echo.php
@@ -0,0 +1,43 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/testing/echo.proto
+
+namespace GPBMetadata\Src\Proto\Grpc\Testing;
+
+class Echo
+{
+    public static $is_initialized = false;
+
+    public static function initOnce() {
+        $pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool();
+
+        if (static::$is_initialized == true) {
+          return;
+        }
+        \GPBMetadata\Src\Proto\Grpc\Testing\EchoMessages::initOnce();
+        $pool->internalAddGeneratedFile(hex2bin(
+            "0aa6040a217372632f70726f746f2f677270632f74657374696e672f6563" .
+            "686f2e70726f746f120c677270632e74657374696e6732f6020a0f456368" .
+            "6f5465737453657276696365123d0a044563686f12192e677270632e7465" .
+            "7374696e672e4563686f526571756573741a1a2e677270632e7465737469" .
+            "6e672e4563686f526573706f6e736512480a0d5265717565737453747265" .
+            "616d12192e677270632e74657374696e672e4563686f526571756573741a" .
+            "1a2e677270632e74657374696e672e4563686f526573706f6e7365280112" .
+            "490a0e526573706f6e736553747265616d12192e677270632e7465737469" .
+            "6e672e4563686f526571756573741a1a2e677270632e74657374696e672e" .
+            "4563686f526573706f6e7365300112470a0a4269646953747265616d1219" .
+            "2e677270632e74657374696e672e4563686f526571756573741a1a2e6772" .
+            "70632e74657374696e672e4563686f526573706f6e73652801300112460a" .
+            "0d556e696d706c656d656e74656412192e677270632e74657374696e672e" .
+            "4563686f526571756573741a1a2e677270632e74657374696e672e456368" .
+            "6f526573706f6e736532620a18556e696d706c656d656e7465644563686f" .
+            "5365727669636512460a0d556e696d706c656d656e74656412192e677270" .
+            "632e74657374696e672e4563686f526571756573741a1a2e677270632e74" .
+            "657374696e672e4563686f526573706f6e7365320e0a0c4e6f5270635365" .
+            "7276696365620670726f746f33"
+        ));
+
+        static::$is_initialized = true;
+    }
+}
+
diff --git a/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/EchoMessages.php b/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/EchoMessages.php
new file mode 100644
index 0000000..4bac8a2
--- /dev/null
+++ b/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/EchoMessages.php
@@ -0,0 +1,54 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/testing/echo_messages.proto
+
+namespace GPBMetadata\Src\Proto\Grpc\Testing;
+
+class EchoMessages
+{
+    public static $is_initialized = false;
+
+    public static function initOnce() {
+        $pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool();
+
+        if (static::$is_initialized == true) {
+          return;
+        }
+        $pool->internalAddGeneratedFile(hex2bin(
+            "0a8f070a2a7372632f70726f746f2f677270632f74657374696e672f6563" .
+            "686f5f6d657373616765732e70726f746f120c677270632e74657374696e" .
+            "6722320a094465627567496e666f12150a0d737461636b5f656e74726965" .
+            "73180120032809120e0a0664657461696c18022001280922500a0b457272" .
+            "6f72537461747573120c0a04636f646518012001280512150a0d6572726f" .
+            "725f6d657373616765180220012809121c0a1462696e6172795f6572726f" .
+            "725f64657461696c7318032001280922e2030a0d52657175657374506172" .
+            "616d7312150a0d6563686f5f646561646c696e65180120012808121e0a16" .
+            "636c69656e745f63616e63656c5f61667465725f7573180220012805121e" .
+            "0a167365727665725f63616e63656c5f61667465725f7573180320012805" .
+            "12150a0d6563686f5f6d65746164617461180420012808121a0a12636865" .
+            "636b5f617574685f636f6e74657874180520012808121f0a17726573706f" .
+            "6e73655f6d6573736167655f6c656e67746818062001280512110a096563" .
+            "686f5f7065657218072001280812200a1865787065637465645f636c6965" .
+            "6e745f6964656e74697479180820012809121c0a14736b69705f63616e63" .
+            "656c6c65645f636865636b18092001280812280a2065787065637465645f" .
+            "7472616e73706f72745f73656375726974795f74797065180a2001280912" .
+            "2b0a0a64656275675f696e666f180b2001280b32172e677270632e746573" .
+            "74696e672e4465627567496e666f12120a0a7365727665725f646965180c" .
+            "20012808121c0a1462696e6172795f6572726f725f64657461696c73180d" .
+            "2001280912310a0e65787065637465645f6572726f72180e2001280b3219" .
+            "2e677270632e74657374696e672e4572726f7253746174757312170a0f73" .
+            "65727665725f736c6565705f7573180f20012805224a0a0b4563686f5265" .
+            "7175657374120f0a076d657373616765180120012809122a0a0570617261" .
+            "6d18022001280b321b2e677270632e74657374696e672e52657175657374" .
+            "506172616d7322460a0e526573706f6e7365506172616d7312180a107265" .
+            "71756573745f646561646c696e65180120012803120c0a04686f73741802" .
+            "20012809120c0a0470656572180320012809224c0a0c4563686f52657370" .
+            "6f6e7365120f0a076d657373616765180120012809122b0a05706172616d" .
+            "18022001280b321c2e677270632e74657374696e672e526573706f6e7365" .
+            "506172616d73620670726f746f33"
+        ));
+
+        static::$is_initialized = true;
+    }
+}
+
diff --git a/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/GPBEmpty.php b/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/GPBEmpty.php
new file mode 100644
index 0000000..7198f7d
--- /dev/null
+++ b/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/GPBEmpty.php
@@ -0,0 +1,26 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/testing/empty.proto
+
+namespace GPBMetadata\Src\Proto\Grpc\Testing;
+
+class GPBEmpty
+{
+    public static $is_initialized = false;
+
+    public static function initOnce() {
+        $pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool();
+
+        if (static::$is_initialized == true) {
+          return;
+        }
+        $pool->internalAddGeneratedFile(hex2bin(
+            "0a430a227372632f70726f746f2f677270632f74657374696e672f656d70" .
+            "74792e70726f746f120c677270632e74657374696e6722070a05456d7074" .
+            "79620670726f746f33"
+        ));
+
+        static::$is_initialized = true;
+    }
+}
+
diff --git a/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Metrics.php b/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Metrics.php
new file mode 100644
index 0000000..7ac739f
--- /dev/null
+++ b/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Metrics.php
@@ -0,0 +1,36 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/testing/metrics.proto
+
+namespace GPBMetadata\Src\Proto\Grpc\Testing;
+
+class Metrics
+{
+    public static $is_initialized = false;
+
+    public static function initOnce() {
+        $pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool();
+
+        if (static::$is_initialized == true) {
+          return;
+        }
+        $pool->internalAddGeneratedFile(hex2bin(
+            "0afb020a247372632f70726f746f2f677270632f74657374696e672f6d65" .
+            "74726963732e70726f746f120c677270632e74657374696e67226c0a0d47" .
+            "61756765526573706f6e7365120c0a046e616d6518012001280912140a0a" .
+            "6c6f6e675f76616c7565180220012803480012160a0c646f75626c655f76" .
+            "616c7565180320012801480012160a0c737472696e675f76616c75651804" .
+            "20012809480042070a0576616c7565221c0a0c4761756765526571756573" .
+            "74120c0a046e616d65180120012809220e0a0c456d7074794d6573736167" .
+            "6532a0010a0e4d6574726963735365727669636512490a0c476574416c6c" .
+            "476175676573121a2e677270632e74657374696e672e456d7074794d6573" .
+            "736167651a1b2e677270632e74657374696e672e4761756765526573706f" .
+            "6e7365300112430a084765744761756765121a2e677270632e7465737469" .
+            "6e672e4761756765526571756573741a1b2e677270632e74657374696e67" .
+            "2e4761756765526573706f6e7365620670726f746f33"
+        ));
+
+        static::$is_initialized = true;
+    }
+}
+
diff --git a/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/ReportQpsScenarioService.php b/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/ReportQpsScenarioService.php
new file mode 100644
index 0000000..35a1fb4
--- /dev/null
+++ b/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/ReportQpsScenarioService.php
@@ -0,0 +1,30 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/testing/report_qps_scenario_service.proto
+
+namespace GPBMetadata\Src\Proto\Grpc\Testing;
+
+class ReportQpsScenarioService
+{
+    public static $is_initialized = false;
+
+    public static function initOnce() {
+        $pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool();
+
+        if (static::$is_initialized == true) {
+          return;
+        }
+        \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce();
+        $pool->internalAddGeneratedFile(hex2bin(
+            "0ab0010a387372632f70726f746f2f677270632f74657374696e672f7265" .
+            "706f72745f7170735f7363656e6172696f5f736572766963652e70726f74" .
+            "6f120c677270632e74657374696e67325e0a185265706f72745170735363" .
+            "656e6172696f5365727669636512420a0e5265706f72745363656e617269" .
+            "6f121c2e677270632e74657374696e672e5363656e6172696f526573756c" .
+            "741a122e677270632e74657374696e672e566f6964620670726f746f33"
+        ));
+
+        static::$is_initialized = true;
+    }
+}
+
diff --git a/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Test.php b/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Test.php
new file mode 100644
index 0000000..54628cf
--- /dev/null
+++ b/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/Test.php
@@ -0,0 +1,60 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/testing/test.proto
+
+namespace GPBMetadata\Src\Proto\Grpc\Testing;
+
+class Test
+{
+    public static $is_initialized = false;
+
+    public static function initOnce() {
+        $pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool();
+
+        if (static::$is_initialized == true) {
+          return;
+        }
+        \GPBMetadata\Src\Proto\Grpc\Testing\GPBEmpty::initOnce();
+        \GPBMetadata\Src\Proto\Grpc\Testing\Messages::initOnce();
+        $pool->internalAddGeneratedFile(hex2bin(
+            "0a91080a217372632f70726f746f2f677270632f74657374696e672f7465" .
+            "73742e70726f746f120c677270632e74657374696e671a257372632f7072" .
+            "6f746f2f677270632f74657374696e672f6d657373616765732e70726f74" .
+            "6f32cb050a0b546573745365727669636512350a09456d70747943616c6c" .
+            "12132e677270632e74657374696e672e456d7074791a132e677270632e74" .
+            "657374696e672e456d70747912460a09556e61727943616c6c121b2e6772" .
+            "70632e74657374696e672e53696d706c65526571756573741a1c2e677270" .
+            "632e74657374696e672e53696d706c65526573706f6e7365124f0a124361" .
+            "63686561626c65556e61727943616c6c121b2e677270632e74657374696e" .
+            "672e53696d706c65526571756573741a1c2e677270632e74657374696e67" .
+            "2e53696d706c65526573706f6e7365126c0a1353747265616d696e674f75" .
+            "7470757443616c6c12282e677270632e74657374696e672e53747265616d" .
+            "696e674f757470757443616c6c526571756573741a292e677270632e7465" .
+            "7374696e672e53747265616d696e674f757470757443616c6c526573706f" .
+            "6e7365300112690a1253747265616d696e67496e70757443616c6c12272e" .
+            "677270632e74657374696e672e53747265616d696e67496e70757443616c" .
+            "6c526571756573741a282e677270632e74657374696e672e53747265616d" .
+            "696e67496e70757443616c6c526573706f6e7365280112690a0e46756c6c" .
+            "4475706c657843616c6c12282e677270632e74657374696e672e53747265" .
+            "616d696e674f757470757443616c6c526571756573741a292e677270632e" .
+            "74657374696e672e53747265616d696e674f757470757443616c6c526573" .
+            "706f6e73652801300112690a0e48616c664475706c657843616c6c12282e" .
+            "677270632e74657374696e672e53747265616d696e674f75747075744361" .
+            "6c6c526571756573741a292e677270632e74657374696e672e5374726561" .
+            "6d696e674f757470757443616c6c526573706f6e736528013001123d0a11" .
+            "556e696d706c656d656e74656443616c6c12132e677270632e7465737469" .
+            "6e672e456d7074791a132e677270632e74657374696e672e456d70747932" .
+            "550a14556e696d706c656d656e74656453657276696365123d0a11556e69" .
+            "6d706c656d656e74656443616c6c12132e677270632e74657374696e672e" .
+            "456d7074791a132e677270632e74657374696e672e456d7074793289010a" .
+            "105265636f6e6e65637453657276696365123b0a055374617274121d2e67" .
+            "7270632e74657374696e672e5265636f6e6e656374506172616d731a132e" .
+            "677270632e74657374696e672e456d70747912380a0453746f7012132e67" .
+            "7270632e74657374696e672e456d7074791a1b2e677270632e7465737469" .
+            "6e672e5265636f6e6e656374496e666f620670726f746f33"
+        ));
+
+        static::$is_initialized = true;
+    }
+}
+
diff --git a/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/WorkerService.php b/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/WorkerService.php
new file mode 100644
index 0000000..a8a863d
--- /dev/null
+++ b/src/php/tests/qps/generated_code/GPBMetadata/Src/Proto/Grpc/Testing/WorkerService.php
@@ -0,0 +1,36 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/testing/worker_service.proto
+
+namespace GPBMetadata\Src\Proto\Grpc\Testing;
+
+class WorkerService
+{
+    public static $is_initialized = false;
+
+    public static function initOnce() {
+        $pool = \Google\Protobuf\Internal\DescriptorPool::getGeneratedPool();
+
+        if (static::$is_initialized == true) {
+          return;
+        }
+        \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce();
+        $pool->internalAddGeneratedFile(hex2bin(
+            "0add020a2b7372632f70726f746f2f677270632f74657374696e672f776f" .
+            "726b65725f736572766963652e70726f746f120c677270632e7465737469" .
+            "6e673297020a0d576f726b65725365727669636512450a0952756e536572" .
+            "76657212182e677270632e74657374696e672e536572766572417267731a" .
+            "1a2e677270632e74657374696e672e536572766572537461747573280130" .
+            "0112450a0952756e436c69656e7412182e677270632e74657374696e672e" .
+            "436c69656e74417267731a1a2e677270632e74657374696e672e436c6965" .
+            "6e745374617475732801300112420a09436f7265436f756e7412192e6772" .
+            "70632e74657374696e672e436f7265526571756573741a1a2e677270632e" .
+            "74657374696e672e436f7265526573706f6e736512340a0a51756974576f" .
+            "726b657212122e677270632e74657374696e672e566f69641a122e677270" .
+            "632e74657374696e672e566f6964620670726f746f33"
+        ));
+
+        static::$is_initialized = true;
+    }
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/ClientConfig.php b/src/php/tests/qps/generated_code/Grpc/Testing/ClientConfig.php
index f7bc215..0dd3072 100644
--- a/src/php/tests/qps/generated_code/Grpc/Testing/ClientConfig.php
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/ClientConfig.php
@@ -97,6 +97,12 @@
      * Generated from protobuf field <code>int32 messages_per_stream = 18;</code>
      */
     private $messages_per_stream = 0;
+    /**
+     * Use coalescing API when possible.
+     *
+     * Generated from protobuf field <code>bool use_coalesce_api = 19;</code>
+     */
+    private $use_coalesce_api = false;
 
     public function __construct() {
         \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce();
@@ -495,5 +501,31 @@
         return $this;
     }
 
+    /**
+     * Use coalescing API when possible.
+     *
+     * Generated from protobuf field <code>bool use_coalesce_api = 19;</code>
+     * @return bool
+     */
+    public function getUseCoalesceApi()
+    {
+        return $this->use_coalesce_api;
+    }
+
+    /**
+     * Use coalescing API when possible.
+     *
+     * Generated from protobuf field <code>bool use_coalesce_api = 19;</code>
+     * @param bool $var
+     * @return $this
+     */
+    public function setUseCoalesceApi($var)
+    {
+        GPBUtil::checkBool($var);
+        $this->use_coalesce_api = $var;
+
+        return $this;
+    }
+
 }
 
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/DebugInfo.php b/src/php/tests/qps/generated_code/Grpc/Testing/DebugInfo.php
new file mode 100644
index 0000000..805b629
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/DebugInfo.php
@@ -0,0 +1,77 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/testing/echo_messages.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Message to be echoed back serialized in trailer.
+ *
+ * Generated from protobuf message <code>grpc.testing.DebugInfo</code>
+ */
+class DebugInfo extends \Google\Protobuf\Internal\Message
+{
+    /**
+     * Generated from protobuf field <code>repeated string stack_entries = 1;</code>
+     */
+    private $stack_entries;
+    /**
+     * Generated from protobuf field <code>string detail = 2;</code>
+     */
+    private $detail = '';
+
+    public function __construct() {
+        \GPBMetadata\Src\Proto\Grpc\Testing\EchoMessages::initOnce();
+        parent::__construct();
+    }
+
+    /**
+     * Generated from protobuf field <code>repeated string stack_entries = 1;</code>
+     * @return \Google\Protobuf\Internal\RepeatedField
+     */
+    public function getStackEntries()
+    {
+        return $this->stack_entries;
+    }
+
+    /**
+     * Generated from protobuf field <code>repeated string stack_entries = 1;</code>
+     * @param string[]|\Google\Protobuf\Internal\RepeatedField $var
+     * @return $this
+     */
+    public function setStackEntries($var)
+    {
+        $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::STRING);
+        $this->stack_entries = $arr;
+
+        return $this;
+    }
+
+    /**
+     * Generated from protobuf field <code>string detail = 2;</code>
+     * @return string
+     */
+    public function getDetail()
+    {
+        return $this->detail;
+    }
+
+    /**
+     * Generated from protobuf field <code>string detail = 2;</code>
+     * @param string $var
+     * @return $this
+     */
+    public function setDetail($var)
+    {
+        GPBUtil::checkString($var, True);
+        $this->detail = $var;
+
+        return $this;
+    }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/EchoRequest.php b/src/php/tests/qps/generated_code/Grpc/Testing/EchoRequest.php
new file mode 100644
index 0000000..9aadfc5
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/EchoRequest.php
@@ -0,0 +1,75 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/testing/echo_messages.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Generated from protobuf message <code>grpc.testing.EchoRequest</code>
+ */
+class EchoRequest extends \Google\Protobuf\Internal\Message
+{
+    /**
+     * Generated from protobuf field <code>string message = 1;</code>
+     */
+    private $message = '';
+    /**
+     * Generated from protobuf field <code>.grpc.testing.RequestParams param = 2;</code>
+     */
+    private $param = null;
+
+    public function __construct() {
+        \GPBMetadata\Src\Proto\Grpc\Testing\EchoMessages::initOnce();
+        parent::__construct();
+    }
+
+    /**
+     * Generated from protobuf field <code>string message = 1;</code>
+     * @return string
+     */
+    public function getMessage()
+    {
+        return $this->message;
+    }
+
+    /**
+     * Generated from protobuf field <code>string message = 1;</code>
+     * @param string $var
+     * @return $this
+     */
+    public function setMessage($var)
+    {
+        GPBUtil::checkString($var, True);
+        $this->message = $var;
+
+        return $this;
+    }
+
+    /**
+     * Generated from protobuf field <code>.grpc.testing.RequestParams param = 2;</code>
+     * @return \Grpc\Testing\RequestParams
+     */
+    public function getParam()
+    {
+        return $this->param;
+    }
+
+    /**
+     * Generated from protobuf field <code>.grpc.testing.RequestParams param = 2;</code>
+     * @param \Grpc\Testing\RequestParams $var
+     * @return $this
+     */
+    public function setParam($var)
+    {
+        GPBUtil::checkMessage($var, \Grpc\Testing\RequestParams::class);
+        $this->param = $var;
+
+        return $this;
+    }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/EchoResponse.php b/src/php/tests/qps/generated_code/Grpc/Testing/EchoResponse.php
new file mode 100644
index 0000000..c4a9db3
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/EchoResponse.php
@@ -0,0 +1,75 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/testing/echo_messages.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Generated from protobuf message <code>grpc.testing.EchoResponse</code>
+ */
+class EchoResponse extends \Google\Protobuf\Internal\Message
+{
+    /**
+     * Generated from protobuf field <code>string message = 1;</code>
+     */
+    private $message = '';
+    /**
+     * Generated from protobuf field <code>.grpc.testing.ResponseParams param = 2;</code>
+     */
+    private $param = null;
+
+    public function __construct() {
+        \GPBMetadata\Src\Proto\Grpc\Testing\EchoMessages::initOnce();
+        parent::__construct();
+    }
+
+    /**
+     * Generated from protobuf field <code>string message = 1;</code>
+     * @return string
+     */
+    public function getMessage()
+    {
+        return $this->message;
+    }
+
+    /**
+     * Generated from protobuf field <code>string message = 1;</code>
+     * @param string $var
+     * @return $this
+     */
+    public function setMessage($var)
+    {
+        GPBUtil::checkString($var, True);
+        $this->message = $var;
+
+        return $this;
+    }
+
+    /**
+     * Generated from protobuf field <code>.grpc.testing.ResponseParams param = 2;</code>
+     * @return \Grpc\Testing\ResponseParams
+     */
+    public function getParam()
+    {
+        return $this->param;
+    }
+
+    /**
+     * Generated from protobuf field <code>.grpc.testing.ResponseParams param = 2;</code>
+     * @param \Grpc\Testing\ResponseParams $var
+     * @return $this
+     */
+    public function setParam($var)
+    {
+        GPBUtil::checkMessage($var, \Grpc\Testing\ResponseParams::class);
+        $this->param = $var;
+
+        return $this;
+    }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/EchoTestServiceClient.php b/src/php/tests/qps/generated_code/Grpc/Testing/EchoTestServiceClient.php
new file mode 100644
index 0000000..b3dcf5b
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/EchoTestServiceClient.php
@@ -0,0 +1,93 @@
+<?php
+// GENERATED CODE -- DO NOT EDIT!
+
+// Original file comments:
+// Copyright 2015 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.
+//
+namespace Grpc\Testing;
+
+/**
+ */
+class EchoTestServiceClient extends \Grpc\BaseStub {
+
+    /**
+     * @param string $hostname hostname
+     * @param array $opts channel options
+     * @param \Grpc\Channel $channel (optional) re-use channel object
+     */
+    public function __construct($hostname, $opts, $channel = null) {
+        parent::__construct($hostname, $opts, $channel);
+    }
+
+    /**
+     * @param \Grpc\Testing\EchoRequest $argument input argument
+     * @param array $metadata metadata
+     * @param array $options call options
+     */
+    public function Echo(\Grpc\Testing\EchoRequest $argument,
+      $metadata = [], $options = []) {
+        return $this->_simpleRequest('/grpc.testing.EchoTestService/Echo',
+        $argument,
+        ['\Grpc\Testing\EchoResponse', 'decode'],
+        $metadata, $options);
+    }
+
+    /**
+     * @param array $metadata metadata
+     * @param array $options call options
+     */
+    public function RequestStream($metadata = [], $options = []) {
+        return $this->_clientStreamRequest('/grpc.testing.EchoTestService/RequestStream',
+        ['\Grpc\Testing\EchoResponse','decode'],
+        $metadata, $options);
+    }
+
+    /**
+     * @param \Grpc\Testing\EchoRequest $argument input argument
+     * @param array $metadata metadata
+     * @param array $options call options
+     */
+    public function ResponseStream(\Grpc\Testing\EchoRequest $argument,
+      $metadata = [], $options = []) {
+        return $this->_serverStreamRequest('/grpc.testing.EchoTestService/ResponseStream',
+        $argument,
+        ['\Grpc\Testing\EchoResponse', 'decode'],
+        $metadata, $options);
+    }
+
+    /**
+     * @param array $metadata metadata
+     * @param array $options call options
+     */
+    public function BidiStream($metadata = [], $options = []) {
+        return $this->_bidiRequest('/grpc.testing.EchoTestService/BidiStream',
+        ['\Grpc\Testing\EchoResponse','decode'],
+        $metadata, $options);
+    }
+
+    /**
+     * @param \Grpc\Testing\EchoRequest $argument input argument
+     * @param array $metadata metadata
+     * @param array $options call options
+     */
+    public function Unimplemented(\Grpc\Testing\EchoRequest $argument,
+      $metadata = [], $options = []) {
+        return $this->_simpleRequest('/grpc.testing.EchoTestService/Unimplemented',
+        $argument,
+        ['\Grpc\Testing\EchoResponse', 'decode'],
+        $metadata, $options);
+    }
+
+}
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/EmptyMessage.php b/src/php/tests/qps/generated_code/Grpc/Testing/EmptyMessage.php
new file mode 100644
index 0000000..3da163e
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/EmptyMessage.php
@@ -0,0 +1,23 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/testing/metrics.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Generated from protobuf message <code>grpc.testing.EmptyMessage</code>
+ */
+class EmptyMessage extends \Google\Protobuf\Internal\Message
+{
+
+    public function __construct() {
+        \GPBMetadata\Src\Proto\Grpc\Testing\Metrics::initOnce();
+        parent::__construct();
+    }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/ErrorStatus.php b/src/php/tests/qps/generated_code/Grpc/Testing/ErrorStatus.php
new file mode 100644
index 0000000..cc37875
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/ErrorStatus.php
@@ -0,0 +1,103 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/testing/echo_messages.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Error status client expects to see.
+ *
+ * Generated from protobuf message <code>grpc.testing.ErrorStatus</code>
+ */
+class ErrorStatus extends \Google\Protobuf\Internal\Message
+{
+    /**
+     * Generated from protobuf field <code>int32 code = 1;</code>
+     */
+    private $code = 0;
+    /**
+     * Generated from protobuf field <code>string error_message = 2;</code>
+     */
+    private $error_message = '';
+    /**
+     * Generated from protobuf field <code>string binary_error_details = 3;</code>
+     */
+    private $binary_error_details = '';
+
+    public function __construct() {
+        \GPBMetadata\Src\Proto\Grpc\Testing\EchoMessages::initOnce();
+        parent::__construct();
+    }
+
+    /**
+     * Generated from protobuf field <code>int32 code = 1;</code>
+     * @return int
+     */
+    public function getCode()
+    {
+        return $this->code;
+    }
+
+    /**
+     * Generated from protobuf field <code>int32 code = 1;</code>
+     * @param int $var
+     * @return $this
+     */
+    public function setCode($var)
+    {
+        GPBUtil::checkInt32($var);
+        $this->code = $var;
+
+        return $this;
+    }
+
+    /**
+     * Generated from protobuf field <code>string error_message = 2;</code>
+     * @return string
+     */
+    public function getErrorMessage()
+    {
+        return $this->error_message;
+    }
+
+    /**
+     * Generated from protobuf field <code>string error_message = 2;</code>
+     * @param string $var
+     * @return $this
+     */
+    public function setErrorMessage($var)
+    {
+        GPBUtil::checkString($var, True);
+        $this->error_message = $var;
+
+        return $this;
+    }
+
+    /**
+     * Generated from protobuf field <code>string binary_error_details = 3;</code>
+     * @return string
+     */
+    public function getBinaryErrorDetails()
+    {
+        return $this->binary_error_details;
+    }
+
+    /**
+     * Generated from protobuf field <code>string binary_error_details = 3;</code>
+     * @param string $var
+     * @return $this
+     */
+    public function setBinaryErrorDetails($var)
+    {
+        GPBUtil::checkString($var, True);
+        $this->binary_error_details = $var;
+
+        return $this;
+    }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/GaugeRequest.php b/src/php/tests/qps/generated_code/Grpc/Testing/GaugeRequest.php
new file mode 100644
index 0000000..3c28369
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/GaugeRequest.php
@@ -0,0 +1,51 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/testing/metrics.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Request message containing the gauge name
+ *
+ * Generated from protobuf message <code>grpc.testing.GaugeRequest</code>
+ */
+class GaugeRequest extends \Google\Protobuf\Internal\Message
+{
+    /**
+     * Generated from protobuf field <code>string name = 1;</code>
+     */
+    private $name = '';
+
+    public function __construct() {
+        \GPBMetadata\Src\Proto\Grpc\Testing\Metrics::initOnce();
+        parent::__construct();
+    }
+
+    /**
+     * Generated from protobuf field <code>string name = 1;</code>
+     * @return string
+     */
+    public function getName()
+    {
+        return $this->name;
+    }
+
+    /**
+     * Generated from protobuf field <code>string name = 1;</code>
+     * @param string $var
+     * @return $this
+     */
+    public function setName($var)
+    {
+        GPBUtil::checkString($var, True);
+        $this->name = $var;
+
+        return $this;
+    }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/GaugeResponse.php b/src/php/tests/qps/generated_code/Grpc/Testing/GaugeResponse.php
new file mode 100644
index 0000000..da658ba
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/GaugeResponse.php
@@ -0,0 +1,126 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/testing/metrics.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Reponse message containing the gauge name and value
+ *
+ * Generated from protobuf message <code>grpc.testing.GaugeResponse</code>
+ */
+class GaugeResponse extends \Google\Protobuf\Internal\Message
+{
+    /**
+     * Generated from protobuf field <code>string name = 1;</code>
+     */
+    private $name = '';
+    protected $value;
+
+    public function __construct() {
+        \GPBMetadata\Src\Proto\Grpc\Testing\Metrics::initOnce();
+        parent::__construct();
+    }
+
+    /**
+     * Generated from protobuf field <code>string name = 1;</code>
+     * @return string
+     */
+    public function getName()
+    {
+        return $this->name;
+    }
+
+    /**
+     * Generated from protobuf field <code>string name = 1;</code>
+     * @param string $var
+     * @return $this
+     */
+    public function setName($var)
+    {
+        GPBUtil::checkString($var, True);
+        $this->name = $var;
+
+        return $this;
+    }
+
+    /**
+     * Generated from protobuf field <code>int64 long_value = 2;</code>
+     * @return int|string
+     */
+    public function getLongValue()
+    {
+        return $this->readOneof(2);
+    }
+
+    /**
+     * Generated from protobuf field <code>int64 long_value = 2;</code>
+     * @param int|string $var
+     * @return $this
+     */
+    public function setLongValue($var)
+    {
+        GPBUtil::checkInt64($var);
+        $this->writeOneof(2, $var);
+
+        return $this;
+    }
+
+    /**
+     * Generated from protobuf field <code>double double_value = 3;</code>
+     * @return float
+     */
+    public function getDoubleValue()
+    {
+        return $this->readOneof(3);
+    }
+
+    /**
+     * Generated from protobuf field <code>double double_value = 3;</code>
+     * @param float $var
+     * @return $this
+     */
+    public function setDoubleValue($var)
+    {
+        GPBUtil::checkDouble($var);
+        $this->writeOneof(3, $var);
+
+        return $this;
+    }
+
+    /**
+     * Generated from protobuf field <code>string string_value = 4;</code>
+     * @return string
+     */
+    public function getStringValue()
+    {
+        return $this->readOneof(4);
+    }
+
+    /**
+     * Generated from protobuf field <code>string string_value = 4;</code>
+     * @param string $var
+     * @return $this
+     */
+    public function setStringValue($var)
+    {
+        GPBUtil::checkString($var, True);
+        $this->writeOneof(4, $var);
+
+        return $this;
+    }
+
+    /**
+     * @return string
+     */
+    public function getValue()
+    {
+        return $this->whichOneof("value");
+    }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/MetricsServiceClient.php b/src/php/tests/qps/generated_code/Grpc/Testing/MetricsServiceClient.php
new file mode 100644
index 0000000..491ccbc
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/MetricsServiceClient.php
@@ -0,0 +1,69 @@
+<?php
+// GENERATED CODE -- DO NOT EDIT!
+
+// Original file comments:
+// Copyright 2015-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.
+//
+// Contains the definitions for a metrics service and the type of metrics
+// exposed by the service.
+//
+// Currently, 'Gauge' (i.e a metric that represents the measured value of
+// something at an instant of time) is the only metric type supported by the
+// service.
+namespace Grpc\Testing;
+
+/**
+ */
+class MetricsServiceClient extends \Grpc\BaseStub {
+
+    /**
+     * @param string $hostname hostname
+     * @param array $opts channel options
+     * @param \Grpc\Channel $channel (optional) re-use channel object
+     */
+    public function __construct($hostname, $opts, $channel = null) {
+        parent::__construct($hostname, $opts, $channel);
+    }
+
+    /**
+     * Returns the values of all the gauges that are currently being maintained by
+     * the service
+     * @param \Grpc\Testing\EmptyMessage $argument input argument
+     * @param array $metadata metadata
+     * @param array $options call options
+     */
+    public function GetAllGauges(\Grpc\Testing\EmptyMessage $argument,
+      $metadata = [], $options = []) {
+        return $this->_serverStreamRequest('/grpc.testing.MetricsService/GetAllGauges',
+        $argument,
+        ['\Grpc\Testing\GaugeResponse', 'decode'],
+        $metadata, $options);
+    }
+
+    /**
+     * Returns the value of one gauge
+     * @param \Grpc\Testing\GaugeRequest $argument input argument
+     * @param array $metadata metadata
+     * @param array $options call options
+     */
+    public function GetGauge(\Grpc\Testing\GaugeRequest $argument,
+      $metadata = [], $options = []) {
+        return $this->_simpleRequest('/grpc.testing.MetricsService/GetGauge',
+        $argument,
+        ['\Grpc\Testing\GaugeResponse', 'decode'],
+        $metadata, $options);
+    }
+
+}
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/NoRpcServiceClient.php b/src/php/tests/qps/generated_code/Grpc/Testing/NoRpcServiceClient.php
new file mode 100644
index 0000000..1d58eaf
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/NoRpcServiceClient.php
@@ -0,0 +1,35 @@
+<?php
+// GENERATED CODE -- DO NOT EDIT!
+
+// Original file comments:
+// Copyright 2015 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.
+//
+namespace Grpc\Testing;
+
+/**
+ * A service without any rpc defined to test coverage.
+ */
+class NoRpcServiceClient extends \Grpc\BaseStub {
+
+    /**
+     * @param string $hostname hostname
+     * @param array $opts channel options
+     * @param \Grpc\Channel $channel (optional) re-use channel object
+     */
+    public function __construct($hostname, $opts, $channel = null) {
+        parent::__construct($hostname, $opts, $channel);
+    }
+
+}
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/PBEmpty.php b/src/php/tests/qps/generated_code/Grpc/Testing/PBEmpty.php
new file mode 100644
index 0000000..a1fe9df
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/PBEmpty.php
@@ -0,0 +1,30 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/testing/empty.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * An empty message that you can re-use to avoid defining duplicated empty
+ * messages in your project. A typical example is to use it as argument or the
+ * return value of a service API. For instance:
+ *   service Foo {
+ *     rpc Bar (grpc.testing.Empty) returns (grpc.testing.Empty) { };
+ *   };
+ *
+ * Generated from protobuf message <code>grpc.testing.Empty</code>
+ */
+class PBEmpty extends \Google\Protobuf\Internal\Message
+{
+
+    public function __construct() {
+        \GPBMetadata\Src\Proto\Grpc\Testing\GPBEmpty::initOnce();
+        parent::__construct();
+    }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/PBVoid.php b/src/php/tests/qps/generated_code/Grpc/Testing/PBVoid.php
new file mode 100644
index 0000000..94cb6c1
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/PBVoid.php
@@ -0,0 +1,23 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/testing/control.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Generated from protobuf message <code>grpc.testing.Void</code>
+ */
+class PBVoid extends \Google\Protobuf\Internal\Message
+{
+
+    public function __construct() {
+        \GPBMetadata\Src\Proto\Grpc\Testing\Control::initOnce();
+        parent::__construct();
+    }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/ProxyClientServiceClient.php b/src/php/tests/qps/generated_code/Grpc/Testing/ProxyClientServiceClient.php
index 5510b57..c0e3049 100644
--- a/src/php/tests/qps/generated_code/Grpc/Testing/ProxyClientServiceClient.php
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/ProxyClientServiceClient.php
@@ -32,11 +32,11 @@
     }
 
     /**
-     * @param \Grpc\Testing\Void $argument input argument
+     * @param \Grpc\Testing\PBVoid $argument input argument
      * @param array $metadata metadata
      * @param array $options call options
      */
-    public function GetConfig(\Grpc\Testing\Void $argument,
+    public function GetConfig(\Grpc\Testing\PBVoid $argument,
       $metadata = [], $options = []) {
         return $this->_simpleRequest('/grpc.testing.ProxyClientService/GetConfig',
         $argument,
@@ -50,7 +50,7 @@
      */
     public function ReportTime($metadata = [], $options = []) {
         return $this->_clientStreamRequest('/grpc.testing.ProxyClientService/ReportTime',
-        ['\Grpc\Testing\Void','decode'],
+        ['\Grpc\Testing\PBVoid','decode'],
         $metadata, $options);
     }
 
@@ -60,7 +60,7 @@
      */
     public function ReportHist($metadata = [], $options = []) {
         return $this->_clientStreamRequest('/grpc.testing.ProxyClientService/ReportHist',
-        ['\Grpc\Testing\Void','decode'],
+        ['\Grpc\Testing\PBVoid','decode'],
         $metadata, $options);
     }
 
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/ReconnectServiceClient.php b/src/php/tests/qps/generated_code/Grpc/Testing/ReconnectServiceClient.php
new file mode 100644
index 0000000..a1802e9
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/ReconnectServiceClient.php
@@ -0,0 +1,64 @@
+<?php
+// GENERATED CODE -- DO NOT EDIT!
+
+// Original file comments:
+// Copyright 2015-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.
+//
+// An integration test service that covers all the method signature permutations
+// of unary/streaming requests/responses.
+//
+namespace Grpc\Testing;
+
+/**
+ * A service used to control reconnect server.
+ */
+class ReconnectServiceClient extends \Grpc\BaseStub {
+
+    /**
+     * @param string $hostname hostname
+     * @param array $opts channel options
+     * @param \Grpc\Channel $channel (optional) re-use channel object
+     */
+    public function __construct($hostname, $opts, $channel = null) {
+        parent::__construct($hostname, $opts, $channel);
+    }
+
+    /**
+     * @param \Grpc\Testing\ReconnectParams $argument input argument
+     * @param array $metadata metadata
+     * @param array $options call options
+     */
+    public function Start(\Grpc\Testing\ReconnectParams $argument,
+      $metadata = [], $options = []) {
+        return $this->_simpleRequest('/grpc.testing.ReconnectService/Start',
+        $argument,
+        ['\Grpc\Testing\PBEmpty', 'decode'],
+        $metadata, $options);
+    }
+
+    /**
+     * @param \Grpc\Testing\PBEmpty $argument input argument
+     * @param array $metadata metadata
+     * @param array $options call options
+     */
+    public function Stop(\Grpc\Testing\PBEmpty $argument,
+      $metadata = [], $options = []) {
+        return $this->_simpleRequest('/grpc.testing.ReconnectService/Stop',
+        $argument,
+        ['\Grpc\Testing\ReconnectInfo', 'decode'],
+        $metadata, $options);
+    }
+
+}
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/ReportQpsScenarioServiceClient.php b/src/php/tests/qps/generated_code/Grpc/Testing/ReportQpsScenarioServiceClient.php
index 72d44ff..3abb5ab 100644
--- a/src/php/tests/qps/generated_code/Grpc/Testing/ReportQpsScenarioServiceClient.php
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/ReportQpsScenarioServiceClient.php
@@ -43,7 +43,7 @@
       $metadata = [], $options = []) {
         return $this->_simpleRequest('/grpc.testing.ReportQpsScenarioService/ReportScenario',
         $argument,
-        ['\Grpc\Testing\Void', 'decode'],
+        ['\Grpc\Testing\PBVoid', 'decode'],
         $metadata, $options);
     }
 
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/Request.php b/src/php/tests/qps/generated_code/Grpc/Testing/Request.php
new file mode 100644
index 0000000..6a20f6a
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/Request.php
@@ -0,0 +1,23 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/testing/compiler_test.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Generated from protobuf message <code>grpc.testing.Request</code>
+ */
+class Request extends \Google\Protobuf\Internal\Message
+{
+
+    public function __construct() {
+        \GPBMetadata\Src\Proto\Grpc\Testing\CompilerTest::initOnce();
+        parent::__construct();
+    }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/RequestParams.php b/src/php/tests/qps/generated_code/Grpc/Testing/RequestParams.php
new file mode 100644
index 0000000..f01f50d
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/RequestParams.php
@@ -0,0 +1,431 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/testing/echo_messages.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Generated from protobuf message <code>grpc.testing.RequestParams</code>
+ */
+class RequestParams extends \Google\Protobuf\Internal\Message
+{
+    /**
+     * Generated from protobuf field <code>bool echo_deadline = 1;</code>
+     */
+    private $echo_deadline = false;
+    /**
+     * Generated from protobuf field <code>int32 client_cancel_after_us = 2;</code>
+     */
+    private $client_cancel_after_us = 0;
+    /**
+     * Generated from protobuf field <code>int32 server_cancel_after_us = 3;</code>
+     */
+    private $server_cancel_after_us = 0;
+    /**
+     * Generated from protobuf field <code>bool echo_metadata = 4;</code>
+     */
+    private $echo_metadata = false;
+    /**
+     * Generated from protobuf field <code>bool check_auth_context = 5;</code>
+     */
+    private $check_auth_context = false;
+    /**
+     * Generated from protobuf field <code>int32 response_message_length = 6;</code>
+     */
+    private $response_message_length = 0;
+    /**
+     * Generated from protobuf field <code>bool echo_peer = 7;</code>
+     */
+    private $echo_peer = false;
+    /**
+     * will force check_auth_context.
+     *
+     * Generated from protobuf field <code>string expected_client_identity = 8;</code>
+     */
+    private $expected_client_identity = '';
+    /**
+     * Generated from protobuf field <code>bool skip_cancelled_check = 9;</code>
+     */
+    private $skip_cancelled_check = false;
+    /**
+     * Generated from protobuf field <code>string expected_transport_security_type = 10;</code>
+     */
+    private $expected_transport_security_type = '';
+    /**
+     * Generated from protobuf field <code>.grpc.testing.DebugInfo debug_info = 11;</code>
+     */
+    private $debug_info = null;
+    /**
+     * Server should not see a request with this set.
+     *
+     * Generated from protobuf field <code>bool server_die = 12;</code>
+     */
+    private $server_die = false;
+    /**
+     * Generated from protobuf field <code>string binary_error_details = 13;</code>
+     */
+    private $binary_error_details = '';
+    /**
+     * Generated from protobuf field <code>.grpc.testing.ErrorStatus expected_error = 14;</code>
+     */
+    private $expected_error = null;
+    /**
+     * Amount to sleep when invoking server
+     *
+     * Generated from protobuf field <code>int32 server_sleep_us = 15;</code>
+     */
+    private $server_sleep_us = 0;
+
+    public function __construct() {
+        \GPBMetadata\Src\Proto\Grpc\Testing\EchoMessages::initOnce();
+        parent::__construct();
+    }
+
+    /**
+     * Generated from protobuf field <code>bool echo_deadline = 1;</code>
+     * @return bool
+     */
+    public function getEchoDeadline()
+    {
+        return $this->echo_deadline;
+    }
+
+    /**
+     * Generated from protobuf field <code>bool echo_deadline = 1;</code>
+     * @param bool $var
+     * @return $this
+     */
+    public function setEchoDeadline($var)
+    {
+        GPBUtil::checkBool($var);
+        $this->echo_deadline = $var;
+
+        return $this;
+    }
+
+    /**
+     * Generated from protobuf field <code>int32 client_cancel_after_us = 2;</code>
+     * @return int
+     */
+    public function getClientCancelAfterUs()
+    {
+        return $this->client_cancel_after_us;
+    }
+
+    /**
+     * Generated from protobuf field <code>int32 client_cancel_after_us = 2;</code>
+     * @param int $var
+     * @return $this
+     */
+    public function setClientCancelAfterUs($var)
+    {
+        GPBUtil::checkInt32($var);
+        $this->client_cancel_after_us = $var;
+
+        return $this;
+    }
+
+    /**
+     * Generated from protobuf field <code>int32 server_cancel_after_us = 3;</code>
+     * @return int
+     */
+    public function getServerCancelAfterUs()
+    {
+        return $this->server_cancel_after_us;
+    }
+
+    /**
+     * Generated from protobuf field <code>int32 server_cancel_after_us = 3;</code>
+     * @param int $var
+     * @return $this
+     */
+    public function setServerCancelAfterUs($var)
+    {
+        GPBUtil::checkInt32($var);
+        $this->server_cancel_after_us = $var;
+
+        return $this;
+    }
+
+    /**
+     * Generated from protobuf field <code>bool echo_metadata = 4;</code>
+     * @return bool
+     */
+    public function getEchoMetadata()
+    {
+        return $this->echo_metadata;
+    }
+
+    /**
+     * Generated from protobuf field <code>bool echo_metadata = 4;</code>
+     * @param bool $var
+     * @return $this
+     */
+    public function setEchoMetadata($var)
+    {
+        GPBUtil::checkBool($var);
+        $this->echo_metadata = $var;
+
+        return $this;
+    }
+
+    /**
+     * Generated from protobuf field <code>bool check_auth_context = 5;</code>
+     * @return bool
+     */
+    public function getCheckAuthContext()
+    {
+        return $this->check_auth_context;
+    }
+
+    /**
+     * Generated from protobuf field <code>bool check_auth_context = 5;</code>
+     * @param bool $var
+     * @return $this
+     */
+    public function setCheckAuthContext($var)
+    {
+        GPBUtil::checkBool($var);
+        $this->check_auth_context = $var;
+
+        return $this;
+    }
+
+    /**
+     * Generated from protobuf field <code>int32 response_message_length = 6;</code>
+     * @return int
+     */
+    public function getResponseMessageLength()
+    {
+        return $this->response_message_length;
+    }
+
+    /**
+     * Generated from protobuf field <code>int32 response_message_length = 6;</code>
+     * @param int $var
+     * @return $this
+     */
+    public function setResponseMessageLength($var)
+    {
+        GPBUtil::checkInt32($var);
+        $this->response_message_length = $var;
+
+        return $this;
+    }
+
+    /**
+     * Generated from protobuf field <code>bool echo_peer = 7;</code>
+     * @return bool
+     */
+    public function getEchoPeer()
+    {
+        return $this->echo_peer;
+    }
+
+    /**
+     * Generated from protobuf field <code>bool echo_peer = 7;</code>
+     * @param bool $var
+     * @return $this
+     */
+    public function setEchoPeer($var)
+    {
+        GPBUtil::checkBool($var);
+        $this->echo_peer = $var;
+
+        return $this;
+    }
+
+    /**
+     * will force check_auth_context.
+     *
+     * Generated from protobuf field <code>string expected_client_identity = 8;</code>
+     * @return string
+     */
+    public function getExpectedClientIdentity()
+    {
+        return $this->expected_client_identity;
+    }
+
+    /**
+     * will force check_auth_context.
+     *
+     * Generated from protobuf field <code>string expected_client_identity = 8;</code>
+     * @param string $var
+     * @return $this
+     */
+    public function setExpectedClientIdentity($var)
+    {
+        GPBUtil::checkString($var, True);
+        $this->expected_client_identity = $var;
+
+        return $this;
+    }
+
+    /**
+     * Generated from protobuf field <code>bool skip_cancelled_check = 9;</code>
+     * @return bool
+     */
+    public function getSkipCancelledCheck()
+    {
+        return $this->skip_cancelled_check;
+    }
+
+    /**
+     * Generated from protobuf field <code>bool skip_cancelled_check = 9;</code>
+     * @param bool $var
+     * @return $this
+     */
+    public function setSkipCancelledCheck($var)
+    {
+        GPBUtil::checkBool($var);
+        $this->skip_cancelled_check = $var;
+
+        return $this;
+    }
+
+    /**
+     * Generated from protobuf field <code>string expected_transport_security_type = 10;</code>
+     * @return string
+     */
+    public function getExpectedTransportSecurityType()
+    {
+        return $this->expected_transport_security_type;
+    }
+
+    /**
+     * Generated from protobuf field <code>string expected_transport_security_type = 10;</code>
+     * @param string $var
+     * @return $this
+     */
+    public function setExpectedTransportSecurityType($var)
+    {
+        GPBUtil::checkString($var, True);
+        $this->expected_transport_security_type = $var;
+
+        return $this;
+    }
+
+    /**
+     * Generated from protobuf field <code>.grpc.testing.DebugInfo debug_info = 11;</code>
+     * @return \Grpc\Testing\DebugInfo
+     */
+    public function getDebugInfo()
+    {
+        return $this->debug_info;
+    }
+
+    /**
+     * Generated from protobuf field <code>.grpc.testing.DebugInfo debug_info = 11;</code>
+     * @param \Grpc\Testing\DebugInfo $var
+     * @return $this
+     */
+    public function setDebugInfo($var)
+    {
+        GPBUtil::checkMessage($var, \Grpc\Testing\DebugInfo::class);
+        $this->debug_info = $var;
+
+        return $this;
+    }
+
+    /**
+     * Server should not see a request with this set.
+     *
+     * Generated from protobuf field <code>bool server_die = 12;</code>
+     * @return bool
+     */
+    public function getServerDie()
+    {
+        return $this->server_die;
+    }
+
+    /**
+     * Server should not see a request with this set.
+     *
+     * Generated from protobuf field <code>bool server_die = 12;</code>
+     * @param bool $var
+     * @return $this
+     */
+    public function setServerDie($var)
+    {
+        GPBUtil::checkBool($var);
+        $this->server_die = $var;
+
+        return $this;
+    }
+
+    /**
+     * Generated from protobuf field <code>string binary_error_details = 13;</code>
+     * @return string
+     */
+    public function getBinaryErrorDetails()
+    {
+        return $this->binary_error_details;
+    }
+
+    /**
+     * Generated from protobuf field <code>string binary_error_details = 13;</code>
+     * @param string $var
+     * @return $this
+     */
+    public function setBinaryErrorDetails($var)
+    {
+        GPBUtil::checkString($var, True);
+        $this->binary_error_details = $var;
+
+        return $this;
+    }
+
+    /**
+     * Generated from protobuf field <code>.grpc.testing.ErrorStatus expected_error = 14;</code>
+     * @return \Grpc\Testing\ErrorStatus
+     */
+    public function getExpectedError()
+    {
+        return $this->expected_error;
+    }
+
+    /**
+     * Generated from protobuf field <code>.grpc.testing.ErrorStatus expected_error = 14;</code>
+     * @param \Grpc\Testing\ErrorStatus $var
+     * @return $this
+     */
+    public function setExpectedError($var)
+    {
+        GPBUtil::checkMessage($var, \Grpc\Testing\ErrorStatus::class);
+        $this->expected_error = $var;
+
+        return $this;
+    }
+
+    /**
+     * Amount to sleep when invoking server
+     *
+     * Generated from protobuf field <code>int32 server_sleep_us = 15;</code>
+     * @return int
+     */
+    public function getServerSleepUs()
+    {
+        return $this->server_sleep_us;
+    }
+
+    /**
+     * Amount to sleep when invoking server
+     *
+     * Generated from protobuf field <code>int32 server_sleep_us = 15;</code>
+     * @param int $var
+     * @return $this
+     */
+    public function setServerSleepUs($var)
+    {
+        GPBUtil::checkInt32($var);
+        $this->server_sleep_us = $var;
+
+        return $this;
+    }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/Response.php b/src/php/tests/qps/generated_code/Grpc/Testing/Response.php
new file mode 100644
index 0000000..7925a7d
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/Response.php
@@ -0,0 +1,23 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/testing/compiler_test.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Generated from protobuf message <code>grpc.testing.Response</code>
+ */
+class Response extends \Google\Protobuf\Internal\Message
+{
+
+    public function __construct() {
+        \GPBMetadata\Src\Proto\Grpc\Testing\CompilerTest::initOnce();
+        parent::__construct();
+    }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/ResponseParams.php b/src/php/tests/qps/generated_code/Grpc/Testing/ResponseParams.php
new file mode 100644
index 0000000..d20f922
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/ResponseParams.php
@@ -0,0 +1,101 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/testing/echo_messages.proto
+
+namespace Grpc\Testing;
+
+use Google\Protobuf\Internal\GPBType;
+use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
+
+/**
+ * Generated from protobuf message <code>grpc.testing.ResponseParams</code>
+ */
+class ResponseParams extends \Google\Protobuf\Internal\Message
+{
+    /**
+     * Generated from protobuf field <code>int64 request_deadline = 1;</code>
+     */
+    private $request_deadline = 0;
+    /**
+     * Generated from protobuf field <code>string host = 2;</code>
+     */
+    private $host = '';
+    /**
+     * Generated from protobuf field <code>string peer = 3;</code>
+     */
+    private $peer = '';
+
+    public function __construct() {
+        \GPBMetadata\Src\Proto\Grpc\Testing\EchoMessages::initOnce();
+        parent::__construct();
+    }
+
+    /**
+     * Generated from protobuf field <code>int64 request_deadline = 1;</code>
+     * @return int|string
+     */
+    public function getRequestDeadline()
+    {
+        return $this->request_deadline;
+    }
+
+    /**
+     * Generated from protobuf field <code>int64 request_deadline = 1;</code>
+     * @param int|string $var
+     * @return $this
+     */
+    public function setRequestDeadline($var)
+    {
+        GPBUtil::checkInt64($var);
+        $this->request_deadline = $var;
+
+        return $this;
+    }
+
+    /**
+     * Generated from protobuf field <code>string host = 2;</code>
+     * @return string
+     */
+    public function getHost()
+    {
+        return $this->host;
+    }
+
+    /**
+     * Generated from protobuf field <code>string host = 2;</code>
+     * @param string $var
+     * @return $this
+     */
+    public function setHost($var)
+    {
+        GPBUtil::checkString($var, True);
+        $this->host = $var;
+
+        return $this;
+    }
+
+    /**
+     * Generated from protobuf field <code>string peer = 3;</code>
+     * @return string
+     */
+    public function getPeer()
+    {
+        return $this->peer;
+    }
+
+    /**
+     * Generated from protobuf field <code>string peer = 3;</code>
+     * @param string $var
+     * @return $this
+     */
+    public function setPeer($var)
+    {
+        GPBUtil::checkString($var, True);
+        $this->peer = $var;
+
+        return $this;
+    }
+
+}
+
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/ServiceAClient.php b/src/php/tests/qps/generated_code/Grpc/Testing/ServiceAClient.php
new file mode 100644
index 0000000..df469cb
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/ServiceAClient.php
@@ -0,0 +1,97 @@
+<?php
+// GENERATED CODE -- DO NOT EDIT!
+
+// Original file comments:
+// 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.
+//
+// File detached comment 1
+//
+// File detached comment 2
+//
+// File leading comment 1
+namespace Grpc\Testing;
+
+/**
+ * ServiceA detached comment 1
+ *
+ * ServiceA detached comment 2
+ *
+ * ServiceA leading comment 1
+ */
+class ServiceAClient extends \Grpc\BaseStub {
+
+    /**
+     * @param string $hostname hostname
+     * @param array $opts channel options
+     * @param \Grpc\Channel $channel (optional) re-use channel object
+     */
+    public function __construct($hostname, $opts, $channel = null) {
+        parent::__construct($hostname, $opts, $channel);
+    }
+
+    /**
+     * MethodA1 leading comment 1
+     * @param \Grpc\Testing\Request $argument input argument
+     * @param array $metadata metadata
+     * @param array $options call options
+     */
+    public function MethodA1(\Grpc\Testing\Request $argument,
+      $metadata = [], $options = []) {
+        return $this->_simpleRequest('/grpc.testing.ServiceA/MethodA1',
+        $argument,
+        ['\Grpc\Testing\Response', 'decode'],
+        $metadata, $options);
+    }
+
+    /**
+     * MethodA2 detached leading comment 1
+     *
+     * Method A2 leading comment 1
+     * Method A2 leading comment 2
+     * @param array $metadata metadata
+     * @param array $options call options
+     */
+    public function MethodA2($metadata = [], $options = []) {
+        return $this->_clientStreamRequest('/grpc.testing.ServiceA/MethodA2',
+        ['\Grpc\Testing\Response','decode'],
+        $metadata, $options);
+    }
+
+    /**
+     * Method A3 leading comment 1
+     * @param \Grpc\Testing\Request $argument input argument
+     * @param array $metadata metadata
+     * @param array $options call options
+     */
+    public function MethodA3(\Grpc\Testing\Request $argument,
+      $metadata = [], $options = []) {
+        return $this->_serverStreamRequest('/grpc.testing.ServiceA/MethodA3',
+        $argument,
+        ['\Grpc\Testing\Response', 'decode'],
+        $metadata, $options);
+    }
+
+    /**
+     * Method A4 leading comment 1
+     * @param array $metadata metadata
+     * @param array $options call options
+     */
+    public function MethodA4($metadata = [], $options = []) {
+        return $this->_bidiRequest('/grpc.testing.ServiceA/MethodA4',
+        ['\Grpc\Testing\Response','decode'],
+        $metadata, $options);
+    }
+
+}
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/ServiceBClient.php b/src/php/tests/qps/generated_code/Grpc/Testing/ServiceBClient.php
new file mode 100644
index 0000000..54acf63
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/ServiceBClient.php
@@ -0,0 +1,54 @@
+<?php
+// GENERATED CODE -- DO NOT EDIT!
+
+// Original file comments:
+// 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.
+//
+// File detached comment 1
+//
+// File detached comment 2
+//
+// File leading comment 1
+namespace Grpc\Testing;
+
+/**
+ * ServiceB leading comment 1
+ */
+class ServiceBClient extends \Grpc\BaseStub {
+
+    /**
+     * @param string $hostname hostname
+     * @param array $opts channel options
+     * @param \Grpc\Channel $channel (optional) re-use channel object
+     */
+    public function __construct($hostname, $opts, $channel = null) {
+        parent::__construct($hostname, $opts, $channel);
+    }
+
+    /**
+     * MethodB1 leading comment 1
+     * @param \Grpc\Testing\Request $argument input argument
+     * @param array $metadata metadata
+     * @param array $options call options
+     */
+    public function MethodB1(\Grpc\Testing\Request $argument,
+      $metadata = [], $options = []) {
+        return $this->_simpleRequest('/grpc.testing.ServiceB/MethodB1',
+        $argument,
+        ['\Grpc\Testing\Response', 'decode'],
+        $metadata, $options);
+    }
+
+}
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/TestServiceClient.php b/src/php/tests/qps/generated_code/Grpc/Testing/TestServiceClient.php
new file mode 100644
index 0000000..7da9713
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/TestServiceClient.php
@@ -0,0 +1,152 @@
+<?php
+// GENERATED CODE -- DO NOT EDIT!
+
+// Original file comments:
+// Copyright 2015-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.
+//
+// An integration test service that covers all the method signature permutations
+// of unary/streaming requests/responses.
+//
+namespace Grpc\Testing;
+
+/**
+ * A simple service to test the various types of RPCs and experiment with
+ * performance with various types of payload.
+ */
+class TestServiceClient extends \Grpc\BaseStub {
+
+    /**
+     * @param string $hostname hostname
+     * @param array $opts channel options
+     * @param \Grpc\Channel $channel (optional) re-use channel object
+     */
+    public function __construct($hostname, $opts, $channel = null) {
+        parent::__construct($hostname, $opts, $channel);
+    }
+
+    /**
+     * One empty request followed by one empty response.
+     * @param \Grpc\Testing\PBEmpty $argument input argument
+     * @param array $metadata metadata
+     * @param array $options call options
+     */
+    public function EmptyCall(\Grpc\Testing\PBEmpty $argument,
+      $metadata = [], $options = []) {
+        return $this->_simpleRequest('/grpc.testing.TestService/EmptyCall',
+        $argument,
+        ['\Grpc\Testing\PBEmpty', 'decode'],
+        $metadata, $options);
+    }
+
+    /**
+     * One request followed by one response.
+     * @param \Grpc\Testing\SimpleRequest $argument input argument
+     * @param array $metadata metadata
+     * @param array $options call options
+     */
+    public function UnaryCall(\Grpc\Testing\SimpleRequest $argument,
+      $metadata = [], $options = []) {
+        return $this->_simpleRequest('/grpc.testing.TestService/UnaryCall',
+        $argument,
+        ['\Grpc\Testing\SimpleResponse', 'decode'],
+        $metadata, $options);
+    }
+
+    /**
+     * One request followed by one response. Response has cache control
+     * headers set such that a caching HTTP proxy (such as GFE) can
+     * satisfy subsequent requests.
+     * @param \Grpc\Testing\SimpleRequest $argument input argument
+     * @param array $metadata metadata
+     * @param array $options call options
+     */
+    public function CacheableUnaryCall(\Grpc\Testing\SimpleRequest $argument,
+      $metadata = [], $options = []) {
+        return $this->_simpleRequest('/grpc.testing.TestService/CacheableUnaryCall',
+        $argument,
+        ['\Grpc\Testing\SimpleResponse', 'decode'],
+        $metadata, $options);
+    }
+
+    /**
+     * One request followed by a sequence of responses (streamed download).
+     * The server returns the payload with client desired type and sizes.
+     * @param \Grpc\Testing\StreamingOutputCallRequest $argument input argument
+     * @param array $metadata metadata
+     * @param array $options call options
+     */
+    public function StreamingOutputCall(\Grpc\Testing\StreamingOutputCallRequest $argument,
+      $metadata = [], $options = []) {
+        return $this->_serverStreamRequest('/grpc.testing.TestService/StreamingOutputCall',
+        $argument,
+        ['\Grpc\Testing\StreamingOutputCallResponse', 'decode'],
+        $metadata, $options);
+    }
+
+    /**
+     * A sequence of requests followed by one response (streamed upload).
+     * The server returns the aggregated size of client payload as the result.
+     * @param array $metadata metadata
+     * @param array $options call options
+     */
+    public function StreamingInputCall($metadata = [], $options = []) {
+        return $this->_clientStreamRequest('/grpc.testing.TestService/StreamingInputCall',
+        ['\Grpc\Testing\StreamingInputCallResponse','decode'],
+        $metadata, $options);
+    }
+
+    /**
+     * A sequence of requests with each request served by the server immediately.
+     * As one request could lead to multiple responses, this interface
+     * demonstrates the idea of full duplexing.
+     * @param array $metadata metadata
+     * @param array $options call options
+     */
+    public function FullDuplexCall($metadata = [], $options = []) {
+        return $this->_bidiRequest('/grpc.testing.TestService/FullDuplexCall',
+        ['\Grpc\Testing\StreamingOutputCallResponse','decode'],
+        $metadata, $options);
+    }
+
+    /**
+     * A sequence of requests followed by a sequence of responses.
+     * The server buffers all the client requests and then serves them in order. A
+     * stream of responses are returned to the client when the server starts with
+     * first request.
+     * @param array $metadata metadata
+     * @param array $options call options
+     */
+    public function HalfDuplexCall($metadata = [], $options = []) {
+        return $this->_bidiRequest('/grpc.testing.TestService/HalfDuplexCall',
+        ['\Grpc\Testing\StreamingOutputCallResponse','decode'],
+        $metadata, $options);
+    }
+
+    /**
+     * The test server will not implement this method. It will be used
+     * to test the behavior when clients call unimplemented methods.
+     * @param \Grpc\Testing\PBEmpty $argument input argument
+     * @param array $metadata metadata
+     * @param array $options call options
+     */
+    public function UnimplementedCall(\Grpc\Testing\PBEmpty $argument,
+      $metadata = [], $options = []) {
+        return $this->_simpleRequest('/grpc.testing.TestService/UnimplementedCall',
+        $argument,
+        ['\Grpc\Testing\PBEmpty', 'decode'],
+        $metadata, $options);
+    }
+
+}
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/UnimplementedEchoServiceClient.php b/src/php/tests/qps/generated_code/Grpc/Testing/UnimplementedEchoServiceClient.php
new file mode 100644
index 0000000..fee0daa
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/UnimplementedEchoServiceClient.php
@@ -0,0 +1,47 @@
+<?php
+// GENERATED CODE -- DO NOT EDIT!
+
+// Original file comments:
+// Copyright 2015 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.
+//
+namespace Grpc\Testing;
+
+/**
+ */
+class UnimplementedEchoServiceClient extends \Grpc\BaseStub {
+
+    /**
+     * @param string $hostname hostname
+     * @param array $opts channel options
+     * @param \Grpc\Channel $channel (optional) re-use channel object
+     */
+    public function __construct($hostname, $opts, $channel = null) {
+        parent::__construct($hostname, $opts, $channel);
+    }
+
+    /**
+     * @param \Grpc\Testing\EchoRequest $argument input argument
+     * @param array $metadata metadata
+     * @param array $options call options
+     */
+    public function Unimplemented(\Grpc\Testing\EchoRequest $argument,
+      $metadata = [], $options = []) {
+        return $this->_simpleRequest('/grpc.testing.UnimplementedEchoService/Unimplemented',
+        $argument,
+        ['\Grpc\Testing\EchoResponse', 'decode'],
+        $metadata, $options);
+    }
+
+}
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/UnimplementedServiceClient.php b/src/php/tests/qps/generated_code/Grpc/Testing/UnimplementedServiceClient.php
new file mode 100644
index 0000000..53b2020
--- /dev/null
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/UnimplementedServiceClient.php
@@ -0,0 +1,53 @@
+<?php
+// GENERATED CODE -- DO NOT EDIT!
+
+// Original file comments:
+// Copyright 2015-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.
+//
+// An integration test service that covers all the method signature permutations
+// of unary/streaming requests/responses.
+//
+namespace Grpc\Testing;
+
+/**
+ * A simple service NOT implemented at servers so clients can test for
+ * that case.
+ */
+class UnimplementedServiceClient extends \Grpc\BaseStub {
+
+    /**
+     * @param string $hostname hostname
+     * @param array $opts channel options
+     * @param \Grpc\Channel $channel (optional) re-use channel object
+     */
+    public function __construct($hostname, $opts, $channel = null) {
+        parent::__construct($hostname, $opts, $channel);
+    }
+
+    /**
+     * A call that no server should implement
+     * @param \Grpc\Testing\PBEmpty $argument input argument
+     * @param array $metadata metadata
+     * @param array $options call options
+     */
+    public function UnimplementedCall(\Grpc\Testing\PBEmpty $argument,
+      $metadata = [], $options = []) {
+        return $this->_simpleRequest('/grpc.testing.UnimplementedService/UnimplementedCall',
+        $argument,
+        ['\Grpc\Testing\PBEmpty', 'decode'],
+        $metadata, $options);
+    }
+
+}
diff --git a/src/php/tests/qps/generated_code/Grpc/Testing/WorkerServiceClient.php b/src/php/tests/qps/generated_code/Grpc/Testing/WorkerServiceClient.php
index 98c244f..366e365 100644
--- a/src/php/tests/qps/generated_code/Grpc/Testing/WorkerServiceClient.php
+++ b/src/php/tests/qps/generated_code/Grpc/Testing/WorkerServiceClient.php
@@ -81,15 +81,15 @@
 
     /**
      * Quit this worker
-     * @param \Grpc\Testing\Void $argument input argument
+     * @param \Grpc\Testing\PBVoid $argument input argument
      * @param array $metadata metadata
      * @param array $options call options
      */
-    public function QuitWorker(\Grpc\Testing\Void $argument,
+    public function QuitWorker(\Grpc\Testing\PBVoid $argument,
       $metadata = [], $options = []) {
         return $this->_simpleRequest('/grpc.testing.WorkerService/QuitWorker',
         $argument,
-        ['\Grpc\Testing\Void', 'decode'],
+        ['\Grpc\Testing\PBVoid', 'decode'],
         $metadata, $options);
     }
 
diff --git a/src/php/tests/unit_tests/InterceptorTest.php b/src/php/tests/unit_tests/InterceptorTest.php
new file mode 100644
index 0000000..08f5abb
--- /dev/null
+++ b/src/php/tests/unit_tests/InterceptorTest.php
@@ -0,0 +1,427 @@
+<?php
+/*
+ *
+ * Copyright 2018 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.
+ *
+ */
+/**
+ * Interface exported by the server.
+ */
+require_once(dirname(__FILE__).'/../../lib/Grpc/BaseStub.php');
+require_once(dirname(__FILE__).'/../../lib/Grpc/AbstractCall.php');
+require_once(dirname(__FILE__).'/../../lib/Grpc/UnaryCall.php');
+require_once(dirname(__FILE__).'/../../lib/Grpc/ClientStreamingCall.php');
+require_once(dirname(__FILE__).'/../../lib/Grpc/Interceptor.php');
+require_once(dirname(__FILE__).'/../../lib/Grpc/Internal/InterceptorChannel.php');
+
+class SimpleRequest
+{
+    private $data;
+    public function __construct($data)
+    {
+        $this->data = $data;
+    }
+    public function setData($data)
+    {
+        $this->data = $data;
+    }
+    public function serializeToString()
+    {
+        return $this->data;
+    }
+}
+
+class InterceptorClient extends Grpc\BaseStub
+{
+
+    /**
+     * @param string $hostname hostname
+     * @param array $opts channel options
+     * @param Channel|InterceptorChannel $channel (optional) re-use channel object
+     */
+    public function __construct($hostname, $opts, $channel = null)
+    {
+        parent::__construct($hostname, $opts, $channel);
+    }
+
+    /**
+     * A simple RPC.
+     * @param \Routeguide\Point $argument input argument
+     * @param array $metadata metadata
+     * @param array $options call options
+     */
+    public function UnaryCall(
+        SimpleRequest $argument,
+        $metadata = [],
+        $options = []
+    ) {
+        return $this->_simpleRequest(
+            '/dummy_method',
+            $argument,
+            [],
+            $metadata,
+            $options
+        );
+    }
+
+    /**
+     * A client-to-server streaming RPC.
+     * @param array $metadata metadata
+     * @param array $options call options
+     */
+    public function StreamCall(
+        $metadata = [],
+        $options = []
+    ) {
+        return $this->_clientStreamRequest('/dummy_method', [], $metadata, $options);
+    }
+}
+
+
+class ChangeMetadataInterceptor extends Grpc\Interceptor
+{
+    public function interceptUnaryUnary($method,
+                                        $argument,
+                                        array $metadata = [],
+                                        array $options = [],
+                                        $continuation)
+    {
+        $metadata["foo"] = array('interceptor_from_unary_request');
+        return $continuation($method, $argument, $metadata, $options);
+    }
+    public function interceptStreamUnary($method, array $metadata = [], array $options = [], $continuation)
+    {
+        $metadata["foo"] = array('interceptor_from_stream_request');
+        return $continuation($method, $metadata, $options);
+    }
+}
+
+class ChangeMetadataInterceptor2 extends Grpc\Interceptor
+{
+    public function interceptUnaryUnary($method,
+                                        $argument,
+                                        array $metadata = [],
+                                        array $options = [],
+                                        $continuation)
+    {
+        if (array_key_exists('foo', $metadata)) {
+            $metadata['bar'] = array('ChangeMetadataInterceptor should be executed first');
+        } else {
+            $metadata["bar"] = array('interceptor_from_unary_request');
+        }
+        return $continuation($method, $argument, $metadata, $options);
+    }
+    public function interceptStreamUnary($method,
+                                         array $metadata = [],
+                                         array $options = [],
+                                         $continuation)
+    {
+        if (array_key_exists('foo', $metadata)) {
+            $metadata['bar'] = array('ChangeMetadataInterceptor should be executed first');
+        } else {
+            $metadata["bar"] = array('interceptor_from_stream_request');
+        }
+        return $continuation($method, $metadata, $options);
+    }
+}
+
+class ChangeRequestCall
+{
+    private $call;
+
+    public function __construct($call)
+    {
+        $this->call = $call;
+    }
+    public function getCall()
+    {
+        return $this->call;
+    }
+
+    public function write($request)
+    {
+        $request->setData('intercepted_stream_request');
+        $this->getCall()->write($request);
+    }
+
+    public function wait()
+    {
+        return $this->getCall()->wait();
+    }
+}
+
+class ChangeRequestInterceptor extends Grpc\Interceptor
+{
+    public function interceptUnaryUnary($method,
+                                        $argument,
+                                        array $metadata = [],
+                                        array $options = [],
+                                        $continuation)
+    {
+        $argument->setData('intercepted_unary_request');
+        return $continuation($method, $argument, $metadata, $options);
+    }
+    public function interceptStreamUnary($method, array $metadata = [], array $options = [], $continuation)
+    {
+        return new ChangeRequestCall(
+            $continuation($method, $metadata, $options)
+        );
+    }
+}
+
+class StopCallInterceptor extends Grpc\Interceptor
+{
+    public function interceptUnaryUnary($method,
+                                        $argument,
+                                        array $metadata = [],
+                                        array $options = [],
+                                        $continuation)
+    {
+        $metadata["foo"] = array('interceptor_from_request_response');
+    }
+    public function interceptStreamUnary($method,
+                                         array $metadata = [],
+                                         array $options = [],
+                                         $continuation)
+    {
+        $metadata["foo"] = array('interceptor_from_request_response');
+    }
+}
+
+class InterceptorTest extends PHPUnit_Framework_TestCase
+{
+    public function setUp()
+    {
+        $this->server = new Grpc\Server([]);
+        $this->port = $this->server->addHttp2Port('0.0.0.0:0');
+        $this->channel = new Grpc\Channel('localhost:'.$this->port, ['credentials' => Grpc\ChannelCredentials::createInsecure()]);
+        $this->server->start();
+    }
+
+    public function tearDown()
+    {
+        $this->channel->close();
+    }
+
+
+    public function testClientChangeMetadataOneInterceptor()
+    {
+        $req_text = 'client_request';
+        $channel_matadata_interceptor = new ChangeMetadataInterceptor();
+        $intercept_channel = Grpc\Interceptor::intercept($this->channel, $channel_matadata_interceptor);
+        echo "create Client\n";
+        $client = new InterceptorClient('localhost:'.$this->port, [
+            'credentials' => Grpc\ChannelCredentials::createInsecure(),
+        ], $intercept_channel);
+        echo "create Call\n";
+        $req = new SimpleRequest($req_text);
+        echo "Call created\n";
+        $unary_call = $client->UnaryCall($req);
+        echo "start call\n";
+        $event = $this->server->requestCall();
+        $this->assertSame('/dummy_method', $event->method);
+        $this->assertSame(['interceptor_from_unary_request'], $event->metadata['foo']);
+
+        $stream_call = $client->StreamCall();
+        $stream_call->write($req);
+        $event = $this->server->requestCall();
+        $this->assertSame('/dummy_method', $event->method);
+        $this->assertSame(['interceptor_from_stream_request'], $event->metadata['foo']);
+
+        unset($unary_call);
+        unset($stream_call);
+        unset($server_call);
+    }
+
+    public function testClientChangeMetadataTwoInterceptor()
+    {
+        $req_text = 'client_request';
+        $channel_matadata_interceptor = new ChangeMetadataInterceptor();
+        $channel_matadata_intercepto2 = new ChangeMetadataInterceptor2();
+        // test intercept separately.
+        $intercept_channel1 = Grpc\Interceptor::intercept($this->channel, $channel_matadata_interceptor);
+        $intercept_channel2 = Grpc\Interceptor::intercept($intercept_channel1, $channel_matadata_intercepto2);
+        $client = new InterceptorClient('localhost:'.$this->port, [
+            'credentials' => Grpc\ChannelCredentials::createInsecure(),
+        ], $intercept_channel2);
+
+        $req = new SimpleRequest($req_text);
+        $unary_call = $client->UnaryCall($req);
+        $event = $this->server->requestCall();
+        $this->assertSame('/dummy_method', $event->method);
+        $this->assertSame(['interceptor_from_unary_request'], $event->metadata['foo']);
+        $this->assertSame(['interceptor_from_unary_request'], $event->metadata['bar']);
+
+        $stream_call = $client->StreamCall();
+        $stream_call->write($req);
+        $event = $this->server->requestCall();
+        $this->assertSame('/dummy_method', $event->method);
+        $this->assertSame(['interceptor_from_stream_request'], $event->metadata['foo']);
+        $this->assertSame(['interceptor_from_stream_request'], $event->metadata['bar']);
+
+        unset($unary_call);
+        unset($stream_call);
+        unset($server_call);
+
+        // test intercept by array.
+        $intercept_channel3 = Grpc\Interceptor::intercept($this->channel,
+            [$channel_matadata_intercepto2, $channel_matadata_interceptor]);
+        $client = new InterceptorClient('localhost:'.$this->port, [
+            'credentials' => Grpc\ChannelCredentials::createInsecure(),
+        ], $intercept_channel3);
+
+        $req = new SimpleRequest($req_text);
+        $unary_call = $client->UnaryCall($req);
+        $event = $this->server->requestCall();
+        $this->assertSame('/dummy_method', $event->method);
+        $this->assertSame(['interceptor_from_unary_request'], $event->metadata['foo']);
+        $this->assertSame(['interceptor_from_unary_request'], $event->metadata['bar']);
+
+        $stream_call = $client->StreamCall();
+        $stream_call->write($req);
+        $event = $this->server->requestCall();
+        $this->assertSame('/dummy_method', $event->method);
+        $this->assertSame(['interceptor_from_stream_request'], $event->metadata['foo']);
+        $this->assertSame(['interceptor_from_stream_request'], $event->metadata['bar']);
+
+        unset($unary_call);
+        unset($stream_call);
+        unset($server_call);
+    }
+
+    public function testClientChangeRequestInterceptor()
+    {
+        $req_text = 'client_request';
+        $change_request_interceptor = new ChangeRequestInterceptor();
+        $intercept_channel = Grpc\Interceptor::intercept($this->channel,
+            $change_request_interceptor);
+        $client = new InterceptorClient('localhost:'.$this->port, [
+            'credentials' => Grpc\ChannelCredentials::createInsecure(),
+        ], $intercept_channel);
+
+        $req = new SimpleRequest($req_text);
+        $unary_call = $client->UnaryCall($req);
+
+        $event = $this->server->requestCall();
+        $this->assertSame('/dummy_method', $event->method);
+        $server_call = $event->call;
+        $event = $server_call->startBatch([
+            Grpc\OP_SEND_INITIAL_METADATA => [],
+            Grpc\OP_SEND_STATUS_FROM_SERVER => [
+                'metadata' => [],
+                'code' => Grpc\STATUS_OK,
+                'details' => '',
+            ],
+            Grpc\OP_RECV_MESSAGE => true,
+            Grpc\OP_RECV_CLOSE_ON_SERVER => true,
+        ]);
+        $this->assertSame('intercepted_unary_request', $event->message);
+
+        $stream_call = $client->StreamCall();
+        $stream_call->write($req);
+        $event = $this->server->requestCall();
+        $this->assertSame('/dummy_method', $event->method);
+        $server_call = $event->call;
+        $event = $server_call->startBatch([
+            Grpc\OP_SEND_INITIAL_METADATA => [],
+            Grpc\OP_SEND_STATUS_FROM_SERVER => [
+                'metadata' => [],
+                'code' => Grpc\STATUS_OK,
+                'details' => '',
+            ],
+            Grpc\OP_RECV_MESSAGE => true,
+            Grpc\OP_RECV_CLOSE_ON_SERVER => true,
+        ]);
+        $this->assertSame('intercepted_stream_request', $event->message);
+
+        unset($unary_call);
+        unset($stream_call);
+        unset($server_call);
+    }
+
+    public function testClientChangeStopCallInterceptor()
+    {
+        $req_text = 'client_request';
+        $channel_request_interceptor = new StopCallInterceptor();
+        $intercept_channel = Grpc\Interceptor::intercept($this->channel,
+            $channel_request_interceptor);
+        $client = new InterceptorClient('localhost:'.$this->port, [
+            'credentials' => Grpc\ChannelCredentials::createInsecure(),
+        ], $intercept_channel);
+
+        $req = new SimpleRequest($req_text);
+        $unary_call = $client->UnaryCall($req);
+        $this->assertNull($unary_call);
+
+
+        $stream_call = $client->StreamCall();
+        $this->assertNull($stream_call);
+
+        unset($unary_call);
+        unset($stream_call);
+        unset($server_call);
+    }
+
+    public function testGetInterceptorChannelConnectivityState()
+    {
+        $channel = new Grpc\Channel(
+            'localhost:0',
+            ['credentials' => Grpc\ChannelCredentials::createInsecure()]
+        );
+        $interceptor_channel = Grpc\Interceptor::intercept($channel, new Grpc\Interceptor());
+        $state = $interceptor_channel->getConnectivityState();
+        $this->assertEquals(0, $state);
+        $channel->close();
+    }
+
+    public function testInterceptorChannelWatchConnectivityState()
+    {
+        $channel = new Grpc\Channel(
+            'localhost:0',
+            ['credentials' => Grpc\ChannelCredentials::createInsecure()]
+        );
+        $interceptor_channel = Grpc\Interceptor::intercept($channel, new Grpc\Interceptor());
+        $now = Grpc\Timeval::now();
+        $deadline = $now->add(new Grpc\Timeval(100*1000));
+        $state = $interceptor_channel->watchConnectivityState(1, $deadline);
+        $this->assertTrue($state);
+        unset($time);
+        unset($deadline);
+        $channel->close();
+    }
+
+    public function testInterceptorChannelClose()
+    {
+        $channel = new Grpc\Channel(
+            'localhost:0',
+            ['credentials' => Grpc\ChannelCredentials::createInsecure()]
+        );
+        $interceptor_channel = Grpc\Interceptor::intercept($channel, new Grpc\Interceptor());
+        $this->assertNotNull($interceptor_channel);
+        $channel->close();
+    }
+
+    public function testInterceptorChannelGetTarget()
+    {
+        $channel = new Grpc\Channel(
+            'localhost:8888',
+            ['credentials' => Grpc\ChannelCredentials::createInsecure()]
+        );
+        $interceptor_channel = Grpc\Interceptor::intercept($channel, new Grpc\Interceptor());
+        $target = $interceptor_channel->getTarget();
+        $this->assertTrue(is_string($target));
+        $channel->close();
+    }
+}
diff --git a/src/php/tests/unit_tests/ServerTest.php b/src/php/tests/unit_tests/ServerTest.php
index fee9f1e..ac6f2f0 100644
--- a/src/php/tests/unit_tests/ServerTest.php
+++ b/src/php/tests/unit_tests/ServerTest.php
@@ -99,6 +99,24 @@
     /**
      * @expectedException InvalidArgumentException
      */
+    public function testInvalidConstructorWithNumKeyOfArray()
+    {
+        $this->server = new Grpc\Server([10 => '127.0.0.1',
+                                         20 => '8080', ]);
+        $this->assertNull($this->server);
+    }
+
+    /**
+     * @expectedException InvalidArgumentException
+     */
+    public function testInvalidConstructorWithList()
+    {
+        $this->server = new Grpc\Server(['127.0.0.1', '8080']);
+        $this->assertNull($this->server);
+    }
+    /**
+     * @expectedException InvalidArgumentException
+     */
     public function testInvalidAddHttp2Port()
     {
         $this->server = new Grpc\Server([]);
diff --git a/src/proto/grpc/health/v1/health.proto b/src/proto/grpc/health/v1/health.proto
index 3fda02c..4b4677b 100644
--- a/src/proto/grpc/health/v1/health.proto
+++ b/src/proto/grpc/health/v1/health.proto
@@ -1,4 +1,4 @@
-// Copyright 2015 gRPC authors.
+// Copyright 2015 The gRPC Authors
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -12,10 +12,18 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+// The canonical version of this proto can be found at
+// https://github.com/grpc/grpc-proto/blob/master/grpc/health/v1/health.proto
+
 syntax = "proto3";
 
 package grpc.health.v1;
+
 option csharp_namespace = "Grpc.Health.V1";
+option go_package = "google.golang.org/grpc/health/grpc_health_v1";
+option java_multiple_files = true;
+option java_outer_classname = "HealthProto";
+option java_package = "io.grpc.health.v1";
 
 message HealthCheckRequest {
   string service = 1;
diff --git a/src/proto/grpc/testing/BUILD b/src/proto/grpc/testing/BUILD
index 58412ed..16721ff 100644
--- a/src/proto/grpc/testing/BUILD
+++ b/src/proto/grpc/testing/BUILD
@@ -76,11 +76,26 @@
 )
 
 grpc_proto_library(
-    name = "services_proto",
-    srcs = ["services.proto"],
+    name = "benchmark_service_proto",
+    srcs = ["benchmark_service.proto"],
     deps = [
-        "control_proto",
-        "messages_proto",
+      "messages_proto",
+    ],
+)
+
+grpc_proto_library(
+    name = "report_qps_scenario_service_proto",
+    srcs = ["report_qps_scenario_service.proto"],
+    deps = [
+      "control_proto",
+    ],
+)
+
+grpc_proto_library(
+    name = "worker_service_proto",
+    srcs = ["worker_service.proto"],
+    deps = [
+      "control_proto",
     ],
 )
 
diff --git a/src/proto/grpc/testing/benchmark_service.proto b/src/proto/grpc/testing/benchmark_service.proto
new file mode 100644
index 0000000..63167a8
--- /dev/null
+++ b/src/proto/grpc/testing/benchmark_service.proto
@@ -0,0 +1,44 @@
+// Copyright 2015 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.
+
+// An integration test service that covers all the method signature permutations
+// of unary/streaming requests/responses.
+syntax = "proto3";
+
+import "src/proto/grpc/testing/messages.proto";
+
+package grpc.testing;
+
+service BenchmarkService {
+  // One request followed by one response.
+  // The server returns the client payload as-is.
+  rpc UnaryCall(SimpleRequest) returns (SimpleResponse);
+
+  // Repeated sequence of one request followed by one response.
+  // Should be called streaming ping-pong
+  // The server returns the client payload as-is on each response
+  rpc StreamingCall(stream SimpleRequest) returns (stream SimpleResponse);
+
+  // Single-sided unbounded streaming from client to server
+  // The server returns the client payload as-is once the client does WritesDone
+  rpc StreamingFromClient(stream SimpleRequest) returns (SimpleResponse);
+
+  // Single-sided unbounded streaming from server to client
+  // The server repeatedly returns the client payload as-is
+  rpc StreamingFromServer(SimpleRequest) returns (stream SimpleResponse);
+
+  // Two-sided unbounded streaming between server to client
+  // Both sides send the content of their own choice to the other
+  rpc StreamingBothWays(stream SimpleRequest) returns (stream SimpleResponse);
+}
diff --git a/src/proto/grpc/testing/report_qps_scenario_service.proto b/src/proto/grpc/testing/report_qps_scenario_service.proto
new file mode 100644
index 0000000..f4e5c36
--- /dev/null
+++ b/src/proto/grpc/testing/report_qps_scenario_service.proto
@@ -0,0 +1,26 @@
+// Copyright 2015 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.
+
+// An integration test service that covers all the method signature permutations
+// of unary/streaming requests/responses.
+syntax = "proto3";
+
+import "src/proto/grpc/testing/control.proto";
+
+package grpc.testing;
+
+service ReportQpsScenarioService {
+  // Report results of a QPS test benchmark scenario.
+  rpc ReportScenario(ScenarioResult) returns (Void);
+}
diff --git a/src/proto/grpc/testing/services.proto b/src/proto/grpc/testing/services.proto
deleted file mode 100644
index 93c21f4..0000000
--- a/src/proto/grpc/testing/services.proto
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2015 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.
-
-// An integration test service that covers all the method signature permutations
-// of unary/streaming requests/responses.
-syntax = "proto3";
-
-import "src/proto/grpc/testing/messages.proto";
-import "src/proto/grpc/testing/control.proto";
-
-package grpc.testing;
-
-service BenchmarkService {
-  // One request followed by one response.
-  // The server returns the client payload as-is.
-  rpc UnaryCall(SimpleRequest) returns (SimpleResponse);
-
-  // Repeated sequence of one request followed by one response.
-  // Should be called streaming ping-pong
-  // The server returns the client payload as-is on each response
-  rpc StreamingCall(stream SimpleRequest) returns (stream SimpleResponse);
-
-  // Single-sided unbounded streaming from client to server
-  // The server returns the client payload as-is once the client does WritesDone
-  rpc StreamingFromClient(stream SimpleRequest) returns (SimpleResponse);
-
-  // Single-sided unbounded streaming from server to client
-  // The server repeatedly returns the client payload as-is
-  rpc StreamingFromServer(SimpleRequest) returns (stream SimpleResponse);
-
-  // Two-sided unbounded streaming between server to client
-  // Both sides send the content of their own choice to the other
-  rpc StreamingBothWays(stream SimpleRequest) returns (stream SimpleResponse);
-}
-
-service WorkerService {
-  // Start server with specified workload.
-  // First request sent specifies the ServerConfig followed by ServerStatus
-  // response. After that, a "Mark" can be sent anytime to request the latest
-  // stats. Closing the stream will initiate shutdown of the test server
-  // and once the shutdown has finished, the OK status is sent to terminate
-  // this RPC.
-  rpc RunServer(stream ServerArgs) returns (stream ServerStatus);
-
-  // Start client with specified workload.
-  // First request sent specifies the ClientConfig followed by ClientStatus
-  // response. After that, a "Mark" can be sent anytime to request the latest
-  // stats. Closing the stream will initiate shutdown of the test client
-  // and once the shutdown has finished, the OK status is sent to terminate
-  // this RPC.
-  rpc RunClient(stream ClientArgs) returns (stream ClientStatus);
-
-  // Just return the core count - unary call
-  rpc CoreCount(CoreRequest) returns (CoreResponse);
-
-  // Quit this worker
-  rpc QuitWorker(Void) returns (Void);
-}
-
-service ReportQpsScenarioService {
-  // Report results of a QPS test benchmark scenario.
-  rpc ReportScenario(ScenarioResult) returns (Void);
-}
diff --git a/src/proto/grpc/testing/worker_service.proto b/src/proto/grpc/testing/worker_service.proto
new file mode 100644
index 0000000..a4cde94
--- /dev/null
+++ b/src/proto/grpc/testing/worker_service.proto
@@ -0,0 +1,45 @@
+// Copyright 2015 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.
+
+// An integration test service that covers all the method signature permutations
+// of unary/streaming requests/responses.
+syntax = "proto3";
+
+import "src/proto/grpc/testing/control.proto";
+
+package grpc.testing;
+
+service WorkerService {
+  // Start server with specified workload.
+  // First request sent specifies the ServerConfig followed by ServerStatus
+  // response. After that, a "Mark" can be sent anytime to request the latest
+  // stats. Closing the stream will initiate shutdown of the test server
+  // and once the shutdown has finished, the OK status is sent to terminate
+  // this RPC.
+  rpc RunServer(stream ServerArgs) returns (stream ServerStatus);
+
+  // Start client with specified workload.
+  // First request sent specifies the ClientConfig followed by ClientStatus
+  // response. After that, a "Mark" can be sent anytime to request the latest
+  // stats. Closing the stream will initiate shutdown of the test client
+  // and once the shutdown has finished, the OK status is sent to terminate
+  // this RPC.
+  rpc RunClient(stream ClientArgs) returns (stream ClientStatus);
+
+  // Just return the core count - unary call
+  rpc CoreCount(CoreRequest) returns (CoreResponse);
+
+  // Quit this worker
+  rpc QuitWorker(Void) returns (Void);
+}
diff --git a/src/python/grpcio/grpc/__init__.py b/src/python/grpcio/grpc/__init__.py
index 7fa7303..b7ed0c8 100644
--- a/src/python/grpcio/grpc/__init__.py
+++ b/src/python/grpcio/grpc/__init__.py
@@ -813,7 +813,11 @@
 
 
 class Channel(six.with_metaclass(abc.ABCMeta)):
-    """Affords RPC invocation via generic methods on client-side."""
+    """Affords RPC invocation via generic methods on client-side.
+
+    Channel objects implement the Context Manager type, although they need not
+    support being entered and exited multiple times.
+    """
 
     @abc.abstractmethod
     def subscribe(self, callback, try_to_connect=False):
@@ -926,6 +930,17 @@
         """
         raise NotImplementedError()
 
+    @abc.abstractmethod
+    def close(self):
+        """Closes this Channel and releases all resources held by it.
+
+        Closing the Channel will immediately terminate all RPCs active with the
+        Channel and it is not valid to invoke new RPCs with the Channel.
+
+        This method is idempotent.
+        """
+        raise NotImplementedError()
+
 
 ##########################  Service-Side Context  ##############################
 
diff --git a/src/python/grpcio/grpc/_channel.py b/src/python/grpcio/grpc/_channel.py
index 2eff08a..8cc0e98 100644
--- a/src/python/grpcio/grpc/_channel.py
+++ b/src/python/grpcio/grpc/_channel.py
@@ -79,27 +79,6 @@
             condition.wait(timeout=remaining)
 
 
-_INTERNAL_CALL_ERROR_MESSAGE_FORMAT = (
-    'Internal gRPC call error %d. ' +
-    'Please report to https://github.com/grpc/grpc/issues')
-
-
-def _check_call_error(call_error, metadata):
-    if call_error == cygrpc.CallError.invalid_metadata:
-        raise ValueError('metadata was invalid: %s' % metadata)
-    elif call_error != cygrpc.CallError.ok:
-        raise ValueError(_INTERNAL_CALL_ERROR_MESSAGE_FORMAT % call_error)
-
-
-def _call_error_set_RPCstate(state, call_error, metadata):
-    if call_error == cygrpc.CallError.invalid_metadata:
-        _abort(state, grpc.StatusCode.INTERNAL,
-               'metadata was invalid: %s' % metadata)
-    else:
-        _abort(state, grpc.StatusCode.INTERNAL,
-               _INTERNAL_CALL_ERROR_MESSAGE_FORMAT % call_error)
-
-
 class _RPCState(object):
 
     def __init__(self, due, initial_metadata, trailing_metadata, code, details):
@@ -163,7 +142,7 @@
     return callbacks
 
 
-def _event_handler(state, call, response_deserializer):
+def _event_handler(state, response_deserializer):
 
     def handle_event(event):
         with state.condition:
@@ -172,40 +151,47 @@
             done = not state.due
         for callback in callbacks:
             callback()
-        return call if done else None
+        return done
 
     return handle_event
 
 
-def _consume_request_iterator(request_iterator, state, call,
-                              request_serializer):
-    event_handler = _event_handler(state, call, None)
+def _consume_request_iterator(request_iterator, state, call, request_serializer,
+                              event_handler):
 
-    def consume_request_iterator():
+    def consume_request_iterator():  # pylint: disable=too-many-branches
         while True:
             try:
                 request = next(request_iterator)
             except StopIteration:
                 break
             except Exception:  # pylint: disable=broad-except
-                logging.exception("Exception iterating requests!")
-                call.cancel()
-                _abort(state, grpc.StatusCode.UNKNOWN,
-                       "Exception iterating requests!")
+                code = grpc.StatusCode.UNKNOWN
+                details = 'Exception iterating requests!'
+                logging.exception(details)
+                call.cancel(_common.STATUS_CODE_TO_CYGRPC_STATUS_CODE[code],
+                            details)
+                _abort(state, code, details)
                 return
             serialized_request = _common.serialize(request, request_serializer)
             with state.condition:
                 if state.code is None and not state.cancelled:
                     if serialized_request is None:
-                        call.cancel()
+                        code = grpc.StatusCode.INTERNAL  # pylint: disable=redefined-variable-type
                         details = 'Exception serializing request!'
-                        _abort(state, grpc.StatusCode.INTERNAL, details)
+                        call.cancel(
+                            _common.STATUS_CODE_TO_CYGRPC_STATUS_CODE[code],
+                            details)
+                        _abort(state, code, details)
                         return
                     else:
                         operations = (cygrpc.SendMessageOperation(
                             serialized_request, _EMPTY_FLAGS),)
-                        call.start_client_batch(operations, event_handler)
-                        state.due.add(cygrpc.OperationType.send_message)
+                        operating = call.operate(operations, event_handler)
+                        if operating:
+                            state.due.add(cygrpc.OperationType.send_message)
+                        else:
+                            return
                         while True:
                             state.condition.wait()
                             if state.code is None:
@@ -219,19 +205,12 @@
             if state.code is None:
                 operations = (
                     cygrpc.SendCloseFromClientOperation(_EMPTY_FLAGS),)
-                call.start_client_batch(operations, event_handler)
-                state.due.add(cygrpc.OperationType.send_close_from_client)
+                operating = call.operate(operations, event_handler)
+                if operating:
+                    state.due.add(cygrpc.OperationType.send_close_from_client)
 
-    def stop_consumption_thread(timeout):  # pylint: disable=unused-argument
-        with state.condition:
-            if state.code is None:
-                call.cancel()
-                state.cancelled = True
-                _abort(state, grpc.StatusCode.CANCELLED, 'Cancelled!')
-                state.condition.notify_all()
-
-    consumption_thread = _common.CleanupThread(
-        stop_consumption_thread, target=consume_request_iterator)
+    consumption_thread = threading.Thread(target=consume_request_iterator)
+    consumption_thread.daemon = True
     consumption_thread.start()
 
 
@@ -247,9 +226,12 @@
     def cancel(self):
         with self._state.condition:
             if self._state.code is None:
-                self._call.cancel()
+                code = grpc.StatusCode.CANCELLED
+                details = 'Locally cancelled by application!'
+                self._call.cancel(
+                    _common.STATUS_CODE_TO_CYGRPC_STATUS_CODE[code], details)
                 self._state.cancelled = True
-                _abort(self._state, grpc.StatusCode.CANCELLED, 'Cancelled!')
+                _abort(self._state, code, details)
                 self._state.condition.notify_all()
             return False
 
@@ -318,12 +300,13 @@
     def _next(self):
         with self._state.condition:
             if self._state.code is None:
-                event_handler = _event_handler(self._state, self._call,
+                event_handler = _event_handler(self._state,
                                                self._response_deserializer)
-                self._call.start_client_batch(
+                operating = self._call.operate(
                     (cygrpc.ReceiveMessageOperation(_EMPTY_FLAGS),),
                     event_handler)
-                self._state.due.add(cygrpc.OperationType.receive_message)
+                if operating:
+                    self._state.due.add(cygrpc.OperationType.receive_message)
             elif self._state.code is grpc.StatusCode.OK:
                 raise StopIteration()
             else:
@@ -408,9 +391,12 @@
     def __del__(self):
         with self._state.condition:
             if self._state.code is None:
-                self._call.cancel()
-                self._state.cancelled = True
                 self._state.code = grpc.StatusCode.CANCELLED
+                self._state.details = 'Cancelled upon garbage collection!'
+                self._state.cancelled = True
+                self._call.cancel(
+                    _common.STATUS_CODE_TO_CYGRPC_STATUS_CODE[self._state.code],
+                    self._state.details)
                 self._state.condition.notify_all()
 
 
@@ -437,6 +423,24 @@
         raise _Rendezvous(state, None, None, deadline)
 
 
+def _stream_unary_invocation_operationses(metadata):
+    return (
+        (
+            cygrpc.SendInitialMetadataOperation(metadata, _EMPTY_FLAGS),
+            cygrpc.ReceiveMessageOperation(_EMPTY_FLAGS),
+            cygrpc.ReceiveStatusOnClientOperation(_EMPTY_FLAGS),
+        ),
+        (cygrpc.ReceiveInitialMetadataOperation(_EMPTY_FLAGS),),
+    )
+
+
+def _stream_unary_invocation_operationses_and_tags(metadata):
+    return tuple((
+        operations,
+        None,
+    ) for operations in _stream_unary_invocation_operationses(metadata))
+
+
 class _UnaryUnaryMultiCallable(grpc.UnaryUnaryMultiCallable):
 
     def __init__(self, channel, managed_call, method, request_serializer,
@@ -448,8 +452,8 @@
         self._response_deserializer = response_deserializer
 
     def _prepare(self, request, timeout, metadata):
-        deadline, serialized_request, rendezvous = (_start_unary_request(
-            request, timeout, self._request_serializer))
+        deadline, serialized_request, rendezvous = _start_unary_request(
+            request, timeout, self._request_serializer)
         if serialized_request is None:
             return None, None, None, rendezvous
         else:
@@ -467,48 +471,38 @@
     def _blocking(self, request, timeout, metadata, credentials):
         state, operations, deadline, rendezvous = self._prepare(
             request, timeout, metadata)
-        if rendezvous:
+        if state is None:
             raise rendezvous
         else:
-            completion_queue = cygrpc.CompletionQueue()
-            call = self._channel.create_call(None, 0, completion_queue,
-                                             self._method, None, deadline)
-            if credentials is not None:
-                call.set_credentials(credentials._credentials)
-            call_error = call.start_client_batch(operations, None)
-            _check_call_error(call_error, metadata)
-            _handle_event(completion_queue.poll(), state,
-                          self._response_deserializer)
-            return state, call, deadline
+            call = self._channel.segregated_call(
+                0, self._method, None, deadline, metadata, None
+                if credentials is None else credentials._credentials, ((
+                    operations,
+                    None,
+                ),))
+            event = call.next_event()
+            _handle_event(event, state, self._response_deserializer)
+            return state, call,
 
     def __call__(self, request, timeout=None, metadata=None, credentials=None):
-        state, call, deadline = self._blocking(request, timeout, metadata,
-                                               credentials)
-        return _end_unary_response_blocking(state, call, False, deadline)
+        state, call, = self._blocking(request, timeout, metadata, credentials)
+        return _end_unary_response_blocking(state, call, False, None)
 
     def with_call(self, request, timeout=None, metadata=None, credentials=None):
-        state, call, deadline = self._blocking(request, timeout, metadata,
-                                               credentials)
-        return _end_unary_response_blocking(state, call, True, deadline)
+        state, call, = self._blocking(request, timeout, metadata, credentials)
+        return _end_unary_response_blocking(state, call, True, None)
 
     def future(self, request, timeout=None, metadata=None, credentials=None):
         state, operations, deadline, rendezvous = self._prepare(
             request, timeout, metadata)
-        if rendezvous:
-            return rendezvous
+        if state is None:
+            raise rendezvous
         else:
-            call, drive_call = self._managed_call(None, 0, self._method, None,
-                                                  deadline)
-            if credentials is not None:
-                call.set_credentials(credentials._credentials)
-            event_handler = _event_handler(state, call,
-                                           self._response_deserializer)
-            with state.condition:
-                call_error = call.start_client_batch(operations, event_handler)
-                if call_error != cygrpc.CallError.ok:
-                    _call_error_set_RPCstate(state, call_error, metadata)
-                    return _Rendezvous(state, None, None, deadline)
-                drive_call()
+            event_handler = _event_handler(state, self._response_deserializer)
+            call = self._managed_call(
+                0, self._method, None, deadline, metadata, None
+                if credentials is None else credentials._credentials,
+                (operations,), event_handler)
             return _Rendezvous(state, call, self._response_deserializer,
                                deadline)
 
@@ -524,34 +518,27 @@
         self._response_deserializer = response_deserializer
 
     def __call__(self, request, timeout=None, metadata=None, credentials=None):
-        deadline, serialized_request, rendezvous = (_start_unary_request(
-            request, timeout, self._request_serializer))
+        deadline, serialized_request, rendezvous = _start_unary_request(
+            request, timeout, self._request_serializer)
         if serialized_request is None:
             raise rendezvous
         else:
             state = _RPCState(_UNARY_STREAM_INITIAL_DUE, None, None, None, None)
-            call, drive_call = self._managed_call(None, 0, self._method, None,
-                                                  deadline)
-            if credentials is not None:
-                call.set_credentials(credentials._credentials)
-            event_handler = _event_handler(state, call,
-                                           self._response_deserializer)
-            with state.condition:
-                call.start_client_batch(
-                    (cygrpc.ReceiveInitialMetadataOperation(_EMPTY_FLAGS),),
-                    event_handler)
-                operations = (
+            operationses = (
+                (
                     cygrpc.SendInitialMetadataOperation(metadata, _EMPTY_FLAGS),
                     cygrpc.SendMessageOperation(serialized_request,
                                                 _EMPTY_FLAGS),
                     cygrpc.SendCloseFromClientOperation(_EMPTY_FLAGS),
                     cygrpc.ReceiveStatusOnClientOperation(_EMPTY_FLAGS),
-                )
-                call_error = call.start_client_batch(operations, event_handler)
-                if call_error != cygrpc.CallError.ok:
-                    _call_error_set_RPCstate(state, call_error, metadata)
-                    return _Rendezvous(state, None, None, deadline)
-                drive_call()
+                ),
+                (cygrpc.ReceiveInitialMetadataOperation(_EMPTY_FLAGS),),
+            )
+            event_handler = _event_handler(state, self._response_deserializer)
+            call = self._managed_call(
+                0, self._method, None, deadline, metadata, None
+                if credentials is None else credentials._credentials,
+                operationses, event_handler)
             return _Rendezvous(state, call, self._response_deserializer,
                                deadline)
 
@@ -569,49 +556,38 @@
     def _blocking(self, request_iterator, timeout, metadata, credentials):
         deadline = _deadline(timeout)
         state = _RPCState(_STREAM_UNARY_INITIAL_DUE, None, None, None, None)
-        completion_queue = cygrpc.CompletionQueue()
-        call = self._channel.create_call(None, 0, completion_queue,
-                                         self._method, None, deadline)
-        if credentials is not None:
-            call.set_credentials(credentials._credentials)
-        with state.condition:
-            call.start_client_batch(
-                (cygrpc.ReceiveInitialMetadataOperation(_EMPTY_FLAGS),), None)
-            operations = (
-                cygrpc.SendInitialMetadataOperation(metadata, _EMPTY_FLAGS),
-                cygrpc.ReceiveMessageOperation(_EMPTY_FLAGS),
-                cygrpc.ReceiveStatusOnClientOperation(_EMPTY_FLAGS),
-            )
-            call_error = call.start_client_batch(operations, None)
-            _check_call_error(call_error, metadata)
-            _consume_request_iterator(request_iterator, state, call,
-                                      self._request_serializer)
+        call = self._channel.segregated_call(
+            0, self._method, None, deadline, metadata, None
+            if credentials is None else credentials._credentials,
+            _stream_unary_invocation_operationses_and_tags(metadata))
+        _consume_request_iterator(request_iterator, state, call,
+                                  self._request_serializer, None)
         while True:
-            event = completion_queue.poll()
+            event = call.next_event()
             with state.condition:
                 _handle_event(event, state, self._response_deserializer)
                 state.condition.notify_all()
                 if not state.due:
                     break
-        return state, call, deadline
+        return state, call,
 
     def __call__(self,
                  request_iterator,
                  timeout=None,
                  metadata=None,
                  credentials=None):
-        state, call, deadline = self._blocking(request_iterator, timeout,
-                                               metadata, credentials)
-        return _end_unary_response_blocking(state, call, False, deadline)
+        state, call, = self._blocking(request_iterator, timeout, metadata,
+                                      credentials)
+        return _end_unary_response_blocking(state, call, False, None)
 
     def with_call(self,
                   request_iterator,
                   timeout=None,
                   metadata=None,
                   credentials=None):
-        state, call, deadline = self._blocking(request_iterator, timeout,
-                                               metadata, credentials)
-        return _end_unary_response_blocking(state, call, True, deadline)
+        state, call, = self._blocking(request_iterator, timeout, metadata,
+                                      credentials)
+        return _end_unary_response_blocking(state, call, True, None)
 
     def future(self,
                request_iterator,
@@ -620,27 +596,13 @@
                credentials=None):
         deadline = _deadline(timeout)
         state = _RPCState(_STREAM_UNARY_INITIAL_DUE, None, None, None, None)
-        call, drive_call = self._managed_call(None, 0, self._method, None,
-                                              deadline)
-        if credentials is not None:
-            call.set_credentials(credentials._credentials)
-        event_handler = _event_handler(state, call, self._response_deserializer)
-        with state.condition:
-            call.start_client_batch(
-                (cygrpc.ReceiveInitialMetadataOperation(_EMPTY_FLAGS),),
-                event_handler)
-            operations = (
-                cygrpc.SendInitialMetadataOperation(metadata, _EMPTY_FLAGS),
-                cygrpc.ReceiveMessageOperation(_EMPTY_FLAGS),
-                cygrpc.ReceiveStatusOnClientOperation(_EMPTY_FLAGS),
-            )
-            call_error = call.start_client_batch(operations, event_handler)
-            if call_error != cygrpc.CallError.ok:
-                _call_error_set_RPCstate(state, call_error, metadata)
-                return _Rendezvous(state, None, None, deadline)
-            drive_call()
-            _consume_request_iterator(request_iterator, state, call,
-                                      self._request_serializer)
+        event_handler = _event_handler(state, self._response_deserializer)
+        call = self._managed_call(
+            0, self._method, None, deadline, metadata, None
+            if credentials is None else credentials._credentials,
+            _stream_unary_invocation_operationses(metadata), event_handler)
+        _consume_request_iterator(request_iterator, state, call,
+                                  self._request_serializer, event_handler)
         return _Rendezvous(state, call, self._response_deserializer, deadline)
 
 
@@ -661,26 +623,20 @@
                  credentials=None):
         deadline = _deadline(timeout)
         state = _RPCState(_STREAM_STREAM_INITIAL_DUE, None, None, None, None)
-        call, drive_call = self._managed_call(None, 0, self._method, None,
-                                              deadline)
-        if credentials is not None:
-            call.set_credentials(credentials._credentials)
-        event_handler = _event_handler(state, call, self._response_deserializer)
-        with state.condition:
-            call.start_client_batch(
-                (cygrpc.ReceiveInitialMetadataOperation(_EMPTY_FLAGS),),
-                event_handler)
-            operations = (
+        operationses = (
+            (
                 cygrpc.SendInitialMetadataOperation(metadata, _EMPTY_FLAGS),
                 cygrpc.ReceiveStatusOnClientOperation(_EMPTY_FLAGS),
-            )
-            call_error = call.start_client_batch(operations, event_handler)
-            if call_error != cygrpc.CallError.ok:
-                _call_error_set_RPCstate(state, call_error, metadata)
-                return _Rendezvous(state, None, None, deadline)
-            drive_call()
-            _consume_request_iterator(request_iterator, state, call,
-                                      self._request_serializer)
+            ),
+            (cygrpc.ReceiveInitialMetadataOperation(_EMPTY_FLAGS),),
+        )
+        event_handler = _event_handler(state, self._response_deserializer)
+        call = self._managed_call(
+            0, self._method, None, deadline, metadata, None
+            if credentials is None else credentials._credentials, operationses,
+            event_handler)
+        _consume_request_iterator(request_iterator, state, call,
+                                  self._request_serializer, event_handler)
         return _Rendezvous(state, call, self._response_deserializer, deadline)
 
 
@@ -689,67 +645,63 @@
     def __init__(self, channel):
         self.lock = threading.Lock()
         self.channel = channel
-        self.completion_queue = cygrpc.CompletionQueue()
-        self.managed_calls = None
+        self.managed_calls = 0
 
 
 def _run_channel_spin_thread(state):
 
     def channel_spin():
         while True:
-            event = state.completion_queue.poll()
-            completed_call = event.tag(event)
-            if completed_call is not None:
+            event = state.channel.next_call_event()
+            call_completed = event.tag(event)
+            if call_completed:
                 with state.lock:
-                    state.managed_calls.remove(completed_call)
-                    if not state.managed_calls:
-                        state.managed_calls = None
+                    state.managed_calls -= 1
+                    if state.managed_calls == 0:
                         return
 
-    def stop_channel_spin(timeout):  # pylint: disable=unused-argument
-        with state.lock:
-            if state.managed_calls is not None:
-                for call in state.managed_calls:
-                    call.cancel()
-
-    channel_spin_thread = _common.CleanupThread(
-        stop_channel_spin, target=channel_spin)
+    channel_spin_thread = threading.Thread(target=channel_spin)
+    channel_spin_thread.daemon = True
     channel_spin_thread.start()
 
 
 def _channel_managed_call_management(state):
 
-    def create(parent, flags, method, host, deadline):
-        """Creates a managed cygrpc.Call and a function to call to drive it.
+    # pylint: disable=too-many-arguments
+    def create(flags, method, host, deadline, metadata, credentials,
+               operationses, event_handler):
+        """Creates a cygrpc.IntegratedCall.
 
-    If operations are successfully added to the returned cygrpc.Call, the
-    returned function must be called. If operations are not successfully added
-    to the returned cygrpc.Call, the returned function must not be called.
+        Args:
+          flags: An integer bitfield of call flags.
+          method: The RPC method.
+          host: A host string for the created call.
+          deadline: A float to be the deadline of the created call or None if
+            the call is to have an infinite deadline.
+          metadata: The metadata for the call or None.
+          credentials: A cygrpc.CallCredentials or None.
+          operationses: An iterable of iterables of cygrpc.Operations to be
+            started on the call.
+          event_handler: A behavior to call to handle the events resultant from
+            the operations on the call.
 
-    Args:
-      parent: A cygrpc.Call to be used as the parent of the created call.
-      flags: An integer bitfield of call flags.
-      method: The RPC method.
-      host: A host string for the created call.
-      deadline: A float to be the deadline of the created call or None if the
-        call is to have an infinite deadline.
-
-    Returns:
-      A cygrpc.Call with which to conduct an RPC and a function to call if
-        operations are successfully started on the call.
-    """
-        call = state.channel.create_call(parent, flags, state.completion_queue,
-                                         method, host, deadline)
-
-        def drive():
-            with state.lock:
-                if state.managed_calls is None:
-                    state.managed_calls = set((call,))
-                    _run_channel_spin_thread(state)
-                else:
-                    state.managed_calls.add(call)
-
-        return call, drive
+        Returns:
+          A cygrpc.IntegratedCall with which to conduct an RPC.
+        """
+        operationses_and_tags = tuple((
+            operations,
+            event_handler,
+        ) for operations in operationses)
+        with state.lock:
+            call = state.channel.integrated_call(flags, method, host, deadline,
+                                                 metadata, credentials,
+                                                 operationses_and_tags)
+            if state.managed_calls == 0:
+                state.managed_calls = 1
+                _run_channel_spin_thread(state)
+            else:
+                state.managed_calls += 1
+            return call
 
     return create
 
@@ -819,12 +771,9 @@
             callback_and_connectivity[1] = state.connectivity
         if callbacks:
             _spawn_delivery(state, callbacks)
-    completion_queue = cygrpc.CompletionQueue()
     while True:
-        channel.watch_connectivity_state(connectivity,
-                                         time.time() + 0.2, completion_queue,
-                                         None)
-        event = completion_queue.poll()
+        event = channel.watch_connectivity_state(connectivity,
+                                                 time.time() + 0.2)
         with state.lock:
             if not state.callbacks_and_connectivities and not state.try_to_connect:
                 state.polling = False
@@ -855,10 +804,10 @@
 def _subscribe(state, callback, try_to_connect):
     with state.lock:
         if not state.callbacks_and_connectivities and not state.polling:
-            polling_thread = _common.CleanupThread(
-                lambda timeout: _moot(state),
+            polling_thread = threading.Thread(
                 target=_poll_connectivity,
                 args=(state, state.channel, bool(try_to_connect)))
+            polling_thread.daemon = True
             polling_thread.start()
             state.polling = True
             state.callbacks_and_connectivities.append([callback, None])
@@ -944,5 +893,28 @@
             self._channel, _channel_managed_call_management(self._call_state),
             _common.encode(method), request_serializer, response_deserializer)
 
+    def _close(self):
+        self._channel.close(cygrpc.StatusCode.cancelled, 'Channel closed!')
+        _moot(self._connectivity_state)
+
+    def __enter__(self):
+        return self
+
+    def __exit__(self, exc_type, exc_val, exc_tb):
+        self._close()
+        return False
+
+    def close(self):
+        self._close()
+
     def __del__(self):
+        # TODO(https://github.com/grpc/grpc/issues/12531): Several releases
+        # after 1.12 (1.16 or thereabouts?) add a "self._channel.close" call
+        # here (or more likely, call self._close() here). We don't do this today
+        # because many valid use cases today allow the channel to be deleted
+        # immediately after stubs are created. After a sufficient period of time
+        # has passed for all users to be trusted to hang out to their channels
+        # for as long as they are in use and to close them after using them,
+        # then deletion of this grpc._channel.Channel instance can be made to
+        # effect closure of the underlying cygrpc.Channel instance.
         _moot(self._connectivity_state)
diff --git a/src/python/grpcio/grpc/_common.py b/src/python/grpcio/grpc/_common.py
index bbb69ad..862987a 100644
--- a/src/python/grpcio/grpc/_common.py
+++ b/src/python/grpcio/grpc/_common.py
@@ -14,8 +14,6 @@
 """Shared implementation."""
 
 import logging
-import threading
-import time
 
 import six
 
@@ -101,35 +99,3 @@
 
 def fully_qualified_method(group, method):
     return '/{}/{}'.format(group, method)
-
-
-class CleanupThread(threading.Thread):
-    """A threading.Thread subclass supporting custom behavior on join().
-
-    On Python Interpreter exit, Python will attempt to join outstanding threads
-    prior to garbage collection.  We may need to do additional cleanup, and
-    we accomplish this by overriding the join() method.
-    """
-
-    def __init__(self, behavior, *args, **kwargs):
-        """Constructor.
-
-        Args:
-            behavior (function): Function called on join() with a single
-                argument, timeout, indicating the maximum duration of
-                `behavior`, or None indicating `behavior` has no deadline.
-                `behavior` must be idempotent.
-            args: Positional arguments passed to threading.Thread constructor.
-            kwargs: Keyword arguments passed to threading.Thread constructor.
-        """
-        super(CleanupThread, self).__init__(*args, **kwargs)
-        self._behavior = behavior
-
-    def join(self, timeout=None):
-        start_time = time.time()
-        self._behavior(timeout)
-        end_time = time.time()
-        if timeout is not None:
-            timeout -= end_time - start_time
-            timeout = max(timeout, 0)
-        super(CleanupThread, self).join(timeout)
diff --git a/src/python/grpcio/grpc/_cython/.gitignore b/src/python/grpcio/grpc/_cython/.gitignore
index 306e3ad..b9936e9 100644
--- a/src/python/grpcio/grpc/_cython/.gitignore
+++ b/src/python/grpcio/grpc/_cython/.gitignore
@@ -1,4 +1,4 @@
-cygrpc.c
+cygrpc.cpp
 *.a
 *.so
 *.dll
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/channel.pxd.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/channel.pxd.pxi
index 1ba76b7..eefc685 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/channel.pxd.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/channel.pxd.pxi
@@ -13,9 +13,59 @@
 # limitations under the License.
 
 
+cdef _check_call_error_no_metadata(c_call_error)
+
+
+cdef _check_and_raise_call_error_no_metadata(c_call_error)
+
+
+cdef _check_call_error(c_call_error, metadata)
+
+
+cdef class _CallState:
+
+  cdef grpc_call *c_call
+  cdef set due
+
+
+cdef class _ChannelState:
+
+  cdef object condition
+  cdef grpc_channel *c_channel
+  # A boolean field indicating that the channel is open (if True) or is being
+  # closed (i.e. a call to close is currently executing) or is closed (if
+  # False).
+  # TODO(https://github.com/grpc/grpc/issues/3064): Eliminate "is being closed"
+  # a state in which condition may be acquired by any thread, eliminate this
+  # field and just use the NULLness of c_channel as an indication that the
+  # channel is closed.
+  cdef object open
+
+  # A dict from _BatchOperationTag to _CallState
+  cdef dict integrated_call_states
+  cdef grpc_completion_queue *c_call_completion_queue
+
+  # A set of _CallState
+  cdef set segregated_call_states
+
+  cdef set connectivity_due
+  cdef grpc_completion_queue *c_connectivity_completion_queue
+
+
+cdef class IntegratedCall:
+
+  cdef _ChannelState _channel_state
+  cdef _CallState _call_state
+
+
+cdef class SegregatedCall:
+
+  cdef _ChannelState _channel_state
+  cdef _CallState _call_state
+  cdef grpc_completion_queue *_c_completion_queue
+
+
 cdef class Channel:
 
   cdef grpc_arg_pointer_vtable _vtable
-  cdef grpc_channel *c_channel
-  cdef list references
-  cdef readonly _ArgumentsProcessor _arguments_processor
+  cdef _ChannelState _state
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi
index a396649..72e74e8 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx.pxi
@@ -14,82 +14,439 @@
 
 cimport cpython
 
+import threading
+
+_INTERNAL_CALL_ERROR_MESSAGE_FORMAT = (
+    'Internal gRPC call error %d. ' +
+    'Please report to https://github.com/grpc/grpc/issues')
+
+
+cdef str _call_error_metadata(metadata):
+  return 'metadata was invalid: %s' % metadata
+
+
+cdef str _call_error_no_metadata(c_call_error):
+  return _INTERNAL_CALL_ERROR_MESSAGE_FORMAT % c_call_error
+
+
+cdef str _call_error(c_call_error, metadata):
+  if c_call_error == GRPC_CALL_ERROR_INVALID_METADATA:
+    return _call_error_metadata(metadata)
+  else:
+    return _call_error_no_metadata(c_call_error)
+
+
+cdef _check_call_error_no_metadata(c_call_error):
+  if c_call_error != GRPC_CALL_OK:
+    return _INTERNAL_CALL_ERROR_MESSAGE_FORMAT % c_call_error
+  else:
+    return None
+
+
+cdef _check_and_raise_call_error_no_metadata(c_call_error):
+  error = _check_call_error_no_metadata(c_call_error)
+  if error is not None:
+    raise ValueError(error)
+
+
+cdef _check_call_error(c_call_error, metadata):
+  if c_call_error == GRPC_CALL_ERROR_INVALID_METADATA:
+    return _call_error_metadata(metadata)
+  else:
+    return _check_call_error_no_metadata(c_call_error)
+
+
+cdef void _raise_call_error_no_metadata(c_call_error) except *:
+  raise ValueError(_call_error_no_metadata(c_call_error))
+
+
+cdef void _raise_call_error(c_call_error, metadata) except *:
+  raise ValueError(_call_error(c_call_error, metadata))
+
+
+cdef _destroy_c_completion_queue(grpc_completion_queue *c_completion_queue):
+  grpc_completion_queue_shutdown(c_completion_queue)
+  grpc_completion_queue_destroy(c_completion_queue)
+
+
+cdef class _CallState:
+
+  def __cinit__(self):
+    self.due = set()
+
+
+cdef class _ChannelState:
+
+  def __cinit__(self):
+    self.condition = threading.Condition()
+    self.open = True
+    self.integrated_call_states = {}
+    self.segregated_call_states = set()
+    self.connectivity_due = set()
+
+
+cdef tuple _operate(grpc_call *c_call, object operations, object user_tag):
+  cdef grpc_call_error c_call_error
+  cdef _BatchOperationTag tag = _BatchOperationTag(user_tag, operations, None)
+  tag.prepare()
+  cpython.Py_INCREF(tag)
+  with nogil:
+    c_call_error = grpc_call_start_batch(
+        c_call, tag.c_ops, tag.c_nops, <cpython.PyObject *>tag, NULL)
+  return c_call_error, tag
+
+
+cdef object _operate_from_integrated_call(
+    _ChannelState channel_state, _CallState call_state, object operations,
+    object user_tag):
+  cdef grpc_call_error c_call_error
+  cdef _BatchOperationTag tag
+  with channel_state.condition:
+    if call_state.due:
+      c_call_error, tag = _operate(call_state.c_call, operations, user_tag)
+      if c_call_error == GRPC_CALL_OK:
+        call_state.due.add(tag)
+        channel_state.integrated_call_states[tag] = call_state
+        return True
+      else:
+        _raise_call_error_no_metadata(c_call_error)
+    else:
+      return False
+
+
+cdef object _operate_from_segregated_call(
+    _ChannelState channel_state, _CallState call_state, object operations,
+    object user_tag):
+  cdef grpc_call_error c_call_error
+  cdef _BatchOperationTag tag
+  with channel_state.condition:
+    if call_state.due:
+      c_call_error, tag = _operate(call_state.c_call, operations, user_tag)
+      if c_call_error == GRPC_CALL_OK:
+        call_state.due.add(tag)
+        return True
+      else:
+        _raise_call_error_no_metadata(c_call_error)
+    else:
+      return False
+
+
+cdef _cancel(
+    _ChannelState channel_state, _CallState call_state, grpc_status_code code,
+    str details):
+  cdef grpc_call_error c_call_error
+  with channel_state.condition:
+    if call_state.due:
+      c_call_error = grpc_call_cancel_with_status(
+          call_state.c_call, code, _encode(details), NULL)
+      _check_and_raise_call_error_no_metadata(c_call_error)
+
+
+cdef BatchOperationEvent _next_call_event(
+    _ChannelState channel_state, grpc_completion_queue *c_completion_queue,
+    on_success):
+  tag, event = _latent_event(c_completion_queue, None)
+  with channel_state.condition:
+    on_success(tag)
+    channel_state.condition.notify_all()
+  return event
+
+
+# TODO(https://github.com/grpc/grpc/issues/14569): This could be a lot simpler.
+cdef void _call(
+    _ChannelState channel_state, _CallState call_state,
+    grpc_completion_queue *c_completion_queue, on_success, int flags, method,
+    host, object deadline, CallCredentials credentials,
+    object operationses_and_user_tags, object metadata) except *:
+  """Invokes an RPC.
+
+  Args:
+    channel_state: A _ChannelState with its "open" attribute set to True. RPCs
+      may not be invoked on a closed channel.
+    call_state: An empty _CallState to be altered (specifically assigned a
+      c_call and having its due set populated) if the RPC invocation is
+      successful.
+    c_completion_queue: A grpc_completion_queue to be used for the call's
+      operations.
+    on_success: A behavior to be called if attempting to start operations for
+      the call succeeds. If called the behavior will be called while holding the
+      channel_state condition and passed the tags associated with operations
+      that were successfully started for the call.
+    flags: Flags to be passed to gRPC Core as part of call creation.
+    method: The fully-qualified name of the RPC method being invoked.
+    host: A "host" string to be passed to gRPC Core as part of call creation.
+    deadline: A float for the deadline of the RPC, or None if the RPC is to have
+      no deadline.
+    credentials: A _CallCredentials for the RPC or None.
+    operationses_and_user_tags: A sequence of length-two sequences the first
+      element of which is a sequence of Operations and the second element of
+      which is an object to be used as a tag. A SendInitialMetadataOperation
+      must be present in the first element of this value.
+    metadata: The metadata for this call.
+  """
+  cdef grpc_slice method_slice
+  cdef grpc_slice host_slice
+  cdef grpc_slice *host_slice_ptr
+  cdef grpc_call_credentials *c_call_credentials
+  cdef grpc_call_error c_call_error
+  cdef tuple error_and_wrapper_tag
+  cdef _BatchOperationTag wrapper_tag
+  with channel_state.condition:
+    if channel_state.open:
+      method_slice = _slice_from_bytes(method)
+      if host is None:
+        host_slice_ptr = NULL
+      else:
+        host_slice = _slice_from_bytes(host)
+        host_slice_ptr = &host_slice
+      call_state.c_call = grpc_channel_create_call(
+          channel_state.c_channel, NULL, flags,
+          c_completion_queue, method_slice, host_slice_ptr,
+          _timespec_from_time(deadline), NULL)
+      grpc_slice_unref(method_slice)
+      if host_slice_ptr:
+        grpc_slice_unref(host_slice)
+      if credentials is not None:
+        c_call_credentials = credentials.c()
+        c_call_error = grpc_call_set_credentials(
+            call_state.c_call, c_call_credentials)
+        grpc_call_credentials_release(c_call_credentials)
+        if c_call_error != GRPC_CALL_OK:
+          grpc_call_unref(call_state.c_call)
+          call_state.c_call = NULL
+          _raise_call_error_no_metadata(c_call_error)
+      started_tags = set()
+      for operations, user_tag in operationses_and_user_tags:
+        c_call_error, tag = _operate(call_state.c_call, operations, user_tag)
+        if c_call_error == GRPC_CALL_OK:
+          started_tags.add(tag)
+        else:
+          grpc_call_cancel(call_state.c_call, NULL)
+          grpc_call_unref(call_state.c_call)
+          call_state.c_call = NULL
+          _raise_call_error(c_call_error, metadata)
+      else:
+        call_state.due.update(started_tags)
+        on_success(started_tags)
+    else:
+      raise ValueError('Cannot invoke RPC on closed channel!')
+
+cdef void _process_integrated_call_tag(
+    _ChannelState state, _BatchOperationTag tag) except *:
+  cdef _CallState call_state = state.integrated_call_states.pop(tag)
+  call_state.due.remove(tag)
+  if not call_state.due:
+    grpc_call_unref(call_state.c_call)
+    call_state.c_call = NULL
+
+
+cdef class IntegratedCall:
+
+  def __cinit__(self, _ChannelState channel_state, _CallState call_state):
+    self._channel_state = channel_state
+    self._call_state = call_state
+
+  def operate(self, operations, tag):
+    return _operate_from_integrated_call(
+        self._channel_state, self._call_state, operations, tag)
+
+  def cancel(self, code, details):
+    _cancel(self._channel_state, self._call_state, code, details)
+
+
+cdef IntegratedCall _integrated_call(
+    _ChannelState state, int flags, method, host, object deadline,
+    object metadata, CallCredentials credentials, operationses_and_user_tags):
+  call_state = _CallState()
+
+  def on_success(started_tags):
+    for started_tag in started_tags:
+      state.integrated_call_states[started_tag] = call_state
+
+  _call(
+      state, call_state, state.c_call_completion_queue, on_success, flags,
+      method, host, deadline, credentials, operationses_and_user_tags, metadata)
+
+  return IntegratedCall(state, call_state)
+
+
+cdef object _process_segregated_call_tag(
+    _ChannelState state, _CallState call_state,
+    grpc_completion_queue *c_completion_queue, _BatchOperationTag tag):
+  call_state.due.remove(tag)
+  if not call_state.due:
+    grpc_call_unref(call_state.c_call)
+    call_state.c_call = NULL
+    state.segregated_call_states.remove(call_state)
+    _destroy_c_completion_queue(c_completion_queue)
+    return True
+  else:
+    return False
+
+
+cdef class SegregatedCall:
+
+  def __cinit__(self, _ChannelState channel_state, _CallState call_state):
+    self._channel_state = channel_state
+    self._call_state = call_state
+
+  def operate(self, operations, tag):
+    return _operate_from_segregated_call(
+        self._channel_state, self._call_state, operations, tag)
+
+  def cancel(self, code, details):
+    _cancel(self._channel_state, self._call_state, code, details)
+
+  def next_event(self):
+    def on_success(tag):
+      _process_segregated_call_tag(
+          self._channel_state, self._call_state, self._c_completion_queue, tag)
+    return _next_call_event(
+        self._channel_state, self._c_completion_queue, on_success)
+
+
+cdef SegregatedCall _segregated_call(
+    _ChannelState state, int flags, method, host, object deadline,
+    object metadata, CallCredentials credentials, operationses_and_user_tags):
+  cdef _CallState call_state = _CallState()
+  cdef grpc_completion_queue *c_completion_queue = (
+      grpc_completion_queue_create_for_next(NULL))
+  cdef SegregatedCall segregated_call
+
+  def on_success(started_tags):
+    state.segregated_call_states.add(call_state)
+
+  try:
+    _call(
+        state, call_state, c_completion_queue, on_success, flags, method, host,
+        deadline, credentials, operationses_and_user_tags, metadata)
+  except:
+    _destroy_c_completion_queue(c_completion_queue)
+    raise
+
+  segregated_call = SegregatedCall(state, call_state)
+  segregated_call._c_completion_queue = c_completion_queue
+  return segregated_call
+
+
+cdef object _watch_connectivity_state(
+    _ChannelState state, grpc_connectivity_state last_observed_state,
+    object deadline):
+  cdef _ConnectivityTag tag = _ConnectivityTag(object())
+  with state.condition:
+    if state.open:
+      cpython.Py_INCREF(tag)
+      grpc_channel_watch_connectivity_state(
+          state.c_channel, last_observed_state, _timespec_from_time(deadline),
+          state.c_connectivity_completion_queue, <cpython.PyObject *>tag)
+      state.connectivity_due.add(tag)
+    else:
+      raise ValueError('Cannot invoke RPC on closed channel!')
+  completed_tag, event = _latent_event(
+      state.c_connectivity_completion_queue, None)
+  with state.condition:
+    state.connectivity_due.remove(completed_tag)
+    state.condition.notify_all()
+  return event
+
+
+cdef _close(_ChannelState state, grpc_status_code code, object details):
+  cdef _CallState call_state
+  encoded_details = _encode(details)
+  with state.condition:
+    if state.open:
+      state.open = False
+      for call_state in set(state.integrated_call_states.values()):
+        grpc_call_cancel_with_status(
+            call_state.c_call, code, encoded_details, NULL)
+      for call_state in state.segregated_call_states:
+        grpc_call_cancel_with_status(
+            call_state.c_call, code, encoded_details, NULL)
+      # TODO(https://github.com/grpc/grpc/issues/3064): Cancel connectivity
+      # watching.
+
+      while state.integrated_call_states:
+        state.condition.wait()
+      while state.segregated_call_states:
+        state.condition.wait()
+      while state.connectivity_due:
+        state.condition.wait()
+
+      _destroy_c_completion_queue(state.c_call_completion_queue)
+      _destroy_c_completion_queue(state.c_connectivity_completion_queue)
+      grpc_channel_destroy(state.c_channel)
+      state.c_channel = NULL
+      grpc_shutdown()
+      state.condition.notify_all()
+    else:
+      # Another call to close already completed in the past or is currently
+      # being executed in another thread.
+      while state.c_channel != NULL:
+        state.condition.wait()
+
 
 cdef class Channel:
 
-  def __cinit__(self, bytes target, object arguments,
-                ChannelCredentials channel_credentials=None):
+  def __cinit__(
+      self, bytes target, object arguments,
+      ChannelCredentials channel_credentials):
     grpc_init()
+    self._state = _ChannelState()
     self._vtable.copy = &_copy_pointer
     self._vtable.destroy = &_destroy_pointer
     self._vtable.cmp = &_compare_pointer
     cdef _ArgumentsProcessor arguments_processor = _ArgumentsProcessor(
         arguments)
     cdef grpc_channel_args *c_arguments = arguments_processor.c(&self._vtable)
-    self.references = []
-    c_target = target
     if channel_credentials is None:
-      self.c_channel = grpc_insecure_channel_create(c_target, c_arguments, NULL)
+      self._state.c_channel = grpc_insecure_channel_create(
+          <char *>target, c_arguments, NULL)
     else:
       c_channel_credentials = channel_credentials.c()
-      self.c_channel = grpc_secure_channel_create(
-          c_channel_credentials, c_target, c_arguments, NULL)
+      self._state.c_channel = grpc_secure_channel_create(
+          c_channel_credentials, <char *>target, c_arguments, NULL)
       grpc_channel_credentials_release(c_channel_credentials)
-    arguments_processor.un_c()
-    self.references.append(target)
-    self.references.append(arguments)
-
-  def create_call(self, Call parent, int flags,
-                  CompletionQueue queue not None,
-                  method, host, object deadline):
-    if queue.is_shutting_down:
-      raise ValueError("queue must not be shutting down or shutdown")
-    cdef grpc_slice method_slice = _slice_from_bytes(method)
-    cdef grpc_slice host_slice
-    cdef grpc_slice *host_slice_ptr = NULL
-    if host is not None:
-      host_slice = _slice_from_bytes(host)
-      host_slice_ptr = &host_slice
-    cdef Call operation_call = Call()
-    operation_call.references = [self, queue]
-    cdef grpc_call *parent_call = NULL
-    if parent is not None:
-      parent_call = parent.c_call
-    operation_call.c_call = grpc_channel_create_call(
-        self.c_channel, parent_call, flags,
-        queue.c_completion_queue, method_slice, host_slice_ptr,
-        _timespec_from_time(deadline), NULL)
-    grpc_slice_unref(method_slice)
-    if host_slice_ptr:
-      grpc_slice_unref(host_slice)
-    return operation_call
-
-  def check_connectivity_state(self, bint try_to_connect):
-    cdef grpc_connectivity_state result
-    with nogil:
-      result = grpc_channel_check_connectivity_state(self.c_channel,
-                                                     try_to_connect)
-    return result
-
-  def watch_connectivity_state(
-      self, grpc_connectivity_state last_observed_state,
-      object deadline, CompletionQueue queue not None, tag):
-    cdef _ConnectivityTag connectivity_tag = _ConnectivityTag(tag)
-    cpython.Py_INCREF(connectivity_tag)
-    grpc_channel_watch_connectivity_state(
-        self.c_channel, last_observed_state, _timespec_from_time(deadline),
-        queue.c_completion_queue, <cpython.PyObject *>connectivity_tag)
+    self._state.c_call_completion_queue = (
+        grpc_completion_queue_create_for_next(NULL))
+    self._state.c_connectivity_completion_queue = (
+        grpc_completion_queue_create_for_next(NULL))
 
   def target(self):
-    cdef char *target = NULL
-    with nogil:
-      target = grpc_channel_get_target(self.c_channel)
-    result = <bytes>target
-    with nogil:
-      gpr_free(target)
-    return result
+    cdef char *c_target
+    with self._state.condition:
+      c_target = grpc_channel_get_target(self._state.c_channel)
+      target = <bytes>c_target
+      gpr_free(c_target)
+      return target
 
-  def __dealloc__(self):
-    if self.c_channel != NULL:
-      grpc_channel_destroy(self.c_channel)
-    grpc_shutdown()
+  def integrated_call(
+      self, int flags, method, host, object deadline, object metadata,
+      CallCredentials credentials, operationses_and_tags):
+    return _integrated_call(
+        self._state, flags, method, host, deadline, metadata, credentials,
+        operationses_and_tags)
+
+  def next_call_event(self):
+    def on_success(tag):
+      _process_integrated_call_tag(self._state, tag)
+    return _next_call_event(
+        self._state, self._state.c_call_completion_queue, on_success)
+
+  def segregated_call(
+      self, int flags, method, host, object deadline, object metadata,
+      CallCredentials credentials, operationses_and_tags):
+    return _segregated_call(
+        self._state, flags, method, host, deadline, metadata, credentials,
+        operationses_and_tags)
+
+  def check_connectivity_state(self, bint try_to_connect):
+    with self._state.condition:
+      return grpc_channel_check_connectivity_state(
+          self._state.c_channel, try_to_connect)
+
+  def watch_connectivity_state(
+      self, grpc_connectivity_state last_observed_state, object deadline):
+    return _watch_connectivity_state(self._state, last_observed_state, deadline)
+
+  def close(self, code, details):
+    _close(self._state, code, details)
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pxd.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pxd.pxi
index 5ea0287..9f06ce0 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pxd.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pxd.pxi
@@ -13,10 +13,16 @@
 # limitations under the License.
 
 
+cdef grpc_event _next(grpc_completion_queue *c_completion_queue, deadline)
+
+
+cdef _interpret_event(grpc_event c_event)
+
+
 cdef class CompletionQueue:
 
   cdef grpc_completion_queue *c_completion_queue
   cdef bint is_shutting_down
   cdef bint is_shutdown
 
-  cdef _interpret_event(self, grpc_event event)
+  cdef _interpret_event(self, grpc_event c_event)
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi b/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi
index 40496d1..a2d7655 100644
--- a/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx.pxi
@@ -20,6 +20,53 @@
 cdef int _INTERRUPT_CHECK_PERIOD_MS = 200
 
 
+cdef grpc_event _next(grpc_completion_queue *c_completion_queue, deadline):
+  cdef gpr_timespec c_increment
+  cdef gpr_timespec c_timeout
+  cdef gpr_timespec c_deadline
+  c_increment = gpr_time_from_millis(_INTERRUPT_CHECK_PERIOD_MS, GPR_TIMESPAN)
+  if deadline is None:
+    c_deadline = gpr_inf_future(GPR_CLOCK_REALTIME)
+  else:
+    c_deadline = _timespec_from_time(deadline)
+
+  with nogil:
+    while True:
+      c_timeout = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), c_increment)
+      if gpr_time_cmp(c_timeout, c_deadline) > 0:
+        c_timeout = c_deadline
+      c_event = grpc_completion_queue_next(c_completion_queue, c_timeout, NULL)
+      if (c_event.type != GRPC_QUEUE_TIMEOUT or
+          gpr_time_cmp(c_timeout, c_deadline) == 0):
+        break
+
+      # Handle any signals
+      with gil:
+        cpython.PyErr_CheckSignals()
+  return c_event
+
+
+cdef _interpret_event(grpc_event c_event):
+  cdef _Tag tag
+  if c_event.type == GRPC_QUEUE_TIMEOUT:
+    # NOTE(nathaniel): For now we coopt ConnectivityEvent here.
+    return None, ConnectivityEvent(GRPC_QUEUE_TIMEOUT, False, None)
+  elif c_event.type == GRPC_QUEUE_SHUTDOWN:
+    # NOTE(nathaniel): For now we coopt ConnectivityEvent here.
+    return None, ConnectivityEvent(GRPC_QUEUE_SHUTDOWN, False, None)
+  else:
+    tag = <_Tag>c_event.tag
+    # We receive event tags only after they've been inc-ref'd elsewhere in
+    # the code.
+    cpython.Py_DECREF(tag)
+    return tag, tag.event(c_event)
+
+
+cdef _latent_event(grpc_completion_queue *c_completion_queue, object deadline):
+  cdef grpc_event c_event = _next(c_completion_queue, deadline)
+  return _interpret_event(c_event)
+
+
 cdef class CompletionQueue:
 
   def __cinit__(self, shutdown_cq=False):
@@ -36,48 +83,16 @@
     self.is_shutting_down = False
     self.is_shutdown = False
 
-  cdef _interpret_event(self, grpc_event event):
-    cdef _Tag tag = None
-    if event.type == GRPC_QUEUE_TIMEOUT:
-      # NOTE(nathaniel): For now we coopt ConnectivityEvent here.
-      return ConnectivityEvent(GRPC_QUEUE_TIMEOUT, False, None)
-    elif event.type == GRPC_QUEUE_SHUTDOWN:
+  cdef _interpret_event(self, grpc_event c_event):
+    unused_tag, event = _interpret_event(c_event)
+    if event.completion_type == GRPC_QUEUE_SHUTDOWN:
       self.is_shutdown = True
-      # NOTE(nathaniel): For now we coopt ConnectivityEvent here.
-      return ConnectivityEvent(GRPC_QUEUE_TIMEOUT, True, None)
-    else:
-      tag = <_Tag>event.tag
-      # We receive event tags only after they've been inc-ref'd elsewhere in
-      # the code.
-      cpython.Py_DECREF(tag)
-      return tag.event(event)
+    return event
 
+  # We name this 'poll' to avoid problems with CPython's expectations for
+  # 'special' methods (like next and __next__).
   def poll(self, deadline=None):
-    # We name this 'poll' to avoid problems with CPython's expectations for
-    # 'special' methods (like next and __next__).
-    cdef gpr_timespec c_increment
-    cdef gpr_timespec c_timeout
-    cdef gpr_timespec c_deadline
-    if deadline is None:
-      c_deadline = gpr_inf_future(GPR_CLOCK_REALTIME)
-    else:
-      c_deadline = _timespec_from_time(deadline)
-    with nogil:
-      c_increment = gpr_time_from_millis(_INTERRUPT_CHECK_PERIOD_MS, GPR_TIMESPAN)
-
-      while True:
-        c_timeout = gpr_time_add(gpr_now(GPR_CLOCK_REALTIME), c_increment)
-        if gpr_time_cmp(c_timeout, c_deadline) > 0:
-          c_timeout = c_deadline
-        event = grpc_completion_queue_next(
-          self.c_completion_queue, c_timeout, NULL)
-        if event.type != GRPC_QUEUE_TIMEOUT or gpr_time_cmp(c_timeout, c_deadline) == 0:
-          break;
-
-        # Handle any signals
-        with gil:
-          cpython.PyErr_CheckSignals()
-    return self._interpret_event(event)
+    return self._interpret_event(_next(self.c_completion_queue, deadline))
 
   def shutdown(self):
     with nogil:
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/grpc_gevent.pxd b/src/python/grpcio/grpc/_cython/_cygrpc/grpc_gevent.pxd
new file mode 100644
index 0000000..f5688d0
--- /dev/null
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/grpc_gevent.pxd
@@ -0,0 +1,152 @@
+# Copyright 2017 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.
+# distutils: language=c++
+
+from libc.stdint cimport uint32_t
+
+cdef extern from "grpc/impl/codegen/slice.h":
+  struct grpc_slice_buffer:
+    int count
+
+cdef extern from "src/core/lib/iomgr/error.h":
+  struct grpc_error:
+    pass
+
+cdef extern from "src/core/lib/iomgr/gevent_util.h":
+  grpc_error* grpc_socket_error(char* error) 
+  char* grpc_slice_buffer_start(grpc_slice_buffer* buffer, int i)
+  int grpc_slice_buffer_length(grpc_slice_buffer* buffer, int i)
+
+cdef extern from "src/core/lib/iomgr/sockaddr.h":
+  ctypedef struct grpc_sockaddr:
+    pass
+
+cdef extern from "src/core/lib/iomgr/resolve_address.h":
+  ctypedef struct grpc_resolved_addresses:
+    size_t naddrs
+    grpc_resolved_address* addrs
+
+  ctypedef struct grpc_resolved_address:
+    char[128] addr
+    size_t len
+
+cdef extern from "src/core/lib/iomgr/resolve_address_custom.h":
+  struct grpc_custom_resolver:
+    pass
+
+  struct grpc_custom_resolver_vtable:
+    grpc_error* (*resolve)(char* host, char* port, grpc_resolved_addresses** res);
+    void (*resolve_async)(grpc_custom_resolver* resolver, char* host, char* port);
+
+  void grpc_custom_resolve_callback(grpc_custom_resolver* resolver,
+                                    grpc_resolved_addresses* result,
+                                    grpc_error* error);
+
+cdef extern from "src/core/lib/iomgr/tcp_custom.h":
+  struct grpc_custom_socket:
+    void* impl
+    # We don't care about the rest of the fields
+  ctypedef void (*grpc_custom_connect_callback)(grpc_custom_socket* socket,
+                                             grpc_error* error)
+  ctypedef void (*grpc_custom_write_callback)(grpc_custom_socket* socket,
+                                           grpc_error* error)
+  ctypedef void (*grpc_custom_read_callback)(grpc_custom_socket* socket,
+                                          size_t nread, grpc_error* error)
+  ctypedef void (*grpc_custom_accept_callback)(grpc_custom_socket* socket,
+                                            grpc_custom_socket* client,
+                                            grpc_error* error)
+  ctypedef void (*grpc_custom_close_callback)(grpc_custom_socket* socket)
+
+  struct grpc_socket_vtable:
+      grpc_error* (*init)(grpc_custom_socket* socket, int domain);
+      void (*connect)(grpc_custom_socket* socket, const grpc_sockaddr* addr,
+                      size_t len, grpc_custom_connect_callback cb);
+      void (*destroy)(grpc_custom_socket* socket);
+      void (*shutdown)(grpc_custom_socket* socket);
+      void (*close)(grpc_custom_socket* socket, grpc_custom_close_callback cb);
+      void (*write)(grpc_custom_socket* socket, grpc_slice_buffer* slices,
+                    grpc_custom_write_callback cb);
+      void (*read)(grpc_custom_socket* socket, char* buffer, size_t length,
+                   grpc_custom_read_callback cb);
+      grpc_error* (*getpeername)(grpc_custom_socket* socket,
+                                 const grpc_sockaddr* addr, int* len);
+      grpc_error* (*getsockname)(grpc_custom_socket* socket,
+                             const grpc_sockaddr* addr, int* len);
+      grpc_error* (*bind)(grpc_custom_socket* socket, const grpc_sockaddr* addr,
+                          size_t len, int flags);
+      grpc_error* (*listen)(grpc_custom_socket* socket);
+      void (*accept)(grpc_custom_socket* socket, grpc_custom_socket* client,
+                     grpc_custom_accept_callback cb);
+
+cdef extern from "src/core/lib/iomgr/timer_custom.h":
+  struct grpc_custom_timer:
+    void* timer
+    int timeout_ms
+     # We don't care about the rest of the fields
+
+  struct grpc_custom_timer_vtable:
+    void (*start)(grpc_custom_timer* t);
+    void (*stop)(grpc_custom_timer* t);
+
+  void grpc_custom_timer_callback(grpc_custom_timer* t, grpc_error* error);
+
+cdef extern from "src/core/lib/iomgr/pollset_custom.h":
+  struct grpc_custom_poller_vtable:
+    void (*init)()
+    void (*poll)(size_t timeout_ms)
+    void (*kick)()
+    void (*shutdown)()
+
+cdef extern from "src/core/lib/iomgr/iomgr_custom.h":
+  void grpc_custom_iomgr_init(grpc_socket_vtable* socket,
+                            grpc_custom_resolver_vtable* resolver,
+                            grpc_custom_timer_vtable* timer,
+                            grpc_custom_poller_vtable* poller);
+
+cdef extern from "src/core/lib/iomgr/sockaddr_utils.h":
+  int grpc_sockaddr_get_port(const grpc_resolved_address *addr);
+  int grpc_sockaddr_to_string(char **out, const grpc_resolved_address *addr,
+                              int normalize);
+  void grpc_string_to_sockaddr(grpc_resolved_address *out, char* addr, int port);
+  int grpc_sockaddr_set_port(const grpc_resolved_address *resolved_addr,
+                             int port)
+  const char* grpc_sockaddr_get_uri_scheme(const grpc_resolved_address* resolved_addr)
+
+
+cdef class TimerWrapper:
+
+  cdef grpc_custom_timer *c_timer
+  cdef object timer
+  cdef object event
+
+cdef class SocketWrapper:
+  cdef object sockopts
+  cdef object socket
+  cdef object closed
+  cdef grpc_custom_socket *c_socket
+  cdef char* c_buffer
+  cdef size_t len
+  cdef grpc_custom_socket *accepting_socket
+
+  cdef grpc_custom_connect_callback connect_cb
+  cdef grpc_custom_write_callback write_cb
+  cdef grpc_custom_read_callback read_cb
+  cdef grpc_custom_accept_callback accept_cb
+  cdef grpc_custom_close_callback close_cb
+
+
+cdef class ResolveWrapper:
+  cdef grpc_custom_resolver *c_resolver
+  cdef char* c_host
+  cdef char* c_port
diff --git a/src/python/grpcio/grpc/_cython/_cygrpc/grpc_gevent.pyx b/src/python/grpcio/grpc/_cython/_cygrpc/grpc_gevent.pyx
new file mode 100644
index 0000000..31ef671
--- /dev/null
+++ b/src/python/grpcio/grpc/_cython/_cygrpc/grpc_gevent.pyx
@@ -0,0 +1,448 @@
+# Copyright 2018 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.
+# distutils: language=c++
+
+cimport cpython
+from libc cimport string
+from libc.stdlib cimport malloc, free
+import errno
+gevent_g = None
+gevent_socket = None
+gevent_hub = None
+gevent_event = None
+g_event = None
+g_pool = None
+
+cdef grpc_error* grpc_error_none():
+  return <grpc_error*>0
+
+cdef grpc_error* socket_error(str syscall, str err):
+  error_str = "{} failed: {}".format(syscall, err)
+  error_bytes = str_to_bytes(error_str)
+  return grpc_socket_error(error_bytes)
+
+cdef resolved_addr_to_tuple(grpc_resolved_address* address):
+  cdef char* res_str
+  port = grpc_sockaddr_get_port(address)
+  str_len = grpc_sockaddr_to_string(&res_str, address, 0) 
+  byte_str = _decode(<bytes>res_str[:str_len])
+  if byte_str.endswith(':' + str(port)):
+    byte_str = byte_str[:(0 - len(str(port)) - 1)]
+  byte_str = byte_str.lstrip('[')
+  byte_str = byte_str.rstrip(']')
+  byte_str = '{}'.format(byte_str)
+  return byte_str, port
+
+cdef sockaddr_to_tuple(const grpc_sockaddr* address, size_t length):
+  cdef grpc_resolved_address c_addr
+  string.memcpy(<void*>c_addr.addr, <void*> address, length)
+  c_addr.len = length
+  return resolved_addr_to_tuple(&c_addr)
+
+cdef sockaddr_is_ipv4(const grpc_sockaddr* address, size_t length):
+  cdef grpc_resolved_address c_addr
+  string.memcpy(<void*>c_addr.addr, <void*> address, length)
+  c_addr.len = length
+  return grpc_sockaddr_get_uri_scheme(&c_addr) == b'ipv4'
+
+cdef grpc_resolved_addresses* tuples_to_resolvaddr(tups):
+  cdef grpc_resolved_addresses* addresses
+  tups_set = set((tup[4][0], tup[4][1]) for tup in tups)
+  addresses = <grpc_resolved_addresses*> malloc(sizeof(grpc_resolved_addresses))
+  addresses.naddrs = len(tups_set)
+  addresses.addrs = <grpc_resolved_address*> malloc(sizeof(grpc_resolved_address) * len(tups_set))
+  i = 0
+  for tup in set(tups_set):
+    hostname = str_to_bytes(tup[0])
+    grpc_string_to_sockaddr(&addresses.addrs[i], hostname, tup[1])
+    i += 1
+  return addresses
+
+def _spawn_greenlet(*args):
+  greenlet = g_pool.spawn(*args)
+
+###############################
+### socket implementation ###
+###############################
+
+cdef class SocketWrapper:
+  def __cinit__(self):
+    self.sockopts = []
+    self.socket = None
+    self.c_socket = NULL
+    self.c_buffer = NULL
+    self.len = 0
+
+cdef grpc_error* socket_init(grpc_custom_socket* socket, int domain) with gil:
+  sw = SocketWrapper()
+  sw.c_socket = socket
+  sw.sockopts = []
+  cpython.Py_INCREF(sw)
+  # Python doesn't support AF_UNSPEC sockets, so we defer creation until
+  # bind/connect when we know what type of socket we need
+  sw.socket = None
+  sw.closed = False
+  sw.accepting_socket = NULL
+  socket.impl = <void*>sw
+  return grpc_error_none()
+
+cdef socket_connect_async_cython(SocketWrapper socket_wrapper, addr_tuple):
+  try:
+    socket_wrapper.socket.connect(addr_tuple)
+    socket_wrapper.connect_cb(<grpc_custom_socket*>socket_wrapper.c_socket,
+                              grpc_error_none())
+  except IOError as io_error:
+    socket_wrapper.connect_cb(<grpc_custom_socket*>socket_wrapper.c_socket,
+                              socket_error("connect", str(io_error)))
+  g_event.set()
+
+def socket_connect_async(socket_wrapper, addr_tuple):
+  socket_connect_async_cython(socket_wrapper, addr_tuple)
+
+cdef void socket_connect(grpc_custom_socket* socket, const grpc_sockaddr* addr,
+                         size_t addr_len,
+                         grpc_custom_connect_callback cb) with gil:
+  py_socket = None
+  socket_wrapper = <SocketWrapper>socket.impl
+  socket_wrapper.connect_cb = cb
+  addr_tuple = sockaddr_to_tuple(addr, addr_len)
+  if sockaddr_is_ipv4(addr, addr_len):
+      py_socket = gevent_socket.socket(gevent_socket.AF_INET)
+  else:
+      py_socket = gevent_socket.socket(gevent_socket.AF_INET6)
+  applysockopts(py_socket)
+  socket_wrapper.socket = py_socket
+  _spawn_greenlet(socket_connect_async, socket_wrapper, addr_tuple)
+
+cdef void socket_destroy(grpc_custom_socket* socket) with gil:
+  cpython.Py_DECREF(<SocketWrapper>socket.impl)
+
+cdef void socket_shutdown(grpc_custom_socket* socket) with gil:
+  try:
+    (<SocketWrapper>socket.impl).socket.shutdown(gevent_socket.SHUT_RDWR)
+  except IOError as io_error:
+    if io_error.errno != errno.ENOTCONN:
+      raise io_error
+
+cdef void socket_close(grpc_custom_socket* socket,
+                       grpc_custom_close_callback cb) with gil:
+  socket_wrapper = (<SocketWrapper>socket.impl)
+  if socket_wrapper.socket is not None:
+    socket_wrapper.socket.close()
+    socket_wrapper.closed = True
+    socket_wrapper.close_cb = cb
+    # Delay the close callback until the accept() call has picked it up
+    if socket_wrapper.accepting_socket != NULL:
+      return
+  socket_wrapper.close_cb(socket)
+
+def socket_sendmsg(socket, write_bytes):
+  try:
+    return socket.sendmsg(write_bytes)
+  except AttributeError:
+    # sendmsg not available on all Pythons/Platforms
+    return socket.send(b''.join(write_bytes))
+
+cdef socket_write_async_cython(SocketWrapper socket_wrapper, write_bytes):
+  try:
+    while write_bytes:
+      sent_byte_count = socket_sendmsg(socket_wrapper.socket, write_bytes)
+      while sent_byte_count > 0:
+        if sent_byte_count < len(write_bytes[0]):
+          write_bytes[0] = write_bytes[0][sent_byte_count:]
+          sent_byte_count = 0
+        else:
+          sent_byte_count -= len(write_bytes[0])
+          write_bytes = write_bytes[1:]
+    socket_wrapper.write_cb(<grpc_custom_socket*>socket_wrapper.c_socket,
+                            grpc_error_none())
+  except IOError as io_error:
+    socket_wrapper.write_cb(<grpc_custom_socket*>socket_wrapper.c_socket,
+                            socket_error("send", str(io_error)))
+  g_event.set()
+
+def socket_write_async(socket_wrapper, write_bytes):
+  socket_write_async_cython(socket_wrapper, write_bytes)
+
+cdef void socket_write(grpc_custom_socket* socket, grpc_slice_buffer* buffer,
+                       grpc_custom_write_callback cb) with gil:
+  cdef char* start
+  sw = <SocketWrapper>socket.impl
+  sw.write_cb = cb
+  write_bytes = []
+  for i in range(buffer.count):
+    start = grpc_slice_buffer_start(buffer, i)
+    length = grpc_slice_buffer_length(buffer, i)
+    write_bytes.append(<bytes>start[:length])
+  _spawn_greenlet(socket_write_async, <SocketWrapper>socket.impl, write_bytes)
+
+cdef socket_read_async_cython(SocketWrapper socket_wrapper):
+  cdef char* buff_char_arr
+  try:
+    buff_str = socket_wrapper.socket.recv(socket_wrapper.len)
+    buff_char_arr = buff_str
+    string.memcpy(<void*>socket_wrapper.c_buffer, buff_char_arr, len(buff_str))
+    socket_wrapper.read_cb(<grpc_custom_socket*>socket_wrapper.c_socket,
+                           len(buff_str), grpc_error_none())
+  except IOError as io_error:
+    socket_wrapper.read_cb(<grpc_custom_socket*>socket_wrapper.c_socket,
+                           -1, socket_error("recv", str(io_error)))
+  g_event.set()
+
+def socket_read_async(socket_wrapper):
+  socket_read_async_cython(socket_wrapper)
+
+cdef void socket_read(grpc_custom_socket* socket, char* buffer,
+                      size_t length, grpc_custom_read_callback cb) with gil:
+  sw = <SocketWrapper>socket.impl
+  sw.read_cb = cb
+  sw.c_buffer = buffer
+  sw.len = length
+  _spawn_greenlet(socket_read_async, sw)
+
+cdef grpc_error* socket_getpeername(grpc_custom_socket* socket,
+                                    const grpc_sockaddr* addr,
+                                    int* length) with gil:
+  cdef char* src_buf
+  peer = (<SocketWrapper>socket.impl).socket.getpeername()
+
+  cdef grpc_resolved_address c_addr
+  hostname = str_to_bytes(peer[0])
+  grpc_string_to_sockaddr(&c_addr, hostname, peer[1])
+  string.memcpy(<void*>addr, <void*>c_addr.addr, c_addr.len)
+  length[0] = c_addr.len
+  return grpc_error_none()  
+
+cdef grpc_error* socket_getsockname(grpc_custom_socket* socket,
+                                    const grpc_sockaddr* addr,
+                                    int* length) with gil:
+  cdef char* src_buf
+  cdef grpc_resolved_address c_addr
+  if (<SocketWrapper>socket.impl).socket is None:
+    peer = ('0.0.0.0', 0)
+  else:
+    peer = (<SocketWrapper>socket.impl).socket.getsockname()
+  hostname = str_to_bytes(peer[0])
+  grpc_string_to_sockaddr(&c_addr, hostname, peer[1])
+  string.memcpy(<void*>addr, <void*>c_addr.addr, c_addr.len)
+  length[0] = c_addr.len
+  return grpc_error_none()
+
+def applysockopts(s):
+  s.setsockopt(gevent_socket.SOL_SOCKET, gevent_socket.SO_REUSEADDR, 1)
+  s.setsockopt(gevent_socket.IPPROTO_TCP, gevent_socket.TCP_NODELAY, True)
+
+cdef grpc_error* socket_bind(grpc_custom_socket* socket,
+                             const grpc_sockaddr* addr,
+                             size_t len, int flags) with gil:
+  addr_tuple = sockaddr_to_tuple(addr, len)
+  try:
+    try:
+      py_socket = gevent_socket.socket(gevent_socket.AF_INET)
+      applysockopts(py_socket)
+      py_socket.bind(addr_tuple)
+    except gevent_socket.gaierror as e:
+      py_socket = gevent_socket.socket(gevent_socket.AF_INET6)
+      applysockopts(py_socket)
+      py_socket.bind(addr_tuple)
+    (<SocketWrapper>socket.impl).socket = py_socket
+  except IOError as io_error:
+    return socket_error("bind", str(io_error))
+  else:
+    return grpc_error_none()
+
+cdef grpc_error* socket_listen(grpc_custom_socket* socket) with gil:
+  (<SocketWrapper>socket.impl).socket.listen(50)
+  return grpc_error_none()
+
+cdef void accept_callback_cython(SocketWrapper s):
+   try:
+     conn, address = s.socket.accept()
+     sw = SocketWrapper()
+     sw.closed = False
+     sw.c_socket = s.accepting_socket
+     sw.sockopts = []
+     sw.socket = conn
+     sw.c_socket.impl = <void*>sw
+     sw.accepting_socket = NULL
+     cpython.Py_INCREF(sw)
+     s.accepting_socket = NULL
+     s.accept_cb(<grpc_custom_socket*>s.c_socket, sw.c_socket, grpc_error_none())
+   except IOError as io_error:
+      #TODO actual error
+      s.accepting_socket = NULL
+      s.accept_cb(<grpc_custom_socket*>s.c_socket, s.accepting_socket,
+                  socket_error("accept", str(io_error)))
+      if s.closed:
+        s.close_cb(<grpc_custom_socket*>s.c_socket)
+   g_event.set()
+
+def socket_accept_async(s):
+  accept_callback_cython(s)
+
+cdef void socket_accept(grpc_custom_socket* socket, grpc_custom_socket* client,
+                        grpc_custom_accept_callback cb) with gil:
+  sw = <SocketWrapper>socket.impl
+  sw.accepting_socket = client
+  sw.accept_cb = cb
+  _spawn_greenlet(socket_accept_async, sw)
+
+#####################################
+######Resolver implementation #######
+#####################################
+
+cdef class ResolveWrapper:
+  def __cinit__(self):
+    self.c_resolver = NULL
+    self.c_host = NULL
+    self.c_port = NULL
+
+cdef socket_resolve_async_cython(ResolveWrapper resolve_wrapper):
+  try:
+    res = gevent_socket.getaddrinfo(resolve_wrapper.c_host, resolve_wrapper.c_port)
+    grpc_custom_resolve_callback(<grpc_custom_resolver*>resolve_wrapper.c_resolver,
+                                 tuples_to_resolvaddr(res), grpc_error_none())
+  except IOError as io_error:
+    grpc_custom_resolve_callback(<grpc_custom_resolver*>resolve_wrapper.c_resolver,
+                                 <grpc_resolved_addresses*>0,
+                                 socket_error("getaddrinfo", str(io_error)))
+  g_event.set()
+
+def socket_resolve_async_python(resolve_wrapper):
+  socket_resolve_async_cython(resolve_wrapper)
+
+cdef void socket_resolve_async(grpc_custom_resolver* r, char* host, char* port) with gil:
+  rw = ResolveWrapper()
+  rw.c_resolver = r
+  rw.c_host = host
+  rw.c_port = port
+  _spawn_greenlet(socket_resolve_async_python, rw)
+
+cdef grpc_error* socket_resolve(char* host, char* port,
+                                grpc_resolved_addresses** res) with gil:
+    try:
+      result = gevent_socket.getaddrinfo(host, port)
+      res[0] = tuples_to_resolvaddr(result)
+      return grpc_error_none()
+    except IOError as io_error:
+      return socket_error("getaddrinfo", str(io_error))
+
+###############################
+### timer implementation ######
+###############################
+
+cdef class TimerWrapper:
+  def __cinit__(self, deadline):
+    self.timer = gevent_hub.get_hub().loop.timer(deadline)
+    self.event = None
+
+  def start(self):
+    self.event = gevent_event.Event()
+    self.timer.start(self.on_finish)
+
+  def on_finish(self):
+    grpc_custom_timer_callback(self.c_timer, grpc_error_none())
+    self.timer.stop()
+    g_event.set()
+
+  def stop(self):
+    self.event.set()
+    self.timer.stop()
+
+cdef void timer_start(grpc_custom_timer* t) with gil:
+  timer = TimerWrapper(t.timeout_ms / 1000.0)
+  timer.c_timer = t
+  t.timer = <void*>timer
+  timer.start()
+
+cdef void timer_stop(grpc_custom_timer* t) with gil:
+  time_wrapper = <object>t.timer
+  time_wrapper.stop()
+
+###############################
+### pollset implementation ###
+###############################
+
+cdef void init_loop() with gil:
+  pass
+
+cdef void destroy_loop() with gil:
+  g_pool.join()
+
+cdef void kick_loop() with gil:
+  g_event.set()
+
+cdef void run_loop(size_t timeout_ms) with gil:
+    timeout = timeout_ms / 1000.0
+    if timeout_ms > 0:
+      g_event.wait(timeout)
+      g_event.clear()
+
+###############################
+### Initializer ###############
+###############################
+
+cdef grpc_socket_vtable gevent_socket_vtable
+cdef grpc_custom_resolver_vtable gevent_resolver_vtable
+cdef grpc_custom_timer_vtable gevent_timer_vtable
+cdef grpc_custom_poller_vtable gevent_pollset_vtable
+
+def init_grpc_gevent():
+  # Lazily import gevent
+  global gevent_socket
+  global gevent_g
+  global gevent_hub
+  global gevent_event
+  global g_event
+  global g_pool
+  import gevent
+  gevent_g = gevent
+  import gevent.socket
+  gevent_socket = gevent.socket
+  import gevent.hub
+  gevent_hub = gevent.hub
+  import gevent.event
+  gevent_event = gevent.event
+  import gevent.pool
+
+  g_event = gevent.event.Event()
+  g_pool = gevent.pool.Group()
+  gevent_resolver_vtable.resolve = socket_resolve
+  gevent_resolver_vtable.resolve_async = socket_resolve_async
+
+  gevent_socket_vtable.init = socket_init
+  gevent_socket_vtable.connect = socket_connect
+  gevent_socket_vtable.destroy = socket_destroy
+  gevent_socket_vtable.shutdown = socket_shutdown
+  gevent_socket_vtable.close = socket_close
+  gevent_socket_vtable.write = socket_write
+  gevent_socket_vtable.read = socket_read
+  gevent_socket_vtable.getpeername = socket_getpeername
+  gevent_socket_vtable.getsockname = socket_getsockname
+  gevent_socket_vtable.bind = socket_bind
+  gevent_socket_vtable.listen = socket_listen
+  gevent_socket_vtable.accept = socket_accept
+
+  gevent_timer_vtable.start = timer_start
+  gevent_timer_vtable.stop = timer_stop
+
+  gevent_pollset_vtable.init = init_loop
+  gevent_pollset_vtable.poll = run_loop
+  gevent_pollset_vtable.kick = kick_loop
+  gevent_pollset_vtable.shutdown = destroy_loop
+
+  grpc_custom_iomgr_init(&gevent_socket_vtable,
+                         &gevent_resolver_vtable,
+                         &gevent_timer_vtable,
+                         &gevent_pollset_vtable)
diff --git a/src/python/grpcio/grpc/_cython/cygrpc.pxd b/src/python/grpcio/grpc/_cython/cygrpc.pxd
index b6a794c..c8ace7c 100644
--- a/src/python/grpcio/grpc/_cython/cygrpc.pxd
+++ b/src/python/grpcio/grpc/_cython/cygrpc.pxd
@@ -11,6 +11,7 @@
 # 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.
+# distutils: language=c++
 
 include "_cygrpc/grpc.pxi"
 
@@ -27,3 +28,5 @@
 include "_cygrpc/server.pxd.pxi"
 include "_cygrpc/tag.pxd.pxi"
 include "_cygrpc/time.pxd.pxi"
+
+include "_cygrpc/grpc_gevent.pxd"
diff --git a/src/python/grpcio/grpc/_cython/cygrpc.pyx b/src/python/grpcio/grpc/_cython/cygrpc.pyx
index 2ee2e6b..f5f08fc 100644
--- a/src/python/grpcio/grpc/_cython/cygrpc.pyx
+++ b/src/python/grpcio/grpc/_cython/cygrpc.pyx
@@ -11,6 +11,7 @@
 # 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.
+# distutils: language=c++
 
 cimport cpython
 
@@ -35,6 +36,8 @@
 include "_cygrpc/tag.pyx.pxi"
 include "_cygrpc/time.pyx.pxi"
 
+include "_cygrpc/grpc_gevent.pyx"
+
 #
 # initialize gRPC
 #
diff --git a/src/python/grpcio/grpc/_grpcio_metadata.py b/src/python/grpcio/grpc/_grpcio_metadata.py
index 4a69d85..ad53f60 100644
--- a/src/python/grpcio/grpc/_grpcio_metadata.py
+++ b/src/python/grpcio/grpc/_grpcio_metadata.py
@@ -14,4 +14,4 @@
 
 # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio/grpc/_grpcio_metadata.py.template`!!!
 
-__version__ = """1.11.0.dev0"""
+__version__ = """1.13.0.dev0"""
diff --git a/src/python/grpcio/grpc/_interceptor.py b/src/python/grpcio/grpc/_interceptor.py
index d029472..f465e35 100644
--- a/src/python/grpcio/grpc/_interceptor.py
+++ b/src/python/grpcio/grpc/_interceptor.py
@@ -334,6 +334,19 @@
         else:
             return thunk(method)
 
+    def _close(self):
+        self._channel.close()
+
+    def __enter__(self):
+        return self
+
+    def __exit__(self, exc_type, exc_val, exc_tb):
+        self._close()
+        return False
+
+    def close(self):
+        self._channel.close()
+
 
 def intercept_channel(channel, *interceptors):
     for interceptor in reversed(list(interceptors)):
diff --git a/src/python/grpcio/grpc/_server.py b/src/python/grpcio/grpc/_server.py
index c988e0c..d849cad 100644
--- a/src/python/grpcio/grpc/_server.py
+++ b/src/python/grpcio/grpc/_server.py
@@ -780,14 +780,8 @@
         state.stage = _ServerStage.STARTED
         _request_call(state)
 
-        def cleanup_server(timeout):
-            if timeout is None:
-                _stop(state, _UNEXPECTED_EXIT_SERVER_GRACE).wait()
-            else:
-                _stop(state, timeout).wait()
-
-        thread = _common.CleanupThread(
-            cleanup_server, target=_serve, args=(state,))
+        thread = threading.Thread(target=_serve, args=(state,))
+        thread.daemon = True
         thread.start()
 
 
diff --git a/src/python/grpcio/grpc/beta/_server_adaptations.py b/src/python/grpcio/grpc/beta/_server_adaptations.py
index 3c04fd7..ccafec8 100644
--- a/src/python/grpcio/grpc/beta/_server_adaptations.py
+++ b/src/python/grpcio/grpc/beta/_server_adaptations.py
@@ -168,11 +168,8 @@
                 return
         request_consumer.terminate()
 
-    def stop_request_pipe(timeout):  # pylint: disable=unused-argument
-        thread_joined.set()
-
-    request_pipe_thread = _common.CleanupThread(
-        stop_request_pipe, target=pipe_requests)
+    request_pipe_thread = threading.Thread(target=pipe_requests)
+    request_pipe_thread.daemon = True
     request_pipe_thread.start()
 
 
diff --git a/src/python/grpcio/grpc/experimental/__init__.py b/src/python/grpcio/grpc/experimental/__init__.py
new file mode 100644
index 0000000..dcec322
--- /dev/null
+++ b/src/python/grpcio/grpc/experimental/__init__.py
@@ -0,0 +1,17 @@
+# Copyright 2018 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.
+"""gRPC's experimental APIs.
+
+These APIs are subject to be removed during any minor version release.
+"""
diff --git a/src/python/grpcio/grpc/experimental/gevent.py b/src/python/grpcio/grpc/experimental/gevent.py
new file mode 100644
index 0000000..159d612
--- /dev/null
+++ b/src/python/grpcio/grpc/experimental/gevent.py
@@ -0,0 +1,27 @@
+# Copyright 2018 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.
+"""gRPC's Python gEvent APIs."""
+
+from grpc._cython import cygrpc as _cygrpc
+
+
+def init_gevent():
+    """Patches gRPC's libraries to be compatible with gevent.
+
+    This must be called AFTER the python standard lib has been patched,
+    but BEFORE creating and gRPC objects.
+
+    In order for progress to be made, the application must drive the event loop.
+    """
+    _cygrpc.init_grpc_gevent()
diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py
index 9f4aaff..699d504 100644
--- a/src/python/grpcio/grpc_core_dependencies.py
+++ b/src/python/grpcio/grpc_core_dependencies.py
@@ -296,9 +296,9 @@
     'third_party/nanopb/pb_decode.c',
     'third_party/nanopb/pb_encode.c',
     'src/core/tsi/transport_security.cc',
-    'src/core/tsi/transport_security_adapter.cc',
     'src/core/ext/transport/chttp2/client/insecure/channel_create.cc',
     'src/core/ext/transport/chttp2/client/insecure/channel_create_posix.cc',
+    'src/core/ext/transport/chttp2/client/authority.cc',
     'src/core/ext/transport/chttp2/client/chttp2_connector.cc',
     'src/core/ext/filters/client_channel/backup_poller.cc',
     'src/core/ext/filters/client_channel/channel_connectivity.cc',
@@ -343,7 +343,6 @@
     'src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.c',
     'src/core/ext/filters/client_channel/resolver/fake/fake_resolver.cc',
     'src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc',
-    'src/core/ext/filters/client_channel/lb_policy/subchannel_list.cc',
     'src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc',
     'src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.cc',
     'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.cc',
@@ -356,6 +355,7 @@
     'src/core/ext/census/grpc_context.cc',
     'src/core/ext/filters/max_age/max_age_filter.cc',
     'src/core/ext/filters/message_size/message_size_filter.cc',
+    'src/core/ext/filters/http/client_authority_filter.cc',
     'src/core/ext/filters/workarounds/workaround_cronet_compression_filter.cc',
     'src/core/ext/filters/workarounds/workaround_utils.cc',
     'src/core/plugin_registry/grpc_plugin_registry.cc',
diff --git a/src/python/grpcio/grpc_version.py b/src/python/grpcio/grpc_version.py
index 32e8249..57dc26d 100644
--- a/src/python/grpcio/grpc_version.py
+++ b/src/python/grpcio/grpc_version.py
@@ -14,4 +14,4 @@
 
 # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio/grpc_version.py.template`!!!
 
-VERSION = '1.11.0.dev0'
+VERSION = '1.13.0.dev0'
diff --git a/src/python/grpcio_health_checking/grpc_version.py b/src/python/grpcio_health_checking/grpc_version.py
index ad4c85c..ba0d4a3 100644
--- a/src/python/grpcio_health_checking/grpc_version.py
+++ b/src/python/grpcio_health_checking/grpc_version.py
@@ -14,4 +14,4 @@
 
 # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_health_checking/grpc_version.py.template`!!!
 
-VERSION = '1.11.0.dev0'
+VERSION = '1.13.0.dev0'
diff --git a/src/python/grpcio_health_checking/setup.py b/src/python/grpcio_health_checking/setup.py
index 60d309e..35c0982 100644
--- a/src/python/grpcio_health_checking/setup.py
+++ b/src/python/grpcio_health_checking/setup.py
@@ -57,7 +57,7 @@
 }
 
 INSTALL_REQUIRES = (
-    'protobuf>=3.5.0.post1',
+    'protobuf>=3.5.2.post1',
     'grpcio>={version}'.format(version=grpc_version.VERSION),
 )
 
diff --git a/src/python/grpcio_reflection/grpc_version.py b/src/python/grpcio_reflection/grpc_version.py
index 6322d84..ea2878d 100644
--- a/src/python/grpcio_reflection/grpc_version.py
+++ b/src/python/grpcio_reflection/grpc_version.py
@@ -14,4 +14,4 @@
 
 # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_reflection/grpc_version.py.template`!!!
 
-VERSION = '1.11.0.dev0'
+VERSION = '1.13.0.dev0'
diff --git a/src/python/grpcio_reflection/setup.py b/src/python/grpcio_reflection/setup.py
index 10c4c38..589d0ff 100644
--- a/src/python/grpcio_reflection/setup.py
+++ b/src/python/grpcio_reflection/setup.py
@@ -58,7 +58,7 @@
 }
 
 INSTALL_REQUIRES = (
-    'protobuf>=3.5.0.post1',
+    'protobuf>=3.5.2.post1',
     'grpcio>={version}'.format(version=grpc_version.VERSION),
 )
 
diff --git a/src/python/grpcio_testing/grpc_testing/_channel/_channel.py b/src/python/grpcio_testing/grpc_testing/_channel/_channel.py
index b015b8d..0c1941e 100644
--- a/src/python/grpcio_testing/grpc_testing/_channel/_channel.py
+++ b/src/python/grpcio_testing/grpc_testing/_channel/_channel.py
@@ -56,6 +56,21 @@
                       response_deserializer=None):
         return _multi_callable.StreamStream(method, self._state)
 
+    def _close(self):
+        # TODO(https://github.com/grpc/grpc/issues/12531): Decide what
+        # action to take here, if any?
+        pass
+
+    def __enter__(self):
+        return self
+
+    def __exit__(self, exc_type, exc_val, exc_tb):
+        self._close()
+        return False
+
+    def close(self):
+        self._close()
+
     def take_unary_unary(self, method_descriptor):
         return _channel_rpc.unary_unary(self._state, method_descriptor)
 
diff --git a/src/python/grpcio_testing/grpc_version.py b/src/python/grpcio_testing/grpc_version.py
index 1e75fea..02f19f2 100644
--- a/src/python/grpcio_testing/grpc_version.py
+++ b/src/python/grpcio_testing/grpc_version.py
@@ -14,4 +14,4 @@
 
 # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_testing/grpc_version.py.template`!!!
 
-VERSION = '1.11.0.dev0'
+VERSION = '1.13.0.dev0'
diff --git a/src/python/grpcio_testing/setup.py b/src/python/grpcio_testing/setup.py
index 5a9d593..eb480a5 100644
--- a/src/python/grpcio_testing/setup.py
+++ b/src/python/grpcio_testing/setup.py
@@ -29,7 +29,7 @@
 }
 
 INSTALL_REQUIRES = (
-    'protobuf>=3.5.0.post1',
+    'protobuf>=3.5.2.post1',
     'grpcio>={version}'.format(version=grpc_version.VERSION),
 )
 
diff --git a/src/python/grpcio_tests/commands.py b/src/python/grpcio_tests/commands.py
index 93f8457..42e01c1 100644
--- a/src/python/grpcio_tests/commands.py
+++ b/src/python/grpcio_tests/commands.py
@@ -108,6 +108,57 @@
         self.distribution.fetch_build_eggs(self.distribution.tests_require)
 
 
+class TestGevent(setuptools.Command):
+    """Command to run tests w/gevent."""
+
+    BANNED_TESTS = (
+        # These tests send a lot of RPCs and are really slow on gevent.  They will
+        # eventually succeed, but need to dig into performance issues.
+        'unit._cython._no_messages_server_completion_queue_per_call_test.Test.test_rpcs',
+        'unit._cython._no_messages_single_server_completion_queue_test.Test.test_rpcs',
+        # I have no idea why this doesn't work in gevent, but it shouldn't even be
+        # using the c-core
+        'testing._client_test.ClientTest.test_infinite_request_stream_real_time',
+        # TODO(https://github.com/grpc/grpc/issues/14789) enable this test
+        'unit._server_ssl_cert_config_test',
+        # TODO(https://github.com/grpc/grpc/issues/14901) enable this test
+        'protoc_plugin._python_plugin_test.PythonPluginTest',
+        # Beta API is unsupported for gevent
+        'protoc_plugin.beta_python_plugin_test',
+        'unit.beta._beta_features_test',
+    )
+    description = 'run tests with gevent.  Assumes grpc/gevent are installed'
+    user_options = []
+
+    def initialize_options(self):
+        pass
+
+    def finalize_options(self):
+        # distutils requires this override.
+        pass
+
+    def run(self):
+        from gevent import monkey
+        monkey.patch_all()
+
+        import tests
+
+        import grpc.experimental.gevent
+        grpc.experimental.gevent.init_gevent()
+
+        import gevent
+
+        import tests
+        loader = tests.Loader()
+        loader.loadTestsFromNames(['tests'])
+        runner = tests.Runner()
+        runner.skip_tests(self.BANNED_TESTS)
+        result = gevent.spawn(runner.run, loader.suite)
+        result.join()
+        if not result.value.wasSuccessful():
+            sys.exit('Test failure')
+
+
 class RunInterop(test.test):
 
     description = 'run interop test client/server'
diff --git a/src/python/grpcio_tests/grpc_version.py b/src/python/grpcio_tests/grpc_version.py
index 0cd7bd2..9d2e416 100644
--- a/src/python/grpcio_tests/grpc_version.py
+++ b/src/python/grpcio_tests/grpc_version.py
@@ -14,4 +14,4 @@
 
 # AUTO-GENERATED FROM `$REPO_ROOT/templates/src/python/grpcio_tests/grpc_version.py.template`!!!
 
-VERSION = '1.11.0.dev0'
+VERSION = '1.13.0.dev0'
diff --git a/src/python/grpcio_tests/setup.py b/src/python/grpcio_tests/setup.py
index 250df65..98ac19d 100644
--- a/src/python/grpcio_tests/setup.py
+++ b/src/python/grpcio_tests/setup.py
@@ -41,7 +41,7 @@
     'grpcio>={version}'.format(version=grpc_version.VERSION),
     'grpcio-tools>={version}'.format(version=grpc_version.VERSION),
     'grpcio-health-checking>={version}'.format(version=grpc_version.VERSION),
-    'oauth2client>=1.4.7', 'protobuf>=3.5.0.post1', 'six>=1.10',
+    'oauth2client>=1.4.7', 'protobuf>=3.5.2.post1', 'six>=1.10',
     'google-auth>=1.0.0', 'requests>=2.14.2')
 
 COMMAND_CLASS = {
@@ -50,7 +50,8 @@
     'build_package_protos': grpc_tools.command.BuildPackageProtos,
     'build_py': commands.BuildPy,
     'run_interop': commands.RunInterop,
-    'test_lite': commands.TestLite
+    'test_lite': commands.TestLite,
+    'test_gevent': commands.TestGevent,
 }
 
 PACKAGE_DATA = {
diff --git a/src/python/grpcio_tests/tests/_loader.py b/src/python/grpcio_tests/tests/_loader.py
index 3168091..be0af646 100644
--- a/src/python/grpcio_tests/tests/_loader.py
+++ b/src/python/grpcio_tests/tests/_loader.py
@@ -54,7 +54,7 @@
         for module in modules:
             try:
                 package_paths = module.__path__
-            except:
+            except AttributeError:
                 continue
             self.walk_packages(package_paths)
         coverage_context.stop()
diff --git a/src/python/grpcio_tests/tests/_result.py b/src/python/grpcio_tests/tests/_result.py
index 9907c4e..b105f18 100644
--- a/src/python/grpcio_tests/tests/_result.py
+++ b/src/python/grpcio_tests/tests/_result.py
@@ -46,7 +46,7 @@
       None.
   """
 
-    class Kind:
+    class Kind(object):
         UNTESTED = 'untested'
         RUNNING = 'running'
         ERROR = 'error'
@@ -257,7 +257,7 @@
         #coverage.Coverage().combine()
 
 
-class _Colors:
+class _Colors(object):
     """Namespaced constants for terminal color magic numbers."""
     HEADER = '\033[95m'
     INFO = '\033[94m'
diff --git a/src/python/grpcio_tests/tests/_runner.py b/src/python/grpcio_tests/tests/_runner.py
index 8e27dc6..eaaa027 100644
--- a/src/python/grpcio_tests/tests/_runner.py
+++ b/src/python/grpcio_tests/tests/_runner.py
@@ -117,6 +117,12 @@
 
 class Runner(object):
 
+    def __init__(self):
+        self._skipped_tests = []
+
+    def skip_tests(self, tests):
+        self._skipped_tests = tests
+
     def run(self, suite):
         """See setuptools' test_runner setup argument for information."""
         # only run test cases with id starting with given prefix
@@ -181,27 +187,31 @@
         # Run the tests
         result.startTestRun()
         for augmented_case in augmented_cases:
-            sys.stdout.write('Running       {}\n'.format(
-                augmented_case.case.id()))
-            sys.stdout.flush()
-            case_thread = threading.Thread(
-                target=augmented_case.case.run, args=(result,))
-            try:
-                with stdout_pipe, stderr_pipe:
-                    case_thread.start()
-                    while case_thread.is_alive():
-                        check_kill_self()
-                        time.sleep(0)
-                    case_thread.join()
-            except:
-                # re-raise the exception after forcing the with-block to end
-                raise
-            result.set_output(augmented_case.case, stdout_pipe.output(),
-                              stderr_pipe.output())
-            sys.stdout.write(result_out.getvalue())
-            sys.stdout.flush()
-            result_out.truncate(0)
-            check_kill_self()
+            for skipped_test in self._skipped_tests:
+                if skipped_test in augmented_case.case.id():
+                    break
+            else:
+                sys.stdout.write('Running       {}\n'.format(
+                    augmented_case.case.id()))
+                sys.stdout.flush()
+                case_thread = threading.Thread(
+                    target=augmented_case.case.run, args=(result,))
+                try:
+                    with stdout_pipe, stderr_pipe:
+                        case_thread.start()
+                        while case_thread.is_alive():
+                            check_kill_self()
+                            time.sleep(0)
+                        case_thread.join()
+                except:
+                    # re-raise the exception after forcing the with-block to end
+                    raise
+                result.set_output(augmented_case.case, stdout_pipe.output(),
+                                  stderr_pipe.output())
+                sys.stdout.write(result_out.getvalue())
+                sys.stdout.flush()
+                result_out.truncate(0)
+                check_kill_self()
         result.stopTestRun()
         stdout_pipe.close()
         stderr_pipe.close()
diff --git a/src/python/grpcio_tests/tests/interop/_insecure_intraop_test.py b/src/python/grpcio_tests/tests/interop/_insecure_intraop_test.py
index 8d464b2..ace15be 100644
--- a/src/python/grpcio_tests/tests/interop/_insecure_intraop_test.py
+++ b/src/python/grpcio_tests/tests/interop/_insecure_intraop_test.py
@@ -36,6 +36,9 @@
         self.stub = test_pb2_grpc.TestServiceStub(
             grpc.insecure_channel('localhost:{}'.format(port)))
 
+    def tearDown(self):
+        self.server.stop(None)
+
 
 if __name__ == '__main__':
     unittest.main(verbosity=2)
diff --git a/src/python/grpcio_tests/tests/interop/_secure_intraop_test.py b/src/python/grpcio_tests/tests/interop/_secure_intraop_test.py
index c891359..e27e551 100644
--- a/src/python/grpcio_tests/tests/interop/_secure_intraop_test.py
+++ b/src/python/grpcio_tests/tests/interop/_secure_intraop_test.py
@@ -45,6 +45,9 @@
                                         _SERVER_HOST_OVERRIDE,
                                     ),)))
 
+    def tearDown(self):
+        self.server.stop(None)
+
 
 if __name__ == '__main__':
     unittest.main(verbosity=2)
diff --git a/src/python/grpcio_tests/tests/interop/client.py b/src/python/grpcio_tests/tests/interop/client.py
index 3780ed9..698c370 100644
--- a/src/python/grpcio_tests/tests/interop/client.py
+++ b/src/python/grpcio_tests/tests/interop/client.py
@@ -66,10 +66,6 @@
     return parser.parse_args()
 
 
-def _application_default_credentials():
-    return oauth2client_client.GoogleCredentials.get_application_default()
-
-
 def _stub(args):
     target = '{}:{}'.format(args.server_host, args.server_port)
     if args.test_case == 'oauth2_auth_token':
diff --git a/src/python/grpcio_tests/tests/protoc_plugin/_python_plugin_test.py b/src/python/grpcio_tests/tests/protoc_plugin/_python_plugin_test.py
index 6d85f43..00e60b4 100644
--- a/src/python/grpcio_tests/tests/protoc_plugin/_python_plugin_test.py
+++ b/src/python/grpcio_tests/tests/protoc_plugin/_python_plugin_test.py
@@ -237,6 +237,7 @@
         self.assertIsNotNone(service.servicer_methods)
         self.assertIsNotNone(service.server)
         self.assertIsNotNone(service.stub)
+        service.server.stop(None)
 
     def testIncompleteServicer(self):
         service = _CreateIncompleteService()
@@ -245,6 +246,7 @@
             service.stub.UnaryCall(request)
         self.assertIs(exception_context.exception.code(),
                       grpc.StatusCode.UNIMPLEMENTED)
+        service.server.stop(None)
 
     def testUnaryCall(self):
         service = _CreateService()
@@ -253,6 +255,7 @@
         expected_response = service.servicer_methods.UnaryCall(
             request, 'not a real context!')
         self.assertEqual(expected_response, response)
+        service.server.stop(None)
 
     def testUnaryCallFuture(self):
         service = _CreateService()
@@ -264,6 +267,7 @@
         expected_response = service.servicer_methods.UnaryCall(
             request, 'not a real RpcContext!')
         self.assertEqual(expected_response, response)
+        service.server.stop(None)
 
     def testUnaryCallFutureExpired(self):
         service = _CreateService()
@@ -276,6 +280,7 @@
         self.assertIs(exception_context.exception.code(),
                       grpc.StatusCode.DEADLINE_EXCEEDED)
         self.assertIs(response_future.code(), grpc.StatusCode.DEADLINE_EXCEEDED)
+        service.server.stop(None)
 
     def testUnaryCallFutureCancelled(self):
         service = _CreateService()
@@ -285,6 +290,7 @@
             response_future.cancel()
         self.assertTrue(response_future.cancelled())
         self.assertIs(response_future.code(), grpc.StatusCode.CANCELLED)
+        service.server.stop(None)
 
     def testUnaryCallFutureFailed(self):
         service = _CreateService()
@@ -293,6 +299,7 @@
             response_future = service.stub.UnaryCall.future(request)
             self.assertIsNotNone(response_future.exception())
         self.assertIs(response_future.code(), grpc.StatusCode.UNKNOWN)
+        service.server.stop(None)
 
     def testStreamingOutputCall(self):
         service = _CreateService()
@@ -303,6 +310,7 @@
         for expected_response, response in moves.zip_longest(
                 expected_responses, responses):
             self.assertEqual(expected_response, response)
+        service.server.stop(None)
 
     def testStreamingOutputCallExpired(self):
         service = _CreateService()
@@ -314,6 +322,7 @@
                 list(responses)
         self.assertIs(exception_context.exception.code(),
                       grpc.StatusCode.DEADLINE_EXCEEDED)
+        service.server.stop(None)
 
     def testStreamingOutputCallCancelled(self):
         service = _CreateService()
@@ -324,6 +333,7 @@
         with self.assertRaises(grpc.RpcError) as exception_context:
             next(responses)
         self.assertIs(responses.code(), grpc.StatusCode.CANCELLED)
+        service.server.stop(None)
 
     def testStreamingOutputCallFailed(self):
         service = _CreateService()
@@ -335,6 +345,7 @@
                 next(responses)
         self.assertIs(exception_context.exception.code(),
                       grpc.StatusCode.UNKNOWN)
+        service.server.stop(None)
 
     def testStreamingInputCall(self):
         service = _CreateService()
@@ -343,6 +354,7 @@
         expected_response = service.servicer_methods.StreamingInputCall(
             _streaming_input_request_iterator(), 'not a real RpcContext!')
         self.assertEqual(expected_response, response)
+        service.server.stop(None)
 
     def testStreamingInputCallFuture(self):
         service = _CreateService()
@@ -353,6 +365,7 @@
         expected_response = service.servicer_methods.StreamingInputCall(
             _streaming_input_request_iterator(), 'not a real RpcContext!')
         self.assertEqual(expected_response, response)
+        service.server.stop(None)
 
     def testStreamingInputCallFutureExpired(self):
         service = _CreateService()
@@ -367,6 +380,7 @@
                       grpc.StatusCode.DEADLINE_EXCEEDED)
         self.assertIs(exception_context.exception.code(),
                       grpc.StatusCode.DEADLINE_EXCEEDED)
+        service.server.stop(None)
 
     def testStreamingInputCallFutureCancelled(self):
         service = _CreateService()
@@ -377,6 +391,7 @@
         self.assertTrue(response_future.cancelled())
         with self.assertRaises(grpc.FutureCancelledError):
             response_future.result()
+        service.server.stop(None)
 
     def testStreamingInputCallFutureFailed(self):
         service = _CreateService()
@@ -385,6 +400,7 @@
                 _streaming_input_request_iterator())
             self.assertIsNotNone(response_future.exception())
             self.assertIs(response_future.code(), grpc.StatusCode.UNKNOWN)
+        service.server.stop(None)
 
     def testFullDuplexCall(self):
         service = _CreateService()
@@ -394,6 +410,7 @@
         for expected_response, response in moves.zip_longest(
                 expected_responses, responses):
             self.assertEqual(expected_response, response)
+        service.server.stop(None)
 
     def testFullDuplexCallExpired(self):
         request_iterator = _full_duplex_request_iterator()
@@ -405,6 +422,7 @@
                 list(responses)
         self.assertIs(exception_context.exception.code(),
                       grpc.StatusCode.DEADLINE_EXCEEDED)
+        service.server.stop(None)
 
     def testFullDuplexCallCancelled(self):
         service = _CreateService()
@@ -416,6 +434,7 @@
             next(responses)
         self.assertIs(exception_context.exception.code(),
                       grpc.StatusCode.CANCELLED)
+        service.server.stop(None)
 
     def testFullDuplexCallFailed(self):
         request_iterator = _full_duplex_request_iterator()
@@ -426,6 +445,7 @@
                 next(responses)
         self.assertIs(exception_context.exception.code(),
                       grpc.StatusCode.UNKNOWN)
+        service.server.stop(None)
 
     def testHalfDuplexCall(self):
         service = _CreateService()
@@ -445,6 +465,7 @@
         for expected_response, response in moves.zip_longest(
                 expected_responses, responses):
             self.assertEqual(expected_response, response)
+        service.server.stop(None)
 
     def testHalfDuplexCallWedged(self):
         condition = threading.Condition()
@@ -478,6 +499,7 @@
                 next(responses)
         self.assertIs(exception_context.exception.code(),
                       grpc.StatusCode.DEADLINE_EXCEEDED)
+        service.server.stop(None)
 
 
 if __name__ == '__main__':
diff --git a/src/python/grpcio_tests/tests/protoc_plugin/_split_definitions_test.py b/src/python/grpcio_tests/tests/protoc_plugin/_split_definitions_test.py
index ab33775..e21ea00 100644
--- a/src/python/grpcio_tests/tests/protoc_plugin/_split_definitions_test.py
+++ b/src/python/grpcio_tests/tests/protoc_plugin/_split_definitions_test.py
@@ -271,6 +271,7 @@
             stub = services_module.TestServiceStub(channel)
             response = stub.Call(self._messages_pb2.Request())
             self.assertEqual(self._messages_pb2.Response(), response)
+            server.stop(None)
 
 
 def _create_test_case_class(split_proto, protoc_style):
diff --git a/src/python/grpcio_tests/tests/protoc_plugin/beta_python_plugin_test.py b/src/python/grpcio_tests/tests/protoc_plugin/beta_python_plugin_test.py
index ad0ecf0..b46e533 100644
--- a/src/python/grpcio_tests/tests/protoc_plugin/beta_python_plugin_test.py
+++ b/src/python/grpcio_tests/tests/protoc_plugin/beta_python_plugin_test.py
@@ -329,9 +329,7 @@
 
         _packagify(self._python_out)
 
-        with _system_path([
-                self._python_out,
-        ]):
+        with _system_path([self._python_out]):
             self._payload_pb2 = importlib.import_module(_PAYLOAD_PB2)
             self._requests_pb2 = importlib.import_module(_REQUESTS_PB2)
             self._responses_pb2 = importlib.import_module(_RESPONSES_PB2)
diff --git a/src/python/grpcio_tests/tests/qps/benchmark_client.py b/src/python/grpcio_tests/tests/qps/benchmark_client.py
index e6392a8..0488450 100644
--- a/src/python/grpcio_tests/tests/qps/benchmark_client.py
+++ b/src/python/grpcio_tests/tests/qps/benchmark_client.py
@@ -22,7 +22,7 @@
 
 import grpc
 from src.proto.grpc.testing import messages_pb2
-from src.proto.grpc.testing import services_pb2_grpc
+from src.proto.grpc.testing import benchmark_service_pb2_grpc
 from tests.unit import resources
 from tests.unit import test_common
 
@@ -58,7 +58,8 @@
 
         if config.payload_config.WhichOneof('payload') == 'simple_params':
             self._generic = False
-            self._stub = services_pb2_grpc.BenchmarkServiceStub(channel)
+            self._stub = benchmark_service_pb2_grpc.BenchmarkServiceStub(
+                channel)
             payload = messages_pb2.Payload(
                 body='\0' * config.payload_config.simple_params.req_size)
             self._request = messages_pb2.SimpleRequest(
diff --git a/src/python/grpcio_tests/tests/qps/benchmark_server.py b/src/python/grpcio_tests/tests/qps/benchmark_server.py
index bb07844..2bd89cb 100644
--- a/src/python/grpcio_tests/tests/qps/benchmark_server.py
+++ b/src/python/grpcio_tests/tests/qps/benchmark_server.py
@@ -13,10 +13,10 @@
 # limitations under the License.
 
 from src.proto.grpc.testing import messages_pb2
-from src.proto.grpc.testing import services_pb2_grpc
+from src.proto.grpc.testing import benchmark_service_pb2_grpc
 
 
-class BenchmarkServer(services_pb2_grpc.BenchmarkServiceServicer):
+class BenchmarkServer(benchmark_service_pb2_grpc.BenchmarkServiceServicer):
     """Synchronous Server implementation for the Benchmark service."""
 
     def UnaryCall(self, request, context):
@@ -29,7 +29,8 @@
             yield messages_pb2.SimpleResponse(payload=payload)
 
 
-class GenericBenchmarkServer(services_pb2_grpc.BenchmarkServiceServicer):
+class GenericBenchmarkServer(
+        benchmark_service_pb2_grpc.BenchmarkServiceServicer):
     """Generic Server implementation for the Benchmark service."""
 
     def __init__(self, resp_size):
diff --git a/src/python/grpcio_tests/tests/qps/qps_worker.py b/src/python/grpcio_tests/tests/qps/qps_worker.py
index 54f69db..c33d013 100644
--- a/src/python/grpcio_tests/tests/qps/qps_worker.py
+++ b/src/python/grpcio_tests/tests/qps/qps_worker.py
@@ -17,7 +17,7 @@
 import time
 
 import grpc
-from src.proto.grpc.testing import services_pb2_grpc
+from src.proto.grpc.testing import worker_service_pb2_grpc
 
 from tests.qps import worker_server
 from tests.unit import test_common
@@ -26,7 +26,8 @@
 def run_worker_server(port):
     server = test_common.test_server()
     servicer = worker_server.WorkerServer()
-    services_pb2_grpc.add_WorkerServiceServicer_to_server(servicer, server)
+    worker_service_pb2_grpc.add_WorkerServiceServicer_to_server(
+        servicer, server)
     server.add_insecure_port('[::]:{}'.format(port))
     server.start()
     servicer.wait_for_quit()
diff --git a/src/python/grpcio_tests/tests/qps/worker_server.py b/src/python/grpcio_tests/tests/qps/worker_server.py
index 41e2403..db145fb 100644
--- a/src/python/grpcio_tests/tests/qps/worker_server.py
+++ b/src/python/grpcio_tests/tests/qps/worker_server.py
@@ -20,7 +20,7 @@
 from concurrent import futures
 import grpc
 from src.proto.grpc.testing import control_pb2
-from src.proto.grpc.testing import services_pb2_grpc
+from src.proto.grpc.testing import worker_service_pb2_grpc
 from src.proto.grpc.testing import stats_pb2
 
 from tests.qps import benchmark_client
@@ -31,7 +31,7 @@
 from tests.unit import test_common
 
 
-class WorkerServer(services_pb2_grpc.WorkerServiceServicer):
+class WorkerServer(worker_service_pb2_grpc.WorkerServiceServicer):
     """Python Worker Server implementation."""
 
     def __init__(self):
@@ -72,7 +72,7 @@
         server = test_common.test_server(max_workers=server_threads)
         if config.server_type == control_pb2.ASYNC_SERVER:
             servicer = benchmark_server.BenchmarkServer()
-            services_pb2_grpc.add_BenchmarkServiceServicer_to_server(
+            worker_service_pb2_grpc.add_BenchmarkServiceServicer_to_server(
                 servicer, server)
         elif config.server_type == control_pb2.ASYNC_GENERIC_SERVER:
             resp_size = config.payload_config.bytebuf_params.resp_size
diff --git a/src/python/grpcio_tests/tests/stress/test_runner.py b/src/python/grpcio_tests/tests/stress/test_runner.py
index d5038e3..764cda1 100644
--- a/src/python/grpcio_tests/tests/stress/test_runner.py
+++ b/src/python/grpcio_tests/tests/stress/test_runner.py
@@ -50,7 +50,7 @@
                 test_case.test_interoperability(self._stub, None)
                 end_time = time.time()
                 self._histogram.add((end_time - start_time) * 1e9)
-            except Exception as e:
+            except Exception as e:  # pylint: disable=broad-except
                 traceback.print_exc()
                 self._exception_queue.put(
                     Exception("An exception occured during test {}"
diff --git a/src/python/grpcio_tests/tests/testing/_client_application.py b/src/python/grpcio_tests/tests/testing/_client_application.py
index 7d0d74c..3ddeba2 100644
--- a/src/python/grpcio_tests/tests/testing/_client_application.py
+++ b/src/python/grpcio_tests/tests/testing/_client_application.py
@@ -215,30 +215,6 @@
         return _UNSATISFACTORY_OUTCOME
 
 
-def run(scenario, channel):
-    stub = services_pb2_grpc.FirstServiceStub(channel)
-    try:
-        if scenario is Scenario.UNARY_UNARY:
-            return _run_unary_unary(stub)
-        elif scenario is Scenario.UNARY_STREAM:
-            return _run_unary_stream(stub)
-        elif scenario is Scenario.STREAM_UNARY:
-            return _run_stream_unary(stub)
-        elif scenario is Scenario.STREAM_STREAM:
-            return _run_stream_stream(stub)
-        elif scenario is Scenario.CONCURRENT_STREAM_UNARY:
-            return _run_concurrent_stream_unary(stub)
-        elif scenario is Scenario.CONCURRENT_STREAM_STREAM:
-            return _run_concurrent_stream_stream(stub)
-        elif scenario is Scenario.CANCEL_UNARY_UNARY:
-            return _run_cancel_unary_unary(stub)
-        elif scenario is Scenario.INFINITE_REQUEST_STREAM:
-            return _run_infinite_request_stream(stub)
-    except grpc.RpcError as rpc_error:
-        return Outcome(Outcome.Kind.RPC_ERROR, rpc_error.code(),
-                       rpc_error.details())
-
-
 _IMPLEMENTATIONS = {
     Scenario.UNARY_UNARY: _run_unary_unary,
     Scenario.UNARY_STREAM: _run_unary_stream,
diff --git a/src/python/grpcio_tests/tests/testing/_server_application.py b/src/python/grpcio_tests/tests/testing/_server_application.py
index 02769ca..243c385 100644
--- a/src/python/grpcio_tests/tests/testing/_server_application.py
+++ b/src/python/grpcio_tests/tests/testing/_server_application.py
@@ -38,7 +38,7 @@
             context.set_code(grpc.StatusCode.INVALID_ARGUMENT)
             context.set_details('Something is wrong with your request!')
         return
-        yield services_pb2.Strange()
+        yield services_pb2.Strange()  # pylint: disable=unreachable
 
     def StreUn(self, request_iterator, context):
         context.send_initial_metadata(((
diff --git a/src/python/grpcio_tests/tests/testing/_server_test.py b/src/python/grpcio_tests/tests/testing/_server_test.py
index 4f4abd7..88e3a79 100644
--- a/src/python/grpcio_tests/tests/testing/_server_test.py
+++ b/src/python/grpcio_tests/tests/testing/_server_test.py
@@ -21,13 +21,8 @@
 from tests.testing import _application_common
 from tests.testing import _application_testing_common
 from tests.testing import _server_application
-from tests.testing.proto import services_pb2
 
 
-# TODO(https://github.com/google/protobuf/issues/3452): Drop this skip.
-@unittest.skipIf(
-    services_pb2.DESCRIPTOR.services_by_name.get('FirstService') is None,
-    'Fix protobuf issue 3452!')
 class FirstServiceServicerTest(unittest.TestCase):
 
     def setUp(self):
diff --git a/src/python/grpcio_tests/tests/tests.json b/src/python/grpcio_tests/tests/tests.json
index d38ee51..0d94426 100644
--- a/src/python/grpcio_tests/tests/tests.json
+++ b/src/python/grpcio_tests/tests/tests.json
@@ -25,6 +25,7 @@
   "unit._auth_test.AccessTokenAuthMetadataPluginTest",
   "unit._auth_test.GoogleCallCredentialsTest",
   "unit._channel_args_test.ChannelArgsTest",
+  "unit._channel_close_test.ChannelCloseTest",
   "unit._channel_connectivity_test.ChannelConnectivityTest",
   "unit._channel_ready_future_test.ChannelReadyFutureTest",
   "unit._compression_test.CompressionTest",
@@ -52,7 +53,6 @@
   "unit._server_ssl_cert_config_test.ServerSSLCertReloadTestCertConfigReuse",
   "unit._server_ssl_cert_config_test.ServerSSLCertReloadTestWithClientAuth",
   "unit._server_ssl_cert_config_test.ServerSSLCertReloadTestWithoutClientAuth",
-  "unit._thread_cleanup_test.CleanupThreadTest",
   "unit.beta._beta_features_test.BetaFeaturesTest",
   "unit.beta._beta_features_test.ContextManagementAndLifecycleTest",
   "unit.beta._connectivity_channel_test.ConnectivityStatesTest",
diff --git a/src/python/grpcio_tests/tests/unit/_channel_close_test.py b/src/python/grpcio_tests/tests/unit/_channel_close_test.py
new file mode 100644
index 0000000..af3a9ee
--- /dev/null
+++ b/src/python/grpcio_tests/tests/unit/_channel_close_test.py
@@ -0,0 +1,185 @@
+# Copyright 2018 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.
+"""Tests server and client side compression."""
+
+import threading
+import time
+import unittest
+
+import grpc
+
+from tests.unit import test_common
+from tests.unit.framework.common import test_constants
+
+_BEAT = 0.5
+_SOME_TIME = 5
+_MORE_TIME = 10
+
+
+class _MethodHandler(grpc.RpcMethodHandler):
+
+    request_streaming = True
+    response_streaming = True
+    request_deserializer = None
+    response_serializer = None
+
+    def stream_stream(self, request_iterator, servicer_context):
+        for request in request_iterator:
+            yield request * 2
+
+
+_METHOD_HANDLER = _MethodHandler()
+
+
+class _GenericHandler(grpc.GenericRpcHandler):
+
+    def service(self, handler_call_details):
+        return _METHOD_HANDLER
+
+
+_GENERIC_HANDLER = _GenericHandler()
+
+
+class _Pipe(object):
+
+    def __init__(self, values):
+        self._condition = threading.Condition()
+        self._values = list(values)
+        self._open = True
+
+    def __iter__(self):
+        return self
+
+    def _next(self):
+        with self._condition:
+            while not self._values and self._open:
+                self._condition.wait()
+            if self._values:
+                return self._values.pop(0)
+            else:
+                raise StopIteration()
+
+    def next(self):
+        return self._next()
+
+    def __next__(self):
+        return self._next()
+
+    def add(self, value):
+        with self._condition:
+            self._values.append(value)
+            self._condition.notify()
+
+    def close(self):
+        with self._condition:
+            self._open = False
+            self._condition.notify()
+
+    def __enter__(self):
+        return self
+
+    def __exit__(self, type, value, traceback):
+        self.close()
+
+
+class ChannelCloseTest(unittest.TestCase):
+
+    def setUp(self):
+        self._server = test_common.test_server(
+            max_workers=test_constants.THREAD_CONCURRENCY)
+        self._server.add_generic_rpc_handlers((_GENERIC_HANDLER,))
+        self._port = self._server.add_insecure_port('[::]:0')
+        self._server.start()
+
+    def tearDown(self):
+        self._server.stop(None)
+
+    def test_close_immediately_after_call_invocation(self):
+        channel = grpc.insecure_channel('localhost:{}'.format(self._port))
+        multi_callable = channel.stream_stream('Meffod')
+        request_iterator = _Pipe(())
+        response_iterator = multi_callable(request_iterator)
+        channel.close()
+        request_iterator.close()
+
+        self.assertIs(response_iterator.code(), grpc.StatusCode.CANCELLED)
+
+    def test_close_while_call_active(self):
+        channel = grpc.insecure_channel('localhost:{}'.format(self._port))
+        multi_callable = channel.stream_stream('Meffod')
+        request_iterator = _Pipe((b'abc',))
+        response_iterator = multi_callable(request_iterator)
+        next(response_iterator)
+        channel.close()
+        request_iterator.close()
+
+        self.assertIs(response_iterator.code(), grpc.StatusCode.CANCELLED)
+
+    def test_context_manager_close_while_call_active(self):
+        with grpc.insecure_channel('localhost:{}'.format(
+                self._port)) as channel:  # pylint: disable=bad-continuation
+            multi_callable = channel.stream_stream('Meffod')
+            request_iterator = _Pipe((b'abc',))
+            response_iterator = multi_callable(request_iterator)
+            next(response_iterator)
+        request_iterator.close()
+
+        self.assertIs(response_iterator.code(), grpc.StatusCode.CANCELLED)
+
+    def test_context_manager_close_while_many_calls_active(self):
+        with grpc.insecure_channel('localhost:{}'.format(
+                self._port)) as channel:  # pylint: disable=bad-continuation
+            multi_callable = channel.stream_stream('Meffod')
+            request_iterators = tuple(
+                _Pipe((b'abc',))
+                for _ in range(test_constants.THREAD_CONCURRENCY))
+            response_iterators = []
+            for request_iterator in request_iterators:
+                response_iterator = multi_callable(request_iterator)
+                next(response_iterator)
+                response_iterators.append(response_iterator)
+        for request_iterator in request_iterators:
+            request_iterator.close()
+
+        for response_iterator in response_iterators:
+            self.assertIs(response_iterator.code(), grpc.StatusCode.CANCELLED)
+
+    def test_many_concurrent_closes(self):
+        channel = grpc.insecure_channel('localhost:{}'.format(self._port))
+        multi_callable = channel.stream_stream('Meffod')
+        request_iterator = _Pipe((b'abc',))
+        response_iterator = multi_callable(request_iterator)
+        next(response_iterator)
+        start = time.time()
+        end = start + _MORE_TIME
+
+        def sleep_some_time_then_close():
+            time.sleep(_SOME_TIME)
+            channel.close()
+
+        for _ in range(test_constants.THREAD_CONCURRENCY):
+            close_thread = threading.Thread(target=sleep_some_time_then_close)
+            close_thread.start()
+        while True:
+            request_iterator.add(b'def')
+            time.sleep(_BEAT)
+            if end < time.time():
+                break
+        request_iterator.close()
+
+        self.assertIs(response_iterator.code(), grpc.StatusCode.CANCELLED)
+
+
+if __name__ == '__main__':
+    unittest.main(verbosity=2)
diff --git a/src/python/grpcio_tests/tests/unit/_compression_test.py b/src/python/grpcio_tests/tests/unit/_compression_test.py
index 7550cd3..0b11f03 100644
--- a/src/python/grpcio_tests/tests/unit/_compression_test.py
+++ b/src/python/grpcio_tests/tests/unit/_compression_test.py
@@ -52,9 +52,9 @@
         self.stream_unary = None
         self.stream_stream = None
         if self.request_streaming and self.response_streaming:
-            self.stream_stream = lambda x, y: handle_stream(x, y)
+            self.stream_stream = handle_stream
         elif not self.request_streaming and not self.response_streaming:
-            self.unary_unary = lambda x, y: handle_unary(x, y)
+            self.unary_unary = handle_unary
 
 
 class _GenericHandler(grpc.GenericRpcHandler):
diff --git a/src/python/grpcio_tests/tests/unit/_cython/_cancel_many_calls_test.py b/src/python/grpcio_tests/tests/unit/_cython/_cancel_many_calls_test.py
index 3765ce4..578a3d7 100644
--- a/src/python/grpcio_tests/tests/unit/_cython/_cancel_many_calls_test.py
+++ b/src/python/grpcio_tests/tests/unit/_cython/_cancel_many_calls_test.py
@@ -19,6 +19,7 @@
 from grpc._cython import cygrpc
 from grpc.framework.foundation import logging_pool
 from tests.unit.framework.common import test_constants
+from tests.unit._cython import test_utilities
 
 _EMPTY_FLAGS = 0
 _EMPTY_METADATA = ()
@@ -30,6 +31,8 @@
 _SERVER_COMPLETE_CALL_TAG = 'server_complete_call'
 
 _SUCCESS_CALL_FRACTION = 1.0 / 8.0
+_SUCCESSFUL_CALLS = int(test_constants.RPC_CONCURRENCY * _SUCCESS_CALL_FRACTION)
+_UNSUCCESSFUL_CALLS = test_constants.RPC_CONCURRENCY - _SUCCESSFUL_CALLS
 
 
 class _State(object):
@@ -43,7 +46,7 @@
 
 def _is_cancellation_event(event):
     return (event.tag is _RECEIVE_CLOSE_ON_SERVER_TAG and
-            event.batch_operations[0].received_cancelled)
+            event.batch_operations[0].cancelled())
 
 
 class _Handler(object):
@@ -150,7 +153,8 @@
         server.register_completion_queue(server_completion_queue)
         port = server.add_http2_port(b'[::]:0')
         server.start()
-        channel = cygrpc.Channel('localhost:{}'.format(port).encode(), None)
+        channel = cygrpc.Channel('localhost:{}'.format(port).encode(), None,
+                                 None)
 
         state = _State()
 
@@ -165,31 +169,33 @@
 
         client_condition = threading.Condition()
         client_due = set()
-        client_completion_queue = cygrpc.CompletionQueue()
-        client_driver = _QueueDriver(client_condition, client_completion_queue,
-                                     client_due)
-        client_driver.start()
 
         with client_condition:
             client_calls = []
             for index in range(test_constants.RPC_CONCURRENCY):
-                client_call = channel.create_call(None, _EMPTY_FLAGS,
-                                                  client_completion_queue,
-                                                  b'/twinkies', None, None)
-                operations = (
-                    cygrpc.SendInitialMetadataOperation(_EMPTY_METADATA,
-                                                        _EMPTY_FLAGS),
-                    cygrpc.SendMessageOperation(b'\x45\x56', _EMPTY_FLAGS),
-                    cygrpc.SendCloseFromClientOperation(_EMPTY_FLAGS),
-                    cygrpc.ReceiveInitialMetadataOperation(_EMPTY_FLAGS),
-                    cygrpc.ReceiveMessageOperation(_EMPTY_FLAGS),
-                    cygrpc.ReceiveStatusOnClientOperation(_EMPTY_FLAGS),
-                )
                 tag = 'client_complete_call_{0:04d}_tag'.format(index)
-                client_call.start_client_batch(operations, tag)
+                client_call = channel.integrated_call(
+                    _EMPTY_FLAGS, b'/twinkies', None, None, _EMPTY_METADATA,
+                    None, ((
+                        (
+                            cygrpc.SendInitialMetadataOperation(
+                                _EMPTY_METADATA, _EMPTY_FLAGS),
+                            cygrpc.SendMessageOperation(b'\x45\x56',
+                                                        _EMPTY_FLAGS),
+                            cygrpc.SendCloseFromClientOperation(_EMPTY_FLAGS),
+                            cygrpc.ReceiveInitialMetadataOperation(
+                                _EMPTY_FLAGS),
+                            cygrpc.ReceiveMessageOperation(_EMPTY_FLAGS),
+                            cygrpc.ReceiveStatusOnClientOperation(_EMPTY_FLAGS),
+                        ),
+                        tag,
+                    ),))
                 client_due.add(tag)
                 client_calls.append(client_call)
 
+        client_events_future = test_utilities.SimpleFuture(
+            lambda: tuple(channel.next_call_event() for _ in range(_SUCCESSFUL_CALLS)))
+
         with state.condition:
             while True:
                 if state.parked_handlers < test_constants.THREAD_CONCURRENCY:
@@ -201,12 +207,14 @@
                     state.condition.notify_all()
                     break
 
-        client_driver.events(
-            test_constants.RPC_CONCURRENCY * _SUCCESS_CALL_FRACTION)
+        client_events_future.result()
         with client_condition:
             for client_call in client_calls:
-                client_call.cancel()
+                client_call.cancel(cygrpc.StatusCode.cancelled, 'Cancelled!')
+        for _ in range(_UNSUCCESSFUL_CALLS):
+            channel.next_call_event()
 
+        channel.close(cygrpc.StatusCode.unknown, 'Cancelled on channel close!')
         with state.condition:
             server.shutdown(server_completion_queue, _SERVER_SHUTDOWN_TAG)
 
diff --git a/src/python/grpcio_tests/tests/unit/_cython/_channel_test.py b/src/python/grpcio_tests/tests/unit/_cython/_channel_test.py
index 7305d0f..d952860 100644
--- a/src/python/grpcio_tests/tests/unit/_cython/_channel_test.py
+++ b/src/python/grpcio_tests/tests/unit/_cython/_channel_test.py
@@ -21,25 +21,20 @@
 from tests.unit.framework.common import test_constants
 
 
-def _channel_and_completion_queue():
-    channel = cygrpc.Channel(b'localhost:54321', ())
-    completion_queue = cygrpc.CompletionQueue()
-    return channel, completion_queue
+def _channel():
+    return cygrpc.Channel(b'localhost:54321', (), None)
 
 
-def _connectivity_loop(channel, completion_queue):
+def _connectivity_loop(channel):
     for _ in range(100):
         connectivity = channel.check_connectivity_state(True)
-        channel.watch_connectivity_state(connectivity,
-                                         time.time() + 0.2, completion_queue,
-                                         None)
-        completion_queue.poll()
+        channel.watch_connectivity_state(connectivity, time.time() + 0.2)
 
 
 def _create_loop_destroy():
-    channel, completion_queue = _channel_and_completion_queue()
-    _connectivity_loop(channel, completion_queue)
-    completion_queue.shutdown()
+    channel = _channel()
+    _connectivity_loop(channel)
+    channel.close(cygrpc.StatusCode.ok, 'Channel close!')
 
 
 def _in_parallel(behavior, arguments):
@@ -55,12 +50,9 @@
 class ChannelTest(unittest.TestCase):
 
     def test_single_channel_lonely_connectivity(self):
-        channel, completion_queue = _channel_and_completion_queue()
-        _in_parallel(_connectivity_loop, (
-            channel,
-            completion_queue,
-        ))
-        completion_queue.shutdown()
+        channel = _channel()
+        _connectivity_loop(channel)
+        channel.close(cygrpc.StatusCode.ok, 'Channel close!')
 
     def test_multiple_channels_lonely_connectivity(self):
         _in_parallel(_create_loop_destroy, ())
diff --git a/src/python/grpcio_tests/tests/unit/_cython/_common.py b/src/python/grpcio_tests/tests/unit/_cython/_common.py
index 7fd3d19..d8210f3 100644
--- a/src/python/grpcio_tests/tests/unit/_cython/_common.py
+++ b/src/python/grpcio_tests/tests/unit/_cython/_common.py
@@ -100,7 +100,8 @@
         self.server.register_completion_queue(self.server_completion_queue)
         port = self.server.add_http2_port(b'[::]:0')
         self.server.start()
-        self.channel = cygrpc.Channel('localhost:{}'.format(port).encode(), [])
+        self.channel = cygrpc.Channel('localhost:{}'.format(port).encode(), [],
+                                      None)
 
         self._server_shutdown_tag = 'server_shutdown_tag'
         self.server_condition = threading.Condition()
diff --git a/src/python/grpcio_tests/tests/unit/_cython/_no_messages_server_completion_queue_per_call_test.py b/src/python/grpcio_tests/tests/unit/_cython/_no_messages_server_completion_queue_per_call_test.py
index 7caa98f..8a72178 100644
--- a/src/python/grpcio_tests/tests/unit/_cython/_no_messages_server_completion_queue_per_call_test.py
+++ b/src/python/grpcio_tests/tests/unit/_cython/_no_messages_server_completion_queue_per_call_test.py
@@ -19,6 +19,7 @@
 from grpc._cython import cygrpc
 
 from tests.unit._cython import _common
+from tests.unit._cython import test_utilities
 
 
 class Test(_common.RpcTest, unittest.TestCase):
@@ -41,31 +42,27 @@
                 server_request_call_tag,
             })
 
-        client_call = self.channel.create_call(None, _common.EMPTY_FLAGS,
-                                               self.client_completion_queue,
-                                               b'/twinkies', None, None)
         client_receive_initial_metadata_tag = 'client_receive_initial_metadata_tag'
         client_complete_rpc_tag = 'client_complete_rpc_tag'
-        with self.client_condition:
-            client_receive_initial_metadata_start_batch_result = (
-                client_call.start_client_batch([
-                    cygrpc.ReceiveInitialMetadataOperation(_common.EMPTY_FLAGS),
-                ], client_receive_initial_metadata_tag))
-            self.assertEqual(cygrpc.CallError.ok,
-                             client_receive_initial_metadata_start_batch_result)
-            client_complete_rpc_start_batch_result = client_call.start_client_batch(
+        client_call = self.channel.integrated_call(
+            _common.EMPTY_FLAGS, b'/twinkies', None, None,
+            _common.INVOCATION_METADATA, None, [(
                 [
-                    cygrpc.SendInitialMetadataOperation(
-                        _common.INVOCATION_METADATA, _common.EMPTY_FLAGS),
-                    cygrpc.SendCloseFromClientOperation(_common.EMPTY_FLAGS),
-                    cygrpc.ReceiveStatusOnClientOperation(_common.EMPTY_FLAGS),
-                ], client_complete_rpc_tag)
-            self.assertEqual(cygrpc.CallError.ok,
-                             client_complete_rpc_start_batch_result)
-            self.client_driver.add_due({
+                    cygrpc.ReceiveInitialMetadataOperation(_common.EMPTY_FLAGS),
+                ],
                 client_receive_initial_metadata_tag,
-                client_complete_rpc_tag,
-            })
+            )])
+        client_call.operate([
+            cygrpc.SendInitialMetadataOperation(_common.INVOCATION_METADATA,
+                                                _common.EMPTY_FLAGS),
+            cygrpc.SendCloseFromClientOperation(_common.EMPTY_FLAGS),
+            cygrpc.ReceiveStatusOnClientOperation(_common.EMPTY_FLAGS),
+        ], client_complete_rpc_tag)
+
+        client_events_future = test_utilities.SimpleFuture(
+            lambda: [
+                self.channel.next_call_event(),
+                self.channel.next_call_event(),])
 
         server_request_call_event = self.server_driver.event_with_tag(
             server_request_call_tag)
@@ -96,20 +93,23 @@
         server_complete_rpc_event = server_call_driver.event_with_tag(
             server_complete_rpc_tag)
 
-        client_receive_initial_metadata_event = self.client_driver.event_with_tag(
-            client_receive_initial_metadata_tag)
-        client_complete_rpc_event = self.client_driver.event_with_tag(
-            client_complete_rpc_tag)
+        client_events = client_events_future.result()
+        if client_events[0].tag is client_receive_initial_metadata_tag:
+            client_receive_initial_metadata_event = client_events[0]
+            client_complete_rpc_event = client_events[1]
+        else:
+            client_complete_rpc_event = client_events[0]
+            client_receive_initial_metadata_event = client_events[1]
 
         return (
             _common.OperationResult(server_request_call_start_batch_result,
                                     server_request_call_event.completion_type,
                                     server_request_call_event.success),
             _common.OperationResult(
-                client_receive_initial_metadata_start_batch_result,
+                cygrpc.CallError.ok,
                 client_receive_initial_metadata_event.completion_type,
                 client_receive_initial_metadata_event.success),
-            _common.OperationResult(client_complete_rpc_start_batch_result,
+            _common.OperationResult(cygrpc.CallError.ok,
                                     client_complete_rpc_event.completion_type,
                                     client_complete_rpc_event.success),
             _common.OperationResult(
diff --git a/src/python/grpcio_tests/tests/unit/_cython/_no_messages_single_server_completion_queue_test.py b/src/python/grpcio_tests/tests/unit/_cython/_no_messages_single_server_completion_queue_test.py
index 8582a39..47f39eb 100644
--- a/src/python/grpcio_tests/tests/unit/_cython/_no_messages_single_server_completion_queue_test.py
+++ b/src/python/grpcio_tests/tests/unit/_cython/_no_messages_single_server_completion_queue_test.py
@@ -19,6 +19,7 @@
 from grpc._cython import cygrpc
 
 from tests.unit._cython import _common
+from tests.unit._cython import test_utilities
 
 
 class Test(_common.RpcTest, unittest.TestCase):
@@ -36,28 +37,31 @@
                 server_request_call_tag,
             })
 
-        client_call = self.channel.create_call(None, _common.EMPTY_FLAGS,
-                                               self.client_completion_queue,
-                                               b'/twinkies', None, None)
         client_receive_initial_metadata_tag = 'client_receive_initial_metadata_tag'
         client_complete_rpc_tag = 'client_complete_rpc_tag'
-        with self.client_condition:
-            client_receive_initial_metadata_start_batch_result = (
-                client_call.start_client_batch([
-                    cygrpc.ReceiveInitialMetadataOperation(_common.EMPTY_FLAGS),
-                ], client_receive_initial_metadata_tag))
-            client_complete_rpc_start_batch_result = client_call.start_client_batch(
-                [
-                    cygrpc.SendInitialMetadataOperation(
-                        _common.INVOCATION_METADATA, _common.EMPTY_FLAGS),
-                    cygrpc.SendCloseFromClientOperation(_common.EMPTY_FLAGS),
-                    cygrpc.ReceiveStatusOnClientOperation(_common.EMPTY_FLAGS),
-                ], client_complete_rpc_tag)
-            self.client_driver.add_due({
-                client_receive_initial_metadata_tag,
-                client_complete_rpc_tag,
-            })
+        client_call = self.channel.integrated_call(
+            _common.EMPTY_FLAGS, b'/twinkies', None, None,
+            _common.INVOCATION_METADATA, None, [
+                (
+                    [
+                        cygrpc.SendInitialMetadataOperation(
+                            _common.INVOCATION_METADATA, _common.EMPTY_FLAGS),
+                        cygrpc.SendCloseFromClientOperation(
+                            _common.EMPTY_FLAGS),
+                        cygrpc.ReceiveStatusOnClientOperation(
+                            _common.EMPTY_FLAGS),
+                    ],
+                    client_complete_rpc_tag,
+                ),
+            ])
+        client_call.operate([
+            cygrpc.ReceiveInitialMetadataOperation(_common.EMPTY_FLAGS),
+        ], client_receive_initial_metadata_tag)
 
+        client_events_future = test_utilities.SimpleFuture(
+            lambda: [
+                self.channel.next_call_event(),
+                self.channel.next_call_event(),])
         server_request_call_event = self.server_driver.event_with_tag(
             server_request_call_tag)
 
@@ -87,20 +91,19 @@
         server_complete_rpc_event = self.server_driver.event_with_tag(
             server_complete_rpc_tag)
 
-        client_receive_initial_metadata_event = self.client_driver.event_with_tag(
-            client_receive_initial_metadata_tag)
-        client_complete_rpc_event = self.client_driver.event_with_tag(
-            client_complete_rpc_tag)
+        client_events = client_events_future.result()
+        client_receive_initial_metadata_event = client_events[0]
+        client_complete_rpc_event = client_events[1]
 
         return (
             _common.OperationResult(server_request_call_start_batch_result,
                                     server_request_call_event.completion_type,
                                     server_request_call_event.success),
             _common.OperationResult(
-                client_receive_initial_metadata_start_batch_result,
+                cygrpc.CallError.ok,
                 client_receive_initial_metadata_event.completion_type,
                 client_receive_initial_metadata_event.success),
-            _common.OperationResult(client_complete_rpc_start_batch_result,
+            _common.OperationResult(cygrpc.CallError.ok,
                                     client_complete_rpc_event.completion_type,
                                     client_complete_rpc_event.success),
             _common.OperationResult(
diff --git a/src/python/grpcio_tests/tests/unit/_cython/_read_some_but_not_all_responses_test.py b/src/python/grpcio_tests/tests/unit/_cython/_read_some_but_not_all_responses_test.py
index bc63b54..8a903bf 100644
--- a/src/python/grpcio_tests/tests/unit/_cython/_read_some_but_not_all_responses_test.py
+++ b/src/python/grpcio_tests/tests/unit/_cython/_read_some_but_not_all_responses_test.py
@@ -17,6 +17,7 @@
 import unittest
 
 from grpc._cython import cygrpc
+from tests.unit._cython import test_utilities
 
 _EMPTY_FLAGS = 0
 _EMPTY_METADATA = ()
@@ -118,7 +119,8 @@
         server.register_completion_queue(server_completion_queue)
         port = server.add_http2_port(b'[::]:0')
         server.start()
-        channel = cygrpc.Channel('localhost:{}'.format(port).encode(), set())
+        channel = cygrpc.Channel('localhost:{}'.format(port).encode(), set(),
+                                 None)
 
         server_shutdown_tag = 'server_shutdown_tag'
         server_driver = _ServerDriver(server_completion_queue,
@@ -127,10 +129,6 @@
 
         client_condition = threading.Condition()
         client_due = set()
-        client_completion_queue = cygrpc.CompletionQueue()
-        client_driver = _QueueDriver(client_condition, client_completion_queue,
-                                     client_due)
-        client_driver.start()
 
         server_call_condition = threading.Condition()
         server_send_initial_metadata_tag = 'server_send_initial_metadata_tag'
@@ -154,25 +152,28 @@
                                                   server_completion_queue,
                                                   server_rpc_tag)
 
-        client_call = channel.create_call(None, _EMPTY_FLAGS,
-                                          client_completion_queue, b'/twinkies',
-                                          None, None)
         client_receive_initial_metadata_tag = 'client_receive_initial_metadata_tag'
         client_complete_rpc_tag = 'client_complete_rpc_tag'
-        with client_condition:
-            client_receive_initial_metadata_start_batch_result = (
-                client_call.start_client_batch([
-                    cygrpc.ReceiveInitialMetadataOperation(_EMPTY_FLAGS),
-                ], client_receive_initial_metadata_tag))
-            client_due.add(client_receive_initial_metadata_tag)
-            client_complete_rpc_start_batch_result = (
-                client_call.start_client_batch([
-                    cygrpc.SendInitialMetadataOperation(_EMPTY_METADATA,
-                                                        _EMPTY_FLAGS),
-                    cygrpc.SendCloseFromClientOperation(_EMPTY_FLAGS),
-                    cygrpc.ReceiveStatusOnClientOperation(_EMPTY_FLAGS),
-                ], client_complete_rpc_tag))
-            client_due.add(client_complete_rpc_tag)
+        client_call = channel.segregated_call(
+            _EMPTY_FLAGS, b'/twinkies', None, None, _EMPTY_METADATA, None, (
+                (
+                    [
+                        cygrpc.ReceiveInitialMetadataOperation(_EMPTY_FLAGS),
+                    ],
+                    client_receive_initial_metadata_tag,
+                ),
+                (
+                    [
+                        cygrpc.SendInitialMetadataOperation(
+                            _EMPTY_METADATA, _EMPTY_FLAGS),
+                        cygrpc.SendCloseFromClientOperation(_EMPTY_FLAGS),
+                        cygrpc.ReceiveStatusOnClientOperation(_EMPTY_FLAGS),
+                    ],
+                    client_complete_rpc_tag,
+                ),
+            ))
+        client_receive_initial_metadata_event_future = test_utilities.SimpleFuture(
+            client_call.next_event)
 
         server_rpc_event = server_driver.first_event()
 
@@ -208,19 +209,20 @@
             server_complete_rpc_tag)
         server_call_driver.events()
 
-        with client_condition:
-            client_receive_first_message_tag = 'client_receive_first_message_tag'
-            client_receive_first_message_start_batch_result = (
-                client_call.start_client_batch([
-                    cygrpc.ReceiveMessageOperation(_EMPTY_FLAGS),
-                ], client_receive_first_message_tag))
-            client_due.add(client_receive_first_message_tag)
-        client_receive_first_message_event = client_driver.event_with_tag(
-            client_receive_first_message_tag)
+        client_recieve_initial_metadata_event = client_receive_initial_metadata_event_future.result(
+        )
 
-        client_call_cancel_result = client_call.cancel()
-        client_driver.events()
+        client_receive_first_message_tag = 'client_receive_first_message_tag'
+        client_call.operate([
+            cygrpc.ReceiveMessageOperation(_EMPTY_FLAGS),
+        ], client_receive_first_message_tag)
+        client_receive_first_message_event = client_call.next_event()
 
+        client_call_cancel_result = client_call.cancel(
+            cygrpc.StatusCode.cancelled, 'Cancelled during test!')
+        client_complete_rpc_event = client_call.next_event()
+
+        channel.close(cygrpc.StatusCode.unknown, 'Channel closed!')
         server.shutdown(server_completion_queue, server_shutdown_tag)
         server.cancel_all_calls()
         server_driver.events()
@@ -228,11 +230,6 @@
         self.assertEqual(cygrpc.CallError.ok, request_call_result)
         self.assertEqual(cygrpc.CallError.ok,
                          server_send_initial_metadata_start_batch_result)
-        self.assertEqual(cygrpc.CallError.ok,
-                         client_receive_initial_metadata_start_batch_result)
-        self.assertEqual(cygrpc.CallError.ok,
-                         client_complete_rpc_start_batch_result)
-        self.assertEqual(cygrpc.CallError.ok, client_call_cancel_result)
         self.assertIs(server_rpc_tag, server_rpc_event.tag)
         self.assertEqual(cygrpc.CompletionType.operation_complete,
                          server_rpc_event.completion_type)
diff --git a/src/python/grpcio_tests/tests/unit/_cython/cygrpc_test.py b/src/python/grpcio_tests/tests/unit/_cython/cygrpc_test.py
index 9045ff5..724a690 100644
--- a/src/python/grpcio_tests/tests/unit/_cython/cygrpc_test.py
+++ b/src/python/grpcio_tests/tests/unit/_cython/cygrpc_test.py
@@ -51,8 +51,8 @@
         del server
 
     def testChannelUpDown(self):
-        channel = cygrpc.Channel(b'[::]:0', None)
-        del channel
+        channel = cygrpc.Channel(b'[::]:0', None, None)
+        channel.close(cygrpc.StatusCode.cancelled, 'Test method anyway!')
 
     def test_metadata_plugin_call_credentials_up_down(self):
         cygrpc.MetadataPluginCallCredentials(_metadata_plugin,
@@ -121,7 +121,7 @@
                                                  client_credentials)
         else:
             self.client_channel = cygrpc.Channel('localhost:{}'.format(
-                self.port).encode(), set())
+                self.port).encode(), set(), None)
         if host_override:
             self.host_argument = None  # default host
             self.expected_host = host_override
@@ -131,17 +131,20 @@
             self.expected_host = self.host_argument
 
     def tearDownMixin(self):
+        self.client_channel.close(cygrpc.StatusCode.ok, 'test being torn down!')
+        del self.client_channel
         del self.server
         del self.client_completion_queue
         del self.server_completion_queue
 
-    def _perform_operations(self, operations, call, queue, deadline,
-                            description):
-        """Perform the list of operations with given call, queue, and deadline.
+    def _perform_queue_operations(self, operations, call, queue, deadline,
+                                  description):
+        """Perform the operations with given call, queue, and deadline.
 
-    Invocation errors are reported with as an exception with `description` in
-    the message. Performs the operations asynchronously, returning a future.
-    """
+        Invocation errors are reported with as an exception with `description`
+        in the message. Performs the operations asynchronously, returning a
+        future.
+        """
 
         def performer():
             tag = object()
@@ -185,9 +188,6 @@
         self.assertEqual(cygrpc.CallError.ok, request_call_result)
 
         client_call_tag = object()
-        client_call = self.client_channel.create_call(
-            None, 0, self.client_completion_queue, METHOD, self.host_argument,
-            DEADLINE)
         client_initial_metadata = (
             (
                 CLIENT_METADATA_ASCII_KEY,
@@ -198,18 +198,24 @@
                 CLIENT_METADATA_BIN_VALUE,
             ),
         )
-        client_start_batch_result = client_call.start_client_batch([
-            cygrpc.SendInitialMetadataOperation(client_initial_metadata,
-                                                _EMPTY_FLAGS),
-            cygrpc.SendMessageOperation(REQUEST, _EMPTY_FLAGS),
-            cygrpc.SendCloseFromClientOperation(_EMPTY_FLAGS),
-            cygrpc.ReceiveInitialMetadataOperation(_EMPTY_FLAGS),
-            cygrpc.ReceiveMessageOperation(_EMPTY_FLAGS),
-            cygrpc.ReceiveStatusOnClientOperation(_EMPTY_FLAGS),
-        ], client_call_tag)
-        self.assertEqual(cygrpc.CallError.ok, client_start_batch_result)
-        client_event_future = test_utilities.CompletionQueuePollFuture(
-            self.client_completion_queue, DEADLINE)
+        client_call = self.client_channel.integrated_call(
+            0, METHOD, self.host_argument, DEADLINE, client_initial_metadata,
+            None, [
+                (
+                    [
+                        cygrpc.SendInitialMetadataOperation(
+                            client_initial_metadata, _EMPTY_FLAGS),
+                        cygrpc.SendMessageOperation(REQUEST, _EMPTY_FLAGS),
+                        cygrpc.SendCloseFromClientOperation(_EMPTY_FLAGS),
+                        cygrpc.ReceiveInitialMetadataOperation(_EMPTY_FLAGS),
+                        cygrpc.ReceiveMessageOperation(_EMPTY_FLAGS),
+                        cygrpc.ReceiveStatusOnClientOperation(_EMPTY_FLAGS),
+                    ],
+                    client_call_tag,
+                ),
+            ])
+        client_event_future = test_utilities.SimpleFuture(
+            self.client_channel.next_call_event)
 
         request_event = self.server_completion_queue.poll(deadline=DEADLINE)
         self.assertEqual(cygrpc.CompletionType.operation_complete,
@@ -285,7 +291,7 @@
         self.assertEqual(5, len(server_event.batch_operations))
         found_server_op_types = set()
         for server_result in server_event.batch_operations:
-            self.assertNotIn(client_result.type(), found_server_op_types)
+            self.assertNotIn(server_result.type(), found_server_op_types)
             found_server_op_types.add(server_result.type())
             if server_result.type() == cygrpc.OperationType.receive_message:
                 self.assertEqual(REQUEST, server_result.message())
@@ -304,66 +310,76 @@
         del client_call
         del server_call
 
-    def test6522(self):
+    def test_6522(self):
         DEADLINE = time.time() + 5
         DEADLINE_TOLERANCE = 0.25
         METHOD = b'twinkies'
 
         empty_metadata = ()
 
+        # Prologue
         server_request_tag = object()
         self.server.request_call(self.server_completion_queue,
                                  self.server_completion_queue,
                                  server_request_tag)
-        client_call = self.client_channel.create_call(
-            None, 0, self.client_completion_queue, METHOD, self.host_argument,
-            DEADLINE)
+        client_call = self.client_channel.segregated_call(
+            0, METHOD, self.host_argument, DEADLINE, None, None, ([(
+                [
+                    cygrpc.SendInitialMetadataOperation(empty_metadata,
+                                                        _EMPTY_FLAGS),
+                    cygrpc.ReceiveInitialMetadataOperation(_EMPTY_FLAGS),
+                ],
+                object(),
+            ), (
+                [
+                    cygrpc.ReceiveStatusOnClientOperation(_EMPTY_FLAGS),
+                ],
+                object(),
+            )]))
 
-        # Prologue
-        def perform_client_operations(operations, description):
-            return self._perform_operations(operations, client_call,
-                                            self.client_completion_queue,
-                                            DEADLINE, description)
-
-        client_event_future = perform_client_operations([
-            cygrpc.SendInitialMetadataOperation(empty_metadata, _EMPTY_FLAGS),
-            cygrpc.ReceiveInitialMetadataOperation(_EMPTY_FLAGS),
-        ], "Client prologue")
+        client_initial_metadata_event_future = test_utilities.SimpleFuture(
+            client_call.next_event)
 
         request_event = self.server_completion_queue.poll(deadline=DEADLINE)
         server_call = request_event.call
 
         def perform_server_operations(operations, description):
-            return self._perform_operations(operations, server_call,
-                                            self.server_completion_queue,
-                                            DEADLINE, description)
+            return self._perform_queue_operations(operations, server_call,
+                                                  self.server_completion_queue,
+                                                  DEADLINE, description)
 
         server_event_future = perform_server_operations([
             cygrpc.SendInitialMetadataOperation(empty_metadata, _EMPTY_FLAGS),
         ], "Server prologue")
 
-        client_event_future.result()  # force completion
+        client_initial_metadata_event_future.result()  # force completion
         server_event_future.result()
 
         # Messaging
         for _ in range(10):
-            client_event_future = perform_client_operations([
+            client_call.operate([
                 cygrpc.SendMessageOperation(b'', _EMPTY_FLAGS),
                 cygrpc.ReceiveMessageOperation(_EMPTY_FLAGS),
             ], "Client message")
+            client_message_event_future = test_utilities.SimpleFuture(
+                client_call.next_event)
             server_event_future = perform_server_operations([
                 cygrpc.SendMessageOperation(b'', _EMPTY_FLAGS),
                 cygrpc.ReceiveMessageOperation(_EMPTY_FLAGS),
             ], "Server receive")
 
-            client_event_future.result()  # force completion
+            client_message_event_future.result()  # force completion
             server_event_future.result()
 
         # Epilogue
-        client_event_future = perform_client_operations([
+        client_call.operate([
             cygrpc.SendCloseFromClientOperation(_EMPTY_FLAGS),
-            cygrpc.ReceiveStatusOnClientOperation(_EMPTY_FLAGS)
         ], "Client epilogue")
+        # One for ReceiveStatusOnClient, one for SendCloseFromClient.
+        client_events_future = test_utilities.SimpleFuture(
+            lambda: {
+                client_call.next_event(),
+                client_call.next_event(),})
 
         server_event_future = perform_server_operations([
             cygrpc.ReceiveCloseOnServerOperation(_EMPTY_FLAGS),
@@ -371,7 +387,7 @@
                 empty_metadata, cygrpc.StatusCode.ok, b'', _EMPTY_FLAGS)
         ], "Server epilogue")
 
-        client_event_future.result()  # force completion
+        client_events_future.result()  # force completion
         server_event_future.result()
 
 
diff --git a/src/python/grpcio_tests/tests/unit/_cython/test_utilities.py b/src/python/grpcio_tests/tests/unit/_cython/test_utilities.py
index 4a00b9e..7d5eaaa 100644
--- a/src/python/grpcio_tests/tests/unit/_cython/test_utilities.py
+++ b/src/python/grpcio_tests/tests/unit/_cython/test_utilities.py
@@ -25,7 +25,7 @@
         def wrapped_function():
             try:
                 self._result = function(*args, **kwargs)
-            except Exception as error:
+            except Exception as error:  # pylint: disable=broad-except
                 self._error = error
 
         self._result = None
@@ -41,7 +41,7 @@
         self._thread.join()
         if self._error:
             # TODO(atash): re-raise exceptions in a way that preserves tracebacks
-            raise self._error
+            raise self._error  # pylint: disable=raising-bad-type
         return self._result
 
 
diff --git a/src/python/grpcio_tests/tests/unit/_exit_test.py b/src/python/grpcio_tests/tests/unit/_exit_test.py
index 6e6d9de..f40f3ae 100644
--- a/src/python/grpcio_tests/tests/unit/_exit_test.py
+++ b/src/python/grpcio_tests/tests/unit/_exit_test.py
@@ -49,7 +49,7 @@
         for process in processes:
             try:
                 process.kill()
-            except Exception:
+            except Exception:  # pylint: disable=broad-except
                 pass
 
 
diff --git a/src/python/grpcio_tests/tests/unit/_from_grpc_import_star.py b/src/python/grpcio_tests/tests/unit/_from_grpc_import_star.py
index e683131..ad847ae 100644
--- a/src/python/grpcio_tests/tests/unit/_from_grpc_import_star.py
+++ b/src/python/grpcio_tests/tests/unit/_from_grpc_import_star.py
@@ -14,7 +14,7 @@
 
 _BEFORE_IMPORT = tuple(globals())
 
-from grpc import *
+from grpc import *  # pylint: disable=wildcard-import
 
 _AFTER_IMPORT = tuple(globals())
 
diff --git a/src/python/grpcio_tests/tests/unit/_invalid_metadata_test.py b/src/python/grpcio_tests/tests/unit/_invalid_metadata_test.py
index 4edf0fc..f153089 100644
--- a/src/python/grpcio_tests/tests/unit/_invalid_metadata_test.py
+++ b/src/python/grpcio_tests/tests/unit/_invalid_metadata_test.py
@@ -81,29 +81,16 @@
         request = b'\x07\x08'
         metadata = (('InVaLiD', 'UnaryRequestFutureUnaryResponse'),)
         expected_error_details = "metadata was invalid: %s" % metadata
-        response_future = self._unary_unary.future(request, metadata=metadata)
-        with self.assertRaises(grpc.RpcError) as exception_context:
-            response_future.result()
-        self.assertEqual(exception_context.exception.details(),
-                         expected_error_details)
-        self.assertEqual(exception_context.exception.code(),
-                         grpc.StatusCode.INTERNAL)
-        self.assertEqual(response_future.details(), expected_error_details)
-        self.assertEqual(response_future.code(), grpc.StatusCode.INTERNAL)
+        with self.assertRaises(ValueError) as exception_context:
+            self._unary_unary.future(request, metadata=metadata)
 
     def testUnaryRequestStreamResponse(self):
         request = b'\x37\x58'
         metadata = (('InVaLiD', 'UnaryRequestStreamResponse'),)
         expected_error_details = "metadata was invalid: %s" % metadata
-        response_iterator = self._unary_stream(request, metadata=metadata)
-        with self.assertRaises(grpc.RpcError) as exception_context:
-            next(response_iterator)
-        self.assertEqual(exception_context.exception.details(),
-                         expected_error_details)
-        self.assertEqual(exception_context.exception.code(),
-                         grpc.StatusCode.INTERNAL)
-        self.assertEqual(response_iterator.details(), expected_error_details)
-        self.assertEqual(response_iterator.code(), grpc.StatusCode.INTERNAL)
+        with self.assertRaises(ValueError) as exception_context:
+            self._unary_stream(request, metadata=metadata)
+        self.assertIn(expected_error_details, str(exception_context.exception))
 
     def testStreamRequestBlockingUnaryResponse(self):
         request_iterator = (
@@ -129,32 +116,18 @@
             b'\x07\x08' for _ in range(test_constants.STREAM_LENGTH))
         metadata = (('InVaLiD', 'StreamRequestFutureUnaryResponse'),)
         expected_error_details = "metadata was invalid: %s" % metadata
-        response_future = self._stream_unary.future(
-            request_iterator, metadata=metadata)
-        with self.assertRaises(grpc.RpcError) as exception_context:
-            response_future.result()
-        self.assertEqual(exception_context.exception.details(),
-                         expected_error_details)
-        self.assertEqual(exception_context.exception.code(),
-                         grpc.StatusCode.INTERNAL)
-        self.assertEqual(response_future.details(), expected_error_details)
-        self.assertEqual(response_future.code(), grpc.StatusCode.INTERNAL)
+        with self.assertRaises(ValueError) as exception_context:
+            self._stream_unary.future(request_iterator, metadata=metadata)
+        self.assertIn(expected_error_details, str(exception_context.exception))
 
     def testStreamRequestStreamResponse(self):
         request_iterator = (
             b'\x07\x08' for _ in range(test_constants.STREAM_LENGTH))
         metadata = (('InVaLiD', 'StreamRequestStreamResponse'),)
         expected_error_details = "metadata was invalid: %s" % metadata
-        response_iterator = self._stream_stream(
-            request_iterator, metadata=metadata)
-        with self.assertRaises(grpc.RpcError) as exception_context:
-            next(response_iterator)
-        self.assertEqual(exception_context.exception.details(),
-                         expected_error_details)
-        self.assertEqual(exception_context.exception.code(),
-                         grpc.StatusCode.INTERNAL)
-        self.assertEqual(response_iterator.details(), expected_error_details)
-        self.assertEqual(response_iterator.code(), grpc.StatusCode.INTERNAL)
+        with self.assertRaises(ValueError) as exception_context:
+            self._stream_stream(request_iterator, metadata=metadata)
+        self.assertIn(expected_error_details, str(exception_context.exception))
 
 
 if __name__ == '__main__':
diff --git a/src/python/grpcio_tests/tests/unit/_invocation_defects_test.py b/src/python/grpcio_tests/tests/unit/_invocation_defects_test.py
index e40cca8..93a5fdf 100644
--- a/src/python/grpcio_tests/tests/unit/_invocation_defects_test.py
+++ b/src/python/grpcio_tests/tests/unit/_invocation_defects_test.py
@@ -165,11 +165,13 @@
 
     def __next__(self):
         if self._current >= self._high:
-            raise Exception("This is a deliberate failure in a unit test.")
+            raise test_control.Defect()
         else:
             self._current += 1
             return self._bytestring
 
+    next = __next__
+
 
 def _unary_unary_multi_callable(channel):
     return channel.unary_unary(_UNARY_UNARY)
diff --git a/src/python/grpcio_tests/tests/unit/_thread_cleanup_test.py b/src/python/grpcio_tests/tests/unit/_thread_cleanup_test.py
deleted file mode 100644
index 18f5af0..0000000
--- a/src/python/grpcio_tests/tests/unit/_thread_cleanup_test.py
+++ /dev/null
@@ -1,115 +0,0 @@
-# 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.
-"""Tests for CleanupThread."""
-
-import threading
-import time
-import unittest
-
-from grpc import _common
-
-_SHORT_TIME = 0.5
-_LONG_TIME = 5.0
-_EPSILON = 0.5
-
-
-def cleanup(timeout):
-    if timeout is not None:
-        time.sleep(timeout)
-    else:
-        time.sleep(_LONG_TIME)
-
-
-def slow_cleanup(timeout):
-    # Don't respect timeout
-    time.sleep(_LONG_TIME)
-
-
-class CleanupThreadTest(unittest.TestCase):
-
-    def testTargetInvocation(self):
-        event = threading.Event()
-
-        def target(arg1, arg2, arg3=None):
-            self.assertEqual('arg1', arg1)
-            self.assertEqual('arg2', arg2)
-            self.assertEqual('arg3', arg3)
-            event.set()
-
-        cleanup_thread = _common.CleanupThread(
-            behavior=lambda x: None,
-            target=target,
-            name='test-name',
-            args=('arg1', 'arg2'),
-            kwargs={
-                'arg3': 'arg3'
-            })
-        cleanup_thread.start()
-        cleanup_thread.join()
-        self.assertEqual(cleanup_thread.name, 'test-name')
-        self.assertTrue(event.is_set())
-
-    def testJoinNoTimeout(self):
-        cleanup_thread = _common.CleanupThread(behavior=cleanup)
-        cleanup_thread.start()
-        start_time = time.time()
-        cleanup_thread.join()
-        end_time = time.time()
-        self.assertAlmostEqual(
-            _LONG_TIME, end_time - start_time, delta=_EPSILON)
-
-    def testJoinTimeout(self):
-        cleanup_thread = _common.CleanupThread(behavior=cleanup)
-        cleanup_thread.start()
-        start_time = time.time()
-        cleanup_thread.join(_SHORT_TIME)
-        end_time = time.time()
-        self.assertAlmostEqual(
-            _SHORT_TIME, end_time - start_time, delta=_EPSILON)
-
-    def testJoinTimeoutSlowBehavior(self):
-        cleanup_thread = _common.CleanupThread(behavior=slow_cleanup)
-        cleanup_thread.start()
-        start_time = time.time()
-        cleanup_thread.join(_SHORT_TIME)
-        end_time = time.time()
-        self.assertAlmostEqual(
-            _LONG_TIME, end_time - start_time, delta=_EPSILON)
-
-    def testJoinTimeoutSlowTarget(self):
-        event = threading.Event()
-
-        def target():
-            event.wait(_LONG_TIME)
-
-        cleanup_thread = _common.CleanupThread(behavior=cleanup, target=target)
-        cleanup_thread.start()
-        start_time = time.time()
-        cleanup_thread.join(_SHORT_TIME)
-        end_time = time.time()
-        self.assertAlmostEqual(
-            _SHORT_TIME, end_time - start_time, delta=_EPSILON)
-        event.set()
-
-    def testJoinZeroTimeout(self):
-        cleanup_thread = _common.CleanupThread(behavior=cleanup)
-        cleanup_thread.start()
-        start_time = time.time()
-        cleanup_thread.join(0)
-        end_time = time.time()
-        self.assertAlmostEqual(0, end_time - start_time, delta=_EPSILON)
-
-
-if __name__ == '__main__':
-    unittest.main(verbosity=2)
diff --git a/src/python/grpcio_tests/tests/unit/beta/_beta_features_test.py b/src/python/grpcio_tests/tests/unit/beta/_beta_features_test.py
index 61c03f6..b43c647 100644
--- a/src/python/grpcio_tests/tests/unit/beta/_beta_features_test.py
+++ b/src/python/grpcio_tests/tests/unit/beta/_beta_features_test.py
@@ -65,7 +65,7 @@
             self._serviced = True
             self._condition.notify_all()
             return
-            yield
+            yield  # pylint: disable=unreachable
 
     def stream_unary(self, request_iterator, context):
         for request in request_iterator:
diff --git a/src/ruby/end2end/client_memory_usage_client.rb b/src/ruby/end2end/client_memory_usage_client.rb
new file mode 100755
index 0000000..c6268b4
--- /dev/null
+++ b/src/ruby/end2end/client_memory_usage_client.rb
@@ -0,0 +1,44 @@
+#!/usr/bin/env ruby
+
+# Copyright 2018 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.
+
+require_relative './end2end_common'
+require 'objspace'
+
+def main
+  server_port = ''
+  loop_count = 200
+
+  OptionParser.new do |opts|
+    opts.on('--client_control_port=P', String) do
+      STDERR.puts 'client_control_port ignored'
+    end
+    opts.on('--server_port=P', String) do |p|
+      server_port = p
+    end
+  end.parse!
+
+  loop_count.times do
+    stub = Echo::EchoServer::Stub.new("localhost:#{server_port}", :this_channel_is_insecure)
+    stub.echo(Echo::EchoRequest.new(request: 'client/child'))
+
+    # Get memory usage of all objects
+    ObjectSpace.memsize_of_all
+  end
+
+  STDERR.puts "Succeeded in getting memory usage for #{loop_count} times"
+end
+
+main
diff --git a/src/ruby/end2end/client_memory_usage_driver.rb b/src/ruby/end2end/client_memory_usage_driver.rb
new file mode 100755
index 0000000..9e46d7e
--- /dev/null
+++ b/src/ruby/end2end/client_memory_usage_driver.rb
@@ -0,0 +1,36 @@
+#!/usr/bin/env ruby
+
+# Copyright 2018 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.
+
+require_relative './end2end_common'
+
+def main
+  STDERR.puts 'start server'
+  server_runner = ServerRunner.new(EchoServerImpl)
+  server_port = server_runner.run
+  STDERR.puts 'start client'
+  _, client_pid = start_client('client_memory_usage_client.rb', server_port)
+
+  Process.wait(client_pid)
+
+  client_exit_code = $CHILD_STATUS
+  if client_exit_code != 0
+    raise "Getting memory usage was failed, exit code #{client_exit_code}"
+  end
+ensure
+  server_runner.stop
+end
+
+main
diff --git a/src/ruby/end2end/multiple_killed_watching_threads_driver.rb b/src/ruby/end2end/multiple_killed_watching_threads_driver.rb
index 8f078cf..8ec2073 100755
--- a/src/ruby/end2end/multiple_killed_watching_threads_driver.rb
+++ b/src/ruby/end2end/multiple_killed_watching_threads_driver.rb
@@ -54,8 +54,14 @@
 end
 
 def main
+  STDERR.puts '10 iterations, sleep 0.1 before killing thread'
   run_multiple_killed_watches(10, 0.1)
+  STDERR.puts '1000 iterations, sleep 0.001 before killing thread'
   run_multiple_killed_watches(1000, 0.001)
+  STDERR.puts '10000 iterations, sleep 0.00001 before killing thread'
+  run_multiple_killed_watches(10_000, 0.00001)
+  STDERR.puts '20000 iterations, sleep 0.00001 before killing thread'
+  run_multiple_killed_watches(20_000, 0.00001)
 end
 
 main
diff --git a/src/ruby/ext/grpc/extconf.rb b/src/ruby/ext/grpc/extconf.rb
index e8e87e4..4760f33 100644
--- a/src/ruby/ext/grpc/extconf.rb
+++ b/src/ruby/ext/grpc/extconf.rb
@@ -84,7 +84,7 @@
 end
 
 if grpc_config == 'dbg'
-  $CFLAGS << ' -O0'
+  $CFLAGS << ' -O0 -ggdb3'
 end
 
 $LDFLAGS << ' -Wl,-wrap,memcpy' if RUBY_PLATFORM =~ /linux/
diff --git a/src/ruby/ext/grpc/rb_call.c b/src/ruby/ext/grpc/rb_call.c
index 7f3ca2a..b6c0791 100644
--- a/src/ruby/ext/grpc/rb_call.c
+++ b/src/ruby/ext/grpc/rb_call.c
@@ -103,23 +103,11 @@
   xfree(p);
 }
 
-static size_t md_ary_datasize(const void* p) {
-  const grpc_metadata_array* const ary = (grpc_metadata_array*)p;
-  size_t i, datasize = sizeof(grpc_metadata_array);
-  for (i = 0; i < ary->count; ++i) {
-    const grpc_metadata* const md = &ary->metadata[i];
-    datasize += GRPC_SLICE_LENGTH(md->key);
-    datasize += GRPC_SLICE_LENGTH(md->value);
-  }
-  datasize += ary->capacity * sizeof(grpc_metadata);
-  return datasize;
-}
-
 static const rb_data_type_t grpc_rb_md_ary_data_type = {
     "grpc_metadata_array",
     {GRPC_RB_GC_NOT_MARKED,
      GRPC_RB_GC_DONT_FREE,
-     md_ary_datasize,
+     GRPC_RB_MEMSIZE_UNAVAILABLE,
      {NULL, NULL}},
     NULL,
     NULL,
diff --git a/src/ruby/ext/grpc/rb_channel.c b/src/ruby/ext/grpc/rb_channel.c
index e8bfeb3..3f0dc53 100644
--- a/src/ruby/ext/grpc/rb_channel.c
+++ b/src/ruby/ext/grpc/rb_channel.c
@@ -315,7 +315,7 @@
 }
 
 typedef struct watch_state_stack {
-  grpc_channel* channel;
+  bg_watched_channel* bg_wrapped;
   gpr_timespec deadline;
   int last_state;
 } watch_state_stack;
@@ -328,15 +328,15 @@
   gpr_mu_lock(&global_connection_polling_mu);
   // its unsafe to do a "watch" after "channel polling abort" because the cq has
   // been shut down.
-  if (abort_channel_polling) {
+  if (abort_channel_polling || stack->bg_wrapped->channel_destroyed) {
     gpr_mu_unlock(&global_connection_polling_mu);
     return (void*)0;
   }
   op = gpr_zalloc(sizeof(watch_state_op));
   op->op_type = WATCH_STATE_API;
-  grpc_channel_watch_connectivity_state(stack->channel, stack->last_state,
-                                        stack->deadline, channel_polling_cq,
-                                        op);
+  grpc_channel_watch_connectivity_state(stack->bg_wrapped->channel,
+                                        stack->last_state, stack->deadline,
+                                        channel_polling_cq, op);
 
   while (!op->op.api_callback_args.called_back) {
     gpr_cv_wait(&global_connection_polling_cv, &global_connection_polling_mu,
@@ -388,7 +388,7 @@
     return Qnil;
   }
 
-  stack.channel = wrapper->bg_wrapped->channel;
+  stack.bg_wrapped = wrapper->bg_wrapped;
   stack.deadline = grpc_rb_time_timeval(deadline, 0),
   stack.last_state = NUM2LONG(last_state);
 
diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.c b/src/ruby/ext/grpc/rb_grpc_imports.generated.c
index a12819e..02f84c0 100644
--- a/src/ruby/ext/grpc/rb_grpc_imports.generated.c
+++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.c
@@ -138,6 +138,12 @@
 grpc_server_add_secure_http2_port_type grpc_server_add_secure_http2_port_import;
 grpc_call_set_credentials_type grpc_call_set_credentials_import;
 grpc_server_credentials_set_auth_metadata_processor_type grpc_server_credentials_set_auth_metadata_processor_import;
+grpc_alts_credentials_client_options_create_type grpc_alts_credentials_client_options_create_import;
+grpc_alts_credentials_server_options_create_type grpc_alts_credentials_server_options_create_import;
+grpc_alts_credentials_client_options_add_target_service_account_type grpc_alts_credentials_client_options_add_target_service_account_import;
+grpc_alts_credentials_options_destroy_type grpc_alts_credentials_options_destroy_import;
+grpc_alts_credentials_create_type grpc_alts_credentials_create_import;
+grpc_alts_server_credentials_create_type grpc_alts_server_credentials_create_import;
 grpc_raw_byte_buffer_create_type grpc_raw_byte_buffer_create_import;
 grpc_raw_compressed_byte_buffer_create_type grpc_raw_compressed_byte_buffer_create_import;
 grpc_byte_buffer_copy_type grpc_byte_buffer_copy_import;
@@ -208,6 +214,7 @@
 gpr_cpu_current_cpu_type gpr_cpu_current_cpu_import;
 gpr_log_severity_string_type gpr_log_severity_string_import;
 gpr_log_type gpr_log_import;
+gpr_should_log_type gpr_should_log_import;
 gpr_log_message_type gpr_log_message_import;
 gpr_set_log_verbosity_type gpr_set_log_verbosity_import;
 gpr_log_verbosity_init_type gpr_log_verbosity_init_import;
@@ -379,6 +386,12 @@
   grpc_server_add_secure_http2_port_import = (grpc_server_add_secure_http2_port_type) GetProcAddress(library, "grpc_server_add_secure_http2_port");
   grpc_call_set_credentials_import = (grpc_call_set_credentials_type) GetProcAddress(library, "grpc_call_set_credentials");
   grpc_server_credentials_set_auth_metadata_processor_import = (grpc_server_credentials_set_auth_metadata_processor_type) GetProcAddress(library, "grpc_server_credentials_set_auth_metadata_processor");
+  grpc_alts_credentials_client_options_create_import = (grpc_alts_credentials_client_options_create_type) GetProcAddress(library, "grpc_alts_credentials_client_options_create");
+  grpc_alts_credentials_server_options_create_import = (grpc_alts_credentials_server_options_create_type) GetProcAddress(library, "grpc_alts_credentials_server_options_create");
+  grpc_alts_credentials_client_options_add_target_service_account_import = (grpc_alts_credentials_client_options_add_target_service_account_type) GetProcAddress(library, "grpc_alts_credentials_client_options_add_target_service_account");
+  grpc_alts_credentials_options_destroy_import = (grpc_alts_credentials_options_destroy_type) GetProcAddress(library, "grpc_alts_credentials_options_destroy");
+  grpc_alts_credentials_create_import = (grpc_alts_credentials_create_type) GetProcAddress(library, "grpc_alts_credentials_create");
+  grpc_alts_server_credentials_create_import = (grpc_alts_server_credentials_create_type) GetProcAddress(library, "grpc_alts_server_credentials_create");
   grpc_raw_byte_buffer_create_import = (grpc_raw_byte_buffer_create_type) GetProcAddress(library, "grpc_raw_byte_buffer_create");
   grpc_raw_compressed_byte_buffer_create_import = (grpc_raw_compressed_byte_buffer_create_type) GetProcAddress(library, "grpc_raw_compressed_byte_buffer_create");
   grpc_byte_buffer_copy_import = (grpc_byte_buffer_copy_type) GetProcAddress(library, "grpc_byte_buffer_copy");
@@ -449,6 +462,7 @@
   gpr_cpu_current_cpu_import = (gpr_cpu_current_cpu_type) GetProcAddress(library, "gpr_cpu_current_cpu");
   gpr_log_severity_string_import = (gpr_log_severity_string_type) GetProcAddress(library, "gpr_log_severity_string");
   gpr_log_import = (gpr_log_type) GetProcAddress(library, "gpr_log");
+  gpr_should_log_import = (gpr_should_log_type) GetProcAddress(library, "gpr_should_log");
   gpr_log_message_import = (gpr_log_message_type) GetProcAddress(library, "gpr_log_message");
   gpr_set_log_verbosity_import = (gpr_set_log_verbosity_type) GetProcAddress(library, "gpr_set_log_verbosity");
   gpr_log_verbosity_init_import = (gpr_log_verbosity_init_type) GetProcAddress(library, "gpr_log_verbosity_init");
diff --git a/src/ruby/ext/grpc/rb_grpc_imports.generated.h b/src/ruby/ext/grpc/rb_grpc_imports.generated.h
index 089cb8a..b2186a6 100644
--- a/src/ruby/ext/grpc/rb_grpc_imports.generated.h
+++ b/src/ruby/ext/grpc/rb_grpc_imports.generated.h
@@ -389,6 +389,24 @@
 typedef void(*grpc_server_credentials_set_auth_metadata_processor_type)(grpc_server_credentials* creds, grpc_auth_metadata_processor processor);
 extern grpc_server_credentials_set_auth_metadata_processor_type grpc_server_credentials_set_auth_metadata_processor_import;
 #define grpc_server_credentials_set_auth_metadata_processor grpc_server_credentials_set_auth_metadata_processor_import
+typedef grpc_alts_credentials_options*(*grpc_alts_credentials_client_options_create_type)();
+extern grpc_alts_credentials_client_options_create_type grpc_alts_credentials_client_options_create_import;
+#define grpc_alts_credentials_client_options_create grpc_alts_credentials_client_options_create_import
+typedef grpc_alts_credentials_options*(*grpc_alts_credentials_server_options_create_type)();
+extern grpc_alts_credentials_server_options_create_type grpc_alts_credentials_server_options_create_import;
+#define grpc_alts_credentials_server_options_create grpc_alts_credentials_server_options_create_import
+typedef void(*grpc_alts_credentials_client_options_add_target_service_account_type)(grpc_alts_credentials_options* options, const char* service_account);
+extern grpc_alts_credentials_client_options_add_target_service_account_type grpc_alts_credentials_client_options_add_target_service_account_import;
+#define grpc_alts_credentials_client_options_add_target_service_account grpc_alts_credentials_client_options_add_target_service_account_import
+typedef void(*grpc_alts_credentials_options_destroy_type)(grpc_alts_credentials_options* options);
+extern grpc_alts_credentials_options_destroy_type grpc_alts_credentials_options_destroy_import;
+#define grpc_alts_credentials_options_destroy grpc_alts_credentials_options_destroy_import
+typedef grpc_channel_credentials*(*grpc_alts_credentials_create_type)(const grpc_alts_credentials_options* options);
+extern grpc_alts_credentials_create_type grpc_alts_credentials_create_import;
+#define grpc_alts_credentials_create grpc_alts_credentials_create_import
+typedef grpc_server_credentials*(*grpc_alts_server_credentials_create_type)(const grpc_alts_credentials_options* options);
+extern grpc_alts_server_credentials_create_type grpc_alts_server_credentials_create_import;
+#define grpc_alts_server_credentials_create grpc_alts_server_credentials_create_import
 typedef grpc_byte_buffer*(*grpc_raw_byte_buffer_create_type)(grpc_slice* slices, size_t nslices);
 extern grpc_raw_byte_buffer_create_type grpc_raw_byte_buffer_create_import;
 #define grpc_raw_byte_buffer_create grpc_raw_byte_buffer_create_import
@@ -599,6 +617,9 @@
 typedef void(*gpr_log_type)(const char* file, int line, gpr_log_severity severity, const char* format, ...) GPR_PRINT_FORMAT_CHECK(4, 5);
 extern gpr_log_type gpr_log_import;
 #define gpr_log gpr_log_import
+typedef int(*gpr_should_log_type)(gpr_log_severity severity);
+extern gpr_should_log_type gpr_should_log_import;
+#define gpr_should_log gpr_should_log_import
 typedef void(*gpr_log_message_type)(const char* file, int line, gpr_log_severity severity, const char* message);
 extern gpr_log_message_type gpr_log_message_import;
 #define gpr_log_message gpr_log_message_import
diff --git a/src/ruby/lib/grpc/generic/bidi_call.rb b/src/ruby/lib/grpc/generic/bidi_call.rb
index 086455d..ffb232b 100644
--- a/src/ruby/lib/grpc/generic/bidi_call.rb
+++ b/src/ruby/lib/grpc/generic/bidi_call.rb
@@ -124,12 +124,18 @@
     def read_using_run_batch
       ops = { RECV_MESSAGE => nil }
       ops[RECV_INITIAL_METADATA] = nil unless @metadata_received
-      batch_result = @call.run_batch(ops)
-      unless @metadata_received
-        @call.metadata = batch_result.metadata
-        @metadata_received = true
+      begin
+        batch_result = @call.run_batch(ops)
+        unless @metadata_received
+          @call.metadata = batch_result.metadata
+          @metadata_received = true
+        end
+        batch_result
+      rescue GRPC::Core::CallError => e
+        GRPC.logger.warn('bidi call: read_using_run_batch failed')
+        GRPC.logger.warn(e)
+        nil
       end
-      batch_result
     end
 
     # set_output_stream_done is relevant on client-side
@@ -155,7 +161,12 @@
       GRPC.logger.debug("bidi-write-loop: #{count} writes done")
       if is_client
         GRPC.logger.debug("bidi-write-loop: client sent #{count}, waiting")
-        @call.run_batch(SEND_CLOSE_FROM_CLIENT => nil)
+        begin
+          @call.run_batch(SEND_CLOSE_FROM_CLIENT => nil)
+        rescue GRPC::Core::CallError => e
+          GRPC.logger.warn('bidi-write-loop: send close failed')
+          GRPC.logger.warn(e)
+        end
         GRPC.logger.debug('bidi-write-loop: done')
       end
       GRPC.logger.debug('bidi-write-loop: finished')
@@ -187,7 +198,7 @@
           batch_result = read_using_run_batch
 
           # handle the next message
-          if batch_result.message.nil?
+          if batch_result.nil? || batch_result.message.nil?
             GRPC.logger.debug("bidi-read-loop: null batch #{batch_result}")
 
             if is_client
diff --git a/src/ruby/lib/grpc/version.rb b/src/ruby/lib/grpc/version.rb
index 256a543..15f3751 100644
--- a/src/ruby/lib/grpc/version.rb
+++ b/src/ruby/lib/grpc/version.rb
@@ -14,5 +14,5 @@
 
 # GRPC contains the General RPC module.
 module GRPC
-  VERSION = '1.11.0.dev'
+  VERSION = '1.13.0.dev'
 end
diff --git a/src/ruby/pb/generate_proto_ruby.sh b/src/ruby/pb/generate_proto_ruby.sh
index d25eff5..ec6e2ee 100755
--- a/src/ruby/pb/generate_proto_ruby.sh
+++ b/src/ruby/pb/generate_proto_ruby.sh
@@ -32,7 +32,13 @@
     --plugin=$PLUGIN
 
 $PROTOC -I . \
-    src/proto/grpc/testing/{messages,payloads,stats,services,control}.proto \
+    src/proto/grpc/core/stats.proto \
+    --grpc_out=src/ruby/qps \
+    --ruby_out=src/ruby/qps \
+    --plugin=$PLUGIN
+
+$PROTOC -I . \
+    src/proto/grpc/testing/{messages,payloads,stats,benchmark_service,report_qps_scenario_service,worker_service,control}.proto \
     --grpc_out=src/ruby/qps \
     --ruby_out=src/ruby/qps \
     --plugin=$PLUGIN
diff --git a/src/ruby/pb/grpc/health/v1/health_services_pb.rb b/src/ruby/pb/grpc/health/v1/health_services_pb.rb
index 520f8e7..169e160 100644
--- a/src/ruby/pb/grpc/health/v1/health_services_pb.rb
+++ b/src/ruby/pb/grpc/health/v1/health_services_pb.rb
@@ -1,7 +1,7 @@
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
 # Source: grpc/health/v1/health.proto for package 'grpc.health.v1'
 # Original file comments:
-# Copyright 2015 gRPC authors.
+# Copyright 2015 The gRPC Authors
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -15,6 +15,9 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
+# The canonical version of this proto can be found at
+# https://github.com/grpc/grpc-proto/blob/master/grpc/health/v1/health.proto
+#
 
 require 'grpc'
 require 'grpc/health/v1/health_pb'
diff --git a/src/ruby/qps/client.rb b/src/ruby/qps/client.rb
index 0426aee..d573d82 100644
--- a/src/ruby/qps/client.rb
+++ b/src/ruby/qps/client.rb
@@ -23,7 +23,7 @@
 
 require 'grpc'
 require 'histogram'
-require 'src/proto/grpc/testing/services_services_pb'
+require 'src/proto/grpc/testing/benchmark_service_services_pb'
 
 class Poisson
   def interarrival
diff --git a/src/ruby/qps/proxy-worker.rb b/src/ruby/qps/proxy-worker.rb
index 4c7c510..5f23d89 100755
--- a/src/ruby/qps/proxy-worker.rb
+++ b/src/ruby/qps/proxy-worker.rb
@@ -27,7 +27,7 @@
 require 'etc'
 require 'facter'
 require 'qps-common'
-require 'src/proto/grpc/testing/services_services_pb'
+require 'src/proto/grpc/testing/worker_service_services_pb'
 require 'src/proto/grpc/testing/proxy-service_services_pb'
 
 class ProxyBenchmarkClientServiceImpl < Grpc::Testing::ProxyClientService::Service
diff --git a/src/ruby/qps/server.rb b/src/ruby/qps/server.rb
index 90218ea..dccc64e 100644
--- a/src/ruby/qps/server.rb
+++ b/src/ruby/qps/server.rb
@@ -24,7 +24,7 @@
 require 'grpc'
 require 'qps-common'
 require 'src/proto/grpc/testing/messages_pb'
-require 'src/proto/grpc/testing/services_services_pb'
+require 'src/proto/grpc/testing/benchmark_service_services_pb'
 require 'src/proto/grpc/testing/stats_pb'
 
 class BenchmarkServiceImpl < Grpc::Testing::BenchmarkService::Service
diff --git a/src/ruby/qps/src/proto/grpc/core/stats_pb.rb b/src/ruby/qps/src/proto/grpc/core/stats_pb.rb
new file mode 100644
index 0000000..59c0578
--- /dev/null
+++ b/src/ruby/qps/src/proto/grpc/core/stats_pb.rb
@@ -0,0 +1,33 @@
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: src/proto/grpc/core/stats.proto
+
+require 'google/protobuf'
+
+Google::Protobuf::DescriptorPool.generated_pool.build do
+  add_message "grpc.core.Bucket" do
+    optional :start, :double, 1
+    optional :count, :uint64, 2
+  end
+  add_message "grpc.core.Histogram" do
+    repeated :buckets, :message, 1, "grpc.core.Bucket"
+  end
+  add_message "grpc.core.Metric" do
+    optional :name, :string, 1
+    oneof :value do
+      optional :count, :uint64, 10
+      optional :histogram, :message, 11, "grpc.core.Histogram"
+    end
+  end
+  add_message "grpc.core.Stats" do
+    repeated :metrics, :message, 1, "grpc.core.Metric"
+  end
+end
+
+module Grpc
+  module Core
+    Bucket = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.core.Bucket").msgclass
+    Histogram = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.core.Histogram").msgclass
+    Metric = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.core.Metric").msgclass
+    Stats = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.core.Stats").msgclass
+  end
+end
diff --git a/src/ruby/qps/src/proto/grpc/testing/services_pb.rb b/src/ruby/qps/src/proto/grpc/testing/benchmark_service_pb.rb
similarity index 71%
copy from src/ruby/qps/src/proto/grpc/testing/services_pb.rb
copy to src/ruby/qps/src/proto/grpc/testing/benchmark_service_pb.rb
index 5ce13bf..0bd3625 100644
--- a/src/ruby/qps/src/proto/grpc/testing/services_pb.rb
+++ b/src/ruby/qps/src/proto/grpc/testing/benchmark_service_pb.rb
@@ -1,10 +1,9 @@
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
-# source: src/proto/grpc/testing/services.proto
+# source: src/proto/grpc/testing/benchmark_service.proto
 
 require 'google/protobuf'
 
 require 'src/proto/grpc/testing/messages_pb'
-require 'src/proto/grpc/testing/control_pb'
 Google::Protobuf::DescriptorPool.generated_pool.build do
 end
 
diff --git a/src/ruby/qps/src/proto/grpc/testing/benchmark_service_services_pb.rb b/src/ruby/qps/src/proto/grpc/testing/benchmark_service_services_pb.rb
new file mode 100644
index 0000000..65e5a75
--- /dev/null
+++ b/src/ruby/qps/src/proto/grpc/testing/benchmark_service_services_pb.rb
@@ -0,0 +1,56 @@
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# Source: src/proto/grpc/testing/benchmark_service.proto for package 'grpc.testing'
+# Original file comments:
+# Copyright 2015 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.
+#
+# An integration test service that covers all the method signature permutations
+# of unary/streaming requests/responses.
+
+require 'grpc'
+require 'src/proto/grpc/testing/benchmark_service_pb'
+
+module Grpc
+  module Testing
+    module BenchmarkService
+      class Service
+
+        include GRPC::GenericService
+
+        self.marshal_class_method = :encode
+        self.unmarshal_class_method = :decode
+        self.service_name = 'grpc.testing.BenchmarkService'
+
+        # One request followed by one response.
+        # The server returns the client payload as-is.
+        rpc :UnaryCall, SimpleRequest, SimpleResponse
+        # Repeated sequence of one request followed by one response.
+        # Should be called streaming ping-pong
+        # The server returns the client payload as-is on each response
+        rpc :StreamingCall, stream(SimpleRequest), stream(SimpleResponse)
+        # Single-sided unbounded streaming from client to server
+        # The server returns the client payload as-is once the client does WritesDone
+        rpc :StreamingFromClient, stream(SimpleRequest), SimpleResponse
+        # Single-sided unbounded streaming from server to client
+        # The server repeatedly returns the client payload as-is
+        rpc :StreamingFromServer, SimpleRequest, stream(SimpleResponse)
+        # Two-sided unbounded streaming between server to client
+        # Both sides send the content of their own choice to the other
+        rpc :StreamingBothWays, stream(SimpleRequest), stream(SimpleResponse)
+      end
+
+      Stub = Service.rpc_stub_class
+    end
+  end
+end
diff --git a/src/ruby/qps/src/proto/grpc/testing/control_pb.rb b/src/ruby/qps/src/proto/grpc/testing/control_pb.rb
index 02207a2..5acc7fc 100644
--- a/src/ruby/qps/src/proto/grpc/testing/control_pb.rb
+++ b/src/ruby/qps/src/proto/grpc/testing/control_pb.rb
@@ -20,6 +20,14 @@
   add_message "grpc.testing.SecurityParams" do
     optional :use_test_ca, :bool, 1
     optional :server_host_override, :string, 2
+    optional :cred_type, :string, 3
+  end
+  add_message "grpc.testing.ChannelArg" do
+    optional :name, :string, 1
+    oneof :value do
+      optional :str_value, :string, 2
+      optional :int_value, :int32, 3
+    end
   end
   add_message "grpc.testing.ClientConfig" do
     repeated :server_targets, :string, 1
@@ -35,6 +43,10 @@
     repeated :core_list, :int32, 13
     optional :core_limit, :int32, 14
     optional :other_client_api, :string, 15
+    repeated :channel_args, :message, 16, "grpc.testing.ChannelArg"
+    optional :threads_per_cq, :int32, 17
+    optional :messages_per_stream, :int32, 18
+    optional :use_coalesce_api, :bool, 19
   end
   add_message "grpc.testing.ClientStatus" do
     optional :stats, :message, 1, "grpc.testing.ClientStats"
@@ -57,6 +69,9 @@
     optional :payload_config, :message, 9, "grpc.testing.PayloadConfig"
     repeated :core_list, :int32, 10
     optional :other_server_api, :string, 11
+    optional :threads_per_cq, :int32, 12
+    optional :resource_quota_size, :int32, 1001
+    repeated :channel_args, :message, 1002, "grpc.testing.ChannelArg"
   end
   add_message "grpc.testing.ServerArgs" do
     oneof :argtype do
@@ -101,6 +116,13 @@
     optional :latency_95, :double, 9
     optional :latency_99, :double, 10
     optional :latency_999, :double, 11
+    optional :server_cpu_usage, :double, 12
+    optional :successful_requests_per_second, :double, 13
+    optional :failed_requests_per_second, :double, 14
+    optional :client_polls_per_request, :double, 15
+    optional :server_polls_per_request, :double, 16
+    optional :server_queries_per_cpu_sec, :double, 17
+    optional :client_queries_per_cpu_sec, :double, 18
   end
   add_message "grpc.testing.ScenarioResult" do
     optional :scenario, :message, 1, "grpc.testing.Scenario"
@@ -111,6 +133,7 @@
     optional :summary, :message, 6, "grpc.testing.ScenarioResultSummary"
     repeated :client_success, :bool, 7
     repeated :server_success, :bool, 8
+    repeated :request_results, :message, 9, "grpc.testing.RequestResultCount"
   end
   add_enum "grpc.testing.ClientType" do
     value :SYNC_CLIENT, 0
@@ -126,6 +149,9 @@
   add_enum "grpc.testing.RpcType" do
     value :UNARY, 0
     value :STREAMING, 1
+    value :STREAMING_FROM_CLIENT, 2
+    value :STREAMING_FROM_SERVER, 3
+    value :STREAMING_BOTH_WAYS, 4
   end
 end
 
@@ -135,6 +161,7 @@
     ClosedLoopParams = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.ClosedLoopParams").msgclass
     LoadParams = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.LoadParams").msgclass
     SecurityParams = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.SecurityParams").msgclass
+    ChannelArg = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.ChannelArg").msgclass
     ClientConfig = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.ClientConfig").msgclass
     ClientStatus = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.ClientStatus").msgclass
     Mark = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.Mark").msgclass
diff --git a/src/ruby/qps/src/proto/grpc/testing/services_pb.rb b/src/ruby/qps/src/proto/grpc/testing/report_qps_scenario_service_pb.rb
similarity index 71%
rename from src/ruby/qps/src/proto/grpc/testing/services_pb.rb
rename to src/ruby/qps/src/proto/grpc/testing/report_qps_scenario_service_pb.rb
index 5ce13bf..1b43e37 100644
--- a/src/ruby/qps/src/proto/grpc/testing/services_pb.rb
+++ b/src/ruby/qps/src/proto/grpc/testing/report_qps_scenario_service_pb.rb
@@ -1,9 +1,8 @@
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
-# source: src/proto/grpc/testing/services.proto
+# source: src/proto/grpc/testing/report_qps_scenario_service.proto
 
 require 'google/protobuf'
 
-require 'src/proto/grpc/testing/messages_pb'
 require 'src/proto/grpc/testing/control_pb'
 Google::Protobuf::DescriptorPool.generated_pool.build do
 end
diff --git a/src/ruby/qps/src/proto/grpc/testing/report_qps_scenario_service_services_pb.rb b/src/ruby/qps/src/proto/grpc/testing/report_qps_scenario_service_services_pb.rb
new file mode 100644
index 0000000..ddc81be
--- /dev/null
+++ b/src/ruby/qps/src/proto/grpc/testing/report_qps_scenario_service_services_pb.rb
@@ -0,0 +1,42 @@
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# Source: src/proto/grpc/testing/report_qps_scenario_service.proto for package 'grpc.testing'
+# Original file comments:
+# Copyright 2015 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.
+#
+# An integration test service that covers all the method signature permutations
+# of unary/streaming requests/responses.
+
+require 'grpc'
+require 'src/proto/grpc/testing/report_qps_scenario_service_pb'
+
+module Grpc
+  module Testing
+    module ReportQpsScenarioService
+      class Service
+
+        include GRPC::GenericService
+
+        self.marshal_class_method = :encode
+        self.unmarshal_class_method = :decode
+        self.service_name = 'grpc.testing.ReportQpsScenarioService'
+
+        # Report results of a QPS test benchmark scenario.
+        rpc :ReportScenario, ScenarioResult, Void
+      end
+
+      Stub = Service.rpc_stub_class
+    end
+  end
+end
diff --git a/src/ruby/qps/src/proto/grpc/testing/stats_pb.rb b/src/ruby/qps/src/proto/grpc/testing/stats_pb.rb
index 41f75be..2069840 100644
--- a/src/ruby/qps/src/proto/grpc/testing/stats_pb.rb
+++ b/src/ruby/qps/src/proto/grpc/testing/stats_pb.rb
@@ -3,11 +3,16 @@
 
 require 'google/protobuf'
 
+require 'src/proto/grpc/core/stats_pb'
 Google::Protobuf::DescriptorPool.generated_pool.build do
   add_message "grpc.testing.ServerStats" do
     optional :time_elapsed, :double, 1
     optional :time_user, :double, 2
     optional :time_system, :double, 3
+    optional :total_cpu_time, :uint64, 4
+    optional :idle_cpu_time, :uint64, 5
+    optional :cq_poll_count, :uint64, 6
+    optional :core_stats, :message, 7, "grpc.core.Stats"
   end
   add_message "grpc.testing.HistogramParams" do
     optional :resolution, :double, 1
@@ -21,11 +26,18 @@
     optional :sum_of_squares, :double, 5
     optional :count, :double, 6
   end
+  add_message "grpc.testing.RequestResultCount" do
+    optional :status_code, :int32, 1
+    optional :count, :int64, 2
+  end
   add_message "grpc.testing.ClientStats" do
     optional :latencies, :message, 1, "grpc.testing.HistogramData"
     optional :time_elapsed, :double, 2
     optional :time_user, :double, 3
     optional :time_system, :double, 4
+    repeated :request_results, :message, 5, "grpc.testing.RequestResultCount"
+    optional :cq_poll_count, :uint64, 6
+    optional :core_stats, :message, 7, "grpc.core.Stats"
   end
 end
 
@@ -34,6 +46,7 @@
     ServerStats = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.ServerStats").msgclass
     HistogramParams = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.HistogramParams").msgclass
     HistogramData = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.HistogramData").msgclass
+    RequestResultCount = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.RequestResultCount").msgclass
     ClientStats = Google::Protobuf::DescriptorPool.generated_pool.lookup("grpc.testing.ClientStats").msgclass
   end
 end
diff --git a/src/ruby/qps/src/proto/grpc/testing/services_pb.rb b/src/ruby/qps/src/proto/grpc/testing/worker_service_pb.rb
similarity index 71%
copy from src/ruby/qps/src/proto/grpc/testing/services_pb.rb
copy to src/ruby/qps/src/proto/grpc/testing/worker_service_pb.rb
index 5ce13bf..18b6345 100644
--- a/src/ruby/qps/src/proto/grpc/testing/services_pb.rb
+++ b/src/ruby/qps/src/proto/grpc/testing/worker_service_pb.rb
@@ -1,9 +1,8 @@
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
-# source: src/proto/grpc/testing/services.proto
+# source: src/proto/grpc/testing/worker_service.proto
 
 require 'google/protobuf'
 
-require 'src/proto/grpc/testing/messages_pb'
 require 'src/proto/grpc/testing/control_pb'
 Google::Protobuf::DescriptorPool.generated_pool.build do
 end
diff --git a/src/ruby/qps/src/proto/grpc/testing/services_services_pb.rb b/src/ruby/qps/src/proto/grpc/testing/worker_service_services_pb.rb
similarity index 74%
rename from src/ruby/qps/src/proto/grpc/testing/services_services_pb.rb
rename to src/ruby/qps/src/proto/grpc/testing/worker_service_services_pb.rb
index 1d8b619..a7ecc95 100644
--- a/src/ruby/qps/src/proto/grpc/testing/services_services_pb.rb
+++ b/src/ruby/qps/src/proto/grpc/testing/worker_service_services_pb.rb
@@ -1,5 +1,5 @@
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
-# Source: src/proto/grpc/testing/services.proto for package 'grpc.testing'
+# Source: src/proto/grpc/testing/worker_service.proto for package 'grpc.testing'
 # Original file comments:
 # Copyright 2015 gRPC authors.
 #
@@ -19,29 +19,10 @@
 # of unary/streaming requests/responses.
 
 require 'grpc'
-require 'src/proto/grpc/testing/services_pb'
+require 'src/proto/grpc/testing/worker_service_pb'
 
 module Grpc
   module Testing
-    module BenchmarkService
-      class Service
-
-        include GRPC::GenericService
-
-        self.marshal_class_method = :encode
-        self.unmarshal_class_method = :decode
-        self.service_name = 'grpc.testing.BenchmarkService'
-
-        # One request followed by one response.
-        # The server returns the client payload as-is.
-        rpc :UnaryCall, SimpleRequest, SimpleResponse
-        # One request followed by one response.
-        # The server returns the client payload as-is.
-        rpc :StreamingCall, stream(SimpleRequest), stream(SimpleResponse)
-      end
-
-      Stub = Service.rpc_stub_class
-    end
     module WorkerService
       class Service
 
diff --git a/src/ruby/qps/worker.rb b/src/ruby/qps/worker.rb
index 8258487..633ff13 100755
--- a/src/ruby/qps/worker.rb
+++ b/src/ruby/qps/worker.rb
@@ -29,7 +29,7 @@
 require 'client'
 require 'qps-common'
 require 'server'
-require 'src/proto/grpc/testing/services_services_pb'
+require 'src/proto/grpc/testing/worker_service_services_pb'
 
 class WorkerServiceImpl < Grpc::Testing::WorkerService::Service
   def cpu_cores
diff --git a/src/ruby/spec/generic/client_stub_spec.rb b/src/ruby/spec/generic/client_stub_spec.rb
index d858c4e..da50f8d 100644
--- a/src/ruby/spec/generic/client_stub_spec.rb
+++ b/src/ruby/spec/generic/client_stub_spec.rb
@@ -750,6 +750,90 @@
                                                   expected_error_message)
         end
       end
+
+      # Prompted by grpc/github #14853
+      describe 'client-side error handling on bidi streams' do
+        class EnumeratorQueue
+          def initialize(queue)
+            @queue = queue
+          end
+
+          def each
+            loop do
+              msg = @queue.pop
+              break if msg.nil?
+              yield msg
+            end
+          end
+        end
+
+        def run_server_bidi_shutdown_after_one_read
+          @server.start
+          recvd_rpc = @server.request_call
+          recvd_call = recvd_rpc.call
+          server_call = GRPC::ActiveCall.new(
+            recvd_call, noop, noop, INFINITE_FUTURE,
+            metadata_received: true, started: false)
+          expect(server_call.remote_read).to eq('first message')
+          @server.shutdown_and_notify(from_relative_time(0))
+          @server.close
+        end
+
+        it 'receives a grpc status code when writes to a bidi stream fail' do
+          # This test tries to trigger the case when a 'SEND_MESSAGE' op
+          # and subseqeunt 'SEND_CLOSE_FROM_CLIENT' op of a bidi stream fails.
+          # In this case, iteration through the response stream should result
+          # in a grpc status code, and the writer thread should not raise an
+          # exception.
+          server_thread = Thread.new do
+            run_server_bidi_shutdown_after_one_read
+          end
+          stub = GRPC::ClientStub.new(@host, :this_channel_is_insecure)
+          request_queue = Queue.new
+          @sent_msgs = EnumeratorQueue.new(request_queue)
+          responses = get_responses(stub)
+          request_queue.push('first message')
+          # Now wait for the server to shut down.
+          server_thread.join
+          # Sanity check. This test is not interesting if
+          # Thread.abort_on_exception is not set.
+          expect(Thread.abort_on_exception).to be(true)
+          # An attempt to send a second message should fail now that the
+          # server is down.
+          request_queue.push('second message')
+          request_queue.push(nil)
+          expect { responses.next }.to raise_error(GRPC::BadStatus)
+        end
+
+        def run_server_bidi_shutdown_after_one_write
+          @server.start
+          recvd_rpc = @server.request_call
+          recvd_call = recvd_rpc.call
+          server_call = GRPC::ActiveCall.new(
+            recvd_call, noop, noop, INFINITE_FUTURE,
+            metadata_received: true, started: false)
+          server_call.send_initial_metadata
+          server_call.remote_send('message')
+          @server.shutdown_and_notify(from_relative_time(0))
+          @server.close
+        end
+
+        it 'receives a grpc status code when reading from a failed bidi call' do
+          server_thread = Thread.new do
+            run_server_bidi_shutdown_after_one_write
+          end
+          stub = GRPC::ClientStub.new(@host, :this_channel_is_insecure)
+          request_queue = Queue.new
+          @sent_msgs = EnumeratorQueue.new(request_queue)
+          responses = get_responses(stub)
+          expect(responses.next).to eq('message')
+          # Wait for the server to shut down
+          server_thread.join
+          expect { responses.next }.to raise_error(GRPC::BadStatus)
+          # Push a sentinel to allow the writer thread to finish
+          request_queue.push(nil)
+        end
+      end
     end
 
     describe 'without a call operation' do
@@ -810,6 +894,55 @@
           responses.each { |r| p r }
         end
       end
+
+      def run_server_bidi_expect_client_to_cancel(wait_for_shutdown_ok_callback)
+        @server.start
+        recvd_rpc = @server.request_call
+        recvd_call = recvd_rpc.call
+        server_call = GRPC::ActiveCall.new(
+          recvd_call, noop, noop, INFINITE_FUTURE,
+          metadata_received: true, started: false)
+        server_call.send_initial_metadata
+        server_call.remote_send('server call received')
+        wait_for_shutdown_ok_callback.call
+        # since the client is cancelling the call,
+        # we should be able to shut down cleanly
+        @server.shutdown_and_notify(nil)
+        @server.close
+      end
+
+      it 'receives a grpc status code when reading from a cancelled bidi call' do
+        # This test tries to trigger a 'RECV_INITIAL_METADATA' and/or
+        # 'RECV_MESSAGE' op failure.
+        # An attempt to read a message might fail; in that case, iteration
+        # through the response stream should still result in a grpc status.
+        server_can_shutdown = false
+        server_can_shutdown_mu = Mutex.new
+        server_can_shutdown_cv = ConditionVariable.new
+        wait_for_shutdown_ok_callback = proc do
+          server_can_shutdown_mu.synchronize do
+            server_can_shutdown_cv.wait(server_can_shutdown_mu) until server_can_shutdown
+          end
+        end
+        server_thread = Thread.new do
+          run_server_bidi_expect_client_to_cancel(wait_for_shutdown_ok_callback)
+        end
+        stub = GRPC::ClientStub.new(@host, :this_channel_is_insecure)
+        request_queue = Queue.new
+        @sent_msgs = EnumeratorQueue.new(request_queue)
+        responses = get_responses(stub)
+        expect(responses.next).to eq('server call received')
+        @op.cancel
+        expect { responses.next }.to raise_error(GRPC::Cancelled)
+        # Now let the server proceed to shut down.
+        server_can_shutdown_mu.synchronize do
+          server_can_shutdown = true
+          server_can_shutdown_cv.broadcast
+        end
+        server_thread.join
+        # Push a sentinel to allow the writer thread to finish
+        request_queue.push(nil)
+      end
     end
   end
 
diff --git a/src/ruby/spec/pb/package_with_underscore/checker_spec.rb b/src/ruby/spec/pb/package_with_underscore/checker_spec.rb
new file mode 100644
index 0000000..dac7c14
--- /dev/null
+++ b/src/ruby/spec/pb/package_with_underscore/checker_spec.rb
@@ -0,0 +1,51 @@
+# 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.
+
+require 'open3'
+require 'tmpdir'
+
+describe 'Package with underscore protobuf code generation' do
+  it 'should have the same content as created by code generation' do
+    root_dir = File.join(File.dirname(__FILE__), '..', '..', '..', '..', '..')
+    pb_dir = File.join(root_dir, 'src', 'ruby', 'spec', 'pb')
+
+    fail 'CONFIG env variable unexpectedly unset' unless ENV['CONFIG']
+    bins_sub_dir = ENV['CONFIG']
+    bins_dir = File.join(root_dir, 'bins', bins_sub_dir)
+
+    plugin = File.join(bins_dir, 'grpc_ruby_plugin')
+    protoc = File.join(bins_dir, 'protobuf', 'protoc')
+
+    got = nil
+
+    Dir.mktmpdir do |tmp_dir|
+      gen_out = File.join(tmp_dir, 'package_with_underscore', 'service_services_pb.rb')
+
+      pid = spawn(
+        protoc,
+        '-I.',
+        'package_with_underscore/service.proto',
+        "--grpc_out=#{tmp_dir}",
+        "--plugin=protoc-gen-grpc=#{plugin}",
+        chdir: pb_dir)
+      Process.waitpid2(pid)
+      File.open(gen_out) { |f| got = f.read }
+    end
+
+    correct_modularized_rpc = 'rpc :TestOne, '                \
+      'Grpc::Testing::PackageWithUnderscore::Data::Request, ' \
+      'Grpc::Testing::PackageWithUnderscore::Data::Response'
+    expect(got).to include(correct_modularized_rpc)
+  end
+end
diff --git a/src/ruby/spec/pb/package_with_underscore/data.proto b/src/ruby/spec/pb/package_with_underscore/data.proto
new file mode 100644
index 0000000..2706f1d
--- /dev/null
+++ b/src/ruby/spec/pb/package_with_underscore/data.proto
@@ -0,0 +1,23 @@
+// Copyright 2018 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.
+
+syntax = "proto3";
+
+package grpc.testing.package_with_underscore.data;
+
+message Request {
+}
+
+message Response {
+}
diff --git a/src/ruby/spec/pb/package_with_underscore/service.proto b/src/ruby/spec/pb/package_with_underscore/service.proto
new file mode 100644
index 0000000..814c789
--- /dev/null
+++ b/src/ruby/spec/pb/package_with_underscore/service.proto
@@ -0,0 +1,23 @@
+// Copyright 2018 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.
+
+syntax = "proto3";
+
+package grpc.testing.package_with_underscore.service;
+
+import "package_with_underscore/data.proto";
+
+service MyService {
+  rpc TestOne(data.Request) returns (data.Response) {}
+}
diff --git a/src/ruby/tools/version.rb b/src/ruby/tools/version.rb
index 8dc1623..09d5c82 100644
--- a/src/ruby/tools/version.rb
+++ b/src/ruby/tools/version.rb
@@ -14,6 +14,6 @@
 
 module GRPC
   module Tools
-    VERSION = '1.11.0.dev'
+    VERSION = '1.13.0.dev'
   end
 end
diff --git a/templates/CMakeLists.txt.template b/templates/CMakeLists.txt.template
index 01fe569..06adb33 100644
--- a/templates/CMakeLists.txt.template
+++ b/templates/CMakeLists.txt.template
@@ -82,6 +82,7 @@
   set(gRPC_INSTALL_LIBDIR "lib" CACHE STRING "Installation directory for libraries")
   set(gRPC_INSTALL_INCLUDEDIR "include" CACHE STRING "Installation directory for headers")
   set(gRPC_INSTALL_CMAKEDIR "lib/cmake/<%text>${PACKAGE_NAME}</%text>" CACHE STRING "Installation directory for cmake config files")
+  set(gRPC_INSTALL_SHAREDIR "share/grpc" CACHE STRING "Installation directory for root certificates")
 
   # Options
   option(gRPC_BUILD_TESTS "Build tests" OFF)
@@ -298,11 +299,13 @@
   endif (gRPC_BUILD_TESTS)
   % else:
   ${cc_library(lib)}
+  % if not lib.build in ["tool"]:
   ${cc_install(lib)}
   % endif
   % endif
   % endif
   % endif
+  % endif
   % endfor
 
   % for tgt in targets:
@@ -323,7 +326,9 @@
   % else:
   ${get_platforms_condition_begin(tgt.platforms)}\
   ${cc_binary(tgt)}
+  % if not tgt.build in ["tool"]:
   ${cc_install(tgt)}
+  % endif
   ${get_platforms_condition_end(tgt.platforms)}\
   % endif
   % endif
@@ -503,3 +508,6 @@
       DESTINATION <%text>${gRPC_INSTALL_CMAKEDIR}</%text>
     )
   endforeach()
+  
+  install(FILES <%text>${CMAKE_CURRENT_SOURCE_DIR}/etc/roots.pem</%text>
+    DESTINATION <%text>${gRPC_INSTALL_SHAREDIR}</%text>)
diff --git a/templates/Makefile.template b/templates/Makefile.template
index c0ce2e5..354f2a2 100644
--- a/templates/Makefile.template
+++ b/templates/Makefile.template
@@ -416,7 +416,7 @@
   OPENSSL_ALPN_CHECK_CMD = $(PKG_CONFIG) --atleast-version=1.0.2 openssl
   OPENSSL_NPN_CHECK_CMD = $(PKG_CONFIG) --atleast-version=1.0.1 openssl
   ZLIB_CHECK_CMD = $(PKG_CONFIG) --exists zlib
-  PROTOBUF_CHECK_CMD = $(PKG_CONFIG) --atleast-version=3.0.0 protobuf
+  PROTOBUF_CHECK_CMD = $(PKG_CONFIG) --atleast-version=3.5.0 protobuf
   CARES_CHECK_CMD = $(PKG_CONFIG) --atleast-version=1.11.0 libcares
   else # HAS_PKG_CONFIG
 
@@ -844,7 +844,7 @@
   	@echo
   	@echo "DEPENDENCY ERROR"
   	@echo
-  	@echo "The target you are trying to run requires protobuf 3.0.0+"
+  	@echo "The target you are trying to run requires protobuf 3.5.0+"
   	@echo "Your system doesn't have it, and neither does the third_party directory."
   	@echo
   	@echo "Please consult INSTALL to get more information."
@@ -858,7 +858,7 @@
   	@echo
   	@echo "DEPENDENCY ERROR"
   	@echo
-  	@echo "The target you are trying to run requires protobuf-compiler 3.0.0+"
+  	@echo "The target you are trying to run requires protobuf-compiler 3.5.0+"
   	@echo "Your system doesn't have it, and neither does the third_party directory."
   	@echo
   	@echo "Please consult INSTALL to get more information."
@@ -1636,7 +1636,7 @@
   % endif
   % if lib.language == 'c++':
   ## If the lib was C++, we have to close the Makefile's if that tested
-  ## the presence of protobuf 3.0.0+
+  ## the presence of protobuf 3.5.0+
 
   endif
   % endif
@@ -1702,7 +1702,7 @@
 
   ifeq ($(NO_PROTOBUF),true)
 
-  # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+  # You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.5.0+.
 
   $(BINDIR)/$(CONFIG)/${tgt.name}: protobuf_dep_error
 
diff --git a/templates/config.m4.template b/templates/config.m4.template
index 9877e4b..cc19d98 100644
--- a/templates/config.m4.template
+++ b/templates/config.m4.template
@@ -10,6 +10,7 @@
     PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/include)
     PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/src/php/ext/grpc)
     PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/boringssl/include)
+    PHP_ADD_INCLUDE(PHP_EXT_SRCDIR()/third_party/address_sorting/include)
 
     LIBS="-lpthread $LIBS"
 
diff --git a/templates/config.w32.template b/templates/config.w32.template
index 4edef96..ef25e55 100644
--- a/templates/config.w32.template
+++ b/templates/config.w32.template
@@ -23,11 +23,13 @@
     EXTENSION("grpc", grpc_source, null,
       "/DOPENSSL_NO_ASM /D_GNU_SOURCE /DWIN32_LEAN_AND_MEAN "+
       "/D_HAS_EXCEPTIONS=0 /DNOMINMAX /DGRPC_ARES=0 /D_WIN32_WINNT=0x600 "+
+      "/DPB_FIELD_16BIT "+
       "/I"+configure_module_dirname+" "+
       "/I"+configure_module_dirname+"\\include "+
       "/I"+configure_module_dirname+"\\src\\php\\ext\\grpc "+
       "/I"+configure_module_dirname+"\\third_party\\boringssl\\include "+
-      "/I"+configure_module_dirname+"\\third_party\\zlib");
+      "/I"+configure_module_dirname+"\\third_party\\zlib "+
+      "/I"+configure_module_dirname+"\\third_party\\address_sorting\\include");
   <%
     dirs = {}
     for lib in libs:
diff --git a/templates/gRPC-Core.podspec.template b/templates/gRPC-Core.podspec.template
index 33a8a8b..af97d81 100644
--- a/templates/gRPC-Core.podspec.template
+++ b/templates/gRPC-Core.podspec.template
@@ -42,21 +42,21 @@
     out = grpc_lib_files(libs, ("grpc", "gpr"), ("headers",))
     return [file for file in out if not file.startswith("third_party/nanopb/")]
 
-  def grpc_cronet_private_files(libs):
-    out = grpc_lib_files(libs, ("grpc_cronet", "gpr"), ("headers", "src"))
-    excl = [
-        # We do not want dummy cronet API for ObjC
+  def grpc_cronet_files(libs):
+    out = grpc_lib_files(libs, ("grpc_cronet",), ("src", "headers"))
+    excl = grpc_private_files(libs)
+    excl += [
+        # We do not need cronet dedicated plugin registry
+        "src/core/plugin_registry/grpc_cronet_plugin_registry.cc",
+        # We do not need dummy cronet API for ObjC
         "src/core/ext/transport/cronet/transport/cronet_api_dummy.cc",
     ]
     return [file for file in out if not file in excl]
 
   def grpc_cronet_public_headers(libs):
-    out = grpc_lib_files(libs, ("grpc_cronet", "gpr"), ("public_headers",))
-    return out
-
-  def grpc_cronet_private_headers(libs):
-    out = grpc_lib_files(libs, ("grpc_cronet", "gpr"), ("headers",))
-    return out
+    out = grpc_lib_files(libs, ("grpc_cronet",), ("public_headers",))
+    excl = grpc_public_headers(libs)
+    return [file for file in out if not file in excl]
 
   def grpc_test_util_files(libs):
     out = grpc_lib_files(libs, ("grpc_test_util", "gpr_test_util"), ("src", "headers"))
@@ -169,6 +169,7 @@
       ss.dependency 'BoringSSL', '~> 10.0'
       ss.dependency 'nanopb', '~> 0.3'
 
+      # To save you from scrolling, this is the last part of the podspec.
       ss.source_files = ${ruby_multiline_list(grpc_private_files(libs), 22)}
 
       ss.private_header_files = ${ruby_multiline_list(grpc_private_headers(libs), 30)}
@@ -181,21 +182,19 @@
 
     s.subspec 'Cronet-Implementation' do |ss|
       ss.header_mappings_dir = '.'
-      ss.libraries = 'z'
+
+      ss.dependency "#{s.name}/Interface", version
+      ss.dependency "#{s.name}/Implementation", version
       ss.dependency "#{s.name}/Cronet-Interface", version
-      ss.dependency 'BoringSSL', '~> 10.0'
-      ss.dependency 'nanopb', '~> 0.3'
 
-      ss.source_files = ${ruby_multiline_list(grpc_cronet_private_files(libs), 22)}
-
-      ss.private_header_files = ${ruby_multiline_list(grpc_cronet_private_headers(libs), 30)}
+      ss.source_files = ${ruby_multiline_list(grpc_cronet_files(libs), 22)}
     end
 
-    s.subspec 'Cronet-Tests' do |ss|
+    s.subspec 'Tests' do |ss|
       ss.header_mappings_dir = '.'
 
-      ss.dependency "#{s.name}/Cronet-Interface", version
-      ss.dependency "#{s.name}/Cronet-Implementation", version
+      ss.dependency "#{s.name}/Interface", version
+      ss.dependency "#{s.name}/Implementation", version
 
       ss.source_files = ${ruby_multiline_list(grpc_test_util_files(libs), 22)},
                         ${ruby_multiline_list(end2end_tests_files(libs), 22)}
diff --git a/templates/src/csharp/Grpc.Core/Version.csproj.include.template b/templates/src/csharp/Grpc.Core/Version.csproj.include.template
index 5bc66e9..398b198 100755
--- a/templates/src/csharp/Grpc.Core/Version.csproj.include.template
+++ b/templates/src/csharp/Grpc.Core/Version.csproj.include.template
@@ -4,6 +4,6 @@
   <Project>
     <PropertyGroup>
       <GrpcCsharpVersion>${settings.csharp_version}</GrpcCsharpVersion>
-      <GoogleProtobufVersion>3.3.0</GoogleProtobufVersion>
+      <GoogleProtobufVersion>3.5.1</GoogleProtobufVersion>
     </PropertyGroup>
   </Project>
diff --git a/templates/src/objective-c/GRPCClient/private/version.h.template b/templates/src/objective-c/GRPCClient/private/version.h.template
index 34df24c..22b3bb2 100644
--- a/templates/src/objective-c/GRPCClient/private/version.h.template
+++ b/templates/src/objective-c/GRPCClient/private/version.h.template
@@ -24,5 +24,4 @@
   // instead. This file can be regenerated from the template by running
   // `tools/buildgen/generate_projects.sh`.
 
-
   #define GRPC_OBJC_VERSION_STRING @"${settings.version}"
diff --git a/templates/src/objective-c/tests/version.h.template b/templates/src/objective-c/tests/version.h.template
index 72774ab..a87d43a 100644
--- a/templates/src/objective-c/tests/version.h.template
+++ b/templates/src/objective-c/tests/version.h.template
@@ -24,6 +24,5 @@
   // instead. This file can be regenerated from the template by running
   // `tools/buildgen/generate_projects.sh`.
 
-
   #define GRPC_OBJC_VERSION_STRING @"${settings.version}"
   #define GRPC_C_VERSION_STRING @"${settings.core_version}"
diff --git a/templates/test/cpp/naming/resolver_component_tests_defs.include b/templates/test/cpp/naming/resolver_component_tests_defs.include
index 01e1860..2690af4 100644
--- a/templates/test/cpp/naming/resolver_component_tests_defs.include
+++ b/templates/test/cpp/naming/resolver_component_tests_defs.include
@@ -1,4 +1,4 @@
-<%def name="resolver_component_tests(tests)">#!/bin/bash
+<%def name="resolver_component_tests(tests)">#!/usr/bin/env python
 # Copyright 2015 gRPC authors.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,80 +15,129 @@
 
 # This file is auto-generated
 
-set -ex
+import argparse
+import sys
+import subprocess
+import tempfile
+import os
+import time
+import signal
 
-# all command args required in this set order
-FLAGS_test_bin_path=$(echo "$1" | grep '\--test_bin_path=' | sed 's/^--test_bin_path=//')
-FLAGS_dns_server_bin_path=$(echo "$2" | grep '\--dns_server_bin_path=' | sed 's/^--dns_server_bin_path=//')
-FLAGS_records_config_path=$(echo "$3" | grep '\--records_config_path=' | sed 's/^--records_config_path=//')
-FLAGS_dns_server_port=$(echo "$4" | grep '\--dns_server_port=' | sed 's/^--dns_server_port=//')
-FLAGS_dns_resolver_bin_path=$(echo "$5" | grep '\--dns_resolver_bin_path=' | sed 's/^--dns_resolver_bin_path=//')
-FLAGS_tcp_connect_bin_path=$(echo "$6" | grep '\--tcp_connect_bin_path=' | sed 's/^--tcp_connect_bin_path=//')
 
-for cmd_arg in "$FLAGS_test_bin_path" "$FLAGS_dns_server_bin_path" "$FLAGS_records_config_path" "$FLAGS_dns_server_port" "$FLAGS_dns_resolver_bin_path" "$FLAGS_tcp_connect_bin_path"; do
-  if [[ "$cmd_arg" == "" ]]; then
-    echo "Missing a CMD arg" && exit 1
-  fi
-done
+argp = argparse.ArgumentParser(description='Run c-ares resolver tests')
+argp.add_argument('--test_bin_path', default=None, type=str,
+                  help='Path to gtest test binary to invoke.')
+argp.add_argument('--dns_server_bin_path', default=None, type=str,
+                  help='Path to local DNS server python script.')
+argp.add_argument('--records_config_path', default=None, type=str,
+                  help=('Path to DNS records yaml file that '
+                        'specifies records for the DNS sever. '))
+argp.add_argument('--dns_server_port', default=None, type=int,
+                  help=('Port that local DNS server is listening on.'))
+argp.add_argument('--dns_resolver_bin_path', default=None, type=str,
+                  help=('Path to the DNS health check utility.'))
+argp.add_argument('--tcp_connect_bin_path', default=None, type=str,
+                  help=('Path to the TCP health check utility.'))
+args = argp.parse_args()
 
-if [[ "$GRPC_DNS_RESOLVER" != "" && "$GRPC_DNS_RESOLVER" != ares ]]; then
-  echo "This test only works under GRPC_DNS_RESOLVER=ares. Have GRPC_DNS_RESOLVER=$GRPC_DNS_RESOLVER" && exit 1
-fi
-export GRPC_DNS_RESOLVER=ares
+def test_runner_log(msg):
+  sys.stderr.write('\n%s: %s\n' % (__file__, msg))
 
-"$FLAGS_dns_server_bin_path" --records_config_path="$FLAGS_records_config_path" --port="$FLAGS_dns_server_port" > /dev/null 2>&1 &
-DNS_SERVER_PID=$!
-echo "Local DNS server started. PID: $DNS_SERVER_PID"
+cur_resolver = os.environ.get('GRPC_DNS_RESOLVER')
+if cur_resolver and cur_resolver != 'ares':
+  test_runner_log(('WARNING: cur resolver set to %s. This set of tests '
+      'needs to use GRPC_DNS_RESOLVER=ares.'))
+  test_runner_log('Exit 1 without running tests.')
+  sys.exit(1)
+os.environ.update({'GRPC_DNS_RESOLVER': 'ares'})
 
-# Health check local DNS server TCP and UDP ports
-for ((i=0;i<30;i++));
-do
-  echo "Retry health-check local DNS server by attempting a DNS query and TCP handshake"
-  RETRY=0
-  $FLAGS_dns_resolver_bin_path -s 127.0.0.1 -p "$FLAGS_dns_server_port" -n health-check-local-dns-server-is-alive.resolver-tests.grpctestingexp. -t 1 | grep '123.123.123.123' || RETRY=1
-  $FLAGS_tcp_connect_bin_path -s 127.0.0.1 -p "$FLAGS_dns_server_port" -t 1 || RETRY=1
-  if [[ "$RETRY" == 0 ]]; then
-    break
-  fi;
-  sleep 0.1
-done
+def wait_until_dns_server_is_up(args,
+                                dns_server_subprocess,
+                                dns_server_subprocess_output):
+  for i in range(0, 30):
+    test_runner_log('Health check: attempt to connect to DNS server over TCP.')
+    tcp_connect_subprocess = subprocess.Popen([
+        args.tcp_connect_bin_path,
+        '--server_host', '127.0.0.1',
+        '--server_port', str(args.dns_server_port),
+        '--timeout', str(1)])
+    tcp_connect_subprocess.communicate()
+    if tcp_connect_subprocess.returncode == 0:
+      test_runner_log(('Health check: attempt to make an A-record '
+                       'query to DNS server.'))
+      dns_resolver_subprocess = subprocess.Popen([
+          args.dns_resolver_bin_path,
+          '--qname', 'health-check-local-dns-server-is-alive.resolver-tests.grpctestingexp',
+          '--server_host', '127.0.0.1',
+          '--server_port', str(args.dns_server_port)],
+          stdout=subprocess.PIPE)
+      dns_resolver_stdout, _ = dns_resolver_subprocess.communicate()
+      if dns_resolver_subprocess.returncode == 0:
+        if '123.123.123.123' in dns_resolver_stdout:
+          test_runner_log(('DNS server is up! '
+                           'Successfully reached it over UDP and TCP.'))
+        return
+    time.sleep(0.1)
+  dns_server_subprocess.kill()
+  dns_server_subprocess.wait()
+  test_runner_log(('Failed to reach DNS server over TCP and/or UDP. '
+                   'Exitting without running tests.'))
+  test_runner_log('======= DNS server stdout '
+                  '(merged stdout and stderr) =============')
+  with open(dns_server_subprocess_output, 'r') as l:
+    test_runner_log(l.read())
+  test_runner_log('======= end DNS server output=========')
+  sys.exit(1)
 
-if [[ $RETRY == 1 ]]; then
-  echo "FAILED TO START LOCAL DNS SERVER"
-  kill -SIGTERM "$DNS_SERVER_PID"
-  wait
-  exit 1
-fi
+dns_server_subprocess_output = tempfile.mktemp()
+with open(dns_server_subprocess_output, 'w') as l:
+  dns_server_subprocess = subprocess.Popen([
+      args.dns_server_bin_path,
+      '--port', str(args.dns_server_port),
+      '--records_config_path', args.records_config_path],
+      stdin=subprocess.PIPE,
+      stdout=l,
+      stderr=l)
 
-function terminate_all {
-  echo "Received signal. Terminating $! and $DNS_SERVER_PID"
-  kill -SIGTERM "$!" || true
-  kill -SIGTERM "$DNS_SERVER_PID" || true
-  wait
-  exit 1
-}
+def _quit_on_signal(signum, _frame):
+  test_runner_log('Received signal: %d' % signum)
+  dns_server_subprocess.kill()
+  dns_server_subprocess.wait()
+  sys.exit(1)
 
-trap terminate_all SIGTERM SIGINT
-
-EXIT_CODE=0
-# TODO: this test should check for GCE residency and skip tests using _grpclb._tcp.* SRV records once GCE residency checks are made
-# in the resolver.
+signal.signal(signal.SIGINT, _quit_on_signal)
+signal.signal(signal.SIGTERM, _quit_on_signal)
+wait_until_dns_server_is_up(args,
+                            dns_server_subprocess,
+                            dns_server_subprocess_output)
+num_test_failures = 0
 
 % for test in tests:
-$FLAGS_test_bin_path \\
+test_runner_log('Run test with target: %s' % '${test['target_name']}')\
 
-  --target_name='${test['target_name']}' \\
+current_test_subprocess = subprocess.Popen([\
 
-  --expected_addrs='${test['expected_addrs']}' \\
+  args.test_bin_path,\
 
-  --expected_chosen_service_config='${test['expected_chosen_service_config']}' \\
+  '--target_name', '${test['target_name']}',\
 
-  --expected_lb_policy='${test['expected_lb_policy']}' \\
+  '--expected_addrs', '${test['expected_addrs']}',\
 
-  --local_dns_server_address="127.0.0.1:$FLAGS_dns_server_port" &
-wait "$!" || EXIT_CODE=1
+  '--expected_chosen_service_config', '${test['expected_chosen_service_config']}',\
+
+  '--expected_lb_policy', '${test['expected_lb_policy']}',\
+
+  '--local_dns_server_address', '127.0.0.1:%d' % args.dns_server_port])\
+
+current_test_subprocess.communicate()\
+
+if current_test_subprocess.returncode != 0:\
+
+  num_test_failures += 1
 
 % endfor
-kill -SIGTERM "$DNS_SERVER_PID" || true
-wait
-exit $EXIT_CODE</%def>
+test_runner_log('now kill DNS server')
+dns_server_subprocess.kill()
+dns_server_subprocess.wait()
+test_runner_log('%d tests failed.' % num_test_failures)
+sys.exit(num_test_failures)</%def>
diff --git a/templates/test/cpp/naming/resolver_component_tests_runner.sh.template b/templates/test/cpp/naming/resolver_component_tests_runner.py.template
similarity index 100%
rename from templates/test/cpp/naming/resolver_component_tests_runner.sh.template
rename to templates/test/cpp/naming/resolver_component_tests_runner.py.template
diff --git a/templates/tools/dockerfile/interoptest/grpc_interop_android_java/Dockerfile.template b/templates/tools/dockerfile/interoptest/grpc_interop_android_java/Dockerfile.template
deleted file mode 100644
index 1f6755e..0000000
--- a/templates/tools/dockerfile/interoptest/grpc_interop_android_java/Dockerfile.template
+++ /dev/null
@@ -1,80 +0,0 @@
-%YAML 1.2
---- |
-  # Copyright 2017 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.
-
-  FROM debian:jessie
-
-  # Install JDK 8 and Git
-  RUN echo oracle-java8-installer shared/accepted-oracle-license-v1-1 select true | /usr/bin/debconf-set-selections && ${'\\'}
-    echo "deb http://ppa.launchpad.net/webupd8team/java/ubuntu trusty main" | tee /etc/apt/sources.list.d/webupd8team-java.list && ${'\\'}
-    echo "deb-src http://ppa.launchpad.net/webupd8team/java/ubuntu trusty main" | tee -a /etc/apt/sources.list.d/webupd8team-java.list && ${'\\'}
-    apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys EEA14886
-  RUN apt-get update && apt-get -y install ${'\\'}
-        git ${'\\'}
-        libapr1 ${'\\'}
-        oracle-java8-installer ${'\\'}
-        && ${'\\'}
-      apt-get clean && rm -r /var/cache/oracle-jdk8-installer/
-  ENV JAVA_HOME /usr/lib/jvm/java-8-oracle
-  ENV PATH $PATH:$JAVA_HOME/bin
-
-  # Install protobuf
-  RUN apt-get update && apt-get install -y ${'\\'}
-        autoconf ${'\\'}
-        build-essential ${'\\'}
-        curl ${'\\'}
-        gcc ${'\\'}
-        libtool ${'\\'}
-        unzip ${'\\'}
-        && ${'\\'}
-      apt-get clean
-  WORKDIR /
-  RUN git clone https://github.com/google/protobuf.git
-  WORKDIR /protobuf
-  RUN git checkout v3.3.1 && ${'\\'}
-    ./autogen.sh && ${'\\'}
-    ./configure && ${'\\'}
-    make && ${'\\'}
-    make check && ${'\\'}
-    make install
-
-  # Install gcloud command line tools
-  ENV CLOUD_SDK_REPO "cloud-sdk-jessie"
-  RUN echo "deb http://packages.cloud.google.com/apt $CLOUD_SDK_REPO main" | tee -a /etc/apt/sources.list.d/google-cloud-sdk.list && ${'\\'}
-    curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add - && ${'\\'}
-    apt-get update && apt-get install -y google-cloud-sdk && apt-get clean && ${'\\'}
-    gcloud config set component_manager/disable_update_check true
-
-  # Install Android SDK
-  WORKDIR /
-  RUN mkdir android-sdk
-  WORKDIR android-sdk
-  RUN wget -q https://dl.google.com/android/repository/tools_r25.2.5-linux.zip && ${'\\'}
-    unzip -qq tools_r25.2.5-linux.zip && ${'\\'}
-    rm tools_r25.2.5-linux.zip && ${'\\'}
-    echo y | tools/bin/sdkmanager "platforms;android-22" && ${'\\'}
-    echo y | tools/bin/sdkmanager "build-tools;25.0.2" && ${'\\'}
-    echo y | tools/bin/sdkmanager "extras;android;m2repository" && ${'\\'}
-    echo y | tools/bin/sdkmanager "extras;google;google_play_services" && ${'\\'}
-    echo y | tools/bin/sdkmanager "extras;google;m2repository" && ${'\\'}
-    echo y | tools/bin/sdkmanager "patcher;v4" && ${'\\'}
-    echo y | tools/bin/sdkmanager "platform-tools"
-  ENV ANDROID_HOME "/android-sdk"
-
-  # Reset the working directory
-  WORKDIR /
-
-  # Define the default command.
-  CMD ["bash"]
diff --git a/templates/tools/dockerfile/interoptest/grpc_interop_python/Dockerfile.template b/templates/tools/dockerfile/interoptest/grpc_interop_python/Dockerfile.template
index f5a53f0..bf28796 100644
--- a/templates/tools/dockerfile/interoptest/grpc_interop_python/Dockerfile.template
+++ b/templates/tools/dockerfile/interoptest/grpc_interop_python/Dockerfile.template
@@ -18,6 +18,10 @@
   
   <%include file="../../apt_get_basic.include"/>
   <%include file="../../python_deps.include"/>
+  # Install pip and virtualenv for Python 3.4
+  RUN curl https://bootstrap.pypa.io/get-pip.py | python3.4
+  RUN python3.4 -m pip install virtualenv
+
   <%include file="../../run_tests_addons.include"/>
   # Define the default command.
   CMD ["bash"]
diff --git a/templates/tools/dockerfile/python_deps.include b/templates/tools/dockerfile/python_deps.include
index cd1af22..c7bf238 100644
--- a/templates/tools/dockerfile/python_deps.include
+++ b/templates/tools/dockerfile/python_deps.include
@@ -9,6 +9,6 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.1
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
diff --git a/templates/tools/dockerfile/test/cxx_alpine_x64/Dockerfile.template b/templates/tools/dockerfile/test/cxx_alpine_x64/Dockerfile.template
index 1bbfdfd..d70ad94 100644
--- a/templates/tools/dockerfile/test/cxx_alpine_x64/Dockerfile.template
+++ b/templates/tools/dockerfile/test/cxx_alpine_x64/Dockerfile.template
@@ -34,12 +34,13 @@
     strace ${'\\'}
     python-dev ${'\\'}
     py-pip ${'\\'}
+    py-yaml ${'\\'}
     unzip ${'\\'}
     wget ${'\\'}
     zip
   
   # Install Python packages from PyPI
-  RUN pip install --upgrade pip==9.0.1
+  RUN pip install --upgrade pip==10.0.1
   RUN pip install virtualenv
   RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
   
diff --git a/templates/tools/dockerfile/test/multilang_jessie_x64/Dockerfile.template b/templates/tools/dockerfile/test/multilang_jessie_x64/Dockerfile.template
index 0d47aa9..672e9fb 100644
--- a/templates/tools/dockerfile/test/multilang_jessie_x64/Dockerfile.template
+++ b/templates/tools/dockerfile/test/multilang_jessie_x64/Dockerfile.template
@@ -25,6 +25,10 @@
   <%include file="../../php_deps.include"/>
   <%include file="../../ruby_deps.include"/>
   <%include file="../../python_deps.include"/>
+  # Install pip and virtualenv for Python 3.4
+  RUN curl https://bootstrap.pypa.io/get-pip.py | python3.4
+  RUN python3.4 -m pip install virtualenv
+  
   # Install coverage for Python test coverage reporting
   RUN pip install coverage
   ENV PATH ~/.local/bin:$PATH
diff --git a/templates/tools/dockerfile/test/python_jessie_x64/Dockerfile.template b/templates/tools/dockerfile/test/python_jessie_x64/Dockerfile.template
index dba6a22..e73b839 100644
--- a/templates/tools/dockerfile/test/python_jessie_x64/Dockerfile.template
+++ b/templates/tools/dockerfile/test/python_jessie_x64/Dockerfile.template
@@ -19,6 +19,10 @@
   <%include file="../../apt_get_basic.include"/>
   <%include file="../../gcp_api_libraries.include"/>
   <%include file="../../python_deps.include"/>
+  # Install pip and virtualenv for Python 3.4
+  RUN curl https://bootstrap.pypa.io/get-pip.py | python3.4
+  RUN python3.4 -m pip install virtualenv
+
   <%include file="../../run_tests_addons.include"/>
   # Define the default command.
   CMD ["bash"]
diff --git a/templates/tools/dockerfile/test/python_pyenv_x64/Dockerfile.template b/templates/tools/dockerfile/test/python_pyenv_x64/Dockerfile.template
index 0df19f6..ba65c06 100644
--- a/templates/tools/dockerfile/test/python_pyenv_x64/Dockerfile.template
+++ b/templates/tools/dockerfile/test/python_pyenv_x64/Dockerfile.template
@@ -20,6 +20,10 @@
   <%include file="../../gcp_api_libraries.include"/>
   <%include file="../../python_deps.include"/>
   <%include file="../../apt_get_pyenv.include"/>
+  # Install pip and virtualenv for Python 3.4
+  RUN curl https://bootstrap.pypa.io/get-pip.py | python3.4
+  RUN python3.4 -m pip install virtualenv
+
   <%include file="../../run_tests_addons.include"/>
   # Define the default command.
   CMD ["bash"]
diff --git a/test/core/channel/minimal_stack_is_minimal_test.cc b/test/core/channel/minimal_stack_is_minimal_test.cc
index f02c818..e5953ac 100644
--- a/test/core/channel/minimal_stack_is_minimal_test.cc
+++ b/test/core/channel/minimal_stack_is_minimal_test.cc
@@ -66,35 +66,37 @@
   minimal_stack_arg.key = const_cast<char*>(GRPC_ARG_MINIMAL_STACK);
   minimal_stack_arg.value.integer = 1;
   grpc_channel_args minimal_stack_args = {1, &minimal_stack_arg};
-  errors += CHECK_STACK("unknown", &minimal_stack_args,
-                        GRPC_CLIENT_DIRECT_CHANNEL, "connected", NULL);
+  errors +=
+      CHECK_STACK("unknown", &minimal_stack_args, GRPC_CLIENT_DIRECT_CHANNEL,
+                  "authority", "connected", NULL);
   errors += CHECK_STACK("unknown", &minimal_stack_args, GRPC_CLIENT_SUBCHANNEL,
-                        "connected", NULL);
+                        "authority", "connected", NULL);
   errors += CHECK_STACK("unknown", &minimal_stack_args, GRPC_SERVER_CHANNEL,
                         "server", "connected", NULL);
   errors +=
       CHECK_STACK("chttp2", &minimal_stack_args, GRPC_CLIENT_DIRECT_CHANNEL,
-                  "http-client", "connected", NULL);
+                  "authority", "http-client", "connected", NULL);
   errors += CHECK_STACK("chttp2", &minimal_stack_args, GRPC_CLIENT_SUBCHANNEL,
-                        "http-client", "connected", NULL);
+                        "authority", "http-client", "connected", NULL);
   errors += CHECK_STACK("chttp2", &minimal_stack_args, GRPC_SERVER_CHANNEL,
                         "server", "http-server", "connected", NULL);
   errors += CHECK_STACK(nullptr, &minimal_stack_args, GRPC_CLIENT_CHANNEL,
                         "client-channel", NULL);
 
   // tests with a default stack
-  errors += CHECK_STACK("unknown", nullptr, GRPC_CLIENT_DIRECT_CHANNEL,
-                        "message_size", "deadline", "connected", NULL);
-  errors += CHECK_STACK("unknown", nullptr, GRPC_CLIENT_SUBCHANNEL,
+  errors +=
+      CHECK_STACK("unknown", nullptr, GRPC_CLIENT_DIRECT_CHANNEL, "authority",
+                  "message_size", "deadline", "connected", NULL);
+  errors += CHECK_STACK("unknown", nullptr, GRPC_CLIENT_SUBCHANNEL, "authority",
                         "message_size", "connected", NULL);
   errors += CHECK_STACK("unknown", nullptr, GRPC_SERVER_CHANNEL, "server",
                         "message_size", "deadline", "connected", NULL);
   errors += CHECK_STACK("chttp2", nullptr, GRPC_CLIENT_DIRECT_CHANNEL,
-                        "message_size", "deadline", "http-client",
+                        "authority", "message_size", "deadline", "http-client",
                         "message_compress", "connected", NULL);
-  errors +=
-      CHECK_STACK("chttp2", nullptr, GRPC_CLIENT_SUBCHANNEL, "message_size",
-                  "http-client", "message_compress", "connected", NULL);
+  errors += CHECK_STACK("chttp2", nullptr, GRPC_CLIENT_SUBCHANNEL, "authority",
+                        "message_size", "http-client", "message_compress",
+                        "connected", NULL);
   errors += CHECK_STACK("chttp2", nullptr, GRPC_SERVER_CHANNEL, "server",
                         "message_size", "deadline", "http-server",
                         "message_compress", "connected", NULL);
diff --git a/test/core/client_channel/BUILD b/test/core/client_channel/BUILD
index 5148dc5..db98ffa 100644
--- a/test/core/client_channel/BUILD
+++ b/test/core/client_channel/BUILD
@@ -53,3 +53,18 @@
         "//test/core/util:grpc_test_util",
     ],
 )
+
+grpc_cc_test(
+    name = "retry_throttle_test",
+    srcs = ["retry_throttle_test.cc"],
+    external_deps = [
+        "gtest",
+    ],
+    language = "C++",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:gpr_test_util",
+        "//test/core/util:grpc_test_util",
+    ],
+)
diff --git a/test/core/client_channel/resolvers/dns_resolver_cooldown_test.cc b/test/core/client_channel/resolvers/dns_resolver_cooldown_test.cc
index 01c61a9..37e1d71 100644
--- a/test/core/client_channel/resolvers/dns_resolver_cooldown_test.cc
+++ b/test/core/client_channel/resolvers/dns_resolver_cooldown_test.cc
@@ -145,7 +145,6 @@
   grpc_core::OrphanablePtr<grpc_core::Resolver> resolver;
   grpc_channel_args* result = nullptr;
   grpc_millis delay_before_second_resolution = 0;
-  bool using_cares = false;
 };
 
 // Counter for the number of times a resolution notification callback has been
@@ -155,81 +154,100 @@
 // Set to true by the last callback in the resolution chain.
 bool g_all_callbacks_invoked;
 
-void on_third_resolution(void* arg, grpc_error* error) {
+void on_fourth_resolution(void* arg, grpc_error* error) {
   OnResolutionCallbackArg* cb_arg = static_cast<OnResolutionCallbackArg*>(arg);
+  grpc_channel_args_destroy(cb_arg->result);
   GPR_ASSERT(error == GRPC_ERROR_NONE);
   ++g_on_resolution_invocations_count;
-  grpc_channel_args_destroy(cb_arg->result);
   gpr_log(GPR_INFO,
-          "3rd: g_on_resolution_invocations_count: %d, g_resolution_count: %d",
+          "4th: g_on_resolution_invocations_count: %d, g_resolution_count: %d",
           g_on_resolution_invocations_count, g_resolution_count);
   // In this case we expect to have incurred in another system-level resolution
-  // because on_second_resolution slept for longer than the min resolution
+  // because on_third_resolution slept for longer than the min resolution
   // period.
-  GPR_ASSERT(g_on_resolution_invocations_count == 3);
-  GPR_ASSERT(g_resolution_count == 2);
+  GPR_ASSERT(g_on_resolution_invocations_count == 4);
+  GPR_ASSERT(g_resolution_count == 3);
   cb_arg->resolver.reset();
-  if (cb_arg->using_cares) {
-    gpr_atm_rel_store(&g_iomgr_args.done_atm, 1);
-    gpr_mu_lock(g_iomgr_args.mu);
-    GRPC_LOG_IF_ERROR("pollset_kick",
-                      grpc_pollset_kick(g_iomgr_args.pollset, nullptr));
-    gpr_mu_unlock(g_iomgr_args.mu);
-  }
+  gpr_atm_rel_store(&g_iomgr_args.done_atm, 1);
+  gpr_mu_lock(g_iomgr_args.mu);
+  GRPC_LOG_IF_ERROR("pollset_kick",
+                    grpc_pollset_kick(g_iomgr_args.pollset, nullptr));
+  gpr_mu_unlock(g_iomgr_args.mu);
   grpc_core::Delete(cb_arg);
   g_all_callbacks_invoked = true;
 }
 
+void on_third_resolution(void* arg, grpc_error* error) {
+  OnResolutionCallbackArg* cb_arg = static_cast<OnResolutionCallbackArg*>(arg);
+  grpc_channel_args_destroy(cb_arg->result);
+  GPR_ASSERT(error == GRPC_ERROR_NONE);
+  ++g_on_resolution_invocations_count;
+  gpr_log(GPR_INFO,
+          "3rd: g_on_resolution_invocations_count: %d, g_resolution_count: %d",
+          g_on_resolution_invocations_count, g_resolution_count);
+  // The timer set because of the previous re-resolution request fires, so a new
+  // system-level resolution happened.
+  GPR_ASSERT(g_on_resolution_invocations_count == 3);
+  GPR_ASSERT(g_resolution_count == 2);
+  grpc_core::ExecCtx::Get()->TestOnlySetNow(
+      cb_arg->delay_before_second_resolution * 2);
+  cb_arg->resolver->NextLocked(
+      &cb_arg->result,
+      GRPC_CLOSURE_CREATE(on_fourth_resolution, arg,
+                          grpc_combiner_scheduler(g_combiner)));
+  cb_arg->resolver->RequestReresolutionLocked();
+  gpr_mu_lock(g_iomgr_args.mu);
+  GRPC_LOG_IF_ERROR("pollset_kick",
+                    grpc_pollset_kick(g_iomgr_args.pollset, nullptr));
+  gpr_mu_unlock(g_iomgr_args.mu);
+}
+
 void on_second_resolution(void* arg, grpc_error* error) {
   OnResolutionCallbackArg* cb_arg = static_cast<OnResolutionCallbackArg*>(arg);
-  ++g_on_resolution_invocations_count;
   grpc_channel_args_destroy(cb_arg->result);
-
+  GPR_ASSERT(error == GRPC_ERROR_NONE);
+  ++g_on_resolution_invocations_count;
   gpr_log(GPR_INFO,
           "2nd: g_on_resolution_invocations_count: %d, g_resolution_count: %d",
           g_on_resolution_invocations_count, g_resolution_count);
   // The resolution request for which this function is the callback happened
   // before the min resolution period. Therefore, no new system-level
-  // resolutions happened, as indicated by g_resolution_count.
+  // resolutions happened, as indicated by g_resolution_count. But a resolution
+  // timer was set to fire when the cooldown finishes.
   GPR_ASSERT(g_on_resolution_invocations_count == 2);
   GPR_ASSERT(g_resolution_count == 1);
-  grpc_core::ExecCtx::Get()->TestOnlySetNow(
-      cb_arg->delay_before_second_resolution * 2);
+  // Register a new callback to capture the timer firing.
   cb_arg->resolver->NextLocked(
       &cb_arg->result,
       GRPC_CLOSURE_CREATE(on_third_resolution, arg,
                           grpc_combiner_scheduler(g_combiner)));
-  cb_arg->resolver->RequestReresolutionLocked();
-  if (cb_arg->using_cares) {
-    gpr_mu_lock(g_iomgr_args.mu);
-    GRPC_LOG_IF_ERROR("pollset_kick",
-                      grpc_pollset_kick(g_iomgr_args.pollset, nullptr));
-    gpr_mu_unlock(g_iomgr_args.mu);
-  }
+  gpr_mu_lock(g_iomgr_args.mu);
+  GRPC_LOG_IF_ERROR("pollset_kick",
+                    grpc_pollset_kick(g_iomgr_args.pollset, nullptr));
+  gpr_mu_unlock(g_iomgr_args.mu);
 }
 
 void on_first_resolution(void* arg, grpc_error* error) {
   OnResolutionCallbackArg* cb_arg = static_cast<OnResolutionCallbackArg*>(arg);
-  ++g_on_resolution_invocations_count;
   grpc_channel_args_destroy(cb_arg->result);
+  GPR_ASSERT(error == GRPC_ERROR_NONE);
+  ++g_on_resolution_invocations_count;
+  gpr_log(GPR_INFO,
+          "1st: g_on_resolution_invocations_count: %d, g_resolution_count: %d",
+          g_on_resolution_invocations_count, g_resolution_count);
+  // There's one initial system-level resolution and one invocation of a
+  // notification callback (the current function).
+  GPR_ASSERT(g_on_resolution_invocations_count == 1);
+  GPR_ASSERT(g_resolution_count == 1);
   cb_arg->resolver->NextLocked(
       &cb_arg->result,
       GRPC_CLOSURE_CREATE(on_second_resolution, arg,
                           grpc_combiner_scheduler(g_combiner)));
   cb_arg->resolver->RequestReresolutionLocked();
-  gpr_log(GPR_INFO,
-          "1st: g_on_resolution_invocations_count: %d, g_resolution_count: %d",
-          g_on_resolution_invocations_count, g_resolution_count);
-  // Theres one initial system-level resolution and one invocation of a
-  // notification callback (the current function).
-  GPR_ASSERT(g_on_resolution_invocations_count == 1);
-  GPR_ASSERT(g_resolution_count == 1);
-  if (cb_arg->using_cares) {
-    gpr_mu_lock(g_iomgr_args.mu);
-    GRPC_LOG_IF_ERROR("pollset_kick",
-                      grpc_pollset_kick(g_iomgr_args.pollset, nullptr));
-    gpr_mu_unlock(g_iomgr_args.mu);
-  }
+  gpr_mu_lock(g_iomgr_args.mu);
+  GRPC_LOG_IF_ERROR("pollset_kick",
+                    grpc_pollset_kick(g_iomgr_args.pollset, nullptr));
+  gpr_mu_unlock(g_iomgr_args.mu);
 }
 
 static void start_test_under_combiner(void* arg, grpc_error* error) {
@@ -269,22 +287,19 @@
   grpc_uri_destroy(uri);
 }
 
-static void test_cooldown(bool using_cares) {
+static void test_cooldown() {
   grpc_core::ExecCtx exec_ctx;
-  if (using_cares) iomgr_args_init(&g_iomgr_args);
+  iomgr_args_init(&g_iomgr_args);
   OnResolutionCallbackArg* res_cb_arg =
       grpc_core::New<OnResolutionCallbackArg>();
   res_cb_arg->uri_str = "dns:127.0.0.1";
-  res_cb_arg->using_cares = using_cares;
 
   GRPC_CLOSURE_SCHED(GRPC_CLOSURE_CREATE(start_test_under_combiner, res_cb_arg,
                                          grpc_combiner_scheduler(g_combiner)),
                      GRPC_ERROR_NONE);
-  if (using_cares) {
-    grpc_core::ExecCtx::Get()->Flush();
-    poll_pollset_until_request_done(&g_iomgr_args);
-    iomgr_args_finish(&g_iomgr_args);
-  }
+  grpc_core::ExecCtx::Get()->Flush();
+  poll_pollset_until_request_done(&g_iomgr_args);
+  iomgr_args_finish(&g_iomgr_args);
 }
 
 int main(int argc, char** argv) {
@@ -293,16 +308,12 @@
 
   g_combiner = grpc_combiner_create();
 
-  bool using_cares = false;
-#if GRPC_ARES == 1
-  using_cares = true;
-#endif
   g_default_dns_lookup_ares = grpc_dns_lookup_ares;
   grpc_dns_lookup_ares = test_dns_lookup_ares;
   default_resolve_address = grpc_resolve_address_impl;
   grpc_set_resolver_impl(&test_resolver);
 
-  test_cooldown(using_cares);
+  test_cooldown();
 
   {
     grpc_core::ExecCtx exec_ctx;
diff --git a/test/core/client_channel/resolvers/dns_resolver_test.cc b/test/core/client_channel/resolvers/dns_resolver_test.cc
index e3fba28..103b291 100644
--- a/test/core/client_channel/resolvers/dns_resolver_test.cc
+++ b/test/core/client_channel/resolvers/dns_resolver_test.cc
@@ -70,11 +70,12 @@
 
   test_succeeds(dns, "dns:10.2.1.1");
   test_succeeds(dns, "dns:10.2.1.1:1234");
-  test_succeeds(dns, "ipv4:www.google.com");
+  test_succeeds(dns, "dns:www.google.com");
+  test_succeeds(dns, "dns:///www.google.com");
   if (grpc_resolve_address == grpc_resolve_address_ares) {
-    test_succeeds(dns, "ipv4://8.8.8.8/8.8.8.8:8888");
+    test_succeeds(dns, "dns://8.8.8.8/8.8.8.8:8888");
   } else {
-    test_fails(dns, "ipv4://8.8.8.8/8.8.8.8:8888");
+    test_fails(dns, "dns://8.8.8.8/8.8.8.8:8888");
   }
 
   {
diff --git a/test/core/client_channel/retry_throttle_test.cc b/test/core/client_channel/retry_throttle_test.cc
new file mode 100644
index 0000000..c6d5d3e
--- /dev/null
+++ b/test/core/client_channel/retry_throttle_test.cc
@@ -0,0 +1,142 @@
+/*
+ *
+ * Copyright 2018 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.
+ *
+ */
+
+#include "src/core/ext/filters/client_channel/retry_throttle.h"
+
+#include <gtest/gtest.h>
+
+#include "test/core/util/test_config.h"
+
+namespace grpc_core {
+namespace internal {
+namespace {
+
+TEST(ServerRetryThrottleData, Basic) {
+  // Max token count is 4, so threshold for retrying is 2.
+  // Token count starts at 4.
+  // Each failure decrements by 1.  Each success increments by 1.6.
+  auto throttle_data =
+      MakeRefCounted<ServerRetryThrottleData>(4000, 1600, nullptr);
+  // Failure: token_count=3.  Above threshold.
+  EXPECT_TRUE(throttle_data->RecordFailure());
+  // Success: token_count=4.  Not incremented beyond max.
+  throttle_data->RecordSuccess();
+  // Failure: token_count=3.  Above threshold.
+  EXPECT_TRUE(throttle_data->RecordFailure());
+  // Failure: token_count=2.  At threshold, so no retries.
+  EXPECT_FALSE(throttle_data->RecordFailure());
+  // Failure: token_count=1.  Below threshold, so no retries.
+  EXPECT_FALSE(throttle_data->RecordFailure());
+  // Failure: token_count=0.  Below threshold, so no retries.
+  EXPECT_FALSE(throttle_data->RecordFailure());
+  // Failure: token_count=0.  Below threshold, so no retries.  Not
+  // decremented below min.
+  EXPECT_FALSE(throttle_data->RecordFailure());
+  // Success: token_count=1.6.
+  throttle_data->RecordSuccess();
+  // Success: token_count=3.2.
+  throttle_data->RecordSuccess();
+  // Failure: token_count=2.2.  Above threshold.
+  EXPECT_TRUE(throttle_data->RecordFailure());
+  // Failure: token_count=1.2.  Below threshold, so no retries.
+  EXPECT_FALSE(throttle_data->RecordFailure());
+  // Success: token_count=2.8.
+  throttle_data->RecordSuccess();
+  // Failure: token_count=1.8.  Below threshold, so no retries.
+  EXPECT_FALSE(throttle_data->RecordFailure());
+  // Success: token_count=3.4.
+  throttle_data->RecordSuccess();
+  // Failure: token_count=2.4.  Above threshold.
+  EXPECT_TRUE(throttle_data->RecordFailure());
+}
+
+TEST(ServerRetryThrottleData, Replacement) {
+  // Create old throttle data.
+  // Max token count is 4, so threshold for retrying is 2.
+  // Token count starts at 4.
+  // Each failure decrements by 1.  Each success increments by 1.
+  auto old_throttle_data =
+      MakeRefCounted<ServerRetryThrottleData>(4000, 1000, nullptr);
+  // Failure: token_count=3.  Above threshold.
+  EXPECT_TRUE(old_throttle_data->RecordFailure());
+  // Create new throttle data.
+  // Max token count is 10, so threshold for retrying is 5.
+  // Token count starts at 7.5 (ratio inherited from old_throttle_data).
+  // Each failure decrements by 1.  Each success increments by 3.
+  auto throttle_data = MakeRefCounted<ServerRetryThrottleData>(
+      10000, 3000, old_throttle_data.get());
+  // Failure via old_throttle_data: token_count=6.5.
+  EXPECT_TRUE(old_throttle_data->RecordFailure());
+  // Failure: token_count=5.5.
+  EXPECT_TRUE(old_throttle_data->RecordFailure());
+  // Failure via old_throttle_data: token_count=4.5.  Below threshold.
+  EXPECT_FALSE(old_throttle_data->RecordFailure());
+  // Failure: token_count=3.5.  Below threshold.
+  EXPECT_FALSE(throttle_data->RecordFailure());
+  // Success: token_count=6.5.
+  throttle_data->RecordSuccess();
+  // Failure via old_throttle_data: token_count=5.5.  Above threshold.
+  EXPECT_TRUE(old_throttle_data->RecordFailure());
+  // Failure: token_count=4.5.  Below threshold.
+  EXPECT_FALSE(throttle_data->RecordFailure());
+}
+
+TEST(ServerRetryThrottleMap, Replacement) {
+  ServerRetryThrottleMap::Init();
+  const char kServerName[] = "server_name";
+  // Create old throttle data.
+  // Max token count is 4, so threshold for retrying is 2.
+  // Token count starts at 4.
+  // Each failure decrements by 1.  Each success increments by 1.
+  auto old_throttle_data =
+      ServerRetryThrottleMap::GetDataForServer(kServerName, 4000, 1000);
+  // Failure: token_count=3.  Above threshold.
+  EXPECT_TRUE(old_throttle_data->RecordFailure());
+  // Create new throttle data.
+  // Max token count is 10, so threshold for retrying is 5.
+  // Token count starts at 7.5 (ratio inherited from old_throttle_data).
+  // Each failure decrements by 1.  Each success increments by 3.
+  auto throttle_data =
+      ServerRetryThrottleMap::GetDataForServer(kServerName, 10000, 3000);
+  // Failure via old_throttle_data: token_count=6.5.
+  EXPECT_TRUE(old_throttle_data->RecordFailure());
+  // Failure: token_count=5.5.
+  EXPECT_TRUE(old_throttle_data->RecordFailure());
+  // Failure via old_throttle_data: token_count=4.5.  Below threshold.
+  EXPECT_FALSE(old_throttle_data->RecordFailure());
+  // Failure: token_count=3.5.  Below threshold.
+  EXPECT_FALSE(throttle_data->RecordFailure());
+  // Success: token_count=6.5.
+  throttle_data->RecordSuccess();
+  // Failure via old_throttle_data: token_count=5.5.  Above threshold.
+  EXPECT_TRUE(old_throttle_data->RecordFailure());
+  // Failure: token_count=4.5.  Below threshold.
+  EXPECT_FALSE(throttle_data->RecordFailure());
+  // Clean up.
+  ServerRetryThrottleMap::Shutdown();
+}
+
+}  // namespace
+}  // namespace internal
+}  // namespace grpc_core
+
+int main(int argc, char** argv) {
+  grpc_test_init(argc, argv);
+  ::testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
diff --git a/test/core/end2end/end2end_nosec_tests.cc b/test/core/end2end/end2end_nosec_tests.cc
index 78ddcdb..59eb643 100644
--- a/test/core/end2end/end2end_nosec_tests.cc
+++ b/test/core/end2end/end2end_nosec_tests.cc
@@ -38,6 +38,8 @@
 extern void bad_ping_pre_init(void);
 extern void binary_metadata(grpc_end2end_test_config config);
 extern void binary_metadata_pre_init(void);
+extern void call_host_override(grpc_end2end_test_config config);
+extern void call_host_override_pre_init(void);
 extern void cancel_after_accept(grpc_end2end_test_config config);
 extern void cancel_after_accept_pre_init(void);
 extern void cancel_after_client_done(grpc_end2end_test_config config);
@@ -130,6 +132,8 @@
 extern void retry_exceeds_buffer_size_in_subsequent_batch_pre_init(void);
 extern void retry_non_retriable_status(grpc_end2end_test_config config);
 extern void retry_non_retriable_status_pre_init(void);
+extern void retry_non_retriable_status_before_recv_trailing_metadata_started(grpc_end2end_test_config config);
+extern void retry_non_retriable_status_before_recv_trailing_metadata_started_pre_init(void);
 extern void retry_recv_initial_metadata(grpc_end2end_test_config config);
 extern void retry_recv_initial_metadata_pre_init(void);
 extern void retry_recv_message(grpc_end2end_test_config config);
@@ -187,6 +191,7 @@
   bad_hostname_pre_init();
   bad_ping_pre_init();
   binary_metadata_pre_init();
+  call_host_override_pre_init();
   cancel_after_accept_pre_init();
   cancel_after_client_done_pre_init();
   cancel_after_invoke_pre_init();
@@ -233,6 +238,7 @@
   retry_exceeds_buffer_size_in_initial_batch_pre_init();
   retry_exceeds_buffer_size_in_subsequent_batch_pre_init();
   retry_non_retriable_status_pre_init();
+  retry_non_retriable_status_before_recv_trailing_metadata_started_pre_init();
   retry_recv_initial_metadata_pre_init();
   retry_recv_message_pre_init();
   retry_server_pushback_delay_pre_init();
@@ -270,6 +276,7 @@
     bad_hostname(config);
     bad_ping(config);
     binary_metadata(config);
+    call_host_override(config);
     cancel_after_accept(config);
     cancel_after_client_done(config);
     cancel_after_invoke(config);
@@ -316,6 +323,7 @@
     retry_exceeds_buffer_size_in_initial_batch(config);
     retry_exceeds_buffer_size_in_subsequent_batch(config);
     retry_non_retriable_status(config);
+    retry_non_retriable_status_before_recv_trailing_metadata_started(config);
     retry_recv_initial_metadata(config);
     retry_recv_message(config);
     retry_server_pushback_delay(config);
@@ -360,6 +368,10 @@
       binary_metadata(config);
       continue;
     }
+    if (0 == strcmp("call_host_override", argv[i])) {
+      call_host_override(config);
+      continue;
+    }
     if (0 == strcmp("cancel_after_accept", argv[i])) {
       cancel_after_accept(config);
       continue;
@@ -544,6 +556,10 @@
       retry_non_retriable_status(config);
       continue;
     }
+    if (0 == strcmp("retry_non_retriable_status_before_recv_trailing_metadata_started", argv[i])) {
+      retry_non_retriable_status_before_recv_trailing_metadata_started(config);
+      continue;
+    }
     if (0 == strcmp("retry_recv_initial_metadata", argv[i])) {
       retry_recv_initial_metadata(config);
       continue;
diff --git a/test/core/end2end/end2end_tests.cc b/test/core/end2end/end2end_tests.cc
index fb1e61b..9f164b4 100644
--- a/test/core/end2end/end2end_tests.cc
+++ b/test/core/end2end/end2end_tests.cc
@@ -40,6 +40,8 @@
 extern void binary_metadata_pre_init(void);
 extern void call_creds(grpc_end2end_test_config config);
 extern void call_creds_pre_init(void);
+extern void call_host_override(grpc_end2end_test_config config);
+extern void call_host_override_pre_init(void);
 extern void cancel_after_accept(grpc_end2end_test_config config);
 extern void cancel_after_accept_pre_init(void);
 extern void cancel_after_client_done(grpc_end2end_test_config config);
@@ -132,6 +134,8 @@
 extern void retry_exceeds_buffer_size_in_subsequent_batch_pre_init(void);
 extern void retry_non_retriable_status(grpc_end2end_test_config config);
 extern void retry_non_retriable_status_pre_init(void);
+extern void retry_non_retriable_status_before_recv_trailing_metadata_started(grpc_end2end_test_config config);
+extern void retry_non_retriable_status_before_recv_trailing_metadata_started_pre_init(void);
 extern void retry_recv_initial_metadata(grpc_end2end_test_config config);
 extern void retry_recv_initial_metadata_pre_init(void);
 extern void retry_recv_message(grpc_end2end_test_config config);
@@ -190,6 +194,7 @@
   bad_ping_pre_init();
   binary_metadata_pre_init();
   call_creds_pre_init();
+  call_host_override_pre_init();
   cancel_after_accept_pre_init();
   cancel_after_client_done_pre_init();
   cancel_after_invoke_pre_init();
@@ -236,6 +241,7 @@
   retry_exceeds_buffer_size_in_initial_batch_pre_init();
   retry_exceeds_buffer_size_in_subsequent_batch_pre_init();
   retry_non_retriable_status_pre_init();
+  retry_non_retriable_status_before_recv_trailing_metadata_started_pre_init();
   retry_recv_initial_metadata_pre_init();
   retry_recv_message_pre_init();
   retry_server_pushback_delay_pre_init();
@@ -274,6 +280,7 @@
     bad_ping(config);
     binary_metadata(config);
     call_creds(config);
+    call_host_override(config);
     cancel_after_accept(config);
     cancel_after_client_done(config);
     cancel_after_invoke(config);
@@ -320,6 +327,7 @@
     retry_exceeds_buffer_size_in_initial_batch(config);
     retry_exceeds_buffer_size_in_subsequent_batch(config);
     retry_non_retriable_status(config);
+    retry_non_retriable_status_before_recv_trailing_metadata_started(config);
     retry_recv_initial_metadata(config);
     retry_recv_message(config);
     retry_server_pushback_delay(config);
@@ -368,6 +376,10 @@
       call_creds(config);
       continue;
     }
+    if (0 == strcmp("call_host_override", argv[i])) {
+      call_host_override(config);
+      continue;
+    }
     if (0 == strcmp("cancel_after_accept", argv[i])) {
       cancel_after_accept(config);
       continue;
@@ -552,6 +564,10 @@
       retry_non_retriable_status(config);
       continue;
     }
+    if (0 == strcmp("retry_non_retriable_status_before_recv_trailing_metadata_started", argv[i])) {
+      retry_non_retriable_status_before_recv_trailing_metadata_started(config);
+      continue;
+    }
     if (0 == strcmp("retry_recv_initial_metadata", argv[i])) {
       retry_recv_initial_metadata(config);
       continue;
diff --git a/test/core/end2end/end2end_tests.h b/test/core/end2end/end2end_tests.h
index b42d90b..a1ebded 100644
--- a/test/core/end2end/end2end_tests.h
+++ b/test/core/end2end/end2end_tests.h
@@ -52,6 +52,11 @@
   /* Which features are supported by this fixture. See feature flags above. */
   uint32_t feature_mask;
 
+  /* If the call host is setup by the fixture (for example, via the
+   * GRPC_SSL_TARGET_NAME_OVERRIDE_ARG channel arg), which value should the test
+   * expect to find in call_details.host */
+  const char* overridden_call_host;
+
   grpc_end2end_test_fixture (*create_fixture)(grpc_channel_args* client_args,
                                               grpc_channel_args* server_args);
   void (*init_client)(grpc_end2end_test_fixture* f,
diff --git a/test/core/end2end/fixtures/h2_census.cc b/test/core/end2end/fixtures/h2_census.cc
index b3b4171..29b1d6d 100644
--- a/test/core/end2end/fixtures/h2_census.cc
+++ b/test/core/end2end/fixtures/h2_census.cc
@@ -111,7 +111,7 @@
      FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
          FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
          FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
-     chttp2_create_fixture_fullstack, chttp2_init_client_fullstack,
+     nullptr, chttp2_create_fixture_fullstack, chttp2_init_client_fullstack,
      chttp2_init_server_fullstack, chttp2_tear_down_fullstack},
 };
 
diff --git a/test/core/end2end/fixtures/h2_compress.cc b/test/core/end2end/fixtures/h2_compress.cc
index 565c96c..4aaadf7 100644
--- a/test/core/end2end/fixtures/h2_compress.cc
+++ b/test/core/end2end/fixtures/h2_compress.cc
@@ -109,7 +109,7 @@
      FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
          FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
          FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
-     chttp2_create_fixture_fullstack_compression,
+     nullptr, chttp2_create_fixture_fullstack_compression,
      chttp2_init_client_fullstack_compression,
      chttp2_init_server_fullstack_compression,
      chttp2_tear_down_fullstack_compression},
diff --git a/test/core/end2end/fixtures/h2_fakesec.cc b/test/core/end2end/fixtures/h2_fakesec.cc
index bbf65fc..a653d7c 100644
--- a/test/core/end2end/fixtures/h2_fakesec.cc
+++ b/test/core/end2end/fixtures/h2_fakesec.cc
@@ -132,10 +132,9 @@
 static grpc_end2end_test_config configs[] = {
     {"chttp2/fake_secure_fullstack",
      FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
-         FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS |
          FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
          FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
-     chttp2_create_fixture_secure_fullstack,
+     nullptr, chttp2_create_fixture_secure_fullstack,
      chttp2_init_client_fake_secure_fullstack,
      chttp2_init_server_fake_secure_fullstack,
      chttp2_tear_down_secure_fullstack},
diff --git a/test/core/end2end/fixtures/h2_fd.cc b/test/core/end2end/fixtures/h2_fd.cc
index 9157ab0..52be0f7 100644
--- a/test/core/end2end/fixtures/h2_fd.cc
+++ b/test/core/end2end/fixtures/h2_fd.cc
@@ -96,7 +96,7 @@
 
 /* All test configurations */
 static grpc_end2end_test_config configs[] = {
-    {"chttp2/fd", FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
+    {"chttp2/fd", FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, nullptr,
      chttp2_create_fixture_socketpair, chttp2_init_client_socketpair,
      chttp2_init_server_socketpair, chttp2_tear_down_socketpair},
 };
diff --git a/test/core/end2end/fixtures/h2_full+pipe.cc b/test/core/end2end/fixtures/h2_full+pipe.cc
index ed173c1..c532964 100644
--- a/test/core/end2end/fixtures/h2_full+pipe.cc
+++ b/test/core/end2end/fixtures/h2_full+pipe.cc
@@ -96,7 +96,7 @@
      FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
          FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
          FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
-     chttp2_create_fixture_fullstack, chttp2_init_client_fullstack,
+     nullptr, chttp2_create_fixture_fullstack, chttp2_init_client_fullstack,
      chttp2_init_server_fullstack, chttp2_tear_down_fullstack},
 };
 
diff --git a/test/core/end2end/fixtures/h2_full+trace.cc b/test/core/end2end/fixtures/h2_full+trace.cc
index afb86ea..ba7a780 100644
--- a/test/core/end2end/fixtures/h2_full+trace.cc
+++ b/test/core/end2end/fixtures/h2_full+trace.cc
@@ -96,7 +96,7 @@
      FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
          FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
          FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
-     chttp2_create_fixture_fullstack, chttp2_init_client_fullstack,
+     nullptr, chttp2_create_fixture_fullstack, chttp2_init_client_fullstack,
      chttp2_init_server_fullstack, chttp2_tear_down_fullstack},
 };
 
diff --git a/test/core/end2end/fixtures/h2_full+workarounds.cc b/test/core/end2end/fixtures/h2_full+workarounds.cc
index bd9ddff..78da841 100644
--- a/test/core/end2end/fixtures/h2_full+workarounds.cc
+++ b/test/core/end2end/fixtures/h2_full+workarounds.cc
@@ -107,7 +107,7 @@
          FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
          FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER |
          FEATURE_MASK_SUPPORTS_WORKAROUNDS,
-     chttp2_create_fixture_fullstack, chttp2_init_client_fullstack,
+     nullptr, chttp2_create_fixture_fullstack, chttp2_init_client_fullstack,
      chttp2_init_server_fullstack, chttp2_tear_down_fullstack},
 };
 
diff --git a/test/core/end2end/fixtures/h2_full.cc b/test/core/end2end/fixtures/h2_full.cc
index ca61ec8..0c826b6 100644
--- a/test/core/end2end/fixtures/h2_full.cc
+++ b/test/core/end2end/fixtures/h2_full.cc
@@ -90,7 +90,7 @@
      FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
          FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
          FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
-     chttp2_create_fixture_fullstack, chttp2_init_client_fullstack,
+     nullptr, chttp2_create_fixture_fullstack, chttp2_init_client_fullstack,
      chttp2_init_server_fullstack, chttp2_tear_down_fullstack},
 };
 
diff --git a/test/core/end2end/fixtures/h2_http_proxy.cc b/test/core/end2end/fixtures/h2_http_proxy.cc
index 90d0627..0af8a29 100644
--- a/test/core/end2end/fixtures/h2_http_proxy.cc
+++ b/test/core/end2end/fixtures/h2_http_proxy.cc
@@ -113,7 +113,7 @@
      FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
          FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
          FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
-     chttp2_create_fixture_fullstack, chttp2_init_client_fullstack,
+     nullptr, chttp2_create_fixture_fullstack, chttp2_init_client_fullstack,
      chttp2_init_server_fullstack, chttp2_tear_down_fullstack},
 };
 
diff --git a/test/core/end2end/fixtures/h2_load_reporting.cc b/test/core/end2end/fixtures/h2_load_reporting.cc
index ec9eedb..18ea10a 100644
--- a/test/core/end2end/fixtures/h2_load_reporting.cc
+++ b/test/core/end2end/fixtures/h2_load_reporting.cc
@@ -98,8 +98,9 @@
      FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
          FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
          FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
-     chttp2_create_fixture_load_reporting, chttp2_init_client_load_reporting,
-     chttp2_init_server_load_reporting, chttp2_tear_down_load_reporting},
+     nullptr, chttp2_create_fixture_load_reporting,
+     chttp2_init_client_load_reporting, chttp2_init_server_load_reporting,
+     chttp2_tear_down_load_reporting},
 };
 
 int main(int argc, char** argv) {
diff --git a/test/core/end2end/fixtures/h2_oauth2.cc b/test/core/end2end/fixtures/h2_oauth2.cc
index 9453f2f..d44aafd 100644
--- a/test/core/end2end/fixtures/h2_oauth2.cc
+++ b/test/core/end2end/fixtures/h2_oauth2.cc
@@ -216,7 +216,7 @@
          FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS |
          FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
          FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
-     chttp2_create_fixture_secure_fullstack,
+     "foo.test.google.fr", chttp2_create_fixture_secure_fullstack,
      chttp2_init_client_simple_ssl_with_oauth2_secure_fullstack,
      chttp2_init_server_simple_ssl_secure_fullstack,
      chttp2_tear_down_secure_fullstack},
diff --git a/test/core/end2end/fixtures/h2_proxy.cc b/test/core/end2end/fixtures/h2_proxy.cc
index c97188f..a320000 100644
--- a/test/core/end2end/fixtures/h2_proxy.cc
+++ b/test/core/end2end/fixtures/h2_proxy.cc
@@ -117,7 +117,7 @@
          FEATURE_MASK_SUPPORTS_REQUEST_PROXYING |
          FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
          FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
-     chttp2_create_fixture_fullstack, chttp2_init_client_fullstack,
+     nullptr, chttp2_create_fixture_fullstack, chttp2_init_client_fullstack,
      chttp2_init_server_fullstack, chttp2_tear_down_fullstack},
 };
 
diff --git a/test/core/end2end/fixtures/h2_sockpair+trace.cc b/test/core/end2end/fixtures/h2_sockpair+trace.cc
index d539dda..cdefcf4 100644
--- a/test/core/end2end/fixtures/h2_sockpair+trace.cc
+++ b/test/core/end2end/fixtures/h2_sockpair+trace.cc
@@ -63,9 +63,14 @@
 
 static void client_setup_transport(void* ts, grpc_transport* transport) {
   sp_client_setup* cs = static_cast<sp_client_setup*>(ts);
-
-  cs->f->client = grpc_channel_create("socketpair-target", cs->client_args,
+  grpc_arg authority_arg = grpc_channel_arg_string_create(
+      const_cast<char*>(GRPC_ARG_DEFAULT_AUTHORITY),
+      const_cast<char*>("test-authority"));
+  grpc_channel_args* args =
+      grpc_channel_args_copy_and_add(cs->client_args, &authority_arg, 1);
+  cs->f->client = grpc_channel_create("socketpair-target", args,
                                       GRPC_CLIENT_DIRECT_CHANNEL, transport);
+  grpc_channel_args_destroy(args);
 }
 
 static grpc_end2end_test_fixture chttp2_create_fixture_socketpair(
@@ -118,7 +123,7 @@
 
 /* All test configurations */
 static grpc_end2end_test_config configs[] = {
-    {"chttp2/socketpair", FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
+    {"chttp2/socketpair", FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, nullptr,
      chttp2_create_fixture_socketpair, chttp2_init_client_socketpair,
      chttp2_init_server_socketpair, chttp2_tear_down_socketpair},
 };
diff --git a/test/core/end2end/fixtures/h2_sockpair.cc b/test/core/end2end/fixtures/h2_sockpair.cc
index 75f6402..8966cb3 100644
--- a/test/core/end2end/fixtures/h2_sockpair.cc
+++ b/test/core/end2end/fixtures/h2_sockpair.cc
@@ -58,8 +58,14 @@
 static void client_setup_transport(void* ts, grpc_transport* transport) {
   sp_client_setup* cs = static_cast<sp_client_setup*>(ts);
 
-  cs->f->client = grpc_channel_create("socketpair-target", cs->client_args,
+  grpc_arg authority_arg = grpc_channel_arg_string_create(
+      const_cast<char*>(GRPC_ARG_DEFAULT_AUTHORITY),
+      const_cast<char*>("test-authority"));
+  grpc_channel_args* args =
+      grpc_channel_args_copy_and_add(cs->client_args, &authority_arg, 1);
+  cs->f->client = grpc_channel_create("socketpair-target", args,
                                       GRPC_CLIENT_DIRECT_CHANNEL, transport);
+  grpc_channel_args_destroy(args);
 }
 
 static grpc_end2end_test_fixture chttp2_create_fixture_socketpair(
@@ -112,7 +118,7 @@
 
 /* All test configurations */
 static grpc_end2end_test_config configs[] = {
-    {"chttp2/socketpair", FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
+    {"chttp2/socketpair", FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, nullptr,
      chttp2_create_fixture_socketpair, chttp2_init_client_socketpair,
      chttp2_init_server_socketpair, chttp2_tear_down_socketpair},
 };
diff --git a/test/core/end2end/fixtures/h2_sockpair_1byte.cc b/test/core/end2end/fixtures/h2_sockpair_1byte.cc
index 9296319..ebf4162 100644
--- a/test/core/end2end/fixtures/h2_sockpair_1byte.cc
+++ b/test/core/end2end/fixtures/h2_sockpair_1byte.cc
@@ -58,8 +58,14 @@
 static void client_setup_transport(void* ts, grpc_transport* transport) {
   sp_client_setup* cs = static_cast<sp_client_setup*>(ts);
 
-  cs->f->client = grpc_channel_create("socketpair-target", cs->client_args,
+  grpc_arg authority_arg = grpc_channel_arg_string_create(
+      const_cast<char*>(GRPC_ARG_DEFAULT_AUTHORITY),
+      const_cast<char*>("test-authority"));
+  grpc_channel_args* args =
+      grpc_channel_args_copy_and_add(cs->client_args, &authority_arg, 1);
+  cs->f->client = grpc_channel_create("socketpair-target", args,
                                       GRPC_CLIENT_DIRECT_CHANNEL, transport);
+  grpc_channel_args_destroy(args);
 }
 
 static grpc_end2end_test_fixture chttp2_create_fixture_socketpair(
@@ -124,9 +130,9 @@
 /* All test configurations */
 static grpc_end2end_test_config configs[] = {
     {"chttp2/socketpair_one_byte_at_a_time",
-     FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, chttp2_create_fixture_socketpair,
-     chttp2_init_client_socketpair, chttp2_init_server_socketpair,
-     chttp2_tear_down_socketpair},
+     FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, nullptr,
+     chttp2_create_fixture_socketpair, chttp2_init_client_socketpair,
+     chttp2_init_server_socketpair, chttp2_tear_down_socketpair},
 };
 
 int main(int argc, char** argv) {
diff --git a/test/core/end2end/fixtures/h2_ssl.cc b/test/core/end2end/fixtures/h2_ssl.cc
index bbcc88e..999cd4c 100644
--- a/test/core/end2end/fixtures/h2_ssl.cc
+++ b/test/core/end2end/fixtures/h2_ssl.cc
@@ -109,10 +109,7 @@
   grpc_channel_args* new_client_args =
       grpc_channel_args_copy_and_add(client_args, &ssl_name_override, 1);
   chttp2_init_client_secure_fullstack(f, new_client_args, ssl_creds);
-  {
-    grpc_core::ExecCtx exec_ctx;
-    grpc_channel_args_destroy(new_client_args);
-  }
+  grpc_channel_args_destroy(new_client_args);
 }
 
 static int fail_server_auth_check(grpc_channel_args* server_args) {
@@ -149,7 +146,7 @@
          FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS |
          FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
          FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
-     chttp2_create_fixture_secure_fullstack,
+     "foo.test.google.fr", chttp2_create_fixture_secure_fullstack,
      chttp2_init_client_simple_ssl_secure_fullstack,
      chttp2_init_server_simple_ssl_secure_fullstack,
      chttp2_tear_down_secure_fullstack},
diff --git a/test/core/end2end/fixtures/h2_ssl_proxy.cc b/test/core/end2end/fixtures/h2_ssl_proxy.cc
index 6b0b891..9ab50c6 100644
--- a/test/core/end2end/fixtures/h2_ssl_proxy.cc
+++ b/test/core/end2end/fixtures/h2_ssl_proxy.cc
@@ -187,7 +187,7 @@
          FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS |
          FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
          FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
-     chttp2_create_fixture_secure_fullstack,
+     "foo.test.google.fr", chttp2_create_fixture_secure_fullstack,
      chttp2_init_client_simple_ssl_secure_fullstack,
      chttp2_init_server_simple_ssl_secure_fullstack,
      chttp2_tear_down_secure_fullstack},
diff --git a/test/core/end2end/fixtures/h2_uds.cc b/test/core/end2end/fixtures/h2_uds.cc
index 1b081f9..2c81c3d 100644
--- a/test/core/end2end/fixtures/h2_uds.cc
+++ b/test/core/end2end/fixtures/h2_uds.cc
@@ -95,7 +95,7 @@
      FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |
          FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL |
          FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER,
-     chttp2_create_fixture_fullstack, chttp2_init_client_fullstack,
+     nullptr, chttp2_create_fixture_fullstack, chttp2_init_client_fullstack,
      chttp2_init_server_fullstack, chttp2_tear_down_fullstack},
 };
 
diff --git a/test/core/end2end/fixtures/inproc.cc b/test/core/end2end/fixtures/inproc.cc
index d47de42..be6eda8 100644
--- a/test/core/end2end/fixtures/inproc.cc
+++ b/test/core/end2end/fixtures/inproc.cc
@@ -75,8 +75,9 @@
 
 /* All test configurations */
 static grpc_end2end_test_config configs[] = {
-    {"inproc", FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, inproc_create_fixture,
-     inproc_init_client, inproc_init_server, inproc_tear_down},
+    {"inproc", FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER, nullptr,
+     inproc_create_fixture, inproc_init_client, inproc_init_server,
+     inproc_tear_down},
 };
 
 int main(int argc, char** argv) {
diff --git a/test/core/end2end/fuzzers/api_fuzzer.cc b/test/core/end2end/fuzzers/api_fuzzer.cc
index 9ace7d0..36f257d 100644
--- a/test/core/end2end/fuzzers/api_fuzzer.cc
+++ b/test/core/end2end/fuzzers/api_fuzzer.cc
@@ -38,8 +38,14 @@
 #include "src/core/lib/surface/server.h"
 #include "src/core/lib/transport/metadata.h"
 #include "test/core/end2end/data/ssl_test_data.h"
+#include "test/core/util/fuzzer_util.h"
 #include "test/core/util/passthru_endpoint.h"
 
+using grpc_core::testing::grpc_fuzzer_get_next_byte;
+using grpc_core::testing::grpc_fuzzer_get_next_string;
+using grpc_core::testing::grpc_fuzzer_get_next_uint32;
+using grpc_core::testing::input_stream;
+
 ////////////////////////////////////////////////////////////////////////////////
 // logging
 
@@ -65,58 +71,20 @@
   return ts;
 }
 
-////////////////////////////////////////////////////////////////////////////////
-// input_stream: allows easy access to input bytes, and allows reading a little
-//               past the end (avoiding needing to check everywhere)
-
-typedef struct {
-  const uint8_t* cur;
-  const uint8_t* end;
-} input_stream;
-
-static uint8_t next_byte(input_stream* inp) {
-  if (inp->cur == inp->end) {
-    return 0;
-  }
-  return *inp->cur++;
-}
-
 static void end(input_stream* inp) { inp->cur = inp->end; }
 
-static char* read_string(input_stream* inp, bool* special) {
-  char* str = nullptr;
-  size_t cap = 0;
-  size_t sz = 0;
-  char c;
-  do {
-    if (cap == sz) {
-      cap = GPR_MAX(3 * cap / 2, cap + 8);
-      str = static_cast<char*>(gpr_realloc(str, cap));
-    }
-    c = static_cast<char>(next_byte(inp));
-    str[sz++] = c;
-  } while (c != 0 && c != 1);
-  if (special != nullptr) {
-    *special = (c == 1);
-  }
-  if (c == 1) {
-    str[sz - 1] = 0;
-  }
-  return str;
-}
-
 static void read_buffer(input_stream* inp, char** buffer, size_t* length,
                         bool* special) {
-  *length = next_byte(inp);
+  *length = grpc_fuzzer_get_next_byte(inp);
   if (*length == 255) {
     if (special != nullptr) *special = true;
-    *length = next_byte(inp);
+    *length = grpc_fuzzer_get_next_byte(inp);
   } else {
     if (special != nullptr) *special = false;
   }
   *buffer = static_cast<char*>(gpr_malloc(*length));
   for (size_t i = 0; i < *length; i++) {
-    (*buffer)[i] = static_cast<char>(next_byte(inp));
+    (*buffer)[i] = static_cast<char>(grpc_fuzzer_get_next_byte(inp));
   }
 }
 
@@ -128,7 +96,7 @@
 
 static grpc_slice read_string_like_slice(input_stream* inp) {
   bool special;
-  char* s = read_string(inp, &special);
+  char* s = grpc_fuzzer_get_next_string(inp, &special);
   grpc_slice r = maybe_intern(grpc_slice_from_copied_string(s), special);
   gpr_free(s);
   return r;
@@ -146,39 +114,15 @@
 }
 
 static uint32_t read_uint22(input_stream* inp) {
-  uint8_t b = next_byte(inp);
+  uint8_t b = grpc_fuzzer_get_next_byte(inp);
   uint32_t x = b & 0x7f;
   if (b & 0x80) {
     x <<= 7;
-    b = next_byte(inp);
+    b = grpc_fuzzer_get_next_byte(inp);
     x |= b & 0x7f;
     if (b & 0x80) {
       x <<= 8;
-      x |= next_byte(inp);
-    }
-  }
-  return x;
-}
-
-static uint32_t read_uint32(input_stream* inp) {
-  uint8_t b = next_byte(inp);
-  uint32_t x = b & 0x7f;
-  if (b & 0x80) {
-    x <<= 7;
-    b = next_byte(inp);
-    x |= b & 0x7f;
-    if (b & 0x80) {
-      x <<= 7;
-      b = next_byte(inp);
-      x |= b & 0x7f;
-      if (b & 0x80) {
-        x <<= 7;
-        b = next_byte(inp);
-        x |= b & 0x7f;
-        if (b & 0x80) {
-          x = (x << 4) | (next_byte(inp) & 0x0f);
-        }
-      }
+      x |= grpc_fuzzer_get_next_byte(inp);
     }
   }
   return x;
@@ -193,22 +137,22 @@
 }
 
 static int read_int(input_stream* inp) {
-  return static_cast<int>(read_uint32(inp));
+  return static_cast<int>(grpc_fuzzer_get_next_uint32(inp));
 }
 
 static grpc_channel_args* read_args(input_stream* inp) {
-  size_t n = next_byte(inp);
+  size_t n = grpc_fuzzer_get_next_byte(inp);
   grpc_arg* args = static_cast<grpc_arg*>(gpr_malloc(sizeof(*args) * n));
   for (size_t i = 0; i < n; i++) {
-    switch (next_byte(inp)) {
+    switch (grpc_fuzzer_get_next_byte(inp)) {
       case 1:
         args[i].type = GRPC_ARG_STRING;
-        args[i].key = read_string(inp, nullptr);
-        args[i].value.string = read_string(inp, nullptr);
+        args[i].key = grpc_fuzzer_get_next_string(inp, nullptr);
+        args[i].value.string = grpc_fuzzer_get_next_string(inp, nullptr);
         break;
       case 2:
         args[i].type = GRPC_ARG_INTEGER;
-        args[i].key = read_string(inp, nullptr);
+        args[i].key = grpc_fuzzer_get_next_string(inp, nullptr);
         args[i].value.integer = read_int(inp);
         break;
       case 3:
@@ -249,10 +193,11 @@
 static const char* read_cred_artifact(cred_artifact_ctx* ctx, input_stream* inp,
                                       const char** builtins,
                                       size_t num_builtins) {
-  uint8_t b = next_byte(inp);
+  uint8_t b = grpc_fuzzer_get_next_byte(inp);
   if (b == 0) return nullptr;
   if (b == 1)
-    return ctx->release[ctx->num_release++] = read_string(inp, nullptr);
+    return ctx->release[ctx->num_release++] =
+               grpc_fuzzer_get_next_string(inp, nullptr);
   if (b >= num_builtins + 1) {
     end(inp);
     return nullptr;
@@ -288,7 +233,7 @@
     end(inp);
     return nullptr;
   }
-  switch (next_byte(inp)) {
+  switch (grpc_fuzzer_get_next_byte(inp)) {
     default:
       end(inp);
       return nullptr;
@@ -339,7 +284,7 @@
 }
 
 static grpc_channel_credentials* read_channel_creds(input_stream* inp) {
-  switch (next_byte(inp)) {
+  switch (grpc_fuzzer_get_next_byte(inp)) {
     case 0:
       return read_ssl_channel_creds(inp);
       break;
@@ -673,7 +618,7 @@
 
 static void read_metadata(input_stream* inp, size_t* count,
                           grpc_metadata** metadata, call_state* cs) {
-  *count = next_byte(inp);
+  *count = grpc_fuzzer_get_next_byte(inp);
   if (*count) {
     *metadata =
         static_cast<grpc_metadata*>(gpr_malloc(*count * sizeof(**metadata)));
@@ -681,7 +626,7 @@
     for (size_t i = 0; i < *count; i++) {
       (*metadata)[i].key = read_string_like_slice(inp);
       (*metadata)[i].value = read_buffer_like_slice(inp);
-      (*metadata)[i].flags = read_uint32(inp);
+      (*metadata)[i].flags = grpc_fuzzer_get_next_uint32(inp);
       add_slice_to_unref(cs, (*metadata)[i].key);
       add_slice_to_unref(cs, (*metadata)[i].value);
     }
@@ -811,7 +756,7 @@
 
     grpc_timer_manager_tick();
 
-    switch (next_byte(&inp)) {
+    switch (grpc_fuzzer_get_next_byte(&inp)) {
       // terminate on bad bytes
       default:
         end(&inp);
@@ -838,13 +783,14 @@
       // increment global time
       case 1: {
         g_now = gpr_time_add(
-            g_now, gpr_time_from_micros(read_uint32(&inp), GPR_TIMESPAN));
+            g_now, gpr_time_from_micros(grpc_fuzzer_get_next_uint32(&inp),
+                                        GPR_TIMESPAN));
         break;
       }
       // create an insecure channel
       case 2: {
         if (g_channel == nullptr) {
-          char* target = read_string(&inp, nullptr);
+          char* target = grpc_fuzzer_get_next_string(&inp, nullptr);
           char* target_uri;
           gpr_asprintf(&target_uri, "dns:%s", target);
           grpc_channel_args* args = read_args(&inp);
@@ -927,7 +873,7 @@
       // check connectivity
       case 8: {
         if (g_channel != nullptr) {
-          uint8_t try_to_connect = next_byte(&inp);
+          uint8_t try_to_connect = grpc_fuzzer_get_next_byte(&inp);
           if (try_to_connect == 0 || try_to_connect == 1) {
             grpc_channel_check_connectivity_state(g_channel, try_to_connect);
           } else {
@@ -946,7 +892,8 @@
           if (st != GRPC_CHANNEL_SHUTDOWN) {
             gpr_timespec deadline = gpr_time_add(
                 gpr_now(GPR_CLOCK_REALTIME),
-                gpr_time_from_micros(read_uint32(&inp), GPR_TIMESPAN));
+                gpr_time_from_micros(grpc_fuzzer_get_next_uint32(&inp),
+                                     GPR_TIMESPAN));
             grpc_channel_watch_connectivity_state(
                 g_channel, st, deadline, cq,
                 create_validator(validate_connectivity_watch,
@@ -971,7 +918,7 @@
           }
           parent_call = g_active_call->call;
         }
-        uint32_t propagation_mask = read_uint32(&inp);
+        uint32_t propagation_mask = grpc_fuzzer_get_next_uint32(&inp);
         grpc_slice method = read_string_like_slice(&inp);
         if (GRPC_SLICE_LENGTH(method) == 0) {
           ok = false;
@@ -979,7 +926,8 @@
         grpc_slice host = read_string_like_slice(&inp);
         gpr_timespec deadline =
             gpr_time_add(gpr_now(GPR_CLOCK_REALTIME),
-                         gpr_time_from_micros(read_uint32(&inp), GPR_TIMESPAN));
+                         gpr_time_from_micros(grpc_fuzzer_get_next_uint32(&inp),
+                                              GPR_TIMESPAN));
 
         if (ok) {
           call_state* cs = new_call(g_active_call, CLIENT);
@@ -1005,7 +953,7 @@
           end(&inp);
           break;
         }
-        size_t num_ops = next_byte(&inp);
+        size_t num_ops = grpc_fuzzer_get_next_byte(&inp);
         if (num_ops > 6) {
           end(&inp);
           break;
@@ -1019,7 +967,7 @@
         uint8_t has_ops = 0;
         for (i = 0; i < num_ops; i++) {
           op = &ops[i];
-          switch (next_byte(&inp)) {
+          switch (grpc_fuzzer_get_next_byte(&inp)) {
             default:
               /* invalid value */
               op->op = (grpc_op_type)-1;
@@ -1060,7 +1008,8 @@
                   &op->data.send_status_from_server.trailing_metadata,
                   g_active_call);
               op->data.send_status_from_server.status =
-                  static_cast<grpc_status_code>(next_byte(&inp));
+                  static_cast<grpc_status_code>(
+                      grpc_fuzzer_get_next_byte(&inp));
               op->data.send_status_from_server.status_details =
                   add_slice_to_unref(g_active_call,
                                      read_buffer_like_slice(&inp));
@@ -1097,7 +1046,7 @@
               break;
           }
           op->reserved = nullptr;
-          op->flags = read_uint32(&inp);
+          op->flags = grpc_fuzzer_get_next_uint32(&inp);
         }
         if (ok) {
           validator* v = make_finished_batch_validator(g_active_call, has_ops);
@@ -1160,14 +1109,14 @@
       }
       // enable a tracer
       case 17: {
-        char* tracer = read_string(&inp, nullptr);
+        char* tracer = grpc_fuzzer_get_next_string(&inp, nullptr);
         grpc_tracer_set_enabled(tracer, 1);
         gpr_free(tracer);
         break;
       }
       // disable a tracer
       case 18: {
-        char* tracer = read_string(&inp, nullptr);
+        char* tracer = grpc_fuzzer_get_next_string(&inp, nullptr);
         grpc_tracer_set_enabled(tracer, 0);
         gpr_free(tracer);
         break;
@@ -1209,7 +1158,7 @@
       // create a secure channel
       case 22: {
         if (g_channel == nullptr) {
-          char* target = read_string(&inp, nullptr);
+          char* target = grpc_fuzzer_get_next_string(&inp, nullptr);
           char* target_uri;
           gpr_asprintf(&target_uri, "dns:%s", target);
           grpc_channel_args* args = read_args(&inp);
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-api_fuzzer-5406804084260864 b/test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-api_fuzzer-5406804084260864
new file mode 100644
index 0000000..121aac7
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-api_fuzzer-5406804084260864
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-api_fuzzer-5471994809155584 b/test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-api_fuzzer-5471994809155584
new file mode 100644
index 0000000..e5d3d38
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-api_fuzzer-5471994809155584
Binary files differ
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-api_fuzzer-6609852341157888 b/test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-api_fuzzer-6609852341157888
new file mode 100644
index 0000000..b7debab
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-api_fuzzer-6609852341157888
Binary files differ
diff --git a/test/core/end2end/fuzzers/client_fuzzer.cc b/test/core/end2end/fuzzers/client_fuzzer.cc
index 16acf8e..e21006b 100644
--- a/test/core/end2end/fuzzers/client_fuzzer.cc
+++ b/test/core/end2end/fuzzers/client_fuzzer.cc
@@ -20,6 +20,7 @@
 
 #include <grpc/grpc.h>
 #include <grpc/support/alloc.h>
+#include <grpc/support/string_util.h>
 
 #include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
 #include "src/core/lib/iomgr/executor.h"
@@ -58,8 +59,14 @@
         grpc_create_chttp2_transport(nullptr, mock_endpoint, true);
     grpc_chttp2_transport_start_reading(transport, nullptr, nullptr);
 
+    grpc_arg authority_arg = grpc_channel_arg_string_create(
+        const_cast<char*>(GRPC_ARG_DEFAULT_AUTHORITY),
+        const_cast<char*>("test-authority"));
+    grpc_channel_args* args =
+        grpc_channel_args_copy_and_add(nullptr, &authority_arg, 1);
     grpc_channel* channel = grpc_channel_create(
-        "test-target", nullptr, GRPC_CLIENT_DIRECT_CHANNEL, transport);
+        "test-target", args, GRPC_CLIENT_DIRECT_CHANNEL, transport);
+    grpc_channel_args_destroy(args);
     grpc_slice host = grpc_slice_from_static_string("localhost");
     grpc_call* call = grpc_channel_create_call(
         channel, nullptr, 0, cq, grpc_slice_from_static_string("/foo"), &host,
diff --git a/test/core/end2end/gen_build_yaml.py b/test/core/end2end/gen_build_yaml.py
index 4e20b0b..c355fc2 100755
--- a/test/core/end2end/gen_build_yaml.py
+++ b/test/core/end2end/gen_build_yaml.py
@@ -108,6 +108,8 @@
         proxyable=False, cpu_cost=LOWCPU, exclude_iomgrs=['uv']),
     'default_host': default_test_options._replace(
         needs_fullstack=True, needs_dns=True, needs_names=True),
+    'call_host_override': default_test_options._replace(
+        needs_fullstack=True, needs_dns=True, needs_names=True),
     'disappearing_server': connectivity_test_options._replace(flaky=True,
                                                               needs_names=True),
     'empty_batch': default_test_options._replace(cpu_cost=LOWCPU),
@@ -168,6 +170,9 @@
                                       proxyable=False),
     'retry_non_retriable_status': default_test_options._replace(
         cpu_cost=LOWCPU, needs_client_channel=True, proxyable=False),
+    'retry_non_retriable_status_before_recv_trailing_metadata_started':
+        default_test_options._replace(
+            cpu_cost=LOWCPU, needs_client_channel=True, proxyable=False),
     'retry_recv_initial_metadata': default_test_options._replace(
         cpu_cost=LOWCPU, needs_client_channel=True, proxyable=False),
     'retry_recv_message': default_test_options._replace(
diff --git a/test/core/end2end/generate_tests.bzl b/test/core/end2end/generate_tests.bzl
index 8e723fd..11fc576 100755
--- a/test/core/end2end/generate_tests.bzl
+++ b/test/core/end2end/generate_tests.bzl
@@ -101,6 +101,8 @@
     'binary_metadata': test_options(),
     'resource_quota_server': test_options(proxyable=False),
     'call_creds': test_options(secure=True),
+    'call_host_override': test_options(needs_fullstack=True, needs_dns=True,
+                                       needs_names=True),
     'cancel_after_accept': test_options(),
     'cancel_after_client_done': test_options(),
     'cancel_after_invoke': test_options(),
@@ -156,6 +158,8 @@
         needs_client_channel=True, proxyable=False),
     'retry_non_retriable_status': test_options(needs_client_channel=True,
                                                proxyable=False),
+    'retry_non_retriable_status_before_recv_trailing_metadata_started':
+        test_options(needs_client_channel=True, proxyable=False),
     'retry_recv_initial_metadata': test_options(needs_client_channel=True,
                                                 proxyable=False),
     'retry_recv_message': test_options(needs_client_channel=True,
diff --git a/test/core/end2end/h2_ssl_cert_test.cc b/test/core/end2end/h2_ssl_cert_test.cc
index 9e2082c..9ed6f23 100644
--- a/test/core/end2end/h2_ssl_cert_test.cc
+++ b/test/core/end2end/h2_ssl_cert_test.cc
@@ -57,8 +57,6 @@
 
   f.fixture_data = ffd;
   f.cq = grpc_completion_queue_create_for_next(nullptr);
-  f.shutdown_cq = grpc_completion_queue_create_for_pluck(nullptr);
-
   return f;
 }
 
@@ -202,6 +200,7 @@
      FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION |       \
          FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS | \
          FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL,        \
+     "foo.test.google.fr",                            \
      chttp2_create_fixture_secure_fullstack,          \
      CLIENT_INIT_NAME(cert_type),                     \
      SERVER_INIT_NAME(request_type),                  \
@@ -270,27 +269,13 @@
   } while (ev.type != GRPC_QUEUE_SHUTDOWN);
 }
 
+// Shuts down the server.
+// Side effect - Also shuts down and drains the completion queue.
 static void shutdown_server(grpc_end2end_test_fixture* f) {
   if (!f->server) return;
-  /* Perform a completion queue next, so that any pending operations can be
-   * finished, and resources can be released. This is so that, shutdown does not
-   * hang. For example, the server might be stuck in the handshaking code, which
-   * keeps a ref to a listener. Unless, it is unref'd, shutdown won't be able
-   * to proceed.
-   *
-   * (If shutdown times out, it is probably because 100ms wasn't enough. In that
-   * case, the deadline can be increased. Or, we could simply have another
-   * thread for the server to poll the completion queue while the shutdown
-   * progresses.)
-   */
-  GPR_ASSERT(grpc_completion_queue_next(
-                 f->cq, grpc_timeout_milliseconds_to_deadline(100), nullptr)
-                 .type == GRPC_QUEUE_TIMEOUT);
-  grpc_server_shutdown_and_notify(f->server, f->shutdown_cq, tag(1000));
-  GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_cq, tag(1000),
-                                         grpc_timeout_seconds_to_deadline(5),
-                                         nullptr)
-                 .type == GRPC_OP_COMPLETE);
+  grpc_server_shutdown_and_notify(f->server, f->cq, tag(1000));
+  grpc_completion_queue_shutdown(f->cq);
+  drain_cq(f->cq);
   grpc_server_destroy(f->server);
   f->server = nullptr;
 }
@@ -304,11 +289,7 @@
 static void end_test(grpc_end2end_test_fixture* f) {
   shutdown_client(f);
   shutdown_server(f);
-
-  grpc_completion_queue_shutdown(f->cq);
-  drain_cq(f->cq);
   grpc_completion_queue_destroy(f->cq);
-  grpc_completion_queue_destroy(f->shutdown_cq);
 }
 
 static void simple_request_body(grpc_end2end_test_fixture f,
diff --git a/test/core/end2end/tests/bad_ping.cc b/test/core/end2end/tests/bad_ping.cc
index 239c608..98d893f 100644
--- a/test/core/end2end/tests/bad_ping.cc
+++ b/test/core/end2end/tests/bad_ping.cc
@@ -108,11 +108,9 @@
   grpc_slice details;
   int was_cancelled = 2;
 
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -207,8 +205,6 @@
   // the in-progress RPC should fail.
   GPR_ASSERT(status == GRPC_STATUS_UNAVAILABLE);
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 1);
 
   grpc_slice_unref(details);
@@ -271,11 +267,9 @@
   grpc_slice details;
   int was_cancelled = 2;
 
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -361,6 +355,11 @@
 
   grpc_server_shutdown_and_notify(f.server, f.cq, tag(0xdead));
   CQ_EXPECT_COMPLETION(cqv, tag(0xdead), 1);
+
+  // Also expect the previously blocked pings to complete with an error
+  CQ_EXPECT_COMPLETION(cqv, tag(200 + MAX_PING_STRIKES + 1), 0);
+  CQ_EXPECT_COMPLETION(cqv, tag(200 + MAX_PING_STRIKES + 2), 0);
+
   cq_verify(cqv);
 
   grpc_call_unref(s);
@@ -368,8 +367,6 @@
   // The rpc should be successful.
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
 
   grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
diff --git a/test/core/end2end/tests/binary_metadata.cc b/test/core/end2end/tests/binary_metadata.cc
index e66b4da..cdf5b1e 100644
--- a/test/core/end2end/tests/binary_metadata.cc
+++ b/test/core/end2end/tests/binary_metadata.cc
@@ -136,11 +136,9 @@
   int was_cancelled = 2;
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -278,8 +276,6 @@
           "\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0"
           "\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 0);
   GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world"));
   GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, "hello you"));
diff --git a/test/core/end2end/tests/call_creds.cc b/test/core/end2end/tests/call_creds.cc
index e9cbaa3..ead6ecb 100644
--- a/test/core/end2end/tests/call_creds.cc
+++ b/test/core/end2end/tests/call_creds.cc
@@ -156,11 +156,9 @@
   cqv = cq_verifier_create(f.cq);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
   creds = grpc_google_iam_credentials_create(iam_token, iam_selector, nullptr);
   GPR_ASSERT(creds != nullptr);
@@ -292,8 +290,6 @@
   GPR_ASSERT(status == GRPC_STATUS_OK);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 0);
   GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world"));
   GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, "hello you"));
@@ -396,11 +392,9 @@
   f = begin_test(config, "test_request_with_server_rejecting_client_creds", 1);
   cqv = cq_verifier_create(f.cq);
 
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   creds = grpc_google_iam_credentials_create(iam_token, iam_selector, nullptr);
diff --git a/test/core/end2end/tests/call_host_override.cc b/test/core/end2end/tests/call_host_override.cc
new file mode 100644
index 0000000..251dc6d
--- /dev/null
+++ b/test/core/end2end/tests/call_host_override.cc
@@ -0,0 +1,230 @@
+/*
+ *
+ * Copyright 2015 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.
+ *
+ */
+
+#include "test/core/end2end/end2end_tests.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include <grpc/byte_buffer.h>
+#include <grpc/grpc.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/time.h>
+
+#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/gpr/string.h"
+#include "test/core/end2end/cq_verifier.h"
+
+static void* tag(intptr_t t) { return (void*)t; }
+
+static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
+                                            const char* test_name,
+                                            grpc_channel_args* client_args,
+                                            grpc_channel_args* server_args) {
+  grpc_end2end_test_fixture f;
+  gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
+  f = config.create_fixture(client_args, server_args);
+  grpc_arg fake_security_name_override = {
+      GRPC_ARG_STRING,
+      const_cast<char*>(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG),
+      {const_cast<char*>("foo.test.google.fr:1234")}};
+  grpc_channel_args* new_client_args = grpc_channel_args_copy_and_add(
+      client_args, &fake_security_name_override, 1);
+  config.init_client(&f, new_client_args);
+  grpc_channel_args_destroy(new_client_args);
+  config.init_server(&f, server_args);
+  return f;
+}
+
+static gpr_timespec n_seconds_from_now(int n) {
+  return grpc_timeout_seconds_to_deadline(n);
+}
+
+static gpr_timespec five_seconds_from_now(void) {
+  return n_seconds_from_now(5);
+}
+
+static void drain_cq(grpc_completion_queue* cq) {
+  grpc_event ev;
+  do {
+    ev = grpc_completion_queue_next(cq, five_seconds_from_now(), nullptr);
+  } while (ev.type != GRPC_QUEUE_SHUTDOWN);
+}
+
+static void shutdown_server(grpc_end2end_test_fixture* f) {
+  if (!f->server) return;
+  grpc_server_shutdown_and_notify(f->server, f->shutdown_cq, tag(1000));
+  GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_cq, tag(1000),
+                                         grpc_timeout_seconds_to_deadline(5),
+                                         nullptr)
+                 .type == GRPC_OP_COMPLETE);
+  grpc_server_destroy(f->server);
+  f->server = nullptr;
+}
+
+static void shutdown_client(grpc_end2end_test_fixture* f) {
+  if (!f->client) return;
+  grpc_channel_destroy(f->client);
+  f->client = nullptr;
+}
+
+static void end_test(grpc_end2end_test_fixture* f) {
+  shutdown_server(f);
+  shutdown_client(f);
+
+  grpc_completion_queue_shutdown(f->cq);
+  drain_cq(f->cq);
+  grpc_completion_queue_destroy(f->cq);
+  grpc_completion_queue_destroy(f->shutdown_cq);
+}
+
+static void test_invoke_simple_request(grpc_end2end_test_config config) {
+  grpc_end2end_test_fixture f =
+      begin_test(config, "test_invoke_simple_request", nullptr, nullptr);
+  grpc_call* c;
+  grpc_call* s;
+  cq_verifier* cqv = cq_verifier_create(f.cq);
+  grpc_op ops[6];
+  grpc_op* op;
+  grpc_metadata_array initial_metadata_recv;
+  grpc_metadata_array trailing_metadata_recv;
+  grpc_metadata_array request_metadata_recv;
+  grpc_call_details call_details;
+  grpc_status_code status;
+  grpc_call_error error;
+  grpc_slice details;
+  int was_cancelled = 2;
+  char* peer;
+
+  gpr_timespec deadline = five_seconds_from_now();
+  c = grpc_channel_create_call(
+      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+      grpc_slice_from_static_string("/foo"),
+      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
+      nullptr);
+  GPR_ASSERT(c);
+
+  peer = grpc_call_get_peer(c);
+  GPR_ASSERT(peer != nullptr);
+  gpr_log(GPR_DEBUG, "client_peer_before_call=%s", peer);
+  gpr_free(peer);
+
+  grpc_metadata_array_init(&initial_metadata_recv);
+  grpc_metadata_array_init(&trailing_metadata_recv);
+  grpc_metadata_array_init(&request_metadata_recv);
+  grpc_call_details_init(&call_details);
+
+  memset(ops, 0, sizeof(ops));
+  op = ops;
+  op->op = GRPC_OP_SEND_INITIAL_METADATA;
+  op->data.send_initial_metadata.count = 0;
+  op->flags = 0;
+  op->reserved = nullptr;
+  op++;
+  op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
+  op->flags = 0;
+  op->reserved = nullptr;
+  op++;
+  op->op = GRPC_OP_RECV_INITIAL_METADATA;
+  op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv;
+  op->flags = 0;
+  op->reserved = nullptr;
+  op++;
+  op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
+  op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
+  op->data.recv_status_on_client.status = &status;
+  op->data.recv_status_on_client.status_details = &details;
+  op->flags = 0;
+  op->reserved = nullptr;
+  op++;
+  error = grpc_call_start_batch(c, ops, static_cast<size_t>(op - ops), tag(1),
+                                nullptr);
+  GPR_ASSERT(error == GRPC_CALL_OK);
+
+  error =
+      grpc_server_request_call(f.server, &s, &call_details,
+                               &request_metadata_recv, f.cq, f.cq, tag(101));
+  GPR_ASSERT(error == GRPC_CALL_OK);
+  CQ_EXPECT_COMPLETION(cqv, tag(101), 1);
+  cq_verify(cqv);
+
+  peer = grpc_call_get_peer(s);
+  GPR_ASSERT(peer != nullptr);
+  gpr_log(GPR_DEBUG, "server_peer=%s", peer);
+  gpr_free(peer);
+  peer = grpc_call_get_peer(c);
+  GPR_ASSERT(peer != nullptr);
+  gpr_log(GPR_DEBUG, "client_peer=%s", peer);
+  gpr_free(peer);
+
+  memset(ops, 0, sizeof(ops));
+  op = ops;
+  op->op = GRPC_OP_SEND_INITIAL_METADATA;
+  op->data.send_initial_metadata.count = 0;
+  op->flags = 0;
+  op->reserved = nullptr;
+  op++;
+  op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
+  op->data.send_status_from_server.trailing_metadata_count = 0;
+  op->data.send_status_from_server.status = GRPC_STATUS_UNIMPLEMENTED;
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+  op->data.send_status_from_server.status_details = &status_details;
+  op->flags = 0;
+  op->reserved = nullptr;
+  op++;
+  op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
+  op->data.recv_close_on_server.cancelled = &was_cancelled;
+  op->flags = 0;
+  op->reserved = nullptr;
+  op++;
+  error = grpc_call_start_batch(s, ops, static_cast<size_t>(op - ops), tag(102),
+                                nullptr);
+  GPR_ASSERT(error == GRPC_CALL_OK);
+
+  CQ_EXPECT_COMPLETION(cqv, tag(102), 1);
+  CQ_EXPECT_COMPLETION(cqv, tag(1), 1);
+  cq_verify(cqv);
+
+  GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
+  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
+                                config);
+  GPR_ASSERT(was_cancelled == 1);
+
+  grpc_slice_unref(details);
+  grpc_metadata_array_destroy(&initial_metadata_recv);
+  grpc_metadata_array_destroy(&trailing_metadata_recv);
+  grpc_metadata_array_destroy(&request_metadata_recv);
+  grpc_call_details_destroy(&call_details);
+
+  grpc_call_unref(c);
+  grpc_call_unref(s);
+
+  cq_verifier_destroy(cqv);
+
+  end_test(&f);
+  config.tear_down_data(&f);
+}
+
+void call_host_override(grpc_end2end_test_config config) {
+  test_invoke_simple_request(config);
+}
+
+void call_host_override_pre_init(void) {}
diff --git a/test/core/end2end/tests/cancel_after_accept.cc b/test/core/end2end/tests/cancel_after_accept.cc
index e94ea51..788d374 100644
--- a/test/core/end2end/tests/cancel_after_accept.cc
+++ b/test/core/end2end/tests/cancel_after_accept.cc
@@ -146,11 +146,9 @@
   gpr_timespec deadline = use_service_config
                               ? gpr_inf_future(GPR_CLOCK_MONOTONIC)
                               : five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/service/method"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/service/method"),
+                               nullptr, deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
diff --git a/test/core/end2end/tests/cancel_after_client_done.cc b/test/core/end2end/tests/cancel_after_client_done.cc
index 31c3ea6..6e93783 100644
--- a/test/core/end2end/tests/cancel_after_client_done.cc
+++ b/test/core/end2end/tests/cancel_after_client_done.cc
@@ -119,11 +119,9 @@
   int was_cancelled = 2;
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
diff --git a/test/core/end2end/tests/cancel_after_invoke.cc b/test/core/end2end/tests/cancel_after_invoke.cc
index 72f7242..78009eb 100644
--- a/test/core/end2end/tests/cancel_after_invoke.cc
+++ b/test/core/end2end/tests/cancel_after_invoke.cc
@@ -113,11 +113,9 @@
       grpc_raw_byte_buffer_create(&request_payload_slice, 1);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
diff --git a/test/core/end2end/tests/cancel_after_round_trip.cc b/test/core/end2end/tests/cancel_after_round_trip.cc
index 4890b30..061b273 100644
--- a/test/core/end2end/tests/cancel_after_round_trip.cc
+++ b/test/core/end2end/tests/cancel_after_round_trip.cc
@@ -148,11 +148,9 @@
   gpr_timespec deadline = use_service_config
                               ? gpr_inf_future(GPR_CLOCK_MONOTONIC)
                               : five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/service/method"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/service/method"),
+                               nullptr, deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
diff --git a/test/core/end2end/tests/cancel_before_invoke.cc b/test/core/end2end/tests/cancel_before_invoke.cc
index c7d3ed5..abb2dbc 100644
--- a/test/core/end2end/tests/cancel_before_invoke.cc
+++ b/test/core/end2end/tests/cancel_before_invoke.cc
@@ -109,11 +109,9 @@
       grpc_raw_byte_buffer_create(&request_payload_slice, 1);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   GPR_ASSERT(GRPC_CALL_OK == grpc_call_cancel(c, nullptr));
diff --git a/test/core/end2end/tests/cancel_in_a_vacuum.cc b/test/core/end2end/tests/cancel_in_a_vacuum.cc
index 6be2d69..4672e64 100644
--- a/test/core/end2end/tests/cancel_in_a_vacuum.cc
+++ b/test/core/end2end/tests/cancel_in_a_vacuum.cc
@@ -97,11 +97,9 @@
   cq_verifier* v_client = cq_verifier_create(f.cq);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   GPR_ASSERT(GRPC_CALL_OK == mode.initiate_cancel(c, nullptr));
diff --git a/test/core/end2end/tests/cancel_with_status.cc b/test/core/end2end/tests/cancel_with_status.cc
index 887da85..2fc9d2f 100644
--- a/test/core/end2end/tests/cancel_with_status.cc
+++ b/test/core/end2end/tests/cancel_with_status.cc
@@ -104,11 +104,9 @@
   gpr_log(GPR_DEBUG, "test with %" PRIuPTR " ops", num_ops);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
diff --git a/test/core/end2end/tests/compressed_payload.cc b/test/core/end2end/tests/compressed_payload.cc
index 85cfe16..178d68c 100644
--- a/test/core/end2end/tests/compressed_payload.cc
+++ b/test/core/end2end/tests/compressed_payload.cc
@@ -137,11 +137,9 @@
   cqv = cq_verifier_create(f.cq);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -239,8 +237,6 @@
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, expected_details));
   gpr_free(expected_details);
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
 
   grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
@@ -320,11 +316,9 @@
   cqv = cq_verifier_create(f.cq);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -529,8 +523,6 @@
   GPR_ASSERT(status == GRPC_STATUS_OK);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 0);
 
   grpc_slice_unref(details);
diff --git a/test/core/end2end/tests/default_host.cc b/test/core/end2end/tests/default_host.cc
index 3191f76..22c3102 100644
--- a/test/core/end2end/tests/default_host.cc
+++ b/test/core/end2end/tests/default_host.cc
@@ -85,7 +85,9 @@
   grpc_completion_queue_destroy(f->shutdown_cq);
 }
 
-static void simple_request_body(grpc_end2end_test_fixture f) {
+static void test_invoke_simple_request(grpc_end2end_test_config config) {
+  grpc_end2end_test_fixture f =
+      begin_test(config, "test_invoke_simple_request", nullptr, nullptr);
   grpc_call* c;
   grpc_call* s;
   cq_verifier* cqv = cq_verifier_create(f.cq);
@@ -191,7 +193,14 @@
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  GPR_ASSERT(grpc_slice_buf_start_eq(call_details.host, "localhost", 9));
+
+  if (config.overridden_call_host != nullptr) {
+    validate_host_override_string(config.overridden_call_host,
+                                  call_details.host, config);
+  } else {
+    GPR_ASSERT(grpc_slice_buf_start_eq(call_details.host, "localhost", 9) ||
+               grpc_slice_buf_start_eq(call_details.host, "127.0.0.1", 9));
+  }
   GPR_ASSERT(was_cancelled == 1);
 
   grpc_slice_unref(details);
@@ -204,22 +213,12 @@
   grpc_call_unref(s);
 
   cq_verifier_destroy(cqv);
-}
 
-static void test_invoke_simple_request(grpc_end2end_test_config config) {
-  grpc_end2end_test_fixture f;
-
-  f = begin_test(config, "test_invoke_simple_request", nullptr, nullptr);
-  simple_request_body(f);
   end_test(&f);
   config.tear_down_data(&f);
 }
 
 void default_host(grpc_end2end_test_config config) {
-  if ((config.feature_mask & FEATURE_MASK_SUPPORTS_HOSTNAME_VERIFICATION) == 0)
-    return;
-  if ((config.feature_mask & FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION) == 0)
-    return;
   test_invoke_simple_request(config);
 }
 
diff --git a/test/core/end2end/tests/disappearing_server.cc b/test/core/end2end/tests/disappearing_server.cc
index d5b6f8f..fdd780f 100644
--- a/test/core/end2end/tests/disappearing_server.cc
+++ b/test/core/end2end/tests/disappearing_server.cc
@@ -85,11 +85,9 @@
   int was_cancelled = 2;
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f->client, nullptr, GRPC_PROPAGATE_DEFAULTS, f->cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f->client, nullptr, GRPC_PROPAGATE_DEFAULTS,
+                               f->cq, grpc_slice_from_static_string("/foo"),
+                               nullptr, deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -167,8 +165,6 @@
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 1);
 
   grpc_slice_unref(details);
diff --git a/test/core/end2end/tests/empty_batch.cc b/test/core/end2end/tests/empty_batch.cc
index 1de4b8f..317bb7a 100644
--- a/test/core/end2end/tests/empty_batch.cc
+++ b/test/core/end2end/tests/empty_batch.cc
@@ -93,11 +93,9 @@
   grpc_op* op = nullptr;
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   error = grpc_call_start_batch(c, op, 0, tag(1), nullptr);
diff --git a/test/core/end2end/tests/filter_call_init_fails.cc b/test/core/end2end/tests/filter_call_init_fails.cc
index 6f72a18..ab96879 100644
--- a/test/core/end2end/tests/filter_call_init_fails.cc
+++ b/test/core/end2end/tests/filter_call_init_fails.cc
@@ -117,11 +117,9 @@
   grpc_slice details;
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -213,11 +211,9 @@
   grpc_call_error error;
   grpc_slice details;
 
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -304,11 +300,9 @@
   grpc_call_error error;
   grpc_slice details;
 
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -364,11 +358,9 @@
   grpc_slice_unref(details);
   details = grpc_empty_slice();
 
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   error = grpc_call_start_batch(c, ops, static_cast<size_t>(op - ops), tag(2),
diff --git a/test/core/end2end/tests/filter_causes_close.cc b/test/core/end2end/tests/filter_causes_close.cc
index bc4cb86..a7f4268 100644
--- a/test/core/end2end/tests/filter_causes_close.cc
+++ b/test/core/end2end/tests/filter_causes_close.cc
@@ -111,11 +111,9 @@
   grpc_slice details;
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
diff --git a/test/core/end2end/tests/filter_latency.cc b/test/core/end2end/tests/filter_latency.cc
index 51f54c9..a89db7b 100644
--- a/test/core/end2end/tests/filter_latency.cc
+++ b/test/core/end2end/tests/filter_latency.cc
@@ -125,10 +125,9 @@
   const gpr_timespec start_time = gpr_now(GPR_CLOCK_MONOTONIC);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr", config), deadline, nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
diff --git a/test/core/end2end/tests/filter_status_code.cc b/test/core/end2end/tests/filter_status_code.cc
index 32cd954..ba3cbfa 100644
--- a/test/core/end2end/tests/filter_status_code.cc
+++ b/test/core/end2end/tests/filter_status_code.cc
@@ -126,10 +126,9 @@
   gpr_mu_unlock(&g_mu);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr", config), deadline, nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
   gpr_mu_lock(&g_mu);
   g_client_call_stack = grpc_call_get_call_stack(c);
diff --git a/test/core/end2end/tests/graceful_server_shutdown.cc b/test/core/end2end/tests/graceful_server_shutdown.cc
index 3ef414f..42f2d1a 100644
--- a/test/core/end2end/tests/graceful_server_shutdown.cc
+++ b/test/core/end2end/tests/graceful_server_shutdown.cc
@@ -99,11 +99,9 @@
   int was_cancelled = 2;
 
   gpr_timespec deadline = n_seconds_from_now(10);
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -183,8 +181,6 @@
 
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 1);
 
   grpc_slice_unref(details);
diff --git a/test/core/end2end/tests/high_initial_seqno.cc b/test/core/end2end/tests/high_initial_seqno.cc
index 8767437..18e6ee9 100644
--- a/test/core/end2end/tests/high_initial_seqno.cc
+++ b/test/core/end2end/tests/high_initial_seqno.cc
@@ -104,11 +104,9 @@
   int was_cancelled = 2;
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -181,8 +179,6 @@
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 1);
 
   grpc_slice_unref(details);
diff --git a/test/core/end2end/tests/hpack_size.cc b/test/core/end2end/tests/hpack_size.cc
index b4973684..7c51294 100644
--- a/test/core/end2end/tests/hpack_size.cc
+++ b/test/core/end2end/tests/hpack_size.cc
@@ -257,11 +257,9 @@
       grpc_slice_from_static_string(dragons[index % GPR_ARRAY_SIZE(dragons)]);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -335,8 +333,6 @@
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 1);
 
   grpc_slice_unref(details);
diff --git a/test/core/end2end/tests/idempotent_request.cc b/test/core/end2end/tests/idempotent_request.cc
index 56be2d6..80908d5 100644
--- a/test/core/end2end/tests/idempotent_request.cc
+++ b/test/core/end2end/tests/idempotent_request.cc
@@ -104,11 +104,9 @@
   char* peer;
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   peer = grpc_call_get_peer(c);
@@ -195,8 +193,6 @@
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST == call_details.flags);
   GPR_ASSERT(was_cancelled == 1);
 
diff --git a/test/core/end2end/tests/invoke_large_request.cc b/test/core/end2end/tests/invoke_large_request.cc
index 1aab34c..39d90ab 100644
--- a/test/core/end2end/tests/invoke_large_request.cc
+++ b/test/core/end2end/tests/invoke_large_request.cc
@@ -131,11 +131,9 @@
   int was_cancelled = 2;
 
   gpr_timespec deadline = n_seconds_from_now(30);
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -237,8 +235,6 @@
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 1);
 
   grpc_slice_unref(details);
diff --git a/test/core/end2end/tests/keepalive_timeout.cc b/test/core/end2end/tests/keepalive_timeout.cc
index c0771b8..1ee5285 100644
--- a/test/core/end2end/tests/keepalive_timeout.cc
+++ b/test/core/end2end/tests/keepalive_timeout.cc
@@ -130,11 +130,9 @@
   grpc_set_disable_ping_ack(true);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -200,8 +198,6 @@
   GPR_ASSERT(status == GRPC_STATUS_INTERNAL);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "keepalive watchdog timeout"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
 
   gpr_free(details_str);
   gpr_free(method_str);
diff --git a/test/core/end2end/tests/large_metadata.cc b/test/core/end2end/tests/large_metadata.cc
index da0615b..c7f72a1 100644
--- a/test/core/end2end/tests/large_metadata.cc
+++ b/test/core/end2end/tests/large_metadata.cc
@@ -114,11 +114,9 @@
   int was_cancelled = 2;
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   meta.key = grpc_slice_from_static_string("key");
@@ -220,8 +218,6 @@
   GPR_ASSERT(status == GRPC_STATUS_OK);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 0);
   GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world"));
   GPR_ASSERT(contains_metadata_slices(&request_metadata_recv,
diff --git a/test/core/end2end/tests/load_reporting_hook.cc b/test/core/end2end/tests/load_reporting_hook.cc
index 9e79d02..4324e9d 100644
--- a/test/core/end2end/tests/load_reporting_hook.cc
+++ b/test/core/end2end/tests/load_reporting_hook.cc
@@ -138,11 +138,9 @@
   int was_cancelled = 2;
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string(method_name),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string(method_name),
+                               nullptr, deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
diff --git a/test/core/end2end/tests/max_concurrent_streams.cc b/test/core/end2end/tests/max_concurrent_streams.cc
index 789b3d4..86a8d22 100644
--- a/test/core/end2end/tests/max_concurrent_streams.cc
+++ b/test/core/end2end/tests/max_concurrent_streams.cc
@@ -100,11 +100,9 @@
   int was_cancelled = 2;
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -177,8 +175,6 @@
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 1);
 
   grpc_slice_unref(details);
@@ -248,17 +244,13 @@
   /* start two requests - ensuring that the second is not accepted until
      the first completes */
   deadline = n_seconds_from_now(1000);
-  c1 = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/alpha"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c1 = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS,
+                                f.cq, grpc_slice_from_static_string("/alpha"),
+                                nullptr, deadline, nullptr);
   GPR_ASSERT(c1);
-  c2 = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/beta"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c2 = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS,
+                                f.cq, grpc_slice_from_static_string("/beta"),
+                                nullptr, deadline, nullptr);
   GPR_ASSERT(c2);
 
   GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(
@@ -494,17 +486,13 @@
 
   /* start two requests - ensuring that the second is not accepted until
      the first completes */
-  c1 = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/alpha"),
-      get_host_override_slice("foo.test.google.fr:1234", config),
-      n_seconds_from_now(3), nullptr);
+  c1 = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS,
+                                f.cq, grpc_slice_from_static_string("/alpha"),
+                                nullptr, n_seconds_from_now(3), nullptr);
   GPR_ASSERT(c1);
-  c2 = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/beta"),
-      get_host_override_slice("foo.test.google.fr:1234", config),
-      n_seconds_from_now(1000), nullptr);
+  c2 = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS,
+                                f.cq, grpc_slice_from_static_string("/beta"),
+                                nullptr, n_seconds_from_now(1000), nullptr);
   GPR_ASSERT(c2);
 
   GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(
@@ -694,17 +682,13 @@
   /* start two requests - ensuring that the second is not accepted until
      the first completes , and the second request will timeout in the
      concurrent_list */
-  c1 = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/alpha"),
-      get_host_override_slice("foo.test.google.fr:1234", config),
-      n_seconds_from_now(1000), nullptr);
+  c1 = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS,
+                                f.cq, grpc_slice_from_static_string("/alpha"),
+                                nullptr, n_seconds_from_now(1000), nullptr);
   GPR_ASSERT(c1);
-  c2 = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/beta"),
-      get_host_override_slice("foo.test.google.fr:1234", config),
-      n_seconds_from_now(3), nullptr);
+  c2 = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS,
+                                f.cq, grpc_slice_from_static_string("/beta"),
+                                nullptr, n_seconds_from_now(3), nullptr);
   GPR_ASSERT(c2);
 
   GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(
diff --git a/test/core/end2end/tests/max_connection_age.cc b/test/core/end2end/tests/max_connection_age.cc
index e494dad..fcb0aaf 100644
--- a/test/core/end2end/tests/max_connection_age.cc
+++ b/test/core/end2end/tests/max_connection_age.cc
@@ -109,11 +109,9 @@
   grpc_slice details;
   int was_cancelled = 2;
 
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -208,8 +206,6 @@
      the in-progress RPC should fail. */
   GPR_ASSERT(status == GRPC_STATUS_INTERNAL);
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 1);
 
   grpc_slice_unref(details);
@@ -255,11 +251,9 @@
   grpc_slice details;
   int was_cancelled = 2;
 
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -348,8 +342,6 @@
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 1);
 
   grpc_slice_unref(details);
diff --git a/test/core/end2end/tests/max_connection_idle.cc b/test/core/end2end/tests/max_connection_idle.cc
index 2f212b9..faa1383 100644
--- a/test/core/end2end/tests/max_connection_idle.cc
+++ b/test/core/end2end/tests/max_connection_idle.cc
@@ -60,11 +60,9 @@
   char* peer;
 
   gpr_timespec deadline = grpc_timeout_seconds_to_deadline(5);
-  c = grpc_channel_create_call(
-      f->client, nullptr, GRPC_PROPAGATE_DEFAULTS, f->cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f->client, nullptr, GRPC_PROPAGATE_DEFAULTS,
+                               f->cq, grpc_slice_from_static_string("/foo"),
+                               nullptr, deadline, nullptr);
   GPR_ASSERT(c);
 
   peer = grpc_call_get_peer(c);
@@ -151,8 +149,6 @@
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(0 == call_details.flags);
   GPR_ASSERT(was_cancelled == 1);
 
diff --git a/test/core/end2end/tests/max_message_length.cc b/test/core/end2end/tests/max_message_length.cc
index fa5b3b6..6ac941e 100644
--- a/test/core/end2end/tests/max_message_length.cc
+++ b/test/core/end2end/tests/max_message_length.cc
@@ -180,11 +180,10 @@
 
   cqv = cq_verifier_create(f.cq);
 
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/service/method"),
-      get_host_override_slice("foo.test.google.fr:1234", config),
-      gpr_inf_future(GPR_CLOCK_REALTIME), nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/service/method"),
+                               nullptr, gpr_inf_future(GPR_CLOCK_REALTIME),
+                               nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -258,8 +257,6 @@
   cq_verify(cqv);
 
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 1);
 
 done:
@@ -371,11 +368,10 @@
   }
   cqv = cq_verifier_create(f.cq);
 
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/service/method"),
-      get_host_override_slice("foo.test.google.fr:1234", config),
-      gpr_inf_future(GPR_CLOCK_REALTIME), nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/service/method"),
+                               nullptr, gpr_inf_future(GPR_CLOCK_REALTIME),
+                               nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -456,9 +452,6 @@
   cq_verify(cqv);
 
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method"));
-  GPR_ASSERT(0 ==
-             grpc_slice_str_cmp(call_details.host, "foo.test.google.fr:1234"));
-
   GPR_ASSERT(status == GRPC_STATUS_RESOURCE_EXHAUSTED);
   GPR_ASSERT(
       grpc_slice_str_cmp(
diff --git a/test/core/end2end/tests/negative_deadline.cc b/test/core/end2end/tests/negative_deadline.cc
index dce3a02..2b2ff12 100644
--- a/test/core/end2end/tests/negative_deadline.cc
+++ b/test/core/end2end/tests/negative_deadline.cc
@@ -101,11 +101,9 @@
   gpr_log(GPR_DEBUG, "test with %" PRIuPTR " ops", num_ops);
 
   gpr_timespec deadline = gpr_inf_past(GPR_CLOCK_REALTIME);
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
diff --git a/test/core/end2end/tests/network_status_change.cc b/test/core/end2end/tests/network_status_change.cc
index 83cb172..98a9558 100644
--- a/test/core/end2end/tests/network_status_change.cc
+++ b/test/core/end2end/tests/network_status_change.cc
@@ -110,11 +110,9 @@
   int was_cancelled = 2;
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -209,8 +207,6 @@
   GPR_ASSERT(status == GRPC_STATUS_OK);
 
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
 
   grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
diff --git a/test/core/end2end/tests/no_logging.cc b/test/core/end2end/tests/no_logging.cc
index b357e3b..c815402 100644
--- a/test/core/end2end/tests/no_logging.cc
+++ b/test/core/end2end/tests/no_logging.cc
@@ -131,11 +131,9 @@
   char* peer;
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   peer = grpc_call_get_peer(c);
@@ -219,8 +217,6 @@
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(0 == call_details.flags);
   GPR_ASSERT(was_cancelled == 1);
 
diff --git a/test/core/end2end/tests/payload.cc b/test/core/end2end/tests/payload.cc
index 340c76e..cb6eb47 100644
--- a/test/core/end2end/tests/payload.cc
+++ b/test/core/end2end/tests/payload.cc
@@ -129,11 +129,9 @@
   int was_cancelled = 2;
 
   gpr_timespec deadline = n_seconds_from_now(60);
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -235,8 +233,6 @@
   GPR_ASSERT(status == GRPC_STATUS_OK);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 0);
   GPR_ASSERT(byte_buffer_eq_slice(request_payload_recv, request_payload_slice));
   GPR_ASSERT(
diff --git a/test/core/end2end/tests/ping_pong_streaming.cc b/test/core/end2end/tests/ping_pong_streaming.cc
index 9ca8804..30ee0bf 100644
--- a/test/core/end2end/tests/ping_pong_streaming.cc
+++ b/test/core/end2end/tests/ping_pong_streaming.cc
@@ -112,11 +112,9 @@
       grpc_slice_from_copied_string("hello you");
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
diff --git a/test/core/end2end/tests/proxy_auth.cc b/test/core/end2end/tests/proxy_auth.cc
index 5a2e0ef..3b12869 100644
--- a/test/core/end2end/tests/proxy_auth.cc
+++ b/test/core/end2end/tests/proxy_auth.cc
@@ -108,11 +108,9 @@
   char* peer;
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   peer = grpc_call_get_peer(c);
@@ -199,8 +197,6 @@
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(0 == call_details.flags);
   GPR_ASSERT(was_cancelled == 1);
 
diff --git a/test/core/end2end/tests/registered_call.cc b/test/core/end2end/tests/registered_call.cc
index d4ca146..3e05fd1 100644
--- a/test/core/end2end/tests/registered_call.cc
+++ b/test/core/end2end/tests/registered_call.cc
@@ -177,8 +177,6 @@
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 1);
 
   grpc_slice_unref(details);
@@ -196,9 +194,7 @@
 static void test_invoke_simple_request(grpc_end2end_test_config config) {
   grpc_end2end_test_fixture f =
       begin_test(config, "test_invoke_simple_request", nullptr, nullptr);
-  void* rc = grpc_channel_register_call(
-      f.client, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), nullptr);
+  void* rc = grpc_channel_register_call(f.client, "/foo", nullptr, nullptr);
 
   simple_request_body(config, f, rc);
   end_test(&f);
@@ -209,9 +205,7 @@
   int i;
   grpc_end2end_test_fixture f =
       begin_test(config, "test_invoke_10_simple_requests", nullptr, nullptr);
-  void* rc = grpc_channel_register_call(
-      f.client, "/foo",
-      get_host_override_string("foo.test.google.fr:1234", config), nullptr);
+  void* rc = grpc_channel_register_call(f.client, "/foo", nullptr, nullptr);
 
   for (i = 0; i < 10; i++) {
     simple_request_body(config, f, rc);
diff --git a/test/core/end2end/tests/request_with_flags.cc b/test/core/end2end/tests/request_with_flags.cc
index c524824..f3baf37 100644
--- a/test/core/end2end/tests/request_with_flags.cc
+++ b/test/core/end2end/tests/request_with_flags.cc
@@ -108,11 +108,9 @@
   grpc_call_error expectation;
 
   gpr_timespec deadline = one_second_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
diff --git a/test/core/end2end/tests/request_with_payload.cc b/test/core/end2end/tests/request_with_payload.cc
index 44398df..37d9481 100644
--- a/test/core/end2end/tests/request_with_payload.cc
+++ b/test/core/end2end/tests/request_with_payload.cc
@@ -107,11 +107,9 @@
   int was_cancelled = 2;
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -202,8 +200,6 @@
   GPR_ASSERT(status == GRPC_STATUS_OK);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 0);
   GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world"));
 
diff --git a/test/core/end2end/tests/resource_quota_server.cc b/test/core/end2end/tests/resource_quota_server.cc
index 33d6b4e..df83caa 100644
--- a/test/core/end2end/tests/resource_quota_server.cc
+++ b/test/core/end2end/tests/resource_quota_server.cc
@@ -188,11 +188,10 @@
   }
 
   for (int i = 0; i < NUM_CALLS; i++) {
-    client_calls[i] = grpc_channel_create_call(
-        f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-        grpc_slice_from_static_string("/foo"),
-        get_host_override_slice("foo.test.google.fr", config),
-        n_seconds_from_now(60), nullptr);
+    client_calls[i] =
+        grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS,
+                                 f.cq, grpc_slice_from_static_string("/foo"),
+                                 nullptr, n_seconds_from_now(60), nullptr);
 
     memset(ops, 0, sizeof(ops));
     op = ops;
diff --git a/test/core/end2end/tests/retry.cc b/test/core/end2end/tests/retry.cc
index 38ecc6f..243dedc 100644
--- a/test/core/end2end/tests/retry.cc
+++ b/test/core/end2end/tests/retry.cc
@@ -145,11 +145,9 @@
   cq_verifier* cqv = cq_verifier_create(f.cq);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/service/method"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/service/method"),
+                               nullptr, deadline, nullptr);
   GPR_ASSERT(c);
 
   peer = grpc_call_get_peer(c);
@@ -293,8 +291,6 @@
   GPR_ASSERT(status == GRPC_STATUS_OK);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(0 == call_details.flags);
   GPR_ASSERT(was_cancelled == 0);
 
diff --git a/test/core/end2end/tests/retry_cancellation.cc b/test/core/end2end/tests/retry_cancellation.cc
index 0504092..e764fe7 100644
--- a/test/core/end2end/tests/retry_cancellation.cc
+++ b/test/core/end2end/tests/retry_cancellation.cc
@@ -146,11 +146,9 @@
   cq_verifier* cqv = cq_verifier_create(f.cq);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/service/method"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/service/method"),
+                               nullptr, deadline, nullptr);
   GPR_ASSERT(c);
 
   peer = grpc_call_get_peer(c);
diff --git a/test/core/end2end/tests/retry_disabled.cc b/test/core/end2end/tests/retry_disabled.cc
index cb30502..ed35354 100644
--- a/test/core/end2end/tests/retry_disabled.cc
+++ b/test/core/end2end/tests/retry_disabled.cc
@@ -149,11 +149,9 @@
   cq_verifier* cqv = cq_verifier_create(f.cq);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/service/method"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/service/method"),
+                               nullptr, deadline, nullptr);
   GPR_ASSERT(c);
 
   peer = grpc_call_get_peer(c);
@@ -230,8 +228,6 @@
   GPR_ASSERT(status == GRPC_STATUS_ABORTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(0 == call_details.flags);
   GPR_ASSERT(was_cancelled == 1);
 
diff --git a/test/core/end2end/tests/retry_exceeds_buffer_size_in_initial_batch.cc b/test/core/end2end/tests/retry_exceeds_buffer_size_in_initial_batch.cc
index 3908f29..a033a0a 100644
--- a/test/core/end2end/tests/retry_exceeds_buffer_size_in_initial_batch.cc
+++ b/test/core/end2end/tests/retry_exceeds_buffer_size_in_initial_batch.cc
@@ -152,11 +152,9 @@
   cq_verifier* cqv = cq_verifier_create(f.cq);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/service/method"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/service/method"),
+                               nullptr, deadline, nullptr);
   GPR_ASSERT(c);
 
   peer = grpc_call_get_peer(c);
@@ -233,8 +231,6 @@
   GPR_ASSERT(status == GRPC_STATUS_ABORTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(0 == call_details.flags);
   GPR_ASSERT(was_cancelled == 1);
 
diff --git a/test/core/end2end/tests/retry_exceeds_buffer_size_in_subsequent_batch.cc b/test/core/end2end/tests/retry_exceeds_buffer_size_in_subsequent_batch.cc
index 409fac4..c1070e6 100644
--- a/test/core/end2end/tests/retry_exceeds_buffer_size_in_subsequent_batch.cc
+++ b/test/core/end2end/tests/retry_exceeds_buffer_size_in_subsequent_batch.cc
@@ -157,11 +157,9 @@
   cq_verifier* cqv = cq_verifier_create(f.cq);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/service/method"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/service/method"),
+                               nullptr, deadline, nullptr);
   GPR_ASSERT(c);
 
   peer = grpc_call_get_peer(c);
@@ -245,8 +243,6 @@
   GPR_ASSERT(status == GRPC_STATUS_ABORTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(0 == call_details.flags);
   GPR_ASSERT(was_cancelled == 1);
 
diff --git a/test/core/end2end/tests/retry_non_retriable_status.cc b/test/core/end2end/tests/retry_non_retriable_status.cc
index 6d59db0..b8d0947 100644
--- a/test/core/end2end/tests/retry_non_retriable_status.cc
+++ b/test/core/end2end/tests/retry_non_retriable_status.cc
@@ -144,11 +144,9 @@
   cq_verifier* cqv = cq_verifier_create(f.cq);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/service/method"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/service/method"),
+                               nullptr, deadline, nullptr);
   GPR_ASSERT(c);
 
   peer = grpc_call_get_peer(c);
@@ -225,8 +223,6 @@
   GPR_ASSERT(status == GRPC_STATUS_INVALID_ARGUMENT);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(0 == call_details.flags);
   GPR_ASSERT(was_cancelled == 1);
 
diff --git a/test/core/end2end/tests/retry_non_retriable_status_before_recv_trailing_metadata_started.cc b/test/core/end2end/tests/retry_non_retriable_status_before_recv_trailing_metadata_started.cc
new file mode 100644
index 0000000..eb016a3
--- /dev/null
+++ b/test/core/end2end/tests/retry_non_retriable_status_before_recv_trailing_metadata_started.cc
@@ -0,0 +1,266 @@
+/*
+ *
+ * Copyright 2018 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.
+ *
+ */
+
+#include "test/core/end2end/end2end_tests.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include <grpc/byte_buffer.h>
+#include <grpc/grpc.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+#include <grpc/support/time.h>
+
+#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/gpr/string.h"
+#include "src/core/lib/gpr/useful.h"
+#include "src/core/lib/iomgr/exec_ctx.h"
+#include "src/core/lib/transport/static_metadata.h"
+
+#include "test/core/end2end/cq_verifier.h"
+#include "test/core/end2end/tests/cancel_test_helpers.h"
+
+static void* tag(intptr_t t) { return (void*)t; }
+
+static grpc_end2end_test_fixture begin_test(grpc_end2end_test_config config,
+                                            const char* test_name,
+                                            grpc_channel_args* client_args,
+                                            grpc_channel_args* server_args) {
+  grpc_end2end_test_fixture f;
+  gpr_log(GPR_INFO, "Running test: %s/%s", test_name, config.name);
+  f = config.create_fixture(client_args, server_args);
+  config.init_server(&f, server_args);
+  config.init_client(&f, client_args);
+  return f;
+}
+
+static gpr_timespec n_seconds_from_now(int n) {
+  return grpc_timeout_seconds_to_deadline(n);
+}
+
+static gpr_timespec five_seconds_from_now(void) {
+  return n_seconds_from_now(5);
+}
+
+static void drain_cq(grpc_completion_queue* cq) {
+  grpc_event ev;
+  do {
+    ev = grpc_completion_queue_next(cq, five_seconds_from_now(), nullptr);
+  } while (ev.type != GRPC_QUEUE_SHUTDOWN);
+}
+
+static void shutdown_server(grpc_end2end_test_fixture* f) {
+  if (!f->server) return;
+  grpc_server_shutdown_and_notify(f->server, f->shutdown_cq, tag(1000));
+  GPR_ASSERT(grpc_completion_queue_pluck(f->shutdown_cq, tag(1000),
+                                         grpc_timeout_seconds_to_deadline(5),
+                                         nullptr)
+                 .type == GRPC_OP_COMPLETE);
+  grpc_server_destroy(f->server);
+  f->server = nullptr;
+}
+
+static void shutdown_client(grpc_end2end_test_fixture* f) {
+  if (!f->client) return;
+  grpc_channel_destroy(f->client);
+  f->client = nullptr;
+}
+
+static void end_test(grpc_end2end_test_fixture* f) {
+  shutdown_server(f);
+  shutdown_client(f);
+
+  grpc_completion_queue_shutdown(f->cq);
+  drain_cq(f->cq);
+  grpc_completion_queue_destroy(f->cq);
+  grpc_completion_queue_destroy(f->shutdown_cq);
+}
+
+// Tests that we don't retry for non-retryable status codes, even if
+// status is received before the recv_trailing_metadata op is started.
+// - 1 retry allowed for ABORTED status
+// - first attempt gets INVALID_ARGUMENT, so no retry is done
+static void
+test_retry_non_retriable_status_before_recv_trailing_metadata_started(
+    grpc_end2end_test_config config) {
+  grpc_call* c;
+  grpc_call* s;
+  grpc_op ops[6];
+  grpc_op* op;
+  grpc_metadata_array initial_metadata_recv;
+  grpc_metadata_array trailing_metadata_recv;
+  grpc_metadata_array request_metadata_recv;
+  grpc_call_details call_details;
+  grpc_slice request_payload_slice = grpc_slice_from_static_string("foo");
+  grpc_slice response_payload_slice = grpc_slice_from_static_string("bar");
+  grpc_byte_buffer* request_payload =
+      grpc_raw_byte_buffer_create(&request_payload_slice, 1);
+  grpc_byte_buffer* response_payload =
+      grpc_raw_byte_buffer_create(&response_payload_slice, 1);
+  grpc_byte_buffer* request_payload_recv = nullptr;
+  grpc_byte_buffer* response_payload_recv = nullptr;
+  grpc_status_code status;
+  grpc_call_error error;
+  grpc_slice details;
+  int was_cancelled = 2;
+  char* peer;
+
+  grpc_arg arg;
+  arg.type = GRPC_ARG_STRING;
+  arg.key = const_cast<char*>(GRPC_ARG_SERVICE_CONFIG);
+  arg.value.string = const_cast<char*>(
+      "{\n"
+      "  \"methodConfig\": [ {\n"
+      "    \"name\": [\n"
+      "      { \"service\": \"service\", \"method\": \"method\" }\n"
+      "    ],\n"
+      "    \"retryPolicy\": {\n"
+      "      \"maxAttempts\": 2,\n"
+      "      \"initialBackoff\": \"1s\",\n"
+      "      \"maxBackoff\": \"120s\",\n"
+      "      \"backoffMultiplier\": 1.6,\n"
+      "      \"retryableStatusCodes\": [ \"ABORTED\" ]\n"
+      "    }\n"
+      "  } ]\n"
+      "}");
+  grpc_channel_args client_args = {1, &arg};
+  grpc_end2end_test_fixture f =
+      begin_test(config, "retry_non_retriable_status", &client_args, nullptr);
+
+  cq_verifier* cqv = cq_verifier_create(f.cq);
+
+  gpr_timespec deadline = five_seconds_from_now();
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/service/method"),
+                               nullptr, deadline, nullptr);
+  GPR_ASSERT(c);
+
+  peer = grpc_call_get_peer(c);
+  GPR_ASSERT(peer != nullptr);
+  gpr_log(GPR_DEBUG, "client_peer_before_call=%s", peer);
+  gpr_free(peer);
+
+  grpc_metadata_array_init(&initial_metadata_recv);
+  grpc_metadata_array_init(&trailing_metadata_recv);
+  grpc_metadata_array_init(&request_metadata_recv);
+  grpc_call_details_init(&call_details);
+  grpc_slice status_details = grpc_slice_from_static_string("xyz");
+
+  memset(ops, 0, sizeof(ops));
+  op = ops;
+  op->op = GRPC_OP_SEND_INITIAL_METADATA;
+  op->data.send_initial_metadata.count = 0;
+  op++;
+  op->op = GRPC_OP_SEND_MESSAGE;
+  op->data.send_message.send_message = request_payload;
+  op++;
+  op->op = GRPC_OP_RECV_MESSAGE;
+  op->data.recv_message.recv_message = &response_payload_recv;
+  op++;
+  op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
+  op++;
+  op->op = GRPC_OP_RECV_INITIAL_METADATA;
+  op->data.recv_initial_metadata.recv_initial_metadata = &initial_metadata_recv;
+  op++;
+  error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(1), nullptr);
+  GPR_ASSERT(GRPC_CALL_OK == error);
+
+  error =
+      grpc_server_request_call(f.server, &s, &call_details,
+                               &request_metadata_recv, f.cq, f.cq, tag(101));
+  GPR_ASSERT(GRPC_CALL_OK == error);
+  CQ_EXPECT_COMPLETION(cqv, tag(101), true);
+  cq_verify(cqv);
+
+  peer = grpc_call_get_peer(s);
+  GPR_ASSERT(peer != nullptr);
+  gpr_log(GPR_DEBUG, "server_peer=%s", peer);
+  gpr_free(peer);
+  peer = grpc_call_get_peer(c);
+  GPR_ASSERT(peer != nullptr);
+  gpr_log(GPR_DEBUG, "client_peer=%s", peer);
+  gpr_free(peer);
+
+  memset(ops, 0, sizeof(ops));
+  op = ops;
+  op->op = GRPC_OP_SEND_INITIAL_METADATA;
+  op->data.send_initial_metadata.count = 0;
+  op++;
+  op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
+  op->data.send_status_from_server.trailing_metadata_count = 0;
+  op->data.send_status_from_server.status = GRPC_STATUS_INVALID_ARGUMENT;
+  op->data.send_status_from_server.status_details = &status_details;
+  op++;
+  op->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
+  op->data.recv_close_on_server.cancelled = &was_cancelled;
+  op++;
+  error = grpc_call_start_batch(s, ops, (size_t)(op - ops), tag(102), nullptr);
+  GPR_ASSERT(GRPC_CALL_OK == error);
+
+  CQ_EXPECT_COMPLETION(cqv, tag(102), true);
+  CQ_EXPECT_COMPLETION(cqv, tag(1), true);
+  cq_verify(cqv);
+
+  memset(ops, 0, sizeof(ops));
+  op = ops;
+  op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
+  op->data.recv_status_on_client.trailing_metadata = &trailing_metadata_recv;
+  op->data.recv_status_on_client.status = &status;
+  op->data.recv_status_on_client.status_details = &details;
+  op++;
+  error = grpc_call_start_batch(c, ops, (size_t)(op - ops), tag(2), nullptr);
+  GPR_ASSERT(GRPC_CALL_OK == error);
+
+  CQ_EXPECT_COMPLETION(cqv, tag(2), true);
+  cq_verify(cqv);
+
+  GPR_ASSERT(status == GRPC_STATUS_INVALID_ARGUMENT);
+  GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
+  GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method"));
+  GPR_ASSERT(0 == call_details.flags);
+  GPR_ASSERT(was_cancelled == 1);
+
+  grpc_slice_unref(details);
+  grpc_metadata_array_destroy(&initial_metadata_recv);
+  grpc_metadata_array_destroy(&trailing_metadata_recv);
+  grpc_metadata_array_destroy(&request_metadata_recv);
+  grpc_call_details_destroy(&call_details);
+  grpc_byte_buffer_destroy(request_payload);
+  grpc_byte_buffer_destroy(response_payload);
+  grpc_byte_buffer_destroy(request_payload_recv);
+  grpc_byte_buffer_destroy(response_payload_recv);
+
+  grpc_call_unref(c);
+  grpc_call_unref(s);
+
+  cq_verifier_destroy(cqv);
+
+  end_test(&f);
+  config.tear_down_data(&f);
+}
+
+void retry_non_retriable_status_before_recv_trailing_metadata_started(
+    grpc_end2end_test_config config) {
+  GPR_ASSERT(config.feature_mask & FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL);
+  test_retry_non_retriable_status_before_recv_trailing_metadata_started(config);
+}
+
+void retry_non_retriable_status_before_recv_trailing_metadata_started_pre_init() {
+}
diff --git a/test/core/end2end/tests/retry_recv_initial_metadata.cc b/test/core/end2end/tests/retry_recv_initial_metadata.cc
index 14215e4..839b870 100644
--- a/test/core/end2end/tests/retry_recv_initial_metadata.cc
+++ b/test/core/end2end/tests/retry_recv_initial_metadata.cc
@@ -145,11 +145,9 @@
   cq_verifier* cqv = cq_verifier_create(f.cq);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/service/method"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/service/method"),
+                               nullptr, deadline, nullptr);
   GPR_ASSERT(c);
 
   peer = grpc_call_get_peer(c);
@@ -236,8 +234,6 @@
   GPR_ASSERT(status == GRPC_STATUS_ABORTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(0 == call_details.flags);
   GPR_ASSERT(was_cancelled == 1);
 
diff --git a/test/core/end2end/tests/retry_recv_message.cc b/test/core/end2end/tests/retry_recv_message.cc
index 86171fd..5fdaad0 100644
--- a/test/core/end2end/tests/retry_recv_message.cc
+++ b/test/core/end2end/tests/retry_recv_message.cc
@@ -145,11 +145,9 @@
   cq_verifier* cqv = cq_verifier_create(f.cq);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/service/method"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/service/method"),
+                               nullptr, deadline, nullptr);
   GPR_ASSERT(c);
 
   peer = grpc_call_get_peer(c);
@@ -229,8 +227,6 @@
   GPR_ASSERT(status == GRPC_STATUS_ABORTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(0 == call_details.flags);
   GPR_ASSERT(was_cancelled == 1);
 
diff --git a/test/core/end2end/tests/retry_server_pushback_delay.cc b/test/core/end2end/tests/retry_server_pushback_delay.cc
index 1da9860..f6a9796 100644
--- a/test/core/end2end/tests/retry_server_pushback_delay.cc
+++ b/test/core/end2end/tests/retry_server_pushback_delay.cc
@@ -150,11 +150,9 @@
   cq_verifier* cqv = cq_verifier_create(f.cq);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/service/method"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/service/method"),
+                               nullptr, deadline, nullptr);
   GPR_ASSERT(c);
 
   peer = grpc_call_get_peer(c);
@@ -286,8 +284,6 @@
   GPR_ASSERT(status == GRPC_STATUS_OK);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(0 == call_details.flags);
   GPR_ASSERT(was_cancelled == 0);
 
diff --git a/test/core/end2end/tests/retry_server_pushback_disabled.cc b/test/core/end2end/tests/retry_server_pushback_disabled.cc
index 13d4f01..1c56476 100644
--- a/test/core/end2end/tests/retry_server_pushback_disabled.cc
+++ b/test/core/end2end/tests/retry_server_pushback_disabled.cc
@@ -151,11 +151,9 @@
   cq_verifier* cqv = cq_verifier_create(f.cq);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/service/method"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/service/method"),
+                               nullptr, deadline, nullptr);
   GPR_ASSERT(c);
 
   peer = grpc_call_get_peer(c);
@@ -274,8 +272,6 @@
   GPR_ASSERT(status == GRPC_STATUS_ABORTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(0 == call_details.flags);
   GPR_ASSERT(was_cancelled == 1);
 
diff --git a/test/core/end2end/tests/retry_streaming.cc b/test/core/end2end/tests/retry_streaming.cc
index e96e57e..d06d124 100644
--- a/test/core/end2end/tests/retry_streaming.cc
+++ b/test/core/end2end/tests/retry_streaming.cc
@@ -158,11 +158,9 @@
   cq_verifier* cqv = cq_verifier_create(f.cq);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/service/method"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/service/method"),
+                               nullptr, deadline, nullptr);
   GPR_ASSERT(c);
 
   peer = grpc_call_get_peer(c);
@@ -383,8 +381,6 @@
   GPR_ASSERT(status == GRPC_STATUS_ABORTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(0 == call_details.flags);
   GPR_ASSERT(was_cancelled == 1);
 
diff --git a/test/core/end2end/tests/retry_streaming_after_commit.cc b/test/core/end2end/tests/retry_streaming_after_commit.cc
index 43eee86..05025d0 100644
--- a/test/core/end2end/tests/retry_streaming_after_commit.cc
+++ b/test/core/end2end/tests/retry_streaming_after_commit.cc
@@ -151,11 +151,9 @@
   cq_verifier* cqv = cq_verifier_create(f.cq);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/service/method"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/service/method"),
+                               nullptr, deadline, nullptr);
   GPR_ASSERT(c);
 
   peer = grpc_call_get_peer(c);
@@ -312,8 +310,6 @@
   GPR_ASSERT(status == GRPC_STATUS_ABORTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(0 == call_details.flags);
   GPR_ASSERT(was_cancelled == 1);
 
diff --git a/test/core/end2end/tests/retry_streaming_succeeds_before_replay_finished.cc b/test/core/end2end/tests/retry_streaming_succeeds_before_replay_finished.cc
index 5c92f64..14460d2 100644
--- a/test/core/end2end/tests/retry_streaming_succeeds_before_replay_finished.cc
+++ b/test/core/end2end/tests/retry_streaming_succeeds_before_replay_finished.cc
@@ -152,11 +152,9 @@
   cq_verifier* cqv = cq_verifier_create(f.cq);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/service/method"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/service/method"),
+                               nullptr, deadline, nullptr);
   GPR_ASSERT(c);
 
   peer = grpc_call_get_peer(c);
@@ -364,8 +362,6 @@
   GPR_ASSERT(status == GRPC_STATUS_ABORTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(0 == call_details.flags);
   GPR_ASSERT(was_cancelled == 1);
 
diff --git a/test/core/end2end/tests/retry_throttled.cc b/test/core/end2end/tests/retry_throttled.cc
index 8cd0848..f5b28de 100644
--- a/test/core/end2end/tests/retry_throttled.cc
+++ b/test/core/end2end/tests/retry_throttled.cc
@@ -151,11 +151,9 @@
   cq_verifier* cqv = cq_verifier_create(f.cq);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/service/method"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/service/method"),
+                               nullptr, deadline, nullptr);
   GPR_ASSERT(c);
 
   peer = grpc_call_get_peer(c);
@@ -232,8 +230,6 @@
   GPR_ASSERT(status == GRPC_STATUS_ABORTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(0 == call_details.flags);
   GPR_ASSERT(was_cancelled == 1);
 
diff --git a/test/core/end2end/tests/retry_too_many_attempts.cc b/test/core/end2end/tests/retry_too_many_attempts.cc
index 5225c9b..2af3267 100644
--- a/test/core/end2end/tests/retry_too_many_attempts.cc
+++ b/test/core/end2end/tests/retry_too_many_attempts.cc
@@ -145,11 +145,9 @@
   cq_verifier* cqv = cq_verifier_create(f.cq);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/service/method"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/service/method"),
+                               nullptr, deadline, nullptr);
   GPR_ASSERT(c);
 
   peer = grpc_call_get_peer(c);
@@ -267,8 +265,6 @@
   GPR_ASSERT(status == GRPC_STATUS_ABORTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/service/method"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(0 == call_details.flags);
   GPR_ASSERT(was_cancelled == 1);
 
diff --git a/test/core/end2end/tests/server_finishes_request.cc b/test/core/end2end/tests/server_finishes_request.cc
index 6fc06cf..c81b309 100644
--- a/test/core/end2end/tests/server_finishes_request.cc
+++ b/test/core/end2end/tests/server_finishes_request.cc
@@ -102,11 +102,9 @@
   int was_cancelled = 2;
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -175,8 +173,6 @@
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 1);
 
   grpc_slice_unref(details);
diff --git a/test/core/end2end/tests/shutdown_finishes_calls.cc b/test/core/end2end/tests/shutdown_finishes_calls.cc
index 28728ef..5dd5bb2 100644
--- a/test/core/end2end/tests/shutdown_finishes_calls.cc
+++ b/test/core/end2end/tests/shutdown_finishes_calls.cc
@@ -92,11 +92,9 @@
   int was_cancelled = 2;
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -172,8 +170,6 @@
   GPR_ASSERT(status == GRPC_STATUS_INTERNAL ||
              status == GRPC_STATUS_UNAVAILABLE);
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 1);
 
   grpc_slice_unref(details);
diff --git a/test/core/end2end/tests/simple_cacheable_request.cc b/test/core/end2end/tests/simple_cacheable_request.cc
index 4ae8398a..be6d16e 100644
--- a/test/core/end2end/tests/simple_cacheable_request.cc
+++ b/test/core/end2end/tests/simple_cacheable_request.cc
@@ -132,11 +132,9 @@
   int was_cancelled = 2;
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -240,8 +238,6 @@
   GPR_ASSERT(status == GRPC_STATUS_OK);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   if (config.feature_mask & FEATURE_MASK_SUPPORTS_REQUEST_PROXYING) {
     // Our simple proxy does not support cacheable requests
   } else {
diff --git a/test/core/end2end/tests/simple_delayed_request.cc b/test/core/end2end/tests/simple_delayed_request.cc
index f8a1ddf..8d11699 100644
--- a/test/core/end2end/tests/simple_delayed_request.cc
+++ b/test/core/end2end/tests/simple_delayed_request.cc
@@ -94,11 +94,9 @@
   config.init_server(f, server_args);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f->client, nullptr, GRPC_PROPAGATE_DEFAULTS, f->cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f->client, nullptr, GRPC_PROPAGATE_DEFAULTS,
+                               f->cq, grpc_slice_from_static_string("/foo"),
+                               nullptr, deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -171,8 +169,6 @@
   GPR_ASSERT(status == GRPC_STATUS_UNIMPLEMENTED);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 1);
 
   grpc_slice_unref(details);
diff --git a/test/core/end2end/tests/simple_metadata.cc b/test/core/end2end/tests/simple_metadata.cc
index 1f39f89..3e476c2 100644
--- a/test/core/end2end/tests/simple_metadata.cc
+++ b/test/core/end2end/tests/simple_metadata.cc
@@ -130,11 +130,9 @@
   int was_cancelled = 2;
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -238,8 +236,6 @@
   GPR_ASSERT(status == GRPC_STATUS_OK);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 0);
   GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world"));
   GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, "hello you"));
diff --git a/test/core/end2end/tests/simple_request.cc b/test/core/end2end/tests/simple_request.cc
index 926e2c7..2d6ccad 100644
--- a/test/core/end2end/tests/simple_request.cc
+++ b/test/core/end2end/tests/simple_request.cc
@@ -111,11 +111,9 @@
   grpc_stats_collect(before);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   peer = grpc_call_get_peer(c);
@@ -212,8 +210,6 @@
   GPR_ASSERT(nullptr != strstr(error_string, "grpc_message"));
   GPR_ASSERT(nullptr != strstr(error_string, "grpc_status"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(0 == call_details.flags);
   GPR_ASSERT(was_cancelled == 1);
 
diff --git a/test/core/end2end/tests/stream_compression_compressed_payload.cc b/test/core/end2end/tests/stream_compression_compressed_payload.cc
index e90d54f..839f091 100644
--- a/test/core/end2end/tests/stream_compression_compressed_payload.cc
+++ b/test/core/end2end/tests/stream_compression_compressed_payload.cc
@@ -137,11 +137,9 @@
   cqv = cq_verifier_create(f.cq);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -239,8 +237,6 @@
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, expected_details));
   gpr_free(expected_details);
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
 
   grpc_slice_unref(details);
   grpc_metadata_array_destroy(&initial_metadata_recv);
@@ -327,11 +323,9 @@
   cqv = cq_verifier_create(f.cq);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -529,8 +523,6 @@
   GPR_ASSERT(status == GRPC_STATUS_OK);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 0);
 
   grpc_slice_unref(details);
diff --git a/test/core/end2end/tests/stream_compression_payload.cc b/test/core/end2end/tests/stream_compression_payload.cc
index 9eace97..4c08150 100644
--- a/test/core/end2end/tests/stream_compression_payload.cc
+++ b/test/core/end2end/tests/stream_compression_payload.cc
@@ -132,11 +132,9 @@
   int was_cancelled = 2;
 
   gpr_timespec deadline = n_seconds_from_now(60);
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -238,8 +236,6 @@
   GPR_ASSERT(status == GRPC_STATUS_OK);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 0);
   GPR_ASSERT(byte_buffer_eq_slice(request_payload_recv, request_payload_slice));
   GPR_ASSERT(
diff --git a/test/core/end2end/tests/stream_compression_ping_pong_streaming.cc b/test/core/end2end/tests/stream_compression_ping_pong_streaming.cc
index 5b03329..f7af59f 100644
--- a/test/core/end2end/tests/stream_compression_ping_pong_streaming.cc
+++ b/test/core/end2end/tests/stream_compression_ping_pong_streaming.cc
@@ -120,11 +120,9 @@
       grpc_slice_from_copied_string("hello you");
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
diff --git a/test/core/end2end/tests/streaming_error_response.cc b/test/core/end2end/tests/streaming_error_response.cc
index 7c7d778..4c357e0 100644
--- a/test/core/end2end/tests/streaming_error_response.cc
+++ b/test/core/end2end/tests/streaming_error_response.cc
@@ -116,11 +116,9 @@
   int was_cancelled = 2;
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -244,8 +242,6 @@
   GPR_ASSERT(status == GRPC_STATUS_FAILED_PRECONDITION);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 1);
 
   grpc_slice_unref(details);
diff --git a/test/core/end2end/tests/trailing_metadata.cc b/test/core/end2end/tests/trailing_metadata.cc
index 2406985..5cf6f2b 100644
--- a/test/core/end2end/tests/trailing_metadata.cc
+++ b/test/core/end2end/tests/trailing_metadata.cc
@@ -138,11 +138,9 @@
   int was_cancelled = 2;
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -247,8 +245,6 @@
   GPR_ASSERT(status == GRPC_STATUS_OK);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(byte_buffer_eq_string(request_payload_recv, "hello world"));
   GPR_ASSERT(byte_buffer_eq_string(response_payload_recv, "hello you"));
   GPR_ASSERT(contains_metadata(&request_metadata_recv, "key1", "val1"));
diff --git a/test/core/end2end/tests/workaround_cronet_compression.cc b/test/core/end2end/tests/workaround_cronet_compression.cc
index 4d4c369..f44ddca 100644
--- a/test/core/end2end/tests/workaround_cronet_compression.cc
+++ b/test/core/end2end/tests/workaround_cronet_compression.cc
@@ -155,11 +155,9 @@
   cqv = cq_verifier_create(f.cq);
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -338,8 +336,6 @@
   GPR_ASSERT(status == GRPC_STATUS_OK);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 0);
 
   grpc_slice_unref(details);
diff --git a/test/core/end2end/tests/write_buffering.cc b/test/core/end2end/tests/write_buffering.cc
index 5d76d23..2f7ee9c 100644
--- a/test/core/end2end/tests/write_buffering.cc
+++ b/test/core/end2end/tests/write_buffering.cc
@@ -111,11 +111,9 @@
   int was_cancelled = 2;
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -255,8 +253,6 @@
   GPR_ASSERT(status == GRPC_STATUS_OK);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 0);
   GPR_ASSERT(byte_buffer_eq_string(request_payload_recv1, "hello world"));
   GPR_ASSERT(byte_buffer_eq_string(request_payload_recv2, "abc123"));
diff --git a/test/core/end2end/tests/write_buffering_at_end.cc b/test/core/end2end/tests/write_buffering_at_end.cc
index bd046ef..886d491 100644
--- a/test/core/end2end/tests/write_buffering_at_end.cc
+++ b/test/core/end2end/tests/write_buffering_at_end.cc
@@ -108,11 +108,9 @@
   int was_cancelled = 2;
 
   gpr_timespec deadline = five_seconds_from_now();
-  c = grpc_channel_create_call(
-      f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
-      grpc_slice_from_static_string("/foo"),
-      get_host_override_slice("foo.test.google.fr:1234", config), deadline,
-      nullptr);
+  c = grpc_channel_create_call(f.client, nullptr, GRPC_PROPAGATE_DEFAULTS, f.cq,
+                               grpc_slice_from_static_string("/foo"), nullptr,
+                               deadline, nullptr);
   GPR_ASSERT(c);
 
   grpc_metadata_array_init(&initial_metadata_recv);
@@ -246,8 +244,6 @@
   GPR_ASSERT(status == GRPC_STATUS_OK);
   GPR_ASSERT(0 == grpc_slice_str_cmp(details, "xyz"));
   GPR_ASSERT(0 == grpc_slice_str_cmp(call_details.method, "/foo"));
-  validate_host_override_string("foo.test.google.fr:1234", call_details.host,
-                                config);
   GPR_ASSERT(was_cancelled == 0);
   GPR_ASSERT(byte_buffer_eq_string(request_payload_recv1, "hello world"));
   GPR_ASSERT(request_payload_recv2 == nullptr);
diff --git a/test/core/gprpp/inlined_vector_test.cc b/test/core/gprpp/inlined_vector_test.cc
index 2a35742..ae34947 100644
--- a/test/core/gprpp/inlined_vector_test.cc
+++ b/test/core/gprpp/inlined_vector_test.cc
@@ -33,6 +33,7 @@
   EXPECT_EQ(static_cast<size_t>(kNumElements), v.size());
   for (int i = 0; i < kNumElements; ++i) {
     EXPECT_EQ(i, v[i]);
+    EXPECT_EQ(i, &v[i] - &v[0]);  // Ensure contiguous allocation.
   }
 }
 
diff --git a/test/core/gprpp/ref_counted_ptr_test.cc b/test/core/gprpp/ref_counted_ptr_test.cc
index 2e398a7..c810345 100644
--- a/test/core/gprpp/ref_counted_ptr_test.cc
+++ b/test/core/gprpp/ref_counted_ptr_test.cc
@@ -88,7 +88,7 @@
 
 TEST(RefCountedPtr, CopyAssignmentToSelf) {
   RefCountedPtr<Foo> foo(New<Foo>());
-  foo = foo;
+  foo = *&foo;  // The "*&" avoids warnings from LLVM -Wself-assign.
 }
 
 TEST(RefCountedPtr, EnclosedScope) {
diff --git a/test/core/handshake/readahead_handshaker_server_ssl.cc b/test/core/handshake/readahead_handshaker_server_ssl.cc
index 9788320..97e9c20 100644
--- a/test/core/handshake/readahead_handshaker_server_ssl.cc
+++ b/test/core/handshake/readahead_handshaker_server_ssl.cc
@@ -64,7 +64,7 @@
 
 const grpc_handshaker_vtable readahead_handshaker_vtable = {
     readahead_handshaker_destroy, readahead_handshaker_shutdown,
-    readahead_handshaker_do_handshake};
+    readahead_handshaker_do_handshake, "read_ahead"};
 
 static grpc_handshaker* readahead_handshaker_create() {
   grpc_handshaker* h =
diff --git a/test/core/iomgr/udp_server_test.cc b/test/core/iomgr/udp_server_test.cc
index 3058e87..d167c01 100644
--- a/test/core/iomgr/udp_server_test.cc
+++ b/test/core/iomgr/udp_server_test.cc
@@ -40,6 +40,7 @@
 #include "src/core/lib/iomgr/ev_posix.h"
 #include "src/core/lib/iomgr/iomgr.h"
 #include "src/core/lib/iomgr/socket_factory_posix.h"
+#include "src/core/lib/iomgr/socket_utils_posix.h"
 #include "test/core/util/test_config.h"
 
 #define LOG_TEST(x) gpr_log(GPR_INFO, "%s", #x)
@@ -55,6 +56,8 @@
 int rcv_buf_size = 1024;
 int snd_buf_size = 1024;
 
+static int g_num_listeners = 1;
+
 class TestGrpcUdpHandler : public GrpcUdpHandler {
  public:
   TestGrpcUdpHandler(grpc_fd* emfd, void* user_data)
@@ -75,6 +78,7 @@
     g_number_of_reads++;
     g_number_of_bytes_read += static_cast<int>(byte_count);
 
+    gpr_log(GPR_DEBUG, "receive %zu on handler %p", byte_count, this);
     GPR_ASSERT(GRPC_LOG_IF_ERROR("pollset_kick",
                                  grpc_pollset_kick(g_pollset, nullptr)));
     gpr_mu_unlock(g_mu);
@@ -213,7 +217,8 @@
   resolved_addr.len = static_cast<socklen_t>(sizeof(struct sockaddr_in));
   addr->sin_family = AF_INET;
   GPR_ASSERT(grpc_udp_server_add_port(s, &resolved_addr, rcv_buf_size,
-                                      snd_buf_size, &handler_factory));
+                                      snd_buf_size, &handler_factory,
+                                      g_num_listeners));
 
   grpc_udp_server_destroy(s, nullptr);
 
@@ -244,9 +249,10 @@
   resolved_addr.len = static_cast<socklen_t>(sizeof(struct sockaddr_in));
   addr->sin_family = AF_INET;
   GPR_ASSERT(grpc_udp_server_add_port(s, &resolved_addr, rcv_buf_size,
-                                      snd_buf_size, &handler_factory));
-  GPR_ASSERT(socket_factory->number_of_socket_calls == 1);
-  GPR_ASSERT(socket_factory->number_of_bind_calls == 1);
+                                      snd_buf_size, &handler_factory,
+                                      g_num_listeners));
+  GPR_ASSERT(socket_factory->number_of_socket_calls == g_num_listeners);
+  GPR_ASSERT(socket_factory->number_of_bind_calls == g_num_listeners);
 
   grpc_udp_server_destroy(s, nullptr);
 
@@ -271,15 +277,16 @@
   resolved_addr.len = static_cast<socklen_t>(sizeof(struct sockaddr_in));
   addr->sin_family = AF_INET;
   GPR_ASSERT(grpc_udp_server_add_port(s, &resolved_addr, rcv_buf_size,
-                                      snd_buf_size, &handler_factory));
+                                      snd_buf_size, &handler_factory,
+                                      g_num_listeners));
 
   grpc_udp_server_start(s, nullptr, 0, nullptr);
-  GPR_ASSERT(g_number_of_starts == 1);
+  GPR_ASSERT(g_number_of_starts == g_num_listeners);
   grpc_udp_server_destroy(s, nullptr);
 
   /* The server had a single FD, which is orphaned exactly once in *
    * grpc_udp_server_destroy. */
-  GPR_ASSERT(g_number_of_orphan_calls == 1);
+  GPR_ASSERT(g_number_of_orphan_calls == g_num_listeners);
   shutdown_and_destroy_pollset();
 }
 
@@ -304,7 +311,8 @@
   resolved_addr.len = static_cast<socklen_t>(sizeof(struct sockaddr_storage));
   addr->ss_family = AF_INET;
   GPR_ASSERT(grpc_udp_server_add_port(s, &resolved_addr, rcv_buf_size,
-                                      snd_buf_size, &handler_factory));
+                                      snd_buf_size, &handler_factory,
+                                      g_num_listeners));
 
   svrfd = grpc_udp_server_get_fd(s, 0);
   GPR_ASSERT(svrfd >= 0);
@@ -347,13 +355,16 @@
 
   /* The server had a single FD, which is orphaned exactly once in *
    * grpc_udp_server_destroy. */
-  GPR_ASSERT(g_number_of_orphan_calls == 1);
+  GPR_ASSERT(g_number_of_orphan_calls == g_num_listeners);
   shutdown_and_destroy_pollset();
 }
 
 int main(int argc, char** argv) {
   grpc_test_init(argc, argv);
   grpc_init();
+  if (grpc_is_socket_reuse_port_supported()) {
+    g_num_listeners = 10;
+  }
   {
     grpc_core::ExecCtx exec_ctx;
     g_pollset = static_cast<grpc_pollset*>(gpr_zalloc(grpc_pollset_size()));
diff --git a/test/core/security/BUILD b/test/core/security/BUILD
index 9db73b9..70bcc8c 100644
--- a/test/core/security/BUILD
+++ b/test/core/security/BUILD
@@ -21,6 +21,18 @@
 load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
 
 grpc_fuzzer(
+    name = "alts_credentials_fuzzer",
+    srcs = ["alts_credentials_fuzzer.cc"],
+    language = "C++",
+    corpus = "corpus/alts_credentials_corpus",
+    deps = [
+        "//:gpr",
+        "//:grpc",
+        "//test/core/util:grpc_test_util",
+    ],
+)
+
+grpc_fuzzer(
     name = "ssl_server_fuzzer",
     srcs = ["ssl_server_fuzzer.cc"],
     language = "C++",
diff --git a/test/core/security/alts_credentials_fuzzer.cc b/test/core/security/alts_credentials_fuzzer.cc
new file mode 100644
index 0000000..bf18f0a
--- /dev/null
+++ b/test/core/security/alts_credentials_fuzzer.cc
@@ -0,0 +1,120 @@
+/*
+ *
+ * Copyright 2018 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.
+ *
+ */
+
+#include <string.h>
+
+#include <grpc/grpc.h>
+#include <grpc/grpc_security.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+#include "test/core/util/fuzzer_util.h"
+#include "test/core/util/memory_counters.h"
+
+#include "src/core/lib/gpr/env.h"
+#include "src/core/lib/security/credentials/alts/alts_credentials.h"
+#include "src/core/lib/security/credentials/alts/check_gcp_environment.h"
+#include "src/core/lib/security/credentials/alts/grpc_alts_credentials_options.h"
+
+using grpc_core::testing::grpc_fuzzer_get_next_byte;
+using grpc_core::testing::grpc_fuzzer_get_next_string;
+using grpc_core::testing::input_stream;
+
+// Logging
+bool squelch = true;
+bool leak_check = true;
+
+static void dont_log(gpr_log_func_args* args) {}
+
+// Add a random number of target service accounts to client options.
+static void read_target_service_accounts(
+    input_stream* inp, grpc_alts_credentials_options* options) {
+  size_t n = grpc_fuzzer_get_next_byte(inp);
+  for (size_t i = 0; i < n; i++) {
+    char* service_account = grpc_fuzzer_get_next_string(inp, nullptr);
+    if (service_account != nullptr) {
+      grpc_alts_credentials_client_options_add_target_service_account(
+          options, service_account);
+      gpr_free(service_account);
+    }
+  }
+  // Added to improve code coverage.
+  grpc_alts_credentials_client_options_add_target_service_account(options,
+                                                                  nullptr);
+  grpc_alts_credentials_client_options_add_target_service_account(
+      nullptr, "this is service account");
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+  char* grpc_trace_fuzzer = gpr_getenv("GRPC_TRACE_FUZZER");
+  if (squelch && grpc_trace_fuzzer == nullptr) {
+    gpr_set_log_function(dont_log);
+  }
+  gpr_free(grpc_trace_fuzzer);
+  struct grpc_memory_counters counters;
+  if (leak_check) {
+    grpc_memory_counters_init();
+  }
+  input_stream inp = {data, data + size};
+  grpc_init();
+  bool is_on_gcp = grpc_alts_is_running_on_gcp();
+  while (inp.cur != inp.end) {
+    bool enable_untrusted_alts = grpc_fuzzer_get_next_byte(&inp) & 0x01;
+    char* handshaker_service_url =
+        grpc_fuzzer_get_next_byte(&inp) & 0x01
+            ? grpc_fuzzer_get_next_string(&inp, nullptr)
+            : nullptr;
+    if (grpc_fuzzer_get_next_byte(&inp) & 0x01) {
+      // Test ALTS channel credentials.
+      grpc_alts_credentials_options* options =
+          grpc_alts_credentials_client_options_create();
+      read_target_service_accounts(&inp, options);
+      grpc_channel_credentials* cred = grpc_alts_credentials_create_customized(
+          options, handshaker_service_url, enable_untrusted_alts);
+      if (!enable_untrusted_alts && !is_on_gcp) {
+        GPR_ASSERT(cred == nullptr);
+      } else {
+        GPR_ASSERT(cred != nullptr);
+      }
+      grpc_channel_credentials_release(cred);
+      grpc_alts_credentials_options_destroy(options);
+    } else {
+      // Test ALTS server credentials.
+      grpc_alts_credentials_options* options =
+          grpc_alts_credentials_server_options_create();
+      grpc_server_credentials* cred =
+          grpc_alts_server_credentials_create_customized(
+              options, handshaker_service_url, enable_untrusted_alts);
+      if (!enable_untrusted_alts && !is_on_gcp) {
+        GPR_ASSERT(cred == nullptr);
+      } else {
+        GPR_ASSERT(cred != nullptr);
+      }
+      grpc_server_credentials_release(cred);
+      grpc_alts_credentials_options_destroy(options);
+    }
+    gpr_free(handshaker_service_url);
+  }
+  grpc_shutdown();
+  if (leak_check) {
+    counters = grpc_memory_counters_snapshot();
+    grpc_memory_counters_destroy();
+    GPR_ASSERT(counters.total_size_relative == 0);
+  }
+  return 0;
+}
diff --git a/test/core/security/corpus/alts_credentials_corpus/0149b46b88d583e05be0fb1423d10f2a14d36c48 b/test/core/security/corpus/alts_credentials_corpus/0149b46b88d583e05be0fb1423d10f2a14d36c48
new file mode 100644
index 0000000..c062c7f
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/0149b46b88d583e05be0fb1423d10f2a14d36c48
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/047fc351e73f760d329d5a8845944720be9ce773 b/test/core/security/corpus/alts_credentials_corpus/047fc351e73f760d329d5a8845944720be9ce773
new file mode 100644
index 0000000..d943cfe
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/047fc351e73f760d329d5a8845944720be9ce773
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/04ef96c66d8222d1a2c07e6b2a6548e6a527042b b/test/core/security/corpus/alts_credentials_corpus/04ef96c66d8222d1a2c07e6b2a6548e6a527042b
new file mode 100644
index 0000000..e7346f3
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/04ef96c66d8222d1a2c07e6b2a6548e6a527042b
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/05a7e16c1d7f92111f43e9c777421879920e79a4 b/test/core/security/corpus/alts_credentials_corpus/05a7e16c1d7f92111f43e9c777421879920e79a4
new file mode 100644
index 0000000..43b8b47
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/05a7e16c1d7f92111f43e9c777421879920e79a4
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/063eb46f202fdfe7935c30ca38d7eb81c82db419 b/test/core/security/corpus/alts_credentials_corpus/063eb46f202fdfe7935c30ca38d7eb81c82db419
new file mode 100644
index 0000000..5b30f12
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/063eb46f202fdfe7935c30ca38d7eb81c82db419
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/064773597c295fa871c184fc12d17b6de8aab31b b/test/core/security/corpus/alts_credentials_corpus/064773597c295fa871c184fc12d17b6de8aab31b
new file mode 100644
index 0000000..758709b
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/064773597c295fa871c184fc12d17b6de8aab31b
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/087449740758b114d16790067707934479946bd6 b/test/core/security/corpus/alts_credentials_corpus/087449740758b114d16790067707934479946bd6
new file mode 100644
index 0000000..099636f
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/087449740758b114d16790067707934479946bd6
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/0a5d068feb57a2782c6eba57b637abe8668ac82f b/test/core/security/corpus/alts_credentials_corpus/0a5d068feb57a2782c6eba57b637abe8668ac82f
new file mode 100644
index 0000000..fd7d7c8
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/0a5d068feb57a2782c6eba57b637abe8668ac82f
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/0b81e6d89bf7df80e87e5ee7c49f7cc1431f77e8 b/test/core/security/corpus/alts_credentials_corpus/0b81e6d89bf7df80e87e5ee7c49f7cc1431f77e8
new file mode 100644
index 0000000..a40664b
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/0b81e6d89bf7df80e87e5ee7c49f7cc1431f77e8
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/11409339cec708a5e353893101bfe76364337d5c b/test/core/security/corpus/alts_credentials_corpus/11409339cec708a5e353893101bfe76364337d5c
new file mode 100644
index 0000000..c8b350d
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/11409339cec708a5e353893101bfe76364337d5c
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/147696a264cd6f197adb7c68aff834c30b1b77f8 b/test/core/security/corpus/alts_credentials_corpus/147696a264cd6f197adb7c68aff834c30b1b77f8
new file mode 100644
index 0000000..5f68d8a
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/147696a264cd6f197adb7c68aff834c30b1b77f8
@@ -0,0 +1 @@
+ø+ú
\ No newline at end of file
diff --git a/test/core/security/corpus/alts_credentials_corpus/160e5cac38c5c9e919ed6e4fbafee76907d63044 b/test/core/security/corpus/alts_credentials_corpus/160e5cac38c5c9e919ed6e4fbafee76907d63044
new file mode 100644
index 0000000..c11ad66
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/160e5cac38c5c9e919ed6e4fbafee76907d63044
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/173d02167db431040b0540d98f6fc5e8b456587d b/test/core/security/corpus/alts_credentials_corpus/173d02167db431040b0540d98f6fc5e8b456587d
new file mode 100644
index 0000000..662cc9b
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/173d02167db431040b0540d98f6fc5e8b456587d
@@ -0,0 +1 @@
+òÒÒ
\ No newline at end of file
diff --git a/test/core/security/corpus/alts_credentials_corpus/18a3fe239806b3c7d1af24bcd2bd23aeeb072d5c b/test/core/security/corpus/alts_credentials_corpus/18a3fe239806b3c7d1af24bcd2bd23aeeb072d5c
new file mode 100644
index 0000000..9239e10
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/18a3fe239806b3c7d1af24bcd2bd23aeeb072d5c
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/195abd83b2e9d32b1b5b854fe33da44b6db40880 b/test/core/security/corpus/alts_credentials_corpus/195abd83b2e9d32b1b5b854fe33da44b6db40880
new file mode 100644
index 0000000..db7815e
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/195abd83b2e9d32b1b5b854fe33da44b6db40880
@@ -0,0 +1 @@
+apÿì~!õìA~;ì
\ No newline at end of file
diff --git a/test/core/security/corpus/alts_credentials_corpus/19af2509c7d84334b9ec64de4767a07d5294fd72 b/test/core/security/corpus/alts_credentials_corpus/19af2509c7d84334b9ec64de4767a07d5294fd72
new file mode 100644
index 0000000..b87c814
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/19af2509c7d84334b9ec64de4767a07d5294fd72
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/1b9864b948fcf08b062fd4401ef55b214c259535 b/test/core/security/corpus/alts_credentials_corpus/1b9864b948fcf08b062fd4401ef55b214c259535
new file mode 100644
index 0000000..8cb97c5
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/1b9864b948fcf08b062fd4401ef55b214c259535
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/1edddfa67de854d7faaba41418fda845e9c6a89d b/test/core/security/corpus/alts_credentials_corpus/1edddfa67de854d7faaba41418fda845e9c6a89d
new file mode 100644
index 0000000..035f07c
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/1edddfa67de854d7faaba41418fda845e9c6a89d
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/20031bb00e6608e1b570aa96e6afb9de06d42167 b/test/core/security/corpus/alts_credentials_corpus/20031bb00e6608e1b570aa96e6afb9de06d42167
new file mode 100644
index 0000000..27753df
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/20031bb00e6608e1b570aa96e6afb9de06d42167
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/22b4c7ce7db99b0df63c9eae9265de484b695922 b/test/core/security/corpus/alts_credentials_corpus/22b4c7ce7db99b0df63c9eae9265de484b695922
new file mode 100644
index 0000000..ab8f18d
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/22b4c7ce7db99b0df63c9eae9265de484b695922
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/27416437ad287bd3cc1c5efdecebc39f20df73c1 b/test/core/security/corpus/alts_credentials_corpus/27416437ad287bd3cc1c5efdecebc39f20df73c1
new file mode 100644
index 0000000..c400e3e
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/27416437ad287bd3cc1c5efdecebc39f20df73c1
@@ -0,0 +1 @@
+Ä=ļyyyyy‡†yyyyz
\ No newline at end of file
diff --git a/test/core/security/corpus/alts_credentials_corpus/27e8cd785c2b9346f68dba75761b52fbabaf2b72 b/test/core/security/corpus/alts_credentials_corpus/27e8cd785c2b9346f68dba75761b52fbabaf2b72
new file mode 100644
index 0000000..746dee9
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/27e8cd785c2b9346f68dba75761b52fbabaf2b72
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/28236f860d3d8e5ea11176746cb4c1c5c4f1f6c0 b/test/core/security/corpus/alts_credentials_corpus/28236f860d3d8e5ea11176746cb4c1c5c4f1f6c0
new file mode 100644
index 0000000..982c97b
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/28236f860d3d8e5ea11176746cb4c1c5c4f1f6c0
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/29e15b492c5a409938092a30c003c5c34df7e283 b/test/core/security/corpus/alts_credentials_corpus/29e15b492c5a409938092a30c003c5c34df7e283
new file mode 100644
index 0000000..c3e5b25
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/29e15b492c5a409938092a30c003c5c34df7e283
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/2a47864d77749aa042b772895dbdf46f608ccc6d b/test/core/security/corpus/alts_credentials_corpus/2a47864d77749aa042b772895dbdf46f608ccc6d
new file mode 100644
index 0000000..141d94d
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/2a47864d77749aa042b772895dbdf46f608ccc6d
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/2cca5cb1b135c35f6e5e1ec4c37deb9e12d37dc0 b/test/core/security/corpus/alts_credentials_corpus/2cca5cb1b135c35f6e5e1ec4c37deb9e12d37dc0
new file mode 100644
index 0000000..a956708
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/2cca5cb1b135c35f6e5e1ec4c37deb9e12d37dc0
@@ -0,0 +1,2 @@

+ïï
\ No newline at end of file
diff --git a/test/core/security/corpus/alts_credentials_corpus/2df27b6c42dbaee382a29a87338d64ee87354acb b/test/core/security/corpus/alts_credentials_corpus/2df27b6c42dbaee382a29a87338d64ee87354acb
new file mode 100644
index 0000000..a35f0e8
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/2df27b6c42dbaee382a29a87338d64ee87354acb
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/2e9ddd1339d8e599cef658a08965985c4f45e428 b/test/core/security/corpus/alts_credentials_corpus/2e9ddd1339d8e599cef658a08965985c4f45e428
new file mode 100644
index 0000000..17c98e7
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/2e9ddd1339d8e599cef658a08965985c4f45e428
@@ -0,0 +1,2 @@

+ïe
\ No newline at end of file
diff --git a/test/core/security/corpus/alts_credentials_corpus/31a2d12a84a7a56ace831a9668d6ab4847390679 b/test/core/security/corpus/alts_credentials_corpus/31a2d12a84a7a56ace831a9668d6ab4847390679
new file mode 100644
index 0000000..745dc42
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/31a2d12a84a7a56ace831a9668d6ab4847390679
@@ -0,0 +1,2 @@

+ïé
\ No newline at end of file
diff --git a/test/core/security/corpus/alts_credentials_corpus/33cb9ec0ce3538ed6079b5fcb127649a5d05955b b/test/core/security/corpus/alts_credentials_corpus/33cb9ec0ce3538ed6079b5fcb127649a5d05955b
new file mode 100644
index 0000000..2931764
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/33cb9ec0ce3538ed6079b5fcb127649a5d05955b
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/348d9ae6eebb2e1644addf7f07231d108cf6f3b8 b/test/core/security/corpus/alts_credentials_corpus/348d9ae6eebb2e1644addf7f07231d108cf6f3b8
new file mode 100644
index 0000000..02326f0
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/348d9ae6eebb2e1644addf7f07231d108cf6f3b8
@@ -0,0 +1 @@
+òÒä
\ No newline at end of file
diff --git a/test/core/security/corpus/alts_credentials_corpus/359f76f3c802292e92b0640de2bfe051e780a3b6 b/test/core/security/corpus/alts_credentials_corpus/359f76f3c802292e92b0640de2bfe051e780a3b6
new file mode 100644
index 0000000..f31c54b
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/359f76f3c802292e92b0640de2bfe051e780a3b6
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/35a479988e965a6e3e75138b64b0bd1f45073e2f b/test/core/security/corpus/alts_credentials_corpus/35a479988e965a6e3e75138b64b0bd1f45073e2f
new file mode 100644
index 0000000..4e44bcc
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/35a479988e965a6e3e75138b64b0bd1f45073e2f
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/362b00d713686ff70cb0199f3d7d0058e5a1a27a b/test/core/security/corpus/alts_credentials_corpus/362b00d713686ff70cb0199f3d7d0058e5a1a27a
new file mode 100644
index 0000000..3e22fca
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/362b00d713686ff70cb0199f3d7d0058e5a1a27a
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/3849c1625071791ceae709b9c6c705b28d099d67 b/test/core/security/corpus/alts_credentials_corpus/3849c1625071791ceae709b9c6c705b28d099d67
new file mode 100644
index 0000000..5bc905d
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/3849c1625071791ceae709b9c6c705b28d099d67
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/39ef03c66ee2d4bcfb6c8da50486dcd40f02fb12 b/test/core/security/corpus/alts_credentials_corpus/39ef03c66ee2d4bcfb6c8da50486dcd40f02fb12
new file mode 100644
index 0000000..467004c
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/39ef03c66ee2d4bcfb6c8da50486dcd40f02fb12
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/3a3ca061863499ebc171a4f910fa1b49523baad4 b/test/core/security/corpus/alts_credentials_corpus/3a3ca061863499ebc171a4f910fa1b49523baad4
new file mode 100644
index 0000000..97f09bf
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/3a3ca061863499ebc171a4f910fa1b49523baad4
@@ -0,0 +1 @@
+úÒû9
\ No newline at end of file
diff --git a/test/core/security/corpus/alts_credentials_corpus/3a890f3fd01b048ac9db65a9a9b4f4443268b91a b/test/core/security/corpus/alts_credentials_corpus/3a890f3fd01b048ac9db65a9a9b4f4443268b91a
new file mode 100644
index 0000000..97b05e8
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/3a890f3fd01b048ac9db65a9a9b4f4443268b91a
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/3b9554038a425bd1fae057ba41f9366bb467e946 b/test/core/security/corpus/alts_credentials_corpus/3b9554038a425bd1fae057ba41f9366bb467e946
new file mode 100644
index 0000000..d0ef634
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/3b9554038a425bd1fae057ba41f9366bb467e946
@@ -0,0 +1 @@
+„ÜðððððððððððððððððððððððððððÔððððòððððððÔÜÜÜ
\ No newline at end of file
diff --git a/test/core/security/corpus/alts_credentials_corpus/3ce0ae4aa226f205a3a4e66bbb253419d9d754bf b/test/core/security/corpus/alts_credentials_corpus/3ce0ae4aa226f205a3a4e66bbb253419d9d754bf
new file mode 100644
index 0000000..08e6df0
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/3ce0ae4aa226f205a3a4e66bbb253419d9d754bf
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/3dccc5523986c37e27684659bba8a1037e7a92e8 b/test/core/security/corpus/alts_credentials_corpus/3dccc5523986c37e27684659bba8a1037e7a92e8
new file mode 100644
index 0000000..09b735e
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/3dccc5523986c37e27684659bba8a1037e7a92e8
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/3e0908c15b1cede4541d25f388b1345e8641e221 b/test/core/security/corpus/alts_credentials_corpus/3e0908c15b1cede4541d25f388b1345e8641e221
new file mode 100644
index 0000000..eabd458
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/3e0908c15b1cede4541d25f388b1345e8641e221
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/3fcb181ff6a8c8e2ba38ed34cf78f7482eb55cb7 b/test/core/security/corpus/alts_credentials_corpus/3fcb181ff6a8c8e2ba38ed34cf78f7482eb55cb7
new file mode 100644
index 0000000..bbef93b
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/3fcb181ff6a8c8e2ba38ed34cf78f7482eb55cb7
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/41c9b5f720eb8f8fa04c840375a881781a849b43 b/test/core/security/corpus/alts_credentials_corpus/41c9b5f720eb8f8fa04c840375a881781a849b43
new file mode 100644
index 0000000..d611c73
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/41c9b5f720eb8f8fa04c840375a881781a849b43
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/4257a018f08f13a3a9adc848ef808e1be50bc4cf b/test/core/security/corpus/alts_credentials_corpus/4257a018f08f13a3a9adc848ef808e1be50bc4cf
new file mode 100644
index 0000000..607c971
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/4257a018f08f13a3a9adc848ef808e1be50bc4cf
@@ -0,0 +1,2 @@
+òÓ99999999999999999999999999999999999¬¬¬¬¬¬¬¬¬ÿÿÿÿÿÿÿÿÿÿÿÿÿ/////ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
+ÿÿÿÿÿÿÿÿÿÿ²²²²²²²ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿNSt6locale5
\ No newline at end of file
diff --git a/test/core/security/corpus/alts_credentials_corpus/42dfc5c4d13261b7259e65cd692df9c9d607194e b/test/core/security/corpus/alts_credentials_corpus/42dfc5c4d13261b7259e65cd692df9c9d607194e
new file mode 100644
index 0000000..48ffa85
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/42dfc5c4d13261b7259e65cd692df9c9d607194e
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/43144664aedb585d45d42aa5249ddbfe81afe470 b/test/core/security/corpus/alts_credentials_corpus/43144664aedb585d45d42aa5249ddbfe81afe470
new file mode 100644
index 0000000..fee2672
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/43144664aedb585d45d42aa5249ddbfe81afe470
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/43e5ad495a47593b17dbcbd3e70c2e25a417bb6e b/test/core/security/corpus/alts_credentials_corpus/43e5ad495a47593b17dbcbd3e70c2e25a417bb6e
new file mode 100644
index 0000000..32ffc96
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/43e5ad495a47593b17dbcbd3e70c2e25a417bb6e
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/446614e45b7bef49118b17e031c48faf167ebe3e b/test/core/security/corpus/alts_credentials_corpus/446614e45b7bef49118b17e031c48faf167ebe3e
new file mode 100644
index 0000000..849aadf
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/446614e45b7bef49118b17e031c48faf167ebe3e
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/46492477fa84ca88e85df914801af0b09b0939f6 b/test/core/security/corpus/alts_credentials_corpus/46492477fa84ca88e85df914801af0b09b0939f6
new file mode 100644
index 0000000..98885bc
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/46492477fa84ca88e85df914801af0b09b0939f6
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/47157f83b166b57e0052c98a65c6db864fa6cb9b b/test/core/security/corpus/alts_credentials_corpus/47157f83b166b57e0052c98a65c6db864fa6cb9b
new file mode 100644
index 0000000..fad1e0f
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/47157f83b166b57e0052c98a65c6db864fa6cb9b
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/473fc9b6d768a925527d3ad805ca363d490dc741 b/test/core/security/corpus/alts_credentials_corpus/473fc9b6d768a925527d3ad805ca363d490dc741
new file mode 100644
index 0000000..1775a17
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/473fc9b6d768a925527d3ad805ca363d490dc741
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/483c0b4015100eee00f6b23d1100d8c4953dd3b1 b/test/core/security/corpus/alts_credentials_corpus/483c0b4015100eee00f6b23d1100d8c4953dd3b1
new file mode 100644
index 0000000..2d52687
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/483c0b4015100eee00f6b23d1100d8c4953dd3b1
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/48be2dc4cdc5462407b319caa855d976cda88153 b/test/core/security/corpus/alts_credentials_corpus/48be2dc4cdc5462407b319caa855d976cda88153
new file mode 100644
index 0000000..c1c2cd9
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/48be2dc4cdc5462407b319caa855d976cda88153
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/4e84eb54a0e438052b0c2e83653135042d9eb59a b/test/core/security/corpus/alts_credentials_corpus/4e84eb54a0e438052b0c2e83653135042d9eb59a
new file mode 100644
index 0000000..66b525f
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/4e84eb54a0e438052b0c2e83653135042d9eb59a
@@ -0,0 +1 @@
+òÒ
\ No newline at end of file
diff --git a/test/core/security/corpus/alts_credentials_corpus/50839d5c8bf33f0970986dcc4b73b024f11a95b7 b/test/core/security/corpus/alts_credentials_corpus/50839d5c8bf33f0970986dcc4b73b024f11a95b7
new file mode 100644
index 0000000..9673f73
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/50839d5c8bf33f0970986dcc4b73b024f11a95b7
@@ -0,0 +1 @@
+òÿt_Ó	ÿÿÿÿÿæææ&ææææææææææææææææææææææÿÿÿÿÿÿÿÿÿÿûÿÿÿÿÿÿÿÜ
\ No newline at end of file
diff --git a/test/core/security/corpus/alts_credentials_corpus/523d964986d8ad966ae07e540a608681098813f9 b/test/core/security/corpus/alts_credentials_corpus/523d964986d8ad966ae07e540a608681098813f9
new file mode 100644
index 0000000..06e05df
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/523d964986d8ad966ae07e540a608681098813f9
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/5410b8190c95dacd36d6e6ec75b7538a630e08de b/test/core/security/corpus/alts_credentials_corpus/5410b8190c95dacd36d6e6ec75b7538a630e08de
new file mode 100644
index 0000000..4579c6f
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/5410b8190c95dacd36d6e6ec75b7538a630e08de
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/549b2891ac79f504a7c9ea00f6d7527c34ce04e6 b/test/core/security/corpus/alts_credentials_corpus/549b2891ac79f504a7c9ea00f6d7527c34ce04e6
new file mode 100644
index 0000000..6f1a9ed
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/549b2891ac79f504a7c9ea00f6d7527c34ce04e6
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/55321649e7b7f1b5664ae20724e683c930643fc4 b/test/core/security/corpus/alts_credentials_corpus/55321649e7b7f1b5664ae20724e683c930643fc4
new file mode 100644
index 0000000..e38fd28
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/55321649e7b7f1b5664ae20724e683c930643fc4
@@ -0,0 +1 @@
+ò)Ò
\ No newline at end of file
diff --git a/test/core/security/corpus/alts_credentials_corpus/55cc52f25865baee3e6e52c3110a9723caa2b3cb b/test/core/security/corpus/alts_credentials_corpus/55cc52f25865baee3e6e52c3110a9723caa2b3cb
new file mode 100644
index 0000000..aae2fe5
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/55cc52f25865baee3e6e52c3110a9723caa2b3cb
@@ -0,0 +1 @@
+òÒÎ
\ No newline at end of file
diff --git a/test/core/security/corpus/alts_credentials_corpus/56c22410e3295ad03aa31552ab888f581756cc17 b/test/core/security/corpus/alts_credentials_corpus/56c22410e3295ad03aa31552ab888f581756cc17
new file mode 100644
index 0000000..e5d7cf9
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/56c22410e3295ad03aa31552ab888f581756cc17
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/5724a705b62a7548ba2df1abe4ef0c970c4e1bd2 b/test/core/security/corpus/alts_credentials_corpus/5724a705b62a7548ba2df1abe4ef0c970c4e1bd2
new file mode 100644
index 0000000..b0875c9
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/5724a705b62a7548ba2df1abe4ef0c970c4e1bd2
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/576a148c107d56861d1611641a6f7c7921061c5c b/test/core/security/corpus/alts_credentials_corpus/576a148c107d56861d1611641a6f7c7921061c5c
new file mode 100644
index 0000000..6d91b58
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/576a148c107d56861d1611641a6f7c7921061c5c
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/5a6b8263e8939f851cf5b1e347a33d97253b7b3d b/test/core/security/corpus/alts_credentials_corpus/5a6b8263e8939f851cf5b1e347a33d97253b7b3d
new file mode 100644
index 0000000..add56ca
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/5a6b8263e8939f851cf5b1e347a33d97253b7b3d
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/5ba93c9db0cff93f52b521d7420e43f6eda2784f b/test/core/security/corpus/alts_credentials_corpus/5ba93c9db0cff93f52b521d7420e43f6eda2784f
new file mode 100644
index 0000000..f76dd23
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/5ba93c9db0cff93f52b521d7420e43f6eda2784f
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/5bd02a339fd7705449388580c75bfcc597aba954 b/test/core/security/corpus/alts_credentials_corpus/5bd02a339fd7705449388580c75bfcc597aba954
new file mode 100644
index 0000000..f450932
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/5bd02a339fd7705449388580c75bfcc597aba954
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/5bd6fb6fc4163bf3a9db6ddaf509dce8df8a5000 b/test/core/security/corpus/alts_credentials_corpus/5bd6fb6fc4163bf3a9db6ddaf509dce8df8a5000
new file mode 100644
index 0000000..aea3da6
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/5bd6fb6fc4163bf3a9db6ddaf509dce8df8a5000
@@ -0,0 +1 @@
+)applea.ÿÿÿÿ„ÜÜ.ÿßÿÿÿÿÿÜÿÿÿÜÿÿ„ÜÜ.
\ No newline at end of file
diff --git a/test/core/security/corpus/alts_credentials_corpus/5d06fc38005503af3d084721c60e574fb9d2f370 b/test/core/security/corpus/alts_credentials_corpus/5d06fc38005503af3d084721c60e574fb9d2f370
new file mode 100644
index 0000000..42eb673
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/5d06fc38005503af3d084721c60e574fb9d2f370
@@ -0,0 +1 @@
+ÓÓ×
\ No newline at end of file
diff --git a/test/core/security/corpus/alts_credentials_corpus/5ddc10489ff3269bdaa3051b70fb7af455ee1104 b/test/core/security/corpus/alts_credentials_corpus/5ddc10489ff3269bdaa3051b70fb7af455ee1104
new file mode 100644
index 0000000..79db88a
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/5ddc10489ff3269bdaa3051b70fb7af455ee1104
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/5ea9d515f0d10b04f1356b9463139bfe121a6e4a b/test/core/security/corpus/alts_credentials_corpus/5ea9d515f0d10b04f1356b9463139bfe121a6e4a
new file mode 100644
index 0000000..7efb47e
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/5ea9d515f0d10b04f1356b9463139bfe121a6e4a
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/61c449793347cf2e1ed0c38d54d23c63dfaabeb8 b/test/core/security/corpus/alts_credentials_corpus/61c449793347cf2e1ed0c38d54d23c63dfaabeb8
new file mode 100644
index 0000000..96031be
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/61c449793347cf2e1ed0c38d54d23c63dfaabeb8
@@ -0,0 +1 @@
+òÿÿÿÿÿÿÿÿÿÿÿÿÿÿÝÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
\ No newline at end of file
diff --git a/test/core/security/corpus/alts_credentials_corpus/6287389c373e9788dcc04f9747b4be1fd1ef3028 b/test/core/security/corpus/alts_credentials_corpus/6287389c373e9788dcc04f9747b4be1fd1ef3028
new file mode 100644
index 0000000..799bd0e
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/6287389c373e9788dcc04f9747b4be1fd1ef3028
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/64d4de4d5aafab7ec388a7fe83066c1a4d1d9d68 b/test/core/security/corpus/alts_credentials_corpus/64d4de4d5aafab7ec388a7fe83066c1a4d1d9d68
new file mode 100644
index 0000000..2e91965
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/64d4de4d5aafab7ec388a7fe83066c1a4d1d9d68
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/651c37806d2ac579dcfc97643c3c1ea74dbb8774 b/test/core/security/corpus/alts_credentials_corpus/651c37806d2ac579dcfc97643c3c1ea74dbb8774
new file mode 100644
index 0000000..618e514
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/651c37806d2ac579dcfc97643c3c1ea74dbb8774
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/6551d02d20573cfa2944ec1f12b0c01f264a1326 b/test/core/security/corpus/alts_credentials_corpus/6551d02d20573cfa2944ec1f12b0c01f264a1326
new file mode 100644
index 0000000..98056c0
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/6551d02d20573cfa2944ec1f12b0c01f264a1326
@@ -0,0 +1 @@
+‚s
\ No newline at end of file
diff --git a/test/core/security/corpus/alts_credentials_corpus/65f029414ee10e45ff4b9f305f7b472364cea538 b/test/core/security/corpus/alts_credentials_corpus/65f029414ee10e45ff4b9f305f7b472364cea538
new file mode 100644
index 0000000..1c3a1a0
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/65f029414ee10e45ff4b9f305f7b472364cea538
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/68b75a17fe2db060df3e61a597650ba99079abbf b/test/core/security/corpus/alts_credentials_corpus/68b75a17fe2db060df3e61a597650ba99079abbf
new file mode 100644
index 0000000..327dd39
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/68b75a17fe2db060df3e61a597650ba99079abbf
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/69e80594dbc5c4c648e39883a650b1760f20ab63 b/test/core/security/corpus/alts_credentials_corpus/69e80594dbc5c4c648e39883a650b1760f20ab63
new file mode 100644
index 0000000..740b987
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/69e80594dbc5c4c648e39883a650b1760f20ab63
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/6cb47d0e640b4c41e32f13c0d64ee46eae1b80b5 b/test/core/security/corpus/alts_credentials_corpus/6cb47d0e640b4c41e32f13c0d64ee46eae1b80b5
new file mode 100644
index 0000000..b22a010
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/6cb47d0e640b4c41e32f13c0d64ee46eae1b80b5
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/6da5fe063432cb9094c7c083efdbbe5ba4246d18 b/test/core/security/corpus/alts_credentials_corpus/6da5fe063432cb9094c7c083efdbbe5ba4246d18
new file mode 100644
index 0000000..993620e
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/6da5fe063432cb9094c7c083efdbbe5ba4246d18
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/6dd140da774d85f272fb587dc1b2a85d881a7c21 b/test/core/security/corpus/alts_credentials_corpus/6dd140da774d85f272fb587dc1b2a85d881a7c21
new file mode 100644
index 0000000..d838739
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/6dd140da774d85f272fb587dc1b2a85d881a7c21
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/6ddab273597d73be49e2307d68e00fa18bba4765 b/test/core/security/corpus/alts_credentials_corpus/6ddab273597d73be49e2307d68e00fa18bba4765
new file mode 100644
index 0000000..3e74467
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/6ddab273597d73be49e2307d68e00fa18bba4765
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/6eaf85d84fbf47ea0619d0dba8d366f4e3ff0be6 b/test/core/security/corpus/alts_credentials_corpus/6eaf85d84fbf47ea0619d0dba8d366f4e3ff0be6
new file mode 100644
index 0000000..42cddf7
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/6eaf85d84fbf47ea0619d0dba8d366f4e3ff0be6
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/6f751cc09af8113f6ecd491b1830bd8454c4738d b/test/core/security/corpus/alts_credentials_corpus/6f751cc09af8113f6ecd491b1830bd8454c4738d
new file mode 100644
index 0000000..a51a3d0
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/6f751cc09af8113f6ecd491b1830bd8454c4738d
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/70d9eb29a70d483d07e2faca6b00098af78d1fff b/test/core/security/corpus/alts_credentials_corpus/70d9eb29a70d483d07e2faca6b00098af78d1fff
new file mode 100644
index 0000000..e9fb9b9
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/70d9eb29a70d483d07e2faca6b00098af78d1fff
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/7192effa1058382b379fb7b87f1acad5ac554d05 b/test/core/security/corpus/alts_credentials_corpus/7192effa1058382b379fb7b87f1acad5ac554d05
new file mode 100644
index 0000000..23a3819
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/7192effa1058382b379fb7b87f1acad5ac554d05
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/730e85d6a62e70cb6721009b903782ade4ff73a2 b/test/core/security/corpus/alts_credentials_corpus/730e85d6a62e70cb6721009b903782ade4ff73a2
new file mode 100644
index 0000000..9c1e71c
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/730e85d6a62e70cb6721009b903782ade4ff73a2
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/74002471a854059cb29de7cad8f9fb7adc3c5ec2 b/test/core/security/corpus/alts_credentials_corpus/74002471a854059cb29de7cad8f9fb7adc3c5ec2
new file mode 100644
index 0000000..bb83231
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/74002471a854059cb29de7cad8f9fb7adc3c5ec2
@@ -0,0 +1,2 @@
+
+¡Š
\ No newline at end of file
diff --git a/test/core/security/corpus/alts_credentials_corpus/747f2330cd1fc4a06d54b376a9a6528d0364f0ac b/test/core/security/corpus/alts_credentials_corpus/747f2330cd1fc4a06d54b376a9a6528d0364f0ac
new file mode 100644
index 0000000..332ac4b
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/747f2330cd1fc4a06d54b376a9a6528d0364f0ac
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/749d5d7a9e0b1545b297117e834462af32b3e230 b/test/core/security/corpus/alts_credentials_corpus/749d5d7a9e0b1545b297117e834462af32b3e230
new file mode 100644
index 0000000..a00db59
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/749d5d7a9e0b1545b297117e834462af32b3e230
@@ -0,0 +1 @@
+aèÿÿ+
\ No newline at end of file
diff --git a/test/core/security/corpus/alts_credentials_corpus/77de0b1de120ac702ca45868b1008a48626daf12 b/test/core/security/corpus/alts_credentials_corpus/77de0b1de120ac702ca45868b1008a48626daf12
new file mode 100644
index 0000000..352762c
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/77de0b1de120ac702ca45868b1008a48626daf12
@@ -0,0 +1 @@
+òÒ^
\ No newline at end of file
diff --git a/test/core/security/corpus/alts_credentials_corpus/792c67398bce19a4eeda32653c994436e79456e5 b/test/core/security/corpus/alts_credentials_corpus/792c67398bce19a4eeda32653c994436e79456e5
new file mode 100644
index 0000000..0834287
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/792c67398bce19a4eeda32653c994436e79456e5
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/7a3022b248c8960289e4c80c7cc8df409499e5da b/test/core/security/corpus/alts_credentials_corpus/7a3022b248c8960289e4c80c7cc8df409499e5da
new file mode 100644
index 0000000..f9ef6a4
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/7a3022b248c8960289e4c80c7cc8df409499e5da
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/7a9372081294a6fbd3fecdd91b99589c98d4948e b/test/core/security/corpus/alts_credentials_corpus/7a9372081294a6fbd3fecdd91b99589c98d4948e
new file mode 100644
index 0000000..7100f32
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/7a9372081294a6fbd3fecdd91b99589c98d4948e
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/7bbe4ba828947550f4ad089d5989cb695ecbdb1b b/test/core/security/corpus/alts_credentials_corpus/7bbe4ba828947550f4ad089d5989cb695ecbdb1b
new file mode 100644
index 0000000..44e3963
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/7bbe4ba828947550f4ad089d5989cb695ecbdb1b
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/7f1ad514a96f0c3d5ca5d6f7880b929a65eeae96 b/test/core/security/corpus/alts_credentials_corpus/7f1ad514a96f0c3d5ca5d6f7880b929a65eeae96
new file mode 100644
index 0000000..700c079
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/7f1ad514a96f0c3d5ca5d6f7880b929a65eeae96
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/7f2b075f0b6707c38db851747e2578343eeab286 b/test/core/security/corpus/alts_credentials_corpus/7f2b075f0b6707c38db851747e2578343eeab286
new file mode 100644
index 0000000..1f7b5d7
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/7f2b075f0b6707c38db851747e2578343eeab286
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/81ebc64bfde3fad37af5a58ef7f1c5c3c54c4b5d b/test/core/security/corpus/alts_credentials_corpus/81ebc64bfde3fad37af5a58ef7f1c5c3c54c4b5d
new file mode 100644
index 0000000..d89f30f
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/81ebc64bfde3fad37af5a58ef7f1c5c3c54c4b5d
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/82fae081afaea13831404024d39658344d56e1c6 b/test/core/security/corpus/alts_credentials_corpus/82fae081afaea13831404024d39658344d56e1c6
new file mode 100644
index 0000000..bc3cfc2
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/82fae081afaea13831404024d39658344d56e1c6
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/83ba41cea1adab707f7f213af5e2ed734bdddc25 b/test/core/security/corpus/alts_credentials_corpus/83ba41cea1adab707f7f213af5e2ed734bdddc25
new file mode 100644
index 0000000..d465fb4
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/83ba41cea1adab707f7f213af5e2ed734bdddc25
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/841a3f66c94e5acd836a44cd5a8514d4ad45d83e b/test/core/security/corpus/alts_credentials_corpus/841a3f66c94e5acd836a44cd5a8514d4ad45d83e
new file mode 100644
index 0000000..cbb7bdc
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/841a3f66c94e5acd836a44cd5a8514d4ad45d83e
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/841ef94ee0f1b0b45983d95b75aba25421d73f2c b/test/core/security/corpus/alts_credentials_corpus/841ef94ee0f1b0b45983d95b75aba25421d73f2c
new file mode 100644
index 0000000..ba85d1d
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/841ef94ee0f1b0b45983d95b75aba25421d73f2c
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/843b0aad4a9707c5dcc92d12d876b78675cfcb65 b/test/core/security/corpus/alts_credentials_corpus/843b0aad4a9707c5dcc92d12d876b78675cfcb65
new file mode 100644
index 0000000..02d61c5
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/843b0aad4a9707c5dcc92d12d876b78675cfcb65
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/8483e3d92eda8df504b1d1d0d012f4bcd778cd33 b/test/core/security/corpus/alts_credentials_corpus/8483e3d92eda8df504b1d1d0d012f4bcd778cd33
new file mode 100644
index 0000000..3795466
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/8483e3d92eda8df504b1d1d0d012f4bcd778cd33
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/876830fdff4e59038fa2173b700faef5bffe61de b/test/core/security/corpus/alts_credentials_corpus/876830fdff4e59038fa2173b700faef5bffe61de
new file mode 100644
index 0000000..26048bd
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/876830fdff4e59038fa2173b700faef5bffe61de
@@ -0,0 +1 @@
+òÒA
\ No newline at end of file
diff --git a/test/core/security/corpus/alts_credentials_corpus/87ca3342fdce0c1f678a3f1b62428032ef51442d b/test/core/security/corpus/alts_credentials_corpus/87ca3342fdce0c1f678a3f1b62428032ef51442d
new file mode 100644
index 0000000..ea35b45
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/87ca3342fdce0c1f678a3f1b62428032ef51442d
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/87d044027cdb7d35fadb56532f497764246946a6 b/test/core/security/corpus/alts_credentials_corpus/87d044027cdb7d35fadb56532f497764246946a6
new file mode 100644
index 0000000..1e474c9
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/87d044027cdb7d35fadb56532f497764246946a6
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/88ce75ba18bdb7e93a81197d850f4e792f6a8155 b/test/core/security/corpus/alts_credentials_corpus/88ce75ba18bdb7e93a81197d850f4e792f6a8155
new file mode 100644
index 0000000..70c9ab1
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/88ce75ba18bdb7e93a81197d850f4e792f6a8155
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/89dc55e8e20e811e78c952c8bd2c16f55fe72f57 b/test/core/security/corpus/alts_credentials_corpus/89dc55e8e20e811e78c952c8bd2c16f55fe72f57
new file mode 100644
index 0000000..00961fd
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/89dc55e8e20e811e78c952c8bd2c16f55fe72f57
@@ -0,0 +1 @@
+òÒŽ
\ No newline at end of file
diff --git a/test/core/security/corpus/alts_credentials_corpus/8a215a58908f44bdced595ceb01a81977f1d72f0 b/test/core/security/corpus/alts_credentials_corpus/8a215a58908f44bdced595ceb01a81977f1d72f0
new file mode 100644
index 0000000..296f8b7
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/8a215a58908f44bdced595ceb01a81977f1d72f0
@@ -0,0 +1 @@
+Ä=ÒÄ=)†††††††ÄÄÄÄÄÄ
\ No newline at end of file
diff --git a/test/core/security/corpus/alts_credentials_corpus/8ac7459e918304ca40b1cf29a3ac0f555eada678 b/test/core/security/corpus/alts_credentials_corpus/8ac7459e918304ca40b1cf29a3ac0f555eada678
new file mode 100644
index 0000000..629a6f9
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/8ac7459e918304ca40b1cf29a3ac0f555eada678
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/8b93e50a911f3ea0e0b0377ba4636574f2ee9a5e b/test/core/security/corpus/alts_credentials_corpus/8b93e50a911f3ea0e0b0377ba4636574f2ee9a5e
new file mode 100644
index 0000000..280aecf
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/8b93e50a911f3ea0e0b0377ba4636574f2ee9a5e
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/8c9ec0ffd803505772693833d56e7a02110645b3 b/test/core/security/corpus/alts_credentials_corpus/8c9ec0ffd803505772693833d56e7a02110645b3
new file mode 100644
index 0000000..3bd046b
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/8c9ec0ffd803505772693833d56e7a02110645b3
@@ -0,0 +1 @@
+K]//(
\ No newline at end of file
diff --git a/test/core/security/corpus/alts_credentials_corpus/8e4b361a530dc6825afcfb4106bd482c3fd010fa b/test/core/security/corpus/alts_credentials_corpus/8e4b361a530dc6825afcfb4106bd482c3fd010fa
new file mode 100644
index 0000000..3733df9
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/8e4b361a530dc6825afcfb4106bd482c3fd010fa
@@ -0,0 +1 @@
+òÒÝ
\ No newline at end of file
diff --git a/test/core/security/corpus/alts_credentials_corpus/8f6690d97bcda890f2a5b2930a2b7a4d7b56c6e7 b/test/core/security/corpus/alts_credentials_corpus/8f6690d97bcda890f2a5b2930a2b7a4d7b56c6e7
new file mode 100644
index 0000000..7885e1ef
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/8f6690d97bcda890f2a5b2930a2b7a4d7b56c6e7
@@ -0,0 +1 @@
+òÒÝ
\ No newline at end of file
diff --git a/test/core/security/corpus/alts_credentials_corpus/917636de2c14dce2580d4308249a94d61d62c305 b/test/core/security/corpus/alts_credentials_corpus/917636de2c14dce2580d4308249a94d61d62c305
new file mode 100644
index 0000000..cccb20d
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/917636de2c14dce2580d4308249a94d61d62c305
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/91f11008defda918951bda868cc68c6373fb0e6a b/test/core/security/corpus/alts_credentials_corpus/91f11008defda918951bda868cc68c6373fb0e6a
new file mode 100644
index 0000000..bf10853
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/91f11008defda918951bda868cc68c6373fb0e6a
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/92e01a34047b660a798086d55a3d8d7100a01939 b/test/core/security/corpus/alts_credentials_corpus/92e01a34047b660a798086d55a3d8d7100a01939
new file mode 100644
index 0000000..e86bc1d
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/92e01a34047b660a798086d55a3d8d7100a01939
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/963fafadb4de09dee0e6a852bd61b1740039a465 b/test/core/security/corpus/alts_credentials_corpus/963fafadb4de09dee0e6a852bd61b1740039a465
new file mode 100644
index 0000000..8933b18
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/963fafadb4de09dee0e6a852bd61b1740039a465
@@ -0,0 +1 @@
+ê
\ No newline at end of file
diff --git a/test/core/security/corpus/alts_credentials_corpus/97bf33ec97b93fcc2449431915911a55b906e3b6 b/test/core/security/corpus/alts_credentials_corpus/97bf33ec97b93fcc2449431915911a55b906e3b6
new file mode 100644
index 0000000..8101e37
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/97bf33ec97b93fcc2449431915911a55b906e3b6
@@ -0,0 +1 @@
+òÓÓÒ
\ No newline at end of file
diff --git a/test/core/security/corpus/alts_credentials_corpus/99e31e12b02b02479d10b2c08426906bd93a0840 b/test/core/security/corpus/alts_credentials_corpus/99e31e12b02b02479d10b2c08426906bd93a0840
new file mode 100644
index 0000000..9fe2a6a
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/99e31e12b02b02479d10b2c08426906bd93a0840
@@ -0,0 +1 @@
+òÓÓÒ
\ No newline at end of file
diff --git a/test/core/security/corpus/alts_credentials_corpus/9a75ce693e7259d4d3bb9203dfc0a65f8bbaa466 b/test/core/security/corpus/alts_credentials_corpus/9a75ce693e7259d4d3bb9203dfc0a65f8bbaa466
new file mode 100644
index 0000000..5366cdd
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/9a75ce693e7259d4d3bb9203dfc0a65f8bbaa466
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/9ac0d956f9743e026baad7319ba2a75d9f1a534f b/test/core/security/corpus/alts_credentials_corpus/9ac0d956f9743e026baad7319ba2a75d9f1a534f
new file mode 100644
index 0000000..adb0583
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/9ac0d956f9743e026baad7319ba2a75d9f1a534f
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/9ae56d4451dd3e1b66ddc250d84dbf6d8cae0dbd b/test/core/security/corpus/alts_credentials_corpus/9ae56d4451dd3e1b66ddc250d84dbf6d8cae0dbd
new file mode 100644
index 0000000..121d0cb
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/9ae56d4451dd3e1b66ddc250d84dbf6d8cae0dbd
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/9b9a3a1e4023c9b172060249752a482a3437ef2a b/test/core/security/corpus/alts_credentials_corpus/9b9a3a1e4023c9b172060249752a482a3437ef2a
new file mode 100644
index 0000000..0b19f19
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/9b9a3a1e4023c9b172060249752a482a3437ef2a
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/9c81164e10bf612c352dca3ecabf57743b451d42 b/test/core/security/corpus/alts_credentials_corpus/9c81164e10bf612c352dca3ecabf57743b451d42
new file mode 100644
index 0000000..1cae116
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/9c81164e10bf612c352dca3ecabf57743b451d42
@@ -0,0 +1,2 @@
+
+z
\ No newline at end of file
diff --git a/test/core/security/corpus/alts_credentials_corpus/9d8b420b5d32deb0140ab91eeebba58ca6163722 b/test/core/security/corpus/alts_credentials_corpus/9d8b420b5d32deb0140ab91eeebba58ca6163722
new file mode 100644
index 0000000..6d0f809
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/9d8b420b5d32deb0140ab91eeebba58ca6163722
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/9de687bf1e2cfac54c3b2e2eb85b53014a460ff7 b/test/core/security/corpus/alts_credentials_corpus/9de687bf1e2cfac54c3b2e2eb85b53014a460ff7
new file mode 100644
index 0000000..789f59c
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/9de687bf1e2cfac54c3b2e2eb85b53014a460ff7
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/9f3cda19a186bd11bfac361b464f92daa129a33b b/test/core/security/corpus/alts_credentials_corpus/9f3cda19a186bd11bfac361b464f92daa129a33b
new file mode 100644
index 0000000..61347c3
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/9f3cda19a186bd11bfac361b464f92daa129a33b
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/a14fc6a608121f8abf0fe25cf466720f00f25653 b/test/core/security/corpus/alts_credentials_corpus/a14fc6a608121f8abf0fe25cf466720f00f25653
new file mode 100644
index 0000000..58af762
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/a14fc6a608121f8abf0fe25cf466720f00f25653
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/a39906074669a6b76a35b0adf2bf36ad751f3b35 b/test/core/security/corpus/alts_credentials_corpus/a39906074669a6b76a35b0adf2bf36ad751f3b35
new file mode 100644
index 0000000..e10cdb9
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/a39906074669a6b76a35b0adf2bf36ad751f3b35
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/a454ca483b4a66b83826d061be2859dd79ff0d6c b/test/core/security/corpus/alts_credentials_corpus/a454ca483b4a66b83826d061be2859dd79ff0d6c
new file mode 100644
index 0000000..38424fc
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/a454ca483b4a66b83826d061be2859dd79ff0d6c
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/a52df5607370ff0f56d821000f3d5e386a01d489 b/test/core/security/corpus/alts_credentials_corpus/a52df5607370ff0f56d821000f3d5e386a01d489
new file mode 100644
index 0000000..f16da07
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/a52df5607370ff0f56d821000f3d5e386a01d489
@@ -0,0 +1 @@
+úÒû;
\ No newline at end of file
diff --git a/test/core/security/corpus/alts_credentials_corpus/a56eaf47f7c7263e53efdc55ec39063dbb4ae71c b/test/core/security/corpus/alts_credentials_corpus/a56eaf47f7c7263e53efdc55ec39063dbb4ae71c
new file mode 100644
index 0000000..3664ce0
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/a56eaf47f7c7263e53efdc55ec39063dbb4ae71c
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/a79249fb8f7d53f0a280359d2d9df31594adbdfc b/test/core/security/corpus/alts_credentials_corpus/a79249fb8f7d53f0a280359d2d9df31594adbdfc
new file mode 100644
index 0000000..d7f1f45
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/a79249fb8f7d53f0a280359d2d9df31594adbdfc
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/aa98a46f25004f7436aadb36ff8b7f07ed7bfce1 b/test/core/security/corpus/alts_credentials_corpus/aa98a46f25004f7436aadb36ff8b7f07ed7bfce1
new file mode 100644
index 0000000..f1db8d9
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/aa98a46f25004f7436aadb36ff8b7f07ed7bfce1
@@ -0,0 +1 @@
+ap“ž’/òÒ+
\ No newline at end of file
diff --git a/test/core/security/corpus/alts_credentials_corpus/adc83b19e793491b1c6ea0fd8b46cd9f32e592fc b/test/core/security/corpus/alts_credentials_corpus/adc83b19e793491b1c6ea0fd8b46cd9f32e592fc
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/adc83b19e793491b1c6ea0fd8b46cd9f32e592fc
@@ -0,0 +1 @@
+
diff --git a/test/core/security/corpus/alts_credentials_corpus/afd8e19f7bfd6c963f1856be59b75627864821dc b/test/core/security/corpus/alts_credentials_corpus/afd8e19f7bfd6c963f1856be59b75627864821dc
new file mode 100644
index 0000000..385405e
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/afd8e19f7bfd6c963f1856be59b75627864821dc
@@ -0,0 +1,2 @@
+¯+ú
+䍴õ
\ No newline at end of file
diff --git a/test/core/security/corpus/alts_credentials_corpus/b3966239b8568442baecbeb0f8a1aa29dcdfd7ed b/test/core/security/corpus/alts_credentials_corpus/b3966239b8568442baecbeb0f8a1aa29dcdfd7ed
new file mode 100644
index 0000000..3d9fb86
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/b3966239b8568442baecbeb0f8a1aa29dcdfd7ed
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/b430d41ef65493b3e917182c23ce90df983e01ab b/test/core/security/corpus/alts_credentials_corpus/b430d41ef65493b3e917182c23ce90df983e01ab
new file mode 100644
index 0000000..cbb8ceb
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/b430d41ef65493b3e917182c23ce90df983e01ab
@@ -0,0 +1,2 @@
+ÿ
+
diff --git a/test/core/security/corpus/alts_credentials_corpus/b44e715e0cfe05f0c92a9e000ac3c36aae17df9d b/test/core/security/corpus/alts_credentials_corpus/b44e715e0cfe05f0c92a9e000ac3c36aae17df9d
new file mode 100644
index 0000000..f0b1381
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/b44e715e0cfe05f0c92a9e000ac3c36aae17df9d
@@ -0,0 +1 @@
+]]
\ No newline at end of file
diff --git a/test/core/security/corpus/alts_credentials_corpus/b4cf4ef7b3f64eff76cf99091fddc04411774708 b/test/core/security/corpus/alts_credentials_corpus/b4cf4ef7b3f64eff76cf99091fddc04411774708
new file mode 100644
index 0000000..65d4adb
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/b4cf4ef7b3f64eff76cf99091fddc04411774708
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/b53d84468ea93620a9824ca65acf1179f431e763 b/test/core/security/corpus/alts_credentials_corpus/b53d84468ea93620a9824ca65acf1179f431e763
new file mode 100644
index 0000000..5844d31
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/b53d84468ea93620a9824ca65acf1179f431e763
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/b6ac4831cc5baabee9c8ab9af9ca3923f91097a0 b/test/core/security/corpus/alts_credentials_corpus/b6ac4831cc5baabee9c8ab9af9ca3923f91097a0
new file mode 100644
index 0000000..3d54a26
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/b6ac4831cc5baabee9c8ab9af9ca3923f91097a0
@@ -0,0 +1,2 @@
+îÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿAï
+ïé
\ No newline at end of file
diff --git a/test/core/security/corpus/alts_credentials_corpus/b7f4a484866a8050dbc63bc905c9803c6964eda5 b/test/core/security/corpus/alts_credentials_corpus/b7f4a484866a8050dbc63bc905c9803c6964eda5
new file mode 100644
index 0000000..e17c966
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/b7f4a484866a8050dbc63bc905c9803c6964eda5
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/b8f21e59f90431c982d5ec3fb54ae4605f102252 b/test/core/security/corpus/alts_credentials_corpus/b8f21e59f90431c982d5ec3fb54ae4605f102252
new file mode 100644
index 0000000..79e3486
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/b8f21e59f90431c982d5ec3fb54ae4605f102252
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/bad10b6581cdead8e7cb96e4f544dcf0ea650fbc b/test/core/security/corpus/alts_credentials_corpus/bad10b6581cdead8e7cb96e4f544dcf0ea650fbc
new file mode 100644
index 0000000..9deb760
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/bad10b6581cdead8e7cb96e4f544dcf0ea650fbc
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/bb01bed86b43257be9f527388e1183f52438c473 b/test/core/security/corpus/alts_credentials_corpus/bb01bed86b43257be9f527388e1183f52438c473
new file mode 100644
index 0000000..ad47d46
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/bb01bed86b43257be9f527388e1183f52438c473
@@ -0,0 +1 @@
+òÒûþ
\ No newline at end of file
diff --git a/test/core/security/corpus/alts_credentials_corpus/bb7497b00f0d999ef39dbf81c6bd0441e32723b6 b/test/core/security/corpus/alts_credentials_corpus/bb7497b00f0d999ef39dbf81c6bd0441e32723b6
new file mode 100644
index 0000000..3b2f108
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/bb7497b00f0d999ef39dbf81c6bd0441e32723b6
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/bf01b72e635deda1b4a8468f1cc36f01a54e1338 b/test/core/security/corpus/alts_credentials_corpus/bf01b72e635deda1b4a8468f1cc36f01a54e1338
new file mode 100644
index 0000000..7fa6cf8
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/bf01b72e635deda1b4a8468f1cc36f01a54e1338
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/bf8b4530d8d246dd74ac53a13471bba17941dff7 b/test/core/security/corpus/alts_credentials_corpus/bf8b4530d8d246dd74ac53a13471bba17941dff7
new file mode 100644
index 0000000..6b2aaa7
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/bf8b4530d8d246dd74ac53a13471bba17941dff7
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/core/security/corpus/alts_credentials_corpus/c08bc84ab6a512b901bb730beb05c8394e4f1c5d b/test/core/security/corpus/alts_credentials_corpus/c08bc84ab6a512b901bb730beb05c8394e4f1c5d
new file mode 100644
index 0000000..8d75368
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/c08bc84ab6a512b901bb730beb05c8394e4f1c5d
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/c244b635d94e6f5d6b344887434be3e001a04b41 b/test/core/security/corpus/alts_credentials_corpus/c244b635d94e6f5d6b344887434be3e001a04b41
new file mode 100644
index 0000000..92e73a2
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/c244b635d94e6f5d6b344887434be3e001a04b41
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/c281efe9620da999a637ff6e9b3279ec613fb992 b/test/core/security/corpus/alts_credentials_corpus/c281efe9620da999a637ff6e9b3279ec613fb992
new file mode 100644
index 0000000..c17a77e
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/c281efe9620da999a637ff6e9b3279ec613fb992
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/c30a212824ee71e215f475f453de17c65a200101 b/test/core/security/corpus/alts_credentials_corpus/c30a212824ee71e215f475f453de17c65a200101
new file mode 100644
index 0000000..86ac99e
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/c30a212824ee71e215f475f453de17c65a200101
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/c449427f35b7ecdf5641073629f7723df52c4cb0 b/test/core/security/corpus/alts_credentials_corpus/c449427f35b7ecdf5641073629f7723df52c4cb0
new file mode 100644
index 0000000..87d1a32
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/c449427f35b7ecdf5641073629f7723df52c4cb0
@@ -0,0 +1 @@
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‚ՏÒÒÒÒÒÒÒÒÒÒ‘-
\ No newline at end of file
diff --git a/test/core/security/corpus/alts_credentials_corpus/c60240cd3b02eb71e2bf5ebd59afa3a5dc9b5e4d b/test/core/security/corpus/alts_credentials_corpus/c60240cd3b02eb71e2bf5ebd59afa3a5dc9b5e4d
new file mode 100644
index 0000000..f8804b8
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/c60240cd3b02eb71e2bf5ebd59afa3a5dc9b5e4d
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/c60cdf9c3fb9060838f445b3bc3852b6f81e1e4c b/test/core/security/corpus/alts_credentials_corpus/c60cdf9c3fb9060838f445b3bc3852b6f81e1e4c
new file mode 100644
index 0000000..327246f
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/c60cdf9c3fb9060838f445b3bc3852b6f81e1e4c
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/c72d0501bacadb45242c553ba292591302f12a6a b/test/core/security/corpus/alts_credentials_corpus/c72d0501bacadb45242c553ba292591302f12a6a
new file mode 100644
index 0000000..ca02baf
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/c72d0501bacadb45242c553ba292591302f12a6a
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/c739e7b5ad999edbdeffdab672dbc30deb3959a0 b/test/core/security/corpus/alts_credentials_corpus/c739e7b5ad999edbdeffdab672dbc30deb3959a0
new file mode 100644
index 0000000..d7f2d22
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/c739e7b5ad999edbdeffdab672dbc30deb3959a0
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/c7d73b12a7108d82f8dac6d8a6a34f838601aca6 b/test/core/security/corpus/alts_credentials_corpus/c7d73b12a7108d82f8dac6d8a6a34f838601aca6
new file mode 100644
index 0000000..b38437a
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/c7d73b12a7108d82f8dac6d8a6a34f838601aca6
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/ca781e1add632433293e847ae9e71649c217ee5f b/test/core/security/corpus/alts_credentials_corpus/ca781e1add632433293e847ae9e71649c217ee5f
new file mode 100644
index 0000000..5c79dd1
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/ca781e1add632433293e847ae9e71649c217ee5f
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/cc48e916f40e8d69c2d07cfda42c7d3b7fe3447a b/test/core/security/corpus/alts_credentials_corpus/cc48e916f40e8d69c2d07cfda42c7d3b7fe3447a
new file mode 100644
index 0000000..11ccb07
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/cc48e916f40e8d69c2d07cfda42c7d3b7fe3447a
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/cca1aff4c08ee4ccbcb6f80e1cd1480a0a093cfd b/test/core/security/corpus/alts_credentials_corpus/cca1aff4c08ee4ccbcb6f80e1cd1480a0a093cfd
new file mode 100644
index 0000000..b7bebbe
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/cca1aff4c08ee4ccbcb6f80e1cd1480a0a093cfd
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/cf6ae8bf1d08d25e235b7bee0839984bbc04edf6 b/test/core/security/corpus/alts_credentials_corpus/cf6ae8bf1d08d25e235b7bee0839984bbc04edf6
new file mode 100644
index 0000000..32eb656
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/cf6ae8bf1d08d25e235b7bee0839984bbc04edf6
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/cfc52fa086292c699efd7bf41d2fae3deb449536 b/test/core/security/corpus/alts_credentials_corpus/cfc52fa086292c699efd7bf41d2fae3deb449536
new file mode 100644
index 0000000..285e35d
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/cfc52fa086292c699efd7bf41d2fae3deb449536
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/cfe13ef3c6c713a059f231f0001ecec97e2a932d b/test/core/security/corpus/alts_credentials_corpus/cfe13ef3c6c713a059f231f0001ecec97e2a932d
new file mode 100644
index 0000000..1059f60
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/cfe13ef3c6c713a059f231f0001ecec97e2a932d
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/d14026ac6421bca7161024f4e735cb80a1068d01 b/test/core/security/corpus/alts_credentials_corpus/d14026ac6421bca7161024f4e735cb80a1068d01
new file mode 100644
index 0000000..68b7682
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/d14026ac6421bca7161024f4e735cb80a1068d01
@@ -0,0 +1,2 @@
+
+ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûÿ+´úä¯õ
\ No newline at end of file
diff --git a/test/core/security/corpus/alts_credentials_corpus/d2fb6e8f7867fc1e2ebe723da2b5246dc9cc6b14 b/test/core/security/corpus/alts_credentials_corpus/d2fb6e8f7867fc1e2ebe723da2b5246dc9cc6b14
new file mode 100644
index 0000000..9854260
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/d2fb6e8f7867fc1e2ebe723da2b5246dc9cc6b14
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/d4db7d51bdaa4781cf12c3b59914bad414d2a41e b/test/core/security/corpus/alts_credentials_corpus/d4db7d51bdaa4781cf12c3b59914bad414d2a41e
new file mode 100644
index 0000000..0979d45
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/d4db7d51bdaa4781cf12c3b59914bad414d2a41e
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/d533da0e7f8c1e39bb025b4d7a89613142a6f54e b/test/core/security/corpus/alts_credentials_corpus/d533da0e7f8c1e39bb025b4d7a89613142a6f54e
new file mode 100644
index 0000000..89ef0d2
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/d533da0e7f8c1e39bb025b4d7a89613142a6f54e
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/d5cf489d01a1b847a7aac5dddabff23fdc218e1e b/test/core/security/corpus/alts_credentials_corpus/d5cf489d01a1b847a7aac5dddabff23fdc218e1e
new file mode 100644
index 0000000..c544b27
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/d5cf489d01a1b847a7aac5dddabff23fdc218e1e
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/d686f8561a249c7c15c78f76a5fceb884286e070 b/test/core/security/corpus/alts_credentials_corpus/d686f8561a249c7c15c78f76a5fceb884286e070
new file mode 100644
index 0000000..b96c459
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/d686f8561a249c7c15c78f76a5fceb884286e070
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/d92424daad9d96a40e5ab177e3824c36ef51dc0f b/test/core/security/corpus/alts_credentials_corpus/d92424daad9d96a40e5ab177e3824c36ef51dc0f
new file mode 100644
index 0000000..509eb39
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/d92424daad9d96a40e5ab177e3824c36ef51dc0f
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/db242a11ed88b2b26af46770dd1927d9f35301fb b/test/core/security/corpus/alts_credentials_corpus/db242a11ed88b2b26af46770dd1927d9f35301fb
new file mode 100644
index 0000000..bd5d046
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/db242a11ed88b2b26af46770dd1927d9f35301fb
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/db32eb04db13d58f65f46d262608bd088987c063 b/test/core/security/corpus/alts_credentials_corpus/db32eb04db13d58f65f46d262608bd088987c063
new file mode 100644
index 0000000..5c526d8
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/db32eb04db13d58f65f46d262608bd088987c063
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/db39a953317951759e40734de6607a0b4457728e b/test/core/security/corpus/alts_credentials_corpus/db39a953317951759e40734de6607a0b4457728e
new file mode 100644
index 0000000..d794576
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/db39a953317951759e40734de6607a0b4457728e
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/dc5e8f3102456bed90d17303bc4cff1a7e076d5d b/test/core/security/corpus/alts_credentials_corpus/dc5e8f3102456bed90d17303bc4cff1a7e076d5d
new file mode 100644
index 0000000..53e1bbc
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/dc5e8f3102456bed90d17303bc4cff1a7e076d5d
@@ -0,0 +1 @@
+‚
\ No newline at end of file
diff --git a/test/core/security/corpus/alts_credentials_corpus/dd9542bbed8e5dc58da2789edbfb9c38d578d3b4 b/test/core/security/corpus/alts_credentials_corpus/dd9542bbed8e5dc58da2789edbfb9c38d578d3b4
new file mode 100644
index 0000000..95fd950
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/dd9542bbed8e5dc58da2789edbfb9c38d578d3b4
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/de2ebb1ed324385de500a1a3308846239857c3c7 b/test/core/security/corpus/alts_credentials_corpus/de2ebb1ed324385de500a1a3308846239857c3c7
new file mode 100644
index 0000000..d0cee5f
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/de2ebb1ed324385de500a1a3308846239857c3c7
@@ -0,0 +1 @@
+ø+ø
\ No newline at end of file
diff --git a/test/core/security/corpus/alts_credentials_corpus/de8ba9158254c1cd84b53df1e4cdf1757b1392f1 b/test/core/security/corpus/alts_credentials_corpus/de8ba9158254c1cd84b53df1e4cdf1757b1392f1
new file mode 100644
index 0000000..1cbbe5b
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/de8ba9158254c1cd84b53df1e4cdf1757b1392f1
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/e1dd260746f50024822a8b729b89545d26decfb8 b/test/core/security/corpus/alts_credentials_corpus/e1dd260746f50024822a8b729b89545d26decfb8
new file mode 100644
index 0000000..c44854e
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/e1dd260746f50024822a8b729b89545d26decfb8
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/e29add81b20dc570fdc885782689f6dccb1c5fad b/test/core/security/corpus/alts_credentials_corpus/e29add81b20dc570fdc885782689f6dccb1c5fad
new file mode 100644
index 0000000..5c50fe7
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/e29add81b20dc570fdc885782689f6dccb1c5fad
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/e2e99af62843cd3b29d50daeb118e58830784da9 b/test/core/security/corpus/alts_credentials_corpus/e2e99af62843cd3b29d50daeb118e58830784da9
new file mode 100644
index 0000000..04da131
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/e2e99af62843cd3b29d50daeb118e58830784da9
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/e46611c5daf99662e1576147c1623409752a1f39 b/test/core/security/corpus/alts_credentials_corpus/e46611c5daf99662e1576147c1623409752a1f39
new file mode 100644
index 0000000..0334d31
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/e46611c5daf99662e1576147c1623409752a1f39
@@ -0,0 +1 @@
+ä##
\ No newline at end of file
diff --git a/test/core/security/corpus/alts_credentials_corpus/e5a1ba11af830e9d2db201c5164f75747a85fe9b b/test/core/security/corpus/alts_credentials_corpus/e5a1ba11af830e9d2db201c5164f75747a85fe9b
new file mode 100644
index 0000000..8e8b1e2
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/e5a1ba11af830e9d2db201c5164f75747a85fe9b
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/e6026ee0badf216b326443a5f708446b2f2e579f b/test/core/security/corpus/alts_credentials_corpus/e6026ee0badf216b326443a5f708446b2f2e579f
new file mode 100644
index 0000000..a99014f
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/e6026ee0badf216b326443a5f708446b2f2e579f
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/e6c7d2c0038fa1f03fc6590a726abc98f4c641f3 b/test/core/security/corpus/alts_credentials_corpus/e6c7d2c0038fa1f03fc6590a726abc98f4c641f3
new file mode 100644
index 0000000..8f5a9f5
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/e6c7d2c0038fa1f03fc6590a726abc98f4c641f3
@@ -0,0 +1 @@
+òi
\ No newline at end of file
diff --git a/test/core/security/corpus/alts_credentials_corpus/eafdef6a630bed71bd0e4f3d4a16b5fa0c920651 b/test/core/security/corpus/alts_credentials_corpus/eafdef6a630bed71bd0e4f3d4a16b5fa0c920651
new file mode 100644
index 0000000..6fbe750
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/eafdef6a630bed71bd0e4f3d4a16b5fa0c920651
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/ece985b9b82e27281514d460709d7edf8203ded7 b/test/core/security/corpus/alts_credentials_corpus/ece985b9b82e27281514d460709d7edf8203ded7
new file mode 100644
index 0000000..c124302
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/ece985b9b82e27281514d460709d7edf8203ded7
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/edb8f4259f756c2c4bc731f05beaa36f992cf079 b/test/core/security/corpus/alts_credentials_corpus/edb8f4259f756c2c4bc731f05beaa36f992cf079
new file mode 100644
index 0000000..1cc08a4
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/edb8f4259f756c2c4bc731f05beaa36f992cf079
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/edce7778c2e1adb81dda3d057a6536759a7cb293 b/test/core/security/corpus/alts_credentials_corpus/edce7778c2e1adb81dda3d057a6536759a7cb293
new file mode 100644
index 0000000..39b52cf
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/edce7778c2e1adb81dda3d057a6536759a7cb293
@@ -0,0 +1 @@
++
\ No newline at end of file
diff --git a/test/core/security/corpus/alts_credentials_corpus/ee4040c0dd406dd616c49ed2c37b40478dabfe0f b/test/core/security/corpus/alts_credentials_corpus/ee4040c0dd406dd616c49ed2c37b40478dabfe0f
new file mode 100644
index 0000000..48325e3
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/ee4040c0dd406dd616c49ed2c37b40478dabfe0f
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/ee69f2b380663d051a70f30fcfce9f79f5341e5a b/test/core/security/corpus/alts_credentials_corpus/ee69f2b380663d051a70f30fcfce9f79f5341e5a
new file mode 100644
index 0000000..7e0ad2a
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/ee69f2b380663d051a70f30fcfce9f79f5341e5a
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/efc6743e47274058771bb6eda1fefa017bde4a95 b/test/core/security/corpus/alts_credentials_corpus/efc6743e47274058771bb6eda1fefa017bde4a95
new file mode 100644
index 0000000..4418e8a
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/efc6743e47274058771bb6eda1fefa017bde4a95
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/f0038e54162000694d882b1acb80930c807b41d2 b/test/core/security/corpus/alts_credentials_corpus/f0038e54162000694d882b1acb80930c807b41d2
new file mode 100644
index 0000000..292a5e4
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/f0038e54162000694d882b1acb80930c807b41d2
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/f1deb9e388c877337dabe92f31b01e2a019a10f4 b/test/core/security/corpus/alts_credentials_corpus/f1deb9e388c877337dabe92f31b01e2a019a10f4
new file mode 100644
index 0000000..46464ee
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/f1deb9e388c877337dabe92f31b01e2a019a10f4
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/f3a09373e4d3c7310d372089e6deb15d6b22c198 b/test/core/security/corpus/alts_credentials_corpus/f3a09373e4d3c7310d372089e6deb15d6b22c198
new file mode 100644
index 0000000..a974996
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/f3a09373e4d3c7310d372089e6deb15d6b22c198
@@ -0,0 +1 @@
+üÒûþ
\ No newline at end of file
diff --git a/test/core/security/corpus/alts_credentials_corpus/f3db7ef6495fa1ac5bb4db293fb38dd59122bb7c b/test/core/security/corpus/alts_credentials_corpus/f3db7ef6495fa1ac5bb4db293fb38dd59122bb7c
new file mode 100644
index 0000000..8afc32b
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/f3db7ef6495fa1ac5bb4db293fb38dd59122bb7c
@@ -0,0 +1,2 @@
+[ÿÿ[ÿÿÿ	
+¡Š
\ No newline at end of file
diff --git a/test/core/security/corpus/alts_credentials_corpus/f434bb4ceecc573e085d4c3ef453ef01e93d9c89 b/test/core/security/corpus/alts_credentials_corpus/f434bb4ceecc573e085d4c3ef453ef01e93d9c89
new file mode 100644
index 0000000..2b66a00
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/f434bb4ceecc573e085d4c3ef453ef01e93d9c89
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/f55bceaad42ddf9d2b37fdfca68255d29a696109 b/test/core/security/corpus/alts_credentials_corpus/f55bceaad42ddf9d2b37fdfca68255d29a696109
new file mode 100644
index 0000000..a8eef8f
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/f55bceaad42ddf9d2b37fdfca68255d29a696109
@@ -0,0 +1 @@
+òÒ
\ No newline at end of file
diff --git a/test/core/security/corpus/alts_credentials_corpus/f62ca5321428a5d23f3c804fb51eb4e65bc58716 b/test/core/security/corpus/alts_credentials_corpus/f62ca5321428a5d23f3c804fb51eb4e65bc58716
new file mode 100644
index 0000000..0d80f7b
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/f62ca5321428a5d23f3c804fb51eb4e65bc58716
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/f7c6a558b8d0af64db2b139371a7af7068b01b92 b/test/core/security/corpus/alts_credentials_corpus/f7c6a558b8d0af64db2b139371a7af7068b01b92
new file mode 100644
index 0000000..d46ea45
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/f7c6a558b8d0af64db2b139371a7af7068b01b92
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/faa1781e1444bba5b8c677bc5e2a38d023a1ec65 b/test/core/security/corpus/alts_credentials_corpus/faa1781e1444bba5b8c677bc5e2a38d023a1ec65
new file mode 100644
index 0000000..013d565
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/faa1781e1444bba5b8c677bc5e2a38d023a1ec65
@@ -0,0 +1 @@

\ No newline at end of file
diff --git a/test/core/security/corpus/alts_credentials_corpus/fceba33ada1dda05fccedfefd331c9a201f1a2e5 b/test/core/security/corpus/alts_credentials_corpus/fceba33ada1dda05fccedfefd331c9a201f1a2e5
new file mode 100644
index 0000000..f3db26d
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/fceba33ada1dda05fccedfefd331c9a201f1a2e5
@@ -0,0 +1 @@
+¿
\ No newline at end of file
diff --git a/test/core/security/corpus/alts_credentials_corpus/fd668bef6fdaf7f3ffd58d8c60ce550476652e60 b/test/core/security/corpus/alts_credentials_corpus/fd668bef6fdaf7f3ffd58d8c60ce550476652e60
new file mode 100644
index 0000000..dcefd99
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/fd668bef6fdaf7f3ffd58d8c60ce550476652e60
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/fdf06b928e37e7c4ae59a568b5723ad98bbed6e5 b/test/core/security/corpus/alts_credentials_corpus/fdf06b928e37e7c4ae59a568b5723ad98bbed6e5
new file mode 100644
index 0000000..fe28d69
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/fdf06b928e37e7c4ae59a568b5723ad98bbed6e5
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/fe2fc5d499aeb2762387ef2e3ce939280813dec0 b/test/core/security/corpus/alts_credentials_corpus/fe2fc5d499aeb2762387ef2e3ce939280813dec0
new file mode 100644
index 0000000..cb035e7
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/fe2fc5d499aeb2762387ef2e3ce939280813dec0
Binary files differ
diff --git a/test/core/security/corpus/alts_credentials_corpus/ff548d368b090409a138e5cc4afc7f43b4a3fbbd b/test/core/security/corpus/alts_credentials_corpus/ff548d368b090409a138e5cc4afc7f43b4a3fbbd
new file mode 100644
index 0000000..caadbc0
--- /dev/null
+++ b/test/core/security/corpus/alts_credentials_corpus/ff548d368b090409a138e5cc4afc7f43b4a3fbbd
Binary files differ
diff --git a/test/core/security/credentials_test.cc b/test/core/security/credentials_test.cc
index ce92e21..2b90939 100644
--- a/test/core/security/credentials_test.cc
+++ b/test/core/security/credentials_test.cc
@@ -867,6 +867,7 @@
 static void test_google_default_creds_auth_key(void) {
   grpc_core::ExecCtx exec_ctx;
   grpc_service_account_jwt_access_credentials* jwt;
+  grpc_google_default_channel_credentials* default_creds;
   grpc_composite_channel_credentials* creds;
   char* json_key = test_json_key_str();
   grpc_flush_cached_google_default_credentials();
@@ -875,7 +876,9 @@
   gpr_free(json_key);
   creds = reinterpret_cast<grpc_composite_channel_credentials*>(
       grpc_google_default_credentials_create());
-  GPR_ASSERT(creds != nullptr);
+  default_creds = reinterpret_cast<grpc_google_default_channel_credentials*>(
+      creds->inner_creds);
+  GPR_ASSERT(default_creds->ssl_creds != nullptr);
   jwt = reinterpret_cast<grpc_service_account_jwt_access_credentials*>(
       creds->call_creds);
   GPR_ASSERT(
@@ -889,13 +892,16 @@
 static void test_google_default_creds_refresh_token(void) {
   grpc_core::ExecCtx exec_ctx;
   grpc_google_refresh_token_credentials* refresh;
+  grpc_google_default_channel_credentials* default_creds;
   grpc_composite_channel_credentials* creds;
   grpc_flush_cached_google_default_credentials();
   set_google_default_creds_env_var_with_file_contents(
       "refresh_token_google_default_creds", test_refresh_token_str);
   creds = reinterpret_cast<grpc_composite_channel_credentials*>(
       grpc_google_default_credentials_create());
-  GPR_ASSERT(creds != nullptr);
+  default_creds = reinterpret_cast<grpc_google_default_channel_credentials*>(
+      creds->inner_creds);
+  GPR_ASSERT(default_creds->ssl_creds != nullptr);
   refresh = reinterpret_cast<grpc_google_refresh_token_credentials*>(
       creds->call_creds);
   GPR_ASSERT(strcmp(refresh->refresh_token.client_id,
diff --git a/test/core/security/grpc_alts_credentials_options_test.cc b/test/core/security/grpc_alts_credentials_options_test.cc
index 1217065..623db48 100644
--- a/test/core/security/grpc_alts_credentials_options_test.cc
+++ b/test/core/security/grpc_alts_credentials_options_test.cc
@@ -30,39 +30,22 @@
 
 const size_t kTargetServiceAccountNum = 2;
 
-static void test_add_target_service_account_failure() {
-  /* Initialization. */
-  grpc_alts_credentials_options* options =
-      grpc_alts_credentials_client_options_create();
-  auto client_options =
-      reinterpret_cast<grpc_alts_credentials_client_options*>(options);
-
-  /* Test. */
-  GPR_ASSERT(!grpc_alts_credentials_client_options_add_target_service_account(
-      client_options, nullptr));
-  GPR_ASSERT(!grpc_alts_credentials_client_options_add_target_service_account(
-      nullptr, ALTS_CLIENT_OPTIONS_TEST_TARGET_SERVICE_ACCOUNT_1));
-
-  /* Cleanup. */
-  grpc_alts_credentials_options_destroy(options);
-}
-
 static void test_copy_client_options_failure() {
   /* Initialization. */
   grpc_alts_credentials_options* options =
       grpc_alts_credentials_client_options_create();
-
   /* Test. */
   GPR_ASSERT(grpc_alts_credentials_options_copy(nullptr) == nullptr);
-
   /* Cleanup. */
   grpc_alts_credentials_options_destroy(options);
 }
 
 static size_t get_target_service_account_num(
-    grpc_alts_credentials_client_options* options) {
+    grpc_alts_credentials_options* options) {
+  auto client_options =
+      reinterpret_cast<grpc_alts_credentials_client_options*>(options);
   size_t num = 0;
-  target_service_account* node = options->target_account_list_head;
+  target_service_account* node = client_options->target_account_list_head;
   while (node != nullptr) {
     num++;
     node = node->next;
@@ -74,36 +57,31 @@
   /* Initialization. */
   grpc_alts_credentials_options* options =
       grpc_alts_credentials_client_options_create();
-  auto client_options =
-      reinterpret_cast<grpc_alts_credentials_client_options*>(options);
-
   /* Set client options fields. */
   grpc_alts_credentials_client_options_add_target_service_account(
-      client_options, ALTS_CLIENT_OPTIONS_TEST_TARGET_SERVICE_ACCOUNT_1);
+      options, ALTS_CLIENT_OPTIONS_TEST_TARGET_SERVICE_ACCOUNT_1);
   grpc_alts_credentials_client_options_add_target_service_account(
-      client_options, ALTS_CLIENT_OPTIONS_TEST_TARGET_SERVICE_ACCOUNT_2);
-
+      options, ALTS_CLIENT_OPTIONS_TEST_TARGET_SERVICE_ACCOUNT_2);
   /* Validate client option fields. */
-  GPR_ASSERT(get_target_service_account_num(client_options) ==
+  GPR_ASSERT(get_target_service_account_num(options) ==
              kTargetServiceAccountNum);
+  auto client_options =
+      reinterpret_cast<grpc_alts_credentials_client_options*>(options);
   GPR_ASSERT(strcmp(client_options->target_account_list_head->data,
                     ALTS_CLIENT_OPTIONS_TEST_TARGET_SERVICE_ACCOUNT_2) == 0);
   GPR_ASSERT(strcmp(client_options->target_account_list_head->next->data,
                     ALTS_CLIENT_OPTIONS_TEST_TARGET_SERVICE_ACCOUNT_1) == 0);
-
   /* Perform a copy operation and validate its correctness. */
   grpc_alts_credentials_options* new_options =
       grpc_alts_credentials_options_copy(options);
+  GPR_ASSERT(get_target_service_account_num(new_options) ==
+             kTargetServiceAccountNum);
   auto new_client_options =
       reinterpret_cast<grpc_alts_credentials_client_options*>(new_options);
-
-  GPR_ASSERT(get_target_service_account_num(new_client_options) ==
-             kTargetServiceAccountNum);
   GPR_ASSERT(strcmp(new_client_options->target_account_list_head->data,
                     ALTS_CLIENT_OPTIONS_TEST_TARGET_SERVICE_ACCOUNT_2) == 0);
   GPR_ASSERT(strcmp(new_client_options->target_account_list_head->next->data,
                     ALTS_CLIENT_OPTIONS_TEST_TARGET_SERVICE_ACCOUNT_1) == 0);
-
   /* Cleanup.*/
   grpc_alts_credentials_options_destroy(options);
   grpc_alts_credentials_options_destroy(new_options);
@@ -111,7 +89,6 @@
 
 int main(int argc, char** argv) {
   /* Test. */
-  test_add_target_service_account_failure();
   test_copy_client_options_failure();
   test_client_options_api_success();
   return 0;
diff --git a/test/core/security/security_connector_test.cc b/test/core/security/security_connector_test.cc
index f03f4cc..e4c3ace 100644
--- a/test/core/security/security_connector_test.cc
+++ b/test/core/security/security_connector_test.cc
@@ -87,15 +87,15 @@
   GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
                  TSI_CERTIFICATE_TYPE_PEER_PROPERTY, TSI_X509_CERTIFICATE_TYPE,
                  &peer.properties[0]) == TSI_OK);
-  ctx = tsi_ssl_peer_to_auth_context(&peer);
+  ctx = grpc_ssl_peer_to_auth_context(&peer);
   GPR_ASSERT(ctx != nullptr);
   GPR_ASSERT(!grpc_auth_context_peer_is_authenticated(ctx));
   GPR_ASSERT(check_transport_security_type(ctx));
 
-  rpeer = tsi_shallow_peer_from_ssl_auth_context(ctx);
+  rpeer = grpc_shallow_peer_from_ssl_auth_context(ctx);
   GPR_ASSERT(check_ssl_peer_equivalence(&peer, &rpeer));
 
-  tsi_shallow_peer_destruct(&rpeer);
+  grpc_shallow_peer_destruct(&rpeer);
   tsi_peer_destruct(&peer);
   GRPC_AUTH_CONTEXT_UNREF(ctx, "test");
 }
@@ -187,7 +187,7 @@
   GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
                  TSI_X509_PEM_CERT_PROPERTY, expected_pem_cert,
                  &peer.properties[2]) == TSI_OK);
-  ctx = tsi_ssl_peer_to_auth_context(&peer);
+  ctx = grpc_ssl_peer_to_auth_context(&peer);
   GPR_ASSERT(ctx != nullptr);
   GPR_ASSERT(grpc_auth_context_peer_is_authenticated(ctx));
   GPR_ASSERT(check_identity(ctx, GRPC_X509_CN_PROPERTY_NAME, &expected_cn, 1));
@@ -195,10 +195,10 @@
   GPR_ASSERT(check_x509_cn(ctx, expected_cn));
   GPR_ASSERT(check_x509_pem_cert(ctx, expected_pem_cert));
 
-  rpeer = tsi_shallow_peer_from_ssl_auth_context(ctx);
+  rpeer = grpc_shallow_peer_from_ssl_auth_context(ctx);
   GPR_ASSERT(check_ssl_peer_equivalence(&peer, &rpeer));
 
-  tsi_shallow_peer_destruct(&rpeer);
+  grpc_shallow_peer_destruct(&rpeer);
   tsi_peer_destruct(&peer);
   GRPC_AUTH_CONTEXT_UNREF(ctx, "test");
 }
@@ -223,7 +223,7 @@
   GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
                  TSI_X509_PEM_CERT_PROPERTY, expected_pem_cert,
                  &peer.properties[3]) == TSI_OK);
-  ctx = tsi_ssl_peer_to_auth_context(&peer);
+  ctx = grpc_ssl_peer_to_auth_context(&peer);
   GPR_ASSERT(ctx != nullptr);
   GPR_ASSERT(grpc_auth_context_peer_is_authenticated(ctx));
   GPR_ASSERT(
@@ -232,10 +232,10 @@
   GPR_ASSERT(check_x509_cn(ctx, expected_cn));
   GPR_ASSERT(check_x509_pem_cert(ctx, expected_pem_cert));
 
-  rpeer = tsi_shallow_peer_from_ssl_auth_context(ctx);
+  rpeer = grpc_shallow_peer_from_ssl_auth_context(ctx);
   GPR_ASSERT(check_ssl_peer_equivalence(&peer, &rpeer));
 
-  tsi_shallow_peer_destruct(&rpeer);
+  grpc_shallow_peer_destruct(&rpeer);
   tsi_peer_destruct(&peer);
   GRPC_AUTH_CONTEXT_UNREF(ctx, "test");
 }
@@ -264,7 +264,7 @@
                    TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY,
                    expected_sans[i], &peer.properties[3 + i]) == TSI_OK);
   }
-  ctx = tsi_ssl_peer_to_auth_context(&peer);
+  ctx = grpc_ssl_peer_to_auth_context(&peer);
   GPR_ASSERT(ctx != nullptr);
   GPR_ASSERT(grpc_auth_context_peer_is_authenticated(ctx));
   GPR_ASSERT(check_identity(ctx, GRPC_X509_SAN_PROPERTY_NAME, expected_sans,
@@ -273,10 +273,10 @@
   GPR_ASSERT(check_x509_cn(ctx, expected_cn));
   GPR_ASSERT(check_x509_pem_cert(ctx, expected_pem_cert));
 
-  rpeer = tsi_shallow_peer_from_ssl_auth_context(ctx);
+  rpeer = grpc_shallow_peer_from_ssl_auth_context(ctx);
   GPR_ASSERT(check_ssl_peer_equivalence(&peer, &rpeer));
 
-  tsi_shallow_peer_destruct(&rpeer);
+  grpc_shallow_peer_destruct(&rpeer);
   tsi_peer_destruct(&peer);
   GRPC_AUTH_CONTEXT_UNREF(ctx, "test");
 }
@@ -310,7 +310,7 @@
                    TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY,
                    expected_sans[i], &peer.properties[5 + i]) == TSI_OK);
   }
-  ctx = tsi_ssl_peer_to_auth_context(&peer);
+  ctx = grpc_ssl_peer_to_auth_context(&peer);
   GPR_ASSERT(ctx != nullptr);
   GPR_ASSERT(grpc_auth_context_peer_is_authenticated(ctx));
   GPR_ASSERT(check_identity(ctx, GRPC_X509_SAN_PROPERTY_NAME, expected_sans,
@@ -319,10 +319,10 @@
   GPR_ASSERT(check_x509_cn(ctx, expected_cn));
   GPR_ASSERT(check_x509_pem_cert(ctx, expected_pem_cert));
 
-  rpeer = tsi_shallow_peer_from_ssl_auth_context(ctx);
+  rpeer = grpc_shallow_peer_from_ssl_auth_context(ctx);
   GPR_ASSERT(check_ssl_peer_equivalence(&peer, &rpeer));
 
-  tsi_shallow_peer_destruct(&rpeer);
+  grpc_shallow_peer_destruct(&rpeer);
   tsi_peer_destruct(&peer);
   GRPC_AUTH_CONTEXT_UNREF(ctx, "test");
 }
@@ -340,6 +340,26 @@
   return GRPC_SSL_ROOTS_OVERRIDE_FAIL_PERMANENTLY;
 }
 
+static void test_ipv6_address_san(void) {
+  const char* addresses[] = {
+      "2001:db8::1",     "fe80::abcd:ef65:4321%em0", "fd11:feed:beef:0:cafe::4",
+      "128.10.0.1:8888", "[2001:db8::1]:8080",       "[2001:db8::1%em1]:8080",
+  };
+  const char* san_ips[] = {
+      "2001:db8::1", "fe80::abcd:ef65:4321", "fd11:feed:beef:0:cafe::4",
+      "128.10.0.1",  "2001:db8::1",          "2001:db8::1",
+  };
+  tsi_peer peer;
+  GPR_ASSERT(tsi_construct_peer(1, &peer) == TSI_OK);
+  for (size_t i = 0; i < GPR_ARRAY_SIZE(addresses); i++) {
+    GPR_ASSERT(tsi_construct_string_peer_property_from_cstring(
+                   TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, san_ips[i],
+                   &peer.properties[0]) == TSI_OK);
+    GPR_ASSERT(grpc_ssl_host_matches_name(&peer, addresses[i]));
+    tsi_peer_property_destruct(&peer.properties[0]);
+  }
+  tsi_peer_destruct(&peer);
+}
 namespace grpc_core {
 namespace {
 
@@ -416,6 +436,7 @@
   test_cn_and_one_san_ssl_peer_to_auth_context();
   test_cn_and_multiple_sans_ssl_peer_to_auth_context();
   test_cn_and_multiple_sans_and_others_ssl_peer_to_auth_context();
+  test_ipv6_address_san();
   test_default_ssl_roots();
 
   grpc_shutdown();
diff --git a/test/core/surface/BUILD b/test/core/surface/BUILD
index e848dde..77df1cc 100644
--- a/test/core/surface/BUILD
+++ b/test/core/surface/BUILD
@@ -91,18 +91,6 @@
 )
 
 grpc_cc_test(
-    name = "grpc_invalid_channel_args_test",
-    srcs = ["invalid_channel_args_test.cc"],
-    language = "C++",
-    deps = [
-        "//:gpr",
-        "//:grpc",
-        "//test/core/util:gpr_test_util",
-        "//test/core/util:grpc_test_util",
-    ],
-)
-
-grpc_cc_test(
     name = "lame_client_test",
     srcs = ["lame_client_test.cc"],
     language = "C++",
diff --git a/test/core/surface/invalid_channel_args_test.cc b/test/core/surface/invalid_channel_args_test.cc
deleted file mode 100644
index 7c5f1f0..0000000
--- a/test/core/surface/invalid_channel_args_test.cc
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- *
- * Copyright 2015 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.
- *
- */
-
-#include <grpc/grpc.h>
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/string_util.h>
-#include "test/core/util/test_config.h"
-
-static char* g_last_log_error_message = nullptr;
-static const char* g_file_name = "channel.cc";
-
-static int ends_with(const char* src, const char* suffix) {
-  size_t src_len = strlen(src);
-  size_t suffix_len = strlen(suffix);
-  if (src_len < suffix_len) {
-    return 0;
-  }
-  return strcmp(src + src_len - suffix_len, suffix) == 0;
-}
-
-static void log_error_sink(gpr_log_func_args* args) {
-  if (args->severity == GPR_LOG_SEVERITY_ERROR &&
-      ends_with(args->file, g_file_name)) {
-    g_last_log_error_message = gpr_strdup(args->message);
-  }
-}
-
-static void verify_last_error(const char* message) {
-  if (message == nullptr) {
-    GPR_ASSERT(g_last_log_error_message == nullptr);
-    return;
-  }
-  GPR_ASSERT(strcmp(message, g_last_log_error_message) == 0);
-  gpr_free(g_last_log_error_message);
-  g_last_log_error_message = nullptr;
-}
-
-static char* compose_error_string(const char* key, const char* message) {
-  char* ret;
-  gpr_asprintf(&ret, "%s%s", key, message);
-  return ret;
-}
-
-static void one_test(grpc_channel_args* args, char* expected_error_message) {
-  grpc_channel* chan =
-      grpc_insecure_channel_create("nonexistant:54321", args, nullptr);
-  verify_last_error(expected_error_message);
-  gpr_free(expected_error_message);
-  grpc_channel_destroy(chan);
-}
-
-static void test_no_error_message(void) { one_test(nullptr, nullptr); }
-
-static void test_default_authority_type(void) {
-  grpc_arg client_arg;
-  grpc_channel_args client_args;
-  char* expected_error_message;
-
-  client_arg.type = GRPC_ARG_INTEGER;
-  client_arg.key = const_cast<char*>(GRPC_ARG_DEFAULT_AUTHORITY);
-  client_arg.value.integer = 0;
-
-  client_args.num_args = 1;
-  client_args.args = &client_arg;
-  expected_error_message = compose_error_string(
-      GRPC_ARG_DEFAULT_AUTHORITY, " ignored: it must be a string");
-  one_test(&client_args, expected_error_message);
-}
-
-static void test_ssl_name_override_type(void) {
-  grpc_arg client_arg;
-  grpc_channel_args client_args;
-  char* expected_error_message;
-
-  client_arg.type = GRPC_ARG_INTEGER;
-  client_arg.key = const_cast<char*>(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG);
-  client_arg.value.integer = 0;
-
-  client_args.num_args = 1;
-  client_args.args = &client_arg;
-  expected_error_message = compose_error_string(
-      GRPC_SSL_TARGET_NAME_OVERRIDE_ARG, " ignored: it must be a string");
-  one_test(&client_args, expected_error_message);
-}
-
-static void test_ssl_name_override_failed(void) {
-  grpc_arg client_arg[2];
-  grpc_channel_args client_args;
-  char* expected_error_message;
-
-  client_arg[0].type = GRPC_ARG_STRING;
-  client_arg[0].key = const_cast<char*>(GRPC_ARG_DEFAULT_AUTHORITY);
-  client_arg[0].value.string = const_cast<char*>("default");
-  client_arg[1].type = GRPC_ARG_STRING;
-  client_arg[1].key = const_cast<char*>(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG);
-  client_arg[1].value.string = const_cast<char*>("ssl");
-
-  client_args.num_args = 2;
-  client_args.args = client_arg;
-  expected_error_message =
-      compose_error_string(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG,
-                           " ignored: default host already set some other way");
-  one_test(&client_args, expected_error_message);
-}
-
-int main(int argc, char** argv) {
-  grpc_test_init(argc, argv);
-  grpc_init();
-  gpr_set_log_function(log_error_sink);
-
-  test_no_error_message();
-  test_default_authority_type();
-  test_ssl_name_override_type();
-  test_ssl_name_override_failed();
-
-  grpc_shutdown();
-
-  return 0;
-}
diff --git a/test/core/surface/public_headers_must_be_c89.c b/test/core/surface/public_headers_must_be_c89.c
index 866bee5..52a1b03 100644
--- a/test/core/surface/public_headers_must_be_c89.c
+++ b/test/core/surface/public_headers_must_be_c89.c
@@ -173,6 +173,12 @@
   printf("%lx", (unsigned long) grpc_server_add_secure_http2_port);
   printf("%lx", (unsigned long) grpc_call_set_credentials);
   printf("%lx", (unsigned long) grpc_server_credentials_set_auth_metadata_processor);
+  printf("%lx", (unsigned long) grpc_alts_credentials_client_options_create);
+  printf("%lx", (unsigned long) grpc_alts_credentials_server_options_create);
+  printf("%lx", (unsigned long) grpc_alts_credentials_client_options_add_target_service_account);
+  printf("%lx", (unsigned long) grpc_alts_credentials_options_destroy);
+  printf("%lx", (unsigned long) grpc_alts_credentials_create);
+  printf("%lx", (unsigned long) grpc_alts_server_credentials_create);
   printf("%lx", (unsigned long) grpc_raw_byte_buffer_create);
   printf("%lx", (unsigned long) grpc_raw_compressed_byte_buffer_create);
   printf("%lx", (unsigned long) grpc_byte_buffer_copy);
@@ -243,6 +249,7 @@
   printf("%lx", (unsigned long) gpr_cpu_current_cpu);
   printf("%lx", (unsigned long) gpr_log_severity_string);
   printf("%lx", (unsigned long) gpr_log);
+  printf("%lx", (unsigned long) gpr_should_log);
   printf("%lx", (unsigned long) gpr_log_message);
   printf("%lx", (unsigned long) gpr_set_log_verbosity);
   printf("%lx", (unsigned long) gpr_log_verbosity_init);
diff --git a/test/core/surface/server_chttp2_test.cc b/test/core/surface/server_chttp2_test.cc
index f0412d0..fd8ab9c 100644
--- a/test/core/surface/server_chttp2_test.cc
+++ b/test/core/surface/server_chttp2_test.cc
@@ -37,6 +37,8 @@
   grpc_server_destroy(server);
 }
 
+// GRPC_ARG_ALLOW_REUSEPORT isn't supported for custom servers
+#ifndef GRPC_UV
 void test_add_same_port_twice() {
   grpc_arg a;
   a.type = GRPC_ARG_INTEGER;
@@ -62,12 +64,15 @@
   grpc_server_destroy(server);
   grpc_completion_queue_destroy(cq);
 }
+#endif
 
 int main(int argc, char** argv) {
   grpc_test_init(argc, argv);
   grpc_init();
   test_unparsable_target();
+#ifndef GRPC_UV
   test_add_same_port_twice();
+#endif
   grpc_shutdown();
   return 0;
 }
diff --git a/test/core/surface/server_test.cc b/test/core/surface/server_test.cc
index 3b08efb..b4eabd8 100644
--- a/test/core/surface/server_test.cc
+++ b/test/core/surface/server_test.cc
@@ -69,6 +69,8 @@
   grpc_server_destroy(server);
 }
 
+// GRPC_ARG_ALLOW_REUSEPORT isn't supported for custom servers
+#ifndef GRPC_UV
 void test_bind_server_twice(void) {
   grpc_arg a;
   a.type = GRPC_ARG_INTEGER;
@@ -100,6 +102,7 @@
   grpc_completion_queue_destroy(cq);
   gpr_free(addr);
 }
+#endif
 
 void test_bind_server_to_addr(const char* host, bool secure) {
   int port = grpc_pick_unused_port_or_die();
@@ -149,7 +152,9 @@
   grpc_init();
   test_register_method_fail();
   test_request_call_on_no_server_cq();
+#ifndef GRPC_UV
   test_bind_server_twice();
+#endif
 
   static const char* addrs[] = {
       "::1", "127.0.0.1", "::ffff:127.0.0.1", "localhost", "0.0.0.0", "::",
diff --git a/test/core/tsi/alts/crypt/BUILD b/test/core/tsi/alts/crypt/BUILD
index b2fcb65..cf9dbca 100644
--- a/test/core/tsi/alts/crypt/BUILD
+++ b/test/core/tsi/alts/crypt/BUILD
@@ -16,7 +16,7 @@
 
 licenses(["notice"])  # Apache v2
 
-grpc_package(name = "crypt", visibility = "public")
+grpc_package(name = "test/core/tsi/alts/crypt", visibility = "public")
 
 grpc_cc_test(
     name = "alts_crypt_test",
diff --git a/test/core/tsi/alts/fake_handshaker/BUILD b/test/core/tsi/alts/fake_handshaker/BUILD
new file mode 100644
index 0000000..a09a046
--- /dev/null
+++ b/test/core/tsi/alts/fake_handshaker/BUILD
@@ -0,0 +1,57 @@
+# Copyright 2018 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.
+
+licenses(["notice"])  # Apache v2
+
+load("//bazel:grpc_build_system.bzl", "grpc_proto_library", "grpc_cc_library", "grpc_cc_binary", "grpc_package")
+
+grpc_package(name = "test/core/tsi/alts/fake_handshaker", visibility = "public")
+
+grpc_proto_library(
+    name = "transport_security_common_proto",
+    srcs = ["transport_security_common.proto"],
+    has_services = False,
+)
+
+grpc_proto_library(
+    name = "handshaker_proto",
+    srcs = ["handshaker.proto"],
+    has_services = True,
+    deps = [
+        "transport_security_common_proto",
+    ],
+)
+
+grpc_cc_library(
+    name = "fake_handshaker_lib",
+    testonly = True,
+    srcs = ["fake_handshaker_server.cc"],
+    language = "C++",
+    deps = [
+        "handshaker_proto",
+        "transport_security_common_proto",
+        "//:grpc++",
+        "//test/cpp/util:test_config",
+    ],
+)
+
+grpc_cc_binary(
+    name = "fake_handshaker_server",
+    testonly = True,
+    srcs = ["fake_handshaker_server.cc"],
+    language = "C++",
+    deps = [
+        "fake_handshaker_lib",
+    ],
+)
diff --git a/test/core/tsi/alts/fake_handshaker/fake_handshaker_server.cc b/test/core/tsi/alts/fake_handshaker/fake_handshaker_server.cc
new file mode 100644
index 0000000..f6a4791
--- /dev/null
+++ b/test/core/tsi/alts/fake_handshaker/fake_handshaker_server.cc
@@ -0,0 +1,268 @@
+/*
+ *
+ * Copyright 2018 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.
+ *
+ */
+
+#include <memory>
+#include <sstream>
+#include <string>
+
+#include <gflags/gflags.h>
+#include <grpc/grpc.h>
+#include <grpc/support/log.h>
+#include <grpcpp/impl/codegen/async_stream.h>
+#include <grpcpp/security/server_credentials.h>
+#include <grpcpp/server.h>
+#include <grpcpp/server_builder.h>
+#include <grpcpp/server_context.h>
+
+#include "test/core/tsi/alts/fake_handshaker/handshaker.grpc.pb.h"
+#include "test/core/tsi/alts/fake_handshaker/handshaker.pb.h"
+#include "test/core/tsi/alts/fake_handshaker/transport_security_common.pb.h"
+#include "test/cpp/util/test_config.h"
+
+DEFINE_int32(handshaker_port, 55056,
+             "TCP port on which the fake handshaker server listens to.");
+
+// Fake handshake messages.
+constexpr char kClientInitFrame[] = "ClientInit";
+constexpr char kServerFrame[] = "ServerInitAndFinished";
+constexpr char kClientFinishFrame[] = "ClientFinished";
+// Error messages.
+constexpr char kInvalidFrameError[] = "Invalid input frame.";
+constexpr char kWrongStateError[] = "Wrong handshake state.";
+
+namespace grpc {
+namespace gcp {
+
+// FakeHandshakeService implements a fake handshaker service using a fake key
+// exchange protocol. The fake key exchange protocol is a 3-message protocol:
+// - Client first sends ClientInit message to Server.
+// - Server then sends ServerInitAndFinished message back to Client.
+// - Client finally sends ClientFinished message to Server.
+// This fake handshaker service is intended for ALTS integration testing without
+// relying on real ALTS handshaker service inside GCE.
+// It is thread-safe.
+class FakeHandshakerService : public HandshakerService::Service {
+ public:
+  Status DoHandshake(
+      ServerContext* server_context,
+      ServerReaderWriter<HandshakerResp, HandshakerReq>* stream) override {
+    Status status;
+    HandshakerContext context;
+    HandshakerReq request;
+    HandshakerResp response;
+    gpr_log(GPR_DEBUG, "Start a new handshake.");
+    while (stream->Read(&request)) {
+      status = ProcessRequest(&context, request, &response);
+      if (!status.ok()) return WriteErrorResponse(stream, status);
+      stream->Write(response);
+      if (context.state == COMPLETED) return Status::OK;
+      request.Clear();
+    }
+    return Status::OK;
+  }
+
+ private:
+  // HandshakeState is used by fake handshaker server to keep track of client's
+  // handshake status. In the beginning of a handshake, the state is INITIAL.
+  // If start_client or start_server request is called, the state becomes at
+  // least STARTED. When the handshaker server produces the first fame, the
+  // state becomes SENT. After the handshaker server processes the final frame
+  // from the peer, the state becomes COMPLETED.
+  enum HandshakeState { INITIAL, STARTED, SENT, COMPLETED };
+
+  struct HandshakerContext {
+    bool is_client = true;
+    HandshakeState state = INITIAL;
+  };
+
+  Status ProcessRequest(HandshakerContext* context,
+                        const HandshakerReq& request,
+                        HandshakerResp* response) {
+    GPR_ASSERT(context != nullptr && response != nullptr);
+    response->Clear();
+    if (request.has_client_start()) {
+      gpr_log(GPR_DEBUG, "Process client start request.");
+      return ProcessClientStart(context, request.client_start(), response);
+    } else if (request.has_server_start()) {
+      gpr_log(GPR_DEBUG, "Process server start request.");
+      return ProcessServerStart(context, request.server_start(), response);
+    } else if (request.has_next()) {
+      gpr_log(GPR_DEBUG, "Process next request.");
+      return ProcessNext(context, request.next(), response);
+    }
+    return Status(StatusCode::INVALID_ARGUMENT, "Request is empty.");
+  }
+
+  Status ProcessClientStart(HandshakerContext* context,
+                            const StartClientHandshakeReq& request,
+                            HandshakerResp* response) {
+    GPR_ASSERT(context != nullptr && response != nullptr);
+    // Checks request.
+    if (context->state != INITIAL) {
+      return Status(StatusCode::FAILED_PRECONDITION, kWrongStateError);
+    }
+    if (request.application_protocols_size() == 0) {
+      return Status(StatusCode::INVALID_ARGUMENT,
+                    "At least one application protocol needed.");
+    }
+    if (request.record_protocols_size() == 0) {
+      return Status(StatusCode::INVALID_ARGUMENT,
+                    "At least one record protocol needed.");
+    }
+    // Sets response.
+    response->set_out_frames(kClientInitFrame);
+    response->set_bytes_consumed(0);
+    response->mutable_status()->set_code(StatusCode::OK);
+    // Updates handshaker context.
+    context->is_client = true;
+    context->state = SENT;
+    return Status::OK;
+  }
+
+  Status ProcessServerStart(HandshakerContext* context,
+                            const StartServerHandshakeReq& request,
+                            HandshakerResp* response) {
+    GPR_ASSERT(context != nullptr && response != nullptr);
+    // Checks request.
+    if (context->state != INITIAL) {
+      return Status(StatusCode::FAILED_PRECONDITION, kWrongStateError);
+    }
+    if (request.application_protocols_size() == 0) {
+      return Status(StatusCode::INVALID_ARGUMENT,
+                    "At least one application protocol needed.");
+    }
+    if (request.handshake_parameters().empty()) {
+      return Status(StatusCode::INVALID_ARGUMENT,
+                    "At least one set of handshake parameters needed.");
+    }
+    // Sets response.
+    if (request.in_bytes().empty()) {
+      // start_server request does not have in_bytes.
+      response->set_bytes_consumed(0);
+      context->state = STARTED;
+    } else {
+      // start_server request has in_bytes.
+      if (request.in_bytes() == kClientInitFrame) {
+        response->set_out_frames(kServerFrame);
+        response->set_bytes_consumed(strlen(kClientInitFrame));
+        context->state = SENT;
+      } else {
+        return Status(StatusCode::UNKNOWN, kInvalidFrameError);
+      }
+    }
+    response->mutable_status()->set_code(StatusCode::OK);
+    context->is_client = false;
+    return Status::OK;
+  }
+
+  Status ProcessNext(HandshakerContext* context,
+                     const NextHandshakeMessageReq& request,
+                     HandshakerResp* response) {
+    GPR_ASSERT(context != nullptr && response != nullptr);
+    if (context->is_client) {
+      // Processes next request on client side.
+      if (context->state != SENT) {
+        return Status(StatusCode::FAILED_PRECONDITION, kWrongStateError);
+      }
+      if (request.in_bytes() != kServerFrame) {
+        return Status(StatusCode::UNKNOWN, kInvalidFrameError);
+      }
+      response->set_out_frames(kClientFinishFrame);
+      response->set_bytes_consumed(strlen(kServerFrame));
+      context->state = COMPLETED;
+    } else {
+      // Processes next request on server side.
+      HandshakeState current_state = context->state;
+      if (current_state == STARTED) {
+        if (request.in_bytes() != kClientInitFrame) {
+          return Status(StatusCode::UNKNOWN, kInvalidFrameError);
+        }
+        response->set_out_frames(kServerFrame);
+        response->set_bytes_consumed(strlen(kClientInitFrame));
+        context->state = SENT;
+      } else if (current_state == SENT) {
+        // Client finish frame may be sent along with the first payload from the
+        // client, handshaker only consumes the client finish frame.
+        if (request.in_bytes().substr(0, strlen(kClientFinishFrame)) !=
+            kClientFinishFrame) {
+          return Status(StatusCode::UNKNOWN, kInvalidFrameError);
+        }
+        response->set_bytes_consumed(strlen(kClientFinishFrame));
+        context->state = COMPLETED;
+      } else {
+        return Status(StatusCode::FAILED_PRECONDITION, kWrongStateError);
+      }
+    }
+    // At this point, processing next request succeeded.
+    response->mutable_status()->set_code(StatusCode::OK);
+    if (context->state == COMPLETED) {
+      *response->mutable_result() = GetHandshakerResult();
+    }
+    return Status::OK;
+  }
+
+  Status WriteErrorResponse(
+      ServerReaderWriter<HandshakerResp, HandshakerReq>* stream,
+      const Status& status) {
+    GPR_ASSERT(!status.ok());
+    HandshakerResp response;
+    response.mutable_status()->set_code(status.error_code());
+    response.mutable_status()->set_details(status.error_message());
+    stream->Write(response);
+    return status;
+  }
+
+  HandshakerResult GetHandshakerResult() {
+    HandshakerResult result;
+    result.set_application_protocol("grpc");
+    result.set_record_protocol("ALTSRP_GCM_AES128_REKEY");
+    result.mutable_peer_identity()->set_service_account("peer_identity");
+    result.mutable_local_identity()->set_service_account("local_identity");
+    string key(1024, '\0');
+    result.set_key_data(key);
+    result.mutable_peer_rpc_versions()->mutable_max_rpc_version()->set_major(2);
+    result.mutable_peer_rpc_versions()->mutable_max_rpc_version()->set_minor(1);
+    result.mutable_peer_rpc_versions()->mutable_min_rpc_version()->set_major(2);
+    result.mutable_peer_rpc_versions()->mutable_min_rpc_version()->set_minor(1);
+    return result;
+  }
+};
+
+}  // namespace gcp
+}  // namespace grpc
+
+void RunServer() {
+  GPR_ASSERT(FLAGS_handshaker_port != 0);
+  std::ostringstream server_address;
+  server_address << "[::1]:" << FLAGS_handshaker_port;
+  grpc::gcp::FakeHandshakerService service;
+  grpc::ServerBuilder builder;
+  builder.AddListeningPort(server_address.str(),
+                           grpc::InsecureServerCredentials());
+  builder.RegisterService(&service);
+  std::unique_ptr<grpc::Server> server(builder.BuildAndStart());
+  gpr_log(GPR_INFO, "Fake handshaker server listening on %s",
+          server_address.str().c_str());
+  server->Wait();
+}
+
+int main(int argc, char** argv) {
+  grpc::testing::InitTest(&argc, &argv, true);
+  RunServer();
+  return 0;
+}
diff --git a/test/core/tsi/alts/fake_handshaker/handshaker.proto b/test/core/tsi/alts/fake_handshaker/handshaker.proto
new file mode 100644
index 0000000..8af9abf
--- /dev/null
+++ b/test/core/tsi/alts/fake_handshaker/handshaker.proto
@@ -0,0 +1,224 @@
+// Copyright 2018 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.
+
+syntax = "proto3";
+
+import "test/core/tsi/alts/fake_handshaker/transport_security_common.proto";
+
+package grpc.gcp;
+
+option java_package = "io.grpc.alts.internal";
+
+enum HandshakeProtocol {
+  // Default value.
+  HANDSHAKE_PROTOCOL_UNSPECIFIED = 0;
+
+  // TLS handshake protocol.
+  TLS = 1;
+
+  // Application Layer Transport Security handshake protocol.
+  ALTS = 2;
+}
+
+enum NetworkProtocol {
+  NETWORK_PROTOCOL_UNSPECIFIED = 0;
+  TCP = 1;
+  UDP = 2;
+}
+
+message Endpoint {
+  // IP address. It should contain an IPv4 or IPv6 string literal, e.g.
+  // "192.168.0.1" or "2001:db8::1".
+  string ip_address = 1;
+
+  // Port number.
+  int32 port = 2;
+
+  // Network protocol (e.g., TCP, UDP) associated with this endpoint.
+  NetworkProtocol protocol = 3;
+}
+
+message Identity {
+  oneof identity_oneof {
+    // Service account of a connection endpoint.
+    string service_account = 1;
+
+    // Hostname of a connection endpoint.
+    string hostname = 2;
+  }
+}
+
+message StartClientHandshakeReq {
+  // Handshake security protocol requested by the client.
+  HandshakeProtocol handshake_security_protocol = 1;
+
+  // The application protocols supported by the client, e.g., "h2" (for http2),
+  // "grpc".
+  repeated string application_protocols = 2;
+
+  // The record protocols supported by the client, e.g.,
+  // "ALTSRP_GCM_AES128".
+  repeated string record_protocols = 3;
+
+  // (Optional) Describes which server identities are acceptable by the client.
+  // If target identities are provided and none of them matches the peer
+  // identity of the server, handshake will fail.
+  repeated Identity target_identities = 4;
+
+  // (Optional) Application may specify a local identity. Otherwise, the
+  // handshaker chooses a default local identity.
+  Identity local_identity = 5;
+
+  // (Optional) Local endpoint information of the connection to the server,
+  // such as local IP address, port number, and network protocol.
+  Endpoint local_endpoint = 6;
+
+  // (Optional) Endpoint information of the remote server, such as IP address,
+  // port number, and network protocol.
+  Endpoint remote_endpoint = 7;
+
+  // (Optional) If target name is provided, a secure naming check is performed
+  // to verify that the peer authenticated identity is indeed authorized to run
+  // the target name.
+  string target_name = 8;
+
+  // (Optional) RPC protocol versions supported by the client.
+  RpcProtocolVersions rpc_versions = 9;
+}
+
+message ServerHandshakeParameters {
+  // The record protocols supported by the server, e.g.,
+  // "ALTSRP_GCM_AES128".
+  repeated string record_protocols = 1;
+
+  // (Optional) A list of local identities supported by the server, if
+  // specified. Otherwise, the handshaker chooses a default local identity.
+  repeated Identity local_identities = 2;
+}
+
+message StartServerHandshakeReq {
+  // The application protocols supported by the server, e.g., "h2" (for http2),
+  // "grpc".
+  repeated string application_protocols = 1;
+
+  // Handshake parameters (record protocols and local identities supported by
+  // the server) mapped by the handshake protocol. Each handshake security
+  // protocol (e.g., TLS or ALTS) has its own set of record protocols and local
+  // identities. Since protobuf does not support enum as key to the map, the key
+  // to handshake_parameters is the integer value of HandshakeProtocol enum.
+  map<int32, ServerHandshakeParameters> handshake_parameters = 2;
+
+  // Bytes in out_frames returned from the peer's HandshakerResp. It is possible
+  // that the peer's out_frames are split into multiple HandshakReq messages.
+  bytes in_bytes = 3;
+
+  // (Optional) Local endpoint information of the connection to the client,
+  // such as local IP address, port number, and network protocol.
+  Endpoint local_endpoint = 4;
+
+  // (Optional) Endpoint information of the remote client, such as IP address,
+  // port number, and network protocol.
+  Endpoint remote_endpoint = 5;
+
+  // (Optional) RPC protocol versions supported by the server.
+  RpcProtocolVersions rpc_versions = 6;
+}
+
+message NextHandshakeMessageReq {
+  // Bytes in out_frames returned from the peer's HandshakerResp. It is possible
+  // that the peer's out_frames are split into multiple NextHandshakerMessageReq
+  // messages.
+  bytes in_bytes = 1;
+}
+
+message HandshakerReq {
+  oneof req_oneof {
+    // The start client handshake request message.
+    StartClientHandshakeReq client_start = 1;
+
+    // The start server handshake request message.
+    StartServerHandshakeReq server_start = 2;
+
+    // The next handshake request message.
+    NextHandshakeMessageReq next = 3;
+  }
+}
+
+message HandshakerResult {
+  // The application protocol negotiated for this connection.
+  string application_protocol = 1;
+
+  // The record protocol negotiated for this connection.
+  string record_protocol = 2;
+
+  // Cryptographic key data. The key data may be more than the key length
+  // required for the record protocol, thus the client of the handshaker
+  // service needs to truncate the key data into the right key length.
+  bytes key_data = 3;
+
+  // The authenticated identity of the peer.
+  Identity peer_identity = 4;
+
+  // The local identity used in the handshake.
+  Identity local_identity = 5;
+
+  // Indicate whether the handshaker service client should keep the channel
+  // between the handshaker service open, e.g., in order to handle
+  // post-handshake messages in the future.
+  bool keep_channel_open = 6;
+
+  // The RPC protocol versions supported by the peer.
+  RpcProtocolVersions peer_rpc_versions = 7;
+}
+
+message HandshakerStatus {
+  // The status code. This could be the gRPC status code.
+  uint32 code = 1;
+
+  // The status details.
+  string details = 2;
+}
+
+message HandshakerResp {
+  // Frames to be given to the peer for the NextHandshakeMessageReq. May be
+  // empty if no out_frames have to be sent to the peer or if in_bytes in the
+  // HandshakerReq are incomplete. All the non-empty out frames must be sent to
+  // the peer even if the handshaker status is not OK as these frames may
+  // contain the alert frames.
+  bytes out_frames = 1;
+
+  // Number of bytes in the in_bytes consumed by the handshaker. It is possible
+  // that part of in_bytes in HandshakerReq was unrelated to the handshake
+  // process.
+  uint32 bytes_consumed = 2;
+
+  // This is set iff the handshake was successful. out_frames may still be set
+  // to frames that needs to be forwarded to the peer.
+  HandshakerResult result = 3;
+
+  // Status of the handshaker.
+  HandshakerStatus status = 4;
+}
+
+service HandshakerService {
+  // Handshaker service accepts a stream of handshaker request, returning a
+  // stream of handshaker response. Client is expected to send exactly one
+  // message with either client_start or server_start followed by one or more
+  // messages with next. Each time client sends a request, the handshaker
+  // service expects to respond. Client does not have to wait for service's
+  // response before sending next request.
+  rpc DoHandshake(stream HandshakerReq)
+      returns (stream HandshakerResp) {
+  }
+}
diff --git a/test/core/tsi/alts/fake_handshaker/transport_security_common.proto b/test/core/tsi/alts/fake_handshaker/transport_security_common.proto
new file mode 100644
index 0000000..d0f861e
--- /dev/null
+++ b/test/core/tsi/alts/fake_handshaker/transport_security_common.proto
@@ -0,0 +1,40 @@
+// Copyright 2018 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.
+
+syntax = "proto3";
+
+package grpc.gcp;
+
+option java_package = "io.grpc.alts.internal";
+
+// The security level of the created channel. The list is sorted in increasing
+// level of security. This order must always be maintained.
+enum SecurityLevel {
+  SECURITY_NONE = 0;
+  INTEGRITY_ONLY = 1;
+  INTEGRITY_AND_PRIVACY = 2;
+}
+
+// Max and min supported RPC protocol versions.
+message RpcProtocolVersions {
+  // RPC version contains a major version and a minor version.
+  message Version {
+    uint32 major = 1;
+    uint32 minor = 2;
+  }
+  // Maximum supported RPC version.
+  Version max_rpc_version = 1;
+  // Minimum supported RPC version.
+  Version min_rpc_version = 2;
+}
diff --git a/test/core/tsi/alts/frame_protector/BUILD b/test/core/tsi/alts/frame_protector/BUILD
index 94c2ab3..dd1966b 100644
--- a/test/core/tsi/alts/frame_protector/BUILD
+++ b/test/core/tsi/alts/frame_protector/BUILD
@@ -16,7 +16,7 @@
 
 licenses(["notice"])  # Apache v2
 
-grpc_package(name = "frame_protector")
+grpc_package(name = "test/core/tsi/alts/frame_protector")
 
 grpc_cc_test(
     name = "alts_counter_test",
diff --git a/test/core/tsi/alts/handshaker/BUILD b/test/core/tsi/alts/handshaker/BUILD
index fc2c395..8097427 100644
--- a/test/core/tsi/alts/handshaker/BUILD
+++ b/test/core/tsi/alts/handshaker/BUILD
@@ -16,7 +16,7 @@
 
 licenses(["notice"])  # Apache v2 
          
-grpc_package(name = "handshaker")
+grpc_package(name = "test/core/tsi/alts/handshaker")
          
 grpc_cc_library(
     name = "alts_handshaker_service_api_test_lib",
diff --git a/test/core/tsi/alts/handshaker/alts_handshaker_client_test.cc b/test/core/tsi/alts/handshaker/alts_handshaker_client_test.cc
index 7072be6..c8d88aa 100644
--- a/test/core/tsi/alts/handshaker/alts_handshaker_client_test.cc
+++ b/test/core/tsi/alts/handshaker/alts_handshaker_client_test.cc
@@ -54,11 +54,9 @@
                          : grpc_alts_credentials_server_options_create();
   if (is_client) {
     grpc_alts_credentials_client_options_add_target_service_account(
-        reinterpret_cast<grpc_alts_credentials_client_options*>(e->options),
-        ALTS_HANDSHAKER_CLIENT_TEST_TARGET_SERVICE_ACCOUNT1);
+        e->options, ALTS_HANDSHAKER_CLIENT_TEST_TARGET_SERVICE_ACCOUNT1);
     grpc_alts_credentials_client_options_add_target_service_account(
-        reinterpret_cast<grpc_alts_credentials_client_options*>(e->options),
-        ALTS_HANDSHAKER_CLIENT_TEST_TARGET_SERVICE_ACCOUNT2);
+        e->options, ALTS_HANDSHAKER_CLIENT_TEST_TARGET_SERVICE_ACCOUNT2);
   }
   grpc_gcp_rpc_protocol_versions* versions = &e->options->rpc_versions;
   GPR_ASSERT(grpc_gcp_rpc_protocol_versions_set_max(
@@ -328,6 +326,9 @@
   GPR_ASSERT(alts_handshaker_client_next(nullptr, event, &config->out_frame) ==
              TSI_INVALID_ARGUMENT);
 
+  /* Check shutdown. */
+  alts_handshaker_client_shutdown(nullptr);
+
   /* Cleanup. */
   alts_tsi_event_destroy(event);
   destroy_config(config);
diff --git a/test/core/tsi/alts/handshaker/alts_tsi_handshaker_test.cc b/test/core/tsi/alts/handshaker/alts_tsi_handshaker_test.cc
index 95724f8..85a5811 100644
--- a/test/core/tsi/alts/handshaker/alts_tsi_handshaker_test.cc
+++ b/test/core/tsi/alts/handshaker/alts_tsi_handshaker_test.cc
@@ -330,6 +330,8 @@
   return TSI_OK;
 }
 
+static void mock_shutdown(alts_handshaker_client* self) {}
+
 static tsi_result mock_server_start(alts_handshaker_client* self,
                                     alts_tsi_event* event,
                                     grpc_slice* bytes_received) {
@@ -400,7 +402,8 @@
 static void mock_destruct(alts_handshaker_client* client) {}
 
 static const alts_handshaker_client_vtable vtable = {
-    mock_client_start, mock_server_start, mock_next, mock_destruct};
+    mock_client_start, mock_server_start, mock_next, mock_shutdown,
+    mock_destruct};
 
 static alts_handshaker_client* alts_mock_handshaker_client_create(
     bool used_for_success_test) {
@@ -442,6 +445,16 @@
   tsi_handshaker_destroy(handshaker);
 }
 
+static void check_handshaker_shutdown_invalid_input() {
+  /* Initialization. */
+  tsi_handshaker* handshaker = create_test_handshaker(
+      false /* used_for_success_test */, true /* is_client */);
+  /* Check nullptr handshaker. */
+  tsi_handshaker_shutdown(nullptr);
+  /* Cleanup. */
+  tsi_handshaker_destroy(handshaker);
+}
+
 static void check_handshaker_next_success() {
   /**
    * Create handshakers for which internal mock client is going to do
@@ -480,6 +493,33 @@
   tsi_handshaker_destroy(client_handshaker);
 }
 
+static void check_handshaker_next_with_shutdown() {
+  /* Initialization. */
+  tsi_handshaker* handshaker = create_test_handshaker(
+      true /* used_for_success_test */, true /* is_client*/);
+  /* next(success) -- shutdown(success) -- next (fail) */
+  GPR_ASSERT(tsi_handshaker_next(handshaker, nullptr, 0, nullptr, nullptr,
+                                 nullptr, on_client_start_success_cb,
+                                 nullptr) == TSI_ASYNC);
+  wait(&tsi_to_caller_notification);
+  tsi_handshaker_shutdown(handshaker);
+  GPR_ASSERT(tsi_handshaker_next(
+                 handshaker,
+                 (const unsigned char*)ALTS_TSI_HANDSHAKER_TEST_RECV_BYTES,
+                 strlen(ALTS_TSI_HANDSHAKER_TEST_RECV_BYTES), nullptr, nullptr,
+                 nullptr, on_client_next_success_cb,
+                 nullptr) == TSI_HANDSHAKE_SHUTDOWN);
+  /* Cleanup. */
+  tsi_handshaker_destroy(handshaker);
+}
+
+static void check_handle_response_with_shutdown(void* unused) {
+  /* Client start. */
+  wait(&caller_to_tsi_notification);
+  alts_tsi_event_dispatch_to_handshaker(client_start_event, true /* is_ok */);
+  alts_tsi_event_destroy(client_start_event);
+}
+
 static void check_handshaker_next_failure() {
   /**
    * Create handshakers for which internal mock client is always going to fail.
@@ -647,6 +687,49 @@
   tsi_handshaker_destroy(handshaker);
 }
 
+static void on_shutdown_resp_cb(tsi_result status, void* user_data,
+                                const unsigned char* bytes_to_send,
+                                size_t bytes_to_send_size,
+                                tsi_handshaker_result* result) {
+  GPR_ASSERT(status == TSI_HANDSHAKE_SHUTDOWN);
+  GPR_ASSERT(user_data == nullptr);
+  GPR_ASSERT(bytes_to_send == nullptr);
+  GPR_ASSERT(bytes_to_send_size == 0);
+  GPR_ASSERT(result == nullptr);
+}
+
+static void check_handle_response_after_shutdown() {
+  tsi_handshaker* handshaker = create_test_handshaker(
+      true /* used_for_success_test */, true /* is_client */);
+  alts_tsi_handshaker* alts_handshaker =
+      reinterpret_cast<alts_tsi_handshaker*>(handshaker);
+  /* Tests. */
+  tsi_handshaker_shutdown(handshaker);
+  grpc_byte_buffer* recv_buffer = generate_handshaker_response(CLIENT_START);
+  alts_tsi_handshaker_handle_response(alts_handshaker, recv_buffer,
+                                      GRPC_STATUS_OK, nullptr,
+                                      on_shutdown_resp_cb, nullptr, true);
+  grpc_byte_buffer_destroy(recv_buffer);
+  /* Cleanup. */
+  tsi_handshaker_destroy(handshaker);
+}
+
+void check_handshaker_next_fails_after_shutdown() {
+  /* Initialization. */
+  notification_init(&caller_to_tsi_notification);
+  notification_init(&tsi_to_caller_notification);
+  client_start_event = nullptr;
+  /* Tests. */
+  grpc_core::Thread thd("alts_tsi_handshaker_test",
+                        &check_handle_response_with_shutdown, nullptr);
+  thd.Start();
+  check_handshaker_next_with_shutdown();
+  thd.Join();
+  /* Cleanup. */
+  notification_destroy(&caller_to_tsi_notification);
+  notification_destroy(&tsi_to_caller_notification);
+}
+
 void check_handshaker_success() {
   /* Initialization. */
   notification_init(&caller_to_tsi_notification);
@@ -672,10 +755,13 @@
   /* Tests. */
   check_handshaker_success();
   check_handshaker_next_invalid_input();
+  check_handshaker_shutdown_invalid_input();
+  check_handshaker_next_fails_after_shutdown();
   check_handshaker_next_failure();
   check_handle_response_invalid_input();
   check_handle_response_invalid_resp();
   check_handle_response_failure();
+  check_handle_response_after_shutdown();
   /* Cleanup. */
   grpc_shutdown();
   return 0;
diff --git a/test/core/tsi/alts/zero_copy_frame_protector/BUILD b/test/core/tsi/alts/zero_copy_frame_protector/BUILD
index 4c6fb91..2b41dae 100644
--- a/test/core/tsi/alts/zero_copy_frame_protector/BUILD
+++ b/test/core/tsi/alts/zero_copy_frame_protector/BUILD
@@ -16,7 +16,7 @@
 
 licenses(["notice"])  # Apache v2
 
-grpc_package(name = "zero_copy_frame_protector")
+grpc_package(name = "test/core/tsi/alts/zero_copy_frame_protector")
 
 grpc_cc_test(
     name = "alts_grpc_record_protocol_test",
diff --git a/test/core/tsi/ssl_session_cache_test.cc b/test/core/tsi/ssl_session_cache_test.cc
index 72df0e5..c86cefb 100644
--- a/test/core/tsi/ssl_session_cache_test.cc
+++ b/test/core/tsi/ssl_session_cache_test.cc
@@ -88,7 +88,6 @@
   // Verify session initial state.
   {
     tsi::SslSessionPtr tmp_sess = tracker.NewSession(1);
-    EXPECT_EQ(tmp_sess->references, 1);
     EXPECT_TRUE(tracker.IsAlive(1));
     EXPECT_EQ(tracker.AliveCount(), 1);
   }
diff --git a/test/core/tsi/ssl_transport_security_test.cc b/test/core/tsi/ssl_transport_security_test.cc
index 88f1abc..b477904 100644
--- a/test/core/tsi/ssl_transport_security_test.cc
+++ b/test/core/tsi/ssl_transport_security_test.cc
@@ -24,7 +24,6 @@
 #include "src/core/lib/security/security_connector/security_connector.h"
 #include "src/core/tsi/ssl_transport_security.h"
 #include "src/core/tsi/transport_security.h"
-#include "src/core/tsi/transport_security_adapter.h"
 #include "src/core/tsi/transport_security_interface.h"
 #include "test/core/tsi/transport_security_test_lib.h"
 #include "test/core/util/test_config.h"
@@ -34,6 +33,10 @@
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
 
+extern "C" {
+#include <openssl/crypto.h>
+}
+
 #define SSL_TSI_TEST_ALPN1 "foo"
 #define SSL_TSI_TEST_ALPN2 "toto"
 #define SSL_TSI_TEST_ALPN3 "baz"
@@ -42,6 +45,14 @@
 #define SSL_TSI_TEST_BAD_SERVER_KEY_CERT_PAIRS_NUM 1
 #define SSL_TSI_TEST_CREDENTIALS_DIR "src/core/tsi/test_creds/"
 
+// OpenSSL 1.1 uses AES256 for encryption session ticket by default so specify
+// different STEK size.
+#if OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(OPENSSL_IS_BORINGSSL)
+const size_t kSessionTicketEncryptionKeySize = 80;
+#else
+const size_t kSessionTicketEncryptionKeySize = 48;
+#endif
+
 typedef enum AlpnMode {
   NO_ALPN,
   ALPN_CLIENT_NO_SERVER,
@@ -152,19 +163,13 @@
                  &server_options, &ssl_fixture->server_handshaker_factory) ==
              TSI_OK);
   /* Create server and client handshakers. */
-  tsi_handshaker* client_handshaker = nullptr;
   GPR_ASSERT(tsi_ssl_client_handshaker_factory_create_handshaker(
                  ssl_fixture->client_handshaker_factory,
                  ssl_fixture->server_name_indication,
-                 &client_handshaker) == TSI_OK);
-  ssl_fixture->base.client_handshaker =
-      tsi_create_adapter_handshaker(client_handshaker);
-  tsi_handshaker* server_handshaker = nullptr;
+                 &ssl_fixture->base.client_handshaker) == TSI_OK);
   GPR_ASSERT(tsi_ssl_server_handshaker_factory_create_handshaker(
-                 ssl_fixture->server_handshaker_factory, &server_handshaker) ==
-             TSI_OK);
-  ssl_fixture->base.server_handshaker =
-      tsi_create_adapter_handshaker(server_handshaker);
+                 ssl_fixture->server_handshaker_factory,
+                 &ssl_fixture->base.server_handshaker) == TSI_OK);
 }
 
 static void check_alpn(ssl_tsi_test_fixture* ssl_fixture,
@@ -624,7 +629,7 @@
 
 void ssl_tsi_test_do_handshake_session_cache() {
   tsi_ssl_session_cache* session_cache = tsi_ssl_session_cache_create_lru(16);
-  char session_ticket_key[48];
+  char session_ticket_key[kSessionTicketEncryptionKeySize];
   auto do_handshake = [&session_ticket_key,
                        &session_cache](bool session_reused) {
     tsi_test_fixture* fixture = ssl_tsi_test_fixture_create();
@@ -633,22 +638,22 @@
     ssl_fixture->server_name_indication =
         const_cast<char*>("waterzooi.test.google.be");
     ssl_fixture->session_ticket_key = session_ticket_key;
-    ssl_fixture->session_ticket_key_size = 48;
+    ssl_fixture->session_ticket_key_size = sizeof(session_ticket_key);
     tsi_ssl_session_cache_ref(session_cache);
     ssl_fixture->session_cache = session_cache;
     ssl_fixture->session_reused = session_reused;
     tsi_test_do_round_trip(&ssl_fixture->base);
     tsi_test_fixture_destroy(fixture);
   };
-  memset(session_ticket_key, 'a', 48);
+  memset(session_ticket_key, 'a', sizeof(session_ticket_key));
   do_handshake(false);
   do_handshake(true);
   do_handshake(true);
   // Changing session_ticket_key on server invalidates ticket.
-  memset(session_ticket_key, 'b', 48);
+  memset(session_ticket_key, 'b', sizeof(session_ticket_key));
   do_handshake(false);
   do_handshake(true);
-  memset(session_ticket_key, 'c', 48);
+  memset(session_ticket_key, 'c', sizeof(session_ticket_key));
   do_handshake(false);
   do_handshake(true);
   tsi_ssl_session_cache_unref(session_cache);
diff --git a/test/core/util/BUILD b/test/core/util/BUILD
index 886cfdd..f52570c 100644
--- a/test/core/util/BUILD
+++ b/test/core/util/BUILD
@@ -52,6 +52,7 @@
     name = "grpc_test_util_base",
     srcs = [
         "cmdline.cc",
+        "fuzzer_util.cc",
         "grpc_profiler.cc",
         "histogram.cc",
         "mock_endpoint.cc",
@@ -70,6 +71,7 @@
     ],
     hdrs = [
         "cmdline.h",
+        "fuzzer_util.h",
         "grpc_profiler.h",
         "histogram.h",
         "mock_endpoint.h",
diff --git a/test/core/util/fuzzer_corpus_test.cc b/test/core/util/fuzzer_corpus_test.cc
index 18bc0ad..ebf1913 100644
--- a/test/core/util/fuzzer_corpus_test.cc
+++ b/test/core/util/fuzzer_corpus_test.cc
@@ -20,6 +20,7 @@
 
 #include <dirent.h>
 #include <gflags/gflags.h>
+#include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <gtest/gtest.h>
 #include <stdio.h>
@@ -91,6 +92,7 @@
           perror("Couldn't open the directory");
           abort();
         }
+        gpr_free(test_srcdir);
       }
     }
   }
diff --git a/test/core/util/fuzzer_util.cc b/test/core/util/fuzzer_util.cc
new file mode 100644
index 0000000..29c9b88
--- /dev/null
+++ b/test/core/util/fuzzer_util.cc
@@ -0,0 +1,82 @@
+/*
+ *
+ * Copyright 2018 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.
+ *
+ */
+
+#include "test/core/util/fuzzer_util.h"
+
+#include <grpc/support/alloc.h>
+
+#include "src/core/lib/gpr/useful.h"
+
+namespace grpc_core {
+namespace testing {
+
+uint8_t grpc_fuzzer_get_next_byte(input_stream* inp) {
+  if (inp->cur == inp->end) {
+    return 0;
+  }
+  return *inp->cur++;
+}
+
+char* grpc_fuzzer_get_next_string(input_stream* inp, bool* special) {
+  char* str = nullptr;
+  size_t cap = 0;
+  size_t sz = 0;
+  char c;
+  do {
+    if (cap == sz) {
+      cap = GPR_MAX(3 * cap / 2, cap + 8);
+      str = static_cast<char*>(gpr_realloc(str, cap));
+    }
+    c = static_cast<char>(grpc_fuzzer_get_next_byte(inp));
+    str[sz++] = c;
+  } while (c != 0 && c != 1);
+  if (special != nullptr) {
+    *special = (c == 1);
+  }
+  if (c == 1) {
+    str[sz - 1] = 0;
+  }
+  return str;
+}
+
+uint32_t grpc_fuzzer_get_next_uint32(input_stream* inp) {
+  uint8_t b = grpc_fuzzer_get_next_byte(inp);
+  uint32_t x = b & 0x7f;
+  if (b & 0x80) {
+    x <<= 7;
+    b = grpc_fuzzer_get_next_byte(inp);
+    x |= b & 0x7f;
+    if (b & 0x80) {
+      x <<= 7;
+      b = grpc_fuzzer_get_next_byte(inp);
+      x |= b & 0x7f;
+      if (b & 0x80) {
+        x <<= 7;
+        b = grpc_fuzzer_get_next_byte(inp);
+        x |= b & 0x7f;
+        if (b & 0x80) {
+          x = (x << 4) | (grpc_fuzzer_get_next_byte(inp) & 0x0f);
+        }
+      }
+    }
+  }
+  return x;
+}
+
+}  // namespace testing
+}  // namespace grpc_core
diff --git a/test/core/util/fuzzer_util.h b/test/core/util/fuzzer_util.h
new file mode 100644
index 0000000..0e93839
--- /dev/null
+++ b/test/core/util/fuzzer_util.h
@@ -0,0 +1,49 @@
+/*
+ *
+ * Copyright 2018 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_TEST_CORE_UTIL_FUZZER_UTIL_H
+#define GRPC_TEST_CORE_UTIL_FUZZER_UTIL_H
+
+#include <stdint.h>
+
+namespace grpc_core {
+
+namespace testing {
+
+// Main struct for input_stream. It allows easy access to input
+// bytes, and allows reading a little past the end(avoiding
+// needing to check everywhere).
+typedef struct {
+  const uint8_t* cur;
+  const uint8_t* end;
+} input_stream;
+
+// get a byte from an input stream.
+uint8_t grpc_fuzzer_get_next_byte(input_stream* inp);
+
+// get a string and boolean values (if special is not null) from an input
+// stream.
+char* grpc_fuzzer_get_next_string(input_stream* inp, bool* special);
+
+// get a uint32 value from an input stream.
+uint32_t grpc_fuzzer_get_next_uint32(input_stream* inp);
+
+}  // namespace testing
+}  // namespace grpc_core
+
+#endif /* GRPC_TEST_CORE_UTIL_FUZZER_UTIL_H */
diff --git a/test/cpp/cocoapods/generic/generic.mm b/test/cpp/cocoapods/generic/generic.mm
index 6e65176..6740e9c 100644
--- a/test/cpp/cocoapods/generic/generic.mm
+++ b/test/cpp/cocoapods/generic/generic.mm
@@ -20,6 +20,8 @@
 
 #include <sstream>
 
+#include <grpc/grpc.h>
+#include <grpc/support/time.h>
 #include <grpcpp/channel.h>
 #include <grpcpp/client_context.h>
 #include <grpcpp/create_channel.h>
@@ -29,8 +31,6 @@
 #include <grpcpp/server_builder.h>
 #include <grpcpp/server_context.h>
 #include <grpcpp/support/slice.h>
-#include <grpc/grpc.h>
-#include <grpc/support/time.h>
 
 #include "src/core/lib/gprpp/thd.h"
 #include "test/core/util/port.h"
@@ -55,8 +55,7 @@
   cursor = GRPC_SLICE_START_PTR(out);
 
   for (i = 0; i < nslices; i++) {
-    memcpy(cursor, GRPC_SLICE_START_PTR(slices[i]),
-           GRPC_SLICE_LENGTH(slices[i]));
+    memcpy(cursor, GRPC_SLICE_START_PTR(slices[i]), GRPC_SLICE_LENGTH(slices[i]));
     cursor += GRPC_SLICE_LENGTH(slices[i]);
   }
 
@@ -74,16 +73,14 @@
   }
   grpc_slice a = merge_slices(c_slices, slices.size());
   grpc_slice b = grpc_slice_from_copied_string(str);
-  res =
-      (GRPC_SLICE_LENGTH(a) == GRPC_SLICE_LENGTH(b)) &&
-      (0 == memcmp(GRPC_SLICE_START_PTR(a), GRPC_SLICE_START_PTR(b),
-                   GRPC_SLICE_LENGTH(a)));
+  res = (GRPC_SLICE_LENGTH(a) == GRPC_SLICE_LENGTH(b)) &&
+        (0 == memcmp(GRPC_SLICE_START_PTR(a), GRPC_SLICE_START_PTR(b), GRPC_SLICE_LENGTH(a)));
   grpc_slice_unref(a);
   grpc_slice_unref(b);
   for (int i = 0; i < slices.size(); i++) {
     grpc_slice_unref(c_slices[i]);
   }
-  delete [] c_slices;
+  delete[] c_slices;
 
   return res;
 }
@@ -102,9 +99,7 @@
   std::ostringstream server_address_;
 }
 
-- (void)verify_ok:(grpc::CompletionQueue*)cq
-                i:(int)i
-        expect_ok:(bool)expect_ok {
+- (void)verify_ok:(grpc::CompletionQueue*)cq i:(int)i expect_ok:(bool)expect_ok {
   bool ok;
   void* got_tag;
   XCTAssertTrue(cq->Next(&got_tag, &ok));
@@ -112,10 +107,18 @@
   XCTAssertEqual(tag(i), got_tag);
 }
 
-- (void)server_ok:(int)i { [self verify_ok:srv_cq_.get() i:i expect_ok:true]; }
-- (void)client_ok:(int)i { [self verify_ok:&cli_cq_ i:i expect_ok:true]; }
-- (void)server_fail:(int)i { [self verify_ok:srv_cq_.get() i:i expect_ok:false]; }
-- (void)client_fail:(int)i { [self verify_ok:&cli_cq_ i:i expect_ok:false]; }
+- (void)server_ok:(int)i {
+  [self verify_ok:srv_cq_.get() i:i expect_ok:true];
+}
+- (void)client_ok:(int)i {
+  [self verify_ok:&cli_cq_ i:i expect_ok:true];
+}
+- (void)server_fail:(int)i {
+  [self verify_ok:srv_cq_.get() i:i expect_ok:false];
+}
+- (void)client_fail:(int)i {
+  [self verify_ok:&cli_cq_ i:i expect_ok:false];
+}
 
 - (void)setUp {
   [super setUp];
@@ -125,8 +128,7 @@
   server_address_ << server_host_ << ":" << port;
   // Setup server
   ServerBuilder builder;
-  builder.AddListeningPort(server_address_.str(),
-                           InsecureServerCredentials());
+  builder.AddListeningPort(server_address_.str(), InsecureServerCredentials());
   builder.RegisterAsyncGenericService(&generic_service_);
   // Include a second call to RegisterAsyncGenericService to make sure that
   // we get an error in the log, since it is not allowed to have 2 async
@@ -137,14 +139,17 @@
 }
 
 - (void)tearDown {
-  // Put teardown code here. This method is called after the invocation of each test method in the class.
+  // Put teardown code here. This method is called after the invocation of each test method in the
+  // class.
   server_->Shutdown();
   void* ignored_tag;
   bool ignored_ok;
   cli_cq_.Shutdown();
   srv_cq_->Shutdown();
-  while (cli_cq_.Next(&ignored_tag, &ignored_ok));
-  while (srv_cq_->Next(&ignored_tag, &ignored_ok));
+  while (cli_cq_.Next(&ignored_tag, &ignored_ok))
+    ;
+  while (srv_cq_->Next(&ignored_tag, &ignored_ok))
+    ;
   [super tearDown];
 }
 
@@ -156,11 +161,9 @@
 
 - (void)SendRpc:(int)num_rpcs {
   [self SendRpc:num_rpcs check_deadline:false deadline:gpr_inf_future(GPR_CLOCK_MONOTONIC)];
- }
+}
 
-- (void)SendRpc:(int)num_rpcs
- check_deadline:(bool)check_deadline
-       deadline:(gpr_timespec)deadline {
+- (void)SendRpc:(int)num_rpcs check_deadline:(bool)check_deadline deadline:(gpr_timespec)deadline {
   const grpc::string kMethodName("/grpc.cpp.test.util.EchoTestService/Echo");
   for (int i = 0; i < num_rpcs; i++) {
     Status recv_status;
@@ -177,7 +180,7 @@
     }
 
     std::unique_ptr<GenericClientAsyncReaderWriter> call =
-    generic_stub_->Call(&cli_ctx, kMethodName, &cli_cq_, tag(1));
+        generic_stub_->Call(&cli_ctx, kMethodName, &cli_cq_, tag(1));
     [self client_ok:1];
     Slice send_slice = Slice("hello world", 11);
     std::unique_ptr<ByteBuffer> send_buffer =
@@ -189,8 +192,7 @@
     call->WritesDone(tag(3));
     [self client_ok:3];
 
-    generic_service_.RequestCall(&srv_ctx, &stream, srv_cq_.get(),
-                                 srv_cq_.get(), tag(4));
+    generic_service_.RequestCall(&srv_ctx, &stream, srv_cq_.get(), srv_cq_.get(), tag(4));
 
     [self verify_ok:srv_cq_.get() i:4 expect_ok:true];
     XCTAssertEqual(server_host_, srv_ctx.host().substr(0, server_host_.length()));
@@ -198,7 +200,7 @@
 
     if (check_deadline) {
       XCTAssertTrue(gpr_time_similar(deadline, srv_ctx.raw_deadline(),
-                                   gpr_time_from_millis(1000, GPR_TIMESPAN)));
+                                     gpr_time_from_millis(1000, GPR_TIMESPAN)));
     }
 
     ByteBuffer recv_buffer;
@@ -241,4 +243,3 @@
 }
 
 @end
-
diff --git a/test/cpp/cocoapods/test/server_context_test_spouse_test.mm b/test/cpp/cocoapods/test/server_context_test_spouse_test.mm
index 7cb1b36..59f60e3 100644
--- a/test/cpp/cocoapods/test/server_context_test_spouse_test.mm
+++ b/test/cpp/cocoapods/test/server_context_test_spouse_test.mm
@@ -18,7 +18,7 @@
 
 // Hack TEST macro of gTest and make they conform XCTest style. We only
 // need test name (b), not test case name (a).
-#define TEST(a,b) - (void)test ## b
+#define TEST(a, b) -(void)test##b
 #define ASSERT_TRUE XCTAssert
 #define ASSERT_EQ XCTAssertEqual
 
@@ -38,12 +38,10 @@
 const char val1[] = "metadata-val1";
 const char val2[] = "metadata-val2";
 
-bool ClientMetadataContains(const grpc::ServerContext& context,
-                            const grpc::string_ref& key,
+bool ClientMetadataContains(const grpc::ServerContext& context, const grpc::string_ref& key,
                             const grpc::string_ref& value) {
   const auto& client_metadata = context.client_metadata();
-  for (auto iter = client_metadata.begin(); iter != client_metadata.end();
-       ++iter) {
+  for (auto iter = client_metadata.begin(); iter != client_metadata.end(); ++iter) {
     if (iter->first == key && iter->second == value) {
       return true;
     }
diff --git a/test/cpp/codegen/proto_utils_test.cc b/test/cpp/codegen/proto_utils_test.cc
index 836d3d8..801660e 100644
--- a/test/cpp/codegen/proto_utils_test.cc
+++ b/test/cpp/codegen/proto_utils_test.cc
@@ -24,32 +24,42 @@
 #include <gtest/gtest.h>
 
 namespace grpc {
+
 namespace internal {
 
-// Provide access to GrpcBufferWriter internals.
-class GrpcBufferWriterPeer {
+// Provide access to ProtoBufferWriter internals.
+class ProtoBufferWriterPeer {
  public:
-  explicit GrpcBufferWriterPeer(internal::GrpcBufferWriter* writer)
-      : writer_(writer) {}
+  explicit ProtoBufferWriterPeer(ProtoBufferWriter* writer) : writer_(writer) {}
   bool have_backup() const { return writer_->have_backup_; }
   const grpc_slice& backup_slice() const { return writer_->backup_slice_; }
   const grpc_slice& slice() const { return writer_->slice_; }
 
  private:
-  GrpcBufferWriter* writer_;
+  ProtoBufferWriter* writer_;
+};
+
+// Provide access to ByteBuffer internals.
+class GrpcByteBufferPeer {
+ public:
+  explicit GrpcByteBufferPeer(ByteBuffer* bb) : bb_(bb) {}
+  grpc_byte_buffer* c_buffer() { return bb_->c_buffer(); }
+
+ private:
+  ByteBuffer* bb_;
 };
 
 class ProtoUtilsTest : public ::testing::Test {};
 
 // Regression test for a memory corruption bug where a series of
-// GrpcBufferWriter Next()/Backup() invocations could result in a dangling
+// ProtoBufferWriter Next()/Backup() invocations could result in a dangling
 // pointer returned by Next() due to the interaction between grpc_slice inlining
 // and GRPC_SLICE_START_PTR.
 TEST_F(ProtoUtilsTest, TinyBackupThenNext) {
-  grpc_byte_buffer* bp;
+  ByteBuffer bp;
   const int block_size = 1024;
-  GrpcBufferWriter writer(&bp, block_size, 8192);
-  GrpcBufferWriterPeer peer(&writer);
+  ProtoBufferWriter writer(&bp, block_size, 8192);
+  ProtoBufferWriterPeer peer(&writer);
 
   void* data;
   int size;
@@ -63,17 +73,14 @@
   ASSERT_TRUE(writer.Next(&data, &size));
   EXPECT_TRUE(peer.slice().refcount != nullptr);
   EXPECT_EQ(block_size, size);
-
-  // Cleanup.
-  g_core_codegen_interface->grpc_byte_buffer_destroy(bp);
 }
 
 namespace {
 
 // Set backup_size to 0 to indicate no backup is needed.
 void BufferWriterTest(int block_size, int total_size, int backup_size) {
-  grpc_byte_buffer* bp;
-  GrpcBufferWriter writer(&bp, block_size, total_size);
+  ByteBuffer bb;
+  ProtoBufferWriter writer(&bb, block_size, total_size);
 
   int written_size = 0;
   void* data;
@@ -110,10 +117,11 @@
       writer.BackUp(backup_size);
     }
   }
-  EXPECT_EQ(grpc_byte_buffer_length(bp), (size_t)total_size);
+  EXPECT_EQ(bb.Length(), (size_t)total_size);
 
   grpc_byte_buffer_reader reader;
-  grpc_byte_buffer_reader_init(&reader, bp);
+  GrpcByteBufferPeer peer(&bb);
+  grpc_byte_buffer_reader_init(&reader, peer.c_buffer());
   int read_bytes = 0;
   while (read_bytes < total_size) {
     grpc_slice s;
@@ -126,7 +134,6 @@
   }
   EXPECT_EQ(read_bytes, total_size);
   grpc_byte_buffer_reader_destroy(&reader);
-  grpc_byte_buffer_destroy(bp);
 }
 
 TEST(WriterTest, TinyBlockTinyBackup) {
@@ -154,7 +161,7 @@
 }  // namespace grpc
 
 int main(int argc, char** argv) {
-  // Ensure the GrpcBufferWriter internals are initialized.
+  // Ensure the ProtoBufferWriter internals are initialized.
   grpc::internal::GrpcLibraryInitializer init;
   init.summon();
   grpc::GrpcLibraryCodegen lib;
diff --git a/test/cpp/common/alarm_test.cc b/test/cpp/common/alarm_test.cc
index fb5f671..57d9583 100644
--- a/test/cpp/common/alarm_test.cc
+++ b/test/cpp/common/alarm_test.cc
@@ -36,7 +36,7 @@
   void* output_tag;
   bool ok;
   const CompletionQueue::NextStatus status =
-      cq.AsyncNext(&output_tag, &ok, grpc_timeout_seconds_to_deadline(2));
+      cq.AsyncNext(&output_tag, &ok, grpc_timeout_seconds_to_deadline(10));
 
   EXPECT_EQ(status, CompletionQueue::GOT_EVENT);
   EXPECT_TRUE(ok);
@@ -57,7 +57,7 @@
 
   std::thread t2([&cq, &ok, &output_tag, &status] {
     status =
-        cq.AsyncNext(&output_tag, &ok, grpc_timeout_seconds_to_deadline(2));
+        cq.AsyncNext(&output_tag, &ok, grpc_timeout_seconds_to_deadline(10));
   });
 
   t1.join();
@@ -75,7 +75,7 @@
   void* output_tag;
   bool ok;
   const CompletionQueue::NextStatus status =
-      cq.AsyncNext(&output_tag, &ok, grpc_timeout_seconds_to_deadline(2));
+      cq.AsyncNext(&output_tag, &ok, grpc_timeout_seconds_to_deadline(10));
 
   EXPECT_EQ(status, CompletionQueue::GOT_EVENT);
   EXPECT_TRUE(ok);
@@ -91,7 +91,7 @@
   void* output_tag;
   bool ok;
   const CompletionQueue::NextStatus status =
-      cq.AsyncNext(&output_tag, &ok, grpc_timeout_seconds_to_deadline(2));
+      cq.AsyncNext(&output_tag, &ok, grpc_timeout_seconds_to_deadline(10));
   EXPECT_EQ(status, CompletionQueue::GOT_EVENT);
   EXPECT_TRUE(ok);
   EXPECT_EQ(junk, output_tag);
@@ -108,7 +108,7 @@
   void* output_tag;
   bool ok;
   const CompletionQueue::NextStatus status =
-      cq.AsyncNext(&output_tag, &ok, grpc_timeout_seconds_to_deadline(2));
+      cq.AsyncNext(&output_tag, &ok, grpc_timeout_seconds_to_deadline(10));
 
   EXPECT_EQ(status, CompletionQueue::GOT_EVENT);
   EXPECT_TRUE(ok);
@@ -126,7 +126,7 @@
   void* output_tag;
   bool ok;
   const CompletionQueue::NextStatus status =
-      cq.AsyncNext(&output_tag, &ok, grpc_timeout_seconds_to_deadline(2));
+      cq.AsyncNext(&output_tag, &ok, grpc_timeout_seconds_to_deadline(10));
 
   EXPECT_EQ(status, CompletionQueue::GOT_EVENT);
   EXPECT_TRUE(ok);
@@ -169,7 +169,7 @@
   CompletionQueue cq;
   void* junk = reinterpret_cast<void*>(1618033);
   Alarm alarm;
-  alarm.Set(&cq, grpc_timeout_seconds_to_deadline(2), junk);
+  alarm.Set(&cq, grpc_timeout_seconds_to_deadline(10), junk);
   alarm.Cancel();
 
   void* output_tag;
@@ -187,7 +187,7 @@
   void* junk = reinterpret_cast<void*>(1618033);
   {
     Alarm alarm;
-    alarm.Set(&cq, grpc_timeout_seconds_to_deadline(2), junk);
+    alarm.Set(&cq, grpc_timeout_seconds_to_deadline(10), junk);
   }
 
   void* output_tag;
diff --git a/test/cpp/end2end/grpclb_end2end_test.cc b/test/cpp/end2end/grpclb_end2end_test.cc
index 5578456..7aab035 100644
--- a/test/cpp/end2end/grpclb_end2end_test.cc
+++ b/test/cpp/end2end/grpclb_end2end_test.cc
@@ -1139,7 +1139,7 @@
   EXPECT_EQ(0U, backend_servers_[1].service_->request_count());
   WaitForBackend(1);
 
-  // This is serviced by the existing RR policy
+  // This is serviced by the updated RR policy
   backend_servers_[1].service_->ResetCounters();
   gpr_log(GPR_INFO, "========= BEFORE THIRD BATCH ==========");
   CheckRpcSendOk(10);
diff --git a/test/cpp/interop/client.cc b/test/cpp/interop/client.cc
index ca8ee3d..3eb155e 100644
--- a/test/cpp/interop/client.cc
+++ b/test/cpp/interop/client.cc
@@ -31,6 +31,8 @@
 #include "test/cpp/interop/interop_client.h"
 #include "test/cpp/util/test_config.h"
 
+DEFINE_bool(use_alts, false,
+            "Whether to use alts. Enable alts will disable tls.");
 DEFINE_bool(use_tls, false, "Whether to use tls.");
 DEFINE_string(custom_credentials_type, "", "User provided credentials type.");
 DEFINE_bool(use_test_ca, false, "False to use SSL roots for google");
diff --git a/test/cpp/interop/client_helper.cc b/test/cpp/interop/client_helper.cc
index 4041f95..29b5a1e 100644
--- a/test/cpp/interop/client_helper.cc
+++ b/test/cpp/interop/client_helper.cc
@@ -35,6 +35,7 @@
 #include "test/cpp/util/create_test_channel.h"
 #include "test/cpp/util/test_credentials_provider.h"
 
+DECLARE_bool(use_alts);
 DECLARE_bool(use_tls);
 DECLARE_string(custom_credentials_type);
 DECLARE_bool(use_test_ca);
@@ -103,8 +104,10 @@
     GPR_ASSERT(creds);
   }
   if (FLAGS_custom_credentials_type.empty()) {
+    transport_security security_type =
+        FLAGS_use_alts ? ALTS : (FLAGS_use_tls ? TLS : INSECURE);
     return CreateTestChannel(host_port, FLAGS_server_host_override,
-                             FLAGS_use_tls, !FLAGS_use_test_ca, creds);
+                             security_type, !FLAGS_use_test_ca, creds);
   } else {
     return CreateTestChannel(host_port, FLAGS_custom_credentials_type, creds);
   }
diff --git a/test/cpp/interop/http2_client.cc b/test/cpp/interop/http2_client.cc
index 821815c..543f159 100644
--- a/test/cpp/interop/http2_client.cc
+++ b/test/cpp/interop/http2_client.cc
@@ -194,7 +194,7 @@
   snprintf(host_port, host_port_buf_size, "%s:%d", FLAGS_server_host.c_str(),
            FLAGS_server_port);
   std::shared_ptr<grpc::Channel> channel =
-      grpc::CreateTestChannel(host_port, false);
+      grpc::CreateTestChannel(host_port, grpc::testing::INSECURE);
   GPR_ASSERT(channel->WaitForConnected(gpr_time_add(
       gpr_now(GPR_CLOCK_REALTIME), gpr_time_from_seconds(300, GPR_TIMESPAN))));
   grpc::testing::Http2Client client(channel);
diff --git a/test/cpp/interop/interop_server.cc b/test/cpp/interop/interop_server.cc
index 5fa1a33..f55d624 100644
--- a/test/cpp/interop/interop_server.cc
+++ b/test/cpp/interop/interop_server.cc
@@ -38,6 +38,8 @@
 #include "test/cpp/interop/server_helper.h"
 #include "test/cpp/util/test_config.h"
 
+DEFINE_bool(use_alts, false,
+            "Whether to use alts. Enable alts will disable tls.");
 DEFINE_bool(use_tls, false, "Whether to use tls.");
 DEFINE_string(custom_credentials_type, "", "User provided credentials type.");
 DEFINE_int32(port, 0, "Server port.");
@@ -316,12 +318,27 @@
 
 void grpc::testing::interop::RunServer(
     std::shared_ptr<ServerCredentials> creds) {
-  RunServer(creds, FLAGS_port, nullptr);
+  RunServer(creds, FLAGS_port, nullptr, nullptr);
+}
+
+void grpc::testing::interop::RunServer(
+    std::shared_ptr<ServerCredentials> creds,
+    std::unique_ptr<std::vector<std::unique_ptr<ServerBuilderOption>>>
+        server_options) {
+  RunServer(creds, FLAGS_port, nullptr, std::move(server_options));
 }
 
 void grpc::testing::interop::RunServer(
     std::shared_ptr<ServerCredentials> creds, const int port,
     ServerStartedCondition* server_started_condition) {
+  RunServer(creds, port, server_started_condition, nullptr);
+}
+
+void grpc::testing::interop::RunServer(
+    std::shared_ptr<ServerCredentials> creds, const int port,
+    ServerStartedCondition* server_started_condition,
+    std::unique_ptr<std::vector<std::unique_ptr<ServerBuilderOption>>>
+        server_options) {
   GPR_ASSERT(port != 0);
   std::ostringstream server_address;
   server_address << "0.0.0.0:" << port;
@@ -333,6 +350,11 @@
   ServerBuilder builder;
   builder.RegisterService(&service);
   builder.AddListeningPort(server_address.str(), creds);
+  if (server_options != nullptr) {
+    for (size_t i = 0; i < server_options->size(); i++) {
+      builder.SetOption(std::move((*server_options)[i]));
+    }
+  }
   if (FLAGS_max_send_message_size >= 0) {
     builder.SetMaxSendMessageSize(FLAGS_max_send_message_size);
   }
diff --git a/test/cpp/interop/reconnect_interop_client.cc b/test/cpp/interop/reconnect_interop_client.cc
index 9a451fa..8a071d4 100644
--- a/test/cpp/interop/reconnect_interop_client.cc
+++ b/test/cpp/interop/reconnect_interop_client.cc
@@ -44,9 +44,11 @@
 using grpc::CreateTestChannel;
 using grpc::Status;
 using grpc::testing::Empty;
+using grpc::testing::INSECURE;
 using grpc::testing::ReconnectInfo;
 using grpc::testing::ReconnectParams;
 using grpc::testing::ReconnectService;
+using grpc::testing::TLS;
 
 int main(int argc, char** argv) {
   grpc::testing::InitTest(&argc, &argv, true);
@@ -57,7 +59,7 @@
   server_address << FLAGS_server_host << ':' << FLAGS_server_control_port;
   std::unique_ptr<ReconnectService::Stub> control_stub(
       ReconnectService::NewStub(
-          CreateTestChannel(server_address.str(), false)));
+          CreateTestChannel(server_address.str(), INSECURE)));
   ClientContext start_context;
   ReconnectParams reconnect_params;
   reconnect_params.set_max_reconnect_backoff_ms(FLAGS_max_reconnect_backoff_ms);
@@ -75,7 +77,7 @@
                         FLAGS_max_reconnect_backoff_ms);
   }
   std::shared_ptr<Channel> retry_channel =
-      CreateTestChannel(server_address.str(), "foo.test.google.fr", true, false,
+      CreateTestChannel(server_address.str(), "foo.test.google.fr", TLS, false,
                         std::shared_ptr<CallCredentials>(), channel_args);
 
   // About 13 retries.
diff --git a/test/cpp/interop/server_helper.cc b/test/cpp/interop/server_helper.cc
index 93ffd52..2194521 100644
--- a/test/cpp/interop/server_helper.cc
+++ b/test/cpp/interop/server_helper.cc
@@ -26,6 +26,7 @@
 #include "src/core/lib/surface/call_test_only.h"
 #include "test/cpp/util/test_credentials_provider.h"
 
+DECLARE_bool(use_alts);
 DECLARE_bool(use_tls);
 DECLARE_string(custom_credentials_type);
 
@@ -36,6 +37,8 @@
   if (!FLAGS_custom_credentials_type.empty()) {
     return GetCredentialsProvider()->GetServerCredentials(
         FLAGS_custom_credentials_type);
+  } else if (FLAGS_use_alts) {
+    return GetCredentialsProvider()->GetServerCredentials(kAltsCredentialsType);
   } else if (FLAGS_use_tls) {
     return GetCredentialsProvider()->GetServerCredentials(kTlsCredentialsType);
   } else {
diff --git a/test/cpp/interop/server_helper.h b/test/cpp/interop/server_helper.h
index 3004e7f..265874d 100644
--- a/test/cpp/interop/server_helper.h
+++ b/test/cpp/interop/server_helper.h
@@ -26,6 +26,8 @@
 #include <grpc/impl/codegen/atm.h>
 
 #include <grpcpp/security/server_credentials.h>
+#include <grpcpp/server.h>
+#include <grpcpp/server_builder.h>
 #include <grpcpp/server_context.h>
 
 namespace grpc {
@@ -72,6 +74,28 @@
 void RunServer(std::shared_ptr<ServerCredentials> creds, int port,
                ServerStartedCondition* server_started_condition);
 
+/// Run gRPC interop server.
+///
+/// \param creds The credentials associated with the server.
+/// \param server_options List of options to set when building the server.
+void RunServer(
+    std::shared_ptr<ServerCredentials> creds,
+    std::unique_ptr<std::vector<std::unique_ptr<ServerBuilderOption>>>
+        server_options);
+
+/// Run gRPC interop server.
+///
+/// \param creds The credentials associated with the server.
+/// \param port Port to use for the server.
+/// \param server_options List of options to set when building the server.
+/// \param server_started_condition (optional) Struct holding mutex, condition
+//     variable, and condition used to notify when the server has started.
+void RunServer(
+    std::shared_ptr<ServerCredentials> creds, const int port,
+    ServerStartedCondition* server_started_condition,
+    std::unique_ptr<std::vector<std::unique_ptr<grpc::ServerBuilderOption>>>
+        server_options);
+
 }  // namespace interop
 }  // namespace testing
 }  // namespace grpc
diff --git a/test/cpp/interop/stress_test.cc b/test/cpp/interop/stress_test.cc
index 6e8134a..023e0c8 100644
--- a/test/cpp/interop/stress_test.cc
+++ b/test/cpp/interop/stress_test.cc
@@ -99,18 +99,24 @@
 
 // Options from client.cc (for compatibility with interop test).
 // TODO(sreek): Consolidate overlapping options
+DEFINE_bool(use_alts, false,
+            "Whether to use alts. Enable alts will disable tls.");
 DEFINE_bool(use_tls, false, "Whether to use tls.");
 DEFINE_bool(use_test_ca, false, "False to use SSL roots for google");
 DEFINE_string(server_host_override, "foo.test.google.fr",
               "Override the server host which is sent in HTTP header");
 
+using grpc::testing::ALTS;
+using grpc::testing::INSECURE;
 using grpc::testing::MetricsService;
 using grpc::testing::MetricsServiceImpl;
 using grpc::testing::StressTestInteropClient;
+using grpc::testing::TLS;
 using grpc::testing::TestCaseType;
 using grpc::testing::UNKNOWN_TEST;
 using grpc::testing::WeightedRandomTestSelector;
 using grpc::testing::kTestCaseList;
+using grpc::testing::transport_security;
 
 static int log_level = GPR_LOG_SEVERITY_DEBUG;
 
@@ -268,6 +274,8 @@
   int thread_idx = 0;
   int server_idx = -1;
   char buffer[256];
+  transport_security security_type =
+      FLAGS_use_alts ? ALTS : (FLAGS_use_tls ? TLS : INSECURE);
   for (auto it = server_addresses.begin(); it != server_addresses.end(); it++) {
     ++server_idx;
     // Create channel(s) for each server
@@ -276,7 +284,7 @@
       gpr_log(GPR_INFO, "Starting test with %s channel_idx=%d..", it->c_str(),
               channel_idx);
       std::shared_ptr<grpc::Channel> channel = grpc::CreateTestChannel(
-          *it, FLAGS_server_host_override, FLAGS_use_tls, !FLAGS_use_test_ca);
+          *it, FLAGS_server_host_override, security_type, !FLAGS_use_test_ca);
 
       // Create stub(s) for each channel
       for (int stub_idx = 0; stub_idx < FLAGS_num_stubs_per_channel;
diff --git a/test/cpp/microbenchmarks/BUILD b/test/cpp/microbenchmarks/BUILD
index 67f7e44..5dcfd94 100644
--- a/test/cpp/microbenchmarks/BUILD
+++ b/test/cpp/microbenchmarks/BUILD
@@ -42,6 +42,7 @@
         "//:grpc++_unsecure",
         "//src/proto/grpc/testing:echo_proto",
         "//test/core/util:grpc_test_util_unsecure",
+        "//test/cpp/util:test_config",
     ],
 )
 
@@ -113,10 +114,7 @@
     name = "bm_fullstack_trickle",
     testonly = 1,
     srcs = ["bm_fullstack_trickle.cc"],
-    deps = [
-        ":helpers",
-        "//test/cpp/util:test_config",
-    ],
+    deps = [":helpers"],
 )
 
 grpc_cc_library(
diff --git a/test/cpp/microbenchmarks/bm_arena.cc b/test/cpp/microbenchmarks/bm_arena.cc
index 69c8c1c..b97c954 100644
--- a/test/cpp/microbenchmarks/bm_arena.cc
+++ b/test/cpp/microbenchmarks/bm_arena.cc
@@ -18,9 +18,10 @@
 
 /* Benchmark arenas */
 
+#include <benchmark/benchmark.h>
 #include "src/core/lib/gpr/arena.h"
 #include "test/cpp/microbenchmarks/helpers.h"
-#include "third_party/benchmark/include/benchmark/benchmark.h"
+#include "test/cpp/util/test_config.h"
 
 static void BM_Arena_NoOp(benchmark::State& state) {
   while (state.KeepRunning()) {
@@ -56,4 +57,15 @@
 }
 BENCHMARK(BM_Arena_Batch)->Ranges({{1, 64 * 1024}, {1, 64}, {1, 1024}});
 
-BENCHMARK_MAIN();
+// Some distros have RunSpecifiedBenchmarks under the benchmark namespace,
+// and others do not. This allows us to support both modes.
+namespace benchmark {
+void RunTheBenchmarksNamespaced() { RunSpecifiedBenchmarks(); }
+}  // namespace benchmark
+
+int main(int argc, char** argv) {
+  ::benchmark::Initialize(&argc, argv);
+  ::grpc::testing::InitTest(&argc, &argv, false);
+  benchmark::RunTheBenchmarksNamespaced();
+  return 0;
+}
diff --git a/test/cpp/microbenchmarks/bm_call_create.cc b/test/cpp/microbenchmarks/bm_call_create.cc
index 85a9f5e..831b29c 100644
--- a/test/cpp/microbenchmarks/bm_call_create.cc
+++ b/test/cpp/microbenchmarks/bm_call_create.cc
@@ -46,6 +46,7 @@
 #include "src/cpp/client/create_channel_internal.h"
 #include "src/proto/grpc/testing/echo.grpc.pb.h"
 #include "test/cpp/microbenchmarks/helpers.h"
+#include "test/cpp/util/test_config.h"
 
 auto& force_library_initialization = Library::get();
 
@@ -813,4 +814,15 @@
 }
 BENCHMARK(BM_IsolatedCall_StreamingSend);
 
-BENCHMARK_MAIN();
+// Some distros have RunSpecifiedBenchmarks under the benchmark namespace,
+// and others do not. This allows us to support both modes.
+namespace benchmark {
+void RunTheBenchmarksNamespaced() { RunSpecifiedBenchmarks(); }
+}  // namespace benchmark
+
+int main(int argc, char** argv) {
+  ::benchmark::Initialize(&argc, argv);
+  ::grpc::testing::InitTest(&argc, &argv, false);
+  benchmark::RunTheBenchmarksNamespaced();
+  return 0;
+}
diff --git a/test/cpp/microbenchmarks/bm_chttp2_hpack.cc b/test/cpp/microbenchmarks/bm_chttp2_hpack.cc
index d0f3ec8..823c76f 100644
--- a/test/cpp/microbenchmarks/bm_chttp2_hpack.cc
+++ b/test/cpp/microbenchmarks/bm_chttp2_hpack.cc
@@ -33,6 +33,7 @@
 #include "src/core/lib/transport/timeout_encoding.h"
 
 #include "test/cpp/microbenchmarks/helpers.h"
+#include "test/cpp/util/test_config.h"
 
 auto& force_library_initialization = Library::get();
 
@@ -855,4 +856,15 @@
 
 }  // namespace hpack_parser_fixtures
 
-BENCHMARK_MAIN();
+// Some distros have RunSpecifiedBenchmarks under the benchmark namespace,
+// and others do not. This allows us to support both modes.
+namespace benchmark {
+void RunTheBenchmarksNamespaced() { RunSpecifiedBenchmarks(); }
+}  // namespace benchmark
+
+int main(int argc, char** argv) {
+  ::benchmark::Initialize(&argc, argv);
+  ::grpc::testing::InitTest(&argc, &argv, false);
+  benchmark::RunTheBenchmarksNamespaced();
+  return 0;
+}
diff --git a/test/cpp/microbenchmarks/bm_chttp2_transport.cc b/test/cpp/microbenchmarks/bm_chttp2_transport.cc
index d00c79b..1e9bd27 100644
--- a/test/cpp/microbenchmarks/bm_chttp2_transport.cc
+++ b/test/cpp/microbenchmarks/bm_chttp2_transport.cc
@@ -18,6 +18,7 @@
 
 /* Microbenchmarks around CHTTP2 transport operations */
 
+#include <benchmark/benchmark.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
@@ -33,7 +34,7 @@
 #include "src/core/lib/slice/slice_internal.h"
 #include "src/core/lib/transport/static_metadata.h"
 #include "test/cpp/microbenchmarks/helpers.h"
-#include "third_party/benchmark/include/benchmark/benchmark.h"
+#include "test/cpp/util/test_config.h"
 
 auto& force_library_initialization = Library::get();
 
@@ -638,4 +639,15 @@
 }
 BENCHMARK(BM_TransportStreamRecv)->Range(0, 128 * 1024 * 1024);
 
-BENCHMARK_MAIN();
+// Some distros have RunSpecifiedBenchmarks under the benchmark namespace,
+// and others do not. This allows us to support both modes.
+namespace benchmark {
+void RunTheBenchmarksNamespaced() { RunSpecifiedBenchmarks(); }
+}  // namespace benchmark
+
+int main(int argc, char** argv) {
+  ::benchmark::Initialize(&argc, argv);
+  ::grpc::testing::InitTest(&argc, &argv, false);
+  benchmark::RunTheBenchmarksNamespaced();
+  return 0;
+}
diff --git a/test/cpp/microbenchmarks/bm_closure.cc b/test/cpp/microbenchmarks/bm_closure.cc
index 6d88fae..8bdc3b9 100644
--- a/test/cpp/microbenchmarks/bm_closure.cc
+++ b/test/cpp/microbenchmarks/bm_closure.cc
@@ -28,6 +28,7 @@
 #include "src/core/lib/iomgr/exec_ctx.h"
 
 #include "test/cpp/microbenchmarks/helpers.h"
+#include "test/cpp/util/test_config.h"
 
 auto& force_library_initialization = Library::get();
 
@@ -415,4 +416,15 @@
 }
 BENCHMARK(BM_ClosureReschedOnCombinerFinally);
 
-BENCHMARK_MAIN();
+// Some distros have RunSpecifiedBenchmarks under the benchmark namespace,
+// and others do not. This allows us to support both modes.
+namespace benchmark {
+void RunTheBenchmarksNamespaced() { RunSpecifiedBenchmarks(); }
+}  // namespace benchmark
+
+int main(int argc, char** argv) {
+  ::benchmark::Initialize(&argc, argv);
+  ::grpc::testing::InitTest(&argc, &argv, false);
+  benchmark::RunTheBenchmarksNamespaced();
+  return 0;
+}
diff --git a/test/cpp/microbenchmarks/bm_cq.cc b/test/cpp/microbenchmarks/bm_cq.cc
index 342a95e..a7cb939 100644
--- a/test/cpp/microbenchmarks/bm_cq.cc
+++ b/test/cpp/microbenchmarks/bm_cq.cc
@@ -25,6 +25,7 @@
 #include <grpcpp/completion_queue.h>
 #include <grpcpp/impl/grpc_library.h>
 #include "test/cpp/microbenchmarks/helpers.h"
+#include "test/cpp/util/test_config.h"
 
 #include "src/core/lib/surface/completion_queue.h"
 
@@ -148,4 +149,15 @@
 }  // namespace testing
 }  // namespace grpc
 
-BENCHMARK_MAIN();
+// Some distros have RunSpecifiedBenchmarks under the benchmark namespace,
+// and others do not. This allows us to support both modes.
+namespace benchmark {
+void RunTheBenchmarksNamespaced() { RunSpecifiedBenchmarks(); }
+}  // namespace benchmark
+
+int main(int argc, char** argv) {
+  ::benchmark::Initialize(&argc, argv);
+  ::grpc::testing::InitTest(&argc, &argv, false);
+  benchmark::RunTheBenchmarksNamespaced();
+  return 0;
+}
diff --git a/test/cpp/microbenchmarks/bm_cq_multiple_threads.cc b/test/cpp/microbenchmarks/bm_cq_multiple_threads.cc
index ec79b95..da095c3 100644
--- a/test/cpp/microbenchmarks/bm_cq_multiple_threads.cc
+++ b/test/cpp/microbenchmarks/bm_cq_multiple_threads.cc
@@ -24,6 +24,7 @@
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
 #include "test/cpp/microbenchmarks/helpers.h"
+#include "test/cpp/util/test_config.h"
 
 #include "src/core/lib/iomgr/ev_posix.h"
 #include "src/core/lib/iomgr/port.h"
@@ -164,4 +165,15 @@
 }  // namespace testing
 }  // namespace grpc
 
-BENCHMARK_MAIN();
+// Some distros have RunSpecifiedBenchmarks under the benchmark namespace,
+// and others do not. This allows us to support both modes.
+namespace benchmark {
+void RunTheBenchmarksNamespaced() { RunSpecifiedBenchmarks(); }
+}  // namespace benchmark
+
+int main(int argc, char** argv) {
+  ::benchmark::Initialize(&argc, argv);
+  ::grpc::testing::InitTest(&argc, &argv, false);
+  benchmark::RunTheBenchmarksNamespaced();
+  return 0;
+}
diff --git a/test/cpp/microbenchmarks/bm_error.cc b/test/cpp/microbenchmarks/bm_error.cc
index d12f475..ae557a5 100644
--- a/test/cpp/microbenchmarks/bm_error.cc
+++ b/test/cpp/microbenchmarks/bm_error.cc
@@ -25,6 +25,7 @@
 #include "src/core/lib/transport/error_utils.h"
 
 #include "test/cpp/microbenchmarks/helpers.h"
+#include "test/cpp/util/test_config.h"
 
 auto& force_library_initialization = Library::get();
 
@@ -310,4 +311,15 @@
 BENCHMARK_SUITE(ErrorWithHttpError);
 BENCHMARK_SUITE(ErrorWithNestedGrpcStatus);
 
-BENCHMARK_MAIN();
+// Some distros have RunSpecifiedBenchmarks under the benchmark namespace,
+// and others do not. This allows us to support both modes.
+namespace benchmark {
+void RunTheBenchmarksNamespaced() { RunSpecifiedBenchmarks(); }
+}  // namespace benchmark
+
+int main(int argc, char** argv) {
+  ::benchmark::Initialize(&argc, argv);
+  ::grpc::testing::InitTest(&argc, &argv, false);
+  benchmark::RunTheBenchmarksNamespaced();
+  return 0;
+}
diff --git a/test/cpp/microbenchmarks/bm_fullstack_streaming_ping_pong.cc b/test/cpp/microbenchmarks/bm_fullstack_streaming_ping_pong.cc
index 655e032..34df77a 100644
--- a/test/cpp/microbenchmarks/bm_fullstack_streaming_ping_pong.cc
+++ b/test/cpp/microbenchmarks/bm_fullstack_streaming_ping_pong.cc
@@ -19,6 +19,7 @@
 /* Benchmark gRPC end2end in various configurations */
 
 #include "test/cpp/microbenchmarks/fullstack_streaming_ping_pong.h"
+#include "test/cpp/util/test_config.h"
 
 namespace grpc {
 namespace testing {
@@ -114,4 +115,15 @@
 }  // namespace testing
 }  // namespace grpc
 
-BENCHMARK_MAIN();
+// Some distros have RunSpecifiedBenchmarks under the benchmark namespace,
+// and others do not. This allows us to support both modes.
+namespace benchmark {
+void RunTheBenchmarksNamespaced() { RunSpecifiedBenchmarks(); }
+}  // namespace benchmark
+
+int main(int argc, char** argv) {
+  ::benchmark::Initialize(&argc, argv);
+  ::grpc::testing::InitTest(&argc, &argv, false);
+  benchmark::RunTheBenchmarksNamespaced();
+  return 0;
+}
diff --git a/test/cpp/microbenchmarks/bm_fullstack_streaming_pump.cc b/test/cpp/microbenchmarks/bm_fullstack_streaming_pump.cc
index c7ceacd..da98f3c 100644
--- a/test/cpp/microbenchmarks/bm_fullstack_streaming_pump.cc
+++ b/test/cpp/microbenchmarks/bm_fullstack_streaming_pump.cc
@@ -19,6 +19,7 @@
 /* Benchmark gRPC end2end in various configurations */
 
 #include "test/cpp/microbenchmarks/fullstack_streaming_pump.h"
+#include "test/cpp/util/test_config.h"
 
 namespace grpc {
 namespace testing {
@@ -64,4 +65,15 @@
 }  // namespace testing
 }  // namespace grpc
 
-BENCHMARK_MAIN();
+// Some distros have RunSpecifiedBenchmarks under the benchmark namespace,
+// and others do not. This allows us to support both modes.
+namespace benchmark {
+void RunTheBenchmarksNamespaced() { RunSpecifiedBenchmarks(); }
+}  // namespace benchmark
+
+int main(int argc, char** argv) {
+  ::benchmark::Initialize(&argc, argv);
+  ::grpc::testing::InitTest(&argc, &argv, false);
+  benchmark::RunTheBenchmarksNamespaced();
+  return 0;
+}
diff --git a/test/cpp/microbenchmarks/bm_fullstack_trickle.cc b/test/cpp/microbenchmarks/bm_fullstack_trickle.cc
index 3b21c4c..1af92d2 100644
--- a/test/cpp/microbenchmarks/bm_fullstack_trickle.cc
+++ b/test/cpp/microbenchmarks/bm_fullstack_trickle.cc
@@ -458,10 +458,16 @@
 
 extern gpr_timespec (*gpr_now_impl)(gpr_clock_type clock_type);
 
+// Some distros have RunSpecifiedBenchmarks under the benchmark namespace,
+// and others do not. This allows us to support both modes.
+namespace benchmark {
+void RunTheBenchmarksNamespaced() { RunSpecifiedBenchmarks(); }
+}  // namespace benchmark
+
 int main(int argc, char** argv) {
   ::benchmark::Initialize(&argc, argv);
   ::grpc::testing::InitTest(&argc, &argv, false);
   grpc_timer_manager_set_threading(false);
   gpr_now_impl = ::grpc::testing::fake_now;
-  ::benchmark::RunSpecifiedBenchmarks();
+  benchmark::RunTheBenchmarksNamespaced();
 }
diff --git a/test/cpp/microbenchmarks/bm_fullstack_unary_ping_pong.cc b/test/cpp/microbenchmarks/bm_fullstack_unary_ping_pong.cc
index fa41d11..5a7a8d5 100644
--- a/test/cpp/microbenchmarks/bm_fullstack_unary_ping_pong.cc
+++ b/test/cpp/microbenchmarks/bm_fullstack_unary_ping_pong.cc
@@ -19,6 +19,7 @@
 /* Benchmark gRPC end2end in various configurations */
 
 #include "test/cpp/microbenchmarks/fullstack_unary_ping_pong.h"
+#include "test/cpp/util/test_config.h"
 
 namespace grpc {
 namespace testing {
@@ -164,4 +165,15 @@
 }  // namespace testing
 }  // namespace grpc
 
-BENCHMARK_MAIN();
+// Some distros have RunSpecifiedBenchmarks under the benchmark namespace,
+// and others do not. This allows us to support both modes.
+namespace benchmark {
+void RunTheBenchmarksNamespaced() { RunSpecifiedBenchmarks(); }
+}  // namespace benchmark
+
+int main(int argc, char** argv) {
+  ::benchmark::Initialize(&argc, argv);
+  ::grpc::testing::InitTest(&argc, &argv, false);
+  benchmark::RunTheBenchmarksNamespaced();
+  return 0;
+}
diff --git a/test/cpp/microbenchmarks/bm_metadata.cc b/test/cpp/microbenchmarks/bm_metadata.cc
index f1e7890..553b33c 100644
--- a/test/cpp/microbenchmarks/bm_metadata.cc
+++ b/test/cpp/microbenchmarks/bm_metadata.cc
@@ -25,6 +25,7 @@
 #include "src/core/lib/transport/static_metadata.h"
 
 #include "test/cpp/microbenchmarks/helpers.h"
+#include "test/cpp/util/test_config.h"
 
 auto& force_library_initialization = Library::get();
 
@@ -290,4 +291,15 @@
 }
 BENCHMARK(BM_MetadataRefUnrefStatic);
 
-BENCHMARK_MAIN();
+// Some distros have RunSpecifiedBenchmarks under the benchmark namespace,
+// and others do not. This allows us to support both modes.
+namespace benchmark {
+void RunTheBenchmarksNamespaced() { RunSpecifiedBenchmarks(); }
+}  // namespace benchmark
+
+int main(int argc, char** argv) {
+  ::benchmark::Initialize(&argc, argv);
+  ::grpc::testing::InitTest(&argc, &argv, false);
+  benchmark::RunTheBenchmarksNamespaced();
+  return 0;
+}
diff --git a/test/cpp/microbenchmarks/bm_pollset.cc b/test/cpp/microbenchmarks/bm_pollset.cc
index f49f667..bcb68ff 100644
--- a/test/cpp/microbenchmarks/bm_pollset.cc
+++ b/test/cpp/microbenchmarks/bm_pollset.cc
@@ -18,6 +18,7 @@
 
 /* Test out pollset latencies */
 
+#include <benchmark/benchmark.h>
 #include <grpc/grpc.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
@@ -29,7 +30,7 @@
 #include "src/core/lib/iomgr/wakeup_fd_posix.h"
 
 #include "test/cpp/microbenchmarks/helpers.h"
-#include "third_party/benchmark/include/benchmark/benchmark.h"
+#include "test/cpp/util/test_config.h"
 
 #include <string.h>
 
@@ -256,4 +257,15 @@
 }
 BENCHMARK(BM_SingleThreadPollOneFd);
 
-BENCHMARK_MAIN();
+// Some distros have RunSpecifiedBenchmarks under the benchmark namespace,
+// and others do not. This allows us to support both modes.
+namespace benchmark {
+void RunTheBenchmarksNamespaced() { RunSpecifiedBenchmarks(); }
+}  // namespace benchmark
+
+int main(int argc, char** argv) {
+  ::benchmark::Initialize(&argc, argv);
+  ::grpc::testing::InitTest(&argc, &argv, false);
+  benchmark::RunTheBenchmarksNamespaced();
+  return 0;
+}
diff --git a/test/cpp/microbenchmarks/helpers.cc b/test/cpp/microbenchmarks/helpers.cc
index e4a31f5..e4ba37e 100644
--- a/test/cpp/microbenchmarks/helpers.cc
+++ b/test/cpp/microbenchmarks/helpers.cc
@@ -48,16 +48,10 @@
             static_cast<double>(state.iterations()));
   }
   for (int i = 0; i < GRPC_STATS_HISTOGRAM_COUNT; i++) {
-    std::ostringstream median_ss;
-    median_ss << grpc_stats_histogram_name[i] << "-median";
-    state.counters[median_ss.str()] =
-        benchmark::Counter(grpc_stats_histo_percentile(
-            &stats, static_cast<grpc_stats_histograms>(i), 50.0));
-    std::ostringstream tail_ss;
-    tail_ss << grpc_stats_histogram_name[i] << "-99p";
-    state.counters[tail_ss.str()] =
-        benchmark::Counter(grpc_stats_histo_percentile(
-            &stats, static_cast<grpc_stats_histograms>(i), 99.0));
+    out << " " << grpc_stats_histogram_name[i] << "-median:"
+        << grpc_stats_histo_percentile(&stats, (grpc_stats_histograms)i, 50.0)
+        << " " << grpc_stats_histogram_name[i] << "-99p:"
+        << grpc_stats_histo_percentile(&stats, (grpc_stats_histograms)i, 99.0);
   }
 #ifdef GPR_LOW_LEVEL_COUNTERS
   grpc_memory_counters counters_at_end = grpc_memory_counters_snapshot();
diff --git a/test/cpp/naming/BUILD b/test/cpp/naming/BUILD
index 54b53d2..fa0b216 100644
--- a/test/cpp/naming/BUILD
+++ b/test/cpp/naming/BUILD
@@ -22,16 +22,17 @@
 
 licenses(["notice"])  # Apache v2
 
-load("//bazel:grpc_build_system.bzl", "grpc_sh_binary", "grpc_py_binary")
+load("//bazel:grpc_build_system.bzl", "grpc_py_binary")
 
 load(":generate_resolver_component_tests.bzl", "generate_resolver_component_tests")
 
 # Meant to be invoked only through the top-level shell script driver.
-grpc_sh_binary(
+grpc_py_binary(
     name = "resolver_component_tests_runner",
     srcs = [
-        "resolver_component_tests_runner.sh",
+        "resolver_component_tests_runner.py",
     ],
+    testonly = True,
 )
 
 generate_resolver_component_tests()
diff --git a/test/cpp/naming/address_sorting_test.cc b/test/cpp/naming/address_sorting_test.cc
index df93ff6..a92e9e3 100644
--- a/test/cpp/naming/address_sorting_test.cc
+++ b/test/cpp/naming/address_sorting_test.cc
@@ -298,6 +298,29 @@
                                 });
 }
 
+/* Flip the input on the test above to reorder the sort function's
+ * comparator's inputs. */
+TEST(AddressSortingTest, TestUsesLabelFromDefaultTableInputFlipped) {
+  bool ipv4_supported = true;
+  bool ipv6_supported = true;
+  OverrideAddressSortingSourceAddrFactory(
+      ipv4_supported, ipv6_supported,
+      {
+          {"[2002::5001]:443", {"[2001::5002]:0", AF_INET6}},
+          {"[2001::5001]:443",
+           {"[2001::5002]:0", AF_INET6}},  // matching labels
+      });
+  grpc_lb_addresses* lb_addrs = BuildLbAddrInputs({
+      {"[2001::5001]:443", AF_INET6},
+      {"[2002::5001]:443", AF_INET6},
+  });
+  grpc_cares_wrapper_test_only_address_sorting_sort(lb_addrs);
+  VerifyLbAddrOutputs(lb_addrs, {
+                                    "[2001::5001]:443",
+                                    "[2002::5001]:443",
+                                });
+}
+
 /* Tests for rule 6 */
 
 TEST(AddressSortingTest,
@@ -722,16 +745,24 @@
 }
 
 int main(int argc, char** argv) {
-  const char* resolver = gpr_getenv("GRPC_DNS_RESOLVER");
+  char* resolver = gpr_getenv("GRPC_DNS_RESOLVER");
   if (resolver == nullptr || strlen(resolver) == 0) {
     gpr_setenv("GRPC_DNS_RESOLVER", "ares");
   } else if (strcmp("ares", resolver)) {
     gpr_log(GPR_INFO, "GRPC_DNS_RESOLVER != ares: %s.", resolver);
   }
+  gpr_free(resolver);
   grpc_test_init(argc, argv);
   ::testing::InitGoogleTest(&argc, argv);
   grpc_init();
   auto result = RUN_ALL_TESTS();
   grpc_shutdown();
+  // Test sequential and nested inits and shutdowns.
+  grpc_init();
+  grpc_init();
+  grpc_shutdown();
+  grpc_shutdown();
+  grpc_init();
+  grpc_shutdown();
   return result;
 }
diff --git a/test/cpp/naming/generate_resolver_component_tests.bzl b/test/cpp/naming/generate_resolver_component_tests.bzl
index ebc1679..5e9aa63 100755
--- a/test/cpp/naming/generate_resolver_component_tests.bzl
+++ b/test/cpp/naming/generate_resolver_component_tests.bzl
@@ -13,7 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-load("//bazel:grpc_build_system.bzl", "grpc_sh_binary", "grpc_cc_test", "grpc_cc_binary")
+load("//bazel:grpc_build_system.bzl", "grpc_cc_test", "grpc_cc_binary")
 
 def generate_resolver_component_tests():
   for unsecure_build_config_suffix in ['_unsecure', '']:
diff --git a/test/cpp/naming/resolver_component_test.cc b/test/cpp/naming/resolver_component_test.cc
index bfdcd96..f4be064 100644
--- a/test/cpp/naming/resolver_component_test.cc
+++ b/test/cpp/naming/resolver_component_test.cc
@@ -65,11 +65,6 @@
               "List of expected backend or balancer addresses in the form "
               "'<ip0:port0>,<is_balancer0>;<ip1:port1>,<is_balancer1>;...'. "
               "'is_balancer' should be bool, i.e. true or false.");
-DEFINE_bool(allow_extra_addrs, false,
-            "Permit extra resolved addresses in the final list of "
-            "resolved addresses. This is useful in certain integration "
-            "test environments in which DNS responses are not fully "
-            "deterministic.");
 DEFINE_string(expected_chosen_service_config, "",
               "Expected service config json string that gets chosen (no "
               "whitespace). Empty for none.");
@@ -245,11 +240,9 @@
   GPR_ASSERT(channel_arg->type == GRPC_ARG_POINTER);
   grpc_lb_addresses* addresses =
       (grpc_lb_addresses*)channel_arg->value.pointer.p;
-  gpr_log(GPR_INFO,
-          "num addrs found: %" PRIdPTR ". expected %" PRIdPTR
-          ". Allow extra addresses:%d.",
-          addresses->num_addresses, args->expected_addrs.size(),
-          FLAGS_allow_extra_addrs);
+  gpr_log(GPR_INFO, "num addrs found: %" PRIdPTR ". expected %" PRIdPTR,
+          addresses->num_addresses, args->expected_addrs.size());
+  GPR_ASSERT(addresses->num_addresses == args->expected_addrs.size());
   std::vector<GrpcLBAddress> found_lb_addrs;
   for (size_t i = 0; i < addresses->num_addresses; i++) {
     grpc_lb_address addr = addresses->addresses[i];
@@ -261,20 +254,13 @@
     gpr_free(str);
   }
   if (args->expected_addrs.size() != found_lb_addrs.size()) {
-    // Permit extra resolved addresses if "--allow_extra_addrs" was set.
-    if (!(FLAGS_allow_extra_addrs &&
-          found_lb_addrs.size() > args->expected_addrs.size())) {
-      gpr_log(GPR_DEBUG,
-              "found lb addrs size is: %" PRIdPTR
-              ". expected addrs size is %" PRIdPTR ". --allow_extra_addrs=%d.",
-              found_lb_addrs.size(), args->expected_addrs.size(),
-              FLAGS_allow_extra_addrs);
-      abort();
-    }
+    gpr_log(GPR_DEBUG,
+            "found lb addrs size is: %" PRIdPTR
+            ". expected addrs size is %" PRIdPTR,
+            found_lb_addrs.size(), args->expected_addrs.size());
+    abort();
   }
-  for (size_t i = 0; i < args->expected_addrs.size(); i++) {
-    EXPECT_THAT(found_lb_addrs, ::testing::Contains(args->expected_addrs[i]));
-  }
+  EXPECT_THAT(args->expected_addrs, UnorderedElementsAreArray(found_lb_addrs));
   CheckServiceConfigResultLocked(channel_args, args);
   if (args->expected_service_config_string == "") {
     CheckLBPolicyResultLocked(channel_args, args);
diff --git a/test/cpp/naming/resolver_component_tests_runner.py b/test/cpp/naming/resolver_component_tests_runner.py
new file mode 100755
index 0000000..69386eb
--- /dev/null
+++ b/test/cpp/naming/resolver_component_tests_runner.py
@@ -0,0 +1,275 @@
+#!/usr/bin/env python
+# Copyright 2015 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 file is auto-generated
+
+import argparse
+import sys
+import subprocess
+import tempfile
+import os
+import time
+import signal
+
+
+argp = argparse.ArgumentParser(description='Run c-ares resolver tests')
+argp.add_argument('--test_bin_path', default=None, type=str,
+                  help='Path to gtest test binary to invoke.')
+argp.add_argument('--dns_server_bin_path', default=None, type=str,
+                  help='Path to local DNS server python script.')
+argp.add_argument('--records_config_path', default=None, type=str,
+                  help=('Path to DNS records yaml file that '
+                        'specifies records for the DNS sever. '))
+argp.add_argument('--dns_server_port', default=None, type=int,
+                  help=('Port that local DNS server is listening on.'))
+argp.add_argument('--dns_resolver_bin_path', default=None, type=str,
+                  help=('Path to the DNS health check utility.'))
+argp.add_argument('--tcp_connect_bin_path', default=None, type=str,
+                  help=('Path to the TCP health check utility.'))
+args = argp.parse_args()
+
+def test_runner_log(msg):
+  sys.stderr.write('\n%s: %s\n' % (__file__, msg))
+
+cur_resolver = os.environ.get('GRPC_DNS_RESOLVER')
+if cur_resolver and cur_resolver != 'ares':
+  test_runner_log(('WARNING: cur resolver set to %s. This set of tests '
+      'needs to use GRPC_DNS_RESOLVER=ares.'))
+  test_runner_log('Exit 1 without running tests.')
+  sys.exit(1)
+os.environ.update({'GRPC_DNS_RESOLVER': 'ares'})
+
+def wait_until_dns_server_is_up(args,
+                                dns_server_subprocess,
+                                dns_server_subprocess_output):
+  for i in range(0, 30):
+    test_runner_log('Health check: attempt to connect to DNS server over TCP.')
+    tcp_connect_subprocess = subprocess.Popen([
+        args.tcp_connect_bin_path,
+        '--server_host', '127.0.0.1',
+        '--server_port', str(args.dns_server_port),
+        '--timeout', str(1)])
+    tcp_connect_subprocess.communicate()
+    if tcp_connect_subprocess.returncode == 0:
+      test_runner_log(('Health check: attempt to make an A-record '
+                       'query to DNS server.'))
+      dns_resolver_subprocess = subprocess.Popen([
+          args.dns_resolver_bin_path,
+          '--qname', 'health-check-local-dns-server-is-alive.resolver-tests.grpctestingexp',
+          '--server_host', '127.0.0.1',
+          '--server_port', str(args.dns_server_port)],
+          stdout=subprocess.PIPE)
+      dns_resolver_stdout, _ = dns_resolver_subprocess.communicate()
+      if dns_resolver_subprocess.returncode == 0:
+        if '123.123.123.123' in dns_resolver_stdout:
+          test_runner_log(('DNS server is up! '
+                           'Successfully reached it over UDP and TCP.'))
+        return
+    time.sleep(0.1)
+  dns_server_subprocess.kill()
+  dns_server_subprocess.wait()
+  test_runner_log(('Failed to reach DNS server over TCP and/or UDP. '
+                   'Exitting without running tests.'))
+  test_runner_log('======= DNS server stdout '
+                  '(merged stdout and stderr) =============')
+  with open(dns_server_subprocess_output, 'r') as l:
+    test_runner_log(l.read())
+  test_runner_log('======= end DNS server output=========')
+  sys.exit(1)
+
+dns_server_subprocess_output = tempfile.mktemp()
+with open(dns_server_subprocess_output, 'w') as l:
+  dns_server_subprocess = subprocess.Popen([
+      args.dns_server_bin_path,
+      '--port', str(args.dns_server_port),
+      '--records_config_path', args.records_config_path],
+      stdin=subprocess.PIPE,
+      stdout=l,
+      stderr=l)
+
+def _quit_on_signal(signum, _frame):
+  test_runner_log('Received signal: %d' % signum)
+  dns_server_subprocess.kill()
+  dns_server_subprocess.wait()
+  sys.exit(1)
+
+signal.signal(signal.SIGINT, _quit_on_signal)
+signal.signal(signal.SIGTERM, _quit_on_signal)
+wait_until_dns_server_is_up(args,
+                            dns_server_subprocess,
+                            dns_server_subprocess_output)
+num_test_failures = 0
+
+test_runner_log('Run test with target: %s' % 'srv-ipv4-single-target.resolver-tests-version-4.grpctestingexp.')
+current_test_subprocess = subprocess.Popen([
+  args.test_bin_path,
+  '--target_name', 'srv-ipv4-single-target.resolver-tests-version-4.grpctestingexp.',
+  '--expected_addrs', '1.2.3.4:1234,True',
+  '--expected_chosen_service_config', '',
+  '--expected_lb_policy', '',
+  '--local_dns_server_address', '127.0.0.1:%d' % args.dns_server_port])
+current_test_subprocess.communicate()
+if current_test_subprocess.returncode != 0:
+  num_test_failures += 1
+
+test_runner_log('Run test with target: %s' % 'srv-ipv4-multi-target.resolver-tests-version-4.grpctestingexp.')
+current_test_subprocess = subprocess.Popen([
+  args.test_bin_path,
+  '--target_name', 'srv-ipv4-multi-target.resolver-tests-version-4.grpctestingexp.',
+  '--expected_addrs', '1.2.3.5:1234,True;1.2.3.6:1234,True;1.2.3.7:1234,True',
+  '--expected_chosen_service_config', '',
+  '--expected_lb_policy', '',
+  '--local_dns_server_address', '127.0.0.1:%d' % args.dns_server_port])
+current_test_subprocess.communicate()
+if current_test_subprocess.returncode != 0:
+  num_test_failures += 1
+
+test_runner_log('Run test with target: %s' % 'srv-ipv6-single-target.resolver-tests-version-4.grpctestingexp.')
+current_test_subprocess = subprocess.Popen([
+  args.test_bin_path,
+  '--target_name', 'srv-ipv6-single-target.resolver-tests-version-4.grpctestingexp.',
+  '--expected_addrs', '[2607:f8b0:400a:801::1001]:1234,True',
+  '--expected_chosen_service_config', '',
+  '--expected_lb_policy', '',
+  '--local_dns_server_address', '127.0.0.1:%d' % args.dns_server_port])
+current_test_subprocess.communicate()
+if current_test_subprocess.returncode != 0:
+  num_test_failures += 1
+
+test_runner_log('Run test with target: %s' % 'srv-ipv6-multi-target.resolver-tests-version-4.grpctestingexp.')
+current_test_subprocess = subprocess.Popen([
+  args.test_bin_path,
+  '--target_name', 'srv-ipv6-multi-target.resolver-tests-version-4.grpctestingexp.',
+  '--expected_addrs', '[2607:f8b0:400a:801::1002]:1234,True;[2607:f8b0:400a:801::1003]:1234,True;[2607:f8b0:400a:801::1004]:1234,True',
+  '--expected_chosen_service_config', '',
+  '--expected_lb_policy', '',
+  '--local_dns_server_address', '127.0.0.1:%d' % args.dns_server_port])
+current_test_subprocess.communicate()
+if current_test_subprocess.returncode != 0:
+  num_test_failures += 1
+
+test_runner_log('Run test with target: %s' % 'srv-ipv4-simple-service-config.resolver-tests-version-4.grpctestingexp.')
+current_test_subprocess = subprocess.Popen([
+  args.test_bin_path,
+  '--target_name', 'srv-ipv4-simple-service-config.resolver-tests-version-4.grpctestingexp.',
+  '--expected_addrs', '1.2.3.4:1234,True',
+  '--expected_chosen_service_config', '{"loadBalancingPolicy":"round_robin","methodConfig":[{"name":[{"method":"Foo","service":"SimpleService","waitForReady":true}]}]}',
+  '--expected_lb_policy', 'round_robin',
+  '--local_dns_server_address', '127.0.0.1:%d' % args.dns_server_port])
+current_test_subprocess.communicate()
+if current_test_subprocess.returncode != 0:
+  num_test_failures += 1
+
+test_runner_log('Run test with target: %s' % 'ipv4-no-srv-simple-service-config.resolver-tests-version-4.grpctestingexp.')
+current_test_subprocess = subprocess.Popen([
+  args.test_bin_path,
+  '--target_name', 'ipv4-no-srv-simple-service-config.resolver-tests-version-4.grpctestingexp.',
+  '--expected_addrs', '1.2.3.4:443,False',
+  '--expected_chosen_service_config', '{"loadBalancingPolicy":"round_robin","methodConfig":[{"name":[{"method":"Foo","service":"NoSrvSimpleService","waitForReady":true}]}]}',
+  '--expected_lb_policy', 'round_robin',
+  '--local_dns_server_address', '127.0.0.1:%d' % args.dns_server_port])
+current_test_subprocess.communicate()
+if current_test_subprocess.returncode != 0:
+  num_test_failures += 1
+
+test_runner_log('Run test with target: %s' % 'ipv4-no-config-for-cpp.resolver-tests-version-4.grpctestingexp.')
+current_test_subprocess = subprocess.Popen([
+  args.test_bin_path,
+  '--target_name', 'ipv4-no-config-for-cpp.resolver-tests-version-4.grpctestingexp.',
+  '--expected_addrs', '1.2.3.4:443,False',
+  '--expected_chosen_service_config', '',
+  '--expected_lb_policy', '',
+  '--local_dns_server_address', '127.0.0.1:%d' % args.dns_server_port])
+current_test_subprocess.communicate()
+if current_test_subprocess.returncode != 0:
+  num_test_failures += 1
+
+test_runner_log('Run test with target: %s' % 'ipv4-cpp-config-has-zero-percentage.resolver-tests-version-4.grpctestingexp.')
+current_test_subprocess = subprocess.Popen([
+  args.test_bin_path,
+  '--target_name', 'ipv4-cpp-config-has-zero-percentage.resolver-tests-version-4.grpctestingexp.',
+  '--expected_addrs', '1.2.3.4:443,False',
+  '--expected_chosen_service_config', '',
+  '--expected_lb_policy', '',
+  '--local_dns_server_address', '127.0.0.1:%d' % args.dns_server_port])
+current_test_subprocess.communicate()
+if current_test_subprocess.returncode != 0:
+  num_test_failures += 1
+
+test_runner_log('Run test with target: %s' % 'ipv4-second-language-is-cpp.resolver-tests-version-4.grpctestingexp.')
+current_test_subprocess = subprocess.Popen([
+  args.test_bin_path,
+  '--target_name', 'ipv4-second-language-is-cpp.resolver-tests-version-4.grpctestingexp.',
+  '--expected_addrs', '1.2.3.4:443,False',
+  '--expected_chosen_service_config', '{"loadBalancingPolicy":"round_robin","methodConfig":[{"name":[{"method":"Foo","service":"CppService","waitForReady":true}]}]}',
+  '--expected_lb_policy', 'round_robin',
+  '--local_dns_server_address', '127.0.0.1:%d' % args.dns_server_port])
+current_test_subprocess.communicate()
+if current_test_subprocess.returncode != 0:
+  num_test_failures += 1
+
+test_runner_log('Run test with target: %s' % 'ipv4-config-with-percentages.resolver-tests-version-4.grpctestingexp.')
+current_test_subprocess = subprocess.Popen([
+  args.test_bin_path,
+  '--target_name', 'ipv4-config-with-percentages.resolver-tests-version-4.grpctestingexp.',
+  '--expected_addrs', '1.2.3.4:443,False',
+  '--expected_chosen_service_config', '{"loadBalancingPolicy":"round_robin","methodConfig":[{"name":[{"method":"Foo","service":"AlwaysPickedService","waitForReady":true}]}]}',
+  '--expected_lb_policy', 'round_robin',
+  '--local_dns_server_address', '127.0.0.1:%d' % args.dns_server_port])
+current_test_subprocess.communicate()
+if current_test_subprocess.returncode != 0:
+  num_test_failures += 1
+
+test_runner_log('Run test with target: %s' % 'srv-ipv4-target-has-backend-and-balancer.resolver-tests-version-4.grpctestingexp.')
+current_test_subprocess = subprocess.Popen([
+  args.test_bin_path,
+  '--target_name', 'srv-ipv4-target-has-backend-and-balancer.resolver-tests-version-4.grpctestingexp.',
+  '--expected_addrs', '1.2.3.4:1234,True;1.2.3.4:443,False',
+  '--expected_chosen_service_config', '',
+  '--expected_lb_policy', '',
+  '--local_dns_server_address', '127.0.0.1:%d' % args.dns_server_port])
+current_test_subprocess.communicate()
+if current_test_subprocess.returncode != 0:
+  num_test_failures += 1
+
+test_runner_log('Run test with target: %s' % 'srv-ipv6-target-has-backend-and-balancer.resolver-tests-version-4.grpctestingexp.')
+current_test_subprocess = subprocess.Popen([
+  args.test_bin_path,
+  '--target_name', 'srv-ipv6-target-has-backend-and-balancer.resolver-tests-version-4.grpctestingexp.',
+  '--expected_addrs', '[2607:f8b0:400a:801::1002]:1234,True;[2607:f8b0:400a:801::1002]:443,False',
+  '--expected_chosen_service_config', '',
+  '--expected_lb_policy', '',
+  '--local_dns_server_address', '127.0.0.1:%d' % args.dns_server_port])
+current_test_subprocess.communicate()
+if current_test_subprocess.returncode != 0:
+  num_test_failures += 1
+
+test_runner_log('Run test with target: %s' % 'ipv4-config-causing-fallback-to-tcp.resolver-tests-version-4.grpctestingexp.')
+current_test_subprocess = subprocess.Popen([
+  args.test_bin_path,
+  '--target_name', 'ipv4-config-causing-fallback-to-tcp.resolver-tests-version-4.grpctestingexp.',
+  '--expected_addrs', '1.2.3.4:443,False',
+  '--expected_chosen_service_config', '{"loadBalancingPolicy":"round_robin","methodConfig":[{"name":[{"method":"Foo","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooTwo","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooThree","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooFour","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooFive","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooSix","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooSeven","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooEight","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooNine","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooTen","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooEleven","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooTwelve","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooTwelve","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooTwelve","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooTwelve","service":"SimpleService","waitForReady":true}]}]}',
+  '--expected_lb_policy', '',
+  '--local_dns_server_address', '127.0.0.1:%d' % args.dns_server_port])
+current_test_subprocess.communicate()
+if current_test_subprocess.returncode != 0:
+  num_test_failures += 1
+
+test_runner_log('now kill DNS server')
+dns_server_subprocess.kill()
+dns_server_subprocess.wait()
+test_runner_log('%d tests failed.' % num_test_failures)
+sys.exit(num_test_failures)
diff --git a/test/cpp/naming/resolver_component_tests_runner.sh b/test/cpp/naming/resolver_component_tests_runner.sh
deleted file mode 100755
index 18b56ab..0000000
--- a/test/cpp/naming/resolver_component_tests_runner.sh
+++ /dev/null
@@ -1,183 +0,0 @@
-#!/bin/bash
-# Copyright 2015 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 file is auto-generated
-
-set -ex
-
-# all command args required in this set order
-FLAGS_test_bin_path=$(echo "$1" | grep '\--test_bin_path=' | sed 's/^--test_bin_path=//')
-FLAGS_dns_server_bin_path=$(echo "$2" | grep '\--dns_server_bin_path=' | sed 's/^--dns_server_bin_path=//')
-FLAGS_records_config_path=$(echo "$3" | grep '\--records_config_path=' | sed 's/^--records_config_path=//')
-FLAGS_dns_server_port=$(echo "$4" | grep '\--dns_server_port=' | sed 's/^--dns_server_port=//')
-FLAGS_dns_resolver_bin_path=$(echo "$5" | grep '\--dns_resolver_bin_path=' | sed 's/^--dns_resolver_bin_path=//')
-FLAGS_tcp_connect_bin_path=$(echo "$6" | grep '\--tcp_connect_bin_path=' | sed 's/^--tcp_connect_bin_path=//')
-
-for cmd_arg in "$FLAGS_test_bin_path" "$FLAGS_dns_server_bin_path" "$FLAGS_records_config_path" "$FLAGS_dns_server_port" "$FLAGS_dns_resolver_bin_path" "$FLAGS_tcp_connect_bin_path"; do
-  if [[ "$cmd_arg" == "" ]]; then
-    echo "Missing a CMD arg" && exit 1
-  fi
-done
-
-if [[ "$GRPC_DNS_RESOLVER" != "" && "$GRPC_DNS_RESOLVER" != ares ]]; then
-  echo "This test only works under GRPC_DNS_RESOLVER=ares. Have GRPC_DNS_RESOLVER=$GRPC_DNS_RESOLVER" && exit 1
-fi
-export GRPC_DNS_RESOLVER=ares
-
-"$FLAGS_dns_server_bin_path" --records_config_path="$FLAGS_records_config_path" --port="$FLAGS_dns_server_port" > /dev/null 2>&1 &
-DNS_SERVER_PID=$!
-echo "Local DNS server started. PID: $DNS_SERVER_PID"
-
-# Health check local DNS server TCP and UDP ports
-for ((i=0;i<30;i++));
-do
-  echo "Retry health-check local DNS server by attempting a DNS query and TCP handshake"
-  RETRY=0
-  $FLAGS_dns_resolver_bin_path -s 127.0.0.1 -p "$FLAGS_dns_server_port" -n health-check-local-dns-server-is-alive.resolver-tests.grpctestingexp. -t 1 | grep '123.123.123.123' || RETRY=1
-  $FLAGS_tcp_connect_bin_path -s 127.0.0.1 -p "$FLAGS_dns_server_port" -t 1 || RETRY=1
-  if [[ "$RETRY" == 0 ]]; then
-    break
-  fi;
-  sleep 0.1
-done
-
-if [[ $RETRY == 1 ]]; then
-  echo "FAILED TO START LOCAL DNS SERVER"
-  kill -SIGTERM "$DNS_SERVER_PID"
-  wait
-  exit 1
-fi
-
-function terminate_all {
-  echo "Received signal. Terminating $! and $DNS_SERVER_PID"
-  kill -SIGTERM "$!" || true
-  kill -SIGTERM "$DNS_SERVER_PID" || true
-  wait
-  exit 1
-}
-
-trap terminate_all SIGTERM SIGINT
-
-EXIT_CODE=0
-# TODO: this test should check for GCE residency and skip tests using _grpclb._tcp.* SRV records once GCE residency checks are made
-# in the resolver.
-
-$FLAGS_test_bin_path \
-  --target_name='srv-ipv4-single-target.resolver-tests-version-4.grpctestingexp.' \
-  --expected_addrs='1.2.3.4:1234,True' \
-  --expected_chosen_service_config='' \
-  --expected_lb_policy='' \
-  --local_dns_server_address="127.0.0.1:$FLAGS_dns_server_port" &
-wait "$!" || EXIT_CODE=1
-
-$FLAGS_test_bin_path \
-  --target_name='srv-ipv4-multi-target.resolver-tests-version-4.grpctestingexp.' \
-  --expected_addrs='1.2.3.5:1234,True;1.2.3.6:1234,True;1.2.3.7:1234,True' \
-  --expected_chosen_service_config='' \
-  --expected_lb_policy='' \
-  --local_dns_server_address="127.0.0.1:$FLAGS_dns_server_port" &
-wait "$!" || EXIT_CODE=1
-
-$FLAGS_test_bin_path \
-  --target_name='srv-ipv6-single-target.resolver-tests-version-4.grpctestingexp.' \
-  --expected_addrs='[2607:f8b0:400a:801::1001]:1234,True' \
-  --expected_chosen_service_config='' \
-  --expected_lb_policy='' \
-  --local_dns_server_address="127.0.0.1:$FLAGS_dns_server_port" &
-wait "$!" || EXIT_CODE=1
-
-$FLAGS_test_bin_path \
-  --target_name='srv-ipv6-multi-target.resolver-tests-version-4.grpctestingexp.' \
-  --expected_addrs='[2607:f8b0:400a:801::1002]:1234,True;[2607:f8b0:400a:801::1003]:1234,True;[2607:f8b0:400a:801::1004]:1234,True' \
-  --expected_chosen_service_config='' \
-  --expected_lb_policy='' \
-  --local_dns_server_address="127.0.0.1:$FLAGS_dns_server_port" &
-wait "$!" || EXIT_CODE=1
-
-$FLAGS_test_bin_path \
-  --target_name='srv-ipv4-simple-service-config.resolver-tests-version-4.grpctestingexp.' \
-  --expected_addrs='1.2.3.4:1234,True' \
-  --expected_chosen_service_config='{"loadBalancingPolicy":"round_robin","methodConfig":[{"name":[{"method":"Foo","service":"SimpleService","waitForReady":true}]}]}' \
-  --expected_lb_policy='round_robin' \
-  --local_dns_server_address="127.0.0.1:$FLAGS_dns_server_port" &
-wait "$!" || EXIT_CODE=1
-
-$FLAGS_test_bin_path \
-  --target_name='ipv4-no-srv-simple-service-config.resolver-tests-version-4.grpctestingexp.' \
-  --expected_addrs='1.2.3.4:443,False' \
-  --expected_chosen_service_config='{"loadBalancingPolicy":"round_robin","methodConfig":[{"name":[{"method":"Foo","service":"NoSrvSimpleService","waitForReady":true}]}]}' \
-  --expected_lb_policy='round_robin' \
-  --local_dns_server_address="127.0.0.1:$FLAGS_dns_server_port" &
-wait "$!" || EXIT_CODE=1
-
-$FLAGS_test_bin_path \
-  --target_name='ipv4-no-config-for-cpp.resolver-tests-version-4.grpctestingexp.' \
-  --expected_addrs='1.2.3.4:443,False' \
-  --expected_chosen_service_config='' \
-  --expected_lb_policy='' \
-  --local_dns_server_address="127.0.0.1:$FLAGS_dns_server_port" &
-wait "$!" || EXIT_CODE=1
-
-$FLAGS_test_bin_path \
-  --target_name='ipv4-cpp-config-has-zero-percentage.resolver-tests-version-4.grpctestingexp.' \
-  --expected_addrs='1.2.3.4:443,False' \
-  --expected_chosen_service_config='' \
-  --expected_lb_policy='' \
-  --local_dns_server_address="127.0.0.1:$FLAGS_dns_server_port" &
-wait "$!" || EXIT_CODE=1
-
-$FLAGS_test_bin_path \
-  --target_name='ipv4-second-language-is-cpp.resolver-tests-version-4.grpctestingexp.' \
-  --expected_addrs='1.2.3.4:443,False' \
-  --expected_chosen_service_config='{"loadBalancingPolicy":"round_robin","methodConfig":[{"name":[{"method":"Foo","service":"CppService","waitForReady":true}]}]}' \
-  --expected_lb_policy='round_robin' \
-  --local_dns_server_address="127.0.0.1:$FLAGS_dns_server_port" &
-wait "$!" || EXIT_CODE=1
-
-$FLAGS_test_bin_path \
-  --target_name='ipv4-config-with-percentages.resolver-tests-version-4.grpctestingexp.' \
-  --expected_addrs='1.2.3.4:443,False' \
-  --expected_chosen_service_config='{"loadBalancingPolicy":"round_robin","methodConfig":[{"name":[{"method":"Foo","service":"AlwaysPickedService","waitForReady":true}]}]}' \
-  --expected_lb_policy='round_robin' \
-  --local_dns_server_address="127.0.0.1:$FLAGS_dns_server_port" &
-wait "$!" || EXIT_CODE=1
-
-$FLAGS_test_bin_path \
-  --target_name='srv-ipv4-target-has-backend-and-balancer.resolver-tests-version-4.grpctestingexp.' \
-  --expected_addrs='1.2.3.4:1234,True;1.2.3.4:443,False' \
-  --expected_chosen_service_config='' \
-  --expected_lb_policy='' \
-  --local_dns_server_address="127.0.0.1:$FLAGS_dns_server_port" &
-wait "$!" || EXIT_CODE=1
-
-$FLAGS_test_bin_path \
-  --target_name='srv-ipv6-target-has-backend-and-balancer.resolver-tests-version-4.grpctestingexp.' \
-  --expected_addrs='[2607:f8b0:400a:801::1002]:1234,True;[2607:f8b0:400a:801::1002]:443,False' \
-  --expected_chosen_service_config='' \
-  --expected_lb_policy='' \
-  --local_dns_server_address="127.0.0.1:$FLAGS_dns_server_port" &
-wait "$!" || EXIT_CODE=1
-
-$FLAGS_test_bin_path \
-  --target_name='ipv4-config-causing-fallback-to-tcp.resolver-tests-version-4.grpctestingexp.' \
-  --expected_addrs='1.2.3.4:443,False' \
-  --expected_chosen_service_config='{"loadBalancingPolicy":"round_robin","methodConfig":[{"name":[{"method":"Foo","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooTwo","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooThree","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooFour","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooFive","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooSix","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooSeven","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooEight","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooNine","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooTen","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooEleven","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooTwelve","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooTwelve","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooTwelve","service":"SimpleService","waitForReady":true}]},{"name":[{"method":"FooTwelve","service":"SimpleService","waitForReady":true}]}]}' \
-  --expected_lb_policy='' \
-  --local_dns_server_address="127.0.0.1:$FLAGS_dns_server_port" &
-wait "$!" || EXIT_CODE=1
-
-kill -SIGTERM "$DNS_SERVER_PID" || true
-wait
-exit $EXIT_CODE
diff --git a/test/cpp/naming/resolver_component_tests_runner_invoker.cc b/test/cpp/naming/resolver_component_tests_runner_invoker.cc
index b2a7890..45c1029 100644
--- a/test/cpp/naming/resolver_component_tests_runner_invoker.cc
+++ b/test/cpp/naming/resolver_component_tests_runner_invoker.cc
@@ -165,9 +165,9 @@
     GPR_ASSERT(FLAGS_grpc_test_directory_relative_to_test_srcdir != "");
     // Use bazel's TEST_SRCDIR environment variable to locate the "test data"
     // binaries.
+    char* test_srcdir = gpr_getenv("TEST_SRCDIR");
     std::string const bin_dir =
-        gpr_getenv("TEST_SRCDIR") +
-        FLAGS_grpc_test_directory_relative_to_test_srcdir +
+        test_srcdir + FLAGS_grpc_test_directory_relative_to_test_srcdir +
         std::string("/test/cpp/naming");
     // Invoke bazel's executeable links to the .sh and .py scripts (don't use
     // the .sh and .py suffixes) to make
@@ -177,13 +177,14 @@
         bin_dir + "/" + FLAGS_test_bin_name, bin_dir + "/utils/dns_server",
         bin_dir + "/resolver_test_record_groups.yaml",
         bin_dir + "/utils/dns_resolver", bin_dir + "/utils/tcp_connect");
+    gpr_free(test_srcdir);
   } else {
     // Get the current binary's directory relative to repo root to invoke the
     // correct build config (asan/tsan/dbg, etc.).
     std::string const bin_dir = my_bin.substr(0, my_bin.rfind('/'));
     // Invoke the .sh and .py scripts directly where they are in source code.
     grpc::testing::InvokeResolverComponentTestsRunner(
-        "test/cpp/naming/resolver_component_tests_runner.sh",
+        "test/cpp/naming/resolver_component_tests_runner.py",
         bin_dir + "/" + FLAGS_test_bin_name,
         "test/cpp/naming/utils/dns_server.py",
         "test/cpp/naming/resolver_test_record_groups.yaml",
diff --git a/test/cpp/naming/utils/dns_resolver.py b/test/cpp/naming/utils/dns_resolver.py
index 6b27244..74f4ca2 100755
--- a/test/cpp/naming/utils/dns_resolver.py
+++ b/test/cpp/naming/utils/dns_resolver.py
@@ -16,9 +16,12 @@
 """Makes DNS queries for A records to specified servers"""
 
 import argparse
-import signal
+import threading
+import time
 import twisted.internet.task as task
 import twisted.names.client as client
+import twisted.internet.reactor as reactor
+
 
 def main():
   argp = argparse.ArgumentParser(description='Make DNS queries for A records')
@@ -31,7 +34,6 @@
   argp.add_argument('-t', '--timeout', default=1, type=int,
                     help=('Force process exit after this number of seconds.'))
   args = argp.parse_args()
-  signal.alarm(args.timeout)
   def OnResolverResultAvailable(result):
     answers, authority, additional = result
     for a in answers:
diff --git a/test/cpp/naming/utils/dns_server.py b/test/cpp/naming/utils/dns_server.py
index 9f42f65..1e8e2e3 100755
--- a/test/cpp/naming/utils/dns_server.py
+++ b/test/cpp/naming/utils/dns_server.py
@@ -20,6 +20,8 @@
 import yaml
 import signal
 import os
+import threading
+import time
 
 import twisted
 import twisted.internet
@@ -33,6 +35,7 @@
 import twisted.names.server
 from twisted.names import client, server, common, authority, dns
 import argparse
+import platform
 
 _SERVER_HEALTH_CHECK_RECORD_NAME = 'health-check-local-dns-server-is-alive.resolver-tests.grpctestingexp' # missing end '.' for twisted syntax
 _SERVER_HEALTH_CHECK_RECORD_DATA = '123.123.123.123'
@@ -115,6 +118,18 @@
   sys.stdout.flush()
   sys.exit(0)
 
+def flush_stdout_loop():
+  num_timeouts_so_far = 0
+  sleep_time = 1
+  # Prevent zombies. Tests that use this server are short-lived.
+  max_timeouts = 60 * 2
+  while num_timeouts_so_far < max_timeouts:
+    sys.stdout.flush()
+    time.sleep(sleep_time)
+    num_timeouts_so_far += 1
+  print('Process timeout reached, or cancelled. Exitting 0.')
+  os.kill(os.getpid(), signal.SIGTERM)
+
 def main():
   argp = argparse.ArgumentParser(description='Local DNS Server for resolver tests')
   argp.add_argument('-p', '--port', default=None, type=int,
@@ -123,11 +138,11 @@
                     help=('Directory of resolver_test_record_groups.yaml file. '
                           'Defauls to path needed when the test is invoked as part of run_tests.py.'))
   args = argp.parse_args()
-  signal.signal(signal.SIGALRM, _quit_on_signal)
   signal.signal(signal.SIGTERM, _quit_on_signal)
   signal.signal(signal.SIGINT, _quit_on_signal)
-  # Prevent zombies. Tests that use this server are short-lived.
-  signal.alarm(2 * 60)
+  output_flush_thread = threading.Thread(target=flush_stdout_loop)
+  output_flush_thread.setDaemon(True)
+  output_flush_thread.start()
   start_local_dns_server(args)
 
 if __name__ == '__main__':
diff --git a/test/cpp/naming/utils/tcp_connect.py b/test/cpp/naming/utils/tcp_connect.py
index bf7455e..5773c7c 100755
--- a/test/cpp/naming/utils/tcp_connect.py
+++ b/test/cpp/naming/utils/tcp_connect.py
@@ -16,8 +16,11 @@
 """Opens a TCP connection to a specified server and then exits."""
 
 import argparse
-import signal
 import socket
+import threading
+import time
+import sys
+
 
 def main():
   argp = argparse.ArgumentParser(description='Open a TCP handshake to a server')
@@ -28,7 +31,6 @@
   argp.add_argument('-t', '--timeout', default=1, type=int,
                     help='Force process exit after this number of seconds.')
   args = argp.parse_args()
-  signal.alarm(args.timeout)
   socket.create_connection([args.server_host, args.server_port])
 
 if __name__ == '__main__':
diff --git a/test/cpp/qps/BUILD b/test/cpp/qps/BUILD
index f1abb19..a348b88 100644
--- a/test/cpp/qps/BUILD
+++ b/test/cpp/qps/BUILD
@@ -47,9 +47,10 @@
         "//:grpc",
         "//:grpc++",
         "//:grpc++_core_stats",
+        "//src/proto/grpc/testing:benchmark_service_proto",
         "//src/proto/grpc/testing:control_proto",
         "//src/proto/grpc/testing:payloads_proto",
-        "//src/proto/grpc/testing:services_proto",
+        "//src/proto/grpc/testing:worker_service_proto",
         "//test/core/end2end:ssl_test_data",
         "//test/core/util:gpr_test_util",
         "//test/core/util:grpc_test_util",
@@ -74,7 +75,8 @@
         "//:grpc++",
         "//src/proto/grpc/testing:control_proto",
         "//src/proto/grpc/testing:messages_proto",
-        "//src/proto/grpc/testing:services_proto",
+        "//src/proto/grpc/testing:report_qps_scenario_service_proto",
+        "//src/proto/grpc/testing:worker_service_proto",
         "//test/core/util:gpr_test_util",
         "//test/core/util:grpc_test_util",
         "//test/cpp/util:test_util",
diff --git a/test/cpp/qps/client.h b/test/cpp/qps/client.h
index 77743a1..31ae6ca 100644
--- a/test/cpp/qps/client.h
+++ b/test/cpp/qps/client.h
@@ -31,8 +31,8 @@
 #include <grpcpp/support/channel_arguments.h>
 #include <grpcpp/support/slice.h>
 
+#include "src/proto/grpc/testing/benchmark_service.grpc.pb.h"
 #include "src/proto/grpc/testing/payloads.pb.h"
-#include "src/proto/grpc/testing/services.grpc.pb.h"
 
 #include "src/cpp/util/core_stats.h"
 #include "test/cpp/qps/histogram.h"
diff --git a/test/cpp/qps/client_async.cc b/test/cpp/qps/client_async.cc
index f9bef91..c79a10d 100644
--- a/test/cpp/qps/client_async.cc
+++ b/test/cpp/qps/client_async.cc
@@ -35,7 +35,7 @@
 #include <grpcpp/generic/generic_stub.h>
 
 #include "src/core/lib/surface/completion_queue.h"
-#include "src/proto/grpc/testing/services.grpc.pb.h"
+#include "src/proto/grpc/testing/benchmark_service.grpc.pb.h"
 #include "test/cpp/qps/client.h"
 #include "test/cpp/qps/usage_timer.h"
 #include "test/cpp/util/create_test_channel.h"
diff --git a/test/cpp/qps/client_sync.cc b/test/cpp/qps/client_sync.cc
index 5185eef..e65e3b4 100644
--- a/test/cpp/qps/client_sync.cc
+++ b/test/cpp/qps/client_sync.cc
@@ -35,7 +35,7 @@
 
 #include "src/core/lib/gpr/host_port.h"
 #include "src/core/lib/profiling/timers.h"
-#include "src/proto/grpc/testing/services.grpc.pb.h"
+#include "src/proto/grpc/testing/benchmark_service.grpc.pb.h"
 #include "test/cpp/qps/client.h"
 #include "test/cpp/qps/interarrival.h"
 #include "test/cpp/qps/usage_timer.h"
diff --git a/test/cpp/qps/driver.cc b/test/cpp/qps/driver.cc
index 361ee43..34f1291 100644
--- a/test/cpp/qps/driver.cc
+++ b/test/cpp/qps/driver.cc
@@ -33,6 +33,7 @@
 #include "src/core/lib/gpr/env.h"
 #include "src/core/lib/gpr/host_port.h"
 #include "src/core/lib/profiling/timers.h"
+#include "src/proto/grpc/testing/worker_service.grpc.pb.h"
 #include "test/core/util/port.h"
 #include "test/core/util/test_config.h"
 #include "test/cpp/qps/client.h"
diff --git a/test/cpp/qps/gen_build_yaml.py b/test/cpp/qps/gen_build_yaml.py
index 1ef8f65..776283c 100755
--- a/test/cpp/qps/gen_build_yaml.py
+++ b/test/cpp/qps/gen_build_yaml.py
@@ -63,6 +63,11 @@
   return (scenario_json['num_clients'] * client +
           scenario_json['num_servers'] * server)
 
+def maybe_exclude_gcov(scenario_json):
+  if scenario_json['client_config']['client_channels'] > 100:
+    return ['gcov']
+  return []
+
 print yaml.dump({
   'tests': [
     {
@@ -76,7 +81,7 @@
       'boringssl': True,
       'defaults': 'boringssl',
       'cpu_cost': guess_cpu(scenario_json, False),
-      'exclude_configs': ['tsan', 'asan'],
+      'exclude_configs': ['tsan', 'asan'] + maybe_exclude_gcov(scenario_json),
       'timeout_seconds': 2*60,
       'excluded_poll_engines': scenario_json.get('EXCLUDED_POLL_ENGINES', []),
       'auto_timeout_scaling': False
diff --git a/test/cpp/qps/qps_worker.cc b/test/cpp/qps/qps_worker.cc
index aaffb1d..d3f0380 100644
--- a/test/cpp/qps/qps_worker.cc
+++ b/test/cpp/qps/qps_worker.cc
@@ -35,7 +35,7 @@
 #include <grpcpp/server_builder.h>
 
 #include "src/core/lib/gpr/host_port.h"
-#include "src/proto/grpc/testing/services.pb.h"
+#include "src/proto/grpc/testing/worker_service.grpc.pb.h"
 #include "test/core/util/grpc_profiler.h"
 #include "test/core/util/histogram.h"
 #include "test/cpp/qps/client.h"
diff --git a/test/cpp/qps/report.cc b/test/cpp/qps/report.cc
index 0a2565d..607f4e5 100644
--- a/test/cpp/qps/report.cc
+++ b/test/cpp/qps/report.cc
@@ -27,7 +27,7 @@
 
 #include <grpcpp/client_context.h>
 #include "src/cpp/util/core_stats.h"
-#include "src/proto/grpc/testing/services.grpc.pb.h"
+#include "src/proto/grpc/testing/report_qps_scenario_service.grpc.pb.h"
 
 namespace grpc {
 namespace testing {
diff --git a/test/cpp/qps/report.h b/test/cpp/qps/report.h
index c5dd138..8e62f4f 100644
--- a/test/cpp/qps/report.h
+++ b/test/cpp/qps/report.h
@@ -28,7 +28,7 @@
 #include "test/cpp/qps/driver.h"
 
 #include <grpcpp/channel.h>
-#include "src/proto/grpc/testing/services.grpc.pb.h"
+#include "src/proto/grpc/testing/report_qps_scenario_service.grpc.pb.h"
 
 namespace grpc {
 namespace testing {
diff --git a/test/cpp/qps/server_async.cc b/test/cpp/qps/server_async.cc
index 9cb05cd..1dfef6c 100644
--- a/test/cpp/qps/server_async.cc
+++ b/test/cpp/qps/server_async.cc
@@ -36,7 +36,7 @@
 
 #include "src/core/lib/gpr/host_port.h"
 #include "src/core/lib/surface/completion_queue.h"
-#include "src/proto/grpc/testing/services.grpc.pb.h"
+#include "src/proto/grpc/testing/benchmark_service.grpc.pb.h"
 #include "test/core/util/test_config.h"
 #include "test/cpp/qps/server.h"
 
diff --git a/test/cpp/qps/server_sync.cc b/test/cpp/qps/server_sync.cc
index 9dfd362..82a9186 100644
--- a/test/cpp/qps/server_sync.cc
+++ b/test/cpp/qps/server_sync.cc
@@ -26,7 +26,7 @@
 #include <grpcpp/server_context.h>
 
 #include "src/core/lib/gpr/host_port.h"
-#include "src/proto/grpc/testing/services.grpc.pb.h"
+#include "src/proto/grpc/testing/benchmark_service.grpc.pb.h"
 #include "test/cpp/qps/server.h"
 #include "test/cpp/qps/usage_timer.h"
 
diff --git a/test/cpp/server/BUILD b/test/cpp/server/BUILD
index 7538845..3f89d6e 100644
--- a/test/cpp/server/BUILD
+++ b/test/cpp/server/BUILD
@@ -32,6 +32,19 @@
 )
 
 grpc_cc_test(
+    name = "server_builder_with_socket_mutator_test",
+    srcs = ["server_builder_with_socket_mutator_test.cc"],
+    deps = [
+        "//:grpc++_unsecure",
+        "//src/proto/grpc/testing:echo_proto",
+        "//test/core/util:grpc_test_util_unsecure",
+    ],
+    external_deps = [
+        "gtest",
+    ],
+)
+
+grpc_cc_test(
     name = "server_request_call_test",
     srcs = ["server_request_call_test.cc"],
     deps = [
diff --git a/test/cpp/server/load_reporter/BUILD b/test/cpp/server/load_reporter/BUILD
new file mode 100644
index 0000000..5cb3a00
--- /dev/null
+++ b/test/cpp/server/load_reporter/BUILD
@@ -0,0 +1,31 @@
+# Copyright 2017 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.
+
+licenses(["notice"])  # Apache v2
+
+load("//bazel:grpc_build_system.bzl", "grpc_cc_test", "grpc_cc_library", "grpc_cc_binary", "grpc_package")
+
+grpc_package(name = "test/cpp/server/load_reporter")
+
+grpc_cc_test(
+    name = "lb_load_data_store_test",
+    srcs = ["load_data_store_test.cc"],
+    external_deps = [
+        "gtest",
+    ],
+    deps = [
+        "//:lb_load_data_store",
+        "//test/core/util:grpc_test_util",
+    ],
+)
diff --git a/test/cpp/server/load_reporter/load_data_store_test.cc b/test/cpp/server/load_reporter/load_data_store_test.cc
new file mode 100644
index 0000000..8280dee
--- /dev/null
+++ b/test/cpp/server/load_reporter/load_data_store_test.cc
@@ -0,0 +1,481 @@
+/*
+ *
+ * Copyright 2018 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.
+ *
+ */
+
+#include <grpc/impl/codegen/port_platform.h>
+
+#include <set>
+#include <vector>
+
+#include <grpc/grpc.h>
+#include <gtest/gtest.h>
+
+#include "src/cpp/server/load_reporter/load_data_store.h"
+#include "test/core/util/port.h"
+#include "test/core/util/test_config.h"
+
+namespace grpc {
+namespace testing {
+namespace {
+
+using ::grpc::load_reporter::CallMetricValue;
+using ::grpc::load_reporter::LoadDataStore;
+using ::grpc::load_reporter::LoadRecordKey;
+using ::grpc::load_reporter::LoadRecordValue;
+using ::grpc::load_reporter::PerBalancerStore;
+using ::grpc::load_reporter::kInvalidLbId;
+
+class LoadDataStoreTest : public ::testing::Test {
+ public:
+  LoadDataStoreTest()
+      : kKey1(kLbId1, kLbTag1, kUser1, kClientIp1),
+        kKey2(kLbId2, kLbTag2, kUser2, kClientIp2) {}
+
+  // Check whether per_balancer_stores contains a store which was originally
+  // created for <hostname, lb_id, and load_key>.
+  bool PerBalancerStoresContains(
+      const LoadDataStore& load_data_store,
+      const std::set<PerBalancerStore*>* per_balancer_stores,
+      const grpc::string hostname, const grpc::string lb_id,
+      const grpc::string load_key) {
+    auto original_per_balancer_store =
+        load_data_store.FindPerBalancerStore(hostname, lb_id);
+    EXPECT_NE(original_per_balancer_store, nullptr);
+    EXPECT_EQ(original_per_balancer_store->lb_id(), lb_id);
+    EXPECT_EQ(original_per_balancer_store->load_key(), load_key);
+    for (auto per_balancer_store : *per_balancer_stores) {
+      if (per_balancer_store == original_per_balancer_store) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  grpc::string FormatLbId(size_t index) {
+    return "kLbId" + std::to_string(index);
+  }
+
+  const grpc::string kHostname1 = "kHostname1";
+  const grpc::string kHostname2 = "kHostname2";
+  const grpc::string kLbId1 = "kLbId1";
+  const grpc::string kLbId2 = "kLbId2";
+  const grpc::string kLbId3 = "kLbId3";
+  const grpc::string kLbId4 = "kLbId4";
+  const grpc::string kLoadKey1 = "kLoadKey1";
+  const grpc::string kLoadKey2 = "kLoadKey2";
+  const grpc::string kLbTag1 = "kLbTag1";
+  const grpc::string kLbTag2 = "kLbTag2";
+  const grpc::string kUser1 = "kUser1";
+  const grpc::string kUser2 = "kUser2";
+  const grpc::string kClientIp1 = "00";
+  const grpc::string kClientIp2 = "02";
+  const grpc::string kMetric1 = "kMetric1";
+  const grpc::string kMetric2 = "kMetric2";
+  const LoadRecordKey kKey1;
+  const LoadRecordKey kKey2;
+};
+
+using PerBalancerStoreTest = LoadDataStoreTest;
+
+TEST_F(LoadDataStoreTest, AssignToSelf) {
+  LoadDataStore load_data_store;
+  load_data_store.ReportStreamCreated(kHostname1, kLbId1, kLoadKey1);
+  auto assigned_stores = load_data_store.GetAssignedStores(kHostname1, kLbId1);
+  EXPECT_TRUE(PerBalancerStoresContains(load_data_store, assigned_stores,
+                                        kHostname1, kLbId1, kLoadKey1));
+}
+
+TEST_F(LoadDataStoreTest, ReassignOrphanStores) {
+  LoadDataStore load_data_store;
+  load_data_store.ReportStreamCreated(kHostname1, kLbId1, kLoadKey1);
+  load_data_store.ReportStreamCreated(kHostname1, kLbId2, kLoadKey1);
+  load_data_store.ReportStreamCreated(kHostname1, kLbId3, kLoadKey2);
+  load_data_store.ReportStreamCreated(kHostname2, kLbId4, kLoadKey1);
+  // 1. Close the second stream.
+  load_data_store.ReportStreamClosed(kHostname1, kLbId2);
+  auto assigned_to_lb_id_1 =
+      load_data_store.GetAssignedStores(kHostname1, kLbId1);
+  // The orphaned store is re-assigned to kLbId1 with the same load key.
+  EXPECT_TRUE(PerBalancerStoresContains(load_data_store, assigned_to_lb_id_1,
+                                        kHostname1, kLbId1, kLoadKey1));
+  EXPECT_TRUE(PerBalancerStoresContains(load_data_store, assigned_to_lb_id_1,
+                                        kHostname1, kLbId2, kLoadKey1));
+  // 2. Close the first stream.
+  load_data_store.ReportStreamClosed(kHostname1, kLbId1);
+  auto assigned_to_lb_id_3 =
+      load_data_store.GetAssignedStores(kHostname1, kLbId3);
+  // The orphaned stores are re-assigned to kLbId3 with the same host,
+  // because there isn't any LB with the same load key.
+  EXPECT_TRUE(PerBalancerStoresContains(load_data_store, assigned_to_lb_id_3,
+                                        kHostname1, kLbId1, kLoadKey1));
+  EXPECT_TRUE(PerBalancerStoresContains(load_data_store, assigned_to_lb_id_3,
+                                        kHostname1, kLbId2, kLoadKey1));
+  EXPECT_TRUE(PerBalancerStoresContains(load_data_store, assigned_to_lb_id_3,
+                                        kHostname1, kLbId3, kLoadKey2));
+  // 3. Close the third stream.
+  load_data_store.ReportStreamClosed(kHostname1, kLbId3);
+  auto assigned_to_lb_id_4 =
+      load_data_store.GetAssignedStores(kHostname2, kLbId4);
+  // There is no active LB for the first host now. kLbId4 is active but
+  // it's for the second host, so it wll NOT adopt the orphaned stores.
+  EXPECT_FALSE(PerBalancerStoresContains(load_data_store, assigned_to_lb_id_4,
+                                         kHostname1, kLbId1, kLoadKey1));
+  EXPECT_FALSE(PerBalancerStoresContains(load_data_store, assigned_to_lb_id_4,
+                                         kHostname1, kLbId2, kLoadKey1));
+  EXPECT_FALSE(PerBalancerStoresContains(load_data_store, assigned_to_lb_id_4,
+                                         kHostname1, kLbId3, kLoadKey2));
+  EXPECT_TRUE(PerBalancerStoresContains(load_data_store, assigned_to_lb_id_4,
+                                        kHostname2, kLbId4, kLoadKey1));
+}
+
+TEST_F(LoadDataStoreTest, OrphanAssignmentIsSticky) {
+  LoadDataStore load_data_store;
+  std::set<grpc::string> active_lb_ids;
+  size_t num_lb_ids = 1000;
+  for (size_t i = 0; i < num_lb_ids; ++i) {
+    load_data_store.ReportStreamCreated(kHostname1, FormatLbId(i), kLoadKey1);
+    active_lb_ids.insert(FormatLbId(i));
+  }
+  grpc::string orphaned_lb_id = FormatLbId(std::rand() % num_lb_ids);
+  load_data_store.ReportStreamClosed(kHostname1, orphaned_lb_id);
+  active_lb_ids.erase(orphaned_lb_id);
+  // Find which LB is assigned the orphaned store.
+  grpc::string assigned_lb_id = "";
+  for (auto lb_id : active_lb_ids) {
+    if (PerBalancerStoresContains(
+            load_data_store,
+            load_data_store.GetAssignedStores(kHostname1, lb_id), kHostname1,
+            orphaned_lb_id, kLoadKey1)) {
+      assigned_lb_id = lb_id;
+      break;
+    }
+  }
+  EXPECT_STRNE(assigned_lb_id.c_str(), "");
+  // Close 10 more stream, skipping the assigned_lb_id. The assignment of
+  // orphaned_lb_id shouldn't change.
+  for (size_t _ = 0; _ < 10; ++_) {
+    grpc::string lb_id_to_close = "";
+    for (auto lb_id : active_lb_ids) {
+      if (lb_id != assigned_lb_id) {
+        lb_id_to_close = lb_id;
+        break;
+      }
+    }
+    EXPECT_STRNE(lb_id_to_close.c_str(), "");
+    load_data_store.ReportStreamClosed(kHostname1, lb_id_to_close);
+    active_lb_ids.erase(lb_id_to_close);
+    EXPECT_TRUE(PerBalancerStoresContains(
+        load_data_store,
+        load_data_store.GetAssignedStores(kHostname1, assigned_lb_id),
+        kHostname1, orphaned_lb_id, kLoadKey1));
+  }
+  // Close the assigned_lb_id, orphaned_lb_id will be re-assigned again.
+  load_data_store.ReportStreamClosed(kHostname1, assigned_lb_id);
+  active_lb_ids.erase(assigned_lb_id);
+  size_t orphaned_lb_id_occurences = 0;
+  for (auto lb_id : active_lb_ids) {
+    if (PerBalancerStoresContains(
+            load_data_store,
+            load_data_store.GetAssignedStores(kHostname1, lb_id), kHostname1,
+            orphaned_lb_id, kLoadKey1)) {
+      orphaned_lb_id_occurences++;
+    }
+  }
+  EXPECT_EQ(orphaned_lb_id_occurences, 1U);
+}
+
+TEST_F(LoadDataStoreTest, HostTemporarilyLoseAllStreams) {
+  LoadDataStore load_data_store;
+  load_data_store.ReportStreamCreated(kHostname1, kLbId1, kLoadKey1);
+  load_data_store.ReportStreamCreated(kHostname2, kLbId2, kLoadKey1);
+  auto store_lb_id_1 = load_data_store.FindPerBalancerStore(kHostname1, kLbId1);
+  auto store_invalid_lb_id_1 =
+      load_data_store.FindPerBalancerStore(kHostname1, kInvalidLbId);
+  EXPECT_FALSE(store_lb_id_1->IsSuspended());
+  EXPECT_FALSE(store_invalid_lb_id_1->IsSuspended());
+  // Disconnect all the streams of the first host.
+  load_data_store.ReportStreamClosed(kHostname1, kLbId1);
+  // All the streams of that host are suspended.
+  EXPECT_TRUE(store_lb_id_1->IsSuspended());
+  EXPECT_TRUE(store_invalid_lb_id_1->IsSuspended());
+  // Detailed load data won't be kept when the PerBalancerStore is suspended.
+  store_lb_id_1->MergeRow(kKey1, LoadRecordValue());
+  store_invalid_lb_id_1->MergeRow(kKey1, LoadRecordValue());
+  EXPECT_EQ(store_lb_id_1->load_record_map().size(), 0U);
+  EXPECT_EQ(store_invalid_lb_id_1->load_record_map().size(), 0U);
+  // The stores for different hosts won't mix, even if the load key is the same.
+  auto assigned_to_lb_id_2 =
+      load_data_store.GetAssignedStores(kHostname2, kLbId2);
+  EXPECT_EQ(assigned_to_lb_id_2->size(), 2U);
+  EXPECT_TRUE(PerBalancerStoresContains(load_data_store, assigned_to_lb_id_2,
+                                        kHostname2, kLbId2, kLoadKey1));
+  EXPECT_TRUE(PerBalancerStoresContains(load_data_store, assigned_to_lb_id_2,
+                                        kHostname2, kInvalidLbId, ""));
+  // A new stream is created for the first host.
+  load_data_store.ReportStreamCreated(kHostname1, kLbId3, kLoadKey2);
+  // The stores for the first host are resumed.
+  EXPECT_FALSE(store_lb_id_1->IsSuspended());
+  EXPECT_FALSE(store_invalid_lb_id_1->IsSuspended());
+  store_lb_id_1->MergeRow(kKey1, LoadRecordValue());
+  store_invalid_lb_id_1->MergeRow(kKey1, LoadRecordValue());
+  EXPECT_EQ(store_lb_id_1->load_record_map().size(), 1U);
+  EXPECT_EQ(store_invalid_lb_id_1->load_record_map().size(), 1U);
+  // The resumed stores are assigned to the new LB.
+  auto assigned_to_lb_id_3 =
+      load_data_store.GetAssignedStores(kHostname1, kLbId3);
+  EXPECT_EQ(assigned_to_lb_id_3->size(), 3U);
+  EXPECT_TRUE(PerBalancerStoresContains(load_data_store, assigned_to_lb_id_3,
+                                        kHostname1, kLbId1, kLoadKey1));
+  EXPECT_TRUE(PerBalancerStoresContains(load_data_store, assigned_to_lb_id_3,
+                                        kHostname1, kInvalidLbId, ""));
+  EXPECT_TRUE(PerBalancerStoresContains(load_data_store, assigned_to_lb_id_3,
+                                        kHostname1, kLbId3, kLoadKey2));
+}
+
+TEST_F(LoadDataStoreTest, OneStorePerLbId) {
+  LoadDataStore load_data_store;
+  EXPECT_EQ(load_data_store.FindPerBalancerStore(kHostname1, kLbId1), nullptr);
+  EXPECT_EQ(load_data_store.FindPerBalancerStore(kHostname1, kInvalidLbId),
+            nullptr);
+  EXPECT_EQ(load_data_store.FindPerBalancerStore(kHostname2, kLbId2), nullptr);
+  EXPECT_EQ(load_data_store.FindPerBalancerStore(kHostname2, kLbId3), nullptr);
+  // Create The first stream.
+  load_data_store.ReportStreamCreated(kHostname1, kLbId1, kLoadKey1);
+  auto store_lb_id_1 = load_data_store.FindPerBalancerStore(kHostname1, kLbId1);
+  auto store_invalid_lb_id_1 =
+      load_data_store.FindPerBalancerStore(kHostname1, kInvalidLbId);
+  // Two stores will be created: one is for the stream; the other one is for
+  // kInvalidLbId.
+  EXPECT_NE(store_lb_id_1, nullptr);
+  EXPECT_NE(store_invalid_lb_id_1, nullptr);
+  EXPECT_NE(store_lb_id_1, store_invalid_lb_id_1);
+  EXPECT_EQ(load_data_store.FindPerBalancerStore(kHostname2, kLbId2), nullptr);
+  EXPECT_EQ(load_data_store.FindPerBalancerStore(kHostname2, kLbId3), nullptr);
+  // Create the second stream.
+  load_data_store.ReportStreamCreated(kHostname2, kLbId3, kLoadKey1);
+  auto store_lb_id_3 = load_data_store.FindPerBalancerStore(kHostname2, kLbId3);
+  auto store_invalid_lb_id_2 =
+      load_data_store.FindPerBalancerStore(kHostname2, kInvalidLbId);
+  EXPECT_NE(store_lb_id_3, nullptr);
+  EXPECT_NE(store_invalid_lb_id_2, nullptr);
+  EXPECT_NE(store_lb_id_3, store_invalid_lb_id_2);
+  // The PerBalancerStores created for different hosts are independent.
+  EXPECT_NE(store_lb_id_3, store_invalid_lb_id_1);
+  EXPECT_NE(store_invalid_lb_id_2, store_invalid_lb_id_1);
+  EXPECT_EQ(load_data_store.FindPerBalancerStore(kHostname2, kLbId2), nullptr);
+}
+
+TEST_F(LoadDataStoreTest, ExactlyOnceAssignment) {
+  LoadDataStore load_data_store;
+  size_t num_create = 100;
+  size_t num_close = 50;
+  for (size_t i = 0; i < num_create; ++i) {
+    load_data_store.ReportStreamCreated(kHostname1, FormatLbId(i), kLoadKey1);
+  }
+  for (size_t i = 0; i < num_close; ++i) {
+    load_data_store.ReportStreamClosed(kHostname1, FormatLbId(i));
+  }
+  std::set<grpc::string> reported_lb_ids;
+  for (size_t i = num_close; i < num_create; ++i) {
+    for (auto assigned_store :
+         *load_data_store.GetAssignedStores(kHostname1, FormatLbId(i))) {
+      EXPECT_TRUE(reported_lb_ids.insert(assigned_store->lb_id()).second);
+    }
+  }
+  // Add one for kInvalidLbId.
+  EXPECT_EQ(reported_lb_ids.size(), (num_create + 1));
+  EXPECT_NE(reported_lb_ids.find(kInvalidLbId), reported_lb_ids.end());
+}
+
+TEST_F(LoadDataStoreTest, UnknownBalancerIdTracking) {
+  LoadDataStore load_data_store;
+  load_data_store.ReportStreamCreated(kHostname1, kLbId1, kLoadKey1);
+  // Merge data for a known LB ID.
+  LoadRecordValue v1(192);
+  load_data_store.MergeRow(kHostname1, kKey1, v1);
+  // Merge data for unknown LB ID.
+  LoadRecordValue v2(23);
+  EXPECT_FALSE(load_data_store.IsTrackedUnknownBalancerId(kLbId2));
+  load_data_store.MergeRow(
+      kHostname1, LoadRecordKey(kLbId2, kLbTag1, kUser1, kClientIp1), v2);
+  EXPECT_TRUE(load_data_store.IsTrackedUnknownBalancerId(kLbId2));
+  LoadRecordValue v3(952);
+  load_data_store.MergeRow(
+      kHostname2, LoadRecordKey(kLbId3, kLbTag1, kUser1, kClientIp1), v3);
+  EXPECT_TRUE(load_data_store.IsTrackedUnknownBalancerId(kLbId3));
+  // The data kept for a known LB ID is correct.
+  auto store_lb_id_1 = load_data_store.FindPerBalancerStore(kHostname1, kLbId1);
+  EXPECT_EQ(store_lb_id_1->load_record_map().size(), 1U);
+  EXPECT_EQ(store_lb_id_1->load_record_map().find(kKey1)->second.start_count(),
+            v1.start_count());
+  EXPECT_EQ(store_lb_id_1->GetNumCallsInProgressForReport(), v1.start_count());
+  // No PerBalancerStore created for Unknown LB ID.
+  EXPECT_EQ(load_data_store.FindPerBalancerStore(kHostname1, kLbId2), nullptr);
+  EXPECT_EQ(load_data_store.FindPerBalancerStore(kHostname2, kLbId3), nullptr);
+  // End all the started RPCs for kLbId1.
+  LoadRecordValue v4(0, v1.start_count());
+  load_data_store.MergeRow(kHostname1, kKey1, v4);
+  EXPECT_EQ(store_lb_id_1->load_record_map().size(), 1U);
+  EXPECT_EQ(store_lb_id_1->load_record_map().find(kKey1)->second.start_count(),
+            v1.start_count());
+  EXPECT_EQ(store_lb_id_1->load_record_map().find(kKey1)->second.ok_count(),
+            v4.ok_count());
+  EXPECT_EQ(store_lb_id_1->GetNumCallsInProgressForReport(), 0U);
+  EXPECT_FALSE(load_data_store.IsTrackedUnknownBalancerId(kLbId1));
+  // End all the started RPCs for kLbId2.
+  LoadRecordValue v5(0, v2.start_count());
+  load_data_store.MergeRow(
+      kHostname1, LoadRecordKey(kLbId2, kLbTag1, kUser1, kClientIp1), v5);
+  EXPECT_FALSE(load_data_store.IsTrackedUnknownBalancerId(kLbId2));
+  // End some of the started RPCs for kLbId3.
+  LoadRecordValue v6(0, v3.start_count() / 2);
+  load_data_store.MergeRow(
+      kHostname2, LoadRecordKey(kLbId3, kLbTag1, kUser1, kClientIp1), v6);
+  EXPECT_TRUE(load_data_store.IsTrackedUnknownBalancerId(kLbId3));
+}
+
+TEST_F(PerBalancerStoreTest, Suspend) {
+  PerBalancerStore per_balancer_store(kLbId1, kLoadKey1);
+  EXPECT_FALSE(per_balancer_store.IsSuspended());
+  // Suspend the store.
+  per_balancer_store.Suspend();
+  EXPECT_TRUE(per_balancer_store.IsSuspended());
+  EXPECT_EQ(0U, per_balancer_store.load_record_map().size());
+  // Data merged when the store is suspended won't be kept.
+  LoadRecordValue v1(139, 19);
+  per_balancer_store.MergeRow(kKey1, v1);
+  EXPECT_EQ(0U, per_balancer_store.load_record_map().size());
+  // Resume the store.
+  per_balancer_store.Resume();
+  EXPECT_FALSE(per_balancer_store.IsSuspended());
+  EXPECT_EQ(0U, per_balancer_store.load_record_map().size());
+  // Data merged after the store is resumed will be kept.
+  LoadRecordValue v2(23, 0, 51);
+  per_balancer_store.MergeRow(kKey1, v2);
+  EXPECT_EQ(1U, per_balancer_store.load_record_map().size());
+  // Suspend the store.
+  per_balancer_store.Suspend();
+  EXPECT_TRUE(per_balancer_store.IsSuspended());
+  EXPECT_EQ(0U, per_balancer_store.load_record_map().size());
+  // Data merged when the store is suspended won't be kept.
+  LoadRecordValue v3(62, 11);
+  per_balancer_store.MergeRow(kKey1, v3);
+  EXPECT_EQ(0U, per_balancer_store.load_record_map().size());
+  // Resume the store.
+  per_balancer_store.Resume();
+  EXPECT_FALSE(per_balancer_store.IsSuspended());
+  EXPECT_EQ(0U, per_balancer_store.load_record_map().size());
+  // Data merged after the store is resumed will be kept.
+  LoadRecordValue v4(225, 98);
+  per_balancer_store.MergeRow(kKey1, v4);
+  EXPECT_EQ(1U, per_balancer_store.load_record_map().size());
+  // In-progress count is always kept.
+  EXPECT_EQ(per_balancer_store.GetNumCallsInProgressForReport(),
+            v1.start_count() - v1.ok_count() + v2.start_count() -
+                v2.error_count() + v3.start_count() - v3.ok_count() +
+                v4.start_count() - v4.ok_count());
+}
+
+TEST_F(PerBalancerStoreTest, DataAggregation) {
+  PerBalancerStore per_balancer_store(kLbId1, kLoadKey1);
+  // Construct some Values.
+  LoadRecordValue v1(992, 34, 13, 234.0, 164.0, 173467.38);
+  v1.InsertCallMetric(kMetric1, CallMetricValue(3, 2773.2));
+  LoadRecordValue v2(4842, 213, 9, 393.0, 974.0, 1345.2398);
+  v2.InsertCallMetric(kMetric1, CallMetricValue(7, 25.234));
+  v2.InsertCallMetric(kMetric2, CallMetricValue(2, 387.08));
+  // v3 doesn't change the number of in-progress RPCs.
+  LoadRecordValue v3(293, 55, 293 - 55, 28764, 5284, 5772);
+  v3.InsertCallMetric(kMetric1, CallMetricValue(61, 3465.0));
+  v3.InsertCallMetric(kMetric2, CallMetricValue(13, 672.0));
+  // The initial state of the store.
+  uint64_t num_calls_in_progress = 0;
+  EXPECT_FALSE(per_balancer_store.IsNumCallsInProgressChangedSinceLastReport());
+  EXPECT_EQ(per_balancer_store.GetNumCallsInProgressForReport(),
+            num_calls_in_progress);
+  // Merge v1 and get report of the number of in-progress calls.
+  per_balancer_store.MergeRow(kKey1, v1);
+  EXPECT_TRUE(per_balancer_store.IsNumCallsInProgressChangedSinceLastReport());
+  EXPECT_EQ(per_balancer_store.GetNumCallsInProgressForReport(),
+            num_calls_in_progress +=
+            (v1.start_count() - v1.ok_count() - v1.error_count()));
+  EXPECT_FALSE(per_balancer_store.IsNumCallsInProgressChangedSinceLastReport());
+  // Merge v2 and get report of the number of in-progress calls.
+  per_balancer_store.MergeRow(kKey2, v2);
+  EXPECT_TRUE(per_balancer_store.IsNumCallsInProgressChangedSinceLastReport());
+  EXPECT_EQ(per_balancer_store.GetNumCallsInProgressForReport(),
+            num_calls_in_progress +=
+            (v2.start_count() - v2.ok_count() - v2.error_count()));
+  EXPECT_FALSE(per_balancer_store.IsNumCallsInProgressChangedSinceLastReport());
+  // Merge v3 and get report of the number of in-progress calls.
+  per_balancer_store.MergeRow(kKey1, v3);
+  EXPECT_FALSE(per_balancer_store.IsNumCallsInProgressChangedSinceLastReport());
+  EXPECT_EQ(per_balancer_store.GetNumCallsInProgressForReport(),
+            num_calls_in_progress);
+  // LoadRecordValue for kKey1 is aggregated correctly.
+  LoadRecordValue value_for_key1 =
+      per_balancer_store.load_record_map().find(kKey1)->second;
+  EXPECT_EQ(value_for_key1.start_count(), v1.start_count() + v3.start_count());
+  EXPECT_EQ(value_for_key1.ok_count(), v1.ok_count() + v3.ok_count());
+  EXPECT_EQ(value_for_key1.error_count(), v1.error_count() + v3.error_count());
+  EXPECT_EQ(value_for_key1.bytes_sent(), v1.bytes_sent() + v3.bytes_sent());
+  EXPECT_EQ(value_for_key1.bytes_recv(), v1.bytes_recv() + v3.bytes_recv());
+  EXPECT_EQ(value_for_key1.latency_ms(), v1.latency_ms() + v3.latency_ms());
+  EXPECT_EQ(value_for_key1.call_metrics().size(), 2U);
+  EXPECT_EQ(value_for_key1.call_metrics().find(kMetric1)->second.num_calls(),
+            v1.call_metrics().find(kMetric1)->second.num_calls() +
+                v3.call_metrics().find(kMetric1)->second.num_calls());
+  EXPECT_EQ(
+      value_for_key1.call_metrics().find(kMetric1)->second.total_metric_value(),
+      v1.call_metrics().find(kMetric1)->second.total_metric_value() +
+          v3.call_metrics().find(kMetric1)->second.total_metric_value());
+  EXPECT_EQ(value_for_key1.call_metrics().find(kMetric2)->second.num_calls(),
+            v3.call_metrics().find(kMetric2)->second.num_calls());
+  EXPECT_EQ(
+      value_for_key1.call_metrics().find(kMetric2)->second.total_metric_value(),
+      v3.call_metrics().find(kMetric2)->second.total_metric_value());
+  // LoadRecordValue for kKey2 is aggregated (trivially) correctly.
+  LoadRecordValue value_for_key2 =
+      per_balancer_store.load_record_map().find(kKey2)->second;
+  EXPECT_EQ(value_for_key2.start_count(), v2.start_count());
+  EXPECT_EQ(value_for_key2.ok_count(), v2.ok_count());
+  EXPECT_EQ(value_for_key2.error_count(), v2.error_count());
+  EXPECT_EQ(value_for_key2.bytes_sent(), v2.bytes_sent());
+  EXPECT_EQ(value_for_key2.bytes_recv(), v2.bytes_recv());
+  EXPECT_EQ(value_for_key2.latency_ms(), v2.latency_ms());
+  EXPECT_EQ(value_for_key2.call_metrics().size(), 2U);
+  EXPECT_EQ(value_for_key2.call_metrics().find(kMetric1)->second.num_calls(),
+            v2.call_metrics().find(kMetric1)->second.num_calls());
+  EXPECT_EQ(
+      value_for_key2.call_metrics().find(kMetric1)->second.total_metric_value(),
+      v2.call_metrics().find(kMetric1)->second.total_metric_value());
+  EXPECT_EQ(value_for_key2.call_metrics().find(kMetric2)->second.num_calls(),
+            v2.call_metrics().find(kMetric2)->second.num_calls());
+  EXPECT_EQ(
+      value_for_key2.call_metrics().find(kMetric2)->second.total_metric_value(),
+      v2.call_metrics().find(kMetric2)->second.total_metric_value());
+}
+
+}  // namespace
+}  // namespace testing
+}  // namespace grpc
+
+int main(int argc, char** argv) {
+  grpc_test_init(argc, argv);
+  ::testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
diff --git a/test/cpp/server/server_builder_test.cc b/test/cpp/server/server_builder_test.cc
index 2752b58..5c22dda 100644
--- a/test/cpp/server/server_builder_test.cc
+++ b/test/cpp/server/server_builder_test.cc
@@ -39,7 +39,10 @@
   return s.str();
 }
 
-grpc::string g_port = MakePort();
+const grpc::string& GetPort() {
+  static grpc::string g_port = MakePort();
+  return g_port;
+}
 
 TEST(ServerBuilderTest, NoOp) { ServerBuilder b; }
 
@@ -50,7 +53,7 @@
 TEST(ServerBuilderTest, CreateServerOnePort) {
   ServerBuilder()
       .RegisterService(&g_service)
-      .AddListeningPort(g_port, InsecureServerCredentials())
+      .AddListeningPort(GetPort(), InsecureServerCredentials())
       .BuildAndStart()
       ->Shutdown();
 }
@@ -58,8 +61,8 @@
 TEST(ServerBuilderTest, CreateServerRepeatedPort) {
   ServerBuilder()
       .RegisterService(&g_service)
-      .AddListeningPort(g_port, InsecureServerCredentials())
-      .AddListeningPort(g_port, InsecureServerCredentials())
+      .AddListeningPort(GetPort(), InsecureServerCredentials())
+      .AddListeningPort(GetPort(), InsecureServerCredentials())
       .BuildAndStart()
       ->Shutdown();
 }
@@ -67,8 +70,8 @@
 TEST(ServerBuilderTest, CreateServerRepeatedPortWithDisallowedReusePort) {
   EXPECT_EQ(ServerBuilder()
                 .RegisterService(&g_service)
-                .AddListeningPort(g_port, InsecureServerCredentials())
-                .AddListeningPort(g_port, InsecureServerCredentials())
+                .AddListeningPort(GetPort(), InsecureServerCredentials())
+                .AddListeningPort(GetPort(), InsecureServerCredentials())
                 .AddChannelArgument(GRPC_ARG_ALLOW_REUSEPORT, 0)
                 .BuildAndStart(),
             nullptr);
diff --git a/test/cpp/server/server_builder_with_socket_mutator_test.cc b/test/cpp/server/server_builder_with_socket_mutator_test.cc
new file mode 100644
index 0000000..5c7dd69
--- /dev/null
+++ b/test/cpp/server/server_builder_with_socket_mutator_test.cc
@@ -0,0 +1,116 @@
+/*
+ *
+ * Copyright 2017 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.
+ *
+ */
+
+#include <grpcpp/impl/codegen/config.h>
+#include <gtest/gtest.h>
+
+#include <grpcpp/server.h>
+#include <grpcpp/server_builder.h>
+
+#include <grpc/grpc.h>
+#include <memory>
+
+#include "src/core/lib/iomgr/socket_mutator.h"
+#include "src/proto/grpc/testing/echo.grpc.pb.h"
+#include "test/core/util/port.h"
+
+/* This test does a sanity check that grpc_socket_mutator's
+ * are used by servers. It's meant to protect code and end-to-end
+ * tests that rely on this functionality but which live outside
+ * of the grpc github repo. */
+
+namespace grpc {
+namespace {
+
+bool mock_socket_mutator_mutate_fd(int, grpc_socket_mutator*);
+int mock_socket_mutator_compare(grpc_socket_mutator*, grpc_socket_mutator*);
+void mock_socket_mutator_destroy(grpc_socket_mutator*);
+
+const grpc_socket_mutator_vtable mock_socket_mutator_vtable = {
+    mock_socket_mutator_mutate_fd,
+    mock_socket_mutator_compare,
+    mock_socket_mutator_destroy,
+};
+
+class MockSocketMutator : public grpc_socket_mutator {
+ public:
+  MockSocketMutator() : mutate_fd_call_count_(0) {
+    grpc_socket_mutator_init(this, &mock_socket_mutator_vtable);
+  }
+  int mutate_fd_call_count_;
+};
+
+bool mock_socket_mutator_mutate_fd(int fd, grpc_socket_mutator* m) {
+  MockSocketMutator* s = reinterpret_cast<MockSocketMutator*>(m);
+  s->mutate_fd_call_count_++;
+  return true;
+}
+
+int mock_socket_mutator_compare(grpc_socket_mutator* a,
+                                grpc_socket_mutator* b) {
+  return (uintptr_t)a - (uintptr_t)b;
+}
+
+void mock_socket_mutator_destroy(grpc_socket_mutator* m) {
+  MockSocketMutator* s = reinterpret_cast<MockSocketMutator*>(m);
+  delete s;
+}
+
+class MockSocketMutatorServerBuilderOption : public grpc::ServerBuilderOption {
+ public:
+  MockSocketMutatorServerBuilderOption(MockSocketMutator* mock_socket_mutator)
+      : mock_socket_mutator_(mock_socket_mutator) {}
+
+  void UpdateArguments(ChannelArguments* args) override {
+    args->SetSocketMutator(mock_socket_mutator_);
+  }
+
+  void UpdatePlugins(
+      std::vector<std::unique_ptr<ServerBuilderPlugin>>*) override{};
+
+  MockSocketMutator* mock_socket_mutator_;
+};
+
+TEST(ServerBuilderWithSocketMutatorTest, CreateServerWithSocketMutator) {
+  auto address = "localhost:" + std::to_string(grpc_pick_unused_port_or_die());
+  auto mock_socket_mutator = new MockSocketMutator();
+  std::unique_ptr<grpc::ServerBuilderOption> mock_socket_mutator_builder_option(
+      new MockSocketMutatorServerBuilderOption(mock_socket_mutator));
+  testing::EchoTestService::Service echo_service;
+  EXPECT_EQ(mock_socket_mutator->mutate_fd_call_count_, 0);
+  ServerBuilder builder;
+  builder.RegisterService(&echo_service);
+  builder.AddListeningPort(address, InsecureServerCredentials());
+  builder.SetOption(std::move(mock_socket_mutator_builder_option));
+  std::unique_ptr<grpc::Server> server(builder.BuildAndStart());
+  EXPECT_NE(server, nullptr);
+  // Only assert that the socket mutator was used.
+  EXPECT_GE(mock_socket_mutator->mutate_fd_call_count_, 1);
+  server->Shutdown();
+}
+
+}  // namespace
+}  // namespace grpc
+
+int main(int argc, char** argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  grpc_init();
+  int ret = RUN_ALL_TESTS();
+  grpc_shutdown();
+  return ret;
+}
diff --git a/test/cpp/util/BUILD b/test/cpp/util/BUILD
index f53bc7e..b1153d2 100644
--- a/test/cpp/util/BUILD
+++ b/test/cpp/util/BUILD
@@ -112,7 +112,7 @@
     ],
     deps = [
         "//:grpc++_unsecure",
-        "//test/core/util:grpc_test_util",
+        "//test/core/util:grpc_test_util_unsecure",
     ],
 )
 
diff --git a/test/cpp/util/byte_buffer_test.cc b/test/cpp/util/byte_buffer_test.cc
index 605ef15..47a5b7f 100644
--- a/test/cpp/util/byte_buffer_test.cc
+++ b/test/cpp/util/byte_buffer_test.cc
@@ -16,7 +16,8 @@
  *
  */
 
-#include <grpcpp/support/byte_buffer.h>
+#include <grpc++/support/byte_buffer.h>
+#include <grpcpp/impl/grpc_library.h>
 
 #include <cstring>
 #include <vector>
@@ -27,6 +28,9 @@
 #include <gtest/gtest.h>
 
 namespace grpc {
+
+static internal::GrpcLibraryInitializer g_gli_initializer;
+
 namespace {
 
 const char* kContent1 = "hello xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
diff --git a/test/cpp/util/create_test_channel.cc b/test/cpp/util/create_test_channel.cc
index 1047d44..0bcd4db 100644
--- a/test/cpp/util/create_test_channel.cc
+++ b/test/cpp/util/create_test_channel.cc
@@ -107,37 +107,37 @@
 
 std::shared_ptr<Channel> CreateTestChannel(
     const grpc::string& server, const grpc::string& override_hostname,
-    bool enable_ssl, bool use_prod_roots,
+    testing::transport_security security_type, bool use_prod_roots,
     const std::shared_ptr<CallCredentials>& creds,
     const ChannelArguments& args) {
-  grpc::string type;
-  if (enable_ssl) {
-    type = testing::kTlsCredentialsType;
-  }
-
+  grpc::string type =
+      security_type == testing::ALTS
+          ? testing::kAltsCredentialsType
+          : (security_type == testing::TLS ? testing::kTlsCredentialsType
+                                           : testing::kInsecureCredentialsType);
   return CreateTestChannel(server, type, override_hostname, use_prod_roots,
                            creds, args);
 }
 
 std::shared_ptr<Channel> CreateTestChannel(
     const grpc::string& server, const grpc::string& override_hostname,
-    bool enable_ssl, bool use_prod_roots,
+    testing::transport_security security_type, bool use_prod_roots,
     const std::shared_ptr<CallCredentials>& creds) {
-  return CreateTestChannel(server, override_hostname, enable_ssl,
+  return CreateTestChannel(server, override_hostname, security_type,
                            use_prod_roots, creds, ChannelArguments());
 }
 
 std::shared_ptr<Channel> CreateTestChannel(
     const grpc::string& server, const grpc::string& override_hostname,
-    bool enable_ssl, bool use_prod_roots) {
-  return CreateTestChannel(server, override_hostname, enable_ssl,
+    testing::transport_security security_type, bool use_prod_roots) {
+  return CreateTestChannel(server, override_hostname, security_type,
                            use_prod_roots, std::shared_ptr<CallCredentials>());
 }
 
 // Shortcut for end2end and interop tests.
-std::shared_ptr<Channel> CreateTestChannel(const grpc::string& server,
-                                           bool enable_ssl) {
-  return CreateTestChannel(server, "foo.test.google.fr", enable_ssl, false);
+std::shared_ptr<Channel> CreateTestChannel(
+    const grpc::string& server, testing::transport_security security_type) {
+  return CreateTestChannel(server, "foo.test.google.fr", security_type, false);
 }
 
 std::shared_ptr<Channel> CreateTestChannel(
diff --git a/test/cpp/util/create_test_channel.h b/test/cpp/util/create_test_channel.h
index ddaa99f..c615fb7 100644
--- a/test/cpp/util/create_test_channel.h
+++ b/test/cpp/util/create_test_channel.h
@@ -26,21 +26,27 @@
 namespace grpc {
 class Channel;
 
-std::shared_ptr<Channel> CreateTestChannel(const grpc::string& server,
-                                           bool enable_ssl);
+namespace testing {
+
+typedef enum { INSECURE = 0, TLS, ALTS } transport_security;
+
+}  // namespace testing
+
+std::shared_ptr<Channel> CreateTestChannel(
+    const grpc::string& server, testing::transport_security security_type);
 
 std::shared_ptr<Channel> CreateTestChannel(
     const grpc::string& server, const grpc::string& override_hostname,
-    bool enable_ssl, bool use_prod_roots);
+    testing::transport_security security_type, bool use_prod_roots);
 
 std::shared_ptr<Channel> CreateTestChannel(
     const grpc::string& server, const grpc::string& override_hostname,
-    bool enable_ssl, bool use_prod_roots,
+    testing::transport_security security_type, bool use_prod_roots,
     const std::shared_ptr<CallCredentials>& creds);
 
 std::shared_ptr<Channel> CreateTestChannel(
     const grpc::string& server, const grpc::string& override_hostname,
-    bool enable_ssl, bool use_prod_roots,
+    testing::transport_security security_type, bool use_prod_roots,
     const std::shared_ptr<CallCredentials>& creds,
     const ChannelArguments& args);
 
diff --git a/test/cpp/util/grpc_tool_test.cc b/test/cpp/util/grpc_tool_test.cc
index 9f7fec5..6574d1b 100644
--- a/test/cpp/util/grpc_tool_test.cc
+++ b/test/cpp/util/grpc_tool_test.cc
@@ -22,6 +22,7 @@
 
 #include <gflags/gflags.h>
 #include <grpc/grpc.h>
+#include <grpc/support/alloc.h>
 #include <grpcpp/channel.h>
 #include <grpcpp/client_context.h>
 #include <grpcpp/create_channel.h>
@@ -738,6 +739,8 @@
 
   FLAGS_metadata = "";
   FLAGS_protofiles = "";
+
+  gpr_free(test_srcdir);
 }
 
 }  // namespace testing
diff --git a/test/cpp/util/slice_test.cc b/test/cpp/util/slice_test.cc
index 8e06062..dc19100 100644
--- a/test/cpp/util/slice_test.cc
+++ b/test/cpp/util/slice_test.cc
@@ -16,13 +16,17 @@
  *
  */
 
-#include <grpcpp/support/slice.h>
+#include <grpc++/support/slice.h>
+#include <grpcpp/impl/grpc_library.h>
 
 #include <grpc/grpc.h>
 #include <grpc/slice.h>
 #include <gtest/gtest.h>
 
 namespace grpc {
+
+static internal::GrpcLibraryInitializer g_gli_initializer;
+
 namespace {
 
 const char* kContent = "hello xxxxxxxxxxxxxxxxxxxx world";
diff --git a/test/cpp/util/test_credentials_provider.cc b/test/cpp/util/test_credentials_provider.cc
index 7656100..c8b0ac7 100644
--- a/test/cpp/util/test_credentials_provider.cc
+++ b/test/cpp/util/test_credentials_provider.cc
@@ -56,6 +56,9 @@
       const grpc::string& type, ChannelArguments* args) override {
     if (type == grpc::testing::kInsecureCredentialsType) {
       return InsecureChannelCredentials();
+    } else if (type == grpc::testing::kAltsCredentialsType) {
+      grpc::experimental::AltsCredentialsOptions alts_opts;
+      return grpc::experimental::AltsCredentials(alts_opts);
     } else if (type == grpc::testing::kTlsCredentialsType) {
       SslCredentialsOptions ssl_opts = {test_root_cert, "", ""};
       args->SetSslTargetNameOverride("foo.test.google.fr");
@@ -77,6 +80,9 @@
       const grpc::string& type) override {
     if (type == grpc::testing::kInsecureCredentialsType) {
       return InsecureServerCredentials();
+    } else if (type == grpc::testing::kAltsCredentialsType) {
+      grpc::experimental::AltsServerCredentialsOptions alts_opts;
+      return grpc::experimental::AltsServerCredentials(alts_opts);
     } else if (type == grpc::testing::kTlsCredentialsType) {
       SslServerCredentialsOptions::PemKeyCertPair pkcp = {test_server1_key,
                                                           test_server1_cert};
diff --git a/test/cpp/util/test_credentials_provider.h b/test/cpp/util/test_credentials_provider.h
index f489a2c..b1d69e8 100644
--- a/test/cpp/util/test_credentials_provider.h
+++ b/test/cpp/util/test_credentials_provider.h
@@ -29,10 +29,10 @@
 namespace testing {
 
 const char kInsecureCredentialsType[] = "INSECURE_CREDENTIALS";
-
 // For real credentials, like tls/ssl, this name should match the AuthContext
 // property "transport_security_type".
 const char kTlsCredentialsType[] = "ssl";
+const char kAltsCredentialsType[] = "alts";
 
 // Provide test credentials of a particular type.
 class CredentialTypeProvider {
diff --git a/test/distrib/cpp/run_distrib_test_cmake_as_externalproject.bat b/test/distrib/cpp/run_distrib_test_cmake_as_externalproject.bat
new file mode 100644
index 0000000..6f4d581
--- /dev/null
+++ b/test/distrib/cpp/run_distrib_test_cmake_as_externalproject.bat
@@ -0,0 +1,41 @@
+@rem Copyright 2016 gRPC authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem     http://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+
+@rem enter this directory
+cd /d %~dp0\..\..\..
+
+@rem TODO(jtattermusch): Kokoro has pre-installed protoc.exe in C:\Program Files\ProtoC and that directory
+@rem is on PATH. To avoid picking up the older version protoc.exe, we change the path to something non-existent.
+set PATH=%PATH:ProtoC=DontPickupProtoC%
+
+@rem Download OpenSSL-Win32 originally installed from https://slproweb.com/products/Win32OpenSSL.html
+powershell -Command "(New-Object Net.WebClient).DownloadFile('https://storage.googleapis.com/grpc-testing.appspot.com/OpenSSL-Win32-1_1_0g.zip', 'OpenSSL-Win32.zip')"
+powershell -Command "Add-Type -Assembly 'System.IO.Compression.FileSystem'; [System.IO.Compression.ZipFile]::ExtractToDirectory('OpenSSL-Win32.zip', '.');"
+
+@rem set absolute path to OpenSSL with forward slashes
+set OPENSSL_DIR=%cd:\=/%/OpenSSL-Win32
+
+@rem Build helloworld example using cmake
+@rem Use non-standard build directory to avoid too long filenames
+mkdir example_build
+cd example_build
+cmake -DOPENSSL_ROOT_DIR=%OPENSSL_DIR% ../examples/cpp/helloworld/cmake_externalproject || goto :error
+cmake --build . --config Release || goto :error
+cd ..
+
+goto :EOF
+
+:error
+echo Failed!
+exit /b %errorlevel%
diff --git a/test/distrib/cpp/run_distrib_test_cmake_as_externalproject.sh b/test/distrib/cpp/run_distrib_test_cmake_as_externalproject.sh
new file mode 100755
index 0000000..163527f
--- /dev/null
+++ b/test/distrib/cpp/run_distrib_test_cmake_as_externalproject.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+# Copyright 2017 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.
+
+set -ex
+
+cd "$(dirname "$0")/../../.."
+
+echo "deb http://ftp.debian.org/debian jessie-backports main" | tee /etc/apt/sources.list.d/jessie-backports.list
+apt-get update
+apt-get install -t jessie-backports -y libssl-dev
+
+# To increase the confidence that gRPC installation works without depending on
+# too many submodules unnecessarily, just wipe out contents of most submodules
+# before starting the test.
+rm -r third_party/abseil-cpp/* || true
+rm -r third_party/benchmark/* || true
+rm -r third_party/bloaty/* || true
+rm -r third_party/boringssl/* || true
+rm -r third_party/boringssl-with-bazel/* || true
+rm -r third_party/gflags/* || true
+rm -r third_party/googletest/* || true
+
+# Build helloworld example using cmake superbuild
+cd examples/cpp/helloworld/cmake_externalproject
+mkdir -p cmake/build
+cd cmake/build
+cmake ../..
+make
+
diff --git a/test/distrib/cpp/run_distrib_test_cmake_as_submodule.sh b/test/distrib/cpp/run_distrib_test_cmake_as_submodule.sh
new file mode 100755
index 0000000..defc63e
--- /dev/null
+++ b/test/distrib/cpp/run_distrib_test_cmake_as_submodule.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+# Copyright 2017 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.
+
+set -ex
+
+cd "$(dirname "$0")/../../.."
+
+# Build helloworld example using cmake, including grpc with "add_subdirectory"
+cd examples/cpp/helloworld
+mkdir -p cmake/build
+cd cmake/build
+cmake -DGRPC_AS_SUBMODULE=ON ../..
+make
diff --git a/test/distrib/python/run_binary_distrib_test.sh b/test/distrib/python/run_binary_distrib_test.sh
new file mode 100755
index 0000000..061d041
--- /dev/null
+++ b/test/distrib/python/run_binary_distrib_test.sh
@@ -0,0 +1,18 @@
+#!/usr/bin/env bash
+# Copyright 2018 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.
+
+set -ex
+
+"$(dirname "$0")/test_packages.sh" binary
diff --git a/test/distrib/python/run_distrib_test.sh b/test/distrib/python/run_distrib_test.sh
deleted file mode 100755
index a855ae3..0000000
--- a/test/distrib/python/run_distrib_test.sh
+++ /dev/null
@@ -1,66 +0,0 @@
-#!/usr/bin/env bash
-# Copyright 2015 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.
-
-set -ex
-
-cd "$(dirname "$0")"
-
-shopt -s nullglob
-
-# Pick up the source dist archive whatever its version is
-SDIST_ARCHIVES=("$EXTERNAL_GIT_ROOT"/input_artifacts/grpcio-*.tar.gz)
-BDIST_ARCHIVES=("$EXTERNAL_GIT_ROOT"/input_artifacts/grpcio-*.whl)
-TOOLS_SDIST_ARCHIVES=("$EXTERNAL_GIT_ROOT"/input_artifacts/grpcio_tools-*.tar.gz)
-TOOLS_BDIST_ARCHIVES=("$EXTERNAL_GIT_ROOT"/input_artifacts/grpcio_tools-*.whl)
-
-function make_virtualenv() {
-  virtualenv "$1"
-  "$1/bin/python" -m pip install --upgrade six pip
-  "$1/bin/python" -m pip install cython
-}
-
-function at_least_one_installs() {
-  for file in "$@"; do
-    if python -m pip install "$file"; then
-      return 0
-    fi
-  done
-  return -1
-}
-
-make_virtualenv bdist_test
-make_virtualenv sdist_test
-
-#
-# Install our distributions in order of dependencies
-#
-
-(source bdist_test/bin/activate && at_least_one_installs "${BDIST_ARCHIVES[@]}")
-(source bdist_test/bin/activate && at_least_one_installs "${TOOLS_BDIST_ARCHIVES[@]}")
-
-(source sdist_test/bin/activate && at_least_one_installs "${SDIST_ARCHIVES[@]}")
-(source sdist_test/bin/activate && at_least_one_installs "${TOOLS_SDIST_ARCHIVES[@]}")
-
-#
-# Test our distributions
-#
-
-# TODO(jtattermusch): add a .proto file to the distribtest, generate python
-# code from it and then use the generated code from distribtest.py
-(source bdist_test/bin/activate && python -m grpc.tools.protoc --help)
-(source sdist_test/bin/activate && python -m grpc.tools.protoc --help)
-
-(source bdist_test/bin/activate && python distribtest.py)
-(source sdist_test/bin/activate && python distribtest.py)
diff --git a/test/distrib/python/run_source_distrib_test.sh b/test/distrib/python/run_source_distrib_test.sh
new file mode 100755
index 0000000..f667674
--- /dev/null
+++ b/test/distrib/python/run_source_distrib_test.sh
@@ -0,0 +1,18 @@
+#!/usr/bin/env bash
+# Copyright 2018 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.
+
+set -ex
+
+"$(dirname "$0")/test_packages.sh" source
diff --git a/test/distrib/python/test_packages.sh b/test/distrib/python/test_packages.sh
new file mode 100755
index 0000000..6bf49d4
--- /dev/null
+++ b/test/distrib/python/test_packages.sh
@@ -0,0 +1,73 @@
+#!/usr/bin/env bash
+# Copyright 2018 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.
+
+set -ex
+
+cd "$(dirname "$0")"
+
+shopt -s nullglob
+
+if [[ "$1" == "binary" ]]
+then
+  echo "Testing Python binary distribution"
+  ARCHIVES=("$EXTERNAL_GIT_ROOT"/input_artifacts/grpcio-[0-9]*.whl)
+  TOOLS_ARCHIVES=("$EXTERNAL_GIT_ROOT"/input_artifacts/grpcio_tools-[0-9]*.whl)
+else
+  echo "Testing Python source distribution"
+  ARCHIVES=("$EXTERNAL_GIT_ROOT"/input_artifacts/grpcio-[0-9]*.tar.gz)
+  TOOLS_ARCHIVES=("$EXTERNAL_GIT_ROOT"/input_artifacts/grpcio-tools-[0-9]*.tar.gz)
+  HEALTH_ARCHIVES=("$EXTERNAL_GIT_ROOT"/input_artifacts/grpcio-health-checking-[0-9]*.tar.gz)
+  REFLECTION_ARCHIVES=("$EXTERNAL_GIT_ROOT"/input_artifacts/grpcio-reflection-[0-9]*.tar.gz)
+fi
+
+VIRTUAL_ENV=$(mktemp -d)
+virtualenv "$VIRTUAL_ENV"
+PYTHON=$VIRTUAL_ENV/bin/python
+"$PYTHON" -m pip install --upgrade six pip
+
+function at_least_one_installs() {
+  for file in "$@"; do
+    if "$PYTHON" -m pip install "$file"; then
+      return 0
+    fi
+  done
+  return 1
+}
+
+
+#
+# Install our distributions in order of dependencies
+#
+
+at_least_one_installs "${ARCHIVES[@]}"
+at_least_one_installs "${TOOLS_ARCHIVES[@]}"
+
+if [[ "$1" == "source" ]]
+then
+  echo "Testing Python health and reflection packages"
+  at_least_one_installs "${HEALTH_ARCHIVES[@]}"
+  at_least_one_installs "${REFLECTION_ARCHIVES[@]}"
+fi
+
+
+#
+# Test our distributions
+#
+
+# TODO(jtattermusch): add a .proto file to the distribtest, generate python
+# code from it and then use the generated code from distribtest.py
+"$PYTHON" -m grpc.tools.protoc --help
+
+"$PYTHON" distribtest.py
diff --git a/test/distrib/ruby/run_distrib_test.sh b/test/distrib/ruby/run_distrib_test.sh
index 99fb873..cb2eb1f 100755
--- a/test/distrib/ruby/run_distrib_test.sh
+++ b/test/distrib/ruby/run_distrib_test.sh
@@ -35,3 +35,24 @@
 bundle install
 
 bundle exec ./distribtest.rb
+
+# Attempt to repro https://github.com/google/protobuf/issues/4210.
+# TODO: This sanity check only works for linux-based distrib tests and for
+# binary gRPC packages. It will need to be ran conditionally if this test script is
+# used for other types of distrib tests.
+INSTALLATION_DIR="$(gem env | grep '\- INSTALLATION DIRECTORY' | awk '{ print $4 }')"
+if [[ "$(find "$INSTALLATION_DIR" -name 'grpc_c.so' | wc -l)" == 0 ]]; then
+  echo "Sanity check failed. The gRPC package is not installed in $INSTALLATION_DIR."
+  exit 1
+fi
+LIBRUBY_DEPENDENCY_EXISTS="$(find "$INSTALLATION_DIR" -name 'grpc_c.so' -exec ldd {} \; | grep -c 'libruby')" || true
+if [[ "$LIBRUBY_DEPENDENCY_EXISTS" != 0 ]]; then
+  echo "A grpc_c.so file in this binary gRPC package is dynamically linked to libruby."
+fi
+DEPENDENCY_NOT_FOUND="$(find "$INSTALLATION_DIR" -name 'grpc_c.so' -exec ldd {} \; | grep -c 'not found')" || true
+if [[ "$DEPENDENCY_NOT_FOUND" != 0 ]]; then
+  echo "A grpc_c.so file in this binary gRPC package has an non-portable dependency."
+fi
+if [ "$LIBRUBY_DEPENDENCY_EXISTS" != 0 ] || [ "$DEPENDENCY_NOT_FOUND" != 0 ]; then
+  exit 1
+fi
diff --git a/third_party/address_sorting/LICENSE b/third_party/address_sorting/LICENSE
index db4b5a5..824d542 100644
--- a/third_party/address_sorting/LICENSE
+++ b/third_party/address_sorting/LICENSE
@@ -1,262 +1,3 @@
-   Copyright (c) 2014, ARM Limited
-   All rights Reserved.
-   Copyright (c) 2014, Linaro Ltd.
-
-   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 the company 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
-   HOLDER 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.
-
--------------------------------------------------------------------
-
-   Copyright (c) 2014, Linaro Limited
-   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 the Linaro 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
-   HOLDER 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.
-
--------------------------------------------------------------------
-
- Copyright (c) 1993 John Brezak
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions
- are met:
- 1. Redistributions of source code must retain the above copyright
-    notice, this list of conditions and the following disclaimer.
- 2. 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.
- 3. The name of the author may be used to endorse or promote products
-    derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR `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 AUTHOR 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.
-
--------------------------------------------------------------------
-
- Copyright (c) 2009-2013 The Linux Foundation. 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 The Linux Foundation 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 HOLDER 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.
-
--------------------------------------------------------------------
-
-====================================================
-Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
-
-Developed at SunPro, a Sun Microsystems, Inc. business.
-Permission to use, copy, modify, and distribute this
-software is freely granted, provided that this notice
-is preserved.
-
--------------------------------------------------------------------
-
-====================================================
-Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
-
-Developed at SunPro, a Sun Microsystems, Inc. business.
-Permission to use, copy, modify, and distribute this
-software is freely granted, provided that this notice
-is preserved.
-====================================================
-
-Optimized by Bruce D. Evans.
-
--------------------------------------------------------------------
-
-====================================================
-Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
-
-Developed at SunSoft, a Sun Microsystems, Inc. business.
-Permission to use, copy, modify, and distribute this
-software is freely granted, provided that this notice
-is preserved.
-
--------------------------------------------------------------------
-
-====================================================
-Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
-
-Developed at SunSoft, a Sun Microsystems, Inc. business.
-Permission to use, copy, modify, and distribute this
-software is freely granted, provided that this notice
-is preserved.
-====================================================
-
-Optimized by Bruce D. Evans.
-
--------------------------------------------------------------------
-
-====================================================
-Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
-Copyright (c) 2008 Steven G. Kargl, David Schultz, Bruce D. Evans.
-
-Developed at SunSoft, a Sun Microsystems, Inc. business.
-Permission to use, copy, modify, and distribute this
-software is freely granted, provided that this notice
-is preserved.
-
--------------------------------------------------------------------
-
-====================================================
-Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
-Copyright (c) 2008 Steven G. Kargl, David Schultz, Bruce D. Evans.
-
-Developed at SunSoft, a Sun Microsystems, Inc. business.
-Permission to use, copy, modify, and distribute this
-software is freely granted, provided that this notice
-is preserved.
-====================================================
-
-Optimized by Bruce D. Evans.
-
--------------------------------------------------------------------
-
-====================================================
-Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
-Copyright (c) 2009-2011, Bruce D. Evans, Steven G. Kargl, David Schultz.
-
-Developed at SunPro, a Sun Microsystems, Inc. business.
-Permission to use, copy, modify, and distribute this
-software is freely granted, provided that this notice
-is preserved.
-====================================================
-
-The argument reduction and testing for exceptional cases was
-written by Steven G. Kargl with input from Bruce D. Evans
-and David A. Schultz.
-
--------------------------------------------------------------------
-
-====================================================
-Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved.
-
-Permission to use, copy, modify, and distribute this
-software is freely granted, provided that this notice
-is preserved.
-
--------------------------------------------------------------------
-
-====================================================
-Copyright 2004 Sun Microsystems, Inc.  All Rights Reserved.
-
-Permission to use, copy, modify, and distribute this
-software is freely granted, provided that this notice
-is preserved.
-
--------------------------------------------------------------------
-
-====================================================
-Copyright 2004 Sun Microsystems, Inc.  All Rights Reserved.
-Copyright (c) 2008 Steven G. Kargl, David Schultz, Bruce D. Evans.
-
-Permission to use, copy, modify, and distribute this
-software is freely granted, provided that this notice
-is preserved.
-
--------------------------------------------------------------------
-
-Based on the UCB version with the ID appearing below.
-This is ANSIish only when "multibyte character == plain character".
-
-Copyright (c) 1989, 1993
-   The Regents of the University of California.  All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
 Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
 All rights reserved.
 
@@ -283,5819 +24,3 @@
 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.
-
--------------------------------------------------------------------
-
-Copyright (C) 2004, 2005, 2008  Internet Systems Consortium, Inc. ("ISC")
-Copyright (C) 1995-1999, 2001, 2003  Internet Software Consortium.
-
-Permission to use, copy, modify, and/or distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
-REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
-INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-PERFORMANCE OF THIS SOFTWARE.
-
--------------------------------------------------------------------
-
-Copyright (C) 2004, 2005, 2008  Internet Systems Consortium, Inc. ("ISC")
-Copyright (C) 1997-2001  Internet Software Consortium.
-
-Permission to use, copy, modify, and/or distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
-REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
-INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-PERFORMANCE OF THIS SOFTWARE.
-
--------------------------------------------------------------------
-
-Copyright (C) 2006 The Android Open Source Project
-
-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.
-
--------------------------------------------------------------------
-
-Copyright (C) 2006 The Android Open Source Project
-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.
-
-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.
-
--------------------------------------------------------------------
-
-Copyright (C) 2007 The Android Open Source Project
-
-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.
-
--------------------------------------------------------------------
-
-Copyright (C) 2007 The Android Open Source Project
-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.
-
-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.
-
--------------------------------------------------------------------
-
-Copyright (C) 2008 The Android Open Source Project
-
-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.
-
--------------------------------------------------------------------
-
-Copyright (C) 2008 The Android Open Source Project
-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.
-
-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.
-
--------------------------------------------------------------------
-
-Copyright (C) 2008 The Android Open Source Project
-All rights reserved.
-Copyright (c) 2013-2014, NVIDIA Corporation.  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.
-
-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.
-
--------------------------------------------------------------------
-
-Copyright (C) 2009 The Android Open Source Project
-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.
-
-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.
-
--------------------------------------------------------------------
-
-Copyright (C) 2010 The Android Open Source Project
-
-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.
-
--------------------------------------------------------------------
-
-Copyright (C) 2010 The Android Open Source Project
-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.
-
-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.
-
--------------------------------------------------------------------
-
-Copyright (C) 2010 The Android Open Source Project
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-Copyright (C) 2010 The Android Open Source Project
-Copyright (c) 2008 ARM Ltd
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. The name of the company may not be used to endorse or promote
-   products derived from this software without specific prior written
-   permission.
-
-THIS SOFTWARE IS PROVIDED BY ARM LTD ``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 ARM LTD 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.
-
-Android adaptation and tweak by Jim Huang <jserv@0xlab.org>.
-
--------------------------------------------------------------------
-
-Copyright (C) 2011 The Android Open Source Project
-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.
-
-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.
-
--------------------------------------------------------------------
-
-Copyright (C) 2012 The Android Open Source Project
-
-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.
-
--------------------------------------------------------------------
-
-Copyright (C) 2012 The Android Open Source Project
-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.
-
-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.
-
--------------------------------------------------------------------
-
-Copyright (C) 2013 Pietro Cerutti <gahr@FreeBSD.org>
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY AUTHOR 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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-Copyright (C) 2013 The Android Open Source Project
-
-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.
-
--------------------------------------------------------------------
-
-Copyright (C) 2013 The Android Open Source Project
-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.
-
-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.
-
--------------------------------------------------------------------
-
-Copyright (C) 2013 The Android Open Source Project
-All rights reserved.
-Copyright (c) 2013-2014 NVIDIA Corporation.  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.
-
-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.
-
--------------------------------------------------------------------
-
-Copyright (C) 2013 The Android Open Source Project
-Copyright (c) 2014, NVIDIA CORPORATION.  All rights reserved.
-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.
-
-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.
-
--------------------------------------------------------------------
-
-Copyright (C) 2014 The Android Open Source Project
-
-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.
-
--------------------------------------------------------------------
-
-Copyright (C) 2014 The Android Open Source Project
-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.
-
-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.
-
--------------------------------------------------------------------
-
-Copyright (C) 2014 The Android Open Source Project
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-Copyright (C) 2015 The Android Open Source Project
-
-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.
-
--------------------------------------------------------------------
-
-Copyright (C) 2015 The Android Open Source Project
-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.
-
-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.
-
--------------------------------------------------------------------
-
-Copyright (C) 2016 The Android Open Source Project
-
-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.
-
--------------------------------------------------------------------
-
-Copyright (C) 2016 The Android Open Source Project
-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.
-
-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.
-
--------------------------------------------------------------------
-
-Copyright (C) 2017 The Android Open Source Project
-
-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.
-
--------------------------------------------------------------------
-
-Copyright (C) 2017 The Android Open Source Project
-All rights reserved.
-
-Copyright (c) 2009-2011, Code Aurora Forum. 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.
-
-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.
-
--------------------------------------------------------------------
-
-Copyright (C) 2017 The Android Open Source Project
-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.
-
-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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1980, 1983, 1988, 1993
-   The Regents of the University of California.  All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. All advertising materials mentioning features or use of this software
-   must display the following acknowledgement:
-   This product includes software developed by the University of
-   California, Berkeley and its contributors.
-4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
-
-Portions Copyright (c) 1993 by Digital Equipment Corporation.
-
-Permission to use, copy, modify, and distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies, and that
-the name of Digital Equipment Corporation not be used in advertising or
-publicity pertaining to distribution of the document or software without
-specific, written prior permission.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
-WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
-OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
-CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
-DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
-PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
-ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
--------------------------------------------------------------------
-
-Copyright (c) 1982, 1986, 1993
-   The Regents of the University of California.  All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1982, 1986, 1993
-   The Regents of the University of California.  All rights reserved.
-(c) UNIX System Laboratories, Inc.
-All or some portions of this file are derived from material licensed
-to the University of California by American Telephone and Telegraph
-Co. or Unix System Laboratories, Inc. and are reproduced herein with
-the permission of UNIX System Laboratories, Inc.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1983, 1987, 1989
-   The Regents of the University of California.  All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1983, 1989
-   The Regents of the University of California.  All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. All advertising materials mentioning features or use of this software
-   must display the following acknowledgement:
-    This product includes software developed by the University of
-    California, Berkeley and its contributors.
-4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1983, 1989, 1993
-   The Regents of the University of California.  All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1983, 1993
-   The Regents of the University of California.  All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1985
-   The Regents of the University of California.  All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. All advertising materials mentioning features or use of this software
-   must display the following acknowledgement:
-    This product includes software developed by the University of
-    California, Berkeley and its contributors.
-4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1985 Regents of the University of California.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1985, 1988, 1993
-   The Regents of the University of California.  All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
-Portions Copyright (c) 1993 by Digital Equipment Corporation.
-
-Permission to use, copy, modify, and distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies, and that
-the name of Digital Equipment Corporation not be used in advertising or
-publicity pertaining to distribution of the document or software without
-specific, written prior permission.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
-WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
-OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
-CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
-DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
-PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
-ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
--------------------------------------------------------------------
-
-Copyright (c) 1985, 1989, 1993
-   The Regents of the University of California.  All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. All advertising materials mentioning features or use of this software
-   must display the following acknowledgement:
-    This product includes software developed by the University of
-    California, Berkeley and its contributors.
-4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1985, 1993
-   The Regents of the University of California.  All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. All advertising materials mentioning features or use of this software
-   must display the following acknowledgement:
-    This product includes software developed by the University of
-    California, Berkeley and its contributors.
-4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1985, 1993
-   The Regents of the University of California.  All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. All advertising materials mentioning features or use of this software
-   must display the following acknowledgement:
-   This product includes software developed by the University of
-   California, Berkeley and its contributors.
-4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1985, 1993
-   The Regents of the University of California.  All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1987 Regents of the University of California.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1987, 1993
-   The Regents of the University of California.  All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. All advertising materials mentioning features or use of this software
-   must display the following acknowledgement:
-    This product includes software developed by the University of
-    California, Berkeley and its contributors.
-4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1987, 1993
-   The Regents of the University of California.  All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1988 Regents of the University of California.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1988 The Regents of the University of California.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1988, 1993
-   The Regents of the University of California.  All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. All advertising materials mentioning features or use of this software
-   must display the following acknowledgement:
-    This product includes software developed by the University of
-    California, Berkeley and its contributors.
-4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1988, 1993
-   The Regents of the University of California.  All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. All advertising materials mentioning features or use of this software
-   must display the following acknowledgement:
-   This product includes software developed by the University of
-   California, Berkeley and its contributors.
-4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1988, 1993
-   The Regents of the University of California.  All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1988, 1993
-   The Regents of the University of California.  All rights reserved.
-
-This code is derived from software written by Ken Arnold and
-published in UNIX Review, Vol. 6, No. 8.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1989 The Regents of the University of California.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1989 The Regents of the University of California.
-All rights reserved.
-(c) UNIX System Laboratories, Inc.
-All or some portions of this file are derived from material licensed
-to the University of California by American Telephone and Telegraph
-Co. or Unix System Laboratories, Inc. and are reproduced herein with
-the permission of UNIX System Laboratories, Inc.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1989, 1993
-   The Regents of the University of California.  All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1989, 1993
-   The Regents of the University of California.  All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1989, 1993
-   The Regents of the University of California.  All rights reserved.
-
-This code is derived from software contributed to Berkeley by
-Guido van Rossum.
-
-Copyright (c) 2011 The FreeBSD Foundation
-All rights reserved.
-Portions of this software were developed by David Chisnall
-under sponsorship from the FreeBSD Foundation.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1989, 1993
-   The Regents of the University of California.  All rights reserved.
-
-This code is derived from software contributed to Berkeley by
-Guido van Rossum.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1989, 1993
-   The Regents of the University of California.  All rights reserved.
-
-This code is derived from software contributed to Berkeley by
-Roger L. Snyder.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1989, 1993
-   The Regents of the University of California.  All rights reserved.
-(c) UNIX System Laboratories, Inc.
-All or some portions of this file are derived from material licensed
-to the University of California by American Telephone and Telegraph
-Co. or Unix System Laboratories, Inc. and are reproduced herein with
-the permission of UNIX System Laboratories, Inc.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1990 Regents of the University of California.
-All rights reserved.
-
-This code is derived from software contributed to Berkeley by
-Chris Torek.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1990 The Regents of the University of California.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1990 The Regents of the University of California.
-All rights reserved.
-
-This code is derived from software contributed to Berkeley by
-Chris Torek.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1990 The Regents of the University of California.
-All rights reserved.
-
-This code is derived from software contributed to Berkeley by
-William Jolitz.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1990, 1993
-   The Regents of the University of California.  All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1990, 1993
-   The Regents of the University of California.  All rights reserved.
-
-This code is derived from software contributed to Berkeley by
-Chris Torek.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1990, 1993
-   The Regents of the University of California.  All rights reserved.
-
-This code is derived from software contributed to Berkeley by
-Donn Seeley at UUNET Technologies, Inc.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1990, 1993
-   The Regents of the University of California.  All rights reserved.
-
-This code is derived from software contributed to Berkeley by
-Donn Seeley at UUNET Technologies, Inc.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1990, 1993
-   The Regents of the University of California.  All rights reserved.
-(c) UNIX System Laboratories, Inc.
-All or some portions of this file are derived from material licensed
-to the University of California by American Telephone and Telegraph
-Co. or Unix System Laboratories, Inc. and are reproduced herein with
-the permission of UNIX System Laboratories, Inc.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1990, 1993, 1994
-   The Regents of the University of California.  All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1990, 1993, 1994
-   The Regents of the University of California.  All rights reserved.
-
-This code is derived from software contributed to Berkeley by
-Chris Torek.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1991 The Regents of the University of California.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1991, 1993
-   The Regents of the University of California.  All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1991, 1993
-   The Regents of the University of California.  All rights reserved.
-
-This code is derived from software contributed to Berkeley by
-Berkeley Software Design, Inc.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1991, 1993
-   The Regents of the University of California.  All rights reserved.
-(c) UNIX System Laboratories, Inc.
-All or some portions of this file are derived from material licensed
-to the University of California by American Telephone and Telegraph
-Co. or Unix System Laboratories, Inc. and are reproduced herein with
-the permission of UNIX System Laboratories, Inc.
-
-This code is derived from software contributed to Berkeley by
-Hugh Smith at The University of Guelph.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1991, 1993, 1995,
-   The Regents of the University of California.  All rights reserved.
-
-This code is derived from software contributed to Berkeley by
-Havard Eidnes.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1992 Henry Spencer.
-Copyright (c) 1992, 1993
-   The Regents of the University of California.  All rights reserved.
-
-This code is derived from software contributed to Berkeley by
-Henry Spencer of the University of Toronto.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1992 The Regents of the University of California.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1992, 1993
-   The Regents of the University of California.  All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. All advertising materials mentioning features or use of this software
-   must display the following acknowledgement:
-   This product includes software developed by the University of
-   California, Berkeley and its contributors.
-4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1992, 1993
-   The Regents of the University of California.  All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1992, 1993
-   The Regents of the University of California.  All rights reserved.
-
-This code is derived from software contributed to Berkeley by
-Ralph Campbell.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1992, 1993
-   The Regents of the University of California.  All rights reserved.
-
-This software was developed by the Computer Systems Engineering group
-at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
-contributed to Berkeley.
-
-All advertising materials mentioning features or use of this software
-must display the following acknowledgement:
-   This product includes software developed by the University of
-   California, Lawrence Berkeley Laboratory.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. All advertising materials mentioning features or use of this software
-   must display the following acknowledgement:
-   This product includes software developed by the University of
-   California, Berkeley and its contributors.
-4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1992, 1993
-   The Regents of the University of California.  All rights reserved.
-(c) UNIX System Laboratories, Inc.
-All or some portions of this file are derived from material licensed
-to the University of California by American Telephone and Telegraph
-Co. or Unix System Laboratories, Inc. and are reproduced herein with
-the permission of UNIX System Laboratories, Inc.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1992, 1993, 1994
-   The Regents of the University of California.  All rights reserved.
-
-This code is derived from software contributed to Berkeley by
-Henry Spencer.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1992, 1993, 1994 Henry Spencer.
-
-This code is derived from software contributed to Berkeley by
-Henry Spencer.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. All advertising materials mentioning features or use of this software
-   must display the following acknowledgement:
-   This product includes software developed by the University of
-   California, Berkeley and its contributors.
-4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1993
-   The Regents of the University of California.  All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1993 Martin Birgmeier
-All rights reserved.
-
-You may redistribute unmodified or modified versions of this source
-code provided that the above copyright notice and this and the
-following conditions are retained.
-
-This software is provided ``as is'', and comes with no warranties
-of any kind. I shall in no event be liable for anything that happens
-to anyone/anything when using this software.
-
--------------------------------------------------------------------
-
-Copyright (c) 1994 SigmaSoft, Th. Lockert <tholo@sigmasoft.com>
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. The name of the author may not be used to endorse or promote products
-   derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1996 by Internet Software Consortium.
-
-Permission to use, copy, modify, and distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
-ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
-OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
-CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
-DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
-PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
-ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
--------------------------------------------------------------------
-
-Copyright (c) 1996, David Mazieres <dm@uun.org>
-Copyright (c) 2008, Damien Miller <djm@openbsd.org>
-Copyright (c) 2013, Markus Friedl <markus@openbsd.org>
-
-Permission to use, copy, modify, and distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
--------------------------------------------------------------------
-
-Copyright (c) 1996, David Mazieres <dm@uun.org>
-Copyright (c) 2008, Damien Miller <djm@openbsd.org>
-Copyright (c) 2013, Markus Friedl <markus@openbsd.org>
-Copyright (c) 2014, Theo de Raadt <deraadt@openbsd.org>
-
-Permission to use, copy, modify, and distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
--------------------------------------------------------------------
-
-Copyright (c) 1996-1998, 2008 Theo de Raadt
-Copyright (c) 1997, 2008-2009 Todd C. Miller
-
-Permission to use, copy, modify, and distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
--------------------------------------------------------------------
-
-Copyright (c) 1997 Mark Brinicombe
-Copyright (C) 2010 The Android Open Source Project
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. All advertising materials mentioning features or use of this software
-   must display the following acknowledgement:
-   This product includes software developed by Mark Brinicombe
-4. Neither the name of the University 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 AUTHOR 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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1997 Niklas Hallqvist.  All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
-
-Permission to use, copy, modify, and distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
--------------------------------------------------------------------
-
-Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. The name of the author may not be used to endorse or promote products
-   derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
-All rights reserved.
-
-This code was contributed to The NetBSD Foundation by Klaus Klein.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. All advertising materials mentioning features or use of this software
-   must display the following acknowledgement:
-       This product includes software developed by the NetBSD
-       Foundation, Inc. and its contributors.
-4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1997, 1998, 1999, 2004 The NetBSD Foundation, Inc.
-All rights reserved.
-
-This code is derived from software contributed to The NetBSD Foundation
-by Luke Mewburn.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1997, 1998, 1999, 2004 The NetBSD Foundation, Inc.
-All rights reserved.
-
-This code is derived from software contributed to The NetBSD Foundation
-by Luke Mewburn; and by Jason R. Thorpe.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. All advertising materials mentioning features or use of this software
-   must display the following acknowledgement:
-       This product includes software developed by the NetBSD
-       Foundation, Inc. and its contributors.
-4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1997, 2005 Todd C. Miller <Todd.Miller@courtesan.com>
-
-Permission to use, copy, modify, and distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
--------------------------------------------------------------------
-
-Copyright (c) 1998 Softweyr LLC.  All rights reserved.
-
-strtok_r, from Berkeley strtok
-Oct 13, 1998 by Wes Peters <wes@softweyr.com>
-
-Copyright (c) 1988, 1993
-   The Regents of the University of California.  All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notices, this list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright
-   notices, this list of conditions and the following disclaimer in the
-   documentation and/or other materials provided with the distribution.
-3. Neither the name of the University 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 SOFTWEYR LLC, THE REGENTS 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 SOFTWEYR LLC, THE
-REGENTS, 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1998 The NetBSD Foundation, Inc.
-All rights reserved.
-
-This code is derived from software contributed to The NetBSD Foundation
-by Klaus Klein.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. All advertising materials mentioning features or use of this software
-   must display the following acknowledgement:
-       This product includes software developed by the NetBSD
-       Foundation, Inc. and its contributors.
-4. Neither the name of The NetBSD Foundation 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. The name of the author may not be used to endorse or promote products
-   derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED ``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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 1998, 2015 Todd C. Miller <Todd.Miller@courtesan.com>
-
-Permission to use, copy, modify, and distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
--------------------------------------------------------------------
-
-Copyright (c) 1999
-   David E. O'Brien
-Copyright (c) 1988, 1993
-   The Regents of the University of California.  All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. Neither the name of the University 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 REGENTS 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 REGENTS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2000 Ben Harris.
-Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. Neither the name of the project 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 PROJECT 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 PROJECT 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2000 The NetBSD Foundation, Inc.
-All rights reserved.
-
-This code is derived from software contributed to The NetBSD Foundation
-by Dieter Baron and Thomas Klausner.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2001 Wasabi Systems, Inc.
-All rights reserved.
-
-Written by Frank van der Linden for Wasabi Systems, Inc.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. All advertising materials mentioning features or use of this software
-   must display the following acknowledgement:
-     This product includes software developed for the NetBSD Project by
-     Wasabi Systems, Inc.
-4. The name of Wasabi Systems, Inc. may not be used to endorse
-   or promote products derived from this software without specific prior
-   written permission.
-
-THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
-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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2001-2002 Opsycon AB  (www.opsycon.se / www.opsycon.com)
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2001-2002 Opsycon AB  (www.opsycon.se / www.opsycon.com)
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. Neither the name of Opsycon AB 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 AUTHOR ``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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2001-2011 The FreeBSD Project.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2002 Daniel Hartmeier
-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.
-
-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 HOLDERS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2002 The NetBSD Foundation, Inc.
-All rights reserved.
-
-This code is derived from software contributed to The NetBSD Foundation
-by Christos Zoulas.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2002 Tim J. Robbins
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2002 Tim J. Robbins.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
-
-Permission to use, copy, modify, and distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-Sponsored in part by the Defense Advanced Research Projects
-Agency (DARPA) and Air Force Research Laboratory, Air Force
-Materiel Command, USAF, under agreement number F39502-99-1-0512.
-
--------------------------------------------------------------------
-
-Copyright (c) 2002, 2003 Tim J. Robbins.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2002-2004 Tim J. Robbins
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2002-2004 Tim J. Robbins.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2003 Constantin S. Svintsoff <kostik@iclub.nsu.ru>
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. The names of the authors may not be used to endorse or promote
-   products derived from this software without specific prior written
-   permission.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2003 Dag-Erling Smørgrav
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer
-   in this position and unchanged.
-2. 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.
-3. The name of the author may not be used to endorse or promote products
-   derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2003 David Schultz <das@FreeBSD.ORG>
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2003 Mike Barcroft <mike@FreeBSD.org>
-Copyright (c) 2002 David Schultz <das@FreeBSD.ORG>
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2003 Networks Associates Technology, Inc.
-All rights reserved.
-
-Portions of this software were developed for the FreeBSD Project by
-Jacques A. Vidrine, Safeport Network Services, and Network
-Associates Laboratories, the Security Research Division of Network
-Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
-("CBOSS"), as part of the DARPA CHATS research program.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2003 Todd C. Miller <Todd.Miller@courtesan.com>
-
-Permission to use, copy, modify, and distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-Sponsored in part by the Defense Advanced Research Projects
-Agency (DARPA) and Air Force Research Laboratory, Air Force
-Materiel Command, USAF, under agreement number F39502-99-1-0512.
-
--------------------------------------------------------------------
-
-Copyright (c) 2003, 2004 Todd C. Miller <Todd.Miller@courtesan.com>
-
-Permission to use, copy, modify, and distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-Sponsored in part by the Defense Advanced Research Projects
-Agency (DARPA) and Air Force Research Laboratory, Air Force
-Materiel Command, USAF, under agreement number F39502-99-1-0512.
-
--------------------------------------------------------------------
-
-Copyright (c) 2003, Steven G. Kargl
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice unmodified, this list of conditions, and the following
-   disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2004 Stefan Farfeleder
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY AUTHOR 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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
-Copyright (c) 1995,1999 by Internet Software Consortium.
-
-Permission to use, copy, modify, and distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
-OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
--------------------------------------------------------------------
-
-Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
-Copyright (c) 1995-1999 by Internet Software Consortium
-
-Permission to use, copy, modify, and distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
-OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
--------------------------------------------------------------------
-
-Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
-Copyright (c) 1995-1999 by Internet Software Consortium.
-
-Permission to use, copy, modify, and distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
-OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
--------------------------------------------------------------------
-
-Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
-Copyright (c) 1996,1999 by Internet Software Consortium.
-
-Permission to use, copy, modify, and distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
-OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
--------------------------------------------------------------------
-
-Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
-Copyright (c) 1996-1999 by Internet Software Consortium
-
-Permission to use, copy, modify, and distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
-OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
--------------------------------------------------------------------
-
-Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
-Copyright (c) 1996-1999 by Internet Software Consortium.
-
-Permission to use, copy, modify, and distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
-OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
--------------------------------------------------------------------
-
-Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
-Copyright (c) 1997,1999 by Internet Software Consortium.
-
-Permission to use, copy, modify, and distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
-OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
--------------------------------------------------------------------
-
-Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
-Copyright (c) 1999 by Internet Software Consortium.
-
-Permission to use, copy, modify, and distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
-OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
--------------------------------------------------------------------
-
-Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
-Portions Copyright (c) 1996-1999 by Internet Software Consortium.
-
-Permission to use, copy, modify, and distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
-OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
--------------------------------------------------------------------
-
-Copyright (c) 2004, 2005 David Schultz <das@FreeBSD.ORG>
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2004-2005 David Schultz <das (at) FreeBSD.ORG>
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2004-2005 David Schultz <das@FreeBSD.ORG>
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2005 Bruce D. Evans and Steven G. Kargl
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice unmodified, this list of conditions, and the following
-   disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2005 David Schultz <das@FreeBSD.ORG>
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2005 Tim J. Robbins.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2005 by Internet Systems Consortium, Inc. ("ISC")
-Copyright (c) 1995-1999 by Internet Software Consortium
-
-Permission to use, copy, modify, and distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
-OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
--------------------------------------------------------------------
-
-Copyright (c) 2005-2008 David Schultz <das@FreeBSD.ORG>
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2005-2011 David Schultz <das@FreeBSD.ORG>
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2007 David Schultz
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY AUTHOR 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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2007 David Schultz <das@FreeBSD.ORG>
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2007 David Schultz <das@FreeBSD.ORG>
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
-
-Derived from s_modf.c, which has the following Copyright:
-====================================================
-Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
-
-Developed at SunPro, a Sun Microsystems, Inc. business.
-Permission to use, copy, modify, and distribute this
-software is freely granted, provided that this notice
-is preserved.
-
--------------------------------------------------------------------
-
-Copyright (c) 2007 Steven G. Kargl
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice unmodified, this list of conditions, and the following
-   disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2007 The NetBSD Foundation, Inc.
-All rights reserved.
-
-This code is derived from software written by Stephen L. Moshier.
-It is redistributed by the NetBSD Foundation by permission of the author.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2007 Todd C. Miller <Todd.Miller@courtesan.com>
-
-Permission to use, copy, modify, and distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
--------------------------------------------------------------------
-
-Copyright (c) 2007-2008  Michael G Schwern
-
-This software originally derived from Paul Sheer's pivotal_gmtime_r.c.
-
-The MIT License:
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-
--------------------------------------------------------------------
-
-Copyright (c) 2007-2008  Michael G Schwern
-
-This software originally derived from Paul Sheer's pivotal_gmtime_r.c.
-
-The MIT License:
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-
-Origin: http://code.google.com/p/y2038
-Modified for Bionic by the Android Open Source Project
-
--------------------------------------------------------------------
-
-Copyright (c) 2007-2008 David Schultz <das@FreeBSD.ORG>
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2007-2013 Bruce D. Evans
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice unmodified, this list of conditions, and the following
-   disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2008 David Schultz <das@FreeBSD.ORG>
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2008 Otto Moerbeek <otto@drijf.net>
-
-Permission to use, copy, modify, and distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
--------------------------------------------------------------------
-
-Copyright (c) 2008 Todd C. Miller <millert@openbsd.org>
-
-Permission to use, copy, modify, and distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
--------------------------------------------------------------------
-
-Copyright (c) 2008, Damien Miller <djm@openbsd.org>
-
-Permission to use, copy, modify, and distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
--------------------------------------------------------------------
-
-Copyright (c) 2009 David Schultz <das@FreeBSD.org>
-All rights reserved.
-
-Copyright (c) 2011 The FreeBSD Foundation
-All rights reserved.
-Portions of this software were developed by David Chisnall
-under sponsorship from the FreeBSD Foundation.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2009 David Schultz <das@FreeBSD.org>
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2009 The NetBSD Foundation, Inc.
-
-This code is derived from software contributed to The NetBSD Foundation
-by Roy Marples.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2009-2013 Steven G. Kargl
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice unmodified, this list of conditions, and the following
-   disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
-
-Optimized by Bruce D. Evans.
-
--------------------------------------------------------------------
-
-Copyright (c) 2010 The NetBSD Foundation, 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:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2010 Todd C. Miller <Todd.Miller@courtesan.com>
-
-Permission to use, copy, modify, and distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
--------------------------------------------------------------------
-
-Copyright (c) 2010, 2011, 2012, 2013 Intel Corporation
-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 Intel Corporation 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2010, Intel Corporation
-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 Intel Corporation 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2011 David Chisnall
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2011 David Schultz
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice unmodified, this list of conditions, and the following
-   disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2011 David Schultz <das@FreeBSD.ORG>
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2011 Ed Schouten <ed@FreeBSD.org>
-                   David Chisnall <theraven@FreeBSD.org>
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2011 Intel Corporation
-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 Intel Corporation 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2011 Martin Pieuchot <mpi@openbsd.org>
-
-Permission to use, copy, modify, and distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
--------------------------------------------------------------------
-
-Copyright (c) 2011 The Android Open Source Project
-Copyright (c) 2008 ARM Ltd
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. The name of the company may not be used to endorse or promote
-   products derived from this software without specific prior written
-   permission.
-
-THIS SOFTWARE IS PROVIDED BY ARM LTD ``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 ARM LTD 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2011, 2012, 2013 Intel Corporation
-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 Intel Corporation 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2011, Intel Corporation
-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 Intel Corporation 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2011, VMware, 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 the VMware, 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 VMWARE, INC. 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2012 Stephen Montgomery-Smith <stephen@FreeBSD.ORG>
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2012, Linaro Limited
-   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 the Linaro 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
-   HOLDER 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2012, Linaro Limited
-   All rights reserved.
-   Copyright (c) 2014, NVIDIA Corporation.  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 the Linaro 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
-   HOLDER 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2012-2013, Linaro Limited
-   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 the Linaro 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
-   HOLDER 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
-
--------------------------------------------------------------------
-
-Copyright (c) 2013
-     MIPS Technologies, Inc., California.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. Neither the name of the MIPS Technologies, 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 MIPS TECHNOLOGIES, INC. ``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 MIPS TECHNOLOGIES, INC. 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2013 ARM Ltd
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. The name of the company may not be used to endorse or promote
-   products derived from this software without specific prior written
-   permission.
-
-THIS SOFTWARE IS PROVIDED BY ARM LTD ``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 ARM LTD 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2013 Antoine Jacoutot <ajacoutot@openbsd.org>
-
-Permission to use, copy, modify, and distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
--------------------------------------------------------------------
-
-Copyright (c) 2013 The NetBSD Foundation, Inc.
-All rights reserved.
-
-This code is derived from software contributed to The NetBSD Foundation
-by Christos Zoulas.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2013, Linaro Limited
-   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 the Linaro 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
-   HOLDER 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
-
--------------------------------------------------------------------
-
-Copyright (c) 2013-2014, NVIDIA Corporation.  All rights reserved.
-Johnny Qiu <joqiu@nvidia.com>
-Shu Zhang <chazhang@nvidia.com>
-
-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 The Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
-WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
-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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2013-2015, Linaro Limited
-   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 the Linaro 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
-   HOLDER 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
-
--------------------------------------------------------------------
-
-Copyright (c) 2014 Theo de Raadt <deraadt@openbsd.org>
-Copyright (c) 2014 Bob Beck <beck@obtuse.com>
-
-Permission to use, copy, modify, and distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-Emulation of getentropy(2) as documented at:
-http://man.openbsd.org/getentropy.2
-
--------------------------------------------------------------------
-
-Copyright (c) 2014, Intel Corporation
-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 Intel Corporation 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2014, Linaro Limited
-   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 the Linaro 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
-   HOLDER 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2015 ARM Ltd
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. The name of the company may not be used to endorse or promote
-   products derived from this software without specific prior written
-   permission.
-
-THIS SOFTWARE IS PROVIDED BY ARM LTD ``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 ARM LTD 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2015 Joerg Sonnenberger <joerg@NetBSD.org>.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-
-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 HOLDERS 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2015 Nuxi, https://nuxi.nl/
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2017 ARM Ltd
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-3. The name of the company may not be used to endorse or promote
-   products derived from this software without specific prior written
-   permission.
-
-THIS SOFTWARE IS PROVIDED BY ARM LTD ``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 ARM LTD 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.
-
--------------------------------------------------------------------
-
-Copyright (c) 2017 Imagination Technologies.
-
-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 Imagination Technologies 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.
-
--------------------------------------------------------------------
-
-Copyright (c)1999 Citrus Project,
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-Copyright (c)2001 Citrus Project,
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-Copyright (c)2003 Citrus Project,
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-Copyright 1989 The Regents of the University of California.
-   All rights reserved.
-
-   Redistribution and use in source and binary forms, with or without
-   modification, are permitted provided that the following conditions
-   are met:
-   1. Redistributions of source code must retain the above copyright
-      notice, this list of conditions and the following disclaimer.
-   2. 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.
-   3. Neither the name of the University 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 REGENTS 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 REGENTS 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
-
--------------------------------------------------------------------
-
-Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
-Copyright 2008 Damien Miller <djm@openbsd.org>
-All rights reserved.
-
-Theo de Raadt <deraadt@openbsd.org> came up with the idea of using
-such a mathematical system to generate more random (yet non-repeating)
-ids to solve the resolver/named problem.  But Niels designed the
-actual system based on the constraints.
-
-Later modified by Damien Miller to wrap the LCG output in a 15-bit
-permutation generator based on a Luby-Rackoff block cipher. This
-ensures the output is non-repeating and preserves the MSB twiddle
-trick, but makes it more resistant to LCG prediction.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
-
--------------------------------------------------------------------
-
-From: @(#)s_ilogb.c 5.1 93/09/24
-====================================================
-Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
-
-Developed at SunPro, a Sun Microsystems, Inc. business.
-Permission to use, copy, modify, and distribute this
-software is freely granted, provided that this notice
-is preserved.
-
--------------------------------------------------------------------
-
-Portions Copyright (C) 2004, 2005, 2008, 2009  Internet Systems Consortium, Inc. ("ISC")
-Portions Copyright (C) 1996-2003  Internet Software Consortium.
-
-Permission to use, copy, modify, and/or distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
-REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
-INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-PERFORMANCE OF THIS SOFTWARE.
-
--------------------------------------------------------------------
-
-Portions Copyright (c) 1993 by Digital Equipment Corporation.
-
-Permission to use, copy, modify, and distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies, and that
-the name of Digital Equipment Corporation not be used in advertising or
-publicity pertaining to distribution of the document or software without
-specific, written prior permission.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
-WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
-OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
-CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
-DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
-PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
-ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
--------------------------------------------------------------------
-
-Portions Copyright (c) 1995 by International Business Machines, Inc.
-
-International Business Machines, Inc. (hereinafter called IBM) grants
-permission under its copyrights to use, copy, modify, and distribute this
-Software with or without fee, provided that the above copyright notice and
-all paragraphs of this notice appear in all copies, and that the name of IBM
-not be used in connection with the marketing of any product incorporating
-the Software or modifications thereof, without specific, written prior
-permission.
-
-To the extent it has a right to do so, IBM grants an immunity from suit
-under its patents, if any, for the use, sale or manufacture of products to
-the extent that such products are used for performing Domain Name System
-dynamic updates in TCP/IP networks by means of the Software.  No immunity is
-granted for any product per se or for any other function of any product.
-
-THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
-INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-PARTICULAR PURPOSE.  IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
-DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
-OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
-IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
-
--------------------------------------------------------------------
-
-Portions Copyright(C) 1995, Jason Downs.  All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-1. Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2. 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.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``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 AUTHOR(S) 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.
-
--------------------------------------------------------------------
-
-The author of this software is David M. Gay.
-
-Copyright (C) 1998 by Lucent Technologies
-All Rights Reserved
-
-Permission to use, copy, modify, and distribute this software and
-its documentation for any purpose and without fee is hereby
-granted, provided that the above copyright notice appear in all
-copies and that both that the copyright notice and this
-permission notice and warranty disclaimer appear in supporting
-documentation, and that the name of Lucent or any of its entities
-not be used in advertising or publicity pertaining to
-distribution of the software without specific, written prior
-permission.
-
-LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
-INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
-IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
-SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
-IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
-THIS SOFTWARE.
-
--------------------------------------------------------------------
-
-The author of this software is David M. Gay.
-
-Copyright (C) 1998, 1999 by Lucent Technologies
-All Rights Reserved
-
-Permission to use, copy, modify, and distribute this software and
-its documentation for any purpose and without fee is hereby
-granted, provided that the above copyright notice appear in all
-copies and that both that the copyright notice and this
-permission notice and warranty disclaimer appear in supporting
-documentation, and that the name of Lucent or any of its entities
-not be used in advertising or publicity pertaining to
-distribution of the software without specific, written prior
-permission.
-
-LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
-INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
-IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
-SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
-IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
-THIS SOFTWARE.
-
--------------------------------------------------------------------
-
-The author of this software is David M. Gay.
-
-Copyright (C) 1998, 2000 by Lucent Technologies
-All Rights Reserved
-
-Permission to use, copy, modify, and distribute this software and
-its documentation for any purpose and without fee is hereby
-granted, provided that the above copyright notice appear in all
-copies and that both that the copyright notice and this
-permission notice and warranty disclaimer appear in supporting
-documentation, and that the name of Lucent or any of its entities
-not be used in advertising or publicity pertaining to
-distribution of the software without specific, written prior
-permission.
-
-LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
-INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
-IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
-SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
-IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
-THIS SOFTWARE.
-
--------------------------------------------------------------------
-
-The author of this software is David M. Gay.
-
-Copyright (C) 1998-2000 by Lucent Technologies
-All Rights Reserved
-
-Permission to use, copy, modify, and distribute this software and
-its documentation for any purpose and without fee is hereby
-granted, provided that the above copyright notice appear in all
-copies and that both that the copyright notice and this
-permission notice and warranty disclaimer appear in supporting
-documentation, and that the name of Lucent or any of its entities
-not be used in advertising or publicity pertaining to
-distribution of the software without specific, written prior
-permission.
-
-LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
-INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
-IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
-SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
-IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
-THIS SOFTWARE.
-
--------------------------------------------------------------------
-
-The author of this software is David M. Gay.
-
-Copyright (C) 1998-2001 by Lucent Technologies
-All Rights Reserved
-
-Permission to use, copy, modify, and distribute this software and
-its documentation for any purpose and without fee is hereby
-granted, provided that the above copyright notice appear in all
-copies and that both that the copyright notice and this
-permission notice and warranty disclaimer appear in supporting
-documentation, and that the name of Lucent or any of its entities
-not be used in advertising or publicity pertaining to
-distribution of the software without specific, written prior
-permission.
-
-LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
-INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
-IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
-SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
-IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
-THIS SOFTWARE.
-
--------------------------------------------------------------------
-
-The author of this software is David M. Gay.
-
-Copyright (C) 2000 by Lucent Technologies
-All Rights Reserved
-
-Permission to use, copy, modify, and distribute this software and
-its documentation for any purpose and without fee is hereby
-granted, provided that the above copyright notice appear in all
-copies and that both that the copyright notice and this
-permission notice and warranty disclaimer appear in supporting
-documentation, and that the name of Lucent or any of its entities
-not be used in advertising or publicity pertaining to
-distribution of the software without specific, written prior
-permission.
-
-LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
-INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
-IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
-SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
-IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
-THIS SOFTWARE.
-
--------------------------------------------------------------------
-
diff --git a/third_party/address_sorting/address_sorting.c b/third_party/address_sorting/address_sorting.c
index ec46099..e4f3b53 100644
--- a/third_party/address_sorting/address_sorting.c
+++ b/third_party/address_sorting/address_sorting.c
@@ -225,15 +225,15 @@
 static int compare_source_dest_scope_matches(
     const address_sorting_sortable* first,
     const address_sorting_sortable* second) {
-  int first_src_dst_scope_matches = 0;
+  bool first_src_dst_scope_matches = false;
   if (sockaddr_get_scope(&first->dest_addr) ==
       sockaddr_get_scope(&first->source_addr)) {
-    first_src_dst_scope_matches = 1;
+    first_src_dst_scope_matches = true;
   }
-  int second_src_dst_scope_matches = 0;
+  bool second_src_dst_scope_matches = false;
   if (sockaddr_get_scope(&second->dest_addr) ==
       sockaddr_get_scope(&second->source_addr)) {
-    second_src_dst_scope_matches = 1;
+    second_src_dst_scope_matches = true;
   }
   if (first_src_dst_scope_matches != second_src_dst_scope_matches) {
     return first_src_dst_scope_matches ? -1 : 1;
@@ -244,18 +244,18 @@
 static int compare_source_dest_labels_match(
     const address_sorting_sortable* first,
     const address_sorting_sortable* second) {
-  int first_label_matches = 0;
+  bool first_label_matches = false;
   if (get_label_value(&first->dest_addr) ==
       get_label_value(&first->source_addr)) {
-    first_label_matches = 1;
+    first_label_matches = true;
   }
-  int second_label_matches = 0;
+  bool second_label_matches = false;
   if (get_label_value(&second->dest_addr) ==
       get_label_value(&second->source_addr)) {
-    second_label_matches = 1;
+    second_label_matches = true;
   }
   if (first_label_matches != second_label_matches) {
-    return first_label_matches ? 1 : 1;
+    return first_label_matches ? -1 : 1;
   }
   return 0;
 }
@@ -366,4 +366,5 @@
     abort();
   }
   g_current_source_addr_factory->vtable->destroy(g_current_source_addr_factory);
+  g_current_source_addr_factory = NULL;
 }
diff --git a/third_party/protobuf b/third_party/protobuf
index 2761122..b5fbb74 160000
--- a/third_party/protobuf
+++ b/third_party/protobuf
@@ -1 +1 @@
-Subproject commit 2761122b810fe8861004ae785cc3ab39f384d342
+Subproject commit b5fbb742af122b565925987e65c08957739976a7
diff --git a/tools/codegen/core/gen_stats_data.py b/tools/codegen/core/gen_stats_data.py
index 5c9d9e5..3ebd00d 100755
--- a/tools/codegen/core/gen_stats_data.py
+++ b/tools/codegen/core/gen_stats_data.py
@@ -230,13 +230,11 @@
     print >> H, "#ifndef GRPC_CORE_LIB_DEBUG_STATS_DATA_H"
     print >> H, "#define GRPC_CORE_LIB_DEBUG_STATS_DATA_H"
     print >> H
+    print >> H, "#include <grpc/support/port_platform.h>"
+    print >> H
     print >> H, "#include <inttypes.h>"
     print >> H, "#include \"src/core/lib/iomgr/exec_ctx.h\""
     print >> H
-    print >> H, "#ifdef __cplusplus"
-    print >> H, "extern \"C\" {"
-    print >> H, "#endif"
-    print >> H
 
     for typename, instances in sorted(inst_map.items()):
         print >> H, "typedef enum {"
@@ -290,10 +288,6 @@
         inst_map['Histogram'])
 
     print >> H
-    print >> H, "#ifdef __cplusplus"
-    print >> H, "}"
-    print >> H, "#endif"
-    print >> H
     print >> H, "#endif /* GRPC_CORE_LIB_DEBUG_STATS_DATA_H */"
 
 with open('src/core/lib/debug/stats_data.cc', 'w') as C:
@@ -316,10 +310,13 @@
         [C],
         ["Automatically generated by tools/codegen/core/gen_stats_data.py"])
 
-    print >> C, "#include \"src/core/lib/debug/stats_data.h\""
+    print >> C, "#include <grpc/support/port_platform.h>"
+    print >> C
     print >> C, "#include \"src/core/lib/debug/stats.h\""
+    print >> C, "#include \"src/core/lib/debug/stats_data.h\""
+    print >> C, "#include \"src/core/lib/gpr/useful.h\""
     print >> C, "#include \"src/core/lib/iomgr/exec_ctx.h\""
-    print >> C, "#include <grpc/support/useful.h>"
+    print >> C
 
     histo_code = []
     for histogram in inst_map['Histogram']:
diff --git a/tools/distrib/build_ruby_environment_macos.sh b/tools/distrib/build_ruby_environment_macos.sh
index 4a388a0..9e3e3b4 100644
--- a/tools/distrib/build_ruby_environment_macos.sh
+++ b/tools/distrib/build_ruby_environment_macos.sh
@@ -23,9 +23,9 @@
 
 # See https://github.com/grpc/grpc/issues/12161 for verconf.h patch details
 patch "$CROSS_RUBY" << EOF
---- cross-ruby.rake 2017-09-27 16:46:00.311020325 +0200
-+++ patched 2017-09-27 16:49:46.127016895 +0200
-@@ -133,7 +133,8 @@
+--- cross-ruby.rake	2018-04-10 11:32:16.000000000 -0700
++++ patched	2018-04-10 11:40:25.000000000 -0700
+@@ -133,8 +133,10 @@
      "--host=#{MINGW_HOST}",
      "--target=#{MINGW_TARGET}",
      "--build=#{RUBY_BUILD}",
@@ -33,9 +33,11 @@
 +    '--enable-static',
 +    '--disable-shared',
      '--disable-install-doc',
++    '--without-gmp',
      '--with-ext='
    ]
-@@ -151,6 +152,7 @@
+ 
+@@ -151,6 +153,7 @@
  # make
  file "#{USER_HOME}/builds/#{MINGW_HOST}/#{RUBY_CC_VERSION}/ruby.exe" => ["#{USER_HOME}/builds/#{MINGW_HOST}/#{RUBY_CC_VERSION}/Makefile"] do |t|
    chdir File.dirname(t.prerequisites.first) do
diff --git a/tools/distrib/check_copyright.py b/tools/distrib/check_copyright.py
index e7893a1..09eecf4 100755
--- a/tools/distrib/check_copyright.py
+++ b/tools/distrib/check_copyright.py
@@ -93,11 +93,12 @@
     # status.proto copied from googleapis
     'src/proto/grpc/status/status.proto',
 
-    # Gradle wrapper used to build for Android
+    # Gradle wrappers used to build for Android
     'examples/android/helloworld/gradlew.bat',
+    'src/android/test/interop/gradlew.bat',
 ))
 
-RE_YEAR = r'Copyright (?P<first_year>[0-9]+\-)?(?P<last_year>[0-9]+) gRPC authors.'
+RE_YEAR = r'Copyright (?P<first_year>[0-9]+\-)?(?P<last_year>[0-9]+) ([Tt]he )?gRPC [Aa]uthors(\.|)'
 RE_LICENSE = dict(
     (k, r'\n'.join(LICENSE_PREFIX[k] +
                    (RE_YEAR if re.search(RE_YEAR, line) else re.escape(line))
diff --git a/tools/distrib/pylint_code.sh b/tools/distrib/pylint_code.sh
index 7175f1e..013b666 100755
--- a/tools/distrib/pylint_code.sh
+++ b/tools/distrib/pylint_code.sh
@@ -25,15 +25,24 @@
     'src/python/grpcio_testing/grpc_testing'
 )
 
-VIRTUALENV=python_pylint_venv
+TEST_DIRS=(
+    'src/python/grpcio_tests/tests'
+)
 
-virtualenv $VIRTUALENV
-PYTHON=$(realpath $VIRTUALENV/bin/python)
-$PYTHON -m pip install --upgrade pip==9.0.1
+VIRTUALENV=python_pylint_venv
+python -m virtualenv $VIRTUALENV
+
+PYTHON=$VIRTUALENV/bin/python
+
+$PYTHON -m pip install --upgrade pip==10.0.1
 $PYTHON -m pip install pylint==1.6.5
 
 for dir in "${DIRS[@]}"; do
   $PYTHON -m pylint --rcfile=.pylintrc -rn "$dir" || exit $?
 done
 
+for dir in "${TEST_DIRS[@]}"; do
+  $PYTHON -m pylint --rcfile=.pylintrc-tests -rn "$dir" || exit $?
+done
+
 exit 0
diff --git a/tools/distrib/python/docgen.py b/tools/distrib/python/docgen.py
index 4d6fcb5..732d948 100755
--- a/tools/distrib/python/docgen.py
+++ b/tools/distrib/python/docgen.py
@@ -70,7 +70,7 @@
         'env': environment
     },
     {
-        'args': [VIRTUALENV_PIP_PATH, 'install', '--upgrade', 'pip==9.0.1'],
+        'args': [VIRTUALENV_PIP_PATH, 'install', '--upgrade', 'pip==10.0.1'],
         'env': environment
     },
     {
diff --git a/tools/distrib/python/grpcio_tools/grpc_version.py b/tools/distrib/python/grpcio_tools/grpc_version.py
index e8ca685..f0367e2 100644
--- a/tools/distrib/python/grpcio_tools/grpc_version.py
+++ b/tools/distrib/python/grpcio_tools/grpc_version.py
@@ -14,4 +14,4 @@
 
 # AUTO-GENERATED FROM `$REPO_ROOT/templates/tools/distrib/python/grpcio_tools/grpc_version.py.template`!!!
 
-VERSION = '1.11.0.dev0'
+VERSION = '1.13.0.dev0'
diff --git a/tools/distrib/python/grpcio_tools/protoc_lib_deps.py b/tools/distrib/python/grpcio_tools/protoc_lib_deps.py
index 2c65fca..a0e1419 100644
--- a/tools/distrib/python/grpcio_tools/protoc_lib_deps.py
+++ b/tools/distrib/python/grpcio_tools/protoc_lib_deps.py
@@ -20,4 +20,4 @@
 CC_INCLUDE='third_party/protobuf/src'
 PROTO_INCLUDE='third_party/protobuf/src'
 
-PROTOBUF_SUBMODULE_VERSION="2761122b810fe8861004ae785cc3ab39f384d342"
+PROTOBUF_SUBMODULE_VERSION="b5fbb742af122b565925987e65c08957739976a7"
diff --git a/tools/distrib/yapf_code.sh b/tools/distrib/yapf_code.sh
index d188a02..27c5e31 100755
--- a/tools/distrib/yapf_code.sh
+++ b/tools/distrib/yapf_code.sh
@@ -30,11 +30,11 @@
 
 VIRTUALENV=yapf_virtual_environment
 
-virtualenv $VIRTUALENV
-PYTHON=$(realpath "${VIRTUALENV}/bin/python")
-$PYTHON -m pip install --upgrade pip==9.0.1
-$PYTHON -m pip install --upgrade futures
-$PYTHON -m pip install yapf==0.20.0
+python -m virtualenv $VIRTUALENV
+PYTHON=${VIRTUALENV}/bin/python
+"$PYTHON" -m pip install --upgrade pip==10.0.1
+"$PYTHON" -m pip install --upgrade futures
+"$PYTHON" -m pip install yapf==0.20.0
 
 yapf() {
     local exclusion exclusion_args=()
diff --git a/tools/dockerfile/distribtest/python_dev_arch_x64/Dockerfile b/tools/dockerfile/distribtest/python_dev_arch_x64/Dockerfile
new file mode 100644
index 0000000..7f09fd6
--- /dev/null
+++ b/tools/dockerfile/distribtest/python_dev_arch_x64/Dockerfile
@@ -0,0 +1,22 @@
+# Copyright 2015 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.
+
+FROM base/archlinux
+
+RUN pacman --noconfirm -Syy
+RUN pacman --noconfirm -S openssl
+RUN pacman --noconfirm -S python2
+RUN pacman --noconfirm -S python2-pip
+RUN pip2 install virtualenv
+RUN pacman --noconfirm -S base-devel
diff --git a/tools/dockerfile/distribtest/python_dev_centos7_x64/Dockerfile b/tools/dockerfile/distribtest/python_dev_centos7_x64/Dockerfile
new file mode 100644
index 0000000..954146c
--- /dev/null
+++ b/tools/dockerfile/distribtest/python_dev_centos7_x64/Dockerfile
@@ -0,0 +1,22 @@
+# Copyright 2015 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.
+
+FROM centos:7
+
+RUN yum install -y python
+RUN yum install -y epel-release
+RUN yum install -y python-pip
+RUN pip install virtualenv
+RUN yum groupinstall -y 'Development Tools'
+RUN yum install -y python-devel
diff --git a/tools/dockerfile/distribtest/python_dev_fedora22_x64/Dockerfile b/tools/dockerfile/distribtest/python_dev_fedora22_x64/Dockerfile
new file mode 100644
index 0000000..d86ad37
--- /dev/null
+++ b/tools/dockerfile/distribtest/python_dev_fedora22_x64/Dockerfile
@@ -0,0 +1,23 @@
+# Copyright 2015 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.
+
+FROM fedora:22
+
+RUN yum clean all && yum update -y && yum install -y python python-pip
+RUN pip install virtualenv
+
+RUN yum groupinstall -y "Development Tools"
+RUN yum install -y redhat-rpm-config
+RUN yum install -y gcc-c++
+RUN yum install -y python2-devel
diff --git a/tools/dockerfile/distribtest/python_dev_fedora23_x64/Dockerfile b/tools/dockerfile/distribtest/python_dev_fedora23_x64/Dockerfile
new file mode 100644
index 0000000..0dbf5e4
--- /dev/null
+++ b/tools/dockerfile/distribtest/python_dev_fedora23_x64/Dockerfile
@@ -0,0 +1,23 @@
+# Copyright 2015 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.
+
+FROM fedora:23
+
+RUN yum clean all && yum update -y && yum install -y python python-pip
+RUN pip install virtualenv
+
+RUN yum groupinstall -y "Development Tools"
+RUN yum install -y redhat-rpm-config
+RUN yum install -y gcc-c++
+RUN yum install -y python2-devel
diff --git a/tools/dockerfile/distribtest/python_dev_jessie_x64/Dockerfile b/tools/dockerfile/distribtest/python_dev_jessie_x64/Dockerfile
new file mode 100644
index 0000000..c222898
--- /dev/null
+++ b/tools/dockerfile/distribtest/python_dev_jessie_x64/Dockerfile
@@ -0,0 +1,21 @@
+# Copyright 2015 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.
+
+FROM debian:jessie
+
+RUN apt-get update && apt-get install -y python python-pip
+RUN pip install virtualenv
+
+RUN apt-get install -y build-essential
+RUN apt-get install -y python-dev
diff --git a/tools/dockerfile/distribtest/python_dev_jessie_x86/Dockerfile b/tools/dockerfile/distribtest/python_dev_jessie_x86/Dockerfile
new file mode 100644
index 0000000..5e0b8ef
--- /dev/null
+++ b/tools/dockerfile/distribtest/python_dev_jessie_x86/Dockerfile
@@ -0,0 +1,27 @@
+# Copyright 2015 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.
+
+FROM 32bit/debian:jessie
+
+RUN apt-get update && apt-get install -y python python-pip
+
+RUN pip install virtualenv
+
+RUN apt-get install -y build-essential
+RUN apt-get install -y python-dev
+
+# docker is running on a 64-bit machine, so we need to
+# override "uname -m" to report i686 instead of x86_64, otherwise
+# python will choose a wrong binary package to install.
+ENTRYPOINT ["linux32"]
diff --git a/tools/dockerfile/distribtest/python_dev_ubuntu1404_x64/Dockerfile b/tools/dockerfile/distribtest/python_dev_ubuntu1404_x64/Dockerfile
new file mode 100644
index 0000000..6c842ae
--- /dev/null
+++ b/tools/dockerfile/distribtest/python_dev_ubuntu1404_x64/Dockerfile
@@ -0,0 +1,22 @@
+# Copyright 2015 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.
+
+FROM ubuntu:14.04
+
+RUN apt-get update -y && apt-get install -y python python-pip
+
+RUN apt-get install -y build-essential
+RUN apt-get install -y python-dev
+
+RUN pip install virtualenv
diff --git a/tools/dockerfile/distribtest/python_dev_ubuntu1604_x64/Dockerfile b/tools/dockerfile/distribtest/python_dev_ubuntu1604_x64/Dockerfile
new file mode 100644
index 0000000..1ff1e0a
--- /dev/null
+++ b/tools/dockerfile/distribtest/python_dev_ubuntu1604_x64/Dockerfile
@@ -0,0 +1,22 @@
+# Copyright 2015 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.
+
+FROM ubuntu:16.04
+
+RUN apt-get update -y && apt-get install -y python python-pip
+
+RUN apt-get install -y build-essential
+RUN apt-get install -y python-dev
+
+RUN pip install virtualenv
diff --git a/tools/dockerfile/distribtest/ruby_fedora20_x64/Dockerfile b/tools/dockerfile/distribtest/ruby_fedora20_x64/Dockerfile
index 5ea51214f..200c5c2 100644
--- a/tools/dockerfile/distribtest/ruby_fedora20_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/ruby_fedora20_x64/Dockerfile
@@ -14,6 +14,6 @@
 
 FROM fedora:20
 
-RUN yum clean all && yum update -y && yum install -y ruby
+RUN yum clean all && yum update -y && yum install -y ruby findutils
 
 RUN gem install bundler
diff --git a/tools/dockerfile/distribtest/ruby_fedora21_x64/Dockerfile b/tools/dockerfile/distribtest/ruby_fedora21_x64/Dockerfile
index b903401..e1177fd 100644
--- a/tools/dockerfile/distribtest/ruby_fedora21_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/ruby_fedora21_x64/Dockerfile
@@ -19,6 +19,6 @@
 # https://github.com/docker/docker/issues/10180
 RUN yum install -y yum-plugin-ovl
 
-RUN yum clean all && yum update -y && yum install -y ruby
+RUN yum clean all && yum update -y && yum install -y ruby findutils
 
 RUN gem install bundler
diff --git a/tools/dockerfile/distribtest/ruby_fedora22_x64/Dockerfile b/tools/dockerfile/distribtest/ruby_fedora22_x64/Dockerfile
index 0d57370..848c5be 100644
--- a/tools/dockerfile/distribtest/ruby_fedora22_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/ruby_fedora22_x64/Dockerfile
@@ -14,6 +14,6 @@
 
 FROM fedora:22
 
-RUN yum clean all && yum update -y && yum install -y ruby
+RUN yum clean all && yum update -y && yum install -y ruby findutils
 
 RUN gem install bundler
diff --git a/tools/dockerfile/distribtest/ruby_fedora23_x64/Dockerfile b/tools/dockerfile/distribtest/ruby_fedora23_x64/Dockerfile
index 318993b..47dd577 100644
--- a/tools/dockerfile/distribtest/ruby_fedora23_x64/Dockerfile
+++ b/tools/dockerfile/distribtest/ruby_fedora23_x64/Dockerfile
@@ -14,6 +14,6 @@
 
 FROM fedora:23
 
-RUN yum clean all && yum update -y && yum install -y ruby
+RUN yum clean all && yum update -y && yum install -y ruby findutils
 
 RUN gem install bundler
diff --git a/tools/dockerfile/grpc_artifact_android_ndk/Dockerfile b/tools/dockerfile/grpc_artifact_android_ndk/Dockerfile
new file mode 100644
index 0000000..77b6acf
--- /dev/null
+++ b/tools/dockerfile/grpc_artifact_android_ndk/Dockerfile
@@ -0,0 +1,68 @@
+# 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.
+
+# Docker file for building gRPC artifacts.
+
+# Recent enough cmake (>=3.9) needed by Android SDK
+FROM debian:sid
+
+RUN apt-get update && apt-get install -y debian-keyring && apt-key update
+
+# Install Git and basic packages.
+RUN apt-get update && apt-key update && apt-get install -y \
+  autoconf \
+  autotools-dev \
+  build-essential \
+  bzip2 \
+  clang \
+  curl \
+  gcc \
+  gcc-multilib \
+  git \
+  golang \
+  libc6 \
+  libc6-dbg \
+  libc6-dev \
+  libgtest-dev \
+  libtool \
+  make \
+  perl \
+  strace \
+  python-dev \
+  python-setuptools \
+  python-yaml \
+  telnet \
+  unzip \
+  wget \
+  zip && apt-get clean
+
+# Cmake for cross-compilation
+RUN apt-get update && apt-get install -y cmake golang && apt-get clean
+
+##################
+# Android NDK
+
+# Download and install Android NDK
+RUN wget -q https://dl.google.com/android/repository/android-ndk-r16b-linux-x86_64.zip -O android_ndk.zip \
+    && unzip -q android_ndk.zip \
+    && rm android_ndk.zip \
+    && mv ./android-ndk-r16b /opt
+ENV ANDROID_NDK_PATH /opt/android-ndk-r16b
+
+RUN apt-get update && apt-get install -y libpthread-stubs0-dev && apt-get clean
+
+RUN mkdir /var/local/jenkins
+
+# Define the default command.
+CMD ["bash"]
diff --git a/tools/dockerfile/grpc_clang_format/clang_format_all_the_things.sh b/tools/dockerfile/grpc_clang_format/clang_format_all_the_things.sh
index 08c6a96..3b901ae 100755
--- a/tools/dockerfile/grpc_clang_format/clang_format_all_the_things.sh
+++ b/tools/dockerfile/grpc_clang_format/clang_format_all_the_things.sh
@@ -16,10 +16,10 @@
 set -e
 
 # directories to run against
-DIRS="src/core/lib src/core/tsi src/core/ext src/cpp test/core test/cpp include src/compiler src/csharp src/ruby third_party/address_sorting"
+DIRS="src/core/lib src/core/tsi src/core/ext src/cpp test/core test/cpp include src/compiler src/csharp src/ruby third_party/address_sorting src/objective-c"
 
 # file matching patterns to check
-GLOB="*.h *.c *.cc"
+GLOB="*.h *.c *.cc *.m *.mm"
 
 # clang format command
 CLANG_FORMAT=${CLANG_FORMAT:-clang-format-5.0}
@@ -29,7 +29,7 @@
 do
   for glob in $GLOB
   do
-    files="$files `find ${CLANG_FORMAT_ROOT}/$dir -name $glob -and -not -name '*.generated.*' -and -not -name '*.pb.h' -and -not -name '*.pb.c' -and -not -name '*.pb.cc' -and -not -name end2end_tests.cc -and -not -name end2end_nosec_tests.cc -and -not -name public_headers_must_be_c89.c`"
+    files="$files `find ${CLANG_FORMAT_ROOT}/$dir -name $glob -and -not -name '*.generated.*' -and -not -name '*.pb.h' -and -not -name '*.pb.c' -and -not -name '*.pb.cc' -and -not -name '*.pbobjc.h' -and -not -name '*.pbobjc.m' -and -not -name '*.pbrpc.h' -and -not -name '*.pbrpc.m' -and -not -name end2end_tests.cc -and -not -name end2end_nosec_tests.cc -and -not -name public_headers_must_be_c89.c`"
   done
 done
 
diff --git a/tools/dockerfile/grpc_clang_tidy/Dockerfile b/tools/dockerfile/grpc_clang_tidy/Dockerfile
index eeba455..dec7680 100644
--- a/tools/dockerfile/grpc_clang_tidy/Dockerfile
+++ b/tools/dockerfile/grpc_clang_tidy/Dockerfile
@@ -33,9 +33,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.1
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 ADD clang_tidy_all_the_things.sh /
 
diff --git a/tools/dockerfile/interoptest/grpc_interop_android_java/Dockerfile b/tools/dockerfile/interoptest/grpc_interop_android_java/Dockerfile
deleted file mode 100644
index 519cdbf..0000000
--- a/tools/dockerfile/interoptest/grpc_interop_android_java/Dockerfile
+++ /dev/null
@@ -1,78 +0,0 @@
-# Copyright 2017 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.
-
-FROM debian:jessie
-
-# Install JDK 8 and Git
-RUN echo oracle-java8-installer shared/accepted-oracle-license-v1-1 select true | /usr/bin/debconf-set-selections && \
-  echo "deb http://ppa.launchpad.net/webupd8team/java/ubuntu trusty main" | tee /etc/apt/sources.list.d/webupd8team-java.list && \
-  echo "deb-src http://ppa.launchpad.net/webupd8team/java/ubuntu trusty main" | tee -a /etc/apt/sources.list.d/webupd8team-java.list && \
-  apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys EEA14886
-RUN apt-get update && apt-get -y install \
-      git \
-      libapr1 \
-      oracle-java8-installer \
-      && \
-    apt-get clean && rm -r /var/cache/oracle-jdk8-installer/
-ENV JAVA_HOME /usr/lib/jvm/java-8-oracle
-ENV PATH $PATH:$JAVA_HOME/bin
-
-# Install protobuf
-RUN apt-get update && apt-get install -y \
-      autoconf \
-      build-essential \
-      curl \
-      gcc \
-      libtool \
-      unzip \
-      && \
-    apt-get clean
-WORKDIR /
-RUN git clone https://github.com/google/protobuf.git
-WORKDIR /protobuf
-RUN git checkout v3.3.1 && \
-  ./autogen.sh && \
-  ./configure && \
-  make && \
-  make check && \
-  make install
-
-# Install gcloud command line tools
-ENV CLOUD_SDK_REPO "cloud-sdk-jessie"
-RUN echo "deb http://packages.cloud.google.com/apt $CLOUD_SDK_REPO main" | tee -a /etc/apt/sources.list.d/google-cloud-sdk.list && \
-  curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add - && \
-  apt-get update && apt-get install -y google-cloud-sdk && apt-get clean && \
-  gcloud config set component_manager/disable_update_check true
-
-# Install Android SDK
-WORKDIR /
-RUN mkdir android-sdk
-WORKDIR android-sdk
-RUN wget -q https://dl.google.com/android/repository/tools_r25.2.5-linux.zip && \
-  unzip -qq tools_r25.2.5-linux.zip && \
-  rm tools_r25.2.5-linux.zip && \
-  echo y | tools/bin/sdkmanager "platforms;android-22" && \
-  echo y | tools/bin/sdkmanager "build-tools;25.0.2" && \
-  echo y | tools/bin/sdkmanager "extras;android;m2repository" && \
-  echo y | tools/bin/sdkmanager "extras;google;google_play_services" && \
-  echo y | tools/bin/sdkmanager "extras;google;m2repository" && \
-  echo y | tools/bin/sdkmanager "patcher;v4" && \
-  echo y | tools/bin/sdkmanager "platform-tools"
-ENV ANDROID_HOME "/android-sdk"
-
-# Reset the working directory
-WORKDIR /
-
-# Define the default command.
-CMD ["bash"]
diff --git a/tools/dockerfile/interoptest/grpc_interop_csharp/Dockerfile b/tools/dockerfile/interoptest/grpc_interop_csharp/Dockerfile
index af2ab90..e806ba5 100644
--- a/tools/dockerfile/interoptest/grpc_interop_csharp/Dockerfile
+++ b/tools/dockerfile/interoptest/grpc_interop_csharp/Dockerfile
@@ -60,9 +60,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.1
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 #================
 # C# dependencies
diff --git a/tools/dockerfile/interoptest/grpc_interop_csharpcoreclr/Dockerfile b/tools/dockerfile/interoptest/grpc_interop_csharpcoreclr/Dockerfile
index af2ab90..e806ba5 100644
--- a/tools/dockerfile/interoptest/grpc_interop_csharpcoreclr/Dockerfile
+++ b/tools/dockerfile/interoptest/grpc_interop_csharpcoreclr/Dockerfile
@@ -60,9 +60,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.1
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 #================
 # C# dependencies
diff --git a/tools/dockerfile/interoptest/grpc_interop_cxx/Dockerfile b/tools/dockerfile/interoptest/grpc_interop_cxx/Dockerfile
index ec5338b..d3eb456 100644
--- a/tools/dockerfile/interoptest/grpc_interop_cxx/Dockerfile
+++ b/tools/dockerfile/interoptest/grpc_interop_cxx/Dockerfile
@@ -60,9 +60,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.1
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 #=================
 # C++ dependencies
diff --git a/tools/dockerfile/interoptest/grpc_interop_go/Dockerfile b/tools/dockerfile/interoptest/grpc_interop_go/Dockerfile
index a775961..b136259 100644
--- a/tools/dockerfile/interoptest/grpc_interop_go/Dockerfile
+++ b/tools/dockerfile/interoptest/grpc_interop_go/Dockerfile
@@ -28,9 +28,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.1
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 # Define the default command.
 CMD ["bash"]
diff --git a/tools/dockerfile/interoptest/grpc_interop_go1.7/Dockerfile b/tools/dockerfile/interoptest/grpc_interop_go1.7/Dockerfile
index c296c8c..d43d0e4 100644
--- a/tools/dockerfile/interoptest/grpc_interop_go1.7/Dockerfile
+++ b/tools/dockerfile/interoptest/grpc_interop_go1.7/Dockerfile
@@ -28,9 +28,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.1
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 # Define the default command.
 CMD ["bash"]
diff --git a/tools/dockerfile/interoptest/grpc_interop_go1.8/Dockerfile b/tools/dockerfile/interoptest/grpc_interop_go1.8/Dockerfile
index 9ac0b97..17ca678 100644
--- a/tools/dockerfile/interoptest/grpc_interop_go1.8/Dockerfile
+++ b/tools/dockerfile/interoptest/grpc_interop_go1.8/Dockerfile
@@ -28,9 +28,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.1
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 # Define the default command.
 CMD ["bash"]
diff --git a/tools/dockerfile/interoptest/grpc_interop_http2/Dockerfile b/tools/dockerfile/interoptest/grpc_interop_http2/Dockerfile
index 92a2faa..e7555c9 100644
--- a/tools/dockerfile/interoptest/grpc_interop_http2/Dockerfile
+++ b/tools/dockerfile/interoptest/grpc_interop_http2/Dockerfile
@@ -28,9 +28,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.1
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 RUN pip install twisted h2==2.6.1 hyper
 
diff --git a/tools/dockerfile/interoptest/grpc_interop_java/Dockerfile b/tools/dockerfile/interoptest/grpc_interop_java/Dockerfile
index 34b4e39..fc29ada 100644
--- a/tools/dockerfile/interoptest/grpc_interop_java/Dockerfile
+++ b/tools/dockerfile/interoptest/grpc_interop_java/Dockerfile
@@ -43,9 +43,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.1
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 
 # Trigger download of as many Gradle artifacts as possible.
diff --git a/tools/dockerfile/interoptest/grpc_interop_java_oracle8/Dockerfile b/tools/dockerfile/interoptest/grpc_interop_java_oracle8/Dockerfile
index 34b4e39..fc29ada 100644
--- a/tools/dockerfile/interoptest/grpc_interop_java_oracle8/Dockerfile
+++ b/tools/dockerfile/interoptest/grpc_interop_java_oracle8/Dockerfile
@@ -43,9 +43,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.1
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 
 # Trigger download of as many Gradle artifacts as possible.
diff --git a/tools/dockerfile/interoptest/grpc_interop_node/Dockerfile b/tools/dockerfile/interoptest/grpc_interop_node/Dockerfile
index b480d31..539a869 100644
--- a/tools/dockerfile/interoptest/grpc_interop_node/Dockerfile
+++ b/tools/dockerfile/interoptest/grpc_interop_node/Dockerfile
@@ -60,9 +60,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.1
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 #==================
 # Node dependencies
diff --git a/tools/dockerfile/interoptest/grpc_interop_python/Dockerfile b/tools/dockerfile/interoptest/grpc_interop_python/Dockerfile
index 07f419f..94290f3 100644
--- a/tools/dockerfile/interoptest/grpc_interop_python/Dockerfile
+++ b/tools/dockerfile/interoptest/grpc_interop_python/Dockerfile
@@ -60,9 +60,13 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.1
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
+
+# Install pip and virtualenv for Python 3.4
+RUN curl https://bootstrap.pypa.io/get-pip.py | python3.4
+RUN python3.4 -m pip install virtualenv
 
 # Prepare ccache
 RUN ln -s /usr/bin/ccache /usr/local/bin/gcc
diff --git a/tools/dockerfile/interoptest/grpc_interop_ruby/Dockerfile b/tools/dockerfile/interoptest/grpc_interop_ruby/Dockerfile
index 543e207..75e3314 100644
--- a/tools/dockerfile/interoptest/grpc_interop_ruby/Dockerfile
+++ b/tools/dockerfile/interoptest/grpc_interop_ruby/Dockerfile
@@ -60,9 +60,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.1
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 #==================
 # Ruby dependencies
diff --git a/tools/dockerfile/test/csharp_jessie_x64/Dockerfile b/tools/dockerfile/test/csharp_jessie_x64/Dockerfile
index 0fae21d..7a8e26d 100644
--- a/tools/dockerfile/test/csharp_jessie_x64/Dockerfile
+++ b/tools/dockerfile/test/csharp_jessie_x64/Dockerfile
@@ -64,9 +64,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.1
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 #================
 # C# dependencies
diff --git a/tools/dockerfile/test/cxx_alpine_x64/Dockerfile b/tools/dockerfile/test/cxx_alpine_x64/Dockerfile
index c68a5dd..3449af1 100644
--- a/tools/dockerfile/test/cxx_alpine_x64/Dockerfile
+++ b/tools/dockerfile/test/cxx_alpine_x64/Dockerfile
@@ -32,12 +32,13 @@
   strace \
   python-dev \
   py-pip \
+  py-yaml \
   unzip \
   wget \
   zip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.1
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
 RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
 
diff --git a/tools/dockerfile/test/cxx_jessie_x64/Dockerfile b/tools/dockerfile/test/cxx_jessie_x64/Dockerfile
index dff4c96..f251753 100644
--- a/tools/dockerfile/test/cxx_jessie_x64/Dockerfile
+++ b/tools/dockerfile/test/cxx_jessie_x64/Dockerfile
@@ -64,9 +64,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.1
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 #=================
 # C++ dependencies
diff --git a/tools/dockerfile/test/cxx_jessie_x86/Dockerfile b/tools/dockerfile/test/cxx_jessie_x86/Dockerfile
index ea1d645..bb9c751 100644
--- a/tools/dockerfile/test/cxx_jessie_x86/Dockerfile
+++ b/tools/dockerfile/test/cxx_jessie_x86/Dockerfile
@@ -64,9 +64,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.1
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 #=================
 # C++ dependencies
diff --git a/tools/dockerfile/test/cxx_ubuntu1404_x64/Dockerfile b/tools/dockerfile/test/cxx_ubuntu1404_x64/Dockerfile
index 990dac9..b0d9261 100644
--- a/tools/dockerfile/test/cxx_ubuntu1404_x64/Dockerfile
+++ b/tools/dockerfile/test/cxx_ubuntu1404_x64/Dockerfile
@@ -64,9 +64,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.1
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 #=================
 # C++ dependencies
diff --git a/tools/dockerfile/test/cxx_ubuntu1604_x64/Dockerfile b/tools/dockerfile/test/cxx_ubuntu1604_x64/Dockerfile
index c8943ca..65ff58e 100644
--- a/tools/dockerfile/test/cxx_ubuntu1604_x64/Dockerfile
+++ b/tools/dockerfile/test/cxx_ubuntu1604_x64/Dockerfile
@@ -64,9 +64,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.1
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 #=================
 # C++ dependencies
diff --git a/tools/dockerfile/test/cxx_ubuntu1710_x64/Dockerfile b/tools/dockerfile/test/cxx_ubuntu1710_x64/Dockerfile
index 11aca17..e926443 100644
--- a/tools/dockerfile/test/cxx_ubuntu1710_x64/Dockerfile
+++ b/tools/dockerfile/test/cxx_ubuntu1710_x64/Dockerfile
@@ -64,9 +64,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.1
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 #=================
 # C++ dependencies
diff --git a/tools/dockerfile/test/fuzzer/Dockerfile b/tools/dockerfile/test/fuzzer/Dockerfile
index 52666ea..a242492 100644
--- a/tools/dockerfile/test/fuzzer/Dockerfile
+++ b/tools/dockerfile/test/fuzzer/Dockerfile
@@ -64,9 +64,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.1
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 #=================
 # C++ dependencies
diff --git a/tools/dockerfile/test/multilang_jessie_x64/Dockerfile b/tools/dockerfile/test/multilang_jessie_x64/Dockerfile
index 5818ff9..e22484f 100644
--- a/tools/dockerfile/test/multilang_jessie_x64/Dockerfile
+++ b/tools/dockerfile/test/multilang_jessie_x64/Dockerfile
@@ -140,9 +140,13 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.1
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
+
+# Install pip and virtualenv for Python 3.4
+RUN curl https://bootstrap.pypa.io/get-pip.py | python3.4
+RUN python3.4 -m pip install virtualenv
 
 # Install coverage for Python test coverage reporting
 RUN pip install coverage
diff --git a/tools/dockerfile/test/node_jessie_x64/Dockerfile b/tools/dockerfile/test/node_jessie_x64/Dockerfile
index 05c8319..f32b437 100644
--- a/tools/dockerfile/test/node_jessie_x64/Dockerfile
+++ b/tools/dockerfile/test/node_jessie_x64/Dockerfile
@@ -75,9 +75,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.1
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 #==================
 # Node dependencies
diff --git a/tools/dockerfile/test/php7_jessie_x64/Dockerfile b/tools/dockerfile/test/php7_jessie_x64/Dockerfile
index 865bf69..e96be27 100644
--- a/tools/dockerfile/test/php7_jessie_x64/Dockerfile
+++ b/tools/dockerfile/test/php7_jessie_x64/Dockerfile
@@ -75,9 +75,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.1
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 # Prepare ccache
 RUN ln -s /usr/bin/ccache /usr/local/bin/gcc
diff --git a/tools/dockerfile/test/php_jessie_x64/Dockerfile b/tools/dockerfile/test/php_jessie_x64/Dockerfile
index fb653d3..88ee267 100644
--- a/tools/dockerfile/test/php_jessie_x64/Dockerfile
+++ b/tools/dockerfile/test/php_jessie_x64/Dockerfile
@@ -64,9 +64,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.1
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 #=================
 # PHP dependencies
diff --git a/tools/dockerfile/test/python_alpine_x64/Dockerfile b/tools/dockerfile/test/python_alpine_x64/Dockerfile
index 8ae4550..6e06e2d 100644
--- a/tools/dockerfile/test/python_alpine_x64/Dockerfile
+++ b/tools/dockerfile/test/python_alpine_x64/Dockerfile
@@ -37,7 +37,7 @@
   zip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.1
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
 RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0
 
diff --git a/tools/dockerfile/test/python_jessie_x64/Dockerfile b/tools/dockerfile/test/python_jessie_x64/Dockerfile
index 914e343..bd9d55e 100644
--- a/tools/dockerfile/test/python_jessie_x64/Dockerfile
+++ b/tools/dockerfile/test/python_jessie_x64/Dockerfile
@@ -64,9 +64,13 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.1
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
+
+# Install pip and virtualenv for Python 3.4
+RUN curl https://bootstrap.pypa.io/get-pip.py | python3.4
+RUN python3.4 -m pip install virtualenv
 
 # Prepare ccache
 RUN ln -s /usr/bin/ccache /usr/local/bin/gcc
diff --git a/tools/dockerfile/test/python_pyenv_x64/Dockerfile b/tools/dockerfile/test/python_pyenv_x64/Dockerfile
index 379f26a..6d72a1c 100644
--- a/tools/dockerfile/test/python_pyenv_x64/Dockerfile
+++ b/tools/dockerfile/test/python_pyenv_x64/Dockerfile
@@ -64,9 +64,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.1
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 # Install dependencies for pyenv
 RUN apt-get update && apt-get install -y \
@@ -91,6 +91,10 @@
 RUN pyenv install pypy-5.3.1
 RUN pyenv local 3.5-dev 3.6-dev pypy-5.3.1
 
+# Install pip and virtualenv for Python 3.4
+RUN curl https://bootstrap.pypa.io/get-pip.py | python3.4
+RUN python3.4 -m pip install virtualenv
+
 # Prepare ccache
 RUN ln -s /usr/bin/ccache /usr/local/bin/gcc
 RUN ln -s /usr/bin/ccache /usr/local/bin/g++
diff --git a/tools/dockerfile/test/ruby_jessie_x64/Dockerfile b/tools/dockerfile/test/ruby_jessie_x64/Dockerfile
index 63e42fd..37d909a 100644
--- a/tools/dockerfile/test/ruby_jessie_x64/Dockerfile
+++ b/tools/dockerfile/test/ruby_jessie_x64/Dockerfile
@@ -64,9 +64,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.1
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 #==================
 # Ruby dependencies
diff --git a/tools/dockerfile/test/sanity/Dockerfile b/tools/dockerfile/test/sanity/Dockerfile
index f65adf5..4885843 100644
--- a/tools/dockerfile/test/sanity/Dockerfile
+++ b/tools/dockerfile/test/sanity/Dockerfile
@@ -64,9 +64,9 @@
     python-pip
 
 # Install Python packages from PyPI
-RUN pip install --upgrade pip==9.0.1
+RUN pip install --upgrade pip==10.0.1
 RUN pip install virtualenv
-RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.0.post1 six==1.10.0 twisted==17.5.0
+RUN pip install futures==2.2.0 enum34==1.0.4 protobuf==3.5.2.post1 six==1.10.0 twisted==17.5.0
 
 #=================
 # C++ dependencies
diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++
index eb6700d..884eabb 100644
--- a/tools/doxygen/Doxyfile.c++
+++ b/tools/doxygen/Doxyfile.c++
@@ -40,7 +40,7 @@
 # could be handy for archiving the generated documentation or if some version
 # control system is used.
 
-PROJECT_NUMBER         = 1.11.0-dev
+PROJECT_NUMBER         = 1.13.0-dev
 
 # Using the PROJECT_BRIEF tag one can provide an optional one line description
 # for a project that appears at the top of each page and should give viewer a
@@ -954,6 +954,8 @@
 include/grpcpp/impl/codegen/grpc_library.h \
 include/grpcpp/impl/codegen/metadata_map.h \
 include/grpcpp/impl/codegen/method_handler_impl.h \
+include/grpcpp/impl/codegen/proto_buffer_reader.h \
+include/grpcpp/impl/codegen/proto_buffer_writer.h \
 include/grpcpp/impl/codegen/proto_utils.h \
 include/grpcpp/impl/codegen/rpc_method.h \
 include/grpcpp/impl/codegen/rpc_service_method.h \
@@ -992,6 +994,8 @@
 include/grpcpp/support/byte_buffer.h \
 include/grpcpp/support/channel_arguments.h \
 include/grpcpp/support/config.h \
+include/grpcpp/support/proto_buffer_reader.h \
+include/grpcpp/support/proto_buffer_writer.h \
 include/grpcpp/support/slice.h \
 include/grpcpp/support/status.h \
 include/grpcpp/support/status_code_enum.h \
diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal
index 52a16d6..66796ba 100644
--- a/tools/doxygen/Doxyfile.c++.internal
+++ b/tools/doxygen/Doxyfile.c++.internal
@@ -40,7 +40,7 @@
 # could be handy for archiving the generated documentation or if some version
 # control system is used.
 
-PROJECT_NUMBER         = 1.11.0-dev
+PROJECT_NUMBER         = 1.13.0-dev
 
 # Using the PROJECT_BRIEF tag one can provide an optional one line description
 # for a project that appears at the top of each page and should give viewer a
@@ -956,6 +956,8 @@
 include/grpcpp/impl/codegen/grpc_library.h \
 include/grpcpp/impl/codegen/metadata_map.h \
 include/grpcpp/impl/codegen/method_handler_impl.h \
+include/grpcpp/impl/codegen/proto_buffer_reader.h \
+include/grpcpp/impl/codegen/proto_buffer_writer.h \
 include/grpcpp/impl/codegen/proto_utils.h \
 include/grpcpp/impl/codegen/rpc_method.h \
 include/grpcpp/impl/codegen/rpc_service_method.h \
@@ -994,6 +996,8 @@
 include/grpcpp/support/byte_buffer.h \
 include/grpcpp/support/channel_arguments.h \
 include/grpcpp/support/config.h \
+include/grpcpp/support/proto_buffer_reader.h \
+include/grpcpp/support/proto_buffer_writer.h \
 include/grpcpp/support/slice.h \
 include/grpcpp/support/status.h \
 include/grpcpp/support/status_code_enum.h \
@@ -1209,7 +1213,6 @@
 src/cpp/thread_manager/thread_manager.cc \
 src/cpp/thread_manager/thread_manager.h \
 src/cpp/util/byte_buffer_cc.cc \
-src/cpp/util/slice_cc.cc \
 src/cpp/util/status.cc \
 src/cpp/util/string_ref.cc \
 src/cpp/util/time_cc.cc \
diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal
index 85675e9..0969b9c 100644
--- a/tools/doxygen/Doxyfile.core.internal
+++ b/tools/doxygen/Doxyfile.core.internal
@@ -885,6 +885,7 @@
 src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc \
 src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.h \
 src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc \
+src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h \
 src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h \
 src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.cc \
 src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc \
@@ -895,7 +896,6 @@
 src/core/ext/filters/client_channel/lb_policy/grpclb/proto/grpc/lb/v1/load_balancer.pb.h \
 src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc \
 src/core/ext/filters/client_channel/lb_policy/round_robin/round_robin.cc \
-src/core/ext/filters/client_channel/lb_policy/subchannel_list.cc \
 src/core/ext/filters/client_channel/lb_policy/subchannel_list.h \
 src/core/ext/filters/client_channel/lb_policy_factory.cc \
 src/core/ext/filters/client_channel/lb_policy_factory.h \
@@ -939,6 +939,8 @@
 src/core/ext/filters/deadline/deadline_filter.h \
 src/core/ext/filters/http/client/http_client_filter.cc \
 src/core/ext/filters/http/client/http_client_filter.h \
+src/core/ext/filters/http/client_authority_filter.cc \
+src/core/ext/filters/http/client_authority_filter.h \
 src/core/ext/filters/http/http_filters_plugin.cc \
 src/core/ext/filters/http/message_compress/message_compress_filter.cc \
 src/core/ext/filters/http/message_compress/message_compress_filter.h \
@@ -960,6 +962,8 @@
 src/core/ext/transport/chttp2/README.md \
 src/core/ext/transport/chttp2/alpn/alpn.cc \
 src/core/ext/transport/chttp2/alpn/alpn.h \
+src/core/ext/transport/chttp2/client/authority.cc \
+src/core/ext/transport/chttp2/client/authority.h \
 src/core/ext/transport/chttp2/client/chttp2_connector.cc \
 src/core/ext/transport/chttp2/client/chttp2_connector.h \
 src/core/ext/transport/chttp2/client/insecure/README.md \
@@ -1492,8 +1496,6 @@
 src/core/tsi/ssl_types.h \
 src/core/tsi/transport_security.cc \
 src/core/tsi/transport_security.h \
-src/core/tsi/transport_security_adapter.cc \
-src/core/tsi/transport_security_adapter.h \
 src/core/tsi/transport_security_grpc.cc \
 src/core/tsi/transport_security_grpc.h \
 src/core/tsi/transport_security_interface.h \
diff --git a/tools/fuzzer/runners/alts_credentials_fuzzer.sh b/tools/fuzzer/runners/alts_credentials_fuzzer.sh
new file mode 100644
index 0000000..3aaff6b
--- /dev/null
+++ b/tools/fuzzer/runners/alts_credentials_fuzzer.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+# 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.
+#
+
+flags="-max_total_time=$runtime -artifact_prefix=fuzzer_output/ -max_len=2048 -timeout=120"
+
+
+if [ "$jobs" != "1" ]
+then
+  flags="-jobs=$jobs -workers=$jobs $flags"
+fi
+
+if [ "$config" == "asan-trace-cmp" ]
+then
+  flags="-use_traces=1 $flags"
+fi
+
+bins/$config/alts_credentials_fuzzer $flags fuzzer_output test/core/security/corpus/alts_credentials_corpus
diff --git a/tools/gce/create_windows_debug_worker.sh b/tools/gce/create_windows_debug_worker.sh
index 6f903b5..3625df8 100755
--- a/tools/gce/create_windows_debug_worker.sh
+++ b/tools/gce/create_windows_debug_worker.sh
@@ -44,12 +44,13 @@
 echo 'Created scratch disk, waiting for it to become available.'
 sleep 15
 
+# The image version might need updating.
 gcloud compute instances create "$INSTANCE_NAME" \
     --project="$CLOUD_PROJECT" \
     --zone "$ZONE" \
     --machine-type "$MACHINE_TYPE" \
     --image-project google.com:kokoro \
-    --image kokoro-win7build-v9-prod-debug \
+    --image kokoro-win7build-v11-prod-debug \
     --boot-disk-size 500 \
     --boot-disk-type pd-ssd \
     --tags=allow-ssh \
diff --git a/tools/gce/linux_kokoro_performance_worker_init.sh b/tools/gce/linux_kokoro_performance_worker_init.sh
index 1f98d24..4a1e3e6 100755
--- a/tools/gce/linux_kokoro_performance_worker_init.sh
+++ b/tools/gce/linux_kokoro_performance_worker_init.sh
@@ -72,7 +72,7 @@
 sudo apt-get install -y libgflags-dev libgtest-dev libc++-dev clang
 
 # Python dependencies
-sudo pip install --upgrade pip==9.0.1
+sudo pip install --upgrade pip==10.0.1
 sudo pip install tabulate
 sudo pip install google-api-python-client
 sudo pip install virtualenv
diff --git a/tools/gce/linux_performance_worker_init.sh b/tools/gce/linux_performance_worker_init.sh
index 6f68660..7222cef 100755
--- a/tools/gce/linux_performance_worker_init.sh
+++ b/tools/gce/linux_performance_worker_init.sh
@@ -72,7 +72,7 @@
 sudo apt-get install -y libgflags-dev libgtest-dev libc++-dev clang
 
 # Python dependencies
-sudo pip install --upgrade pip==9.0.1
+sudo pip install --upgrade pip==10.0.1
 sudo pip install tabulate
 sudo pip install google-api-python-client
 sudo pip install virtualenv
diff --git a/tools/internal_ci/helper_scripts/gen_report_index.sh b/tools/internal_ci/helper_scripts/gen_report_index.sh
deleted file mode 100755
index 576ff67..0000000
--- a/tools/internal_ci/helper_scripts/gen_report_index.sh
+++ /dev/null
@@ -1,35 +0,0 @@
-#!/usr/bin/env bash
-# Copyright 2017 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.
-#
-# Generates index.html that will contain links to various test results on kokoro.
-set -e
-
-# change to grpc repo root
-cd $(dirname $0)/../../..
-
-# Kororo URLs are in the form "grpc/job/macos/job/master/job/grpc_build_artifacts"
-KOKORO_JOB_PATH=$(echo "${KOKORO_JOB_NAME}" | sed "s|/|/job/|g")
-
-mkdir -p reports
-
-echo '<html><head></head><body>' > reports/kokoro_index.html
-echo '<h1>'${KOKORO_JOB_NAME}', build '#${KOKORO_BUILD_NUMBER}'</h1>' >> reports/kokoro_index.html
-echo '<h2><a href="https://kokoro2.corp.google.com/job/'${KOKORO_JOB_PATH}'/'${KOKORO_BUILD_NUMBER}'/">Kokoro build dashboard (internal only)</a></h2>' >> reports/kokoro_index.html
-echo '<h2><a href="https://sponge.corp.google.com/invocation?id='${KOKORO_BUILD_ID}'&searchFor=">Test result dashboard (internal only)</a></h2>' >> reports/kokoro_index.html
-echo '<h2><a href="test_report.html">HTML test report (Not available yet)</a></h2>' >> reports/kokoro_index.html
-echo '<h2><a href="test_log.txt">Test log (Not available yet)</a></h2>' >> reports/kokoro_index.html
-echo '</body></html>' >> reports/kokoro_index.html
-
-echo 'Created reports/kokoro_index.html report index'
diff --git a/tools/internal_ci/helper_scripts/prepare_build_linux_rc b/tools/internal_ci/helper_scripts/prepare_build_linux_rc
index 74bbc85..992c540 100644
--- a/tools/internal_ci/helper_scripts/prepare_build_linux_rc
+++ b/tools/internal_ci/helper_scripts/prepare_build_linux_rc
@@ -15,8 +15,6 @@
 
 # Source this rc script to prepare the environment for linux builds
 
-tools/internal_ci/helper_scripts/gen_report_index.sh
-
 # Need to increase open files limit for c tests
 ulimit -n 32768
 
diff --git a/tools/internal_ci/helper_scripts/prepare_build_macos_interop_rc b/tools/internal_ci/helper_scripts/prepare_build_macos_interop_rc
index 786cd45..b0feeef 100644
--- a/tools/internal_ci/helper_scripts/prepare_build_macos_interop_rc
+++ b/tools/internal_ci/helper_scripts/prepare_build_macos_interop_rc
@@ -33,9 +33,3 @@
 git clone --recursive https://github.com/grpc/grpc-java ./../grpc-java
 git clone --recursive https://github.com/grpc/grpc-node ./../grpc-node
 git clone --recursive https://github.com/grpc/grpc-dart ./../grpc-dart
-
-# Set up Docker for Mac
-docker-machine create -d virtualbox --virtualbox-share-folder "/Users/kbuilder/workspace:" default
-docker-machine env default
-eval $(docker-machine env default)
-
diff --git a/tools/internal_ci/helper_scripts/prepare_build_macos_rc b/tools/internal_ci/helper_scripts/prepare_build_macos_rc
index 3a09701..d2b7769 100644
--- a/tools/internal_ci/helper_scripts/prepare_build_macos_rc
+++ b/tools/internal_ci/helper_scripts/prepare_build_macos_rc
@@ -15,8 +15,6 @@
 
 # Source this rc script to prepare the environment for macos builds
 
-tools/internal_ci/helper_scripts/gen_report_index.sh
-
 sudo launchctl limit maxfiles unlimited unlimited
 
 # show current maxfiles
@@ -69,7 +67,12 @@
 export PYTHONPATH=/Library/Python/3.4/site-packages
 
 # set xcode version for Obj-C tests
-sudo xcode-select -switch /Applications/Xcode_8.2.1.app/Contents/Developer
+sudo xcode-select -switch /Applications/Xcode_9.2.app/Contents/Developer/
+
+# Disable some unwanted dotnet options
+export NUGET_XMLDOC_MODE=skip
+export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=true
+export DOTNET_CLI_TELEMETRY_OPTOUT=true
 
 # TODO(jtattermusch): better debugging of clock skew, remove once not needed
 date
diff --git a/tools/internal_ci/helper_scripts/prepare_build_windows.bat b/tools/internal_ci/helper_scripts/prepare_build_windows.bat
index f625755..f987f8a 100644
--- a/tools/internal_ci/helper_scripts/prepare_build_windows.bat
+++ b/tools/internal_ci/helper_scripts/prepare_build_windows.bat
@@ -16,8 +16,6 @@
 @rem set path to python 2.7
 set PATH=C:\tools\msys64\usr\bin;C:\Python27;%PATH%
 
-bash tools/internal_ci/helper_scripts/gen_report_index.sh
-
 @rem If this is a PR using RUN_TESTS_FLAGS var, then add flags to filter tests
 if defined KOKORO_GITHUB_PULL_REQUEST_NUMBER if defined RUN_TESTS_FLAGS (
   chocolatey install -y jq
@@ -36,4 +34,9 @@
 @rem Needed for big_query_utils
 python -m pip install google-api-python-client
 
+@rem Disable some unwanted dotnet options
+set NUGET_XMLDOC_MODE=skip
+set DOTNET_SKIP_FIRST_TIME_EXPERIENCE=true
+set DOTNET_CLI_TELEMETRY_OPTOUT=true
+
 git submodule update --init
diff --git a/tools/internal_ci/linux/grpc_android.sh b/tools/internal_ci/linux/grpc_android.sh
index c693b77..2220145 100755
--- a/tools/internal_ci/linux/grpc_android.sh
+++ b/tools/internal_ci/linux/grpc_android.sh
@@ -31,7 +31,32 @@
 git fetch
 git cherry-pick 7daa320065f3bea2b54bf983337d1724f153422d -m 1
 
-cd ../../examples/android/helloworld
+
+# Build and run interop instrumentation tests on Firebase Test Lab
+
+cd "${REPO_ROOT}/src/android/test/interop/"
+./gradlew assembleDebug \
+    "-Pprotoc=${REPO_ROOT}/third_party/protobuf/src/protoc" \
+    "-Pgrpc_cpp_plugin=${REPO_ROOT}/bins/opt/grpc_cpp_plugin"
+./gradlew assembleDebugAndroidTest \
+    "-Pprotoc=${REPO_ROOT}/third_party/protobuf/src/protoc" \
+    "-Pgrpc_cpp_plugin=${REPO_ROOT}/bins/opt/grpc_cpp_plugin"
+gcloud firebase test android run \
+    --type instrumentation \
+    --app app/build/outputs/apk/debug/app-debug.apk \
+    --test app/build/outputs/apk/androidTest/debug/app-debug-androidTest.apk \
+    --device model=Nexus6P,version=27,locale=en,orientation=portrait \
+    --device model=Nexus6P,version=26,locale=en,orientation=portrait \
+    --device model=Nexus6P,version=25,locale=en,orientation=portrait \
+    --device model=Nexus6P,version=24,locale=en,orientation=portrait \
+    --device model=Nexus6P,version=23,locale=en,orientation=portrait \
+    --device model=Nexus6,version=22,locale=en,orientation=portrait \
+    --device model=Nexus6,version=21,locale=en,orientation=portrait
+
+
+# Build hello world example
+
+cd "${REPO_ROOT}/examples/android/helloworld"
 ./gradlew build \
     "-Pprotoc=${REPO_ROOT}/third_party/protobuf/src/protoc" \
     "-Pgrpc_cpp_plugin=${REPO_ROOT}/bins/opt/grpc_cpp_plugin"
diff --git a/tools/internal_ci/linux/grpc_asan_on_foundry.sh b/tools/internal_ci/linux/grpc_asan_on_foundry.sh
index 2aebb65..791c56c 100644
--- a/tools/internal_ci/linux/grpc_asan_on_foundry.sh
+++ b/tools/internal_ci/linux/grpc_asan_on_foundry.sh
@@ -13,6 +13,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+export UPLOAD_TEST_RESULTS=true
 EXTRA_FLAGS="--copt=-gmlt --strip=never --copt=-fsanitize=address --linkopt=-fsanitize=address --test_timeout=3600"
 github/grpc/tools/internal_ci/linux/grpc_bazel_on_foundry_base.sh "${EXTRA_FLAGS}"
 
diff --git a/tools/internal_ci/linux/grpc_bazel_on_foundry_base.sh b/tools/internal_ci/linux/grpc_bazel_on_foundry_base.sh
index 7ec15bf..7881e3a 100755
--- a/tools/internal_ci/linux/grpc_bazel_on_foundry_base.sh
+++ b/tools/internal_ci/linux/grpc_bazel_on_foundry_base.sh
@@ -22,8 +22,8 @@
 cp ${KOKORO_GFILE_DIR}/GrpcTesting-d0eeee2db331.json ${KOKORO_KEYSTORE_DIR}/4321_grpc-testing-service
 
 temp_dir=$(mktemp -d)
-ln -f "${KOKORO_GFILE_DIR}/bazel-canary" ${temp_dir}/bazel
-chmod 755 "${KOKORO_GFILE_DIR}/bazel-canary"
+ln -f "${KOKORO_GFILE_DIR}/bazel-release-0.12.0" ${temp_dir}/bazel
+chmod 755 "${KOKORO_GFILE_DIR}/bazel-release-0.12.0"
 export PATH="${temp_dir}:${PATH}"
 # This should show ${temp_dir}/bazel
 which bazel
@@ -37,7 +37,7 @@
 # TODO(adelez): implement size for test targets and change test_timeout back
 "${KOKORO_GFILE_DIR}/bazel_wrapper.py" \
   --host_jvm_args=-Dbazel.DigestFunction=SHA256 \
-  test --jobs="100" \
+  test --jobs="200" \
   --test_output=errors  \
   --verbose_failures=true  \
   --keep_going  \
@@ -49,8 +49,20 @@
   --strategy=Closure=remote  \
   --genrule_strategy=remote  \
   --experimental_strict_action_env=true \
-  --experimental_remote_platform_override='properties:{name:"container-image" value:"docker://gcr.io/cloud-marketplace/google/rbe-debian8@sha256:b2d946c1ddc20af250fe85cf98bd648ac5519131659f7c36e64184b433175a33" }' \
+  --experimental_remote_platform_override='properties:{name:"container-image" value:"docker://gcr.io/cloud-marketplace/google/rbe-debian8@sha256:1ede2a929b44d629ec5abe86eee6d7ffea1d5a4d247489a8867d46cfde3e38bd" }' \
   --crosstool_top=@com_github_bazelbuild_bazeltoolchains//configs/debian8_clang/0.3.0/bazel_0.10.0:toolchain \
   --define GRPC_PORT_ISOLATED_RUNTIME=1 \
   $1 \
-  -- //test/...
+  -- //test/... || FAILED="true"
+
+if [ "$UPLOAD_TEST_RESULTS" != "" ]
+then
+  # Sleep to let ResultStore finish writing results before querying
+  sleep 60
+  python ./tools/run_tests/python_utils/upload_rbe_results.py
+fi
+
+if [ "$FAILED" != "" ]
+then
+  exit 1
+fi
diff --git a/tools/internal_ci/linux/grpc_bazel_on_foundry_dbg.sh b/tools/internal_ci/linux/grpc_bazel_on_foundry_dbg.sh
index f5111e2..192d9d1 100644
--- a/tools/internal_ci/linux/grpc_bazel_on_foundry_dbg.sh
+++ b/tools/internal_ci/linux/grpc_bazel_on_foundry_dbg.sh
@@ -13,6 +13,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-EXTRA_FLAGS="-c dbg --test_timeout=300,450,1200,7200"
+export UPLOAD_TEST_RESULTS=true
+EXTRA_FLAGS="-c dbg --test_timeout=300,450,1200,3600 --runs_per_test_detects_flakes --runs_per_test=2"
 github/grpc/tools/internal_ci/linux/grpc_bazel_on_foundry_base.sh "${EXTRA_FLAGS}"
-
diff --git a/tools/internal_ci/linux/grpc_bazel_on_foundry_opt.sh b/tools/internal_ci/linux/grpc_bazel_on_foundry_opt.sh
index 7f3e4cf..6fb3c77 100644
--- a/tools/internal_ci/linux/grpc_bazel_on_foundry_opt.sh
+++ b/tools/internal_ci/linux/grpc_bazel_on_foundry_opt.sh
@@ -13,5 +13,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-EXTRA_FLAGS="-c opt --test_timeout=300,450,1200,7200"
+export UPLOAD_TEST_RESULTS=true
+EXTRA_FLAGS="-c opt --test_timeout=300,450,1200,3600 --runs_per_test_detects_flakes --runs_per_test=2"
 github/grpc/tools/internal_ci/linux/grpc_bazel_on_foundry_base.sh "${EXTRA_FLAGS}"
diff --git a/tools/internal_ci/linux/grpc_build_packages.sh b/tools/internal_ci/linux/grpc_build_packages.sh
index 9f65d8e..ff71298 100644
--- a/tools/internal_ci/linux/grpc_build_packages.sh
+++ b/tools/internal_ci/linux/grpc_build_packages.sh
@@ -30,6 +30,7 @@
 # where they can be accessed from within a docker container that builds
 # the packages
 mv ${KOKORO_GFILE_DIR}/github/grpc/artifacts input_artifacts || true
+chmod +x input_artifacts/protoc*/* || true
 ls -R input_artifacts || true
 
 tools/run_tests/task_runner.py -f package linux -j 6
diff --git a/tools/internal_ci/linux/grpc_coverage.cfg b/tools/internal_ci/linux/grpc_coverage.cfg
index 56b7745..794a51d 100644
--- a/tools/internal_ci/linux/grpc_coverage.cfg
+++ b/tools/internal_ci/linux/grpc_coverage.cfg
@@ -19,6 +19,7 @@
 timeout_mins: 420
 action {
   define_artifacts {
+    regex: "**/*sponge_log.xml"
     regex: "github/grpc/reports/**"
   }
 }
diff --git a/tools/internal_ci/linux/grpc_coverage.sh b/tools/internal_ci/linux/grpc_coverage.sh
index 12181f0..fd927a8 100755
--- a/tools/internal_ci/linux/grpc_coverage.sh
+++ b/tools/internal_ci/linux/grpc_coverage.sh
@@ -21,10 +21,9 @@
 source tools/internal_ci/helper_scripts/prepare_build_linux_rc
 
 python tools/run_tests/run_tests.py \
-  --use_docker				        \
+  --use_docker                      \
   -t                                \
   -l all                            \
   -c gcov                           \
-  -x report.xml                     \
+  -x sponge_log.xml                 \
   -j 16
-  
diff --git a/tools/internal_ci/linux/grpc_sanity_webhook_test.cfg b/tools/internal_ci/linux/grpc_interop_alts.cfg
similarity index 74%
copy from tools/internal_ci/linux/grpc_sanity_webhook_test.cfg
copy to tools/internal_ci/linux/grpc_interop_alts.cfg
index 24e7984..bda76fa 100644
--- a/tools/internal_ci/linux/grpc_sanity_webhook_test.cfg
+++ b/tools/internal_ci/linux/grpc_interop_alts.cfg
@@ -1,4 +1,4 @@
-# Copyright 2017 gRPC authors.
+# Copyright 2018 gRPC authors.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -15,16 +15,16 @@
 # Config file for the internal CI (in protobuf text format)
 
 # Location of the continuous shell script in repository.
-build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
-timeout_mins: 20
+build_file: "grpc/tools/internal_ci/linux/grpc_run_interop_tests.sh"
+timeout_mins: 60
 action {
   define_artifacts {
-    regex: "**/*sponge_log.xml"
+    regex: "**/sponge_log.xml"
     regex: "github/grpc/reports/**"
   }
 }
 
 env_vars {
   key: "RUN_TESTS_FLAGS"
-  value: "-f basictests linux sanity opt --inner_jobs 16 -j 1 --internal_ci"
+  value: "-l all -s all --use_docker --transport_security alts --internal_ci -t -j 12 --bq_result_table interop_results"
 }
diff --git a/tools/internal_ci/linux/grpc_interop_toprod.cfg b/tools/internal_ci/linux/grpc_interop_toprod.cfg
index ff7a98f..8d025c4 100644
--- a/tools/internal_ci/linux/grpc_interop_toprod.cfg
+++ b/tools/internal_ci/linux/grpc_interop_toprod.cfg
@@ -26,5 +26,5 @@
 
 env_vars {
   key: "RUN_TESTS_FLAGS"
-  value: "-l all --cloud_to_prod --cloud_to_prod_auth --prod_servers default gateway_v4 cloud_gateway cloud_gateway_v4 --use_docker --internal_ci -t -j 12 --bq_result_table interop_results"
+  value: "-l all --cloud_to_prod --cloud_to_prod_auth --prod_servers default gateway_v4 --use_docker --internal_ci -t -j 12 --bq_result_table interop_results"
 }
diff --git a/tools/internal_ci/linux/grpc_msan_on_foundry.sh b/tools/internal_ci/linux/grpc_msan_on_foundry.sh
index 60b30ff..5e64479 100644
--- a/tools/internal_ci/linux/grpc_msan_on_foundry.sh
+++ b/tools/internal_ci/linux/grpc_msan_on_foundry.sh
@@ -23,8 +23,8 @@
 cp ${KOKORO_GFILE_DIR}/GrpcTesting-d0eeee2db331.json ${KOKORO_KEYSTORE_DIR}/4321_grpc-testing-service
 
 temp_dir=$(mktemp -d)
-ln -f "${KOKORO_GFILE_DIR}/bazel-canary" ${temp_dir}/bazel
-chmod 755 "${KOKORO_GFILE_DIR}/bazel-canary"
+ln -f "${KOKORO_GFILE_DIR}/bazel-release-0.12.0" ${temp_dir}/bazel
+chmod 755 "${KOKORO_GFILE_DIR}/bazel-release-0.12.0"
 export PATH="${temp_dir}:${PATH}"
 # This should show ${temp_dir}/bazel
 which bazel
@@ -37,7 +37,7 @@
 
 "${KOKORO_GFILE_DIR}/bazel_wrapper.py" \
   --host_jvm_args=-Dbazel.DigestFunction=SHA256 \
-  test --jobs="100" \
+  test --jobs="200" \
   --test_timeout="3600,3600,3600,3600" \
   --test_output=errors  \
   --verbose_failures=true  \
@@ -61,4 +61,13 @@
   --action_env=LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH \
   --host_crosstool_top=@com_github_bazelbuild_bazeltoolchains//configs/debian8_clang/0.3.0/bazel_0.10.0:toolchain \
   --crosstool_top=@com_github_bazelbuild_bazeltoolchains//configs/experimental/debian8_clang/0.3.0/bazel_0.10.0/msan:msan_experimental_toolchain \
-  -- //test/...
+  -- //test/... || FAILED="true"
+
+# Sleep to let ResultStore finish writing results before querying
+sleep 60
+python ./tools/run_tests/python_utils/upload_rbe_results.py
+
+if [ "$FAILED" != "" ]
+then
+  exit 1
+fi
diff --git a/tools/internal_ci/linux/grpc_sanity.cfg b/tools/internal_ci/linux/grpc_sanity.cfg
index e06a2f4..9f65918 100644
--- a/tools/internal_ci/linux/grpc_sanity.cfg
+++ b/tools/internal_ci/linux/grpc_sanity.cfg
@@ -26,5 +26,5 @@
 
 env_vars {
   key: "RUN_TESTS_FLAGS"
-  value: "-f basictests linux sanity opt --inner_jobs 16 -j 1 --internal_ci"
+  value: "-f basictests linux sanity --inner_jobs 16 -j 1 --internal_ci --bq_result_table aggregate_results"
 }
diff --git a/tools/internal_ci/linux/grpc_tsan_on_foundry.sh b/tools/internal_ci/linux/grpc_tsan_on_foundry.sh
index aacb1ad..fafa1ce 100644
--- a/tools/internal_ci/linux/grpc_tsan_on_foundry.sh
+++ b/tools/internal_ci/linux/grpc_tsan_on_foundry.sh
@@ -13,6 +13,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+export UPLOAD_TEST_RESULTS=true
 EXTRA_FLAGS="--copt=-gmlt --strip=never --copt=-fsanitize=thread --linkopt=-fsanitize=thread --test_timeout=3600"
 github/grpc/tools/internal_ci/linux/grpc_bazel_on_foundry_base.sh "${EXTRA_FLAGS}"
-
diff --git a/tools/internal_ci/linux/grpc_ubsan_on_foundry.sh b/tools/internal_ci/linux/grpc_ubsan_on_foundry.sh
index a87547d..0f71ff2 100644
--- a/tools/internal_ci/linux/grpc_ubsan_on_foundry.sh
+++ b/tools/internal_ci/linux/grpc_ubsan_on_foundry.sh
@@ -23,8 +23,8 @@
 cp ${KOKORO_GFILE_DIR}/GrpcTesting-d0eeee2db331.json ${KOKORO_KEYSTORE_DIR}/4321_grpc-testing-service
 
 temp_dir=$(mktemp -d)
-ln -f "${KOKORO_GFILE_DIR}/bazel-canary" ${temp_dir}/bazel
-chmod 755 "${KOKORO_GFILE_DIR}/bazel-canary"
+ln -f "${KOKORO_GFILE_DIR}/bazel-release-0.12.0" ${temp_dir}/bazel
+chmod 755 "${KOKORO_GFILE_DIR}/bazel-release-0.12.0"
 export PATH="${temp_dir}:${PATH}"
 # This should show ${temp_dir}/bazel
 which bazel
@@ -37,7 +37,7 @@
 
 "${KOKORO_GFILE_DIR}/bazel_wrapper.py" \
   --host_jvm_args=-Dbazel.DigestFunction=SHA256 \
-  test --jobs="100" \
+  test --jobs="200" \
   --test_timeout="3600,3600,3600,3600" \
   --test_output=errors  \
   --verbose_failures=true  \
@@ -57,4 +57,13 @@
   --copt=-fsanitize=undefined \
   --linkopt=-fsanitize=undefined \
   --crosstool_top=@com_github_bazelbuild_bazeltoolchains//configs/experimental/debian8_clang/0.3.0/bazel_0.10.0/ubsan:ubsan_experimental_toolchain \
-  -- //test/...
+  -- //test/... || FAILED="true"
+
+# Sleep to let ResultStore finish writing results before querying
+sleep 60
+python ./tools/run_tests/python_utils/upload_rbe_results.py
+
+if [ "$FAILED" != "" ]
+then
+  exit 1
+fi
diff --git a/tools/internal_ci/linux/pull_request/grpc_bazel_on_foundry_dbg.sh b/tools/internal_ci/linux/pull_request/grpc_bazel_on_foundry_dbg.sh
new file mode 100644
index 0000000..8e2aaeb
--- /dev/null
+++ b/tools/internal_ci/linux/pull_request/grpc_bazel_on_foundry_dbg.sh
@@ -0,0 +1,17 @@
+#!/usr/bin/env bash
+# Copyright 2017 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.
+
+EXTRA_FLAGS="-c dbg --test_timeout=300,450,1200,3600"
+github/grpc/tools/internal_ci/linux/grpc_bazel_on_foundry_base.sh "${EXTRA_FLAGS}"
diff --git a/tools/internal_ci/linux/pull_request/grpc_bazel_on_foundry_opt.sh b/tools/internal_ci/linux/pull_request/grpc_bazel_on_foundry_opt.sh
new file mode 100644
index 0000000..ded0d36
--- /dev/null
+++ b/tools/internal_ci/linux/pull_request/grpc_bazel_on_foundry_opt.sh
@@ -0,0 +1,17 @@
+#!/usr/bin/env bash
+# Copyright 2017 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.
+
+EXTRA_FLAGS="-c opt --test_timeout=300,450,1200,3600"
+github/grpc/tools/internal_ci/linux/grpc_bazel_on_foundry_base.sh "${EXTRA_FLAGS}"
diff --git a/tools/internal_ci/linux/grpc_sanity_webhook_test.cfg b/tools/internal_ci/linux/pull_request/grpc_interop_alts.cfg
similarity index 76%
copy from tools/internal_ci/linux/grpc_sanity_webhook_test.cfg
copy to tools/internal_ci/linux/pull_request/grpc_interop_alts.cfg
index 24e7984..c1253b3 100644
--- a/tools/internal_ci/linux/grpc_sanity_webhook_test.cfg
+++ b/tools/internal_ci/linux/pull_request/grpc_interop_alts.cfg
@@ -1,4 +1,4 @@
-# Copyright 2017 gRPC authors.
+# Copyright 2018 gRPC authors.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -15,16 +15,16 @@
 # Config file for the internal CI (in protobuf text format)
 
 # Location of the continuous shell script in repository.
-build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
-timeout_mins: 20
+build_file: "grpc/tools/internal_ci/linux/grpc_run_interop_tests.sh"
+timeout_mins: 60
 action {
   define_artifacts {
-    regex: "**/*sponge_log.xml"
+    regex: "**/sponge_log.xml"
     regex: "github/grpc/reports/**"
   }
 }
 
 env_vars {
   key: "RUN_TESTS_FLAGS"
-  value: "-f basictests linux sanity opt --inner_jobs 16 -j 1 --internal_ci"
+  value: "-l all -s all --use_docker --transport_security alts --internal_ci -t -j 12"
 }
diff --git a/tools/internal_ci/linux/pull_request/grpc_interop_toprod.cfg b/tools/internal_ci/linux/pull_request/grpc_interop_toprod.cfg
index e141d9f..d14c79a 100644
--- a/tools/internal_ci/linux/pull_request/grpc_interop_toprod.cfg
+++ b/tools/internal_ci/linux/pull_request/grpc_interop_toprod.cfg
@@ -26,5 +26,5 @@
 
 env_vars {
   key: "RUN_TESTS_FLAGS"
-  value: "-l all --allow_flakes --cloud_to_prod --cloud_to_prod_auth --prod_servers default gateway_v4 --use_docker --internal_ci -t -j 12"
+  value: "-l all --cloud_to_prod --cloud_to_prod_auth --prod_servers default gateway_v4 --use_docker --internal_ci -t -j 12"
 }
diff --git a/tools/internal_ci/linux/grpc_sanity_webhook_test.cfg b/tools/internal_ci/linux/pull_request/grpc_sanity.cfg
similarity index 89%
rename from tools/internal_ci/linux/grpc_sanity_webhook_test.cfg
rename to tools/internal_ci/linux/pull_request/grpc_sanity.cfg
index 24e7984..0f83299 100644
--- a/tools/internal_ci/linux/grpc_sanity_webhook_test.cfg
+++ b/tools/internal_ci/linux/pull_request/grpc_sanity.cfg
@@ -16,7 +16,7 @@
 
 # Location of the continuous shell script in repository.
 build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
-timeout_mins: 20
+timeout_mins: 40
 action {
   define_artifacts {
     regex: "**/*sponge_log.xml"
@@ -26,5 +26,5 @@
 
 env_vars {
   key: "RUN_TESTS_FLAGS"
-  value: "-f basictests linux sanity opt --inner_jobs 16 -j 1 --internal_ci"
+  value: "-f basictests linux sanity --inner_jobs 16 -j 1 --internal_ci"
 }
diff --git a/tools/internal_ci/linux/grpc_sanity_webhook_test.cfg b/tools/internal_ci/macos/grpc_interop_toprod.cfg
similarity index 73%
copy from tools/internal_ci/linux/grpc_sanity_webhook_test.cfg
copy to tools/internal_ci/macos/grpc_interop_toprod.cfg
index 24e7984..c92c397 100644
--- a/tools/internal_ci/linux/grpc_sanity_webhook_test.cfg
+++ b/tools/internal_ci/macos/grpc_interop_toprod.cfg
@@ -15,16 +15,13 @@
 # Config file for the internal CI (in protobuf text format)
 
 # Location of the continuous shell script in repository.
-build_file: "grpc/tools/internal_ci/linux/grpc_run_tests_matrix.sh"
-timeout_mins: 20
+build_file: "grpc/tools/internal_ci/macos/grpc_interop_toprod.sh"
+gfile_resources: "/bigstore/grpc-testing-secrets/gcp_credentials/GrpcTesting-d0eeee2db331.json"
+gfile_resources: "/bigstore/grpc-testing-secrets/interop/service_account/GrpcTesting-726eb1347f15.json"
+timeout_mins: 240
 action {
   define_artifacts {
     regex: "**/*sponge_log.xml"
     regex: "github/grpc/reports/**"
   }
 }
-
-env_vars {
-  key: "RUN_TESTS_FLAGS"
-  value: "-f basictests linux sanity opt --inner_jobs 16 -j 1 --internal_ci"
-}
diff --git a/tools/internal_ci/macos/grpc_interop_toprod.sh b/tools/internal_ci/macos/grpc_interop_toprod.sh
new file mode 100755
index 0000000..819a472
--- /dev/null
+++ b/tools/internal_ci/macos/grpc_interop_toprod.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+# Copyright 2017 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.
+
+set -ex
+
+# change to grpc repo root
+cd $(dirname $0)/../../..
+
+source tools/internal_ci/helper_scripts/prepare_build_macos_interop_rc
+source tools/internal_ci/helper_scripts/prepare_build_macos_rc
+
+# using run_interop_tests.py without --use_docker, so we need to build first
+tools/run_tests/run_tests.py -l c++ -c opt --build_only
+
+export GRPC_DEFAULT_SSL_ROOTS_FILE_PATH="$(pwd)/etc/roots.pem"
+
+# NOTE: only tests a subset of languages for time & dependency constraints
+# building all languages in the same working copy can also lead to conflicts
+# due to different compilation flags
+tools/run_tests/run_interop_tests.py -l c++ \
+    --cloud_to_prod --cloud_to_prod_auth --prod_servers default gateway_v4 \
+    --service_account_key_file="${KOKORO_GFILE_DIR}/GrpcTesting-726eb1347f15.json" \
+    --skip_compute_engine_creds --internal_ci -t -j 4
diff --git a/tools/interop_matrix/client_matrix.py b/tools/interop_matrix/client_matrix.py
index aa45f7f..e39fabe 100644
--- a/tools/interop_matrix/client_matrix.py
+++ b/tools/interop_matrix/client_matrix.py
@@ -87,6 +87,9 @@
         {
             'v1.10.0': None
         },
+        {
+            'v1.11.0': None
+        },
     ],
     'go': [
         {
@@ -117,7 +120,10 @@
             'v1.9.2': None
         },
         {
-            'v1.10.0': None
+            'v1.10.1': None
+        },
+        {
+            'v1.11.3': None
         },
     ],
     'java': [
@@ -154,6 +160,9 @@
         {
             'v1.10.1': None
         },
+        {
+            'v1.11.0': None
+        },
     ],
     'python': [
         {
@@ -186,6 +195,9 @@
         {
             'v1.10.0': None
         },
+        {
+            'v1.11.0': None
+        },
     ],
     'node': [
         {
@@ -256,6 +268,9 @@
         {
             'v1.10.0': None
         },
+        {
+            'v1.11.0': None
+        },
     ],
     'php': [
         {
@@ -288,6 +303,9 @@
         {
             'v1.10.0': None
         },
+        {
+            'v1.11.0': None
+        },
     ],
     'csharp': [
         #{'v1.0.1': None},
@@ -318,6 +336,9 @@
         {
             'v1.10.0': None
         },
+        {
+            'v1.11.0': None
+        },
     ],
 }
 
@@ -337,4 +358,14 @@
     'ruby_v1.0.1': 'ruby__v1.0.1',
     'csharp_v1.1.4': 'csharp__v1.1.4',
     'csharp_v1.2.5': 'csharp__v1.1.4',
+    'python_v1.0.x': 'python__v1.0.x',
+    'python_v1.1.4': 'python__v1.0.x',
+    'python_v1.2.5': 'python__v1.0.x',
+    'python_v1.3.9': 'python__v1.0.x',
+    'python_v1.4.2': 'python__v1.0.x',
+    'python_v1.6.6': 'python__v1.0.x',
+    'python_v1.7.2': 'python__v1.0.x',
+    'python_v1.8.1': 'python__v1.0.x',
+    'python_v1.9.1': 'python__v1.0.x',
+    'python_v1.10.0': 'python__v1.0.x',
 }
diff --git a/tools/interop_matrix/testcases/python__master b/tools/interop_matrix/testcases/python__master
index 71ba75e..467e41f 100755
--- a/tools/interop_matrix/testcases/python__master
+++ b/tools/interop_matrix/testcases/python__master
@@ -1,20 +1,20 @@
 #!/bin/bash
 echo "Testing ${docker_image:=grpc_interop_python:797ca293-94e8-48d4-92e9-a4d52fcfcca9}"
-docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=large_unary\""
-docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=empty_unary\""
-docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=ping_pong\""
-docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=empty_stream\""
-docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=client_streaming\""
-docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=server_streaming\""
-docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=cancel_after_begin\""
-docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=cancel_after_first_response\""
-docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=timeout_on_sleeping_server\""
-docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=large_unary\""
-docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=empty_unary\""
-docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=ping_pong\""
-docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=empty_stream\""
-docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=client_streaming\""
-docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=server_streaming\""
-docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=cancel_after_begin\""
-docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=cancel_after_first_response\""
-docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=timeout_on_sleeping_server\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27_native/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=large_unary\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27_native/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=empty_unary\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27_native/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=ping_pong\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27_native/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=empty_stream\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27_native/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=client_streaming\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27_native/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=server_streaming\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27_native/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=cancel_after_begin\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27_native/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=cancel_after_first_response\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27_native/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=timeout_on_sleeping_server\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27_native/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=large_unary\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27_native/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=empty_unary\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27_native/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=ping_pong\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27_native/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=empty_stream\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27_native/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=client_streaming\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27_native/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=server_streaming\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27_native/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=cancel_after_begin\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27_native/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=cancel_after_first_response\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27_native/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=timeout_on_sleeping_server\""
diff --git a/tools/interop_matrix/testcases/python__v1.0.x b/tools/interop_matrix/testcases/python__v1.0.x
new file mode 100755
index 0000000..71ba75e
--- /dev/null
+++ b/tools/interop_matrix/testcases/python__v1.0.x
@@ -0,0 +1,20 @@
+#!/bin/bash
+echo "Testing ${docker_image:=grpc_interop_python:797ca293-94e8-48d4-92e9-a4d52fcfcca9}"
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=large_unary\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=empty_unary\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=ping_pong\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=empty_stream\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=client_streaming\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=server_streaming\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=cancel_after_begin\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=cancel_after_first_response\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test.sandbox.googleapis.com --server_host_override=grpc-test.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=timeout_on_sleeping_server\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=large_unary\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=empty_unary\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=ping_pong\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=empty_stream\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=client_streaming\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=server_streaming\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=cancel_after_begin\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=cancel_after_first_response\""
+docker run -i --rm=true -e PYTHONPATH=/var/local/git/grpc/src/python/gens -e LD_LIBRARY_PATH=/var/local/git/grpc/libs/opt -w /var/local/git/grpc --net=host $docker_image bash -c "py27/bin/python src/python/grpcio_tests/setup.py run_interop --client --args=\"--server_host=grpc-test4.sandbox.googleapis.com --server_host_override=grpc-test4.sandbox.googleapis.com --server_port=443 --use_tls=true --test_case=timeout_on_sleeping_server\""
diff --git a/tools/profiling/microbenchmarks/bm2bq.py b/tools/profiling/microbenchmarks/bm2bq.py
index e084e28..c5307c5 100755
--- a/tools/profiling/microbenchmarks/bm2bq.py
+++ b/tools/profiling/microbenchmarks/bm2bq.py
@@ -1,9 +1,5 @@
 #!/usr/bin/env python2.7
 #
-# Convert google-benchmark json output to something that can be uploaded to
-# BigQuery
-#
-#
 # Copyright 2017 gRPC authors.
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,6 +14,9 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+# Convert google-benchmark json output to something that can be uploaded to
+# BigQuery
+
 import sys
 import json
 import csv
@@ -54,6 +53,7 @@
 else:
     js2 = None
 
+# TODO(jtattermusch): write directly to a file instead of stdout
 writer = csv.DictWriter(sys.stdout, [c for c, t in columns])
 
 for row in bm_json.expand_json(js, js2):
diff --git a/tools/profiling/microbenchmarks/bm_diff/bm_constants.py b/tools/profiling/microbenchmarks/bm_diff/bm_constants.py
index 5719e42..c8b6c1e 100644
--- a/tools/profiling/microbenchmarks/bm_diff/bm_constants.py
+++ b/tools/profiling/microbenchmarks/bm_diff/bm_constants.py
@@ -22,11 +22,10 @@
     'bm_metadata', 'bm_fullstack_trickle'
 ]
 
-_INTERESTING = ('cpu_time', 'real_time', 'call_initial_size-median',
-                'locks_per_iteration', 'allocs_per_iteration',
-                'writes_per_iteration', 'atm_cas_per_iteration',
-                'atm_add_per_iteration', 'nows_per_iteration',
-                'cli_transport_stalls_per_iteration',
+_INTERESTING = ('cpu_time', 'real_time', 'locks_per_iteration',
+                'allocs_per_iteration', 'writes_per_iteration',
+                'atm_cas_per_iteration', 'atm_add_per_iteration',
+                'nows_per_iteration', 'cli_transport_stalls_per_iteration',
                 'cli_stream_stalls_per_iteration',
                 'svr_transport_stalls_per_iteration',
                 'svr_stream_stalls_per_iteration',
diff --git a/tools/profiling/microbenchmarks/bm_json.py b/tools/profiling/microbenchmarks/bm_json.py
index 497d7ca..2f5eb70 100644
--- a/tools/profiling/microbenchmarks/bm_json.py
+++ b/tools/profiling/microbenchmarks/bm_json.py
@@ -12,8 +12,12 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+# Utilities for manipulating JSON data that represents microbenchmark results.
+
 import os
 
+# template arguments and dynamic arguments of individual benchmark types
+# Example benchmark name: "BM_UnaryPingPong<TCP, NoOpMutator, NoOpMutator>/0/0"
 _BM_SPECS = {
     'BM_UnaryPingPong': {
         'tpl': ['fixture', 'client_mutator', 'server_mutator'],
@@ -115,6 +119,7 @@
 
 
 def numericalize(s):
+    """Convert abbreviations like '100M' or '10k' to a number."""
     if not s: return ''
     if s[-1] == 'k':
         return float(s[:-1]) * 1024
@@ -159,9 +164,6 @@
         rest = s[0]
         dyn_args = s[1:]
     name = rest
-    print(name)
-    print(dyn_args, _BM_SPECS[name]['dyn'])
-    print(tpl_args, _BM_SPECS[name]['tpl'])
     assert name in _BM_SPECS, '_BM_SPECS needs to be expanded for %s' % name
     assert len(dyn_args) == len(_BM_SPECS[name]['dyn'])
     assert len(tpl_args) == len(_BM_SPECS[name]['tpl'])
diff --git a/tools/run_tests/README.md b/tools/run_tests/README.md
index 60f2074..64d67e4 100644
--- a/tools/run_tests/README.md
+++ b/tools/run_tests/README.md
@@ -14,6 +14,12 @@
 - `--use_docker` Builds a docker container containing all the prerequisites for given language and runs the tests under that container.
 - `--build_only` Only build, do not run the tests.
 
+Note: If you get an error such as `ImportError: No module named httplib2`, then you may be missing some Python modules. Install the module listed in the error and try again. 
+
+Note: some tests may be flaky. Check the "Issues" tab for known flakes and other issues.
+
+The full suite of unit tests will take many minutes to run.
+
 # Interop tests (run_interop_tests.py)
 
 Runs tests for cross-platform/cross-language interoperability. For more details, see [Interop tests descriptions](/doc/interop-test-descriptions.md)
diff --git a/tools/run_tests/artifacts/artifact_targets.py b/tools/run_tests/artifacts/artifact_targets.py
index daa163e..e4d9e6b 100644
--- a/tools/run_tests/artifacts/artifact_targets.py
+++ b/tools/run_tests/artifacts/artifact_targets.py
@@ -222,7 +222,13 @@
         return []
 
     def build_jobspec(self):
-        if self.platform == 'windows':
+        if self.arch == 'android':
+            return create_docker_jobspec(
+                self.name,
+                'tools/dockerfile/grpc_artifact_android_ndk',
+                'tools/run_tests/artifacts/build_artifact_csharp_android.sh',
+                environ={})
+        elif self.platform == 'windows':
             cmake_arch_option = 'Win32' if self.arch == 'x86' else self.arch
             return create_jobspec(
                 self.name, [
@@ -342,6 +348,7 @@
         for Cls in (CSharpExtArtifact, ProtocArtifact)
         for platform in ('linux', 'macos', 'windows') for arch in ('x86', 'x64')
     ] + [
+        CSharpExtArtifact('linux', 'android'),
         PythonArtifact('linux', 'x86', 'cp27-cp27m'),
         PythonArtifact('linux', 'x86', 'cp27-cp27mu'),
         PythonArtifact('linux', 'x86', 'cp34-cp34m'),
diff --git a/tools/run_tests/artifacts/build_artifact_csharp_android.sh b/tools/run_tests/artifacts/build_artifact_csharp_android.sh
new file mode 100755
index 0000000..ba598e7
--- /dev/null
+++ b/tools/run_tests/artifacts/build_artifact_csharp_android.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+# 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.
+
+set -ex
+
+cd "$(dirname "$0")/../../.."
+
+src/csharp/experimental/build_native_ext_for_android.sh
+
+mkdir -p "${ARTIFACTS_OUT}"
+cp cmake/build/libgrpc_csharp_ext.so "${ARTIFACTS_OUT}"
diff --git a/tools/run_tests/artifacts/build_artifact_python.sh b/tools/run_tests/artifacts/build_artifact_python.sh
index 9ea0f05..cd794a1 100755
--- a/tools/run_tests/artifacts/build_artifact_python.sh
+++ b/tools/run_tests/artifacts/build_artifact_python.sh
@@ -17,7 +17,6 @@
 
 cd "$(dirname "$0")/../../.."
 
-export GRPC_PYTHON_USE_CUSTOM_BDIST=0
 export GRPC_PYTHON_BUILD_WITH_CYTHON=1
 export PYTHON=${PYTHON:-python}
 export PIP=${PIP:-pip}
diff --git a/tools/run_tests/artifacts/build_package_ruby.sh b/tools/run_tests/artifacts/build_package_ruby.sh
index 05eacd4..4f74f08 100755
--- a/tools/run_tests/artifacts/build_package_ruby.sh
+++ b/tools/run_tests/artifacts/build_package_ruby.sh
@@ -53,8 +53,11 @@
     output_dir="$base/src/ruby/tools/bin/${ruby_arch}-${plat}"
     mkdir -p "$output_dir"/google/protobuf
     mkdir -p "$output_dir"/google/protobuf/compiler  # needed for plugin.proto
-    cp "$input_dir"/protoc* "$output_dir"/
-    cp "$input_dir"/grpc_ruby_plugin* "$output_dir"/
+    cp "$input_dir"/protoc* "$input_dir"/grpc_ruby_plugin* "$output_dir/"
+    if [[ "$plat" != "windows" ]]
+    then
+      chmod +x "$output_dir/protoc" "$output_dir/grpc_ruby_plugin"
+    fi
     for proto in "${well_known_protos[@]}"; do
       cp "$base/third_party/protobuf/src/google/protobuf/$proto.proto" "$output_dir/google/protobuf/$proto.proto"
     done
diff --git a/tools/run_tests/artifacts/distribtest_targets.py b/tools/run_tests/artifacts/distribtest_targets.py
index 041faab..80adc20 100644
--- a/tools/run_tests/artifacts/distribtest_targets.py
+++ b/tools/run_tests/artifacts/distribtest_targets.py
@@ -146,8 +146,12 @@
 class PythonDistribTest(object):
     """Tests Python package"""
 
-    def __init__(self, platform, arch, docker_suffix):
-        self.name = 'python_%s_%s_%s' % (platform, arch, docker_suffix)
+    def __init__(self, platform, arch, docker_suffix, source=False):
+        self.source = source
+        if source:
+            self.name = 'python_dev_%s_%s_%s' % (platform, arch, docker_suffix)
+        else:
+            self.name = 'python_%s_%s_%s' % (platform, arch, docker_suffix)
         self.platform = platform
         self.arch = arch
         self.docker_suffix = docker_suffix
@@ -160,12 +164,20 @@
         if not self.platform == 'linux':
             raise Exception("Not supported yet.")
 
-        return create_docker_jobspec(
-            self.name,
-            'tools/dockerfile/distribtest/python_%s_%s' % (self.docker_suffix,
-                                                           self.arch),
-            'test/distrib/python/run_distrib_test.sh',
-            copy_rel_path='test/distrib')
+        if self.source:
+            return create_docker_jobspec(
+                self.name,
+                'tools/dockerfile/distribtest/python_dev_%s_%s' %
+                (self.docker_suffix, self.arch),
+                'test/distrib/python/run_source_distrib_test.sh',
+                copy_rel_path='test/distrib')
+        else:
+            return create_docker_jobspec(
+                self.name,
+                'tools/dockerfile/distribtest/python_%s_%s' %
+                (self.docker_suffix, self.arch),
+                'test/distrib/python/run_binary_distrib_test.sh',
+                copy_rel_path='test/distrib')
 
     def __str__(self):
         return self.name
@@ -287,7 +299,10 @@
     return [
         CppDistribTest('linux', 'x64', 'jessie', 'routeguide'),
         CppDistribTest('linux', 'x64', 'jessie', 'cmake'),
+        CppDistribTest('linux', 'x64', 'jessie', 'cmake_as_externalproject'),
+        CppDistribTest('linux', 'x64', 'jessie', 'cmake_as_submodule'),
         CppDistribTest('windows', 'x86', testcase='cmake'),
+        CppDistribTest('windows', 'x86', testcase='cmake_as_externalproject'),
         CSharpDistribTest('linux', 'x64', 'wheezy'),
         CSharpDistribTest('linux', 'x64', 'jessie'),
         CSharpDistribTest('linux', 'x86', 'jessie'),
@@ -312,6 +327,14 @@
         PythonDistribTest('linux', 'x64', 'ubuntu1204'),
         PythonDistribTest('linux', 'x64', 'ubuntu1404'),
         PythonDistribTest('linux', 'x64', 'ubuntu1604'),
+        PythonDistribTest('linux', 'x64', 'jessie', source=True),
+        PythonDistribTest('linux', 'x86', 'jessie', source=True),
+        PythonDistribTest('linux', 'x64', 'centos7', source=True),
+        PythonDistribTest('linux', 'x64', 'fedora22', source=True),
+        PythonDistribTest('linux', 'x64', 'fedora23', source=True),
+        PythonDistribTest('linux', 'x64', 'arch', source=True),
+        PythonDistribTest('linux', 'x64', 'ubuntu1404', source=True),
+        PythonDistribTest('linux', 'x64', 'ubuntu1604', source=True),
         RubyDistribTest('linux', 'x64', 'wheezy'),
         RubyDistribTest('linux', 'x64', 'jessie'),
         RubyDistribTest('linux', 'x86', 'jessie'),
diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json
index fd6c526..4f0fc1d 100644
--- a/tools/run_tests/generated/sources_and_headers.json
+++ b/tools/run_tests/generated/sources_and_headers.json
@@ -60,6 +60,23 @@
     "headers": [], 
     "is_filegroup": false, 
     "language": "c", 
+    "name": "alts_credentials_fuzzer", 
+    "src": [
+      "test/core/security/alts_credentials_fuzzer.cc"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "is_filegroup": false, 
+    "language": "c", 
     "name": "api_fuzzer", 
     "src": [
       "test/core/end2end/fuzzers/api_fuzzer.cc"
@@ -993,23 +1010,6 @@
     "headers": [], 
     "is_filegroup": false, 
     "language": "c", 
-    "name": "grpc_invalid_channel_args_test", 
-    "src": [
-      "test/core/surface/invalid_channel_args_test.cc"
-    ], 
-    "third_party": false, 
-    "type": "target"
-  }, 
-  {
-    "deps": [
-      "gpr", 
-      "gpr_test_util", 
-      "grpc", 
-      "grpc_test_util"
-    ], 
-    "headers": [], 
-    "is_filegroup": false, 
-    "language": "c", 
     "name": "grpc_json_token_test", 
     "src": [
       "test/core/security/json_token_test.cc"
@@ -2686,6 +2686,7 @@
       "benchmark", 
       "gpr", 
       "gpr_test_util", 
+      "grpc++_test_config", 
       "grpc++_test_util_unsecure", 
       "grpc++_unsecure", 
       "grpc_benchmark", 
@@ -2707,6 +2708,7 @@
       "benchmark", 
       "gpr", 
       "gpr_test_util", 
+      "grpc++_test_config", 
       "grpc++_test_util_unsecure", 
       "grpc++_unsecure", 
       "grpc_benchmark", 
@@ -2728,6 +2730,7 @@
       "benchmark", 
       "gpr", 
       "gpr_test_util", 
+      "grpc++_test_config", 
       "grpc++_test_util_unsecure", 
       "grpc++_unsecure", 
       "grpc_benchmark", 
@@ -2749,6 +2752,7 @@
       "benchmark", 
       "gpr", 
       "gpr_test_util", 
+      "grpc++_test_config", 
       "grpc++_test_util_unsecure", 
       "grpc++_unsecure", 
       "grpc_benchmark", 
@@ -2770,6 +2774,7 @@
       "benchmark", 
       "gpr", 
       "gpr_test_util", 
+      "grpc++_test_config", 
       "grpc++_test_util_unsecure", 
       "grpc++_unsecure", 
       "grpc_benchmark", 
@@ -2791,6 +2796,7 @@
       "benchmark", 
       "gpr", 
       "gpr_test_util", 
+      "grpc++_test_config", 
       "grpc++_test_util_unsecure", 
       "grpc++_unsecure", 
       "grpc_benchmark", 
@@ -2812,6 +2818,7 @@
       "benchmark", 
       "gpr", 
       "gpr_test_util", 
+      "grpc++_test_config", 
       "grpc++_test_util_unsecure", 
       "grpc++_unsecure", 
       "grpc_benchmark", 
@@ -2833,6 +2840,7 @@
       "benchmark", 
       "gpr", 
       "gpr_test_util", 
+      "grpc++_test_config", 
       "grpc++_test_util_unsecure", 
       "grpc++_unsecure", 
       "grpc_benchmark", 
@@ -2854,6 +2862,7 @@
       "benchmark", 
       "gpr", 
       "gpr_test_util", 
+      "grpc++_test_config", 
       "grpc++_test_util_unsecure", 
       "grpc++_unsecure", 
       "grpc_benchmark", 
@@ -2878,6 +2887,7 @@
       "benchmark", 
       "gpr", 
       "gpr_test_util", 
+      "grpc++_test_config", 
       "grpc++_test_util_unsecure", 
       "grpc++_unsecure", 
       "grpc_benchmark", 
@@ -2924,6 +2934,7 @@
       "benchmark", 
       "gpr", 
       "gpr_test_util", 
+      "grpc++_test_config", 
       "grpc++_test_util_unsecure", 
       "grpc++_unsecure", 
       "grpc_benchmark", 
@@ -2948,6 +2959,7 @@
       "benchmark", 
       "gpr", 
       "gpr_test_util", 
+      "grpc++_test_config", 
       "grpc++_test_util_unsecure", 
       "grpc++_unsecure", 
       "grpc_benchmark", 
@@ -2969,6 +2981,7 @@
       "benchmark", 
       "gpr", 
       "gpr_test_util", 
+      "grpc++_test_config", 
       "grpc++_test_util_unsecure", 
       "grpc++_unsecure", 
       "grpc_benchmark", 
@@ -3211,6 +3224,9 @@
       "grpc++_core_stats"
     ], 
     "headers": [
+      "src/proto/grpc/testing/benchmark_service.grpc.pb.h", 
+      "src/proto/grpc/testing/benchmark_service.pb.h", 
+      "src/proto/grpc/testing/benchmark_service_mock.grpc.pb.h", 
       "src/proto/grpc/testing/control.grpc.pb.h", 
       "src/proto/grpc/testing/control.pb.h", 
       "src/proto/grpc/testing/control_mock.grpc.pb.h", 
@@ -3220,12 +3236,15 @@
       "src/proto/grpc/testing/payloads.grpc.pb.h", 
       "src/proto/grpc/testing/payloads.pb.h", 
       "src/proto/grpc/testing/payloads_mock.grpc.pb.h", 
-      "src/proto/grpc/testing/services.grpc.pb.h", 
-      "src/proto/grpc/testing/services.pb.h", 
-      "src/proto/grpc/testing/services_mock.grpc.pb.h", 
+      "src/proto/grpc/testing/report_qps_scenario_service.grpc.pb.h", 
+      "src/proto/grpc/testing/report_qps_scenario_service.pb.h", 
+      "src/proto/grpc/testing/report_qps_scenario_service_mock.grpc.pb.h", 
       "src/proto/grpc/testing/stats.grpc.pb.h", 
       "src/proto/grpc/testing/stats.pb.h", 
-      "src/proto/grpc/testing/stats_mock.grpc.pb.h"
+      "src/proto/grpc/testing/stats_mock.grpc.pb.h", 
+      "src/proto/grpc/testing/worker_service.grpc.pb.h", 
+      "src/proto/grpc/testing/worker_service.pb.h", 
+      "src/proto/grpc/testing/worker_service_mock.grpc.pb.h"
     ], 
     "is_filegroup": false, 
     "language": "c++", 
@@ -3245,6 +3264,9 @@
       "grpc++_core_stats"
     ], 
     "headers": [
+      "src/proto/grpc/testing/benchmark_service.grpc.pb.h", 
+      "src/proto/grpc/testing/benchmark_service.pb.h", 
+      "src/proto/grpc/testing/benchmark_service_mock.grpc.pb.h", 
       "src/proto/grpc/testing/control.grpc.pb.h", 
       "src/proto/grpc/testing/control.pb.h", 
       "src/proto/grpc/testing/control_mock.grpc.pb.h", 
@@ -3254,12 +3276,15 @@
       "src/proto/grpc/testing/payloads.grpc.pb.h", 
       "src/proto/grpc/testing/payloads.pb.h", 
       "src/proto/grpc/testing/payloads_mock.grpc.pb.h", 
-      "src/proto/grpc/testing/services.grpc.pb.h", 
-      "src/proto/grpc/testing/services.pb.h", 
-      "src/proto/grpc/testing/services_mock.grpc.pb.h", 
+      "src/proto/grpc/testing/report_qps_scenario_service.grpc.pb.h", 
+      "src/proto/grpc/testing/report_qps_scenario_service.pb.h", 
+      "src/proto/grpc/testing/report_qps_scenario_service_mock.grpc.pb.h", 
       "src/proto/grpc/testing/stats.grpc.pb.h", 
       "src/proto/grpc/testing/stats.pb.h", 
-      "src/proto/grpc/testing/stats_mock.grpc.pb.h"
+      "src/proto/grpc/testing/stats_mock.grpc.pb.h", 
+      "src/proto/grpc/testing/worker_service.grpc.pb.h", 
+      "src/proto/grpc/testing/worker_service.pb.h", 
+      "src/proto/grpc/testing/worker_service_mock.grpc.pb.h"
     ], 
     "is_filegroup": false, 
     "language": "c++", 
@@ -3901,6 +3926,26 @@
       "gpr_test_util", 
       "grpc", 
       "grpc++", 
+      "grpc++_test_util", 
+      "grpc_test_util", 
+      "lb_load_data_store"
+    ], 
+    "headers": [], 
+    "is_filegroup": false, 
+    "language": "c++", 
+    "name": "lb_load_data_store_test", 
+    "src": [
+      "test/cpp/server/load_reporter/load_data_store_test.cc"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc++", 
       "grpc++_test", 
       "grpc_test_util"
     ], 
@@ -4248,6 +4293,23 @@
       "gpr", 
       "gpr_test_util", 
       "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "is_filegroup": false, 
+    "language": "c++", 
+    "name": "retry_throttle_test", 
+    "src": [
+      "test/core/client_channel/retry_throttle_test.cc"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
       "grpc++", 
       "grpc++_test_util", 
       "grpc_test_util"
@@ -4333,6 +4395,32 @@
     "deps": [
       "gpr", 
       "gpr_test_util", 
+      "grpc++_test_util_unsecure", 
+      "grpc++_unsecure", 
+      "grpc_test_util_unsecure", 
+      "grpc_unsecure"
+    ], 
+    "headers": [
+      "src/proto/grpc/testing/echo.grpc.pb.h", 
+      "src/proto/grpc/testing/echo.pb.h", 
+      "src/proto/grpc/testing/echo_messages.grpc.pb.h", 
+      "src/proto/grpc/testing/echo_messages.pb.h", 
+      "src/proto/grpc/testing/echo_messages_mock.grpc.pb.h", 
+      "src/proto/grpc/testing/echo_mock.grpc.pb.h"
+    ], 
+    "is_filegroup": false, 
+    "language": "c++", 
+    "name": "server_builder_with_socket_mutator_test", 
+    "src": [
+      "test/cpp/server/server_builder_with_socket_mutator_test.cc"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "gpr_test_util", 
       "grpc", 
       "grpc++", 
       "grpc++_test", 
@@ -6414,6 +6502,24 @@
     "headers": [], 
     "is_filegroup": false, 
     "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "src": [
+      "test/core/security/alts_credentials_fuzzer.cc", 
+      "test/core/util/one_corpus_entry_fuzzer.cc"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "is_filegroup": false, 
+    "language": "c", 
     "name": "api_fuzzer_one_entry", 
     "src": [
       "test/core/end2end/fuzzers/api_fuzzer.cc", 
@@ -6705,6 +6811,7 @@
       "census", 
       "gpr", 
       "grpc_base", 
+      "grpc_client_authority_filter", 
       "grpc_deadline_filter", 
       "grpc_lb_policy_grpclb_secure", 
       "grpc_lb_policy_pick_first", 
@@ -6739,16 +6846,8 @@
     "deps": [
       "gpr", 
       "grpc_base", 
-      "grpc_base_headers", 
-      "grpc_deadline_filter", 
-      "grpc_lb_policy_pick_first", 
-      "grpc_max_age_filter", 
-      "grpc_message_size_filter", 
-      "grpc_resolver_dns_native", 
-      "grpc_resolver_sockaddr", 
       "grpc_server_load_reporting", 
       "grpc_transport_chttp2_client_secure", 
-      "grpc_transport_chttp2_server_secure", 
       "grpc_transport_cronet_client_secure"
     ], 
     "headers": [], 
@@ -6820,6 +6919,7 @@
       "census", 
       "gpr", 
       "grpc_base", 
+      "grpc_client_authority_filter", 
       "grpc_deadline_filter", 
       "grpc_lb_policy_grpclb", 
       "grpc_lb_policy_pick_first", 
@@ -7450,6 +7550,23 @@
   }, 
   {
     "deps": [
+      "grpc++"
+    ], 
+    "headers": [
+      "src/cpp/server/load_reporter/load_data_store.h"
+    ], 
+    "is_filegroup": false, 
+    "language": "c++", 
+    "name": "lb_load_data_store", 
+    "src": [
+      "src/cpp/server/load_reporter/load_data_store.cc", 
+      "src/cpp/server/load_reporter/load_data_store.h"
+    ], 
+    "third_party": false, 
+    "type": "lib"
+  }, 
+  {
+    "deps": [
       "grpc", 
       "grpc++", 
       "grpc++_core_stats", 
@@ -7457,6 +7574,9 @@
       "grpc_test_util"
     ], 
     "headers": [
+      "src/proto/grpc/testing/benchmark_service.grpc.pb.h", 
+      "src/proto/grpc/testing/benchmark_service.pb.h", 
+      "src/proto/grpc/testing/benchmark_service_mock.grpc.pb.h", 
       "src/proto/grpc/testing/control.grpc.pb.h", 
       "src/proto/grpc/testing/control.pb.h", 
       "src/proto/grpc/testing/control_mock.grpc.pb.h", 
@@ -7466,12 +7586,15 @@
       "src/proto/grpc/testing/payloads.grpc.pb.h", 
       "src/proto/grpc/testing/payloads.pb.h", 
       "src/proto/grpc/testing/payloads_mock.grpc.pb.h", 
-      "src/proto/grpc/testing/services.grpc.pb.h", 
-      "src/proto/grpc/testing/services.pb.h", 
-      "src/proto/grpc/testing/services_mock.grpc.pb.h", 
+      "src/proto/grpc/testing/report_qps_scenario_service.grpc.pb.h", 
+      "src/proto/grpc/testing/report_qps_scenario_service.pb.h", 
+      "src/proto/grpc/testing/report_qps_scenario_service_mock.grpc.pb.h", 
       "src/proto/grpc/testing/stats.grpc.pb.h", 
       "src/proto/grpc/testing/stats.pb.h", 
       "src/proto/grpc/testing/stats_mock.grpc.pb.h", 
+      "src/proto/grpc/testing/worker_service.grpc.pb.h", 
+      "src/proto/grpc/testing/worker_service.pb.h", 
+      "src/proto/grpc/testing/worker_service_mock.grpc.pb.h", 
       "test/cpp/qps/benchmark_config.h", 
       "test/cpp/qps/client.h", 
       "test/cpp/qps/driver.h", 
@@ -8524,6 +8647,7 @@
       "test/core/end2end/tests/bad_ping.cc", 
       "test/core/end2end/tests/binary_metadata.cc", 
       "test/core/end2end/tests/call_creds.cc", 
+      "test/core/end2end/tests/call_host_override.cc", 
       "test/core/end2end/tests/cancel_after_accept.cc", 
       "test/core/end2end/tests/cancel_after_client_done.cc", 
       "test/core/end2end/tests/cancel_after_invoke.cc", 
@@ -8571,6 +8695,7 @@
       "test/core/end2end/tests/retry_exceeds_buffer_size_in_initial_batch.cc", 
       "test/core/end2end/tests/retry_exceeds_buffer_size_in_subsequent_batch.cc", 
       "test/core/end2end/tests/retry_non_retriable_status.cc", 
+      "test/core/end2end/tests/retry_non_retriable_status_before_recv_trailing_metadata_started.cc", 
       "test/core/end2end/tests/retry_recv_initial_metadata.cc", 
       "test/core/end2end/tests/retry_recv_message.cc", 
       "test/core/end2end/tests/retry_server_pushback_delay.cc", 
@@ -8621,6 +8746,7 @@
       "test/core/end2end/tests/bad_hostname.cc", 
       "test/core/end2end/tests/bad_ping.cc", 
       "test/core/end2end/tests/binary_metadata.cc", 
+      "test/core/end2end/tests/call_host_override.cc", 
       "test/core/end2end/tests/cancel_after_accept.cc", 
       "test/core/end2end/tests/cancel_after_client_done.cc", 
       "test/core/end2end/tests/cancel_after_invoke.cc", 
@@ -8668,6 +8794,7 @@
       "test/core/end2end/tests/retry_exceeds_buffer_size_in_initial_batch.cc", 
       "test/core/end2end/tests/retry_exceeds_buffer_size_in_subsequent_batch.cc", 
       "test/core/end2end/tests/retry_non_retriable_status.cc", 
+      "test/core/end2end/tests/retry_non_retriable_status_before_recv_trailing_metadata_started.cc", 
       "test/core/end2end/tests/retry_recv_initial_metadata.cc", 
       "test/core/end2end/tests/retry_recv_message.cc", 
       "test/core/end2end/tests/retry_server_pushback_delay.cc", 
@@ -8796,6 +8923,7 @@
       "tsi_interface"
     ], 
     "headers": [
+      "include/grpc/grpc_security.h", 
       "src/core/lib/security/credentials/alts/check_gcp_environment.h", 
       "src/core/lib/security/credentials/alts/grpc_alts_credentials_options.h", 
       "src/core/tsi/alts/handshaker/alts_handshaker_service_api.h", 
@@ -8807,6 +8935,7 @@
     "language": "c", 
     "name": "alts_util", 
     "src": [
+      "include/grpc/grpc_security.h", 
       "src/core/lib/security/credentials/alts/check_gcp_environment.cc", 
       "src/core/lib/security/credentials/alts/check_gcp_environment.h", 
       "src/core/lib/security/credentials/alts/check_gcp_environment_linux.cc", 
@@ -9551,6 +9680,24 @@
   {
     "deps": [
       "gpr", 
+      "grpc_base"
+    ], 
+    "headers": [
+      "src/core/ext/filters/http/client_authority_filter.h"
+    ], 
+    "is_filegroup": true, 
+    "language": "c", 
+    "name": "grpc_client_authority_filter", 
+    "src": [
+      "src/core/ext/filters/http/client_authority_filter.cc", 
+      "src/core/ext/filters/http/client_authority_filter.h"
+    ], 
+    "third_party": false, 
+    "type": "filegroup"
+  }, 
+  {
+    "deps": [
+      "gpr", 
       "grpc_base", 
       "grpc_deadline_filter"
     ], 
@@ -9708,6 +9855,7 @@
     ], 
     "headers": [
       "src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.h", 
+      "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h", 
       "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h", 
       "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h", 
       "src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h", 
@@ -9720,6 +9868,7 @@
       "src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc", 
       "src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.h", 
       "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc", 
+      "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h", 
       "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.cc", 
       "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h", 
       "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc", 
@@ -9743,6 +9892,7 @@
     ], 
     "headers": [
       "src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.h", 
+      "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h", 
       "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h", 
       "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.h", 
       "src/core/ext/filters/client_channel/lb_policy/grpclb/load_balancer_api.h", 
@@ -9755,6 +9905,7 @@
       "src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.cc", 
       "src/core/ext/filters/client_channel/lb_policy/grpclb/client_load_reporting_filter.h", 
       "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.cc", 
+      "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h", 
       "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel.h", 
       "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_channel_secure.cc", 
       "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb_client_stats.cc", 
@@ -9814,7 +9965,6 @@
     "language": "c", 
     "name": "grpc_lb_subchannel_list", 
     "src": [
-      "src/core/ext/filters/client_channel/lb_policy/subchannel_list.cc", 
       "src/core/ext/filters/client_channel/lb_policy/subchannel_list.h"
     ], 
     "third_party": false, 
@@ -9941,6 +10091,7 @@
     ], 
     "headers": [
       "include/grpc/grpc_security.h", 
+      "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h", 
       "src/core/lib/security/context/security_context.h", 
       "src/core/lib/security/credentials/alts/alts_credentials.h", 
       "src/core/lib/security/credentials/composite/composite_credentials.h", 
@@ -9968,6 +10119,7 @@
     "name": "grpc_secure", 
     "src": [
       "include/grpc/grpc_security.h", 
+      "src/core/ext/filters/client_channel/lb_policy/grpclb/grpclb.h", 
       "src/core/lib/http/httpcli_security_connector.cc", 
       "src/core/lib/security/context/security_context.cc", 
       "src/core/lib/security/context/security_context.h", 
@@ -10074,6 +10226,7 @@
       "test/core/end2end/fixtures/proxy.h", 
       "test/core/iomgr/endpoint_tests.h", 
       "test/core/util/debugger_macros.h", 
+      "test/core/util/fuzzer_util.h", 
       "test/core/util/grpc_profiler.h", 
       "test/core/util/histogram.h", 
       "test/core/util/memory_counters.h", 
@@ -10103,6 +10256,8 @@
       "test/core/iomgr/endpoint_tests.h", 
       "test/core/util/debugger_macros.cc", 
       "test/core/util/debugger_macros.h", 
+      "test/core/util/fuzzer_util.cc", 
+      "test/core/util/fuzzer_util.h", 
       "test/core/util/grpc_profiler.cc", 
       "test/core/util/grpc_profiler.h", 
       "test/core/util/histogram.cc", 
@@ -10269,12 +10424,15 @@
       "grpc_transport_chttp2"
     ], 
     "headers": [
+      "src/core/ext/transport/chttp2/client/authority.h", 
       "src/core/ext/transport/chttp2/client/chttp2_connector.h"
     ], 
     "is_filegroup": true, 
     "language": "c", 
     "name": "grpc_transport_chttp2_client_connector", 
     "src": [
+      "src/core/ext/transport/chttp2/client/authority.cc", 
+      "src/core/ext/transport/chttp2/client/authority.h", 
       "src/core/ext/transport/chttp2/client/chttp2_connector.cc", 
       "src/core/ext/transport/chttp2/client/chttp2_connector.h"
     ], 
@@ -10544,7 +10702,6 @@
     ], 
     "headers": [
       "src/core/tsi/transport_security.h", 
-      "src/core/tsi/transport_security_adapter.h", 
       "src/core/tsi/transport_security_interface.h"
     ], 
     "is_filegroup": true, 
@@ -10553,8 +10710,6 @@
     "src": [
       "src/core/tsi/transport_security.cc", 
       "src/core/tsi/transport_security.h", 
-      "src/core/tsi/transport_security_adapter.cc", 
-      "src/core/tsi/transport_security_adapter.h", 
       "src/core/tsi/transport_security_interface.h"
     ], 
     "third_party": false, 
@@ -10729,6 +10884,8 @@
     ], 
     "headers": [
       "include/grpc++/impl/codegen/proto_utils.h", 
+      "include/grpcpp/impl/codegen/proto_buffer_reader.h", 
+      "include/grpcpp/impl/codegen/proto_buffer_writer.h", 
       "include/grpcpp/impl/codegen/proto_utils.h"
     ], 
     "is_filegroup": true, 
@@ -10736,6 +10893,8 @@
     "name": "grpc++_codegen_proto", 
     "src": [
       "include/grpc++/impl/codegen/proto_utils.h", 
+      "include/grpcpp/impl/codegen/proto_buffer_reader.h", 
+      "include/grpcpp/impl/codegen/proto_buffer_writer.h", 
       "include/grpcpp/impl/codegen/proto_utils.h"
     ], 
     "third_party": false, 
@@ -10834,6 +10993,8 @@
       "include/grpcpp/support/byte_buffer.h", 
       "include/grpcpp/support/channel_arguments.h", 
       "include/grpcpp/support/config.h", 
+      "include/grpcpp/support/proto_buffer_reader.h", 
+      "include/grpcpp/support/proto_buffer_writer.h", 
       "include/grpcpp/support/slice.h", 
       "include/grpcpp/support/status.h", 
       "include/grpcpp/support/status_code_enum.h", 
@@ -10936,6 +11097,8 @@
       "include/grpcpp/support/byte_buffer.h", 
       "include/grpcpp/support/channel_arguments.h", 
       "include/grpcpp/support/config.h", 
+      "include/grpcpp/support/proto_buffer_reader.h", 
+      "include/grpcpp/support/proto_buffer_writer.h", 
       "include/grpcpp/support/slice.h", 
       "include/grpcpp/support/status.h", 
       "include/grpcpp/support/status_code_enum.h", 
@@ -10980,7 +11143,6 @@
       "src/cpp/thread_manager/thread_manager.cc", 
       "src/cpp/thread_manager/thread_manager.h", 
       "src/cpp/util/byte_buffer_cc.cc", 
-      "src/cpp/util/slice_cc.cc", 
       "src/cpp/util/status.cc", 
       "src/cpp/util/string_ref.cc", 
       "src/cpp/util/time_cc.cc"
diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json
index c2bbf8c..701f44f 100644
--- a/tools/run_tests/generated/tests.json
+++ b/tools/run_tests/generated/tests.json
@@ -1279,30 +1279,6 @@
     "ci_platforms": [
       "linux", 
       "mac", 
-      "posix", 
-      "windows"
-    ], 
-    "cpu_cost": 1.0, 
-    "exclude_configs": [], 
-    "exclude_iomgrs": [], 
-    "flaky": false, 
-    "gtest": false, 
-    "language": "c", 
-    "name": "grpc_invalid_channel_args_test", 
-    "platforms": [
-      "linux", 
-      "mac", 
-      "posix", 
-      "windows"
-    ], 
-    "uses_polling": false
-  }, 
-  {
-    "args": [], 
-    "benchmark": false, 
-    "ci_platforms": [
-      "linux", 
-      "mac", 
       "posix"
     ], 
     "cpu_cost": 1.0, 
@@ -4428,6 +4404,30 @@
     "flaky": false, 
     "gtest": true, 
     "language": "c++", 
+    "name": "lb_load_data_store_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "uses_polling": true
+  }, 
+  {
+    "args": [], 
+    "benchmark": false, 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "gtest": true, 
+    "language": "c++", 
     "name": "memory_test", 
     "platforms": [
       "linux", 
@@ -4666,6 +4666,30 @@
     "flaky": false, 
     "gtest": true, 
     "language": "c++", 
+    "name": "retry_throttle_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [], 
+    "benchmark": false, 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix", 
+      "windows"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "gtest": true, 
+    "language": "c++", 
     "name": "secure_auth_context_test", 
     "platforms": [
       "linux", 
@@ -4749,6 +4773,24 @@
     "args": [], 
     "benchmark": false, 
     "ci_platforms": [
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "gtest": true, 
+    "language": "c++", 
+    "name": "server_builder_with_socket_mutator_test", 
+    "platforms": [
+      "posix"
+    ], 
+    "uses_polling": true
+  }, 
+  {
+    "args": [], 
+    "benchmark": false, 
+    "ci_platforms": [
       "linux", 
       "mac", 
       "posix", 
@@ -6969,6 +7011,29 @@
   }, 
   {
     "args": [
+      "call_host_override"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_census_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "cancel_after_accept"
     ], 
     "ci_platforms": [
@@ -8008,6 +8073,29 @@
   }, 
   {
     "args": [
+      "retry_non_retriable_status_before_recv_trailing_metadata_started"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_census_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "retry_recv_initial_metadata"
     ], 
     "ci_platforms": [
@@ -8675,6 +8763,29 @@
   }, 
   {
     "args": [
+      "call_host_override"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_compress_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "cancel_after_accept"
     ], 
     "ci_platforms": [
@@ -9691,6 +9802,29 @@
   }, 
   {
     "args": [
+      "retry_non_retriable_status_before_recv_trailing_metadata_started"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_compress_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "retry_recv_initial_metadata"
     ], 
     "ci_platforms": [
@@ -10353,6 +10487,28 @@
   }, 
   {
     "args": [
+      "call_host_override"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_fakesec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "cancel_after_accept"
     ], 
     "ci_platforms": [
@@ -11347,6 +11503,28 @@
   }, 
   {
     "args": [
+      "retry_non_retriable_status_before_recv_trailing_metadata_started"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_fakesec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "retry_recv_initial_metadata"
     ], 
     "ci_platforms": [
@@ -13186,6 +13364,29 @@
   }, 
   {
     "args": [
+      "call_host_override"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "cancel_after_accept"
     ], 
     "ci_platforms": [
@@ -14225,6 +14426,29 @@
   }, 
   {
     "args": [
+      "retry_non_retriable_status_before_recv_trailing_metadata_started"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "retry_recv_initial_metadata"
     ], 
     "ci_platforms": [
@@ -14872,6 +15096,25 @@
   }, 
   {
     "args": [
+      "call_host_override"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full+pipe_test", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
       "cancel_after_accept"
     ], 
     "ci_platforms": [
@@ -15727,6 +15970,25 @@
   }, 
   {
     "args": [
+      "retry_non_retriable_status_before_recv_trailing_metadata_started"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full+pipe_test", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
       "retry_recv_initial_metadata"
     ], 
     "ci_platforms": [
@@ -16298,6 +16560,29 @@
   }, 
   {
     "args": [
+      "call_host_override"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full+trace_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "cancel_after_accept"
     ], 
     "ci_platforms": [
@@ -17291,6 +17576,29 @@
   }, 
   {
     "args": [
+      "retry_non_retriable_status_before_recv_trailing_metadata_started"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full+trace_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "retry_recv_initial_metadata"
     ], 
     "ci_platforms": [
@@ -17958,6 +18266,29 @@
   }, 
   {
     "args": [
+      "call_host_override"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full+workarounds_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "cancel_after_accept"
     ], 
     "ci_platforms": [
@@ -18997,6 +19328,29 @@
   }, 
   {
     "args": [
+      "retry_non_retriable_status_before_recv_trailing_metadata_started"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full+workarounds_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "retry_recv_initial_metadata"
     ], 
     "ci_platforms": [
@@ -19669,6 +20023,30 @@
   }, 
   {
     "args": [
+      "call_host_override"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_http_proxy_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "cancel_after_accept"
     ], 
     "ci_platforms": [
@@ -20773,6 +21151,30 @@
   }, 
   {
     "args": [
+      "retry_non_retriable_status_before_recv_trailing_metadata_started"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_http_proxy_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "retry_recv_initial_metadata"
     ], 
     "ci_platforms": [
@@ -21464,6 +21866,29 @@
   }, 
   {
     "args": [
+      "call_host_override"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_load_reporting_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "cancel_after_accept"
     ], 
     "ci_platforms": [
@@ -22503,6 +22928,29 @@
   }, 
   {
     "args": [
+      "retry_non_retriable_status_before_recv_trailing_metadata_started"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_load_reporting_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "retry_recv_initial_metadata"
     ], 
     "ci_platforms": [
@@ -23175,6 +23623,30 @@
   }, 
   {
     "args": [
+      "call_host_override"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_oauth2_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "cancel_after_accept"
     ], 
     "ci_platforms": [
@@ -24255,6 +24727,30 @@
   }, 
   {
     "args": [
+      "retry_non_retriable_status_before_recv_trailing_metadata_started"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_oauth2_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "retry_recv_initial_metadata"
     ], 
     "ci_platforms": [
@@ -24927,6 +25423,30 @@
   }, 
   {
     "args": [
+      "call_host_override"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_proxy_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "cancel_after_accept"
     ], 
     "ci_platforms": [
@@ -29848,6 +30368,29 @@
   }, 
   {
     "args": [
+      "call_host_override"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_ssl_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "cancel_after_accept"
     ], 
     "ci_platforms": [
@@ -30887,6 +31430,29 @@
   }, 
   {
     "args": [
+      "retry_non_retriable_status_before_recv_trailing_metadata_started"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_ssl_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "retry_recv_initial_metadata"
     ], 
     "ci_platforms": [
@@ -31535,6 +32101,30 @@
   }, 
   {
     "args": [
+      "call_host_override"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_ssl_proxy_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "cancel_after_accept"
     ], 
     "ci_platforms": [
@@ -33718,6 +34308,29 @@
   }, 
   {
     "args": [
+      "retry_non_retriable_status_before_recv_trailing_metadata_started"
+    ], 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_uds_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "retry_recv_initial_metadata"
     ], 
     "ci_platforms": [
@@ -35305,6 +35918,29 @@
   }, 
   {
     "args": [
+      "call_host_override"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_census_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "cancel_after_accept"
     ], 
     "ci_platforms": [
@@ -36344,6 +36980,29 @@
   }, 
   {
     "args": [
+      "retry_non_retriable_status_before_recv_trailing_metadata_started"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_census_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "retry_recv_initial_metadata"
     ], 
     "ci_platforms": [
@@ -36988,6 +37647,29 @@
   }, 
   {
     "args": [
+      "call_host_override"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_compress_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "cancel_after_accept"
     ], 
     "ci_platforms": [
@@ -38004,6 +38686,29 @@
   }, 
   {
     "args": [
+      "retry_non_retriable_status_before_recv_trailing_metadata_started"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_compress_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "retry_recv_initial_metadata"
     ], 
     "ci_platforms": [
@@ -39821,6 +40526,29 @@
   }, 
   {
     "args": [
+      "call_host_override"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "cancel_after_accept"
     ], 
     "ci_platforms": [
@@ -40860,6 +41588,29 @@
   }, 
   {
     "args": [
+      "retry_non_retriable_status_before_recv_trailing_metadata_started"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "retry_recv_initial_metadata"
     ], 
     "ci_platforms": [
@@ -41488,6 +42239,25 @@
   }, 
   {
     "args": [
+      "call_host_override"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full+pipe_nosec_test", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
       "cancel_after_accept"
     ], 
     "ci_platforms": [
@@ -42343,6 +43113,25 @@
   }, 
   {
     "args": [
+      "retry_non_retriable_status_before_recv_trailing_metadata_started"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full+pipe_nosec_test", 
+    "platforms": [
+      "linux"
+    ]
+  }, 
+  {
+    "args": [
       "retry_recv_initial_metadata"
     ], 
     "ci_platforms": [
@@ -42891,6 +43680,29 @@
   }, 
   {
     "args": [
+      "call_host_override"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full+trace_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "cancel_after_accept"
     ], 
     "ci_platforms": [
@@ -43884,6 +44696,29 @@
   }, 
   {
     "args": [
+      "retry_non_retriable_status_before_recv_trailing_metadata_started"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full+trace_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "retry_recv_initial_metadata"
     ], 
     "ci_platforms": [
@@ -44528,6 +45363,29 @@
   }, 
   {
     "args": [
+      "call_host_override"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full+workarounds_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "cancel_after_accept"
     ], 
     "ci_platforms": [
@@ -45567,6 +46425,29 @@
   }, 
   {
     "args": [
+      "retry_non_retriable_status_before_recv_trailing_metadata_started"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_full+workarounds_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "retry_recv_initial_metadata"
     ], 
     "ci_platforms": [
@@ -46215,6 +47096,30 @@
   }, 
   {
     "args": [
+      "call_host_override"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_http_proxy_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "cancel_after_accept"
     ], 
     "ci_platforms": [
@@ -47319,6 +48224,30 @@
   }, 
   {
     "args": [
+      "retry_non_retriable_status_before_recv_trailing_metadata_started"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_http_proxy_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "retry_recv_initial_metadata"
     ], 
     "ci_platforms": [
@@ -47987,6 +48916,29 @@
   }, 
   {
     "args": [
+      "call_host_override"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_load_reporting_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "cancel_after_accept"
     ], 
     "ci_platforms": [
@@ -49026,6 +49978,29 @@
   }, 
   {
     "args": [
+      "retry_non_retriable_status_before_recv_trailing_metadata_started"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_load_reporting_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "retry_recv_initial_metadata"
     ], 
     "ci_platforms": [
@@ -49650,6 +50625,30 @@
   }, 
   {
     "args": [
+      "call_host_override"
+    ], 
+    "ci_platforms": [
+      "windows", 
+      "linux", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_proxy_nosec_test", 
+    "platforms": [
+      "windows", 
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "cancel_after_accept"
     ], 
     "ci_platforms": [
@@ -55486,6 +56485,29 @@
   }, 
   {
     "args": [
+      "retry_non_retriable_status_before_recv_trailing_metadata_started"
+    ], 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "h2_uds_nosec_test", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
+    "args": [
       "retry_recv_initial_metadata"
     ], 
     "ci_platforms": [
@@ -57022,7 +58044,8 @@
     "defaults": "boringssl", 
     "exclude_configs": [
       "tsan", 
-      "asan"
+      "asan", 
+      "gcov"
     ], 
     "excluded_poll_engines": [], 
     "flaky": false, 
@@ -62840,6 +63863,4836 @@
   }, 
   {
     "args": [
+      "test/core/security/corpus/alts_credentials_corpus/0149b46b88d583e05be0fb1423d10f2a14d36c48"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/047fc351e73f760d329d5a8845944720be9ce773"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/04ef96c66d8222d1a2c07e6b2a6548e6a527042b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/05a7e16c1d7f92111f43e9c777421879920e79a4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/063eb46f202fdfe7935c30ca38d7eb81c82db419"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/064773597c295fa871c184fc12d17b6de8aab31b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/087449740758b114d16790067707934479946bd6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/0a5d068feb57a2782c6eba57b637abe8668ac82f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/0b81e6d89bf7df80e87e5ee7c49f7cc1431f77e8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/11409339cec708a5e353893101bfe76364337d5c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/147696a264cd6f197adb7c68aff834c30b1b77f8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/160e5cac38c5c9e919ed6e4fbafee76907d63044"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/173d02167db431040b0540d98f6fc5e8b456587d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/18a3fe239806b3c7d1af24bcd2bd23aeeb072d5c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/195abd83b2e9d32b1b5b854fe33da44b6db40880"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/19af2509c7d84334b9ec64de4767a07d5294fd72"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/1b9864b948fcf08b062fd4401ef55b214c259535"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/1edddfa67de854d7faaba41418fda845e9c6a89d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/20031bb00e6608e1b570aa96e6afb9de06d42167"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/22b4c7ce7db99b0df63c9eae9265de484b695922"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/27416437ad287bd3cc1c5efdecebc39f20df73c1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/27e8cd785c2b9346f68dba75761b52fbabaf2b72"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/28236f860d3d8e5ea11176746cb4c1c5c4f1f6c0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/29e15b492c5a409938092a30c003c5c34df7e283"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/2a47864d77749aa042b772895dbdf46f608ccc6d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/2cca5cb1b135c35f6e5e1ec4c37deb9e12d37dc0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/2df27b6c42dbaee382a29a87338d64ee87354acb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/2e9ddd1339d8e599cef658a08965985c4f45e428"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/31a2d12a84a7a56ace831a9668d6ab4847390679"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/33cb9ec0ce3538ed6079b5fcb127649a5d05955b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/348d9ae6eebb2e1644addf7f07231d108cf6f3b8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/359f76f3c802292e92b0640de2bfe051e780a3b6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/35a479988e965a6e3e75138b64b0bd1f45073e2f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/362b00d713686ff70cb0199f3d7d0058e5a1a27a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/3849c1625071791ceae709b9c6c705b28d099d67"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/39ef03c66ee2d4bcfb6c8da50486dcd40f02fb12"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/3a3ca061863499ebc171a4f910fa1b49523baad4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/3a890f3fd01b048ac9db65a9a9b4f4443268b91a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/3b9554038a425bd1fae057ba41f9366bb467e946"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/3ce0ae4aa226f205a3a4e66bbb253419d9d754bf"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/3dccc5523986c37e27684659bba8a1037e7a92e8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/3e0908c15b1cede4541d25f388b1345e8641e221"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/3fcb181ff6a8c8e2ba38ed34cf78f7482eb55cb7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/41c9b5f720eb8f8fa04c840375a881781a849b43"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/4257a018f08f13a3a9adc848ef808e1be50bc4cf"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/42dfc5c4d13261b7259e65cd692df9c9d607194e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/43144664aedb585d45d42aa5249ddbfe81afe470"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/43e5ad495a47593b17dbcbd3e70c2e25a417bb6e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/446614e45b7bef49118b17e031c48faf167ebe3e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/46492477fa84ca88e85df914801af0b09b0939f6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/47157f83b166b57e0052c98a65c6db864fa6cb9b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/473fc9b6d768a925527d3ad805ca363d490dc741"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/483c0b4015100eee00f6b23d1100d8c4953dd3b1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/48be2dc4cdc5462407b319caa855d976cda88153"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/4e84eb54a0e438052b0c2e83653135042d9eb59a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/50839d5c8bf33f0970986dcc4b73b024f11a95b7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/523d964986d8ad966ae07e540a608681098813f9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/5410b8190c95dacd36d6e6ec75b7538a630e08de"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/549b2891ac79f504a7c9ea00f6d7527c34ce04e6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/55321649e7b7f1b5664ae20724e683c930643fc4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/55cc52f25865baee3e6e52c3110a9723caa2b3cb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/56c22410e3295ad03aa31552ab888f581756cc17"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/5724a705b62a7548ba2df1abe4ef0c970c4e1bd2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/576a148c107d56861d1611641a6f7c7921061c5c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/5a6b8263e8939f851cf5b1e347a33d97253b7b3d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/5ba93c9db0cff93f52b521d7420e43f6eda2784f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/5bd02a339fd7705449388580c75bfcc597aba954"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/5bd6fb6fc4163bf3a9db6ddaf509dce8df8a5000"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/5d06fc38005503af3d084721c60e574fb9d2f370"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/5ddc10489ff3269bdaa3051b70fb7af455ee1104"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/5ea9d515f0d10b04f1356b9463139bfe121a6e4a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/61c449793347cf2e1ed0c38d54d23c63dfaabeb8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/6287389c373e9788dcc04f9747b4be1fd1ef3028"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/64d4de4d5aafab7ec388a7fe83066c1a4d1d9d68"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/651c37806d2ac579dcfc97643c3c1ea74dbb8774"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/6551d02d20573cfa2944ec1f12b0c01f264a1326"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/65f029414ee10e45ff4b9f305f7b472364cea538"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/68b75a17fe2db060df3e61a597650ba99079abbf"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/69e80594dbc5c4c648e39883a650b1760f20ab63"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/6cb47d0e640b4c41e32f13c0d64ee46eae1b80b5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/6da5fe063432cb9094c7c083efdbbe5ba4246d18"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/6dd140da774d85f272fb587dc1b2a85d881a7c21"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/6ddab273597d73be49e2307d68e00fa18bba4765"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/6eaf85d84fbf47ea0619d0dba8d366f4e3ff0be6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/6f751cc09af8113f6ecd491b1830bd8454c4738d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/70d9eb29a70d483d07e2faca6b00098af78d1fff"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/7192effa1058382b379fb7b87f1acad5ac554d05"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/730e85d6a62e70cb6721009b903782ade4ff73a2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/74002471a854059cb29de7cad8f9fb7adc3c5ec2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/747f2330cd1fc4a06d54b376a9a6528d0364f0ac"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/749d5d7a9e0b1545b297117e834462af32b3e230"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/77de0b1de120ac702ca45868b1008a48626daf12"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/792c67398bce19a4eeda32653c994436e79456e5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/7a3022b248c8960289e4c80c7cc8df409499e5da"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/7a9372081294a6fbd3fecdd91b99589c98d4948e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/7bbe4ba828947550f4ad089d5989cb695ecbdb1b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/7f1ad514a96f0c3d5ca5d6f7880b929a65eeae96"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/7f2b075f0b6707c38db851747e2578343eeab286"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/81ebc64bfde3fad37af5a58ef7f1c5c3c54c4b5d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/82fae081afaea13831404024d39658344d56e1c6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/83ba41cea1adab707f7f213af5e2ed734bdddc25"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/841a3f66c94e5acd836a44cd5a8514d4ad45d83e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/841ef94ee0f1b0b45983d95b75aba25421d73f2c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/843b0aad4a9707c5dcc92d12d876b78675cfcb65"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/8483e3d92eda8df504b1d1d0d012f4bcd778cd33"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/876830fdff4e59038fa2173b700faef5bffe61de"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/87ca3342fdce0c1f678a3f1b62428032ef51442d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/87d044027cdb7d35fadb56532f497764246946a6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/88ce75ba18bdb7e93a81197d850f4e792f6a8155"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/89dc55e8e20e811e78c952c8bd2c16f55fe72f57"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/8a215a58908f44bdced595ceb01a81977f1d72f0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/8ac7459e918304ca40b1cf29a3ac0f555eada678"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/8b93e50a911f3ea0e0b0377ba4636574f2ee9a5e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/8c9ec0ffd803505772693833d56e7a02110645b3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/8e4b361a530dc6825afcfb4106bd482c3fd010fa"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/8f6690d97bcda890f2a5b2930a2b7a4d7b56c6e7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/917636de2c14dce2580d4308249a94d61d62c305"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/91f11008defda918951bda868cc68c6373fb0e6a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/92e01a34047b660a798086d55a3d8d7100a01939"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/963fafadb4de09dee0e6a852bd61b1740039a465"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/97bf33ec97b93fcc2449431915911a55b906e3b6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/99e31e12b02b02479d10b2c08426906bd93a0840"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/9a75ce693e7259d4d3bb9203dfc0a65f8bbaa466"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/9ac0d956f9743e026baad7319ba2a75d9f1a534f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/9ae56d4451dd3e1b66ddc250d84dbf6d8cae0dbd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/9b9a3a1e4023c9b172060249752a482a3437ef2a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/9c81164e10bf612c352dca3ecabf57743b451d42"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/9d8b420b5d32deb0140ab91eeebba58ca6163722"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/9de687bf1e2cfac54c3b2e2eb85b53014a460ff7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/9f3cda19a186bd11bfac361b464f92daa129a33b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/a14fc6a608121f8abf0fe25cf466720f00f25653"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/a39906074669a6b76a35b0adf2bf36ad751f3b35"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/a454ca483b4a66b83826d061be2859dd79ff0d6c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/a52df5607370ff0f56d821000f3d5e386a01d489"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/a56eaf47f7c7263e53efdc55ec39063dbb4ae71c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/a79249fb8f7d53f0a280359d2d9df31594adbdfc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/aa98a46f25004f7436aadb36ff8b7f07ed7bfce1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/adc83b19e793491b1c6ea0fd8b46cd9f32e592fc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/afd8e19f7bfd6c963f1856be59b75627864821dc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/b3966239b8568442baecbeb0f8a1aa29dcdfd7ed"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/b430d41ef65493b3e917182c23ce90df983e01ab"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/b44e715e0cfe05f0c92a9e000ac3c36aae17df9d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/b4cf4ef7b3f64eff76cf99091fddc04411774708"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/b53d84468ea93620a9824ca65acf1179f431e763"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/b6ac4831cc5baabee9c8ab9af9ca3923f91097a0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/b7f4a484866a8050dbc63bc905c9803c6964eda5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/b8f21e59f90431c982d5ec3fb54ae4605f102252"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/bad10b6581cdead8e7cb96e4f544dcf0ea650fbc"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/bb01bed86b43257be9f527388e1183f52438c473"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/bb7497b00f0d999ef39dbf81c6bd0441e32723b6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/bf01b72e635deda1b4a8468f1cc36f01a54e1338"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/bf8b4530d8d246dd74ac53a13471bba17941dff7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/c08bc84ab6a512b901bb730beb05c8394e4f1c5d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/c244b635d94e6f5d6b344887434be3e001a04b41"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/c281efe9620da999a637ff6e9b3279ec613fb992"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/c30a212824ee71e215f475f453de17c65a200101"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/c449427f35b7ecdf5641073629f7723df52c4cb0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/c60240cd3b02eb71e2bf5ebd59afa3a5dc9b5e4d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/c60cdf9c3fb9060838f445b3bc3852b6f81e1e4c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/c72d0501bacadb45242c553ba292591302f12a6a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/c739e7b5ad999edbdeffdab672dbc30deb3959a0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/c7d73b12a7108d82f8dac6d8a6a34f838601aca6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/ca781e1add632433293e847ae9e71649c217ee5f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/cc48e916f40e8d69c2d07cfda42c7d3b7fe3447a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/cca1aff4c08ee4ccbcb6f80e1cd1480a0a093cfd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/cf6ae8bf1d08d25e235b7bee0839984bbc04edf6"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/cfc52fa086292c699efd7bf41d2fae3deb449536"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/cfe13ef3c6c713a059f231f0001ecec97e2a932d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/d14026ac6421bca7161024f4e735cb80a1068d01"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/d2fb6e8f7867fc1e2ebe723da2b5246dc9cc6b14"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/d4db7d51bdaa4781cf12c3b59914bad414d2a41e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/d533da0e7f8c1e39bb025b4d7a89613142a6f54e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/d5cf489d01a1b847a7aac5dddabff23fdc218e1e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/d686f8561a249c7c15c78f76a5fceb884286e070"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/d92424daad9d96a40e5ab177e3824c36ef51dc0f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/db242a11ed88b2b26af46770dd1927d9f35301fb"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/db32eb04db13d58f65f46d262608bd088987c063"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/db39a953317951759e40734de6607a0b4457728e"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/dc5e8f3102456bed90d17303bc4cff1a7e076d5d"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/dd9542bbed8e5dc58da2789edbfb9c38d578d3b4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/de2ebb1ed324385de500a1a3308846239857c3c7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/de8ba9158254c1cd84b53df1e4cdf1757b1392f1"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/e1dd260746f50024822a8b729b89545d26decfb8"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/e29add81b20dc570fdc885782689f6dccb1c5fad"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/e2e99af62843cd3b29d50daeb118e58830784da9"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/e46611c5daf99662e1576147c1623409752a1f39"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/e5a1ba11af830e9d2db201c5164f75747a85fe9b"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/e6026ee0badf216b326443a5f708446b2f2e579f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/e6c7d2c0038fa1f03fc6590a726abc98f4c641f3"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/eafdef6a630bed71bd0e4f3d4a16b5fa0c920651"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/ece985b9b82e27281514d460709d7edf8203ded7"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/edb8f4259f756c2c4bc731f05beaa36f992cf079"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/edce7778c2e1adb81dda3d057a6536759a7cb293"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/ee4040c0dd406dd616c49ed2c37b40478dabfe0f"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/ee69f2b380663d051a70f30fcfce9f79f5341e5a"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/efc6743e47274058771bb6eda1fefa017bde4a95"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/f0038e54162000694d882b1acb80930c807b41d2"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/f1deb9e388c877337dabe92f31b01e2a019a10f4"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/f3a09373e4d3c7310d372089e6deb15d6b22c198"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/f3db7ef6495fa1ac5bb4db293fb38dd59122bb7c"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/f434bb4ceecc573e085d4c3ef453ef01e93d9c89"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/f55bceaad42ddf9d2b37fdfca68255d29a696109"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/f62ca5321428a5d23f3c804fb51eb4e65bc58716"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/f7c6a558b8d0af64db2b139371a7af7068b01b92"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/faa1781e1444bba5b8c677bc5e2a38d023a1ec65"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/fceba33ada1dda05fccedfefd331c9a201f1a2e5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/fd668bef6fdaf7f3ffd58d8c60ce550476652e60"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/fdf06b928e37e7c4ae59a568b5723ad98bbed6e5"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/fe2fc5d499aeb2762387ef2e3ce939280813dec0"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/security/corpus/alts_credentials_corpus/ff548d368b090409a138e5cc4afc7f43b4a3fbbd"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "alts_credentials_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/00.bin"
     ], 
     "ci_platforms": [
@@ -103987,6 +109840,75 @@
   }, 
   {
     "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-api_fuzzer-5406804084260864"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-api_fuzzer-5471994809155584"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
+      "test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-api_fuzzer-6609852341157888"
+    ], 
+    "ci_platforms": [
+      "linux"
+    ], 
+    "cpu_cost": 0.1, 
+    "exclude_configs": [
+      "tsan"
+    ], 
+    "exclude_iomgrs": [
+      "uv"
+    ], 
+    "flaky": false, 
+    "language": "c", 
+    "name": "api_fuzzer_one_entry", 
+    "platforms": [
+      "mac", 
+      "linux"
+    ], 
+    "uses_polling": false
+  }, 
+  {
+    "args": [
       "test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-minimized-4688823906729984"
     ], 
     "ci_platforms": [
diff --git a/tools/run_tests/helper_scripts/build_python.sh b/tools/run_tests/helper_scripts/build_python.sh
index b809fe0..cdcb2aa 100755
--- a/tools/run_tests/helper_scripts/build_python.sh
+++ b/tools/run_tests/helper_scripts/build_python.sh
@@ -112,10 +112,6 @@
 export GRPC_PYTHON_BUILD_WITH_CYTHON=1
 export LANG=en_US.UTF-8
 
-# Default python on the host to fall back to when instantiating e.g. the
-# virtualenv.
-HOST_PYTHON=${HOST_PYTHON:-python}
-
 # If ccache is available on Linux, use it.
 if [ "$(is_linux)" ]; then
   # We're not on Darwin (Mac OS X)
@@ -132,16 +128,16 @@
 # Perform build operations #
 ############################
 
-# Instnatiate the virtualenv, preferring to do so from the relevant python
-# version. Even if these commands fail (e.g. on Windows due to name conflicts)
-# it's possible that the virtualenv is still usable and we trust the tester to
-# be able to 'figure it out' instead of us e.g. doing potentially expensive and
-# unnecessary error recovery by `rm -rf`ing the virtualenv.
-($PYTHON -m virtualenv "$VENV" ||
- $HOST_PYTHON -m virtualenv -p "$PYTHON" "$VENV" ||
- true)
+# Instantiate the virtualenv from the Python version passed in.
+$PYTHON -m pip install virtualenv
+$PYTHON -m virtualenv "$VENV"
 VENV_PYTHON=$(script_realpath "$VENV/$VENV_RELATIVE_PYTHON")
 
+# See https://github.com/grpc/grpc/issues/14815 for more context. We cannot rely
+# on pip to upgrade itself because if pip is too old, it may not have the required
+# TLS version to run `pip install`.
+curl https://bootstrap.pypa.io/get-pip.py | $VENV_PYTHON
+
 # pip-installs the directory specified. Used because on MSYS the vanilla Windows
 # Python gets confused when parsing paths.
 pip_install_dir() {
@@ -152,7 +148,13 @@
   cd "$PWD"
 }
 
-$VENV_PYTHON -m pip install --upgrade pip==9.0.1
+case "$VENV" in
+  *gevent*)
+  $VENV_PYTHON -m pip install gevent
+  ;;
+esac
+
+$VENV_PYTHON -m pip install --upgrade pip==10.0.1
 $VENV_PYTHON -m pip install setuptools
 $VENV_PYTHON -m pip install cython
 $VENV_PYTHON -m pip install six enum34 protobuf futures
diff --git a/tools/run_tests/helper_scripts/run_python.sh b/tools/run_tests/helper_scripts/run_python.sh
index bcfe3a6..2b7321e 100755
--- a/tools/run_tests/helper_scripts/run_python.sh
+++ b/tools/run_tests/helper_scripts/run_python.sh
@@ -22,7 +22,7 @@
 
 ROOT=$(pwd)
 
-$PYTHON "$ROOT/src/python/grpcio_tests/setup.py" test_lite
+$PYTHON "$ROOT/src/python/grpcio_tests/setup.py" "$2"
 
 mkdir -p "$ROOT/reports"
 rm -rf "$ROOT/reports/python-coverage"
diff --git a/tools/run_tests/helper_scripts/run_ruby.sh b/tools/run_tests/helper_scripts/run_ruby.sh
index 4e9c212..03eaeb0 100755
--- a/tools/run_tests/helper_scripts/run_ruby.sh
+++ b/tools/run_tests/helper_scripts/run_ruby.sh
@@ -18,4 +18,7 @@
 # change to grpc repo root
 cd "$(dirname "$0")/../../.."
 
+# build grpc_ruby_plugin
+make grpc_ruby_plugin -j8
+
 rake
diff --git a/tools/run_tests/helper_scripts/run_ruby_end2end_tests.sh b/tools/run_tests/helper_scripts/run_ruby_end2end_tests.sh
index 1955442..5784745 100755
--- a/tools/run_tests/helper_scripts/run_ruby_end2end_tests.sh
+++ b/tools/run_tests/helper_scripts/run_ruby_end2end_tests.sh
@@ -28,4 +28,5 @@
 ruby src/ruby/end2end/grpc_class_init_driver.rb || EXIT_CODE=1
 ruby src/ruby/end2end/multiple_killed_watching_threads_driver.rb || EXIT_CODE=1
 ruby src/ruby/end2end/load_grpc_with_gc_stress_driver.rb || EXIT_CODE=1
+ruby src/ruby/end2end/client_memory_usage_driver.rb || EXIT_CODE=1
 exit $EXIT_CODE
diff --git a/tools/run_tests/interop/android/android_interop_helper.sh b/tools/run_tests/interop/android/android_interop_helper.sh
deleted file mode 100755
index 116549b..0000000
--- a/tools/run_tests/interop/android/android_interop_helper.sh
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/bin/bash
-# Copyright 2017 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.
-
-# Helper that runs inside the docker container and builds the APKs and
-# invokes Firebase Test Lab via gcloud.
-
-SERVICE_KEY=$1
-
-gcloud auth activate-service-account --key-file="$SERVICE_KEY" || exit 1
-gcloud config set project grpc-testing || exit 1
-
-rm -rf grpc-java
-git clone https://github.com/grpc/grpc-java.git
-cd grpc-java
-./gradlew install || exit 1
-cd android-interop-testing
-../gradlew assembleDebug
-../gradlew assembleDebugAndroidTest
-
-gcloud firebase test android run \
-  --type instrumentation \
-  --app app/build/outputs/apk/app-debug.apk \
-  --test app/build/outputs/apk/app-debug-androidTest.apk \
-  --device model=Nexus6,version=21,locale=en,orientation=portrait
diff --git a/tools/run_tests/interop/android/run_android_tests_on_firebase.sh b/tools/run_tests/interop/android/run_android_tests_on_firebase.sh
deleted file mode 100755
index f6472eb..0000000
--- a/tools/run_tests/interop/android/run_android_tests_on_firebase.sh
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/bin/bash
-# Copyright 2017 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.
-
-# Builds the gRPC Android instrumented interop tests inside a docker container
-# and runs them on Firebase Test Lab
-
-DOCKERFILE=tools/dockerfile/interoptest/grpc_interop_android_java/Dockerfile
-DOCKER_TAG=android_interop_test
-SERVICE_KEY=~/android-interops-service-key.json
-HELPER=$(pwd)/tools/run_tests/interop/android/android_interop_helper.sh
-
-docker build -t "$DOCKER_TAG" -f "$DOCKERFILE" .
-
-docker run --interactive --rm \
-  --volume="$SERVICE_KEY":/service-key.json:ro \
-  --volume="$HELPER":/android_interop_helper.sh:ro \
-  $DOCKER_TAG \
-      /bin/bash -c "/android_interop_helper.sh /service-key.json"
diff --git a/tools/run_tests/python_utils/upload_rbe_results.py b/tools/run_tests/python_utils/upload_rbe_results.py
new file mode 100644
index 0000000..d302024
--- /dev/null
+++ b/tools/run_tests/python_utils/upload_rbe_results.py
@@ -0,0 +1,182 @@
+#!/usr/bin/env python
+# Copyright 2017 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.
+"""Uploads RBE results to BigQuery"""
+
+import argparse
+import os
+import json
+import sys
+import urllib2
+import uuid
+
+gcp_utils_dir = os.path.abspath(
+    os.path.join(os.path.dirname(__file__), '../../gcp/utils'))
+sys.path.append(gcp_utils_dir)
+import big_query_utils
+
+_DATASET_ID = 'jenkins_test_results'
+_DESCRIPTION = 'Test results from master RBE builds on Kokoro'
+# 90 days in milliseconds
+_EXPIRATION_MS = 90 * 24 * 60 * 60 * 1000
+_PARTITION_TYPE = 'DAY'
+_PROJECT_ID = 'grpc-testing'
+_RESULTS_SCHEMA = [
+    ('job_name', 'STRING', 'Name of Kokoro job'),
+    ('build_id', 'INTEGER', 'Build ID of Kokoro job'),
+    ('build_url', 'STRING', 'URL of Kokoro build'),
+    ('test_target', 'STRING', 'Bazel target path'),
+    ('test_case', 'STRING', 'Name of test case'),
+    ('result', 'STRING', 'Test or build result'),
+    ('timestamp', 'TIMESTAMP', 'Timestamp of test run'),
+]
+_TABLE_ID = 'rbe_test_results'
+
+
+def _get_api_key():
+    """Returns string with API key to access ResultStore.
+	Intended to be used in Kokoro envrionment."""
+    api_key_directory = os.getenv('KOKORO_GFILE_DIR')
+    api_key_file = os.path.join(api_key_directory, 'resultstore_api_key')
+    assert os.path.isfile(api_key_file), 'Must add --api_key arg if not on ' \
+     'Kokoro or Kokoro envrionment is not set up properly.'
+    with open(api_key_file, 'r') as f:
+        return f.read().replace('\n', '')
+
+
+def _get_invocation_id():
+    """Returns String of Bazel invocation ID. Intended to be used in
+	Kokoro envirionment."""
+    bazel_id_directory = os.getenv('KOKORO_ARTIFACTS_DIR')
+    bazel_id_file = os.path.join(bazel_id_directory, 'bazel_invocation_ids')
+    assert os.path.isfile(bazel_id_file), 'bazel_invocation_ids file, written ' \
+     'by bazel_wrapper.py, expected but not found.'
+    with open(bazel_id_file, 'r') as f:
+        return f.read().replace('\n', '')
+
+
+def _upload_results_to_bq(rows):
+    """Upload test results to a BQ table.
+
+  Args:
+      rows: A list of dictionaries containing data for each row to insert
+  """
+    bq = big_query_utils.create_big_query()
+    big_query_utils.create_partitioned_table(
+        bq,
+        _PROJECT_ID,
+        _DATASET_ID,
+        _TABLE_ID,
+        _RESULTS_SCHEMA,
+        _DESCRIPTION,
+        partition_type=_PARTITION_TYPE,
+        expiration_ms=_EXPIRATION_MS)
+
+    max_retries = 3
+    for attempt in range(max_retries):
+        if big_query_utils.insert_rows(bq, _PROJECT_ID, _DATASET_ID, _TABLE_ID,
+                                       rows):
+            break
+        else:
+            if attempt < max_retries - 1:
+                print('Error uploading result to bigquery, will retry.')
+            else:
+                print(
+                    'Error uploading result to bigquery, all attempts failed.')
+                sys.exit(1)
+
+
+def _get_resultstore_data(api_key, invocation_id):
+    """Returns dictionary of test results by querying ResultStore API.
+  Args:
+      api_key: String of ResultStore API key
+      invocation_id: String of ResultStore invocation ID to results from 
+  """
+    all_actions = []
+    page_token = ''
+    # ResultStore's API returns data on a limited number of tests. When we exceed
+    # that limit, the 'nextPageToken' field is included in the request to get
+    # subsequent data, so keep requesting until 'nextPageToken' field is omitted.
+    while True:
+        req = urllib2.Request(
+            url=
+            'https://resultstore.googleapis.com/v2/invocations/%s/targets/-/configuredTargets/-/actions?key=%s&pageToken=%s'
+            % (invocation_id, api_key, page_token),
+            headers={
+                'Content-Type': 'application/json'
+            })
+        results = json.loads(urllib2.urlopen(req).read())
+        all_actions.extend(results['actions'])
+        if 'nextPageToken' not in results:
+            break
+        page_token = results['nextPageToken']
+    return all_actions
+
+
+if __name__ == "__main__":
+    # Arguments are necessary if running in a non-Kokoro envrionment.
+    argp = argparse.ArgumentParser(description='Upload RBE results.')
+    argp.add_argument('--api_key', default='', type=str)
+    argp.add_argument('--invocation_id', default='', type=str)
+    args = argp.parse_args()
+
+    api_key = args.api_key or _get_api_key()
+    invocation_id = args.invocation_id or _get_invocation_id()
+    resultstore_actions = _get_resultstore_data(api_key, invocation_id)
+
+    bq_rows = []
+    for action in resultstore_actions:
+        # Filter out non-test related data, such as build results.
+        if 'testAction' not in action:
+            continue
+        # Some test results contain the fileProcessingErrors field, which indicates
+        # an issue with parsing results individual test cases.
+        if 'fileProcessingErrors' in action:
+            test_cases = [{
+                'testCase': {
+                    'caseName': str(action['id']['actionId']),
+                    'result': str(action['statusAttributes']['status'])
+                }
+            }]
+        else:
+            test_cases = action['testAction']['testSuite']['tests'][0][
+                'testSuite']['tests']
+        for test_case in test_cases:
+            if 'errors' in test_case['testCase']:
+                result = 'FAILED'
+            else:
+                result = 'PASSED'
+            bq_rows.append({
+                'insertId': str(uuid.uuid4()),
+                'json': {
+                    'job_name':
+                    os.getenv('KOKORO_JOB_NAME'),
+                    'build_id':
+                    os.getenv('KOKORO_BUILD_NUMBER'),
+                    'build_url':
+                    'https://sponge.corp.google.com/invocation?id=%s' %
+                    os.getenv('KOKORO_BUILD_ID'),
+                    'test_target':
+                    action['id']['targetId'],
+                    'test_case':
+                    test_case['testCase']['caseName'],
+                    'result':
+                    result,
+                    'timestamp':
+                    action['timing']['startTime'],
+                }
+            })
+    # BigQuery sometimes fails with large uploads, so batch 1,000 rows at a time.
+    for i in range((len(bq_rows) / 1000) + 1):
+        _upload_results_to_bq(bq_rows[i * 1000:(i + 1) * 1000])
diff --git a/tools/run_tests/python_utils/upload_test_results.py b/tools/run_tests/python_utils/upload_test_results.py
index a2dd1c6..09dcd57 100644
--- a/tools/run_tests/python_utils/upload_test_results.py
+++ b/tools/run_tests/python_utils/upload_test_results.py
@@ -74,7 +74,7 @@
     build_id = os.getenv('BUILD_ID') or os.getenv('KOKORO_BUILD_NUMBER')
     build_url = os.getenv('BUILD_URL')
     if os.getenv('KOKORO_BUILD_ID'):
-        build_url = 'https://sponge.corp.google.com/invocation?id=%s' % os.getenv(
+        build_url = 'https://source.cloud.google.com/results/invocations/%s' % os.getenv(
             'KOKORO_BUILD_ID')
     job_name = os.getenv('JOB_BASE_NAME') or os.getenv('KOKORO_JOB_NAME')
 
diff --git a/tools/run_tests/run_interop_tests.py b/tools/run_tests/run_interop_tests.py
index ba4ab3b..aa58107 100755
--- a/tools/run_tests/run_interop_tests.py
+++ b/tools/run_tests/run_interop_tests.py
@@ -545,13 +545,13 @@
 
     def client_cmd(self, args):
         return [
-            'py27/bin/python', 'src/python/grpcio_tests/setup.py',
+            'py27_native/bin/python', 'src/python/grpcio_tests/setup.py',
             'run_interop', '--client', '--args="{}"'.format(' '.join(args))
         ]
 
     def client_cmd_http2interop(self, args):
         return [
-            'py27/bin/python',
+            'py27_native/bin/python',
             'src/python/grpcio_tests/tests/http2/negative_http2_client.py',
         ] + args
 
@@ -560,7 +560,7 @@
 
     def server_cmd(self, args):
         return [
-            'py27/bin/python', 'src/python/grpcio_tests/setup.py',
+            'py27_native/bin/python', 'src/python/grpcio_tests/setup.py',
             'run_interop', '--server', '--args="{}"'.format(' '.join(args))
         ]
 
@@ -637,6 +637,14 @@
     'java', 'go', 'python', 'c++'
 ]
 
+#TODO: Add c++ when c++ ALTS interop client is ready.
+_LANGUAGES_FOR_ALTS_TEST_CASES = ['java', 'go', 'c++']
+
+#TODO: Add c++ when c++ ALTS interop server is ready.
+_SERVERS_FOR_ALTS_TEST_CASES = ['java', 'go', 'c++']
+
+_TRANSPORT_SECURITY_OPTIONS = ['tls', 'alts', 'insecure']
+
 DOCKER_WORKDIR_ROOT = '/var/local/git/grpc'
 
 
@@ -691,17 +699,29 @@
     return ['bash', '-c', ' '.join(cmdline)]
 
 
-def auth_options(language, test_case):
+def compute_engine_creds_required(language, test_case):
+    """Returns True if given test requires access to compute engine creds."""
+    language = str(language)
+    if test_case == 'compute_engine_creds':
+        return True
+    if test_case == 'oauth2_auth_token' and language == 'c++':
+        # C++ oauth2 test uses GCE creds because C++ only supports JWT
+        return True
+    return False
+
+
+def auth_options(language, test_case, service_account_key_file=None):
     """Returns (cmdline, env) tuple with cloud_to_prod_auth test options."""
 
     language = str(language)
     cmdargs = []
     env = {}
 
-    # TODO(jtattermusch): this file path only works inside docker
-    key_filepath = '/root/service_account/GrpcTesting-726eb1347f15.json'
+    if not service_account_key_file:
+        # this file path only works inside docker
+        service_account_key_file = '/root/service_account/GrpcTesting-726eb1347f15.json'
     oauth_scope_arg = '--oauth_scope=https://www.googleapis.com/auth/xapi.zoo'
-    key_file_arg = '--service_account_key_file=%s' % key_filepath
+    key_file_arg = '--service_account_key_file=%s' % service_account_key_file
     default_account_arg = '--default_service_account=830293263384-compute@developer.gserviceaccount.com'
 
     if test_case in ['jwt_token_creds', 'per_rpc_creds', 'oauth2_auth_token']:
@@ -709,7 +729,7 @@
                 'csharp', 'csharpcoreclr', 'node', 'php', 'php7', 'python',
                 'ruby', 'nodepurejs'
         ]:
-            env['GOOGLE_APPLICATION_CREDENTIALS'] = key_filepath
+            env['GOOGLE_APPLICATION_CREDENTIALS'] = service_account_key_file
         else:
             cmdargs += [key_file_arg]
 
@@ -738,22 +758,24 @@
 
 def cloud_to_prod_jobspec(language,
                           test_case,
-                          server_host_name,
-                          server_host_detail,
+                          server_host_nickname,
+                          server_host,
                           docker_image=None,
                           auth=False,
-                          manual_cmd_log=None):
+                          manual_cmd_log=None,
+                          service_account_key_file=None):
     """Creates jobspec for cloud-to-prod interop test"""
     container_name = None
     cmdargs = [
-        '--server_host=%s' % server_host_detail[0],
-        '--server_host_override=%s' % server_host_detail[1],
-        '--server_port=443', '--use_tls=true',
+        '--server_host=%s' % server_host,
+        '--server_host_override=%s' % server_host, '--server_port=443',
+        '--use_tls=true',
         '--test_case=%s' % test_case
     ]
     environ = dict(language.cloud_to_prod_env(), **language.global_env())
     if auth:
-        auth_cmdargs, auth_env = auth_options(language, test_case)
+        auth_cmdargs, auth_env = auth_options(language, test_case,
+                                              service_account_key_file)
         cmdargs += auth_cmdargs
         environ.update(auth_env)
     cmdline = bash_cmdline(language.client_cmd(cmdargs))
@@ -782,7 +804,7 @@
         cmdline=cmdline,
         cwd=cwd,
         environ=environ,
-        shortname='%s:%s:%s:%s' % (suite_name, language, server_host_name,
+        shortname='%s:%s:%s:%s' % (suite_name, language, server_host_nickname,
                                    test_case),
         timeout_seconds=_TEST_TIMEOUT,
         flake_retries=4 if args.allow_flakes else 0,
@@ -799,14 +821,22 @@
                            server_host,
                            server_port,
                            docker_image=None,
-                           insecure=False,
+                           transport_security='tls',
                            manual_cmd_log=None):
     """Creates jobspec for cloud-to-cloud interop test"""
     interop_only_options = [
         '--server_host_override=foo.test.google.fr',
-        '--use_tls=%s' % ('false' if insecure else 'true'),
         '--use_test_ca=true',
     ]
+    if transport_security == 'tls':
+        interop_only_options += ['--use_tls=true']
+    elif transport_security == 'alts':
+        interop_only_options += ['--use_tls=false', '--use_alts=true']
+    elif transport_security == 'insecure':
+        interop_only_options += ['--use_tls=false']
+    else:
+        print('Invalid transport security option.')
+        sys.exit(1)
 
     client_test_case = test_case
     if test_case in _HTTP2_SERVER_TEST_CASES_THAT_USE_GRPC_CLIENTS:
@@ -871,15 +901,24 @@
     return test_job
 
 
-def server_jobspec(language, docker_image, insecure=False, manual_cmd_log=None):
+def server_jobspec(language,
+                   docker_image,
+                   transport_security='tls',
+                   manual_cmd_log=None):
     """Create jobspec for running a server"""
     container_name = dockerjob.random_name(
         'interop_server_%s' % language.safename)
-    cmdline = bash_cmdline(
-        language.server_cmd([
-            '--port=%s' % _DEFAULT_SERVER_PORT,
-            '--use_tls=%s' % ('false' if insecure else 'true')
-        ]))
+    server_cmd = ['--port=%s' % _DEFAULT_SERVER_PORT]
+    if transport_security == 'tls':
+        server_cmd += ['--use_tls=true']
+    elif transport_security == 'alts':
+        server_cmd += ['--use_tls=false', '--use_alts=true']
+    elif transport_security == 'insecure':
+        server_cmd += ['--use_tls=false']
+    else:
+        print('Invalid transport security option.')
+        sys.exit(1)
+    cmdline = bash_cmdline(language.server_cmd(server_cmd))
     environ = language.global_env()
     docker_args = ['--name=%s' % container_name]
     if language.safename == 'http2':
@@ -984,19 +1023,9 @@
 
 
 # A dictionary of prod servers to test.
-# Format: server_name: (server_host, server_host_override, errors_allowed)
-# TODO(adelez): implement logic for errors_allowed where if the indicated tests
-# fail, they don't impact the overall test result.
 prod_servers = {
-    'default': ('216.239.32.254', 'grpc-test.sandbox.googleapis.com', False),
-    'gateway_v2': ('216.239.32.254', 'grpc-test2.sandbox.googleapis.com', True),
-    'cloud_gateway': ('216.239.32.255', 'grpc-test.sandbox.googleapis.com',
-                      False),
-    'cloud_gateway_v2': ('216.239.32.255', 'grpc-test2.sandbox.googleapis.com',
-                         True),
-    'gateway_v4': ('216.239.32.254', 'grpc-test4.sandbox.googleapis.com', True),
-    'cloud_gateway_v4': ('216.239.32.255', 'grpc-test4.sandbox.googleapis.com',
-                         True),
+    'default': 'grpc-test.sandbox.googleapis.com',
+    'gateway_v4': 'grpc-test4.sandbox.googleapis.com',
 }
 
 argp = argparse.ArgumentParser(description='Run interop tests.')
@@ -1044,6 +1073,12 @@
     'Use servername=HOST:PORT to explicitly specify a server. E.g. csharp=localhost:50000',
     default=[])
 argp.add_argument(
+    '--service_account_key_file',
+    type=str,
+    help=
+    'Override the default service account key file to use for auth interop tests.',
+    default=None)
+argp.add_argument(
     '-t', '--travis', default=False, action='store_const', const=True)
 argp.add_argument(
     '-v', '--verbose', default=False, action='store_const', const=True)
@@ -1086,11 +1121,19 @@
     'Enable HTTP/2 server edge case testing. (Includes positive and negative tests'
 )
 argp.add_argument(
-    '--insecure',
+    '--transport_security',
+    choices=_TRANSPORT_SECURITY_OPTIONS,
+    default='tls',
+    type=str,
+    nargs='?',
+    const=True,
+    help='Which transport security mechanism to use.')
+argp.add_argument(
+    '--skip_compute_engine_creds',
     default=False,
     action='store_const',
     const=True,
-    help='Whether to use secure channel.')
+    help='Skip auth tests requiring access to compute engine credentials.')
 argp.add_argument(
     '--internal_ci',
     default=False,
@@ -1110,6 +1153,9 @@
     s
     for s in itertools.chain.from_iterable(
         _SERVERS if x == 'all' else [x] for x in args.server))
+# ALTS servers are only available for certain languages.
+if args.transport_security == 'alts':
+    servers = servers.intersection(_SERVERS_FOR_ALTS_TEST_CASES)
 
 if args.use_docker:
     if not args.travis:
@@ -1139,6 +1185,10 @@
 languages = set(_LANGUAGES[l]
                 for l in itertools.chain.from_iterable(
                     all_but_objc if x == 'all' else [x] for x in args.language))
+# ALTS interop clients are only available for certain languages.
+if args.transport_security == 'alts':
+    alts_languages = set(_LANGUAGES[l] for l in _LANGUAGES_FOR_ALTS_TEST_CASES)
+    languages = languages.intersection(alts_languages)
 
 languages_http2_clients_for_http2_server_interop = set()
 if args.http2_server_interop:
@@ -1207,7 +1257,7 @@
         spec = server_jobspec(
             _LANGUAGES[lang],
             docker_images.get(lang),
-            args.insecure,
+            args.transport_security,
             manual_cmd_log=server_manual_cmd_log)
         if not args.manual_run:
             job = dockerjob.DockerJob(spec)
@@ -1235,9 +1285,9 @@
 
     jobs = []
     if args.cloud_to_prod:
-        if args.insecure:
+        if args.transport_security != 'tls':
             print('TLS is always enabled for cloud_to_prod scenarios.')
-        for server_host_name in args.prod_servers:
+        for server_host_nickname in args.prod_servers:
             for language in languages:
                 for test_case in _TEST_CASES:
                     if not test_case in language.unimplemented_test_cases():
@@ -1245,10 +1295,12 @@
                             test_job = cloud_to_prod_jobspec(
                                 language,
                                 test_case,
-                                server_host_name,
-                                prod_servers[server_host_name],
+                                server_host_nickname,
+                                prod_servers[server_host_nickname],
                                 docker_image=docker_images.get(str(language)),
-                                manual_cmd_log=client_manual_cmd_log)
+                                manual_cmd_log=client_manual_cmd_log,
+                                service_account_key_file=args.
+                                service_account_key_file)
                             jobs.append(test_job)
 
             if args.http2_interop:
@@ -1256,28 +1308,34 @@
                     test_job = cloud_to_prod_jobspec(
                         http2Interop,
                         test_case,
-                        server_host_name,
-                        prod_servers[server_host_name],
+                        server_host_nickname,
+                        prod_servers[server_host_nickname],
                         docker_image=docker_images.get(str(http2Interop)),
-                        manual_cmd_log=client_manual_cmd_log)
+                        manual_cmd_log=client_manual_cmd_log,
+                        service_account_key_file=args.service_account_key_file)
                     jobs.append(test_job)
 
     if args.cloud_to_prod_auth:
-        if args.insecure:
+        if args.transport_security != 'tls':
             print('TLS is always enabled for cloud_to_prod scenarios.')
-        for server_host_name in args.prod_servers:
+        for server_host_nickname in args.prod_servers:
             for language in languages:
                 for test_case in _AUTH_TEST_CASES:
-                    if not test_case in language.unimplemented_test_cases():
-                        test_job = cloud_to_prod_jobspec(
-                            language,
-                            test_case,
-                            server_host_name,
-                            prod_servers[server_host_name],
-                            docker_image=docker_images.get(str(language)),
-                            auth=True,
-                            manual_cmd_log=client_manual_cmd_log)
-                        jobs.append(test_job)
+                    if (not args.skip_compute_engine_creds or
+                            not compute_engine_creds_required(
+                                language, test_case)):
+                        if not test_case in language.unimplemented_test_cases():
+                            test_job = cloud_to_prod_jobspec(
+                                language,
+                                test_case,
+                                server_host_nickname,
+                                prod_servers[server_host_nickname],
+                                docker_image=docker_images.get(str(language)),
+                                auth=True,
+                                manual_cmd_log=client_manual_cmd_log,
+                                service_account_key_file=args.
+                                service_account_key_file)
+                            jobs.append(test_job)
 
     for server in args.override_server:
         server_name = server[0]
@@ -1301,7 +1359,7 @@
                             server_host,
                             server_port,
                             docker_image=docker_images.get(str(language)),
-                            insecure=args.insecure,
+                            transport_security=args.transport_security,
                             manual_cmd_log=client_manual_cmd_log)
                         jobs.append(test_job)
 
@@ -1317,7 +1375,7 @@
                     server_host,
                     server_port,
                     docker_image=docker_images.get(str(http2Interop)),
-                    insecure=args.insecure,
+                    transport_security=args.transport_security,
                     manual_cmd_log=client_manual_cmd_log)
                 jobs.append(test_job)
 
@@ -1353,11 +1411,12 @@
                     server_port = _DEFAULT_SERVER_PORT + offset
                     if not args.manual_run:
                         server_port = http2_server_job.mapped_port(server_port)
-                    if not args.insecure:
-                        print((
-                            'Creating grpc cient to http2 server test case with insecure connection, even though'
-                            ' args.insecure is False. Http2 test server only supports insecure connections.'
-                        ))
+                    if args.transport_security != 'insecure':
+                        print(
+                            ('Creating grpc client to http2 server test case '
+                             'with insecure connection, even though '
+                             'args.transport_security is not insecure. Http2 '
+                             'test server only supports insecure connections.'))
                     test_job = cloud_to_cloud_jobspec(
                         language,
                         test_case,
@@ -1365,7 +1424,7 @@
                         'localhost',
                         server_port,
                         docker_image=docker_images.get(str(language)),
-                        insecure=True,
+                        transport_security='insecure',
                         manual_cmd_log=client_manual_cmd_log)
                     jobs.append(test_job)
 
@@ -1408,12 +1467,6 @@
     http2_server_test_cases = (_HTTP2_SERVER_TEST_CASES
                                if args.http2_server_interop else [])
 
-    report_utils.render_interop_html_report(
-        set([str(l) for l in languages]), servers, _TEST_CASES,
-        _AUTH_TEST_CASES, _HTTP2_TEST_CASES, http2_server_test_cases, resultset,
-        num_failures, args.cloud_to_prod_auth or args.cloud_to_prod,
-        args.prod_servers, args.http2_interop)
-
     if num_failures:
         sys.exit(1)
     else:
diff --git a/tools/run_tests/run_tests.py b/tools/run_tests/run_tests.py
index 85c7f5c..0c270fa 100755
--- a/tools/run_tests/run_tests.py
+++ b/tools/run_tests/run_tests.py
@@ -204,19 +204,28 @@
 
 
 _PythonConfigVars = collections.namedtuple('_ConfigVars', [
-    'shell', 'builder', 'builder_prefix_arguments', 'venv_relative_python',
-    'toolchain', 'runner'
+    'shell',
+    'builder',
+    'builder_prefix_arguments',
+    'venv_relative_python',
+    'toolchain',
+    'runner',
+    'test_name',
+    'iomgr_platform',
 ])
 
 
 def _python_config_generator(name, major, minor, bits, config_vars):
+    name += '_' + config_vars.iomgr_platform
     return PythonConfig(
         name, config_vars.shell + config_vars.builder +
         config_vars.builder_prefix_arguments + [
             _python_pattern_function(major=major, minor=minor, bits=bits)
         ] + [name] + config_vars.venv_relative_python + config_vars.toolchain,
-        config_vars.shell + config_vars.runner +
-        [os.path.join(name, config_vars.venv_relative_python[0])])
+        config_vars.shell + config_vars.runner + [
+            os.path.join(name, config_vars.venv_relative_python[0]),
+            config_vars.test_name
+        ])
 
 
 def _pypy_config_generator(name, major, config_vars):
@@ -281,7 +290,7 @@
             self._docker_distro, self._make_options = self._compiler_options(
                 self.args.use_docker, self.args.compiler)
         if args.iomgr_platform == "uv":
-            cflags = '-DGRPC_UV -DGRPC_CUSTOM_IOMGR_THREAD_CHECK '
+            cflags = '-DGRPC_UV -DGRPC_CUSTOM_IOMGR_THREAD_CHECK -DGRPC_CUSTOM_SOCKET '
             try:
                 cflags += subprocess.check_output(
                     ['pkg-config', '--cflags', 'libuv']).strip() + ' '
@@ -770,12 +779,16 @@
             venv_relative_python = ['bin/python']
             toolchain = ['unix']
 
+        test_command = 'test_lite'
+        if args.iomgr_platform == 'gevent':
+            test_command = 'test_gevent'
         runner = [
             os.path.abspath('tools/run_tests/helper_scripts/run_python.sh')
         ]
-        config_vars = _PythonConfigVars(shell, builder,
-                                        builder_prefix_arguments,
-                                        venv_relative_python, toolchain, runner)
+
+        config_vars = _PythonConfigVars(
+            shell, builder, builder_prefix_arguments, venv_relative_python,
+            toolchain, runner, test_command, args.iomgr_platform)
         python27_config = _python_config_generator(
             name='py27',
             major='2',
@@ -908,9 +921,6 @@
             if self.platform == 'mac':
                 # TODO(jtattermusch): EMBED_ZLIB=true currently breaks the mac build
                 self._make_options = ['EMBED_OPENSSL=true']
-                if self.args.compiler != 'coreclr':
-                    # On Mac, official distribution of mono is 32bit.
-                    self._make_options += ['ARCH_FLAGS=-m32', 'LDFLAGS=-m32']
             else:
                 self._make_options = ['EMBED_OPENSSL=true', 'EMBED_ZLIB=true']
 
@@ -931,6 +941,9 @@
             assembly_subdir += '/net45'
             if self.platform == 'windows':
                 runtime_cmd = []
+            elif self.platform == 'mac':
+                # mono before version 5.2 on MacOS defaults to 32bit runtime
+                runtime_cmd = ['mono', '--arch=64']
             else:
                 runtime_cmd = ['mono']
 
@@ -1341,7 +1354,7 @@
 )
 argp.add_argument(
     '--iomgr_platform',
-    choices=['native', 'uv'],
+    choices=['native', 'uv', 'gevent'],
     default='native',
     help='Selects iomgr platform to build on')
 argp.add_argument(
@@ -1407,16 +1420,18 @@
     nargs='?',
     help='Upload test results to a specified BQ table.')
 argp.add_argument(
-    '--disable_auto_set_flakes',
+    '--auto_set_flakes',
     default=False,
     const=True,
     action='store_const',
-    help='Disable rerunning historically flaky tests')
+    help=
+    'Allow repeated runs for tests that have been failing recently (based on BQ historical data).'
+)
 args = argp.parse_args()
 
 flaky_tests = set()
 shortname_to_cpu = {}
-if not args.disable_auto_set_flakes:
+if args.auto_set_flakes:
     try:
         for test in get_bqtest_data():
             if test.flaky: flaky_tests.add(test.name)
diff --git a/tools/run_tests/run_tests_matrix.py b/tools/run_tests/run_tests_matrix.py
index 1c99e79..64d80ab 100755
--- a/tools/run_tests/run_tests_matrix.py
+++ b/tools/run_tests/run_tests_matrix.py
@@ -114,7 +114,7 @@
 def _generate_jobs(languages,
                    configs,
                    platforms,
-                   iomgr_platform='native',
+                   iomgr_platforms=['native'],
                    arch=None,
                    compiler=None,
                    labels=[],
@@ -125,48 +125,60 @@
     result = []
     for language in languages:
         for platform in platforms:
-            for config in configs:
-                name = '%s_%s_%s_%s' % (language, platform, config,
-                                        iomgr_platform)
-                runtests_args = [
-                    '-l', language, '-c', config, '--iomgr_platform',
-                    iomgr_platform
-                ]
-                if arch or compiler:
-                    name += '_%s_%s' % (arch, compiler)
-                    runtests_args += ['--arch', arch, '--compiler', compiler]
-                if '--build_only' in extra_args:
-                    name += '_buildonly'
-                for extra_env in extra_envs:
-                    name += '_%s_%s' % (extra_env, extra_envs[extra_env])
+            for iomgr_platform in iomgr_platforms:
+                for config in configs:
+                    name = '%s_%s_%s_%s' % (language, platform, config,
+                                            iomgr_platform)
+                    runtests_args = [
+                        '-l', language, '-c', config, '--iomgr_platform',
+                        iomgr_platform
+                    ]
+                    if arch or compiler:
+                        name += '_%s_%s' % (arch, compiler)
+                        runtests_args += [
+                            '--arch', arch, '--compiler', compiler
+                        ]
+                    if '--build_only' in extra_args:
+                        name += '_buildonly'
+                    for extra_env in extra_envs:
+                        name += '_%s_%s' % (extra_env, extra_envs[extra_env])
 
-                runtests_args += extra_args
-                if platform == 'linux':
-                    job = _docker_jobspec(
-                        name=name,
-                        runtests_args=runtests_args,
-                        runtests_envs=extra_envs,
-                        inner_jobs=inner_jobs,
-                        timeout_seconds=timeout_seconds)
-                else:
-                    job = _workspace_jobspec(
-                        name=name,
-                        runtests_args=runtests_args,
-                        runtests_envs=extra_envs,
-                        inner_jobs=inner_jobs,
-                        timeout_seconds=timeout_seconds)
+                    runtests_args += extra_args
+                    if platform == 'linux':
+                        job = _docker_jobspec(
+                            name=name,
+                            runtests_args=runtests_args,
+                            runtests_envs=extra_envs,
+                            inner_jobs=inner_jobs,
+                            timeout_seconds=timeout_seconds)
+                    else:
+                        job = _workspace_jobspec(
+                            name=name,
+                            runtests_args=runtests_args,
+                            runtests_envs=extra_envs,
+                            inner_jobs=inner_jobs,
+                            timeout_seconds=timeout_seconds)
 
-                job.labels = [platform, config, language, iomgr_platform
-                             ] + labels
-                result.append(job)
+                    job.labels = [platform, config, language, iomgr_platform
+                                 ] + labels
+                    result.append(job)
     return result
 
 
 def _create_test_jobs(extra_args=[], inner_jobs=_DEFAULT_INNER_JOBS):
     test_jobs = []
+    # sanity tests
+    test_jobs += _generate_jobs(
+        languages=['sanity'],
+        configs=['dbg', 'opt'],
+        platforms=['linux'],
+        labels=['basictests'],
+        extra_args=extra_args,
+        inner_jobs=inner_jobs)
+
     # supported on linux only
     test_jobs += _generate_jobs(
-        languages=['sanity', 'php7'],
+        languages=['php7'],
         configs=['dbg', 'opt'],
         platforms=['linux'],
         labels=['basictests', 'multilang'],
@@ -184,13 +196,22 @@
         timeout_seconds=_CPP_RUNTESTS_TIMEOUT)
 
     test_jobs += _generate_jobs(
-        languages=['csharp', 'python'],
+        languages=['csharp'],
         configs=['dbg', 'opt'],
         platforms=['linux', 'macos', 'windows'],
         labels=['basictests', 'multilang'],
         extra_args=extra_args,
         inner_jobs=inner_jobs)
 
+    test_jobs += _generate_jobs(
+        languages=['python'],
+        configs=['opt'],
+        platforms=['linux', 'macos', 'windows'],
+        iomgr_platforms=['native', 'gevent'],
+        labels=['basictests', 'multilang'],
+        extra_args=extra_args,
+        inner_jobs=inner_jobs)
+
     # supported on linux and mac.
     test_jobs += _generate_jobs(
         languages=['c++'],
@@ -377,7 +398,7 @@
         languages=['c'],
         configs=['dbg'],
         platforms=['linux'],
-        iomgr_platform='uv',
+        iomgr_platforms=['uv'],
         labels=['portability', 'corelang'],
         extra_args=extra_args,
         inner_jobs=inner_jobs,
@@ -508,7 +529,6 @@
         extra_args.append('--bq_result_table')
         extra_args.append('%s' % args.bq_result_table)
         extra_args.append('--measure_cpu_costs')
-        extra_args.append('--disable_auto_set_flakes')
 
     all_jobs = _create_test_jobs(extra_args=extra_args, inner_jobs=args.inner_jobs) + \
                _create_portability_test_jobs(extra_args=extra_args, inner_jobs=args.inner_jobs)
diff --git a/tools/run_tests/sanity/check_submodules.sh b/tools/run_tests/sanity/check_submodules.sh
index b22bbd6..723d185 100755
--- a/tools/run_tests/sanity/check_submodules.sh
+++ b/tools/run_tests/sanity/check_submodules.sh
@@ -31,7 +31,7 @@
  886e7d75368e3f4fab3f4d0d3584e4abfc557755 third_party/boringssl-with-bazel (version_for_cocoapods_7.0-857-g886e7d7)
  30dbc81fb5ffdc98ea9b14b1918bfe4e8779b26e third_party/gflags (v2.2.0)
  ec44c6c1675c25b9827aacd08c02433cccde7780 third_party/googletest (release-1.8.0)
- 2761122b810fe8861004ae785cc3ab39f384d342 third_party/protobuf (v3.5.0)
+ b5fbb742af122b565925987e65c08957739976a7 third_party/protobuf (v3.5.2)
  cacf7f1d4e3d44d871b605da3b647f07d718623f third_party/zlib (v1.2.11)
  3be1924221e1326df520f8498d704a5c4c8d0cce third_party/cares/cares (cares-1_13_0)
  73594cde8c9a52a102c4341c244c833aa61b9c06 third_party/bloaty